Files
new_install/python/ri_data.py
2010-08-02 16:19:59 +08:00

545 lines
20 KiB
Python

#!/usr/bin/python
import re
import commands
from xml.dom import minidom
from xml.dom.ext import PrettyPrint
# xml file names
install_xml = '../xml/install.xml'
config_xml = '../xml/config.xml'
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 = ''
@staticmethod
def init_from_xml(node):
''' set value based on xml node '''
SerialNumber.value = node.firstChild.data.encode('ascii')
@staticmethod
def to_xml(doc, p_node):
''' write SerialNumber into xml
doc - xml document instance
p_node - xml node (parent node)'''
sn = doc.createElement('serial-number')
data = doc.createTextNode(SerialNumber.value)
sn.appendChild(data)
p_node.appendChild(sn)
class Partition:
''' disk partition '''
unit=''
list=[]
def __init__(self, dev, st, sz, id):
''' Partition init function '''
self.device = dev
self.start = st
self.size = sz
self.id = id
Partition.list.append(self)
@staticmethod
def init_from_os():
''' create a Partition instance from hardware info'''
# cmd = 'sfdisk -d'
# has problem on raid detection
cmd = 'cat /home/zhi/work/new_install/python/mine/sfdisk.txt'
st, o = commands.getstatusoutput(cmd)
if st:
return
p0 = re.compile(r'unit:\s*(\w+)')
p = re.compile(r'''
\s*(\w+)\s*: # device
\s*start=\s*(\d+)\s*, # start
\s*size=\s*(\d+)\s*, # size
\s*Id=\s*(\d+) # id
''', re.VERBOSE)
for s in o.splitlines():
res0 = p0.search(s)
if res0:
Partition.unit = res0.groups()[0]
res = p.search(s)
if res:
dev, start, size, id = res.groups()
Partition(dev.split('/')[-1], start, size, id)
@staticmethod
def init_from_xml(node):
''' create Partition instances from xml node '''
Partition.unit = node.attributes['unit'].value.encode('ascii')
for p in node.childNodes:
if p.nodeType == node.ELEMENT_NODE and p.nodeName == 'partition':
Partition(p.attributes['device'].value.encode('ascii'),\
p.attributes['start'].value.encode('ascii'), \
p.attributes['size'].value.encode('ascii'), \
p.attributes['id'].value.encode('ascii'))
@staticmethod
def to_xml(doc, p_node):
''' write all Partition instance into xml
doc - xml document instance
p_node - xml node (parent node)'''
pts = doc.createElement("partitions")
unit_attr = doc.createAttribute('unit')
unit_attr.value = Partition.unit
pts.setAttributeNode(unit_attr)
for p in Partition.list:
pt = doc.createElement('partition')
dev_attr = doc.createAttribute('device')
start_attr = doc.createAttribute('start')
size_attr = doc.createAttribute('size')
id_attr = doc.createAttribute('id')
dev_attr.value = p.device
start_attr.value = p.start
size_attr.value = p.size
id_attr.value = p.id
pt.setAttributeNode(dev_attr)
pt.setAttributeNode(start_attr)
pt.setAttributeNode(size_attr)
pt.setAttributeNode(id_attr)
pts.appendChild(pt)
p_node.appendChild(pts)
@staticmethod
def get_size(dev):
for p in Partition.list:
if p.device == dev:
return p.size
class Raid:
''' raid information '''
list = []
def __init__(self, raid_dev, raid_type, raid_size, raw_devs):
''' Raid init function '''
self.raid_device = raid_dev
self.raid_type = raid_type
self.raid_size = raid_size
self.raw_devices = raw_devs
Raid.list.append(self)
@staticmethod
def init_from_os():
#cmd = 'cat /proc/mdstat'
cmd = 'cat /home/zhi/work/new_install/python/mine/raid.txt'
st, o = commands.getstatusoutput(cmd)
if st:
return
dev_p = re.compile(r'''
^(md\d+)\s*: # md device
\s*active\s* # "active"
(\w+)\s* # raid type
''', re.VERBOSE)
for s in o.splitlines():
dev_res = dev_p.split(s)
if len(dev_res)>1: # matched
# dev_res[0] is ''
raid_dev = dev_res[1]
raid_type = dev_res[2]
raw_devs =[]
for ss in dev_res[3].split():
raw_devs.append(ss[:ss.index('[')])
Raid(raid_dev, raid_type, '-1', raw_devs)
@staticmethod
def init_from_xml(node):
''' create Raid instances from xml node '''
for e in node.childNodes:
if e.nodeType == e.ELEMENT_NODE and e.nodeName == 'raid':
raid_dev = e.attributes['raid-device'].value
raid_type = e.attributes['raid-type'].value
raid_size = e.attributes['raid-size'].value
raw_devs = []
for sub_e in e.childNodes:
if sub_e.nodeType == sub_e.ELEMENT_NODE and sub_e.nodeName == 'raw-device':
raw_devs.append(sub_e.firstChild.data.encode('ascii'))
Raid(raid_dev, raid_type, raid_size, raw_devs)
@staticmethod
def to_xml(doc, p_node):
''' write all raid instance into xml
doc - xml document instance
p_node - xml node (parent node) '''
raids = doc.createElement('raids')
for r in Raid.list:
rd = doc.createElement('raid')
rd_dev_attr = doc.createAttribute('raid-device')
rd_dev_attr.value = r.raid_device
rd.setAttributeNode(rd_dev_attr)
rd_type_attr = doc.createAttribute('raid-type')
rd_type_attr.value = r.raid_type
rd.setAttributeNode(rd_type_attr)
rd_size_attr = doc.createAttribute('raid-size')
rd_size_attr.value = r.raid_size
rd.setAttributeNode(rd_size_attr)
for raw_dev in r.raw_devices:
raw_dev_e = doc.createElement('raw-device')
raw_dev_tn = doc.createTextNode(raw_dev)
raw_dev_e.appendChild(raw_dev_tn)
rd.appendChild(raw_dev_e)
raids.appendChild(rd)
p_node.appendChild(raids)
@staticmethod
def get_size(dev):
for r in Raid.list:
if r.raid_device == dev:
return r.raid_size
class MountPoint:
''' mount-points '''
list=[]
def __init__(self, dev, dir='', fs='', fm='no'):
self.device = dev
self.directory = dir
self.filesystem = fs
self.format = fm
self.size = Partition.get_size(dev)
MountPoint.list.append(self)
@staticmethod
def change(dev, dir, fs, fm):
for i in range(len(MountPoint.list)):
if MountPoint.list[i].device == dev:
MountPoint.list[i].directory = dir
MountPoint.list[i].filesystem = fs
MountPoint.list[i].format = fm
@staticmethod
def init_from_internal():
''' init MountPoint from internal class Partition and class Raid '''
devs = [ p.device for p in Partition.list ]
for r in Raid.list:
for raw_d in r.raw_devices:
if raw_d in devs:
devs.remove(raw_d)
if not r.raid_device in devs:
devs.append(r.raid_device)
for dev in devs:
MountPoint(dev)
@staticmethod
def init_from_xml(node):
''' create MountPoint instances from xml node '''
for m in node.childNodes:
if m.nodeType == node.ELEMENT_NODE and m.nodeName == 'mount-point':
MountPoint(m.attributes['device'].value.encode('ascii'), \
m.attributes['directory'].value.encode('ascii'), \
m.attributes['file-system'].value.encode('ascii'), \
m.attributes['format'].value.encode('ascii') )
@staticmethod
def to_xml(doc, p_node):
''' write all MountPoint instance into xml
doc - xml document instance
p_node - xml node (parent node)'''
mps = doc.createElement('mount-points')
for m in MountPoint.list:
mp = doc.createElement('mount-point')
dev_attr = doc.createAttribute('device')
dir_attr = doc.createAttribute('directory')
fs_attr = doc.createAttribute('file-system')
fm_attr = doc.createAttribute('format')
dev_attr.value = m.device
dir_attr.value = m.directory
fs_attr.value = m.filesystem
fm_attr.value = m.format
mp.setAttributeNode(dev_attr)
mp.setAttributeNode(dir_attr)
mp.setAttributeNode(fs_attr)
mp.setAttributeNode(fm_attr)
mps.appendChild(mp)
p_node.appendChild(mps)
class Network:
''' network '''
hostname =''
configuration =''
domain = ''
ip = ''
mask = ''
gateway = ''
primary_dns = ''
secondary_dns = ''
@staticmethod
def init_from_xml(node):
''' init Network from xml node '''
for k in node.attributes.keys():
setattr(Network, k, node.attributes[k].value.encode('ascii'))
@staticmethod
def to_xml(doc, p_node):
''' write Network into xml
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'):
to_xml_attr(doc, ntwk, Network, nm)
p_node.appendChild(ntwk)
class Group:
''' software package group '''
dict = {}
def __init__(self, n, i):
self.name = n
self.install = i
self.description = ''
self.mandatory = []
self.selection = 'manual'
self.optional = []
Group.dict[n] = self
@staticmethod
def handle_release_node(r_node):
''' This method is called by init_from_config_xml
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 'mandatory' or 'no')
@staticmethod
def handle_group_node(g_node):
''' This method is called by init_from_config_xml
g_node - group node '''
g = Group.dict[g_node.attributes['name'].value]
for n in g_node.childNodes:
if n.nodeType == n.ELEMENT_NODE:
if n.nodeName == 'description':
g.description = n.firstChild.data
elif n.nodeName == 'including':
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'), 'no'])
@staticmethod
def init_from_config_xml(node):
''' 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']
Group.handle_release_node(rls_list[0])
for g in grp_list:
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'])
g.selection = grp_chld.attributes['selection'].value
init_from_xml = init_from_install_xml
@staticmethod
def to_xml(doc, p_node):
''' write Group instances into xml
doc - xml document instance
p_node - xml node (parent node)'''
grps = doc.createElement('groups')
for g in Group.dict.values():
grp = doc.createElement('group')
name_attr = doc.createAttribute('name')
name_attr.value = g.name
grp.setAttributeNode(name_attr)
inst_attr = doc.createAttribute('install')
inst_attr.value = g.install
grp.setAttributeNode(inst_attr)
if g.description:
dscp = doc.createElement('description')
dscp_data = doc.createTextNode(g.description)
dscp.appendChild(dscp_data)
grp.appendChild(dscp)
if g.mandatory:
mndt = doc.createElement('mandatory')
for m in g.mandatory:
pkg = doc.createElement('package')
pname_attr = doc.createAttribute('name')
pname_attr.value = m
pkg.setAttributeNode(pname_attr)
mndt.appendChild(pkg)
grp.appendChild(mndt)
if g.optional:
optl = doc.createElement('optional')
sel_attr = doc.createAttribute('selection')
sel_attr.value = g.selection
optl.setAttributeNode(sel_attr)
for o in g.optional:
pkg = doc.createElement('package')
pname_attr = doc.createAttribute('name')
pname_attr.value = o[0]
pkg.setAttributeNode(pname_attr)
pinst_attr = doc.createAttribute('install')
pinst_attr.value = o[1]
pkg.setAttributeNode(pinst_attr)
optl.appendChild(pkg)
grp.appendChild(optl)
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)
def init():
''' initialize '''
Partition.init_from_os()
Raid.init_from_os()
MountPoint.init_from_internal()
xmldoc_cfg = minidom.parse(config_xml)
root_cfg = xmldoc_cfg.firstChild
Group.init_from_config_xml(root_cfg)
Service.init_from_config_xml(root_cfg)
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()