From: rmccabe@sourceware.org <rmccabe@sourceware.org>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] conga/luci/site/luci/Extensions StorageReport. ...
Date: 24 Sep 2007 19:48:34 -0000 [thread overview]
Message-ID: <20070924194834.23940.qmail@sourceware.org> (raw)
CVSROOT: /cvs/cluster
Module name: conga
Changes by: rmccabe at sourceware.org 2007-09-24 19:48:34
Modified files:
luci/site/luci/Extensions: StorageReport.py storage_adapters.py
Log message:
Whitespace, readability cleanup
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/StorageReport.py.diff?cvsroot=cluster&r1=1.26&r2=1.27
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/storage_adapters.py.diff?cvsroot=cluster&r1=1.11&r2=1.12
--- conga/luci/site/luci/Extensions/StorageReport.py 2007/08/09 04:37:20 1.26
+++ conga/luci/site/luci/Extensions/StorageReport.py 2007/09/24 19:48:34 1.27
@@ -34,2066 +34,2061 @@
from ricci_communicator import extract_module_status
-
SESSION_STORAGE_XML_REPORT = 'storage_xml_report_dir'
-
class StorageReport:
+ def __init__(self, storage_xml_report):
+ self.__report = storage_xml_report#.cloneNode(True)
- def __init__(self, storage_xml_report):
- self.__report = storage_xml_report#.cloneNode(True)
-
- self.__mappers = None
- self.__m_temps = None
- for node in self.__report.childNodes:
- try:
- var = parse_variable(node)
- if var.get_name() == 'mappers':
- self.__mappers = var.get_value()
- if var.get_name() == 'mapper_templates':
- self.__m_temps = var.get_value()
- except:
- pass
- if self.__mappers is None or self.__m_temps is None:
- raise Exception, 'invalid storage_xml_report'
-
- self.__mapp_dir = {} # holds mapper lists by mapper_type
- for mapp_node in self.__mappers:
- m_type = mapp_node.getAttribute('mapper_type')
- if not (m_type in self.__mapp_dir):
- self.__mapp_dir[m_type] = []
- self.__mapp_dir[m_type].append(mapp_node)#.cloneNode(True))
-
- self.__m_temps_dir = {} # holds mapper_template lists by mapper_type
- for temp_node in self.__m_temps:
- m_type = temp_node.getAttribute('mapper_type')
- if not (m_type in self.__m_temps_dir):
- self.__m_temps_dir[m_type] = []
- self.__m_temps_dir[m_type].append(temp_node)#.cloneNode(True))
- #
-
-
-
-
-
- def get_xml_report(self):
- return self.__report#.cloneNode(True)
-
-
- def get_mappers(self, mapper_type=''):
- l = []
- if mapper_type == '':
- l = self.__mappers
- elif mapper_type in self.__mapp_dir:
- l = self.__mapp_dir[mapper_type]
- r = []
- for s in l:
- r.append(s)#s.cloneNode(True))
- return r
-
-
- def get_mappers_dir(self):
- r = {}
- for mapper_type in self.__mapp_dir:
- l = []
- for m in self.__mapp_dir[mapper_type]:
- l.append(m)#.cloneNode(True))
- r[mapper_type] = l
- return r
-
-
- def get_mapper(self, mapper_id):
- if mapper_id == '':
- raise Exception, 'empty mapper_id!!!'
- for m in self.__mappers:
- if m.getAttribute('mapper_id') == mapper_id:
- return m#.cloneNode(True)
- return None
-
-
- def get_mapper_temps_dir(self):
- r = {}
- for mapper_type in self.__m_temps_dir:
- l = []
- for m in self.__m_temps_dir[mapper_type]:
- l.append(m)#.cloneNode(True))
- r[mapper_type] = l
- return r
-
-
- def get_mapper_temps(self, mapper_type=''):
- l = []
- if mapper_type == '':
- l = self.__m_temps
- elif mapper_type in self.__m_temps_dir:
- l = self.__m_temps_dir[mapper_type]
- r = []
- for s in l:
- r.append(s)#.cloneNode(True))
- return r
-
-
- def get_targets(self, mapper):
- if mapper is None:
- return []
-
- targets_list = []
- for node in mapper.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == MAPPER_TARGETS_TAG:
- targets_xml = node
- for node in targets_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == BD_TYPE:
- targets_list.append(node)#.cloneNode(True))
- return targets_list
-
-
- def get_new_targets(self, mapper):
- if mapper is None:
- return []
-
- targets_list = []
- for node in mapper.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == MAPPER_NEW_TARGETS_TAG:
- targets_xml = node
- for node in targets_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == BD_TEMPLATE:
- targets_list.append(node)#.cloneNode(True))
- return targets_list
-
-
- def get_sources(self, mapper):
- if mapper is None:
- return []
-
- targets_list = []
- for node in mapper.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == MAPPER_SOURCES_TAG:
- targets_xml = node
- for node in targets_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == BD_TYPE:
- targets_list.append(node)#.cloneNode(True))
- return targets_list
-
-
- def get_new_sources(self, mapper):
- if mapper is None:
- return []
-
- targets_list = []
- for node in mapper.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == MAPPER_NEW_SOURCES_TAG:
- targets_xml = node
- for node in targets_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == BD_TYPE:
- targets_list.append(node)#.cloneNode(True))
- return targets_list
-
-
- def get_mapper_props(self, mapper):
- if mapper is None:
- return None
-
- props = None
- for node in mapper.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == PROPS_TAG:
- props = node#.cloneNode(True)
- if props is None:
- raise Exception, 'mapper missing properties tag'
- return props
-
-
- def get_target(self, mapper_id, path):
- mapper = self.get_mapper(mapper_id)
- if mapper is None:
- return None
-
- targets = self.get_targets(mapper)
- for t_xml in targets:
- if t_xml.getAttribute('path') == path:
- return t_xml#.cloneNode(True)
- return None
+ self.__mappers = None
+ self.__m_temps = None
+ for node in self.__report.childNodes:
+ try:
+ var = parse_variable(node)
+ if var.get_name() == 'mappers':
+ self.__mappers = var.get_value()
+ if var.get_name() == 'mapper_templates':
+ self.__m_temps = var.get_value()
+ except:
+ pass
+ if self.__mappers is None or self.__m_temps is None:
+ raise Exception, 'invalid storage_xml_report'
+
+ self.__mapp_dir = {} # holds mapper lists by mapper_type
+ for mapp_node in self.__mappers:
+ m_type = mapp_node.getAttribute('mapper_type')
+ if not (m_type in self.__mapp_dir):
+ self.__mapp_dir[m_type] = []
+ self.__mapp_dir[m_type].append(mapp_node)#.cloneNode(True))
+
+ self.__m_temps_dir = {} # holds mapper_template lists by mapper_type
+ for temp_node in self.__m_temps:
+ m_type = temp_node.getAttribute('mapper_type')
+ if not (m_type in self.__m_temps_dir):
+ self.__m_temps_dir[m_type] = []
+ self.__m_temps_dir[m_type].append(temp_node)#.cloneNode(True))
+ #
+
+ def get_xml_report(self):
+ return self.__report#.cloneNode(True)
+
+ def get_mappers(self, mapper_type=''):
+ l = []
+ if mapper_type == '':
+ l = self.__mappers
+ elif mapper_type in self.__mapp_dir:
+ l = self.__mapp_dir[mapper_type]
+ r = []
+ for s in l:
+ r.append(s)#s.cloneNode(True))
+ return r
+
+ def get_mappers_dir(self):
+ r = {}
+ for mapper_type in self.__mapp_dir:
+ l = []
+ for m in self.__mapp_dir[mapper_type]:
+ l.append(m)#.cloneNode(True))
+ r[mapper_type] = l
+ return r
+
+ def get_mapper(self, mapper_id):
+ if mapper_id == '':
+ raise Exception, 'empty mapper_id!!!'
+ for m in self.__mappers:
+ if m.getAttribute('mapper_id') == mapper_id:
+ return m#.cloneNode(True)
+ return None
+
+ def get_mapper_temps_dir(self):
+ r = {}
+ for mapper_type in self.__m_temps_dir:
+ l = []
+ for m in self.__m_temps_dir[mapper_type]:
+ l.append(m)#.cloneNode(True))
+ r[mapper_type] = l
+ return r
+
+ def get_mapper_temps(self, mapper_type=''):
+ l = []
+ if mapper_type == '':
+ l = self.__m_temps
+ elif mapper_type in self.__m_temps_dir:
+ l = self.__m_temps_dir[mapper_type]
+ r = []
+ for s in l:
+ r.append(s)#.cloneNode(True))
+ return r
+
+ def get_targets(self, mapper):
+ if mapper is None:
+ return []
+
+ targets_list = []
+ for node in mapper.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == MAPPER_TARGETS_TAG:
+ targets_xml = node
+ for node in targets_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == BD_TYPE:
+ targets_list.append(node)#.cloneNode(True))
+ return targets_list
+
+ def get_new_targets(self, mapper):
+ if mapper is None:
+ return []
+
+ targets_list = []
+ for node in mapper.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == MAPPER_NEW_TARGETS_TAG:
+ targets_xml = node
+ for node in targets_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == BD_TEMPLATE:
+ targets_list.append(node)#.cloneNode(True))
+ return targets_list
+
+ def get_sources(self, mapper):
+ if mapper is None:
+ return []
+
+ targets_list = []
+ for node in mapper.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == MAPPER_SOURCES_TAG:
+ targets_xml = node
+ for node in targets_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == BD_TYPE:
+ targets_list.append(node)#.cloneNode(True))
+ return targets_list
+
+ def get_new_sources(self, mapper):
+ if mapper is None:
+ return []
+
+ targets_list = []
+ for node in mapper.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == MAPPER_NEW_SOURCES_TAG:
+ targets_xml = node
+ for node in targets_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == BD_TYPE:
+ targets_list.append(node)#.cloneNode(True))
+ return targets_list
+
+ def get_mapper_props(self, mapper):
+ if mapper is None:
+ return None
+
+ props = None
+ for node in mapper.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == PROPS_TAG:
+ props = node#.cloneNode(True)
+ if props is None:
+ raise Exception, 'mapper missing properties tag'
+ return props
+
+ def get_target(self, mapper_id, path):
+ mapper = self.get_mapper(mapper_id)
+ if mapper is None:
+ return None
+
+ targets = self.get_targets(mapper)
+ for t_xml in targets:
+ if t_xml.getAttribute('path') == path:
+ return t_xml#.cloneNode(True)
+ return None
def is_storage_report_cached(session, storagename):
- if session.has_key(SESSION_STORAGE_XML_REPORT):
- reports_dir = session[SESSION_STORAGE_XML_REPORT]
- if reports_dir.has_key(storagename):
- if reports_dir[storagename] is not None:
- return True
- return False
+ if session.has_key(SESSION_STORAGE_XML_REPORT):
+ reports_dir = session[SESSION_STORAGE_XML_REPORT]
+ if reports_dir.has_key(storagename):
+ if reports_dir[storagename] is not None:
+ return True
+ return False
def invalidate_storage_report(session, storagename):
- reports_dir = {}
- if session.has_key(SESSION_STORAGE_XML_REPORT):
- reports_dir = session[SESSION_STORAGE_XML_REPORT]
- reports_dir[storagename] = None
- session.set(SESSION_STORAGE_XML_REPORT, reports_dir)
- return
+ reports_dir = {}
+ if session.has_key(SESSION_STORAGE_XML_REPORT):
+ reports_dir = session[SESSION_STORAGE_XML_REPORT]
+ reports_dir[storagename] = None
+ session.set(SESSION_STORAGE_XML_REPORT, reports_dir)
+ return
def cache_storage_report(ricci_comm, session):
- try:
- rep = get_storage_report(ricci_comm, session)
- if rep is None:
- raise Exception, 'Unable to communicate with host (either system down or ricci not running on it)'
- else:
- return True
- except Exception, e:
- return str(e)
- except:
- return 'Luci internal error. Please file bug report.'
- return 'should never come here'
+ try:
+ rep = get_storage_report(ricci_comm, session)
+ if rep is None:
+ raise Exception, 'Unable to communicate with host (either system down or ricci not running on it)'
+ else:
+ return True
+ except Exception, e:
+ return str(e)
+ except:
+ return 'Luci internal error. Please file bug report.'
+ return 'should never come here'
def get_storage_report(ricci_comm, session):
- if ricci_comm is None:
- return None
+ if ricci_comm is None:
+ return None
- storagename = ricci_comm.hostname()
+ storagename = ricci_comm.hostname()
- # setup cache, if not already set up
- if not session.has_key(SESSION_STORAGE_XML_REPORT):
- session.set(SESSION_STORAGE_XML_REPORT, {})
- # return cached report if existing
- if session[SESSION_STORAGE_XML_REPORT].has_key(storagename):
- tmp_report = session[SESSION_STORAGE_XML_REPORT][storagename]
- if tmp_report is not None:
- return StorageReport(tmp_report)
-
-
- # request
- doc = minidom.Document()
- batch = doc.createElement('batch')
- module = doc.createElement('module')
- module.setAttribute('name', 'storage')
- request = doc.createElement('request')
- request.setAttribute('API_version', '1.0')
- function = doc.createElement('function_call')
- function.setAttribute('name', 'report')
- batch.appendChild(module)
- module.appendChild(request)
- request.appendChild(function)
-
- # get report
- batch_r = ricci_comm.process_batch(batch)
- if batch_r.getAttribute('status') != '0':
- #raise Exception, 'error retrieving storage report'
- # dig deeper to find causing error
- pass
- module_r = None
- for node in batch_r.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == 'module':
- module_r = node
- if module_r is None:
- raise Exception, 'malformed response: missing <module/> in <batch/>'
- module_r_status = module_r.getAttribute('status')
- if module_r_status != '0':
- #raise Exception, 'error retrieving storage report'
- if module_r_status == '3':
- raise Exception, 'Unable to find storage module on host (reinstall it)'
- resp_r = None
- for node in module_r.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == 'response':
- resp_r = node
- if resp_r is None:
- raise Exception, 'malformed response: missing <response/> in <module/>'
- fr_r = None
- for node in resp_r.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == 'function_response':
- fr_r = node
- if fr_r is None:
- raise Exception, 'malformed response: missing <function_response/> in <response/>'
- succ_v = None
- err_code_v = None
- err_desc_v = None
- for node in fr_r.childNodes:
- try:
- var = parse_variable(node)
- if var.get_name() == 'success':
- succ_v = var
- elif var.get_name() == 'error_code':
- err_code_v = var
- elif var.get_name() == 'error_description':
- err_desc_v = var
- except:
- pass
- if succ_v is None:
- raise Exception, 'malformed response: missing "success" variable in <function_response/>'
- if succ_v.get_value() is not True:
- # error
- if err_code_v.get_value() == -1:
- raise Exception, 'Generic error on host:\n\n%s' % err_desc_v.get_value()
- else:
- raise Exception, 'Host responded: %s' % err_desc_v.get_value()
-
- xml_report = fr_r
-
- # cache xml_report
- reports_dir = session[SESSION_STORAGE_XML_REPORT]
- reports_dir[storagename] = xml_report
- session.set(SESSION_STORAGE_XML_REPORT, reports_dir)
+ # setup cache, if not already set up
+ if not session.has_key(SESSION_STORAGE_XML_REPORT):
+ session.set(SESSION_STORAGE_XML_REPORT, {})
+ # return cached report if existing
+ if session[SESSION_STORAGE_XML_REPORT].has_key(storagename):
+ tmp_report = session[SESSION_STORAGE_XML_REPORT][storagename]
+ if tmp_report is not None:
+ return StorageReport(tmp_report)
+
+ # request
+ doc = minidom.Document()
+ batch = doc.createElement('batch')
+ module = doc.createElement('module')
+ module.setAttribute('name', 'storage')
+ request = doc.createElement('request')
+ request.setAttribute('API_version', '1.0')
+ function = doc.createElement('function_call')
+ function.setAttribute('name', 'report')
+ batch.appendChild(module)
+ module.appendChild(request)
+ request.appendChild(function)
+
+ # get report
+ batch_r = ricci_comm.process_batch(batch)
+ if batch_r.getAttribute('status') != '0':
+ #raise Exception, 'error retrieving storage report'
+ # dig deeper to find causing error
+ pass
+ module_r = None
+ for node in batch_r.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == 'module':
+ module_r = node
+ if module_r is None:
+ raise Exception, 'malformed response: missing <module/> in <batch/>'
+ module_r_status = module_r.getAttribute('status')
+ if module_r_status != '0':
+ #raise Exception, 'error retrieving storage report'
+ if module_r_status == '3':
+ raise Exception, 'Unable to find storage module on host (reinstall it)'
+ resp_r = None
+ for node in module_r.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == 'response':
+ resp_r = node
+ if resp_r is None:
+ raise Exception, 'malformed response: missing <response/> in <module/>'
+ fr_r = None
+ for node in resp_r.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == 'function_response':
+ fr_r = node
+ if fr_r is None:
+ raise Exception, 'malformed response: missing <function_response/> in <response/>'
+ succ_v = None
+ err_code_v = None
+ err_desc_v = None
+ for node in fr_r.childNodes:
+ try:
+ var = parse_variable(node)
+ if var.get_name() == 'success':
+ succ_v = var
+ elif var.get_name() == 'error_code':
+ err_code_v = var
+ elif var.get_name() == 'error_description':
+ err_desc_v = var
+ except:
+ pass
+ if succ_v is None:
+ raise Exception, 'malformed response: missing "success" variable in <function_response/>'
+ if succ_v.get_value() is not True:
+ # error
+ if err_code_v.get_value() == -1:
+ raise Exception, 'Generic error on host:\n\n%s' % err_desc_v.get_value()
+ else:
+ raise Exception, 'Host responded: %s' % err_desc_v.get_value()
+
+ xml_report = fr_r
+
+ # cache xml_report
+ reports_dir = session[SESSION_STORAGE_XML_REPORT]
+ reports_dir[storagename] = xml_report
+ session.set(SESSION_STORAGE_XML_REPORT, reports_dir)
- return StorageReport(xml_report)
+ return StorageReport(xml_report)
def get_content_data(self, storage_report, mapper_id, bd_path, content_id):
- bd_data = get_bd_data(self, storage_report, mapper_id, bd_path)
- for cont in bd_data['contents']:
- if cont['id'] == content_id:
- return cont
- return None
+ bd_data = get_bd_data(self, storage_report, mapper_id, bd_path)
+ for cont in bd_data['contents']:
+ if cont['id'] == content_id:
+ return cont
+ return None
def get_bd_data(self, storage_report, mapper_id, path):
- if storage_report is None or mapper_id is None:
- return None
+ if storage_report is None or mapper_id is None:
+ return None
- mapper = get_mapper_data(self, storage_report, mapper_id)
- if mapper is None:
- return None
-
- for t in mapper['targets']:
- if t['path'] == path:
- return t
- for t in mapper['new_targets']:
- if t['path'] == path:
- return t
- if path == 'new_snapshot' and mapper['mapper_type'] == MAPPER_VG_TYPE:
- return mapper['snapshot_template']
- return None
+ mapper = get_mapper_data(self, storage_report, mapper_id)
+ if mapper is None:
+ return None
+
+ for t in mapper['targets']:
+ if t['path'] == path:
+ return t
+ for t in mapper['new_targets']:
+ if t['path'] == path:
+ return t
+ if path == 'new_snapshot' and mapper['mapper_type'] == MAPPER_VG_TYPE:
+ return mapper['snapshot_template']
+ return None
def get_mappers_data(self, storage_report):
- ret_dir = {}
- # mappers
- mappers_dir = storage_report.get_mappers_dir()
- for mapp_type in mappers_dir:
- for m_xml in mappers_dir[mapp_type]:
- mapper_id = m_xml.getAttribute('mapper_id')
- if mapp_type not in ret_dir:
- ret_dir[mapp_type] = {}
- ret_dir[mapp_type]['mappers'] = []
- ret_dir[mapp_type]['mapper_template'] = None
- ret_dir[mapp_type]['mappers'].append(get_mapper_data(self, storage_report, mapper_id))
- # templates
- for mapp_type in storage_report.get_mapper_temps_dir():
- if mapp_type not in ret_dir:
- ret_dir[mapp_type] = {}
- ret_dir[mapp_type]['mappers'] = []
- ret_dir[mapp_type]['mapper_template'] = get_mapper_template_data(self, storage_report, mapp_type)
-
- # pretty stuff
- for mapp_type in ret_dir:
- info = ret_dir[mapp_type]
- info_source = None
- if len(info['mappers']) != 0:
- info_source = info['mappers'][0]
- else:
- info_source = info['mapper_template']
- info['pretty_type'] = info_source['pretty_type']
- info['pretty_target_name'] = info_source['pretty_target_name']
- info['pretty_targets_name'] = info_source['pretty_targets_name']
- info['pretty_source_name'] = info_source['pretty_source_name']
- info['pretty_sources_name'] = info_source['pretty_sources_name']
+ ret_dir = {}
+ # mappers
+ mappers_dir = storage_report.get_mappers_dir()
+ for mapp_type in mappers_dir:
+ for m_xml in mappers_dir[mapp_type]:
+ mapper_id = m_xml.getAttribute('mapper_id')
+ if mapp_type not in ret_dir:
+ ret_dir[mapp_type] = {}
+ ret_dir[mapp_type]['mappers'] = []
+ ret_dir[mapp_type]['mapper_template'] = None
+ ret_dir[mapp_type]['mappers'].append(get_mapper_data(self, storage_report, mapper_id))
+ # templates
+ for mapp_type in storage_report.get_mapper_temps_dir():
+ if mapp_type not in ret_dir:
+ ret_dir[mapp_type] = {}
+ ret_dir[mapp_type]['mappers'] = []
+ ret_dir[mapp_type]['mapper_template'] = get_mapper_template_data(self, storage_report, mapp_type)
+
+ # pretty stuff
+ for mapp_type in ret_dir:
+ info = ret_dir[mapp_type]
+ info_source = None
+ if len(info['mappers']) != 0:
+ info_source = info['mappers'][0]
+ else:
+ info_source = info['mapper_template']
+ info['pretty_type'] = info_source['pretty_type']
+ info['pretty_target_name'] = info_source['pretty_target_name']
+ info['pretty_targets_name'] = info_source['pretty_targets_name']
+ info['pretty_source_name'] = info_source['pretty_source_name']
+ info['pretty_sources_name'] = info_source['pretty_sources_name']
- return ret_dir
+ return ret_dir
def get_mapper_data(self, storage_report, mapper_id):
- if self is None or storage_report is None or mapper_id is None:
- return None
-
- session = self.REQUEST.SESSION
+ if self is None or storage_report is None or mapper_id is None:
+ return None
- mapper = storage_report.get_mapper(mapper_id)
- if mapper is None:
- return None
-
- removable, props = get_props_data_internal(session, mapper)
-
- new_targets = []
- for t_xml in storage_report.get_new_targets(mapper):
- new_targets.append(get_bd_data_internal(session, t_xml, mapper))
- new_sources = []
- for s_xml in storage_report.get_new_sources(mapper):
- new_sources.append(get_bd_data_internal(session, s_xml, mapper))
- targets = []
- for t_xml in storage_report.get_targets(mapper):
- targets.append(get_bd_data_internal(session, t_xml, mapper))
- sources = []
- for s_xml in storage_report.get_sources(mapper):
- sources.append(get_bd_data_internal(session, s_xml, mapper))
-
- mapper_type = mapper.getAttribute('mapper_type')
- pretty_type, pretty_target_name, pretty_source_name = get_pretty_mapper_info(mapper_type)
- pretty_name = mapper_id.replace('%s:' % mapper_type, '').replace('/dev/', '')
- pretty_targets_name = '%ss' % pretty_target_name
- pretty_sources_name = '%ss' % pretty_source_name
- icon_name, dummy1, dummy2 = get_mapper_icons(mapper_type)
- color = 'black'
-
- mapper_ret = {}
- mapper_ret['pretty_type'] = pretty_type
- mapper_ret['pretty_name'] = pretty_name
- mapper_ret['pretty_target_name'] = pretty_target_name
- mapper_ret['pretty_targets_name'] = pretty_targets_name
- mapper_ret['pretty_source_name'] = pretty_source_name
- mapper_ret['pretty_sources_name'] = pretty_sources_name
- mapper_ret['mapper_id'] = mapper_id
- mapper_ret['mapper_type'] = mapper_type
- mapper_ret['props'] = props
- mapper_ret['props_ordered'] = get_ordered_props(props)
- mapper_ret['targets'] = targets
- mapper_ret['new_targets'] = new_targets
- mapper_ret['sources'] = sources
- mapper_ret['new_sources'] = new_sources
- mapper_ret['icon'] = icon_name
- mapper_ret['color'] = color
- mapper_ret['xml'] = mapper#.cloneNode(True)
-
- assemble_all_targets(mapper_ret)
-
- actions = []
- if removable:
- action = {'name' : 'Remove',
- 'msg' : 'Are you sure you want to remove %s \\\'%s\\\'?' % (pretty_type, pretty_name),
- 'link' : ''}
- actions.append(action)
- if mapper_type == MAPPER_VG_TYPE or mapper_type == MAPPER_MDRAID_TYPE or mapper_type == MAPPER_ATARAID_TYPE or mapper_type == MAPPER_MULTIPATH_TYPE:
- action = {'name' : 'Add %s' % mapper_ret['pretty_sources_name'],
- 'msg' : '',
- 'link' : './?%s=%s&%s=%s&%s=%s' % (PAGETYPE, ADD_SOURCES, PT_MAPPER_ID, mapper_ret['mapper_id'], PT_MAPPER_TYPE, mapper_ret['mapper_type'])}
- actions.append(action)
- if mapper_type == MAPPER_VG_TYPE:
- for nt in mapper_ret['new_targets']:
- if nt['props']['snapshot']['value'] == 'false':
- if nt['new']:
- action = {'name' : 'New %s' % mapper_ret['pretty_target_name'],
- 'msg' : '',
- 'link' : './?%s=%s&%s=%s&%s=%s&%s=%s' \
- % (PAGETYPE, VIEW_BD,
- PT_MAPPER_ID, mapper_ret['mapper_id'], \
- PT_MAPPER_TYPE, mapper_ret['mapper_type'], \
- PT_PATH, nt['path'])}
- actions.append(action)
- break
- mapper_ret['actions'] = actions
-
- if mapper_type == MAPPER_VG_TYPE:
- link_snapshots(mapper_ret)
-
- # cylinders work properly for VGs only, for now
- mapper_ret['graphical_view'] = mapper_type != MAPPER_PT_TYPE
- if mapper_ret['graphical_view']:
- mapper_ret['mappings-view_css_classnames'] = {'graphical_view' : 'visible',
- 'textual_view' : 'invisible'}
- else:
- mapper_ret['mappings-view_css_classnames'] = {'graphical_view' : 'invisible',
- 'textual_view' : 'visible'}
+ session = self.REQUEST.SESSION
- mapper_ret['need_apply_button'] = mutable_props(mapper_ret['props'])
-
- return mapper_ret
+ mapper = storage_report.get_mapper(mapper_id)
+ if mapper is None:
+ return None
+
+ removable, props = get_props_data_internal(session, mapper)
+
+ new_targets = []
+ for t_xml in storage_report.get_new_targets(mapper):
+ new_targets.append(get_bd_data_internal(session, t_xml, mapper))
+
+ new_sources = []
+ for s_xml in storage_report.get_new_sources(mapper):
+ new_sources.append(get_bd_data_internal(session, s_xml, mapper))
+
+ targets = []
+ for t_xml in storage_report.get_targets(mapper):
+ targets.append(get_bd_data_internal(session, t_xml, mapper))
+
+ sources = []
+ for s_xml in storage_report.get_sources(mapper):
+ sources.append(get_bd_data_internal(session, s_xml, mapper))
+
+ mapper_type = mapper.getAttribute('mapper_type')
+ pretty_type, pretty_target_name, pretty_source_name = get_pretty_mapper_info(mapper_type)
+ pretty_name = mapper_id.replace('%s:' % mapper_type, '').replace('/dev/', '')
+ pretty_targets_name = '%ss' % pretty_target_name
+ pretty_sources_name = '%ss' % pretty_source_name
+ icon_name, dummy1, dummy2 = get_mapper_icons(mapper_type)
+ color = 'black'
+
+ mapper_ret = {}
+ mapper_ret['pretty_type'] = pretty_type
+ mapper_ret['pretty_name'] = pretty_name
+ mapper_ret['pretty_target_name'] = pretty_target_name
+ mapper_ret['pretty_targets_name'] = pretty_targets_name
+ mapper_ret['pretty_source_name'] = pretty_source_name
+ mapper_ret['pretty_sources_name'] = pretty_sources_name
+ mapper_ret['mapper_id'] = mapper_id
+ mapper_ret['mapper_type'] = mapper_type
+ mapper_ret['props'] = props
+ mapper_ret['props_ordered'] = get_ordered_props(props)
+ mapper_ret['targets'] = targets
+ mapper_ret['new_targets'] = new_targets
+ mapper_ret['sources'] = sources
+ mapper_ret['new_sources'] = new_sources
+ mapper_ret['icon'] = icon_name
+ mapper_ret['color'] = color
+ mapper_ret['xml'] = mapper#.cloneNode(True)
+
+ assemble_all_targets(mapper_ret)
+
+ actions = []
+ if removable:
+ action = {
+ 'name': 'Remove',
+ 'msg': 'Are you sure you want to remove %s \\\'%s\\\'?' % (pretty_type, pretty_name),
+ 'link': ''
+ }
+ actions.append(action)
+ if mapper_type == MAPPER_VG_TYPE or mapper_type == MAPPER_MDRAID_TYPE or mapper_type == MAPPER_ATARAID_TYPE or mapper_type == MAPPER_MULTIPATH_TYPE:
+ action = {
+ 'name': 'Add %s' % mapper_ret['pretty_sources_name'],
+ 'msg': '',
+ 'link': './?%s=%s&%s=%s&%s=%s' \
+ % (PAGETYPE, ADD_SOURCES, PT_MAPPER_ID, mapper_ret['mapper_id'], PT_MAPPER_TYPE, mapper_ret['mapper_type'])
+ }
+ actions.append(action)
+ if mapper_type == MAPPER_VG_TYPE:
+ for nt in mapper_ret['new_targets']:
+ if nt['props']['snapshot']['value'] == 'false':
+ if nt['new']:
+ action = {
+ 'name': 'New %s' % mapper_ret['pretty_target_name'],
+ 'msg': '',
+ 'link': './?%s=%s&%s=%s&%s=%s&%s=%s' \
+ % (PAGETYPE, VIEW_BD,
+ PT_MAPPER_ID, mapper_ret['mapper_id'], \
+ PT_MAPPER_TYPE, mapper_ret['mapper_type'], \
+ PT_PATH, nt['path'])
+ }
+ actions.append(action)
+ break
+ mapper_ret['actions'] = actions
+
+ if mapper_type == MAPPER_VG_TYPE:
+ link_snapshots(mapper_ret)
+
+ # cylinders work properly for VGs only, for now
+ mapper_ret['graphical_view'] = mapper_type != MAPPER_PT_TYPE
+ if mapper_ret['graphical_view']:
+ mapper_ret['mappings-view_css_classnames'] = {
+ 'graphical_view': 'visible',
+ 'textual_view': 'invisible'
+ }
+ else:
+ mapper_ret['mappings-view_css_classnames'] = {
+ 'graphical_view': 'invisible',
+ 'textual_view': 'visible'
+ }
+ mapper_ret['need_apply_button'] = mutable_props(mapper_ret['props'])
+ return mapper_ret
def link_snapshots(mapper):
- for snap in mapper['targets']:
- if snap['props']['snapshot']['value'] != 'true':
- continue
- orig_name = snap['props']['snapshot_origin']['value']
- snap['description'] = '%s, %s\'s Snapshot' \
- % (snap['description'], orig_name)
-
- # find origin
- for t in mapper['targets']:
- if t['pretty_name'] == orig_name:
- if 'snapshots' not in t:
- t['snapshots'] = []
- snap['origin'] = t
- t['snapshots'].append(snap)
- return
-
-
+ for snap in mapper['targets']:
+ if snap['props']['snapshot']['value'] != 'true':
+ continue
+ orig_name = snap['props']['snapshot_origin']['value']
+ snap['description'] = '%s, %s\'s Snapshot' \
+ % (snap['description'], orig_name)
+
+ # find origin
+ for t in mapper['targets']:
+ if t['pretty_name'] == orig_name:
+ if 'snapshots' not in t:
+ t['snapshots'] = []
+ snap['origin'] = t
+ t['snapshots'].append(snap)
+ return
def assemble_all_targets(mapper_data):
- mdata = mapper_data
- targets_all = []
+ mdata = mapper_data
+ targets_all = []
- if mdata['mapper_type'] == MAPPER_VG_TYPE:
- for t in mdata['targets']:
- targets_all.append(t)
- for t in mdata['new_targets']:
- if t['props']['snapshot']['value'] == 'false':
- targets_all.append(t)
- else:
- mdata['snapshot_template'] = t
- elif mdata['mapper_type'] == MAPPER_PT_TYPE:
- # extended-primary substitution
- extended_templs = []
- for t in mdata['new_targets']:
- if t['props']['partition_type']['value'] == 'extended':
- extended_templs.append(t)
- for ext in extended_templs:
- # find matching primary parts
- for t in mdata['new_targets']:
- if t['props']['partition_type']['value'] == 'primary':
- if t['props']['partition_begin']['value'] == ext['props']['partition_begin']['value']:
- t['props']['partition_type']['replacements'] = {'repl_names' : ['primary', 'extended'],
- 'primary' : t,
- 'extended' : ext }
- ext['props']['partition_type']['replacements'] = {'repl_names' : ['extended', 'primary'],
- 'extended' : ext,
- 'primary' : t }
- for t in mdata['targets']:
- targets_all.append(t)
- for t in mdata['new_targets']:
- if t['props']['partition_type']['value'] != 'extended':
- targets_all.append(t)
-
- # TODO: place logical into extended
-
- # sort partitions
- p_sorted = []
- while len(targets_all) != 0:
- smallest_num = 100000000000000000000
- smallest_bd = None
- smallest_index = 0
- i = 0
- for i in xrange(len(targets_all)):
- bd = targets_all[i]
- begin = int(bd['props']['partition_begin']['value'])
- if begin < smallest_num:
- smallest_num = begin
- smallest_bd = bd
- smallest_index = i
- targets_all.pop(smallest_index)
- p_sorted.append(smallest_bd)
- targets_all = p_sorted
- else:
- for t in mdata['targets']:
- targets_all.append(t)
- for t in mdata['new_targets']:
- targets_all.append(t)
+ if mdata['mapper_type'] == MAPPER_VG_TYPE:
+ for t in mdata['targets']:
+ targets_all.append(t)
+ for t in mdata['new_targets']:
+ if t['props']['snapshot']['value'] == 'false':
+ targets_all.append(t)
+ else:
+ mdata['snapshot_template'] = t
+ elif mdata['mapper_type'] == MAPPER_PT_TYPE:
+ # extended-primary substitution
+ extended_templs = []
+ for t in mdata['new_targets']:
+ if t['props']['partition_type']['value'] == 'extended':
+ extended_templs.append(t)
+ for ext in extended_templs:
+ # find matching primary parts
+ for t in mdata['new_targets']:
+ if t['props']['partition_type']['value'] == 'primary':
+ if t['props']['partition_begin']['value'] == ext['props']['partition_begin']['value']:
+ t['props']['partition_type']['replacements'] = {
+ 'repl_names': ['primary', 'extended'],
+ 'primary': t,
+ 'extended': ext
+ }
+
+ ext['props']['partition_type']['replacements'] = {
+ 'repl_names': ['extended', 'primary'],
+ 'extended': ext,
+ 'primary': t
+ }
+ for t in mdata['targets']:
+ targets_all.append(t)
+ for t in mdata['new_targets']:
+ if t['props']['partition_type']['value'] != 'extended':
+ targets_all.append(t)
+
+ # TODO: place logical into extended
+
+ # sort partitions
+ p_sorted = []
+ while len(targets_all) != 0:
+ smallest_num = 100000000000000000000
+ smallest_bd = None
+ smallest_index = 0
+ i = 0
+ for i in xrange(len(targets_all)):
+ bd = targets_all[i]
+ begin = int(bd['props']['partition_begin']['value'])
+ if begin < smallest_num:
+ smallest_num = begin
+ smallest_bd = bd
+ smallest_index = i
+ targets_all.pop(smallest_index)
+ p_sorted.append(smallest_bd)
+ targets_all = p_sorted
+ else:
+ for t in mdata['targets']:
+ targets_all.append(t)
+ for t in mdata['new_targets']:
+ targets_all.append(t)
- mdata['targets_all'] = targets_all
+ mdata['targets_all'] = targets_all
def get_mapper_template_data(self, storage_report, mapper_type):
- if self is None or storage_report is None or mapper_type is None:
- return None
-
- session = self.REQUEST.SESSION
-
- mapper_id = ''
-
- templ_xml_list = storage_report.get_mapper_temps(mapper_type)
- mapper = None
- if len(templ_xml_list) != 0:
- mapper = templ_xml_list[0]
- if mapper is None:
- return None
-
- removable, props = get_props_data_internal(session, mapper)
-
- new_targets = []
- for t_xml in storage_report.get_new_targets(mapper):
- new_targets.append(get_bd_data_internal(session, t_xml, mapper))
- new_sources = []
- for s_xml in storage_report.get_new_sources(mapper):
- new_sources.append(get_bd_data_internal(session, s_xml, mapper))
- targets = []
- for t_xml in storage_report.get_targets(mapper):
- targets.append(get_bd_data_internal(session, t_xml, mapper))
- sources = []
- for s_xml in storage_report.get_sources(mapper):
- sources.append(get_bd_data_internal(session, s_xml, mapper))
-
- mapper_type = mapper.getAttribute('mapper_type')
- pretty_type, pretty_target_name, pretty_source_name = get_pretty_mapper_info(mapper_type)
- pretty_name = mapper_id.replace('%s:' % mapper_type, '').replace('/dev/', '')
- pretty_targets_name = '%ss' % pretty_target_name
- pretty_sources_name = '%ss' % pretty_source_name
- icon_name, dummy1, dummy2 = get_mapper_icons(mapper_type)
- color = 'black'
-
- min_sources = '0'
- max_sources = '0'
- new_props = {}
- for name in props:
- if name == 'min_sources':
- min_sources = props[name]['value']
- elif name == 'max_sources':
- max_sources = props[name]['value']
- else:
- new_props[name] = props[name]
- props = new_props
-
- mapper_ret = {}
- mapper_ret['pretty_type'] = pretty_type
- mapper_ret['pretty_name'] = pretty_name
- mapper_ret['pretty_target_name'] = pretty_target_name
- mapper_ret['pretty_targets_name'] = pretty_targets_name
- mapper_ret['pretty_source_name'] = pretty_source_name
- mapper_ret['pretty_sources_name'] = pretty_sources_name
- mapper_ret['mapper_id'] = mapper_id
- mapper_ret['mapper_type'] = mapper_type
- mapper_ret['props'] = props
- mapper_ret['props_ordered'] = get_ordered_props(props)
- #mapper_ret['removable'] = removable
- mapper_ret['targets'] = targets
- mapper_ret['new_targets'] = new_targets
- mapper_ret['sources'] = sources
- mapper_ret['new_sources'] = new_sources
- mapper_ret['min_sources'] = min_sources
- mapper_ret['max_sources'] = max_sources
- mapper_ret['icon'] = icon_name
- mapper_ret['color'] = color
- mapper_ret['xml'] = mapper#.cloneNode(True)
-
- mapper_ret['actions'] = []
-
- mapper_ret['need_apply_button'] = True
-
- return mapper_ret
-
-
+ if self is None or storage_report is None or mapper_type is None:
+ return None
+ session = self.REQUEST.SESSION
+ mapper_id = ''
+ templ_xml_list = storage_report.get_mapper_temps(mapper_type)
+ mapper = None
+
+ if len(templ_xml_list) != 0:
+ mapper = templ_xml_list[0]
+
+ if mapper is None:
+ return None
+
+ removable, props = get_props_data_internal(session, mapper)
+
+ new_targets = []
+ for t_xml in storage_report.get_new_targets(mapper):
+ new_targets.append(get_bd_data_internal(session, t_xml, mapper))
+
+ new_sources = []
+ for s_xml in storage_report.get_new_sources(mapper):
+ new_sources.append(get_bd_data_internal(session, s_xml, mapper))
+
+ targets = []
+ for t_xml in storage_report.get_targets(mapper):
+ targets.append(get_bd_data_internal(session, t_xml, mapper))
+
+ sources = []
+ for s_xml in storage_report.get_sources(mapper):
+ sources.append(get_bd_data_internal(session, s_xml, mapper))
+
+ mapper_type = mapper.getAttribute('mapper_type')
+ pretty_type, pretty_target_name, pretty_source_name = get_pretty_mapper_info(mapper_type)
+ pretty_name = mapper_id.replace('%s:' % mapper_type, '').replace('/dev/', '')
+ pretty_targets_name = '%ss' % pretty_target_name
+ pretty_sources_name = '%ss' % pretty_source_name
+ icon_name, dummy1, dummy2 = get_mapper_icons(mapper_type)
+ color = 'black'
+
+ min_sources = '0'
+ max_sources = '0'
+ new_props = {}
+ for name in props:
+ if name == 'min_sources':
+ min_sources = props[name]['value']
+ elif name == 'max_sources':
+ max_sources = props[name]['value']
+ else:
+ new_props[name] = props[name]
+ props = new_props
+
+ mapper_ret = {}
+ mapper_ret['pretty_type'] = pretty_type
+ mapper_ret['pretty_name'] = pretty_name
+ mapper_ret['pretty_target_name'] = pretty_target_name
+ mapper_ret['pretty_targets_name'] = pretty_targets_name
+ mapper_ret['pretty_source_name'] = pretty_source_name
+ mapper_ret['pretty_sources_name'] = pretty_sources_name
+ mapper_ret['mapper_id'] = mapper_id
+ mapper_ret['mapper_type'] = mapper_type
+ mapper_ret['props'] = props
+ mapper_ret['props_ordered'] = get_ordered_props(props)
+ #mapper_ret['removable'] = removable
+ mapper_ret['targets'] = targets
+ mapper_ret['new_targets'] = new_targets
+ mapper_ret['sources'] = sources
+ mapper_ret['new_sources'] = new_sources
+ mapper_ret['min_sources'] = min_sources
+ mapper_ret['max_sources'] = max_sources
+ mapper_ret['icon'] = icon_name
+ mapper_ret['color'] = color
+ mapper_ret['xml'] = mapper#.cloneNode(True)
+
+ mapper_ret['actions'] = []
+ mapper_ret['need_apply_button'] = True
+ return mapper_ret
# TODO: implement
def validate(self, storage_report, request):
- #return 'size has to be within limits'
- #return request
- #return 'OK'
-
- object_type = request['object_type']
- mapper_id = request['mapper_id']
-
- props = None
- content_props = None
-
- if object_type == 'bd' or object_type == 'bd_template':
- path = request[PT_PATH]
- bd_data = get_bd_data(self, storage_report, mapper_id, path)
- props = bd_data['props']
- if path != 'new_snapshot':
- selected_content_id = request['content_id']
- for c_data in bd_data['contents']:
- if c_data['id'] == selected_content_id:
- content_props = c_data['props']
- elif object_type == 'mapper':
- props = get_mapper_data(self, storage_report, mapper_id)['props']
- elif object_type == 'mapper_template':
- mapper_type = request['mapper_type']
- data = get_mapper_template_data(self, storage_report, mapper_type)
- # find sources
- sources_num = 0
- for v in request.keys():
- if v.find('source_bd_') == 0:
- if request[v] == 'on':
- sources_num += 1
- if sources_num < int(data['min_sources']) or sources_num > int(data['max_sources']):
- return 'BAD: Invalid number of %s selected' % data['pretty_sources_name']
- props = data['props']
- elif object_type == 'add_sources':
- data = get_mapper_data(self, storage_report, mapper_id)
- # find sources
- sources_num = 0
- for v in request.keys():
- if v.find('source_bd_') == 0:
- if request[v] == 'on':
- sources_num += 1
- if sources_num == 0 or sources_num > len(data['new_sources']):
- return 'BAD: Invalid number of %s selected' % data['pretty_sources_name']
-
- if props is not None:
- res = check_props(self, props, request)
- if res[0] is False:
- return '%s %s' % (res[1], res[2])
-
- if content_props is not None:
- res = check_props(self, content_props, request)
- if res[0] is False:
- return '%s %s' % (res[1], res[2])
+ #return 'size has to be within limits'
+ #return request
+ #return 'OK'
+
+ object_type = request['object_type']
+ mapper_id = request['mapper_id']
+
+ props = None
+ content_props = None
+
+ if object_type == 'bd' or object_type == 'bd_template':
+ path = request[PT_PATH]
+ bd_data = get_bd_data(self, storage_report, mapper_id, path)
+ props = bd_data['props']
+ if path != 'new_snapshot':
+ selected_content_id = request['content_id']
+ for c_data in bd_data['contents']:
+ if c_data['id'] == selected_content_id:
+ content_props = c_data['props']
+ elif object_type == 'mapper':
+ props = get_mapper_data(self, storage_report, mapper_id)['props']
+ elif object_type == 'mapper_template':
+ mapper_type = request['mapper_type']
+ data = get_mapper_template_data(self, storage_report, mapper_type)
+ # find sources
+ sources_num = 0
+ for v in request.keys():
+ if v.find('source_bd_') == 0:
+ if request[v] == 'on':
+ sources_num += 1
+ if sources_num < int(data['min_sources']) or sources_num > int(data['max_sources']):
+ return 'BAD: Invalid number of %s selected' % data['pretty_sources_name']
+ props = data['props']
+ elif object_type == 'add_sources':
+ data = get_mapper_data(self, storage_report, mapper_id)
+ # find sources
+ sources_num = 0
+ for v in request.keys():
+ if v.find('source_bd_') == 0:
+ if request[v] == 'on':
+ sources_num += 1
+ if sources_num == 0 or sources_num > len(data['new_sources']):
+ return 'BAD: Invalid number of %s selected' % data['pretty_sources_name']
+
+ if props is not None:
+ res = check_props(self, props, request)
+ if res[0] is False:
+ return '%s %s' % (res[1], res[2])
+
+ if content_props is not None:
+ res = check_props(self, content_props, request)
+ if res[0] is False:
+ return '%s %s' % (res[1], res[2])
- return 'OK'
+ return 'OK'
def check_props(self, props, request):
- valid = True
- var_name = ''
- msg = 'no message - BUG'
-
- for prop_name in props:
- if prop_name in request:
- prop = props[prop_name]
- req_value = request[prop_name]
- if prop['type'] == 'int':
- if prop['units'] != 'bytes':
- try:
- req_value = int(req_value)
- except:
- msg = '%s is missing an integer value' % prop['pretty_name']
- var_name = prop_name
- valid = False
- break
- min_val = int(prop['validation']['min'])
- max_val = int(prop['validation']['max'])
- step = int(prop['validation']['step'])
- r_val = (req_value / step) * step
- if r_val > max_val or r_val < min_val:
- msg = '%s has to be within range %d-%d %s' \
- % (prop['pretty_name'], min_val, max_val, prop['units'])
- var_name = prop_name
- valid = False
- break
- else:
- try:
- req_value = float(req_value)
- except:
- msg = '%s is missing a float value' % prop['pretty_name']
- var_name = prop_name
- valid = False
- break
- dummy, units = bytes_to_value_prefunits(self, prop['value'])
- min_val = float(convert_bytes(prop['validation']['min'], units))
- max_val = float(convert_bytes(prop['validation']['max'], units))
- step = float(convert_bytes(prop['validation']['step'], units))
- if step < 0.000001:
- step = 0.000001
- r_val = (req_value / step) * step
- if r_val > max_val or r_val < min_val:
- msg = '%s has to be within range %d-%d %s' \
- % (prop['pretty_name'], min_val, max_val, units)
- var_name = prop_name
- valid = False
- break
- elif prop['type'] == 'text':
- if len(req_value) < int(prop['validation']['min_length']):
- msg = '%s has to have minimum length of %s' \
- % (prop['pretty_name'], prop['validation']['min_length'])
- var_name = prop_name
- valid = False
- break
- elif len(req_value) > int(prop['validation']['max_length']):
- msg = '%s has to have maximum length of %s' \
- % (prop['pretty_name'], prop['validation']['max_length'])
- var_name = prop_name
- valid = False
- break
- elif req_value in prop['validation']['reserved_words'].split(';') and req_value != '':
- msg = '%s contains reserved keyword. \nReserved keywords are %s' % (prop['pretty_name'], prop['validation']['reserved_words'].replace(';', ', '))
- var_name = prop_name
- valid = False
- break
- # check illegal chars
- for ch in prop['validation']['illegal_chars']:
- if ch in req_value and ch != '':
- msg = '%s contains illegal characters. \nIllegal characters are %s' % (prop['pretty_name'], prop['validation']['illegal_chars'].replace(';', ', '))
- var_name = prop_name
- valid = False
- break
+ valid = True
+ var_name = ''
+ msg = 'no message - BUG'
+
+ for prop_name in props:
+ if prop_name in request:
+ prop = props[prop_name]
+ req_value = request[prop_name]
+ if prop['type'] == 'int':
+ if prop['units'] != 'bytes':
+ try:
+ req_value = int(req_value)
+ except:
+ msg = '%s is missing an integer value' % prop['pretty_name']
+ var_name = prop_name
+ valid = False
+ break
+ min_val = int(prop['validation']['min'])
+ max_val = int(prop['validation']['max'])
+ step = int(prop['validation']['step'])
+ r_val = (req_value / step) * step
+ if r_val > max_val or r_val < min_val:
+ msg = '%s has to be within range %d-%d %s' \
+ % (prop['pretty_name'], min_val, max_val, prop['units'])
+ var_name = prop_name
+ valid = False
+ break
+ else:
+ try:
+ req_value = float(req_value)
+ except:
+ msg = '%s is missing a float value' % prop['pretty_name']
+ var_name = prop_name
+ valid = False
+ break
+ dummy, units = bytes_to_value_prefunits(self, prop['value'])
+ min_val = float(convert_bytes(prop['validation']['min'], units))
+ max_val = float(convert_bytes(prop['validation']['max'], units))
+ step = float(convert_bytes(prop['validation']['step'], units))
+ if step < 0.000001:
+ step = 0.000001
+ r_val = (req_value / step) * step
+ if r_val > max_val or r_val < min_val:
+ msg = '%s has to be within range %d-%d %s' \
+ % (prop['pretty_name'], min_val, max_val, units)
+ var_name = prop_name
+ valid = False
+ break
+ elif prop['type'] == 'text':
+ if len(req_value) < int(prop['validation']['min_length']):
+ msg = '%s has to have minimum length of %s' \
+ % (prop['pretty_name'], prop['validation']['min_length'])
+ var_name = prop_name
+ valid = False
+ break
+ elif len(req_value) > int(prop['validation']['max_length']):
+ msg = '%s has to have maximum length of %s' \
+ % (prop['pretty_name'], prop['validation']['max_length'])
+ var_name = prop_name
+ valid = False
+ break
+ elif req_value in prop['validation']['reserved_words'].split(';') and req_value != '':
+ msg = '%s contains reserved keyword. \nReserved keywords are %s' % (prop['pretty_name'], prop['validation']['reserved_words'].replace(';', ', '))
+ var_name = prop_name
+ valid = False
+ break
+ # check illegal chars
+ for ch in prop['validation']['illegal_chars']:
+ if ch in req_value and ch != '':
+ msg = '%s contains illegal characters. \nIllegal characters are %s' \
+ % (prop['pretty_name'], prop['validation']['illegal_chars'].replace(';', ', '))
+ var_name = prop_name
+ valid = False
+ break
- return [valid, var_name, msg]
+ return [valid, var_name, msg]
def apply_storage_changes(self, ricci, storage_report, request):
- if validate(self, storage_report, request) != 'OK':
- raise Exception, 'Internal error: input not validated!!!'
-
- session = request.SESSION
-
- storagename = request['storagename']
-
- object_type = request['object_type']
- mapper_id = request[PT_MAPPER_ID]
- mapper_type = request[PT_MAPPER_TYPE]
- action_type = request['action_type']
- path = ''
- if request.has_key(PT_PATH):
- path = request[PT_PATH]
-
-
- batch_id = ''
-
- if object_type == 'bd':
- bd_data = get_bd_data(self, storage_report, mapper_id, path)
- bd_xml = bd_data['xml']#.cloneNode(True)
-
- if action_type == 'Remove':
- doc = minidom.Document()
- batch = doc.createElement("batch")
- module = doc.createElement("module")
- module.setAttribute("name", "storage")
- req = doc.createElement("request")
- req.setAttribute("API_version", "1.0")
- req.setAttribute("sequence", "10")
- f_call = doc.createElement("function_call")
- f_call.setAttribute('name', 'remove_bd')
- #f_call.appendChild(Variable('bd', bd_xml.cloneNode(True)).export_xml(doc))
- f_call.appendChild(Variable('bd', bd_xml).export_xml(doc))
-
- req.appendChild(f_call)
- module.appendChild(req)
- batch.appendChild(module)
-
- res = ricci.process_batch(batch, True)
- batch_id = res.getAttribute('batch_id')
-
-
- elif action_type == 'Apply':
- # BD props
- props_xml = None
- for node in bd_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == PROPS_TAG:
- props_xml = node
- for node in props_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == VARIABLE_TAG:
- if node.getAttribute('mutable') == 'true':
- var_name = node.getAttribute('name')
- if var_name in request:
- if bd_data['props'][var_name]['type'] == 'int':
- if bd_data['props'][var_name]['units'] != 'bytes':
- val = int(request[var_name])
- step = int(bd_data['props'][var_name]['validation']['step'])
- val = (val / step) * step
- else:
- dummy, units = bytes_to_value_prefunits(self,
- bd_data['props'][var_name]['value'])
- min_val = int(bd_data['props'][var_name]['validation']['min'])
- max_val = int(bd_data['props'][var_name]['validation']['max'])
- step = int(bd_data['props'][var_name]['validation']['step'])
- val_units = float(request[var_name])
- val = int(val_units * get_units_multiplier(units))
- val = (val / step) * step
- if val < min_val:
- val = min_val
- if val > max_val:
- val = max_val
- node.setAttribute('value', str(val))
- else:
- node.setAttribute('value', request[var_name])
-
- # content
- content_data_list = get_content_data_internal(session, bd_xml)
- current_content_id = content_data_list[0]['id']
- selected_content_id = request['content_id']
- selected_content = None
- selected_content_data = None
- for c_data in content_data_list:
- if c_data['id'] == selected_content_id:
- selected_content_data = c_data
- selected_content = c_data['xml']#.cloneNode(True)
-
- # update selected_content props
- props_xml = None
- for node in selected_content.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == PROPS_TAG:
- props_xml = node
- for node in props_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == VARIABLE_TAG:
- if node.getAttribute('mutable') == 'true':
- var_name = node.getAttribute('name')
- req_name = 'content_variable_%s_%s' % (selected_content_id, var_name)
- if req_name in request:
- if selected_content_data['props'][req_name]['type'] == 'int':
- if selected_content_data['props'][req_name]['units'] != 'bytes':
- val = int(request[req_name])
- step = int(selected_content_data['props'][req_name]['validation']['step'])
- val = (val / step) * step
- else:
- dummy, units = bytes_to_value_prefunits(self,
- selected_content_data['props'][req_name]['value'])
- min_val = int(selected_content_data['props'][req_name]['validation']['min'])
- max_val = int(selected_content_data['props'][req_name]['validation']['max'])
- step = int(selected_content_data['props'][req_name]['validation']['step'])
- val_units = float(request[req_name])
- val = int(val_units * get_units_multiplier(units))
- val = (val / step) * step
- if val < min_val:
- val = min_val
- if val > max_val:
- val = max_val
- node.setAttribute('value', str(val))
- else:
- node.setAttribute('value', request[req_name])
-
- if current_content_id == selected_content_id:
- # no change of content
- # replace content_xml
- for node in bd_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == 'content':
- bd_xml.removeChild(node)
- bd_xml.appendChild(selected_content)
- break
- else:
- # content changed
- # place it under <new_content>
- for node in bd_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == 'content':
- for node2 in node.childNodes:
- if node2.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node2.nodeName == 'new_content':
- node2.appendChild(selected_content)
- break
- #return bd_xml.toprettyxml()
- doc = minidom.Document()
- batch = doc.createElement("batch")
- module = doc.createElement("module")
- module.setAttribute("name", "storage")
- req = doc.createElement("request")
- req.setAttribute("API_version", "1.0")
- req.setAttribute("sequence", "10")
- f_call = doc.createElement("function_call")
- f_call.setAttribute('name', 'modify_bd')
- f_call.appendChild(Variable('bd', bd_xml).export_xml(doc))
-
- req.appendChild(f_call)
- module.appendChild(req)
- batch.appendChild(module)
-
- res = ricci.process_batch(batch, True)
- batch_id = res.getAttribute('batch_id')
-
-
- elif object_type == 'bd_template':
- path = request[PT_PATH]
- bd_data = get_bd_data(self, storage_report, mapper_id, path)
- bd_xml = bd_data['xml']#.cloneNode(True)
- #return bd_xml.toprettyxml()
-
- if action_type == 'Apply': # Create
- # BD props
- props_xml = None
- for node in bd_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == PROPS_TAG:
- props_xml = node
- for node in props_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == VARIABLE_TAG:
- if node.getAttribute('mutable') == 'true':
- var_name = node.getAttribute('name')
- if var_name in request:
- if bd_data['props'][var_name]['type'] == 'int':
- if bd_data['props'][var_name]['units'] != 'bytes':
- val = int(request[var_name])
- step = int(bd_data['props'][var_name]['validation']['step'])
- val = (val / step) * step
- else:
- dummy, units = bytes_to_value_prefunits(self,
- bd_data['props'][var_name]['value'])
- min_val = int(bd_data['props'][var_name]['validation']['min'])
- max_val = int(bd_data['props'][var_name]['validation']['max'])
- step = int(bd_data['props'][var_name]['validation']['step'])
- val_units = float(request[var_name])
- val = int(val_units * get_units_multiplier(units))
- val = (val / step) * step
- if val < min_val:
- val = min_val
- if val > max_val:
- val = max_val
- node.setAttribute('value', str(val))
- else:
- node.setAttribute('value', request[var_name])
-
- if path != 'new_snapshot':
- # content
- content_data_list = get_content_data_internal(session, bd_xml)
- current_content_id = content_data_list[0]['id']
- selected_content_id = request['content_id']
- selected_content = None
- selected_content_data = None
- for c_data in content_data_list:
- if c_data['id'] == selected_content_id:
- selected_content_data = c_data
- selected_content = c_data['xml']#.cloneNode(True)
-
- # update selected_content props
- props_xml = None
- for node in selected_content.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == PROPS_TAG:
- props_xml = node
- for node in props_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == VARIABLE_TAG:
- if node.getAttribute('mutable') == 'true':
- var_name = node.getAttribute('name')
- req_name = 'content_variable_%s_%s' % (selected_content_id, var_name)
- if req_name in request:
- if selected_content_data['props'][req_name]['type'] == 'int':
- if selected_content_data['props'][req_name]['units'] != 'bytes':
- val = int(request[req_name])
- step = int(selected_content_data['props'][req_name]['validation']['step'])
- val = (val / step) * step
- else:
- dummy, units = bytes_to_value_prefunits(self,
- selected_content_data['props'][req_name]['value'])
- min_val = int(selected_content_data['props'][req_name]['validation']['min'])
- max_val = int(selected_content_data['props'][req_name]['validation']['max'])
- step = int(selected_content_data['props'][req_name]['validation']['step'])
- val_units = float(request[req_name])
- val = int(val_units * get_units_multiplier(units))
- val = (val / step) * step
- if val < min_val:
- val = min_val
- if val > max_val:
- val = max_val
- node.setAttribute('value', str(val))
- else:
- node.setAttribute('value', request[req_name])
-
- if current_content_id == selected_content_id:
- # no change of content
- # replace content_xml
- for node in bd_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == 'content':
- bd_xml.removeChild(node)
- bd_xml.appendChild(selected_content)
- break
- else:
- # content changed
- # place it under <new_content>
- for node in bd_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == 'content':
- for node2 in node.childNodes:
- if node2.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node2.nodeName == 'new_content':
- node2.appendChild(selected_content)
- break
- #return bd_xml.toprettyxml()
- doc = minidom.Document()
- batch = doc.createElement("batch")
- module = doc.createElement("module")
- module.setAttribute("name", "storage")
- req = doc.createElement("request")
- req.setAttribute("API_version", "1.0")
- req.setAttribute("sequence", "10")
- f_call = doc.createElement("function_call")
- f_call.setAttribute('name', 'create_bd')
- f_call.appendChild(Variable('bd', bd_xml).export_xml(doc))
-
- req.appendChild(f_call)
- module.appendChild(req)
- batch.appendChild(module)
-
- res = ricci.process_batch(batch, True)
- batch_id = res.getAttribute('batch_id')
-
-
-
- elif object_type == 'mapper':
- mapper_data = get_mapper_data(self, storage_report, mapper_id)
- mapper_xml = mapper_data['xml']#.cloneNode(True)
- #return mapper_xml.toprettyxml()
-
- if action_type == 'Remove':
- doc = minidom.Document()
- batch = doc.createElement("batch")
- module = doc.createElement("module")
- module.setAttribute("name", "storage")
- req = doc.createElement("request")
- req.setAttribute("API_version", "1.0")
- req.setAttribute("sequence", "10")
- f_call = doc.createElement("function_call")
- f_call.setAttribute('name', 'remove_mapper')
- f_call.appendChild(Variable('mapper', mapper_xml).export_xml(doc))
-
- req.appendChild(f_call)
- module.appendChild(req)
- batch.appendChild(module)
-
- res = ricci.process_batch(batch, True)
- batch_id = res.getAttribute('batch_id')
-
-
- elif action_type == 'Apply':
- # props
- props_xml = None
- for node in mapper_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == PROPS_TAG:
- props_xml = node
- for node in props_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == VARIABLE_TAG:
- if node.getAttribute('mutable') == 'true':
- var_name = node.getAttribute('name')
- if var_name in request:
- if mapper_data['props'][var_name]['type'] == 'int':
- if mapper_data['props'][var_name]['units'] != 'bytes':
- val = int(request[var_name])
- step = int(mapper_data['props'][var_name]['validation']['step'])
- val = (val / step) * step
- else:
- dummy, units = bytes_to_value_prefunits(self,
- mapper_data['props'][var_name]['value'])
- min_val = int(mapper_data['props'][var_name]['validation']['min'])
- max_val = int(mapper_data['props'][var_name]['validation']['max'])
- step = int(mapper_data['props'][var_name]['validation']['step'])
- val_units = float(request[var_name])
- val = int(val_units * get_units_multiplier(units))
- val = (val / step) * step
- if val < min_val:
- val = min_val
- if val > max_val:
- val = max_val
- node.setAttribute('value', str(val))
- else:
- node.setAttribute('value', request[var_name])
- #return mapper_xml.toprettyxml()
- doc = minidom.Document()
- batch = doc.createElement("batch")
- module = doc.createElement("module")
- module.setAttribute("name", "storage")
- req = doc.createElement("request")
- req.setAttribute("API_version", "1.0")
- req.setAttribute("sequence", "10")
- f_call = doc.createElement("function_call")
- f_call.setAttribute('name', 'modify_mapper')
- f_call.appendChild(Variable('mapper', mapper_xml).export_xml(doc))
-
- req.appendChild(f_call)
- module.appendChild(req)
- batch.appendChild(module)
-
- res = ricci.process_batch(batch, True)
- batch_id = res.getAttribute('batch_id')
-
-
-
- elif object_type == 'mapper_template':
- mapper_data = get_mapper_template_data(self, storage_report, mapper_type)
- mapper_xml = mapper_data['xml']#.cloneNode(True)
- #return mapper_xml.toprettyxml()
-
- if action_type == 'Apply':
- # props
- props_xml = None
- for node in mapper_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == PROPS_TAG:
- props_xml = node
- for node in props_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == VARIABLE_TAG:
- if node.getAttribute('mutable') == 'true':
- var_name = node.getAttribute('name')
- if request.has_key(var_name):
- if mapper_data['props'][var_name]['type'] == 'int':
- if mapper_data['props'][var_name]['units'] != 'bytes':
- val = int(request[var_name])
- step = int(mapper_data['props'][var_name]['validation']['step'])
- val = (val / step) * step
- else:
- dummy, units = bytes_to_value_prefunits(self,
- mapper_data['props'][var_name]['value'])
- min_val = int(mapper_data['props'][var_name]['validation']['min'])
- max_val = int(mapper_data['props'][var_name]['validation']['max'])
- step = int(mapper_data['props'][var_name]['validation']['step'])
- val_units = float(request[var_name])
- val = int(val_units * get_units_multiplier(units))
- val = (val / step) * step
- if val < min_val:
- val = min_val
- if val > max_val:
- val = max_val
- node.setAttribute('value', str(val))
- else:
- node.setAttribute('value', request[var_name])
-
- # find sources
- for v in request.keys():
- if v.find('source_bd_') == 0:
- if request[v] == 'on':
- path = v[len('source_bd_'):]
- for s_xml in storage_report.get_new_sources(mapper_xml):
- if s_xml.getAttribute('path') == path:
- for node in mapper_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == MAPPER_SOURCES_TAG:
- node.appendChild(s_xml)#.cloneNode(True))
- #return mapper_xml.toprettyxml()
- doc = minidom.Document()
- batch = doc.createElement("batch")
- module = doc.createElement("module")
- module.setAttribute("name", "storage")
- req = doc.createElement("request")
- req.setAttribute("API_version", "1.0")
- req.setAttribute("sequence", "10")
- f_call = doc.createElement("function_call")
- f_call.setAttribute('name', 'create_mapper')
-# f_call.appendChild(Variable('mapper', mapper_xml.cloneNode(True)).export_xml(doc))
- f_call.appendChild(Variable('mapper', mapper_xml).export_xml(doc))
-
- req.appendChild(f_call)
- module.appendChild(req)
- batch.appendChild(module)
-
- res = ricci.process_batch(batch, True)
- batch_id = res.getAttribute('batch_id')
-
-
-
-
- elif object_type == 'add_sources':
- mapper_data = get_mapper_data(self, storage_report, mapper_id)
- mapper_xml = mapper_data['xml']#.cloneNode(True)
- new_sources = []
- #return mapper_xml.toprettyxml()
-
- if action_type == 'Apply':
- # find sources
- for v in request.keys():
- if v.find('source_bd_') == 0:
- if request[v] == 'on':
- path = v[len('source_bd_'):]
- for ns in mapper_data['new_sources']:
- if ns['path'] == path:
- new_sources.append(ns['xml'])#.cloneNode(True))
- #return mapper_xml.toprettyxml()
- doc = minidom.Document()
- batch = doc.createElement("batch")
- module = doc.createElement("module")
- module.setAttribute("name", "storage")
- req = doc.createElement("request")
- req.setAttribute("API_version", "1.0")
- req.setAttribute("sequence", "11")
- f_call = doc.createElement("function_call")
- f_call.setAttribute('name', 'add_mapper_sources')
- f_call.appendChild(Variable('mapper_type', mapper_type).export_xml(doc))
- f_call.appendChild(Variable('mapper_id', mapper_id).export_xml(doc))
- f_call.appendChild(Variable('mapper_state_ind', mapper_xml.getAttribute('state_ind')).export_xml(doc))
- f_call.appendChild(VariableList('bds', new_sources, [], VARIABLE_TYPE_LIST_XML).export_xml(doc))
-
- req.appendChild(f_call)
- module.appendChild(req)
- batch.appendChild(module)
-
- res = ricci.process_batch(batch, True)
- batch_id = res.getAttribute('batch_id')
-
-
- if batch_id == '':
- raise Exception, 'unsupported function'
- else:
- invalidate_storage_report(request.SESSION, storagename)
- return batch_id
-
-
-def get_storage_batch_result(self,
- storagename,
- ricci,
- index_html_URL,
- batch_id):
- error = True # ricci reported failure or no ricci
- completed = False # no batch, or batch done (defined if no error)
- url = index_html_URL # redirect URL
- msg = 'Unknown error occured'
-
- if ricci is None:
- # ricci down
- error = True
- url = url
- msg = 'Unable to contact %s' % storagename
- else:
- batch = 'no batch'
- try:
- batch = ricci.batch_report(batch_id)
- except:
- pass
- if batch == 'no batch':
- error = True
- url = url
- msg = 'Ricci on %s responded with error. No detailed info available.' % storagename
- elif batch is None:
- # no such batch
- error = False
- completed = True
- url = '%s?%s=%s&%s=%s' \
- % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
- msg = 'No such batch'
- else:
- DEFAULT_ERROR = 'extract_module_status() failed'
- code, err_msg = DEFAULT_ERROR, ''
- try:
- code, err_msg = extract_module_status(batch, 1)
- except:
- pass
- if code == DEFAULT_ERROR:
- error = True
- url = '%s?%s=%s&%s=%s' \
- % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
- msg = 'Ricci on %s sent a malformed response' % storagename
- elif code == -101 or code == -102:
- # in progress
- error = False
- completed = False
- msg = 'Task still in progress'
- elif code == -103:
- # module removed from scheduler
- error = True
- url = '%s?%s=%s&%s=%s' \
- % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
- msg = 'Ricci on %s removed request from scheduler. File bug report against ricci.' % storagename
- elif code == -104:
- # module failure
- error = True
- url = '%s?%s=%s&%s=%s' \
- % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
- msg = 'Ricci on %s failed to execute storage module; reinstall it.' % storagename
- elif code == -2:
- # API error
- error = True
- url = '%s?%s=%s&%s=%s' \
- % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
- msg = 'Luci server used invalid API to communicate with %s. File a bug report against luci.' % storagename
- elif code == -1:
- # undefined error
- error = True
- url = '%s?%s=%s&%s=%s' \
- % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
- msg = 'Reason for failure (as reported by %s): %s' % (storagename, err_msg)
- elif code == 0:
- # no error
- error = False
- completed = True
- # TODO: implement proper redirect
- url = get_commit_redirect(url,
- storagename,
- batch)
- msg = 'Done successfully'
- elif code == 1:
- # mid-air
- error = True
- url = '%s?%s=%s&%s=%s' \
- % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
- msg = 'Mid-Air collision (storage on %s has changed since last probe).' % storagename
- elif code == 2:
- # validation error
- error = True
- url = '%s?%s=%s&%s=%s' \
- % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
- msg = 'Validation error. File bug report against Luci.'
- elif code == 3:
- # unmount error
- error = True
- url = '%s?%s=%s&%s=%s' \
- % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
- msg = 'Unmount failure: %s' % err_msg
- elif code == 4:
- # clvmd error
- error = True
- url = '%s?%s=%s&%s=%s' \
- % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
- msg = 'clvmd (clustered LVM daemon) is not running on %s' % storagename
- elif code == 5:
- # not quorate
- error = True
- url = '%s?%s=%s&%s=%s' \
- % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
- msg = 'Cluster quorum is required, and yet cluster is not quorate. Start cluster, and try again.'
- elif code == 6:
- # LVM cluster locking not enabled
- error = True
- url = '%s?%s=%s&%s=%s' \
- % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
- msg = 'LVM cluster locking is not enabled on %s' % storagename
- elif code == 7:
- # cluster not running
- error = True
- url = '%s?%s=%s&%s=%s' \
- % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
- msg = 'Cluster infrastructure is not running on %s' % storagename
- elif code > 8:
- error = True
- url = '%s?%s=%s&%s=%s' \
- % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
- msg = err_msg
-
- return {'error' : error,
- 'completed' : completed,
- 'redirect_url' : url,
- 'msg' : msg}
+ if validate(self, storage_report, request) != 'OK':
+ raise Exception, 'Internal error: input not validated!!!'
+ session = request.SESSION
+ storagename = request['storagename']
+ object_type = request['object_type']
+ mapper_id = request[PT_MAPPER_ID]
+ mapper_type = request[PT_MAPPER_TYPE]
+ action_type = request['action_type']
+ path = ''
+ if request.has_key(PT_PATH):
+ path = request[PT_PATH]
+
+
+ batch_id = ''
+
+ if object_type == 'bd':
+ bd_data = get_bd_data(self, storage_report, mapper_id, path)
+ bd_xml = bd_data['xml']#.cloneNode(True)
+
+ if action_type == 'Remove':
+ doc = minidom.Document()
+ batch = doc.createElement("batch")
+ module = doc.createElement("module")
+ module.setAttribute("name", "storage")
+ req = doc.createElement("request")
+ req.setAttribute("API_version", "1.0")
+ req.setAttribute("sequence", "10")
+ f_call = doc.createElement("function_call")
+ f_call.setAttribute('name', 'remove_bd')
+ #f_call.appendChild(Variable('bd', bd_xml.cloneNode(True)).export_xml(doc))
+ f_call.appendChild(Variable('bd', bd_xml).export_xml(doc))
+
+ req.appendChild(f_call)
+ module.appendChild(req)
+ batch.appendChild(module)
+
+ res = ricci.process_batch(batch, True)
+ batch_id = res.getAttribute('batch_id')
+
+
+ elif action_type == 'Apply':
+ # BD props
+ props_xml = None
+ for node in bd_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == PROPS_TAG:
+ props_xml = node
+ for node in props_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == VARIABLE_TAG:
+ if node.getAttribute('mutable') == 'true':
+ var_name = node.getAttribute('name')
+ if var_name in request:
+ if bd_data['props'][var_name]['type'] == 'int':
+ if bd_data['props'][var_name]['units'] != 'bytes':
+ val = int(request[var_name])
+ step = int(bd_data['props'][var_name]['validation']['step'])
+ val = (val / step) * step
+ else:
+ dummy, units = bytes_to_value_prefunits(self,
+ bd_data['props'][var_name]['value'])
+ min_val = int(bd_data['props'][var_name]['validation']['min'])
+ max_val = int(bd_data['props'][var_name]['validation']['max'])
+ step = int(bd_data['props'][var_name]['validation']['step'])
+ val_units = float(request[var_name])
+ val = int(val_units * get_units_multiplier(units))
+ val = (val / step) * step
+ if val < min_val:
+ val = min_val
+ if val > max_val:
+ val = max_val
+ node.setAttribute('value', str(val))
+ else:
+ node.setAttribute('value', request[var_name])
+
+ # content
+ content_data_list = get_content_data_internal(session, bd_xml)
+ current_content_id = content_data_list[0]['id']
+ selected_content_id = request['content_id']
+ selected_content = None
+ selected_content_data = None
+ for c_data in content_data_list:
+ if c_data['id'] == selected_content_id:
+ selected_content_data = c_data
+ selected_content = c_data['xml']#.cloneNode(True)
+
+ # update selected_content props
+ props_xml = None
+ for node in selected_content.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == PROPS_TAG:
+ props_xml = node
+ for node in props_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == VARIABLE_TAG:
+ if node.getAttribute('mutable') == 'true':
+ var_name = node.getAttribute('name')
+ req_name = 'content_variable_%s_%s' % (selected_content_id, var_name)
+ if req_name in request:
+ if selected_content_data['props'][req_name]['type'] == 'int':
+ if selected_content_data['props'][req_name]['units'] != 'bytes':
+ val = int(request[req_name])
+ step = int(selected_content_data['props'][req_name]['validation']['step'])
+ val = (val / step) * step
+ else:
+ dummy, units = bytes_to_value_prefunits(self,
+ selected_content_data['props'][req_name]['value'])
+ min_val = int(selected_content_data['props'][req_name]['validation']['min'])
+ max_val = int(selected_content_data['props'][req_name]['validation']['max'])
+ step = int(selected_content_data['props'][req_name]['validation']['step'])
+ val_units = float(request[req_name])
+ val = int(val_units * get_units_multiplier(units))
+ val = (val / step) * step
+ if val < min_val:
+ val = min_val
+ if val > max_val:
+ val = max_val
+ node.setAttribute('value', str(val))
+ else:
+ node.setAttribute('value', request[req_name])
+
+ if current_content_id == selected_content_id:
+ # no change of content
+ # replace content_xml
+ for node in bd_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == 'content':
+ bd_xml.removeChild(node)
+ bd_xml.appendChild(selected_content)
+ break
+ else:
+ # content changed
+ # place it under <new_content>
+ for node in bd_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == 'content':
+ for node2 in node.childNodes:
+ if node2.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node2.nodeName == 'new_content':
+ node2.appendChild(selected_content)
+ break
+ #return bd_xml.toprettyxml()
+ doc = minidom.Document()
+ batch = doc.createElement("batch")
+ module = doc.createElement("module")
+ module.setAttribute("name", "storage")
+ req = doc.createElement("request")
+ req.setAttribute("API_version", "1.0")
+ req.setAttribute("sequence", "10")
+ f_call = doc.createElement("function_call")
+ f_call.setAttribute('name', 'modify_bd')
+ f_call.appendChild(Variable('bd', bd_xml).export_xml(doc))
+
+ req.appendChild(f_call)
+ module.appendChild(req)
+ batch.appendChild(module)
+
+ res = ricci.process_batch(batch, True)
+ batch_id = res.getAttribute('batch_id')
+
+
+ elif object_type == 'bd_template':
+ path = request[PT_PATH]
+ bd_data = get_bd_data(self, storage_report, mapper_id, path)
+ bd_xml = bd_data['xml']#.cloneNode(True)
+ #return bd_xml.toprettyxml()
+
+ if action_type == 'Apply': # Create
+ # BD props
+ props_xml = None
+ for node in bd_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == PROPS_TAG:
+ props_xml = node
+ for node in props_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == VARIABLE_TAG:
+ if node.getAttribute('mutable') == 'true':
+ var_name = node.getAttribute('name')
+ if var_name in request:
+ if bd_data['props'][var_name]['type'] == 'int':
+ if bd_data['props'][var_name]['units'] != 'bytes':
+ val = int(request[var_name])
+ step = int(bd_data['props'][var_name]['validation']['step'])
+ val = (val / step) * step
+ else:
+ dummy, units = bytes_to_value_prefunits(self,
+ bd_data['props'][var_name]['value'])
+ min_val = int(bd_data['props'][var_name]['validation']['min'])
+ max_val = int(bd_data['props'][var_name]['validation']['max'])
+ step = int(bd_data['props'][var_name]['validation']['step'])
+ val_units = float(request[var_name])
+ val = int(val_units * get_units_multiplier(units))
+ val = (val / step) * step
+ if val < min_val:
+ val = min_val
+ if val > max_val:
+ val = max_val
+ node.setAttribute('value', str(val))
+ else:
+ node.setAttribute('value', request[var_name])
+
+ if path != 'new_snapshot':
+ # content
+ content_data_list = get_content_data_internal(session, bd_xml)
+ current_content_id = content_data_list[0]['id']
+ selected_content_id = request['content_id']
+ selected_content = None
+ selected_content_data = None
+ for c_data in content_data_list:
+ if c_data['id'] == selected_content_id:
+ selected_content_data = c_data
+ selected_content = c_data['xml']#.cloneNode(True)
+
+ # update selected_content props
+ props_xml = None
+ for node in selected_content.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == PROPS_TAG:
+ props_xml = node
+ for node in props_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == VARIABLE_TAG:
+ if node.getAttribute('mutable') == 'true':
+ var_name = node.getAttribute('name')
+ req_name = 'content_variable_%s_%s' % (selected_content_id, var_name)
+ if req_name in request:
+ if selected_content_data['props'][req_name]['type'] == 'int':
+ if selected_content_data['props'][req_name]['units'] != 'bytes':
+ val = int(request[req_name])
+ step = int(selected_content_data['props'][req_name]['validation']['step'])
+ val = (val / step) * step
+ else:
+ dummy, units = bytes_to_value_prefunits(self,
+ selected_content_data['props'][req_name]['value'])
+ min_val = int(selected_content_data['props'][req_name]['validation']['min'])
+ max_val = int(selected_content_data['props'][req_name]['validation']['max'])
+ step = int(selected_content_data['props'][req_name]['validation']['step'])
+ val_units = float(request[req_name])
+ val = int(val_units * get_units_multiplier(units))
+ val = (val / step) * step
+ if val < min_val:
+ val = min_val
+ if val > max_val:
+ val = max_val
+ node.setAttribute('value', str(val))
+ else:
+ node.setAttribute('value', request[req_name])
+
+ if current_content_id == selected_content_id:
+ # no change of content
+ # replace content_xml
+ for node in bd_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == 'content':
+ bd_xml.removeChild(node)
+ bd_xml.appendChild(selected_content)
+ break
+ else:
+ # content changed
+ # place it under <new_content>
+ for node in bd_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == 'content':
+ for node2 in node.childNodes:
+ if node2.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node2.nodeName == 'new_content':
+ node2.appendChild(selected_content)
+ break
+ #return bd_xml.toprettyxml()
+ doc = minidom.Document()
+ batch = doc.createElement("batch")
+ module = doc.createElement("module")
+ module.setAttribute("name", "storage")
+ req = doc.createElement("request")
+ req.setAttribute("API_version", "1.0")
+ req.setAttribute("sequence", "10")
+ f_call = doc.createElement("function_call")
+ f_call.setAttribute('name', 'create_bd')
+ f_call.appendChild(Variable('bd', bd_xml).export_xml(doc))
+
+ req.appendChild(f_call)
+ module.appendChild(req)
+ batch.appendChild(module)
+
+ res = ricci.process_batch(batch, True)
+ batch_id = res.getAttribute('batch_id')
+
+ elif object_type == 'mapper':
+ mapper_data = get_mapper_data(self, storage_report, mapper_id)
+ mapper_xml = mapper_data['xml']#.cloneNode(True)
+ #return mapper_xml.toprettyxml()
+
+ if action_type == 'Remove':
+ doc = minidom.Document()
+ batch = doc.createElement("batch")
+ module = doc.createElement("module")
+ module.setAttribute("name", "storage")
+ req = doc.createElement("request")
+ req.setAttribute("API_version", "1.0")
+ req.setAttribute("sequence", "10")
+ f_call = doc.createElement("function_call")
+ f_call.setAttribute('name', 'remove_mapper')
+ f_call.appendChild(Variable('mapper', mapper_xml).export_xml(doc))
+
+ req.appendChild(f_call)
+ module.appendChild(req)
+ batch.appendChild(module)
+
+ res = ricci.process_batch(batch, True)
+ batch_id = res.getAttribute('batch_id')
+
+
+ elif action_type == 'Apply':
+ # props
+ props_xml = None
+ for node in mapper_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == PROPS_TAG:
+ props_xml = node
+ for node in props_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == VARIABLE_TAG:
+ if node.getAttribute('mutable') == 'true':
+ var_name = node.getAttribute('name')
+ if var_name in request:
+ if mapper_data['props'][var_name]['type'] == 'int':
+ if mapper_data['props'][var_name]['units'] != 'bytes':
+ val = int(request[var_name])
+ step = int(mapper_data['props'][var_name]['validation']['step'])
+ val = (val / step) * step
+ else:
+ dummy, units = bytes_to_value_prefunits(self,
+ mapper_data['props'][var_name]['value'])
+ min_val = int(mapper_data['props'][var_name]['validation']['min'])
+ max_val = int(mapper_data['props'][var_name]['validation']['max'])
+ step = int(mapper_data['props'][var_name]['validation']['step'])
+ val_units = float(request[var_name])
+ val = int(val_units * get_units_multiplier(units))
+ val = (val / step) * step
+ if val < min_val:
+ val = min_val
+ if val > max_val:
+ val = max_val
+ node.setAttribute('value', str(val))
+ else:
+ node.setAttribute('value', request[var_name])
+ #return mapper_xml.toprettyxml()
+ doc = minidom.Document()
+ batch = doc.createElement("batch")
+ module = doc.createElement("module")
+ module.setAttribute("name", "storage")
+ req = doc.createElement("request")
+ req.setAttribute("API_version", "1.0")
+ req.setAttribute("sequence", "10")
+ f_call = doc.createElement("function_call")
+ f_call.setAttribute('name', 'modify_mapper')
+ f_call.appendChild(Variable('mapper', mapper_xml).export_xml(doc))
+
+ req.appendChild(f_call)
+ module.appendChild(req)
+ batch.appendChild(module)
+
+ res = ricci.process_batch(batch, True)
+ batch_id = res.getAttribute('batch_id')
+
+
+
+ elif object_type == 'mapper_template':
+ mapper_data = get_mapper_template_data(self, storage_report, mapper_type)
+ mapper_xml = mapper_data['xml']#.cloneNode(True)
+ #return mapper_xml.toprettyxml()
+
+ if action_type == 'Apply':
+ # props
+ props_xml = None
+ for node in mapper_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == PROPS_TAG:
+ props_xml = node
+ for node in props_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == VARIABLE_TAG:
+ if node.getAttribute('mutable') == 'true':
+ var_name = node.getAttribute('name')
+ if request.has_key(var_name):
+ if mapper_data['props'][var_name]['type'] == 'int':
+ if mapper_data['props'][var_name]['units'] != 'bytes':
+ val = int(request[var_name])
+ step = int(mapper_data['props'][var_name]['validation']['step'])
+ val = (val / step) * step
+ else:
+ dummy, units = bytes_to_value_prefunits(self,
+ mapper_data['props'][var_name]['value'])
+ min_val = int(mapper_data['props'][var_name]['validation']['min'])
+ max_val = int(mapper_data['props'][var_name]['validation']['max'])
+ step = int(mapper_data['props'][var_name]['validation']['step'])
+ val_units = float(request[var_name])
+ val = int(val_units * get_units_multiplier(units))
+ val = (val / step) * step
+ if val < min_val:
+ val = min_val
+ if val > max_val:
+ val = max_val
+ node.setAttribute('value', str(val))
+ else:
+ node.setAttribute('value', request[var_name])
+
+ # find sources
+ for v in request.keys():
+ if v.find('source_bd_') == 0:
+ if request[v] == 'on':
+ path = v[len('source_bd_'):]
+ for s_xml in storage_report.get_new_sources(mapper_xml):
+ if s_xml.getAttribute('path') == path:
+ for node in mapper_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == MAPPER_SOURCES_TAG:
+ node.appendChild(s_xml)#.cloneNode(True))
+ #return mapper_xml.toprettyxml()
+ doc = minidom.Document()
+ batch = doc.createElement("batch")
+ module = doc.createElement("module")
+ module.setAttribute("name", "storage")
+ req = doc.createElement("request")
+ req.setAttribute("API_version", "1.0")
+ req.setAttribute("sequence", "10")
+ f_call = doc.createElement("function_call")
+ f_call.setAttribute('name', 'create_mapper')
+# f_call.appendChild(Variable('mapper', mapper_xml.cloneNode(True)).export_xml(doc))
+ f_call.appendChild(Variable('mapper', mapper_xml).export_xml(doc))
+
+ req.appendChild(f_call)
+ module.appendChild(req)
+ batch.appendChild(module)
+
+ res = ricci.process_batch(batch, True)
+ batch_id = res.getAttribute('batch_id')
+
+
+
+
+ elif object_type == 'add_sources':
+ mapper_data = get_mapper_data(self, storage_report, mapper_id)
+ mapper_xml = mapper_data['xml']#.cloneNode(True)
+ new_sources = []
+ #return mapper_xml.toprettyxml()
+
+ if action_type == 'Apply':
+ # find sources
+ for v in request.keys():
+ if v.find('source_bd_') == 0:
+ if request[v] == 'on':
+ path = v[len('source_bd_'):]
+ for ns in mapper_data['new_sources']:
+ if ns['path'] == path:
+ new_sources.append(ns['xml'])#.cloneNode(True))
+ #return mapper_xml.toprettyxml()
+ doc = minidom.Document()
+ batch = doc.createElement("batch")
+ module = doc.createElement("module")
+ module.setAttribute("name", "storage")
+ req = doc.createElement("request")
+ req.setAttribute("API_version", "1.0")
+ req.setAttribute("sequence", "11")
+ f_call = doc.createElement("function_call")
+ f_call.setAttribute('name', 'add_mapper_sources')
+ f_call.appendChild(Variable('mapper_type', mapper_type).export_xml(doc))
+ f_call.appendChild(Variable('mapper_id', mapper_id).export_xml(doc))
+ f_call.appendChild(Variable('mapper_state_ind', mapper_xml.getAttribute('state_ind')).export_xml(doc))
+ f_call.appendChild(VariableList('bds', new_sources, [], VARIABLE_TYPE_LIST_XML).export_xml(doc))
+
+ req.appendChild(f_call)
+ module.appendChild(req)
+ batch.appendChild(module)
+
+ res = ricci.process_batch(batch, True)
+ batch_id = res.getAttribute('batch_id')
+
+
+ if batch_id == '':
+ raise Exception, 'unsupported function'
+ else:
+ invalidate_storage_report(request.SESSION, storagename)
+ return batch_id
+
+
+def get_storage_batch_result(self, storagename, ricci, index_html_URL, batch_id):
+ error = True # ricci reported failure or no ricci
+ completed = False # no batch, or batch done (defined if no error)
+ url = index_html_URL # redirect URL
+ msg = 'Unknown error occured'
+
+ if ricci is None:
+ # ricci down
+ error = True
+ url = url
+ msg = 'Unable to contact %s' % storagename
+ else:
+ batch = 'no batch'
+ try:
+ batch = ricci.batch_report(batch_id)
+ except:
+ pass
+ if batch == 'no batch':
+ error = True
+ url = url
+ msg = 'Ricci on %s responded with error. No detailed info available.' % storagename
+ elif batch is None:
+ # no such batch
+ error = False
+ completed = True
+ url = '%s?%s=%s&%s=%s' \
+ % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
+ msg = 'No such batch'
+ else:
+ DEFAULT_ERROR = 'extract_module_status() failed'
+ code, err_msg = DEFAULT_ERROR, ''
+ try:
+ code, err_msg = extract_module_status(batch, 1)
+ except:
+ pass
+ if code == DEFAULT_ERROR:
+ error = True
+ url = '%s?%s=%s&%s=%s' \
+ % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
+ msg = 'Ricci on %s sent a malformed response' % storagename
+ elif code == -101 or code == -102:
+ # in progress
+ error = False
+ completed = False
+ msg = 'Task still in progress'
+ elif code == -103:
+ # module removed from scheduler
+ error = True
+ url = '%s?%s=%s&%s=%s' \
+ % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
+ msg = 'Ricci on %s removed request from scheduler. File bug report against ricci.' % storagename
+ elif code == -104:
+ # module failure
+ error = True
+ url = '%s?%s=%s&%s=%s' \
+ % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
+ msg = 'Ricci on %s failed to execute storage module; reinstall it.' % storagename
+ elif code == -2:
+ # API error
+ error = True
+ url = '%s?%s=%s&%s=%s' \
+ % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
+ msg = 'Luci server used invalid API to communicate with %s. File a bug report against luci.' % storagename
+ elif code == -1:
+ # undefined error
+ error = True
+ url = '%s?%s=%s&%s=%s' \
+ % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
+ msg = 'Reason for failure (as reported by %s): %s' % (storagename, err_msg)
+ elif code == 0:
+ # no error
+ error = False
+ completed = True
+ # TODO: implement proper redirect
+ url = get_commit_redirect(url, storagename, batch)
+ msg = 'Done successfully'
+ elif code == 1:
+ # mid-air
+ error = True
+ url = '%s?%s=%s&%s=%s' \
+ % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
+ msg = 'Mid-Air collision (storage on %s has changed since last probe).' % storagename
+ elif code == 2:
+ # validation error
+ error = True
+ url = '%s?%s=%s&%s=%s' \
+ % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
+ msg = 'Validation error. File bug report against Luci.'
+ elif code == 3:
+ # unmount error
+ error = True
+ url = '%s?%s=%s&%s=%s' \
+ % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
+ msg = 'Unmount failure: %s' % err_msg
+ elif code == 4:
+ # clvmd error
+ error = True
+ url = '%s?%s=%s&%s=%s' \
+ % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
+ msg = 'clvmd (clustered LVM daemon) is not running on %s' % storagename
+ elif code == 5:
+ # not quorate
+ error = True
+ url = '%s?%s=%s&%s=%s' \
+ % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
+ msg = 'Cluster quorum is required, but cluster is not quorate. Start cluster, and try again.'
+ elif code == 6:
+ # LVM cluster locking not enabled
+ error = True
+ url = '%s?%s=%s&%s=%s' \
+ % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
+ msg = 'LVM cluster locking is not enabled on %s' % storagename
+ elif code == 7:
+ # cluster not running
+ error = True
+ url = '%s?%s=%s&%s=%s' \
+ % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
+ msg = 'Cluster infrastructure is not running on %s' % storagename
+ elif code > 8:
+ error = True
+ url = '%s?%s=%s&%s=%s' \
+ % (index_html_URL, STONAME, storagename, PAGETYPE, STORAGE)
+ msg = err_msg
+
+ return {
+ 'error': error,
+ 'completed': completed,
+ 'redirect_url': url,
+ 'msg': msg
+ }
######### internal functions (not to be exposed) ##############
+def get_commit_redirect(main_url, storagename, batch_xml):
+ module_r = None
+ for node in batch_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == 'module':
+ module_r = node
+ if module_r is None:
+ raise Exception, 'missing <module/> in <batch/>'
+ resp_r = None
+ for node in module_r.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == RESPONSE_TAG:
+ resp_r = node
+ if resp_r is None:
+ raise Exception, 'missing <response/> in <module/>'
+ fr_r = None
+ for node in resp_r.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == FUNC_RESP_TAG:
+ fr_r = node
+ if fr_r is None:
+ raise Exception, 'missing <function_response/> in <response/>'
+ rvars = {}
+ for node in fr_r.childNodes:
+ try:
+ var = parse_variable(node)
+ rvars[var.get_name()] = var
+ except:
+ pass
+
+ mapper_id = ''
+ mapper_type = ''
+ bd_path = ''
+ if 'mapper' in rvars:
+ mapper = rvars['mapper'].get_value()
+ mapper_type = mapper.getAttribute('mapper_type')
+ mapper_id = mapper.getAttribute('mapper_id')
+ if 'bd' in rvars:
+ bd = rvars['bd'].get_value()
+ bd_path = bd.getAttribute('path')
+ mapper_type = bd.getAttribute('mapper_type')
+ mapper_id = bd.getAttribute('mapper_id')
+
+ url_list = list()
+ url_list.append('%s?%s=%s' % (main_url, STONAME, storagename))
+ if mapper_type != '':
+ url_list.append('&%s=%s' % (PT_MAPPER_TYPE, mapper_type))
+ if mapper_id != '':
+ url_list.append('&%s=%s' % (PT_MAPPER_ID, mapper_id))
+ if bd_path != '':
+ url_list.append('&%s=%s' % (PT_PATH, bd_path))
+
+ if mapper_type == '':
+ url_list.append('&%s=%s' % (PAGETYPE, STORAGE))
+ elif bd_path != '':
+ url_list.append('&%s=%s' % (PAGETYPE, VIEW_BD))
+ else:
+ url_list.append('&%s=%s' % (PAGETYPE, VIEW_MAPPER))
-
-def get_commit_redirect(main_url,
- storagename,
- batch_xml):
- module_r = None
- for node in batch_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == 'module':
- module_r = node
- if module_r is None:
- raise Exception, 'missing <module/> in <batch/>'
- resp_r = None
- for node in module_r.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == RESPONSE_TAG:
- resp_r = node
- if resp_r is None:
- raise Exception, 'missing <response/> in <module/>'
- fr_r = None
- for node in resp_r.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == FUNC_RESP_TAG:
- fr_r = node
- if fr_r is None:
- raise Exception, 'missing <function_response/> in <response/>'
- rvars = {}
- for node in fr_r.childNodes:
- try:
- var = parse_variable(node)
- rvars[var.get_name()] = var
- except:
- pass
-
-
- mapper_id = ''
- mapper_type = ''
- bd_path = ''
- if 'mapper' in rvars:
- mapper = rvars['mapper'].get_value()
- mapper_type = mapper.getAttribute('mapper_type')
- mapper_id = mapper.getAttribute('mapper_id')
- if 'bd' in rvars:
- bd = rvars['bd'].get_value()
- bd_path = bd.getAttribute('path')
- mapper_type = bd.getAttribute('mapper_type')
- mapper_id = bd.getAttribute('mapper_id')
-
- url_list = list()
- url_list.append('%s?%s=%s' % (main_url, STONAME, storagename))
- if mapper_type != '':
- url_list.append('&%s=%s' % (PT_MAPPER_TYPE, mapper_type))
- if mapper_id != '':
- url_list.append('&%s=%s' % (PT_MAPPER_ID, mapper_id))
- if bd_path != '':
- url_list.append('&%s=%s' % (PT_PATH, bd_path))
-
- if mapper_type == '':
- url_list.append('&%s=%s' % (PAGETYPE, STORAGE))
- elif bd_path != '':
- url_list.append('&%s=%s' % (PAGETYPE, VIEW_BD))
- else:
- url_list.append('&%s=%s' % (PAGETYPE, VIEW_MAPPER))
-
- return ''.join(url_list)
+ return ''.join(url_list)
def get_bd_data_internal(session, bd_xml, mapper_xml):
- data = {}
+ data = {}
- removable, props = get_props_data_internal(session, bd_xml)
+ removable, props = get_props_data_internal(session, bd_xml)
- path = bd_xml.getAttribute('path')
- mapper_type = bd_xml.getAttribute('mapper_type')
- mapper_id = bd_xml.getAttribute('mapper_id')
- contents = get_content_data_internal(session, bd_xml)
-
- pretty_mapper_type, pretty_type, dummy2 = get_pretty_mapper_info(mapper_type)
- pretty_name = path.replace('/dev/','')
- dummy1, icon_name, dummy2 = get_mapper_icons(mapper_type)
- color = 'black'
-
- size_in_units, units = bytes_to_value_units(props['size']['value'])
-
- description = None
- if mapper_type == MAPPER_SYS_TYPE:
- if 'scsi_id' in props:
- description = '%s %s, SCSI ID = %s' \
- % (size_in_units, units, props['scsi_id']['value'])
- icon_name = 'icon_bd_scsi.png'
- elif mapper_type == MAPPER_VG_TYPE:
- pretty_name = props['lvname']['value']
- color = '#0192db'
- if props['snapshot']['value'] == 'true':
- icon_name = 'icon_bd_LV_snapshot.png'
- pretty_type = 'Snapshot'
-
- if description is None:
- description = '%s %s' % (size_in_units, units)
-
- if bd_xml.nodeName == BD_TEMPLATE:
- if mapper_type == MAPPER_PT_TYPE:
- path = 'unused_segment_%s_%s' \
- % (props['partition_begin']['value'], props['partition_type']['value'])
- else:
- path = 'unused_segment'
- pretty_type = 'New %s' % pretty_type
- pretty_name = 'Unused Space'
- data['new'] = True
- else:
- data['new'] = False
- if mapper_type == MAPPER_VG_TYPE:
- if props['snapshot']['value'] == 'true':
- if data['new']:
- contents = []
- path = 'new_snapshot'
- pretty_name = ''
-
- data['pretty_mapper_type'] = pretty_mapper_type
- data['pretty_type'] = pretty_type
- data['pretty_name'] = pretty_name
- data['description'] = description
- data['props'] = props
- data['props_ordered'] = get_ordered_props(props)
- data['path'] = path
- data['mapper_type'] = mapper_type
- data['mapper_id'] = mapper_id
- data['contents'] = contents
- data['icon'] = icon_name
- data['color'] = color
- data['xml'] = bd_xml#.cloneNode(True)
-
- actions = []
- if removable:
- action = {'name' : 'Remove',
- 'msg' : 'Are you sure you want to remove %s \\\'%s\\\'?' \
- % (pretty_type, pretty_name),
- 'link' : ''}
- actions.append(action)
- if data['mapper_type'] == MAPPER_VG_TYPE and not data['new']:
- nts = None
- for node in mapper_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == MAPPER_NEW_TARGETS_TAG:
- nts = node
- snap_lv = None
- for node in nts.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == BD_TEMPLATE:
- snap_lv = get_bd_data_internal(session, node, mapper_xml)
-
- if snap_lv is not None and snap_lv['props']['clustered']['value'] != 'true':
- if snap_lv['props']['snapshot']['value'] == 'true':
- origs = snap_lv['props']['snapshot_origin']['value']
- if pretty_name in origs:
- action = {'name' : 'Take Snapshot',
- 'msg' : '',
- 'link' : './?%s=%s&%s=%s&%s=%s&%s=%s' \
- % (PAGETYPE, VIEW_BD, \
- PT_MAPPER_ID, data['mapper_id'], \
- PT_MAPPER_TYPE, data['mapper_type'], \
- PT_PATH, snap_lv['path'])}
- actions.append(action)
- data['actions'] = actions
-
- need_apply_butt = mutable_props(data['props'])
- if need_apply_butt is False:
- if len(data['contents']) > 1:
- need_apply_butt = True
- elif len(data['contents']) == 1:
- need_apply_butt = mutable_props(data['contents'][0]['props'])
- else:
- need_apply_butt = False
- data['need_apply_button'] = need_apply_butt
-
- return data
+ path = bd_xml.getAttribute('path')
+ mapper_type = bd_xml.getAttribute('mapper_type')
+ mapper_id = bd_xml.getAttribute('mapper_id')
+ contents = get_content_data_internal(session, bd_xml)
+
+ pretty_mapper_type, pretty_type, dummy2 = get_pretty_mapper_info(mapper_type)
+ pretty_name = path.replace('/dev/','')
+ dummy1, icon_name, dummy2 = get_mapper_icons(mapper_type)
+ color = 'black'
+
+ size_in_units, units = bytes_to_value_units(props['size']['value'])
+
+ description = None
+ if mapper_type == MAPPER_SYS_TYPE:
+ if 'scsi_id' in props:
+ description = '%s %s, SCSI ID = %s' \
+ % (size_in_units, units, props['scsi_id']['value'])
+ icon_name = 'icon_bd_scsi.png'
+ elif mapper_type == MAPPER_VG_TYPE:
+ pretty_name = props['lvname']['value']
+ color = '#0192db'
+ if props['snapshot']['value'] == 'true':
+ icon_name = 'icon_bd_LV_snapshot.png'
+ pretty_type = 'Snapshot'
+
+ if description is None:
+ description = '%s %s' % (size_in_units, units)
+
+ if bd_xml.nodeName == BD_TEMPLATE:
+ if mapper_type == MAPPER_PT_TYPE:
+ path = 'unused_segment_%s_%s' \
+ % (props['partition_begin']['value'], props['partition_type']['value'])
+ else:
+ path = 'unused_segment'
+ pretty_type = 'New %s' % pretty_type
+ pretty_name = 'Unused Space'
+ data['new'] = True
+ else:
+ data['new'] = False
+ if mapper_type == MAPPER_VG_TYPE:
+ if props['snapshot']['value'] == 'true':
+ if data['new']:
+ contents = []
+ path = 'new_snapshot'
+ pretty_name = ''
+
+ data['pretty_mapper_type'] = pretty_mapper_type
+ data['pretty_type'] = pretty_type
+ data['pretty_name'] = pretty_name
+ data['description'] = description
+ data['props'] = props
+ data['props_ordered'] = get_ordered_props(props)
+ data['path'] = path
+ data['mapper_type'] = mapper_type
+ data['mapper_id'] = mapper_id
+ data['contents'] = contents
+ data['icon'] = icon_name
+ data['color'] = color
+ data['xml'] = bd_xml#.cloneNode(True)
+
+ actions = []
+ if removable:
+ action = {
+ 'name': 'Remove',
+ 'msg': 'Are you sure you want to remove %s \\\'%s\\\'?' \
+ % (pretty_type, pretty_name),
+ 'link': ''
+ }
+ actions.append(action)
+ if data['mapper_type'] == MAPPER_VG_TYPE and not data['new']:
+ nts = None
+ for node in mapper_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == MAPPER_NEW_TARGETS_TAG:
+ nts = node
+ snap_lv = None
+ for node in nts.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == BD_TEMPLATE:
+ snap_lv = get_bd_data_internal(session, node, mapper_xml)
+
+ if snap_lv is not None and snap_lv['props']['clustered']['value'] != 'true':
+ if snap_lv['props']['snapshot']['value'] == 'true':
+ origs = snap_lv['props']['snapshot_origin']['value']
+ if pretty_name in origs:
+ action = {
+ 'name': 'Take Snapshot',
+ 'msg': '',
+ 'link': './?%s=%s&%s=%s&%s=%s&%s=%s' \
+ % (PAGETYPE, VIEW_BD, \
+ PT_MAPPER_ID, data['mapper_id'], \
+ PT_MAPPER_TYPE, data['mapper_type'], \
+ PT_PATH, snap_lv['path'])
+ }
+ actions.append(action)
+ data['actions'] = actions
+
+ need_apply_butt = mutable_props(data['props'])
+ if need_apply_butt is False:
+ if len(data['contents']) > 1:
+ need_apply_butt = True
+ elif len(data['contents']) == 1:
+ need_apply_butt = mutable_props(data['contents'][0]['props'])
+ else:
+ need_apply_butt = False
+ data['need_apply_button'] = need_apply_butt
+ return data
def get_props_data_internal(session, xml_tag):
- data = {}
- removable = False
-
+ data = {}
+ removable = False
- props_xml = None
- for node in xml_tag.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == PROPS_TAG:
- props_xml = node
- var_xmls = {}
- for node in props_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == VARIABLE_TAG:
- var_xmls[node.getAttribute('name')] = node
- removable = False
- for name in var_xmls:
- var = var_xmls[name]
- mutable = var.getAttribute('mutable') == 'true'
- var_type = var.getAttribute('type')
- value = var.getAttribute('value')
-
- d_units = ''
- if name in ['size', 'extent_size', 'block_size', 'size_free', 'partition_begin']:
- d_units = 'bytes'
- if 'percent' in name:
- d_units = '%'
-
- validation_data = {}
- if var_type == VARIABLE_TYPE_INT:
- d_type = 'int'
- d_value = value
- min_val = var.getAttribute('min')
- max_val = var.getAttribute('max')
- step = var.getAttribute('step')
- validation_data['min'] = str(min_val)
- validation_data['max'] = str(max_val)
- validation_data['step'] = str(step)
- elif var_type == VARIABLE_TYPE_STRING:
- d_type = 'text'
- d_value = value
- validation_data['min_length'] = var.getAttribute('min_length')
- validation_data['max_length'] = var.getAttribute('max_length')
- validation_data['illegal_chars'] = var.getAttribute('illegal_chars').replace('\'', '\\\'').replace('<', '<').replace('>', '>').replace('"', '\\\"').replace('&', '&')
- validation_data['reserved_words'] = var.getAttribute('reserved_words')
- elif var_type == VARIABLE_TYPE_INT_SEL or var_type == VARIABLE_TYPE_STRING_SEL:
- d_type = 'select'
- d_value = [value]
- for node in var.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == VARIABLE_TYPE_LISTENTRY:
- val = node.getAttribute('value')
- if val not in d_value:
- d_value.append(val)
- elif var_type == VARIABLE_TYPE_BOOL:
- d_type = 'select'
- d_value = [value]
- if value == 'true':
- d_value.append('false')
- else:
- d_value.append('true')
- elif var_type == VARIABLE_TYPE_LIST_INT or var_type == VARIABLE_TYPE_LIST_STR:
- d_type = 'label'
- d_value = ''
- d_val_list = list()
- for node in var.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == VARIABLE_TYPE_LISTENTRY:
- d_val_list.append(node.getAttribute('value'))
- d_val_list.append(', ')
- d_value = ''.join(d_val_list)
- if d_value != '':
- d_value = d_value[:len(d_value)-2]
- elif var_type == 'hidden':
- d_type = 'hidden'
- d_value = str(value)
- else:
- d_type = 'label'
- d_value = value
-
- if not mutable and d_type != 'label' and d_type != 'hidden':
- d_type = 'label'
- d_value = str(value)
-
- hidden = False
- if var_type == 'hidden' or name in ['partition_begin', 'snapshot']:
- hidden = True
-
- if name == 'removable':
- removable = value == 'true'
- elif name == 'path':
- pass
- else:
- data[name] = {'name' : name,
- 'pretty_name' : get_pretty_prop_name(name),
- 'type' : d_type,
- 'value' : d_value,
- 'units' : d_units,
- 'validation' : validation_data,
- 'hidden' : hidden}
+ props_xml = None
+ for node in xml_tag.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == PROPS_TAG:
+ props_xml = node
+
+ var_xmls = {}
+ for node in props_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == VARIABLE_TAG:
+ var_xmls[node.getAttribute('name')] = node
+
+ removable = False
+ for name in var_xmls:
+ var = var_xmls[name]
+ mutable = var.getAttribute('mutable') == 'true'
+ var_type = var.getAttribute('type')
+ value = var.getAttribute('value')
+
+ d_units = ''
+ if name in ['size', 'extent_size', 'block_size', 'size_free', 'partition_begin']:
+ d_units = 'bytes'
+ if 'percent' in name:
+ d_units = '%'
+
+ validation_data = {}
+ if var_type == VARIABLE_TYPE_INT:
+ d_type = 'int'
+ d_value = value
+ min_val = var.getAttribute('min')
+ max_val = var.getAttribute('max')
+ step = var.getAttribute('step')
+ validation_data['min'] = str(min_val)
+ validation_data['max'] = str(max_val)
+ validation_data['step'] = str(step)
+ elif var_type == VARIABLE_TYPE_STRING:
+ d_type = 'text'
+ d_value = value
+ validation_data['min_length'] = var.getAttribute('min_length')
+ validation_data['max_length'] = var.getAttribute('max_length')
+ validation_data['illegal_chars'] = var.getAttribute('illegal_chars').replace('\'', '\\\'').replace('<', '<').replace('>', '>').replace('"', '\\\"').replace('&', '&')
+ validation_data['reserved_words'] = var.getAttribute('reserved_words')
+ elif var_type == VARIABLE_TYPE_INT_SEL or var_type == VARIABLE_TYPE_STRING_SEL:
+ d_type = 'select'
+ d_value = [value]
+ for node in var.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == VARIABLE_TYPE_LISTENTRY:
+ val = node.getAttribute('value')
+ if val not in d_value:
+ d_value.append(val)
+ elif var_type == VARIABLE_TYPE_BOOL:
+ d_type = 'select'
+ d_value = [value]
+ if value == 'true':
+ d_value.append('false')
+ else:
+ d_value.append('true')
+ elif var_type == VARIABLE_TYPE_LIST_INT or var_type == VARIABLE_TYPE_LIST_STR:
+ d_type = 'label'
+ d_value = ''
+ d_val_list = list()
+ for node in var.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == VARIABLE_TYPE_LISTENTRY:
+ d_val_list.append(node.getAttribute('value'))
+ d_val_list.append(', ')
+ d_value = ''.join(d_val_list)
+ if d_value != '':
+ d_value = d_value[:len(d_value)-2]
+ elif var_type == 'hidden':
+ d_type = 'hidden'
+ d_value = str(value)
+ else:
+ d_type = 'label'
+ d_value = value
+
+ if not mutable and d_type != 'label' and d_type != 'hidden':
+ d_type = 'label'
+ d_value = str(value)
+
+ hidden = False
+ if var_type == 'hidden' or name in ['partition_begin', 'snapshot']:
+ hidden = True
+
+ if name == 'removable':
+ removable = value == 'true'
+ elif name == 'path':
+ pass
+ else:
+ data[name] = {
+ 'name': name,
+ 'pretty_name': get_pretty_prop_name(name),
+ 'type': d_type,
+ 'value': d_value,
+ 'units': d_units,
+ 'validation': validation_data,
+ 'hidden': hidden
+ }
- return (removable, data)
+ return (removable, data)
def get_ordered_props(props):
- names = []
- sizes = []
- mounts = []
- min_max = []
- uuids = []
- rest = []
- for prop_name in props:
- prop = props[prop_name]
- # names
- if 'name' in prop_name or 'label' in prop_name or 'vendor' == prop_name or 'model' == prop_name:
- names.append(prop)
- # sizes
- elif 'size' in prop_name or 'extents' in prop_name or 'percent' in prop_name:
- sizes.append(prop)
- # mounts
- elif 'mount' in prop_name or 'fstab' in prop_name:
- mounts.append(prop)
- # min_max
- elif 'min' in prop_name or 'max' in prop_name:
- min_max.append(prop)
- elif 'uuid' in prop_name:
- uuids.append(prop)
- else:
- rest.append(prop)
-
- ordered = []
- for prop in names:
- ordered.append(prop)
- for prop in sizes:
- ordered.append(prop)
- for prop in mounts:
- ordered.append(prop)
- for prop in min_max:
- ordered.append(prop)
- for prop in rest:
- ordered.append(prop)
- for prop in uuids:
- ordered.append(prop)
- return ordered
+ names = []
+ sizes = []
+ mounts = []
+ min_max = []
+ uuids = []
+ rest = []
+
+ for prop_name in props:
+ prop = props[prop_name]
+ # names
+ if 'name' in prop_name or 'label' in prop_name or 'vendor' == prop_name or 'model' == prop_name:
+ names.append(prop)
+ # sizes
+ elif 'size' in prop_name or 'extents' in prop_name or 'percent' in prop_name:
+ sizes.append(prop)
+ # mounts
+ elif 'mount' in prop_name or 'fstab' in prop_name:
+ mounts.append(prop)
+ # min_max
+ elif 'min' in prop_name or 'max' in prop_name:
+ min_max.append(prop)
+ elif 'uuid' in prop_name:
+ uuids.append(prop)
+ else:
+ rest.append(prop)
+
+ ordered = []
+ for prop in names:
+ ordered.append(prop)
+ for prop in sizes:
+ ordered.append(prop)
+ for prop in mounts:
+ ordered.append(prop)
+ for prop in min_max:
+ ordered.append(prop)
+ for prop in rest:
+ ordered.append(prop)
+ for prop in uuids:
+ ordered.append(prop)
+ return ordered
def mutable_props(props):
- for name in props:
- prop_type = props[name]['type']
- if prop_type == 'int' or prop_type == 'text' or prop_type == 'select':
- return True
- return False
+ for name in props:
+ prop_type = props[name]['type']
+ if prop_type == 'int' or prop_type == 'text' or prop_type == 'select':
+ return True
+ return False
def get_content_data_internal(session, bd_xml):
- c_xml = None
- for node in bd_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == CONTENT_TYPE:
- c_xml = node
- break
- if c_xml is None:
- return {}
-
- a_xmls = []
- for node in c_xml.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == "available_contents":
- a_conts = node
- for node in a_conts.childNodes:
- if node.nodeType == xml.dom.Node.ELEMENT_NODE:
- if node.nodeName == "content_template":
- a_xmls.append(node)
- break
-
- current = {}
- removable, props = get_props_data_internal(session, c_xml)
- current['props'] = props
- name, content_id = get_content_name_id(c_xml)
- current['name'] = name
- current['id'] = content_id
- current['xml'] = c_xml#.cloneNode(True)
-
- data = [current]
- for a_xml in a_xmls:
- available = {}
- removable, props = get_props_data_internal(session, a_xml)
- available['props'] = props
- name, content_id = get_content_name_id(a_xml)
- available['name'] = name
- available['id'] = content_id
- available['xml'] = a_xml#.cloneNode(True)
-
- data.append(available)
-
- for d in data:
- old_props = d['props']
- new_props = {}
- for name in old_props:
- new_name = 'content_variable_%s_%s' % (d['id'], name)
- new_props[new_name] = old_props[name]
- new_props[new_name]['name'] = new_name
- d['props'] = new_props
- d['props_ordered'] = get_ordered_props(new_props)
- d['is_source'] = False
-
- # content's color and icon
- color = 'black'
- icon_name = ''
- content_type = d['xml'].getAttribute('type')
- if content_type == 'filesystem':
- icon_name = get_fs_icon(d['xml'].getAttribute('fs_type'))
- elif content_type == 'mapper_source':
- mapper_type = d['xml'].getAttribute('mapper_type')
- mapper_id = d['xml'].getAttribute('mapper_id')
- pretty_mapper_type, dummy1, dummy2 = get_pretty_mapper_info(mapper_type)
- dummy1, dummy2, icon_name = get_mapper_icons(mapper_type)
- if mapper_type == MAPPER_VG_TYPE:
- color = '#a43737'
- d['is_source'] = True
- d['mapper_type'] = mapper_type
- d['mapper_id'] = mapper_id
- d['pretty_mapper_type'] = pretty_mapper_type
- elif content_type == 'none':
- pass
- elif content_type == 'hidden':
- pass
+ c_xml = None
+ for node in bd_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == CONTENT_TYPE:
+ c_xml = node
+ break
+ if c_xml is None:
+ return {}
+
+ a_xmls = []
+ for node in c_xml.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == "available_contents":
+ a_conts = node
+ for node in a_conts.childNodes:
+ if node.nodeType == xml.dom.Node.ELEMENT_NODE:
+ if node.nodeName == "content_template":
+ a_xmls.append(node)
+ break
+
+ current = {}
+ removable, props = get_props_data_internal(session, c_xml)
+ current['props'] = props
+ name, content_id = get_content_name_id(c_xml)
+ current['name'] = name
+ current['id'] = content_id
+ current['xml'] = c_xml#.cloneNode(True)
+
+ data = [current]
+ for a_xml in a_xmls:
+ available = {}
+ removable, props = get_props_data_internal(session, a_xml)
+ available['props'] = props
+ name, content_id = get_content_name_id(a_xml)
+ available['name'] = name
+ available['id'] = content_id
+ available['xml'] = a_xml#.cloneNode(True)
+
+ data.append(available)
+
+ for d in data:
+ old_props = d['props']
+ new_props = {}
+ for name in old_props:
+ new_name = 'content_variable_%s_%s' % (d['id'], name)
+ new_props[new_name] = old_props[name]
+ new_props[new_name]['name'] = new_name
+ d['props'] = new_props
+ d['props_ordered'] = get_ordered_props(new_props)
+ d['is_source'] = False
+
+ # content's color and icon
+ color = 'black'
+ icon_name = ''
+ content_type = d['xml'].getAttribute('type')
+ if content_type == 'filesystem':
+ icon_name = get_fs_icon(d['xml'].getAttribute('fs_type'))
+ elif content_type == 'mapper_source':
+ mapper_type = d['xml'].getAttribute('mapper_type')
+ mapper_id = d['xml'].getAttribute('mapper_id')
+ pretty_mapper_type, dummy1, dummy2 = get_pretty_mapper_info(mapper_type)
+ dummy1, dummy2, icon_name = get_mapper_icons(mapper_type)
+ if mapper_type == MAPPER_VG_TYPE:
+ color = '#a43737'
+ d['is_source'] = True
+ d['mapper_type'] = mapper_type
+ d['mapper_id'] = mapper_id
+ d['pretty_mapper_type'] = pretty_mapper_type
+ elif content_type == 'none':
+ pass
+ elif content_type == 'hidden':
+ pass
- d['color'] = color
- d['icon'] = icon_name
+ d['color'] = color
+ d['icon'] = icon_name
- return data
+ return data
def get_content_name_id(c_xml):
- name = 'Unknown type'
- content_id = c_xml.getAttribute('type')
- if content_id == CONTENT_FS_TYPE:
- fs_type = c_xml.getAttribute('fs_type')
- content_id = '%s_%s' % (content_id, fs_type)
- name = get_pretty_fs_name(fs_type)
- elif content_id == CONTENT_NONE_TYPE:
- name = 'Empty'
- elif content_id == CONTENT_MS_TYPE:
- mapper_type = c_xml.getAttribute('mapper_type')
- mapper_id = c_xml.getAttribute('mapper_id')
- content_id = '%s_%s_%s' % (content_id, mapper_type, mapper_id.replace(':', '__colon__'))
- if mapper_type == MAPPER_SYS_TYPE:
- pass
- elif mapper_type == MAPPER_VG_TYPE:
- name = 'Physical Volume'
- elif mapper_type == MAPPER_PT_TYPE:
- name = 'Partition Table'
- elif mapper_type == MAPPER_MDRAID_TYPE:
- name = 'Software RAID Disk'
- elif mapper_type == MAPPER_ATARAID_TYPE:
- name = 'ATA-RAID Disk'
- elif mapper_type == MAPPER_MULTIPATH_TYPE:
- name = 'Multipath\'s Path'
- elif mapper_type == MAPPER_CRYPTO_TYPE:
- name = 'Encrypted Device'
- elif mapper_type == MAPPER_iSCSI_TYPE:
- pass
- else:
- name = 'Source of %s' % mapper_type
- elif content_id == CONTENT_HIDDEN_TYPE:
- name = 'Extended Partition'
- else:
- name = 'Unknown type'
+ name = 'Unknown type'
+ content_id = c_xml.getAttribute('type')
+ if content_id == CONTENT_FS_TYPE:
+ fs_type = c_xml.getAttribute('fs_type')
+ content_id = '%s_%s' % (content_id, fs_type)
+ name = get_pretty_fs_name(fs_type)
+ elif content_id == CONTENT_NONE_TYPE:
+ name = 'Empty'
+ elif content_id == CONTENT_MS_TYPE:
+ mapper_type = c_xml.getAttribute('mapper_type')
+ mapper_id = c_xml.getAttribute('mapper_id')
+ content_id = '%s_%s_%s' % (content_id, mapper_type, mapper_id.replace(':', '__colon__'))
+ if mapper_type == MAPPER_SYS_TYPE:
+ pass
+ elif mapper_type == MAPPER_VG_TYPE:
+ name = 'Physical Volume'
+ elif mapper_type == MAPPER_PT_TYPE:
+ name = 'Partition Table'
+ elif mapper_type == MAPPER_MDRAID_TYPE:
+ name = 'Software RAID Disk'
+ elif mapper_type == MAPPER_ATARAID_TYPE:
+ name = 'ATA-RAID Disk'
+ elif mapper_type == MAPPER_MULTIPATH_TYPE:
+ name = 'Multipath\'s Path'
+ elif mapper_type == MAPPER_CRYPTO_TYPE:
+ name = 'Encrypted Device'
+ elif mapper_type == MAPPER_iSCSI_TYPE:
+ pass
+ else:
+ name = 'Source of %s' % mapper_type
+ elif content_id == CONTENT_HIDDEN_TYPE:
+ name = 'Extended Partition'
+ else:
+ name = 'Unknown type'
- return name, content_id
+ return name, content_id
def group_systems_by_cluster(self, allowed_systems, from_cache=False):
- ss = get_systems_statuses(self, allowed_systems, from_cache)
- clusters = {}
- bad_list = []
- for s in ss:
- if s['authed']:
- cluname = s['cluname']
- if cluname not in clusters:
- clusters[cluname] = []
- clusters[cluname].append(s)
- else:
- bad_list.append(s)
- clu_list = []
- nonclu_list = []
- for cluname in clusters:
- if cluname == '':
- nonclu_list = clusters[cluname]
- else:
- cl = {'name' : cluname,
- 'alias' : clusters[cluname][0]['clualias'],
- 'nodes' : clusters[cluname]}
- clu_list.append(cl)
-
- ret = [nonclu_list, clu_list, bad_list]
-
- return ret
-
-
-
-
-def get_mappings_info(self,
- mapper_data,
- length):
- # highlights
- high_list = {}
-
- # upper cyl
- upper_cyl = {'offset' : 0,
- 'cyls' : [],
- 'highs' : [],
- 'js' : [],
- 'color' : 'blue',
- 'color_css' : '#0192db',
- 'description': mapper_data['pretty_targets_name']}
- if mapper_data['mapper_type'] == MAPPER_PT_TYPE:
- upper_cyl['description'] = 'Physical %s' % upper_cyl['description']
-
- offset = 0
- for t in mapper_data['targets_all']:
- if t['mapper_type'] == MAPPER_PT_TYPE:
- if t['props']['partition_type']['value'] == 'logical':
- continue
- data = {}
- data['bd'] = t
- data['id'] = t['path']
- beg = offset
- end = beg + int(t['props']['size']['value'])
- data['beg'] = beg
- data['end'] = end
- data['color'] = 'blue'
- data['color_css'] = '#0192db'
- if mapper_data['mapper_type'] == MAPPER_PT_TYPE:
- if t['props']['partition_type']['value'] == 'extended' and not t['new']:
- data['color'] = 'black'
- data['color_css'] = 'black'
- upper_cyl['cyls'].append(data)
- offset = end
-
- # scale ranges
- for d in upper_cyl['cyls']:
- d['beg'] = d['beg'] * length / offset
- d['end'] = d['end'] * length / offset - 1
-
- # build highlights
- for d in upper_cyl['cyls']:
- h_id = '%s_selected' % d['id']
- beg = d['beg']
- end = d['end']
- upper_cyl['highs'].append({'beg' : beg,
- 'end' : end,
- 'id' : h_id,
- 'type' : 'select'})
- upper_cyl['js'].append([d['id'],
- [beg, end],
- d['bd']['pretty_name']])
- high_list[d['id']] = [h_id]
-
- # snapshots
- bd = d['bd']
- if bd['mapper_type'] == MAPPER_VG_TYPE and not bd['new']:
- if 'origin' in bd:
- # snapshot
- snap_id = '%s_snapshot' % bd['path']
- upper_cyl['highs'].append({'beg' : beg,
- 'end' : end,
- 'id' : snap_id,
- 'type' : 'snapshot'})
- orig = bd['origin']
- high_list[d['id']].append('%s_origin' % orig['path'])
- high_list[d['id']].append(snap_id)
- if 'snapshots' in bd:
- # origin
- upper_cyl['highs'].append({'beg' : beg,
- 'end' : end,
- 'id' : '%s_origin' % bd['path'],
- 'type' : 'snapshot-origin'})
- for snap in bd['snapshots']:
- high_list[d['id']].append('%s_snapshot' % snap['path'])
-
-
-
- upper_cyl['js'] = str(upper_cyl['js']).replace('L,', ',').replace('L]', ']').replace('u\'', '\'').replace('L]', ']')
-
- # lower cylinder
- lower_cyl = {'offset' : 0,
- 'cyls' : [],
- 'highs' : [],
- 'js' : [],
- 'color' : 'red',
- 'color_css' : '#a43737',
- 'description': mapper_data['pretty_sources_name']}
-
- offset = 0
- for t in mapper_data['sources']:
- data = {}
- data['bd'] = t
- data['id'] = t['path']
- beg = offset
- end = beg + int(t['props']['size']['value'])
- data['beg'] = beg
- data['end'] = end
- data['color'] = 'red'
- data['color_css'] = '#a43737'
- lower_cyl['cyls'].append(data)
- offset = end
-
- if mapper_data['mapper_type'] == MAPPER_PT_TYPE:
- lower_cyl['description'] = 'Logical %s' % mapper_data['pretty_targets_name']
- lower_cyl['cyls'] = []
- lower_cyl['color'] = 'blue'
- lower_cyl['color_css'] = '#0192db'
- lower_cyl['offset'] = 9999999999999999999999999
-
- offset = 0
- for t in mapper_data['targets_all']:
- if t['props']['partition_type']['value'] != 'logical':
- continue
- part_beg = int(t['props']['partition_begin']['value'])
- if part_beg < lower_cyl['offset']:
- lower_cyl['offset'] = part_beg
- data = {}
- data['bd'] = t
- data['id'] = t['path']
- beg = offset
- end = beg + int(t['props']['size']['value'])
- data['beg'] = beg
- data['end'] = end
- data['color'] = 'blue'
- data['color_css'] = '#0192db'
- lower_cyl['cyls'].append(data)
- offset = end
-
-
- # scale ranges
- length_in_bytes = 0
- for t in mapper_data['sources']:
- length_in_bytes += int(t['props']['size']['value'])
- ppb = (length * 1.0) / max(0.00001, length_in_bytes) # pixels per byte
- lower_cyl['offset'] = int(lower_cyl['offset'] * ppb)
- for d in lower_cyl['cyls']:
- d['beg'] = int(d['beg'] * ppb)
- d['end'] = int(d['end'] * ppb - 1)
-
-
-
- # build highlights
- for d in lower_cyl['cyls']:
- h_id = '%s_selected' % d['id']
- beg = d['beg']
- end = d['end']
- lower_cyl['highs'].append({'beg' : beg,
- 'end' : end,
- 'id' : h_id,
- 'type' : 'select'})
- lower_cyl['js'].append([d['id'],
- [beg, end],
- d['bd']['pretty_name']])
- high_list[d['id']] = [h_id]
- lower_cyl['js'] = str(lower_cyl['js']).replace('L,', ',').replace('L]', ']').replace('u\'', '\'').replace('L]', ']')
-
- # transform list of highlights
- high_list_js = [[mapper_data['mapper_id'], []]]
- for hl_id in high_list:
- high_list_js.append([hl_id, high_list[hl_id]])
- high_list_js = str(high_list_js).replace('L,', ',').replace('L]', ']').replace('u\'', '\'').replace('L]', ']')
-
- # put everything together
- ret = {}
- ret['mapper'] = mapper_data
- ret['upper_cyl'] = upper_cyl
- ret['lower_cyl'] = lower_cyl
- ret['js'] = high_list_js
-
- return ret
+ ss = get_systems_statuses(self, allowed_systems, from_cache)
+ clusters = {}
+ bad_list = []
+ for s in ss:
+ if s['authed']:
+ cluname = s['cluname']
+ if cluname not in clusters:
+ clusters[cluname] = []
+ clusters[cluname].append(s)
+ else:
+ bad_list.append(s)
+ clu_list = []
+ nonclu_list = []
+ for cluname in clusters:
+ if cluname == '':
+ nonclu_list = clusters[cluname]
+ else:
+ cl = {
+ 'name': cluname,
+ 'alias': clusters[cluname][0]['clualias'],
+ 'nodes': clusters[cluname]
+ }
+ clu_list.append(cl)
+
+ ret = [ nonclu_list, clu_list, bad_list ]
+ return ret
+
+def get_mappings_info(self, mapper_data, length):
+ # highlights
+ high_list = {}
+
+ # upper cyl
+ upper_cyl = {
+ 'offset': 0,
+ 'cyls': [],
+ 'highs': [],
+ 'js': [],
+ 'color': 'blue',
+ 'color_css': '#0192db',
+ 'description': mapper_data['pretty_targets_name']
+ }
+
+ if mapper_data['mapper_type'] == MAPPER_PT_TYPE:
+ upper_cyl['description'] = 'Physical %s' % upper_cyl['description']
+
+ offset = 0
+ for t in mapper_data['targets_all']:
+ if t['mapper_type'] == MAPPER_PT_TYPE:
+ if t['props']['partition_type']['value'] == 'logical':
+ continue
+
+ data = {}
+ data['bd'] = t
+ data['id'] = t['path']
+ beg = offset
+ end = beg + int(t['props']['size']['value'])
+ data['beg'] = beg
+ data['end'] = end
+ data['color'] = 'blue'
+ data['color_css'] = '#0192db'
+
+ if mapper_data['mapper_type'] == MAPPER_PT_TYPE:
+ if t['props']['partition_type']['value'] == 'extended' and not t['new']:
+ data['color'] = 'black'
+ data['color_css'] = 'black'
+ upper_cyl['cyls'].append(data)
+ offset = end
+
+ # scale ranges
+ for d in upper_cyl['cyls']:
+ d['beg'] = d['beg'] * length / offset
+ d['end'] = d['end'] * length / offset - 1
+
+ # build highlights
+ for d in upper_cyl['cyls']:
+ h_id = '%s_selected' % d['id']
+ beg = d['beg']
+ end = d['end']
+ upper_cyl['highs'].append({
+ 'beg': beg,
+ 'end': end,
+ 'id': h_id,
+ 'type': 'select'
+ })
+
+ upper_cyl['js'].append([d['id'], [beg, end], d['bd']['pretty_name']])
+ high_list[d['id']] = [h_id]
+
+ # snapshots
+ bd = d['bd']
+ if bd['mapper_type'] == MAPPER_VG_TYPE and not bd['new']:
+ if 'origin' in bd:
+ # snapshot
+ snap_id = '%s_snapshot' % bd['path']
+ upper_cyl['highs'].append({
+ 'beg': beg,
+ 'end': end,
+ 'id': snap_id,
+ 'type': 'snapshot'
+ })
+ orig = bd['origin']
+ high_list[d['id']].append('%s_origin' % orig['path'])
+ high_list[d['id']].append(snap_id)
+ if 'snapshots' in bd:
+ # origin
+ upper_cyl['highs'].append({
+ 'beg': beg,
+ 'end': end,
+ 'id': '%s_origin' % bd['path'],
+ 'type': 'snapshot-origin'
+ })
+ for snap in bd['snapshots']:
+ high_list[d['id']].append('%s_snapshot' % snap['path'])
+
+ upper_cyl['js'] = str(upper_cyl['js']).replace('L,', ',').replace('L]', ']').replace('u\'', '\'').replace('L]', ']')
+
+ # lower cylinder
+ lower_cyl = {
+ 'offset': 0,
+ 'cyls': [],
+ 'highs': [],
+ 'js': [],
+ 'color': 'red',
+ 'color_css': '#a43737',
+ 'description': mapper_data['pretty_sources_name']
+ }
+
+ offset = 0
+ for t in mapper_data['sources']:
+ data = {}
+ data['bd'] = t
+ data['id'] = t['path']
+ beg = offset
+ end = beg + int(t['props']['size']['value'])
+ data['beg'] = beg
+ data['end'] = end
+ data['color'] = 'red'
+ data['color_css'] = '#a43737'
+ lower_cyl['cyls'].append(data)
+ offset = end
+
+ if mapper_data['mapper_type'] == MAPPER_PT_TYPE:
+ lower_cyl['description'] = 'Logical %s' % mapper_data['pretty_targets_name']
+ lower_cyl['cyls'] = []
+ lower_cyl['color'] = 'blue'
+ lower_cyl['color_css'] = '#0192db'
+ lower_cyl['offset'] = 9999999999999999999999999
+
+ offset = 0
+ for t in mapper_data['targets_all']:
+ if t['props']['partition_type']['value'] != 'logical':
+ continue
+ part_beg = int(t['props']['partition_begin']['value'])
+ if part_beg < lower_cyl['offset']:
+ lower_cyl['offset'] = part_beg
+ data = {}
+ data['bd'] = t
+ data['id'] = t['path']
+ beg = offset
+ end = beg + int(t['props']['size']['value'])
+ data['beg'] = beg
+ data['end'] = end
+ data['color'] = 'blue'
+ data['color_css'] = '#0192db'
+ lower_cyl['cyls'].append(data)
+ offset = end
+
+
+ # scale ranges
+ length_in_bytes = 0
+ for t in mapper_data['sources']:
+ length_in_bytes += int(t['props']['size']['value'])
+ ppb = (length * 1.0) / max(0.00001, length_in_bytes) # pixels per byte
+ lower_cyl['offset'] = int(lower_cyl['offset'] * ppb)
+ for d in lower_cyl['cyls']:
+ d['beg'] = int(d['beg'] * ppb)
+ d['end'] = int(d['end'] * ppb - 1)
+
+
+
+ # build highlights
+ for d in lower_cyl['cyls']:
+ h_id = '%s_selected' % d['id']
+ beg = d['beg']
+ end = d['end']
+ lower_cyl['highs'].append({
+ 'beg': beg,
+ 'end': end,
+ 'id': h_id,
+ 'type': 'select'
+ })
+ lower_cyl['js'].append([d['id'],
+ [beg, end],
+ d['bd']['pretty_name']])
+ high_list[d['id']] = [h_id]
+ lower_cyl['js'] = str(lower_cyl['js']).replace('L,', ',').replace('L]', ']').replace('u\'', '\'').replace('L]', ']')
+
+ # transform list of highlights
+ high_list_js = [[mapper_data['mapper_id'], []]]
+ for hl_id in high_list:
+ high_list_js.append([hl_id, high_list[hl_id]])
+ high_list_js = str(high_list_js).replace('L,', ',').replace('L]', ']').replace('u\'', '\'').replace('L]', ']')
+
+ # put everything together
+ ret = {}
+ ret['mapper'] = mapper_data
+ ret['upper_cyl'] = upper_cyl
+ ret['lower_cyl'] = lower_cyl
+ ret['js'] = high_list_js
+ return ret
--- conga/luci/site/luci/Extensions/storage_adapters.py 2007/06/27 08:14:13 1.11
+++ conga/luci/site/luci/Extensions/storage_adapters.py 2007/09/24 19:48:34 1.12
@@ -18,362 +18,291 @@
from StorageReport import invalidate_storage_report
def createStorageChooser(self, request, systems):
- dummynode = {}
-
- #First, see if a storage system is chosen, then
- #check that the current user can access that system
- stoname = None
- try:
- stoname = request[STONAME]
- except KeyError, e:
- stoname = ""
-
- try:
- url = request['URL']
- except KeyError, e:
- url = "."
-
- if stoname and request.has_key('reprobe_storage'):
- try:
- invalidate_storage_report(request.SESSION, stoname)
- redirect_url = '%s?%s' % (request['ACTUAL_URL'], request['QUERY_STRING'])
- redirect_url = redirect_url.replace('&reprobe_storage=true', '')
- request.RESPONSE.redirect(redirect_url)
- except:
- pass
-
- try:
- pagetype = request[PAGETYPE]
- except KeyError, e:
- pagetype = "0"
-
- sdata = {}
- sdata['Title'] = "System List"
- sdata['cfg_type'] = "storages"
- sdata['absolute_url'] = "%s?pagetype=%s" % (url, STORAGESYS)
- sdata['Description'] = "Systems available for storage configuration"
- if pagetype == STORAGESYS or pagetype == '0':
- sdata['currentItem'] = True
- else:
- sdata['currentItem'] = False
- if pagetype == STORAGESYS or pagetype == '0':
- sdata['show_children'] = True
- else:
- sdata['show_children'] = False
-
-
- syslist = list()
- if sdata['show_children']:
- #display_clusters = True
- display_clusters = False
- if display_clusters:
- sorted_data = self.group_systems_by_cluster(systems, from_cache=False)
- for sdl in sorted_data[:2]:
- for data in sdl:
- createStorageChooser_inner(url,
- pagetype,
- stoname,
- data,
- syslist)
- else:
- sorted_data = get_systems_statuses(self, systems, from_cache=False)
- for data in sorted_data:
- createStorageChooser_inner(url,
- pagetype,
- stoname,
- data,
- syslist)
- sdata['children'] = syslist
-
- mylist = list()
- mylist.append(sdata)
- #mylist.append(sadd)
- #mylist.append(scfg)
- dummynode['children'] = mylist
-
- return dummynode
-
-
-def createStorageChooser_inner(url,
- pagetype,
- stoname,
- system_data,
- syslist):
- ssys = {}
- if 'nodes' in system_data:
- title = system_data['name']
- if system_data['alias'] != '':
- title = '%s (%s)' % (system_data['alias'], title)
- ssys['Title'] = 'Cluster %s' % title
- ssys['cfg_type'] = "storage"
- ssys['absolute_url'] = '%s?%s=%s&%s=%s' \
- % (url, PAGETYPE, CLUSTER_STORAGE, CLUNAME, system_data['name'])
- ssys['Description'] = "Configure shared storage of cluster %s" % title
- ssys['currentItem'] = False
- ssys['show_children'] = True
- kids = []
- for node in system_data['nodes']:
- createStorageChooser_inner(url,
- pagetype,
- stoname,
- node,
- kids)
- ssys['children'] = kids
- else:
- if system_data['authed'] is False:
- return
- ssys['Title'] = system_data['hostname']
- ssys['cfg_type'] = "storage"
- ssys['absolute_url'] = '%s?%s=%s&%s=%s' \
- % (url, PAGETYPE, STORAGE, STONAME, system_data['hostname'])
- ssys['Description'] = "Configure storage on %s" % system_data['hostname']
-
- if pagetype == STORAGE:
- if stoname == system_data['hostname']:
- ssys['currentItem'] = True
- else:
- ssys['currentItem'] = False
- else:
- ssys['currentItem'] = False
- syslist.append(ssys)
- return
-
+ dummynode = {}
+ # First, see if a storage system is chosen, then
+ # check that the current user can access that system
+ stoname = request.get(STONAME) or ''
+ url = request.get('URL') or '.'
+ pagetype = request.get(PAGETYPE) or '0'
+
+ try:
+ if stoname and request.has_key('reprobe_storage'):
+ invalidate_storage_report(request.SESSION, stoname)
+ redirect_url = '%s?%s' % (request['ACTUAL_URL'], request['QUERY_STRING'])
+ redirect_url = redirect_url.replace('&reprobe_storage=true', '')
+ request.RESPONSE.redirect(redirect_url)
+ except:
+ pass
+
+ sdata = {}
+ sdata['Title'] = 'System List'
+ sdata['cfg_type'] = 'storages'
+ sdata['absolute_url'] = '%s?pagetype=%s' % (url, STORAGESYS)
+ sdata['Description'] = 'Systems available for storage configuration'
+
+ if pagetype == STORAGESYS or pagetype == '0':
+ sdata['show_children'] = True
+ sdata['currentItem'] = True
+ else:
+ sdata['currentItem'] = False
+ sdata['show_children'] = False
+
+ syslist = list()
+ if sdata['show_children']:
+ #display_clusters = True
+ display_clusters = False
+ if display_clusters:
+ sorted_data = self.group_systems_by_cluster(systems, from_cache=False)
+ for sdl in sorted_data[:2]:
+ for data in sdl:
+ createStorageChooser_inner(url, pagetype, stoname, data, syslist)
+ else:
+ sorted_data = get_systems_statuses(self, systems, from_cache=False)
+ for data in sorted_data:
+ createStorageChooser_inner(url, pagetype, stoname, data, syslist)
+ sdata['children'] = syslist
+
+ mylist = list()
+ mylist.append(sdata)
+ #mylist.append(sadd)
+ #mylist.append(scfg)
+ dummynode['children'] = mylist
+
+ return dummynode
+
+def createStorageChooser_inner(url, pagetype, stoname, system_data, syslist):
+ ssys = {}
+ if 'nodes' in system_data:
+ title = system_data['name']
+ if system_data['alias'] != '':
+ title = '%s (%s)' % (system_data['alias'], title)
+ ssys['Title'] = 'Cluster %s' % title
+ ssys['cfg_type'] = 'storage'
+ ssys['absolute_url'] = '%s?%s=%s&%s=%s' \
+ % (url, PAGETYPE, CLUSTER_STORAGE, CLUNAME, system_data['name'])
+ ssys['Description'] = 'Configure shared storage of cluster %s' % title
+ ssys['currentItem'] = False
+ ssys['show_children'] = True
+ kids = []
+ for node in system_data['nodes']:
+ createStorageChooser_inner(url, pagetype, stoname, node, kids)
+ ssys['children'] = kids
+ else:
+ if system_data['authed'] is False:
+ return
+ ssys['Title'] = system_data['hostname']
+ ssys['cfg_type'] = 'storage'
+ ssys['absolute_url'] = '%s?%s=%s&%s=%s' \
+ % (url, PAGETYPE, STORAGE, STONAME, system_data['hostname'])
+ ssys['Description'] = 'Configure storage on %s' % system_data['hostname']
+
+ if pagetype == STORAGE:
+ if stoname == system_data['hostname']:
+ ssys['currentItem'] = True
+ else:
+ ssys['currentItem'] = False
+ else:
+ ssys['currentItem'] = False
+ syslist.append(ssys)
+ return
def create_mapper_subitem(storage_report, request, mapper_list, mapper_templ_list):
+ pagetype_req = request.get(PAGETYPE) or '0'
+ mapper_type_req = request.get(PT_MAPPER_TYPE) or ''
+ mapper_id_req = request.get(PT_MAPPER_ID) or ''
+ path_req = request.get(PT_PATH) or ''
+ url = request.get('URL') or '.'
+ hostname = request.get(STONAME) or ''
+
+ mapper_type = None
+ if len(mapper_list) != 0:
+ mapper_type = mapper_list[0].getAttribute('mapper_type')
+ if len(mapper_templ_list) != 0:
+ mapper_type = mapper_templ_list[0].getAttribute('mapper_type')
+ if mapper_type is None:
+ return None
+
+ buff, dummy1, dummy2 = get_pretty_mapper_info(mapper_type)
+ pretty_names = '%ss' % buff
+ pretty_names_desc = 'Manage %ss' % buff
+ pretty_name_desc = 'Manage %s' % buff
+ pretty_new_name = 'New %s' % buff
+ pretty_new_name_desc = 'Create New %s' % buff
+
+ srs_p = {}
+ srs_p['Title'] = pretty_names
+ srs_p['cfg_type'] = 'nodes'
+ srs_p['absolute_url'] = '%s?%s=%s&%s=%s&%s=%s' \
+ % (url, PAGETYPE, VIEW_MAPPERS, STONAME, hostname, PT_MAPPER_TYPE, mapper_type)
+ srs_p['Description'] = pretty_names_desc
+ if pagetype_req in [ VIEW_MAPPERS, VIEW_MAPPER, ADD_SOURCES, CREATE_MAPPER, VIEW_BD ] and mapper_type_req == mapper_type:
+ srs_p['show_children'] = True
+ else:
+ srs_p['show_children'] = False
+
+ if pagetype_req == VIEW_MAPPERS and mapper_type_req == mapper_type:
+ srs_p['currentItem'] = True
+ else:
+ srs_p['currentItem'] = False
+
+ srs_list = []
+
+ # new mapper
+ if len(mapper_templ_list) != 0:
+ sr = {}
+ sr['Title'] = pretty_new_name
+ sr['cfg_type'] = 'nodes'
+ sr['absolute_url'] = '%s?%s=%s&%s=%s&%s=%s' \
+ % (url, PAGETYPE, CREATE_MAPPER, STONAME, hostname, PT_MAPPER_TYPE, mapper_type)
+ sr['Description'] = pretty_new_name_desc
+ sr['show_children'] = False
+
+ if pagetype_req == CREATE_MAPPER and mapper_type_req == mapper_type:
+ sr['currentItem'] = True
+ else:
+ sr['currentItem'] = False
+
+ srs_list.append(sr)
+
+ # existing mappers
+ for sr_xml in mapper_list:
+ sr_id = sr_xml.getAttribute('mapper_id')
+ srname = sr_id.replace('%s:' % mapper_type, '').replace('/dev/', '')
+
+ if srname == '' and mapper_type == MAPPER_VG_TYPE and sr_id == VG_PREFIX:
+ #srname = 'Uninitialized PVs'
+ continue
+
+ sr = {}
+ sr['Title'] = srname
+ sr['cfg_type'] = 'nodes'
+ sr['absolute_url'] = '%s?%s=%s&%s=%s&%s=%s&%s=%s' \
+ % (url, PAGETYPE, VIEW_MAPPER, STONAME, hostname, PT_MAPPER_TYPE, mapper_type, PT_MAPPER_ID, sr_id)
+ sr['Description'] = pretty_name_desc
+
+ if pagetype_req in [ VIEW_MAPPER, ADD_SOURCES, VIEW_BD ] and mapper_id_req == sr_id:
+ sr['currentItem'] = True
+ else:
+ sr['currentItem'] = False
+ sr['show_children'] = False
+
+ # targets
+ tgts_list = []
+ for tgt_xml in storage_report.get_targets(sr_xml):
+ tg_path = tgt_xml.getAttribute('path')
+ tgname = tg_path
+ #if tg_path != path_req:
+ # continue
+ tg = {}
+ tg['Title'] = tgname
+ tg['cfg_type'] = 'nodes'
+ tg['absolute_url'] = '%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s' \
+ % (url, PAGETYPE, VIEW_BD, STONAME, hostname, PT_MAPPER_TYPE, mapper_type, PT_MAPPER_ID, sr_id, PT_PATH, tg_path)
+ tg['Description'] = tgname
+ tg['show_children'] = False
+
+ if pagetype_req == VIEW_BD and path_req == tg_path:
+ tg['currentItem'] = True
+ else:
+ tg['currentItem'] = False
+ tgts_list.append(tg)
+
+ sr['children'] = tgts_list
+ srs_list.append(sr)
+
+ if len(srs_list) != 0:
+ srs_p['children'] = srs_list
+ return srs_p
- try:
- pagetype_req = request[PAGETYPE]
- except KeyError, e:
- pagetype_req = '0'
- try:
- mapper_type_req = request[PT_MAPPER_TYPE]
- except KeyError, e:
- mapper_type_req = ''
- try:
- mapper_id_req = request[PT_MAPPER_ID]
- except KeyError, e:
- mapper_id_req = ''
- try:
- path_req = request[PT_PATH]
- except KeyError, e:
- path_req = ''
- try:
- url = request['URL']
- except KeyError, e:
- url = "."
- hostname = request[STONAME]
-
-
- mapper_type = None
- if len(mapper_list) != 0:
- mapper_type = mapper_list[0].getAttribute('mapper_type')
- if len(mapper_templ_list) != 0:
- mapper_type = mapper_templ_list[0].getAttribute('mapper_type')
- if mapper_type is None:
- return None
-
-
- buff, dummy1, dummy2 = get_pretty_mapper_info(mapper_type)
- pretty_names = '%ss' % buff
- pretty_names_desc = 'Manage %ss' % buff
- pretty_name_desc = 'Manage %s' % buff
- pretty_new_name = 'New %s' % buff
- pretty_new_name_desc = 'Create New %s' % buff
-
-
- srs_p = {}
- srs_p['Title'] = pretty_names
- srs_p['cfg_type'] = "nodes"
- srs_p['absolute_url'] = '%s?%s=%s&%s=%s&%s=%s' \
- % (url, PAGETYPE, VIEW_MAPPERS, STONAME, hostname, PT_MAPPER_TYPE, mapper_type)
- srs_p['Description'] = pretty_names_desc
- if (pagetype_req == VIEW_MAPPERS or pagetype_req == VIEW_MAPPER or pagetype_req == ADD_SOURCES or pagetype_req == CREATE_MAPPER or pagetype_req == VIEW_BD) and mapper_type_req == mapper_type:
- srs_p['show_children'] = True
- else:
- srs_p['show_children'] = False
- if pagetype_req == VIEW_MAPPERS and mapper_type_req == mapper_type:
- srs_p['currentItem'] = True
- else:
- srs_p['currentItem'] = False
-
- srs_list = []
-
- # new mapper
- if len(mapper_templ_list) != 0:
- sr = {}
- sr['Title'] = pretty_new_name
- sr['cfg_type'] = "nodes"
- sr['absolute_url'] = '%s?%s=%s&%s=%s&%s=%s' \
- % (url, PAGETYPE, CREATE_MAPPER, STONAME, hostname, PT_MAPPER_TYPE, mapper_type)
- sr['Description'] = pretty_new_name_desc
- sr['show_children'] = False
-
- if pagetype_req == CREATE_MAPPER and mapper_type_req == mapper_type:
- sr['currentItem'] = True
- else:
- sr['currentItem'] = False
-
- srs_list.append(sr)
-
- # existing mappers
- for sr_xml in mapper_list:
- sr_id = sr_xml.getAttribute('mapper_id')
- srname = sr_id.replace('%s:' % mapper_type, '').replace('/dev/', '')
-
- if srname == '' and mapper_type == MAPPER_VG_TYPE and sr_id == VG_PREFIX:
- #srname = 'Uninitialized PVs'
- continue
-
- sr = {}
- sr['Title'] = srname
- sr['cfg_type'] = "nodes"
- sr['absolute_url'] = '%s?%s=%s&%s=%s&%s=%s&%s=%s' \
- % (url, PAGETYPE, VIEW_MAPPER, STONAME, hostname, PT_MAPPER_TYPE, mapper_type, PT_MAPPER_ID, sr_id)
- sr['Description'] = pretty_name_desc
-
- if (pagetype_req == VIEW_MAPPER or pagetype_req == ADD_SOURCES or pagetype_req == VIEW_BD) and mapper_id_req == sr_id:
- sr['currentItem'] = True
- else:
- sr['currentItem'] = False
- sr['show_children'] = False
-
- # targets
- tgts_list = []
- for tgt_xml in storage_report.get_targets(sr_xml):
- tg_path = tgt_xml.getAttribute('path')
- tgname = tg_path
- #if tg_path != path_req:
- # continue
- tg = {}
- tg['Title'] = tgname
- tg['cfg_type'] = "nodes"
- tg['absolute_url'] = '%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s' \
- % (url, PAGETYPE, VIEW_BD, STONAME, hostname, PT_MAPPER_TYPE, mapper_type, PT_MAPPER_ID, sr_id, PT_PATH, tg_path)
- tg['Description'] = tgname
- tg['show_children'] = False
-
- if pagetype_req == VIEW_BD and path_req == tg_path:
- tg['currentItem'] = True
- else:
- tg['currentItem'] = False
- tgts_list.append(tg)
-
- sr['children'] = tgts_list
- srs_list.append(sr)
-
- if len(srs_list) != 0:
- srs_p['children'] = srs_list
- return srs_p
- return None
-
-
-
+ return None
def createStorageConfigTree(self, request, storage_report):
- dummynode = {}
- if storage_report is None:
- return dummynode
-
- try:
- pagetype = request[PAGETYPE]
- except KeyError, e:
- pagetype = '0'
- try:
- mapper_type = request[PT_MAPPER_TYPE]
- except KeyError, e:
- mapper_type = ''
- try:
- mapper_id = request[PT_MAPPER_ID]
- except KeyError, e:
- mapper_id = ''
- try:
- path = request[PT_PATH]
- except KeyError, e:
- path = ''
- try:
- url = request['URL']
- except KeyError, e:
- url = "."
- hostname = request[STONAME]
-
-
- ### Hard Drives ###
-
- hds_pretty_name, hd_pretty_name, dummy = get_pretty_mapper_info(MAPPER_SYS_TYPE)
-
- hds_p = {}
- hds_p['Title'] = hds_pretty_name
- hds_p['cfg_type'] = "nodes"
- hds_p['absolute_url'] = '%s?%s=%s&%s=%s&%s=%s&%s=%s' \
- % (url, PAGETYPE, VIEW_BDS, STONAME, hostname, PT_MAPPER_TYPE, MAPPER_SYS_TYPE, PT_MAPPER_ID, SYSTEM_PREFIX)
- hds_p['Description'] = "Manage %s" % hds_pretty_name
- if (pagetype == VIEW_BDS or pagetype == VIEW_BD) and mapper_type == MAPPER_SYS_TYPE:
- hds_p['show_children'] = True
- else:
- hds_p['show_children'] = False
- if pagetype == VIEW_BDS and mapper_type == MAPPER_SYS_TYPE:
- hds_p['currentItem'] = True
- else:
- hds_p['currentItem'] = False
-
- targets_list = storage_report.get_targets(storage_report.get_mapper(SYSTEM_PREFIX))
-
- hds_list = []
- for target in targets_list:
- sys_id = target.getAttribute('mapper_id')
- hd_path = target.getAttribute('path')
-
- hd = {}
- hd['Title'] = hd_path.replace('/dev/', '')
- hd['cfg_type'] = "nodes"
- hd['absolute_url'] = '%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s' \
- % (url, PAGETYPE, VIEW_BD, STONAME, hostname, PT_MAPPER_TYPE, MAPPER_SYS_TYPE, PT_MAPPER_ID, sys_id, PT_PATH, hd_path)
- hd['Description'] = 'Manage %s' % hd_pretty_name
- hd['show_children'] = False
-
- if pagetype == VIEW_BD and mapper_id == sys_id and path == hd_path:
- hd['currentItem'] = True
- else:
- hd['currentItem'] = False
-
- hds_list.append(hd)
-
- hds_p['children'] = hds_list
-
-
-
- ## mappers ##
-
- main_kids = [hds_p]
-
- mappers_dir = storage_report.get_mappers_dir()
- mapper_templs_dir = storage_report.get_mapper_temps_dir()
- glo_dir = {}
- for cur_type in mappers_dir:
- glo_dir[cur_type] = [mappers_dir[cur_type], []]
- for cur_type in mapper_templs_dir:
- if cur_type not in glo_dir:
- glo_dir[cur_type] = [[], mapper_templs_dir[cur_type]]
- else:
- glo_dir[cur_type][1] = mapper_templs_dir[cur_type]
-
- for cur_type in glo_dir:
- if cur_type == MAPPER_SYS_TYPE:
- continue
- item = create_mapper_subitem(storage_report, request, glo_dir[cur_type][0], glo_dir[cur_type][1])
- if item is None:
- continue
- else:
- main_kids.append(item)
- dummynode['children'] = main_kids
- return dummynode
+ dummynode = {}
+ if storage_report is None:
+ return dummynode
+
+ pagetype = request.get(PAGETYPE) or '0'
+ mapper_type = request.get(PT_MAPPER_TYPE) or ''
+ mapper_id = request.get(PT_MAPPER_ID) or ''
+ path = request.get(PT_PATH) or ''
+ url = request.get('URL') or '.'
+ hostname = request.get(STONAME) or ''
+
+ ### Hard Drives ###
+
+ hds_pretty_name, hd_pretty_name, dummy = get_pretty_mapper_info(MAPPER_SYS_TYPE)
+
+ hds_p = {}
+ hds_p['Title'] = hds_pretty_name
+ hds_p['cfg_type'] = 'nodes'
+ hds_p['absolute_url'] = '%s?%s=%s&%s=%s&%s=%s&%s=%s' \
+ % (url, PAGETYPE, VIEW_BDS, STONAME, hostname, PT_MAPPER_TYPE, MAPPER_SYS_TYPE, PT_MAPPER_ID, SYSTEM_PREFIX)
+ hds_p['Description'] = 'Manage %s' % hds_pretty_name
+
+ if (pagetype == VIEW_BDS or pagetype == VIEW_BD) and mapper_type == MAPPER_SYS_TYPE:
+ hds_p['show_children'] = True
+ if pagetype == VIEW_BDS:
+ hds_p['currentItem'] = True
+ else:
+ hds_p['currentItem'] = False
+ else:
+ hds_p['show_children'] = False
+
+ targets_list = storage_report.get_targets(storage_report.get_mapper(SYSTEM_PREFIX))
+
+ hds_list = []
+ for target in targets_list:
+ sys_id = target.getAttribute('mapper_id')
+ hd_path = target.getAttribute('path')
+
+ hd = {}
+ hd['Title'] = hd_path.replace('/dev/', '')
+ hd['cfg_type'] = 'nodes'
+ hd['absolute_url'] = '%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s' \
+ % (url, PAGETYPE, VIEW_BD, STONAME, hostname, PT_MAPPER_TYPE, MAPPER_SYS_TYPE, PT_MAPPER_ID, sys_id, PT_PATH, hd_path)
+ hd['Description'] = 'Manage %s' % hd_pretty_name
+ hd['show_children'] = False
+
+ if pagetype == VIEW_BD and mapper_id == sys_id and path == hd_path:
+ hd['currentItem'] = True
+ else:
+ hd['currentItem'] = False
+
+ hds_list.append(hd)
+
+ hds_p['children'] = hds_list
+
+ ## mappers ##
+
+ main_kids = [ hds_p ]
+
+ mappers_dir = storage_report.get_mappers_dir()
+ mapper_templs_dir = storage_report.get_mapper_temps_dir()
+
+ glo_dir = {}
+ for cur_type in mappers_dir:
+ glo_dir[cur_type] = [ mappers_dir[cur_type], [] ]
+
+ for cur_type in mapper_templs_dir:
+ if cur_type not in glo_dir:
+ glo_dir[cur_type] = [ [], mapper_templs_dir[cur_type] ]
+ else:
+ glo_dir[cur_type][1] = mapper_templs_dir[cur_type]
+
+ for cur_type in glo_dir:
+ if cur_type == MAPPER_SYS_TYPE:
+ continue
+ item = create_mapper_subitem(storage_report, request, glo_dir[cur_type][0], glo_dir[cur_type][1])
+ if item is None:
+ continue
+ else:
+ main_kids.append(item)
+ dummynode['children'] = main_kids
+ return dummynode
def getStorageURL(self, request, hostname):
- # return URL to manage this storage system
- try:
- baseurl = request['URL']
- except KeyError, e:
- baseurl = "."
- return '%s?%s=%s&%s=%s' % (baseurl, PAGETYPE, str(STORAGE), STONAME, hostname)
+ # return URL to manage this storage system
+ baseurl = request.get('URL') or '.'
+ return '%s?%s=%s&%s=%s' % (baseurl, PAGETYPE, str(STORAGE), STONAME, hostname)
next reply other threads:[~2007-09-24 19:48 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-24 19:48 rmccabe [this message]
-- strict thread matches above, loose matches on Subject: below --
2007-06-01 23:18 [Cluster-devel] conga/luci/site/luci/Extensions StorageReport. rmccabe
2006-10-16 19:49 rmccabe
2006-10-09 17:01 kupcevic
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070924194834.23940.qmail@sourceware.org \
--to=rmccabe@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.