From 9a1bd8a5df63c1788ab0a6a8e2af445cda8c0cc1 Mon Sep 17 00:00:00 2001 From: lizhi-rocky Date: Thu, 22 Jul 2010 16:37:23 +0800 Subject: [PATCH] finish ri_data module change some ri_cmd to accompany with ri_data --- design.txt | 3 + python/mine/ri_cmd.py | 30 +++---- python/mine/ri_data.py | 183 ++++++++++++++++++++++++++++++++++----- python/mine/test.py | 20 +++-- python/mine/test_data.py | 14 ++- xml/install.xml | 2 +- xml/install_ng.xml | 14 ++- 7 files changed, 217 insertions(+), 49 deletions(-) diff --git a/design.txt b/design.txt index 5e3a77c..0fcd272 100644 --- a/design.txt +++ b/design.txt @@ -86,6 +86,9 @@ row 4 | quit previous next | Besides these, 2 things I also think about: multi-language support(at least English & Chinese) and inheritance among windows/frames. Can Chinese font be displayed in Curses mode? I'm not sure for now. And, at least supporting English is not a bad choice, I think. As I mentioned in section 3.1.1, most windows are similar, they are 5 rows X 3 columns, and only one row are different. So if I brought in a somehow inheritance way into xml format, it would save a lot of code lines and errors. To the first problem, I will design a data type "Message" in XML who has "key", "English text", and "Chinese text". All messages, such as a text on a button, will be references to "Message" variables, via key(for long message) or just English text(for short text). To the second problem, I first think about to introduce XML elements/attributes "derived_from" and "exception", which are similar to what I have done in building system implementation. But finally, I give up, for it is a little complex. Now it is enough to define a base widget for GUI row 0, 1, 3, and 4. While other widgets just define the content in row 2. + group install: mandatory, yes, no + service start: disable, yes, no + 3.2 Data layer I have inspected those data files generated by current install program. After trying to merge them into one unified data, in xml format, I found it is unbelievable simple! diff --git a/python/mine/ri_cmd.py b/python/mine/ri_cmd.py index c96faa6..00c425a 100644 --- a/python/mine/ri_cmd.py +++ b/python/mine/ri_cmd.py @@ -4,6 +4,8 @@ import ri_tk as display import ri_seq import ri_widget +import ri_data + import re def quit(): @@ -33,27 +35,17 @@ def next(): ri_widget.MessageBox.dict["next"].show() def serial_no_init(): - display.var_dict['serial_no.number'].set(value='123') + display.var_dict['serial_no.number'].set(value=ri_data.SerialNumber.value) def serial_no_quit(): - v = display.var_dict['serial_no.number'].get() + ri_data.SerialNumber.value = display.var_dict['serial_no.number'].get() + def mount_list_init(): ''' initialize mount list ''' - f = file('/proc/partitions', 'r') - pattern = re.compile(r''' -\s*\d+ # major dev number -\s*\d+ # minor dev number -\s*\d+ # blocks -\s*(\w+\d) # name -\s*$''', re.VERBOSE) - s = [] - while True: - l = f.readline() - if not l: - break - res = pattern.search(l) - if res: - s.append(res.groups()[0]) - - display.var_dict['mount.list'].set(value='\n'.join(s)) + l = [] + for m in ri_data.MountPoint.list: +# s = m.device.center(10) + m.directory.center(20) + m.filesystem.center(10) + s = m.device.ljust(10) + m.directory.ljust(20) + m.filesystem.ljust(10) + l.append(s) + display.var_dict['mount.list'].set(value=tuple([str(i) for i in l])) diff --git a/python/mine/ri_data.py b/python/mine/ri_data.py index 8ad4b59..c9222da 100644 --- a/python/mine/ri_data.py +++ b/python/mine/ri_data.py @@ -3,6 +3,16 @@ import re import commands +def to_xml_attr(doc, node, cls, name): + ''' This method is called by to_xml. Its function is to create an attribute, and set its value based on Network data member + doc - xml document + node - xml node + cls - python class/python instance + name - attribute name''' + attr = doc.createAttribute(name) + attr.value = getattr(cls, name) + node.setAttributeNode(attr) + class SerialNumber: ''' serial number ''' value = '' @@ -237,16 +247,6 @@ class Network: for k in node.attributes.keys(): setattr(Network, k, node.attributes[k].value.encode('ascii')) - @staticmethod - def to_xml_attr(doc, node, name): - ''' This method is called by to_xml. Its function is to create an attribute, and set its value based on Network data member - doc - xml document - node - xml node - name - attribute name''' - attr = doc.createAttribute(name) - attr.value = getattr(Network, name) - node.setAttributeNode(attr) - @staticmethod def to_xml(doc, p_node): ''' write Network into xml @@ -254,7 +254,7 @@ doc - xml document instance p_node - xml node (parent node)''' ntwk = doc.createElement('network') for nm in ('hostname', 'configuration', 'ip', 'mask', 'gateway', 'primary_dns', 'secondary_dns', 'domain'): - Network.to_xml_attr(doc, ntwk, nm) + to_xml_attr(doc, ntwk, Network, nm) p_node.appendChild(ntwk) class Group: @@ -276,7 +276,7 @@ r_node - release node ''' for i in r_node.childNodes: if i.nodeType == i.ELEMENT_NODE and i.nodeName == 'including': Group(i.attributes['group'].value, \ - i.attributes['install'].value == 'mandatory' and 'yes' or 'no') + i.attributes['install'].value == 'mandatory' and 'mandatory' or 'no') @staticmethod def handle_group_node(g_node): @@ -291,20 +291,38 @@ g_node - group node ''' if n.attributes['install'].value == 'mandatory': g.mandatory.append(n.attributes['package'].value.encode('ascii')) else: - g.optional.append(n.attributes['package'].value.encode('ascii')) + g.optional.append(n.attributes['package'].value.encode('ascii'), 'no') @staticmethod def init_from_config_xml(node): - ''' init Group instance from config xml + ''' init Group instances from config xml node - root node of config xml''' rls_list = [r for r in node.childNodes if r.nodeType == r.ELEMENT_NODE and r.nodeName == 'release'] grp_list = [g for g in node.childNodes if g.nodeType == g.ELEMENT_NODE and g.nodeName == 'group'] - handle_release_node(rls_list[0]) + Group.handle_release_node(rls_list[0]) for g in grp_list: - handle_group_node(g) + Group.handle_group_node(g) + @staticmethod + def init_from_install_xml(node): + ''' init Group instances from install xml + node - install xml 'groups' node''' + for grp in node.childNodes: + if grp.nodeType == grp.ELEMENT_NODE and grp.nodeName == 'group': + g = Group(grp.attributes['name'].value, grp.attributes['install'].value) + for grp_chld in grp.childNodes: + if grp_chld.nodeType == grp_chld.ELEMENT_NODE: + if grp_chld.nodeName == 'description': + g.description = grp_chld.firstChild.data + elif grp_chld.nodeName == 'mandatory': + g.mandatory.extend([pkg.attributes['name'].value for pkg in grp_chld.childNodes + if pkg.nodeType == pkg.ELEMENT_NODE and pkg.nodeName == 'package']) + elif grp_chld.nodeName == 'optional': + g.optional.extend([(pkg.attributes['name'].value, pkg.attributes['install'].value) for pkg in grp_chld.childNodes + if pkg.nodeType == pkg.ELEMENT_NODE and pkg.nodeName == 'package']) + init_from_xml = init_from_install_xml @staticmethod def to_xml(doc, p_node): ''' write Group instances into xml @@ -332,7 +350,7 @@ p_node - xml node (parent node)''' for m in g.mandatory: pkg = doc.createElement('package') pname_attr = doc.createAttribute('name') - pname_attr = m + pname_attr.value = m pkg.setAttributeNode(pname_attr) mndt.appendChild(pkg) @@ -343,12 +361,137 @@ p_node - xml node (parent node)''' for o in g.optional: pkg = doc.createElement('package') pname_attr = doc.createAttribute('name') - pname_attr = o + pname_attr.value = o[0] pkg.setAttributeNode(pname_attr) pinst_attr = doc.createAttribute('install') - pinst_attr = 'no' + pinst_attr.value = o[1] pkg.setAttributeNode(pinst_attr) optl.appendChild(pkg) grp.appendChild(optl) - grps.append(grp) + grps.appendChild(grp) p_node.appendChild(grps) + +class Service: + ''' service ''' + list = [] + def __init__(self, nm, nb, sc, st, p): + ''' init method +nm - name +nb - number +sc - script +st - start (yes/no/disable) +p - pkg, that includes this service +''' + self.name = nm + self.number = nb + self.script = sc + self.start = st + self.package = p + Service.list.append(self) + + @staticmethod + def init_from_config_xml(root): + ''' init Service instances from config xml + root - root node of config xml ''' + for p in root.childNodes: + if p.nodeType == p.ELEMENT_NODE and p.nodeName == 'package': + for s in p.childNodes: + if s.nodeType == s.ELEMENT_NODE and s.nodeName == 'service': + Service(s.attributes['name'].value, \ + s.attributes['number'].value, \ + s.attributes['script'].value, \ + 'disable', \ + p.attributes['name'].value ) + + @staticmethod + def change_state(): + ''' Based on package information in Group class, change 'start' data member + from 'disable' to 'no', or from 'yes'/'no' to 'disable' ''' + l = [] + for g in Group.dict.values(): + if g.install == 'mandatory' or g.install == 'yes': + l.extend(g.mandatory) + if g.selection == 'all': + l.extend([ n for n, i in g.optional]) + elif g.selection == 'manual': + l.extend([ n for n, i in g.optional if i == 'yes']) + else: # selection is 'none' + pass + + for s in Service.list: + if s.pkg in l: + if s.start == 'disable': + s.start = 'no' + else: + s.start = 'disable' + + @staticmethod + def init_from_install_xml(node): + ''' init Service instances from install xml +node - install xml 'services' node''' + for srv in node.childNodes: + if srv.nodeType == srv.ELEMENT_NODE and srv.nodeName == 'service': + Service(srv.attributes['name'].value, \ + srv.attributes['number'].value, \ + srv.attributes['script'].value, \ + srv.attributes['start'].value, \ + srv.attributes['package'].value) + + init_from_xml = init_from_install_xml + @staticmethod + def to_xml(doc, p_node): + ''' write Service instances into xml +doc - xml document instance +p_node - xml node (parent node)''' + srvs = doc.createElement('services') + for s in Service.list: + srv = doc.createElement('service') + for n in ('name', 'number', 'script', 'start', 'package'): + to_xml_attr(doc, srv, s, n) + srvs.appendChild(srv) + p_node.appendChild(srvs) + +# xml file names +install_xml = '../../xml/install.xml' +config_xml = './config.xml' + +from xml.dom import minidom + +def init_from_xml(): + ''' init all classes in this module based input file (install xml) ''' + xmldoc = minidom.parse(install_xml) + root = xmldoc.firstChild + for n in root.childNodes: + if n.nodeType == n.ELEMENT_NODE: + if n.nodeName == 'serial-number': + SerialNumber.init_from_xml(n) + elif n.nodeName == 'partitions': + Partition.init_from_xml(n) + elif n.nodeName == 'raids': + Raid.init_from_xml(n) + elif n.nodeName == 'mount-points': + MountPoint.init_from_xml(n) + elif n.nodeName == 'network': + Network.init_from_xml(n) + elif n.nodeName == 'groups': + Group.init_from_xml(n) + elif n.nodeName == 'services': + Service.init_from_xml(n) + +def to_xml(): + ''' write internal data into xml file ''' + f = file(install_xml, 'w') + xmldoc = minidom.Document() + root = xmldoc.createElement('install') + xmldoc.appendChild(root) + + SerialNumber.to_xml(xmldoc, root) + Partition.to_xml(xmldoc, root) + Raid.to_xml(xmldoc, root) + MountPoint.to_xml(xmldoc, root) + Network.to_xml(xmldoc, root) + Group.to_xml(xmldoc, root) + Service.to_xml(xmldoc, root) + + PrettyPrint(xmldoc, f) + f.close() diff --git a/python/mine/test.py b/python/mine/test.py index 712e5fd..136ac8b 100644 --- a/python/mine/test.py +++ b/python/mine/test.py @@ -3,13 +3,14 @@ import ri_widget import ri_tk import ri_seq -from xml.dom import minidom +import ri_data import sys import getopt +from xml.dom import minidom def print_usages(): - print 'Usages: %s [-b|--begin] xml_file_name' %sys.argv[0] + print 'Usages: %s [-b|--begin step_name] [interface_xml_file] [install_xml_file]' %sys.argv[0] try: opts, args = getopt.getopt(sys.argv[1:], "b:", ["begin=",]) @@ -22,10 +23,19 @@ for opt, arg in opts: if opt in ('-b', '--begin'): begin_step = arg -if len(args): - xmldoc = minidom.parse(args[0]) +if len(args) == 0: + itf_xml = "../../xml/interface_t.xml" + ins_xml = "../../xml/install.xml" +elif len(args) == 1: + itf_xml = args[0] + ins_xml = "../../xml/install.xml" else: - xmldoc = minidom.parse("../../xml/interface_t.xml") + itf_xml = args[0] + ins_xml = args[1] + +xmldoc = minidom.parse(itf_xml) +ri_data.install_xml = ins_xml +ri_data.init_from_xml() ri_widget.construct(xmldoc.firstChild) ri_seq.construct(xmldoc.firstChild) diff --git a/python/mine/test_data.py b/python/mine/test_data.py index 6f4e405..5f3681f 100644 --- a/python/mine/test_data.py +++ b/python/mine/test_data.py @@ -19,6 +19,10 @@ for e in root.childNodes: MountPoint.init_from_xml(e) elif e.nodeName == 'network': Network.init_from_xml(e) + elif e.nodeName == 'groups': + Group.init_from_install_xml(e) +# elif e.nodeName == 'services': +# Service.init_from_install_xml(e) xmldoc2 = minidom.Document() root2 = xmldoc2.createElement('install') @@ -32,7 +36,13 @@ MountPoint.list=[] MountPoint.init_from_internal() MountPoint.to_xml(xmldoc2, root2) Network.to_xml(xmldoc2, root2) - - +Group.to_xml(xmldoc2, root2) +#Group.to_xml(xmldoc2, root2) +xmldoc_cfg = minidom.parse('./config.xml') +root_cfg = xmldoc_cfg.firstChild +#Group.init_from_config_xml(root_cfg) +#Group.to_xml(xmldoc2, root2) +Service.init_from_config_xml(root_cfg) +Service.to_xml(xmldoc2, root2) PrettyPrint(xmldoc2) diff --git a/xml/install.xml b/xml/install.xml index 9c78e68..ff5658c 100644 --- a/xml/install.xml +++ b/xml/install.xml @@ -40,7 +40,7 @@ - + diff --git a/xml/install_ng.xml b/xml/install_ng.xml index b06db93..c7a2d74 100644 --- a/xml/install_ng.xml +++ b/xml/install_ng.xml @@ -99,7 +99,11 @@ - + + mandatory + yes + no + @@ -157,10 +161,16 @@ + - + + disable + yes + no + +