add dependency step, add service step
This commit is contained in:
@@ -462,7 +462,7 @@ p - pkg, that includes this service
|
||||
pass
|
||||
|
||||
for s in Service.list:
|
||||
if s.pkg in l:
|
||||
if s.package in l:
|
||||
if s.start == 'disable':
|
||||
s.start = 'no'
|
||||
else:
|
||||
|
||||
82
python/ri_dep.py
Normal file
82
python/ri_dep.py
Normal file
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import ri_data
|
||||
|
||||
from xml.dom import minidom
|
||||
import os.path
|
||||
|
||||
dep_xml = os.path.join(os.path.dirname(__file__), '../xml/dependency.xml')
|
||||
|
||||
class Depending:
|
||||
''' Class recording depending relation '''
|
||||
dict={}
|
||||
def __init__(self, n):
|
||||
self.name = n
|
||||
self.depending = set()
|
||||
# flag for resolve recursive
|
||||
self.resolved = False
|
||||
Depending.dict[n] = self
|
||||
|
||||
def resolve_recursive(self):
|
||||
if self.resolved: return
|
||||
for d in self.depending:
|
||||
Depending.dict[d].resolve_recursive()
|
||||
tmp=set(self.depending)
|
||||
for d in self.depending:
|
||||
tmp.update(Depending.dict[d].depending)
|
||||
self.depending = tmp
|
||||
self.resolved = True
|
||||
|
||||
class Depended:
|
||||
''' Class recording depended by relation '''
|
||||
dict={}
|
||||
def __init__(self, n):
|
||||
self.name = n
|
||||
self.depended_by = set()
|
||||
Depended.dict[n] = self
|
||||
|
||||
def construct_depending():
|
||||
xml_doc = minidom.parse(dep_xml)
|
||||
xml_root = xml_doc.firstChild
|
||||
xml_dict = {}
|
||||
for n in xml_root.childNodes:
|
||||
if n.nodeType == n.ELEMENT_NODE and n.nodeName == 'package':
|
||||
xml_dict[n.attributes['name'].value] = n
|
||||
Depending(n.attributes['name'].value)
|
||||
|
||||
for d in Depending.dict.values():
|
||||
n = xml_dict[d.name]
|
||||
for r in n.getElementsByTagName('runtime'):
|
||||
for dep in r.getElementsByTagName('depending'):
|
||||
d.depending.add(dep.attributes['package'].value)
|
||||
|
||||
def resolve_recursive_depending():
|
||||
for d in Depending.dict.values():
|
||||
d.resolve_recursive()
|
||||
|
||||
def construct_depended():
|
||||
for d in Depending.dict.values():
|
||||
for dep in d.depending:
|
||||
if not Depended.dict.has_key(dep):
|
||||
Depended(dep)
|
||||
Depended.dict[dep].depended_by.add(d.name)
|
||||
|
||||
def get_extra_depending():
|
||||
l = []
|
||||
for g in ri_data.Group.dict.values():
|
||||
if g.install != 'no':
|
||||
l.extend([ p for p in g.mandatory ])
|
||||
l.extend([ p[0] for p in g.optional if p[1] == 'yes' ])
|
||||
|
||||
set1 = set(l)
|
||||
set2 = set(set1)
|
||||
|
||||
for d in set1:
|
||||
set2.update(Depending.dict[d].depending)
|
||||
|
||||
res = {}
|
||||
for d in set2.difference(set1):
|
||||
res[d] = Depended.dict[d].depended_by.intersection(set1)
|
||||
|
||||
return res
|
||||
|
||||
@@ -210,6 +210,9 @@ class SoftwarePackageWindow():
|
||||
if self.selection.get() == 'all':
|
||||
for ck in self.opt_chks:
|
||||
ck.configure(state='disable')
|
||||
else:
|
||||
for ck in self.opt_chks:
|
||||
ck.configure(state='normal')
|
||||
|
||||
|
||||
def ok(self):
|
||||
@@ -218,10 +221,16 @@ class SoftwarePackageWindow():
|
||||
for i in range(len(self.group.optional)):
|
||||
# install field, yes or no
|
||||
self.group.optional[i][1] = self.opt_vars[i].get()
|
||||
# clear variables and check buttons
|
||||
self.opt_vars = []
|
||||
self.opt_chks = []
|
||||
self.win.destroy()
|
||||
|
||||
def cancel(self):
|
||||
''' callback function for button cancel '''
|
||||
# clear variables and check buttons
|
||||
self.opt_vars = []
|
||||
self.opt_chks = []
|
||||
self.win.destroy()
|
||||
|
||||
def show(self):
|
||||
|
||||
228
python/ri_tk_cmd.py
Normal file
228
python/ri_tk_cmd.py
Normal file
@@ -0,0 +1,228 @@
|
||||
#!/usr/bin/python
|
||||
''' handle gui commands '''
|
||||
import ri_tk as display
|
||||
import ri_widget
|
||||
import ri_data
|
||||
import ri_dep
|
||||
|
||||
import re
|
||||
import copy
|
||||
import sys
|
||||
|
||||
def serial_no_init():
|
||||
display.var_dict['serial_no.number'].set(value=ri_data.SerialNumber.value)
|
||||
|
||||
def serial_no_quit():
|
||||
ri_data.SerialNumber.value = display.var_dict['serial_no.number'].get()
|
||||
|
||||
def mount_list_init():
|
||||
''' initialize mount list '''
|
||||
l = []
|
||||
for m in ri_data.MountPoint.list:
|
||||
# get size from Partition info
|
||||
sz = ri_data.Partition.get_size(m.device)
|
||||
if not sz:
|
||||
sz = ri_data.Raid.get_size(m.device)
|
||||
print m.device, m.directory, m.filesystem, m.format, sz
|
||||
s = m.device.ljust(10) + m.directory.ljust(10) + m.filesystem.ljust(10) + m.format.ljust(4) + sz.ljust(6)
|
||||
l.append(s)
|
||||
display.var_dict['mount.list'].set(value=tuple([str(i) for i in l]))
|
||||
|
||||
def mount_list_modify(*args):
|
||||
''' modify an item in mount list '''
|
||||
tw = ri_widget.TopWindow.dict['mount_list_modify']
|
||||
tw.show()
|
||||
|
||||
def mp_top_init():
|
||||
''' mount dir top window initialize '''
|
||||
ml_win = ri_widget.Widget.dict['mount.list'].tk_widget
|
||||
idxs = ml_win.curselection()
|
||||
if len(idxs) == 1:
|
||||
idx = int(idxs[0])
|
||||
mp = ri_data.MountPoint.list[idx]
|
||||
dev = mp.device
|
||||
dir = mp.directory
|
||||
fs = mp.filesystem
|
||||
fm = mp.format
|
||||
sz = mp.size
|
||||
display.var_dict['mp_top_dev'].set(value=dev)
|
||||
display.var_dict['mp_top_size'].set(value=sz)
|
||||
display.var_dict['mp_top_dir'].set(value=dir)
|
||||
if fm == 'yes':
|
||||
ri_widget.Widget.dict['mp_top_format'].tk_widget.select()
|
||||
else:
|
||||
ri_widget.Widget.dict['mp_top_not_format'].tk_widget.select()
|
||||
|
||||
fs_values = eval(display.var_dict['mp_top_fs'].get())
|
||||
for i in range(len(fs_values)):
|
||||
if fs == fs_values[i]:
|
||||
ri_widget.Widget.dict['mp_top_fs'].tk_widget.selection_set(i)
|
||||
|
||||
def mp_top_ok():
|
||||
''' mount dir top window OK '''
|
||||
l = []
|
||||
for itm in eval(display.var_dict['mount.list'].get()):
|
||||
dev = itm.split()[0]
|
||||
dev2 = display.var_dict['mp_top_dev'].get()
|
||||
if dev == dev2:
|
||||
sz = display.var_dict['mp_top_size'].get()
|
||||
dir = display.var_dict['mp_top_dir'].get()
|
||||
fm = display.var_dict['mp_top_format'].get()
|
||||
idxs2 = ri_widget.Widget.dict['mp_top_fs'].tk_widget.curselection()
|
||||
if len(idxs2):
|
||||
idx2 = int(idxs2[0])
|
||||
fs = eval(display.var_dict['mp_top_fs'].get())[idx2]
|
||||
else:
|
||||
fs = ''
|
||||
|
||||
s2 = dev.ljust(10) + dir.ljust(10) + fs.ljust(10) + fm.ljust(4) + sz.ljust(6)
|
||||
l.append(s2)
|
||||
# make change in internal data structure
|
||||
ri_data.MountPoint.change(dev2, dir, fs, fm)
|
||||
else:
|
||||
l.append(itm)
|
||||
|
||||
display.var_dict['mount.list'].set(value=tuple(l))
|
||||
ri_widget.TopWindow.dict['mount_list_modify'].hide()
|
||||
|
||||
def mp_top_cancel():
|
||||
''' mount dir top window cancel '''
|
||||
ri_widget.TopWindow.dict['mount_list_modify'].hide()
|
||||
pass
|
||||
|
||||
def network_init():
|
||||
''' network initialize '''
|
||||
display.var_dict['network_host_name']. set(value=ri_data.Network.hostname)
|
||||
ri_widget.Widget.dict['network_config_%s' %(ri_data.Network.configuration and ri_data.Network.configuration or 'static')].tk_widget.invoke()
|
||||
display.var_dict['network_domain_name']. set(value=ri_data.Network.domain)
|
||||
display.var_dict['network_ip']. set(value=ri_data.Network.ip)
|
||||
display.var_dict['network_subnet_mask']. set(value=ri_data.Network.mask)
|
||||
display.var_dict['network_gateway']. set(value=ri_data.Network.gateway)
|
||||
display.var_dict['network_primary_dns']. set(value=ri_data.Network.primary_dns)
|
||||
display.var_dict['network_secondary_dns'].set(value=ri_data.Network.secondary_dns)
|
||||
|
||||
def network_quit():
|
||||
''' network quit '''
|
||||
ri_data.Network.hostname = display.var_dict['network_host_name'].get()
|
||||
ri_data.Network.configuration = display.var_dict['network_config_method'].get()
|
||||
ri_data.Network.domain = display.var_dict['network_domain_name'].get()
|
||||
ri_data.Network.ip = display.var_dict['network_ip'].get()
|
||||
ri_data.Network.mask = display.var_dict['network_subnet_mask'].get()
|
||||
ri_data.Network.gateway = display.var_dict['network_gateway'].get()
|
||||
ri_data.Network.primary_dns = display.var_dict['network_primary_dns'].get()
|
||||
ri_data.Network.secondary_dns = display.var_dict['network_secondary_dns'].get()
|
||||
|
||||
def ncm_dynamic():
|
||||
''' when radio button ncm dynamic is checked, several data entry will be set 'disable' '''
|
||||
|
||||
for n in ('network_domain_name','network_ip','network_subnet_mask','network_gateway','network_primary_dns','network_secondary_dns'):
|
||||
ri_widget.Widget.dict[n].tk_widget.configure(state='disable')
|
||||
|
||||
def ncm_static():
|
||||
''' when radio button ncm static is checked, several data entry will be set 'normal' '''
|
||||
for n in ('network_domain_name','network_ip','network_subnet_mask','network_gateway','network_primary_dns','network_secondary_dns'):
|
||||
ri_widget.Widget.dict[n].tk_widget.configure(state='normal')
|
||||
|
||||
class GroupButton(object):
|
||||
''' A function class called whenever the group button is clicked '''
|
||||
dict={}
|
||||
def __init__(self, g):
|
||||
self.name = g.name
|
||||
GroupButton.dict[g.name] = self
|
||||
display.SoftwarePackageWindow(g)
|
||||
|
||||
def __call__(self):
|
||||
print self.name
|
||||
display.SoftwarePackageWindow.dict[self.name].show()
|
||||
|
||||
class GroupCheck(GroupButton):
|
||||
''' A function class called whenever the group check button is checked '''
|
||||
def __init__(self, g, v):
|
||||
self.variable = v
|
||||
GroupButton.__init__(self, g)
|
||||
|
||||
def __call__(self):
|
||||
v = display.var_dict[self.variable]
|
||||
if v.get() == 'yes':
|
||||
display.SoftwarePackageWindow.dict[self.name].show()
|
||||
|
||||
def software_group_mandatory_construct(w):
|
||||
''' construct widgets based actual data
|
||||
w - Widget instance '''
|
||||
mdt = [ m for m in ri_data.Group.dict.values() if m.install == 'mandatory' ]
|
||||
wit = w.widgets.pop()
|
||||
for i in mdt:
|
||||
wi = copy.deepcopy(wit)
|
||||
wi.attr['text'] = i.name
|
||||
vn = "software_group_%s" %(i.name)
|
||||
idx = mdt.index(i)
|
||||
wi.grid_location.dict['column'] = idx % int(w.grid_management.columns)
|
||||
wi.grid_location.dict['row'] = idx / int(w.grid_management.columns)
|
||||
gc = GroupButton(i)
|
||||
setattr(sys.modules['ri_cmd'], vn, gc)
|
||||
wi.attr['command'] = vn
|
||||
w.add_sub_widget(wi)
|
||||
|
||||
def software_group_optional_construct(w):
|
||||
''' construct widgets based actual data
|
||||
w - Widget instance '''
|
||||
opt = [ o for o in ri_data.Group.dict.values() if o.install != 'mandatory' ]
|
||||
wit = w.widgets.pop()
|
||||
for i in opt:
|
||||
wi = copy.deepcopy(wit)
|
||||
wi.attr['text'] = i.name
|
||||
vn = "software_group_%s" %(i.name)
|
||||
idx = opt.index(i)
|
||||
wi.grid_location.dict['column'] = idx % int(w.grid_management.columns)
|
||||
wi.grid_location.dict['row'] = idx / int(w.grid_management.columns)
|
||||
gc = GroupCheck(i, vn)
|
||||
setattr(sys.modules['ri_cmd'], vn, gc)
|
||||
wi.attr['command'] = vn
|
||||
wi.attr['variable'] = vn
|
||||
wi.variables = [(vn, 'StringVar', i.install),]
|
||||
w.add_sub_widget(wi)
|
||||
|
||||
def software_group_optional_quit():
|
||||
''' software group window quit, record optional group state '''
|
||||
opt = [ o for o in ri_data.Group.dict.values() if o.install != 'mandatory' ]
|
||||
for i in opt:
|
||||
print i.name
|
||||
vn = "software_group_%s" %(i.name)
|
||||
i.install = display.var_dict[vn].get()
|
||||
print i.name, i.install
|
||||
|
||||
def dependency_list_init():
|
||||
''' init function for list in dependency step '''
|
||||
ri_dep.construct_depending()
|
||||
ri_dep.resolve_recursive_depending()
|
||||
ri_dep.construct_depended()
|
||||
dep_dict = ri_dep.get_extra_depending()
|
||||
l = [ k.ljust(15) + ': ' + ' '.join(dep_dict[k]) for k in dep_dict.keys()]
|
||||
display.var_dict['dependency.list'].set(value=tuple(l))
|
||||
|
||||
def service_construct(w):
|
||||
''' construct service widget based on actual data
|
||||
w - Widget instance '''
|
||||
|
||||
# first refresh service state
|
||||
ri_data.Service.change_state()
|
||||
wit = w.widgets.pop()
|
||||
for i in ri_data.Service.list:
|
||||
wi = copy.deepcopy(wit)
|
||||
wi.attr['text'] = i.name
|
||||
vn = "service_%s" %(i.name)
|
||||
wi.attr['variable'] = vn
|
||||
wi.variables = [(vn, 'StringVar', i.start=='yes' and 'yes' or 'no')]
|
||||
if i.start == 'disable':
|
||||
wi.attr['state'] = 'disable'
|
||||
idx = ri_data.Service.list.index(i)
|
||||
wi.grid_location.dict['column'] = idx % int(w.grid_management.columns)
|
||||
wi.grid_location.dict['row'] = idx / int(w.grid_management.columns)
|
||||
w.add_sub_widget(wi)
|
||||
|
||||
def service_quit():
|
||||
''' record service state '''
|
||||
for i in ri_data.Service.list:
|
||||
if i.start != 'disable':
|
||||
vn = "service_%s" %(i.name)
|
||||
i.start = display.var_dict[vn].get()
|
||||
@@ -23,7 +23,7 @@
|
||||
<mount-point device='sda4' directory='' file-system='' format='no'/>
|
||||
<mount-point device='sdb2' directory='' file-system='' format='no'/>
|
||||
<mount-point device='sdb3' directory='/olp' file-system='reiserfs' format='yes'/>
|
||||
<mount-point device='sdb4' directory='' file-system='' format='no'/>
|
||||
<mount-point device='sdb4' directory='/' file-system='ext3' format='yes'/>
|
||||
<mount-point device='md0' directory='' file-system='' format='no'/>
|
||||
</mount-points>
|
||||
<network domain='' secondary_dns='' ip='' hostname='lizhi' mask='' primary_dns='' configuration='dynamic' gateway=''/>
|
||||
@@ -85,7 +85,7 @@
|
||||
<package name='trac' install='no'/>
|
||||
</optional>
|
||||
</group>
|
||||
<group name='office' install='yes'>
|
||||
<group name='office' install='no'>
|
||||
<description>
|
||||
办公类包括 OpenOffice.org 等办公软件。
|
||||
办公类都是必选软件包,当选择安装该类后,必选包是默认安装的。
|
||||
@@ -94,7 +94,7 @@
|
||||
<package name='openoffice'/>
|
||||
</mandatory>
|
||||
</group>
|
||||
<group name='kde' install='yes'>
|
||||
<group name='kde' install='no'>
|
||||
<description>
|
||||
KDE是一种著名的自由图形工作环境,整个系统采用Qt程序库
|
||||
KDE桌面类都是可选软件包,可以自由选择安装。
|
||||
@@ -240,8 +240,8 @@
|
||||
</description>
|
||||
<optional selection='manual'>
|
||||
<package name='qemu-kvm' install='no'/>
|
||||
<package name='bridge-utils' install='no'/>
|
||||
<package name='uml-utilities' install='no'/>
|
||||
<package name='bridge-utils' install='yes'/>
|
||||
<package name='uml-utilities' install='yes'/>
|
||||
</optional>
|
||||
</group>
|
||||
<group name='base' install='mandatory'>
|
||||
@@ -461,7 +461,7 @@
|
||||
</groups>
|
||||
<services>
|
||||
<service start='disable' package='netkit-rsh' script='inetd' name='rsh' number='S310'/>
|
||||
<service start='disable' package='openssh' script='sshd' name='ssh' number='S205'/>
|
||||
<service start='yes' package='openssh' script='sshd' name='ssh' number='S205'/>
|
||||
<service start='disable' package='proftpd' script='proftpd' name='ftpd' number='S280'/>
|
||||
<service start='disable' package='netkit-telnetd' script='inetd' name='telnet' number='S310'/>
|
||||
</services>
|
||||
|
||||
@@ -456,6 +456,70 @@ row 4 | |
|
||||
</widget>
|
||||
</widget>
|
||||
|
||||
<!--
|
||||
column1 column2 column3
|
||||
_____________________________________________________
|
||||
| |
|
||||
| ____________________ |
|
||||
| | | ^ |
|
||||
| | | | |
|
||||
| | | | |
|
||||
| | | | |
|
||||
| |____________________| v |
|
||||
| <- - - - - - - - - - -> |
|
||||
|_____________________________________________________|
|
||||
|
||||
-->
|
||||
|
||||
<widget type='Frame' name='dependency'>
|
||||
<grid_management rows='2' columns='2'>
|
||||
<configure row='0' weight='1'/>
|
||||
<configure column='0' weight='1'/>
|
||||
</grid_management>
|
||||
<grid_location row='2' column='1' columnspan='2' sticky='NSWE'/>
|
||||
<action>
|
||||
<scroll scrolling='dependency.scroll.v' scrolled='dependency.list'/>
|
||||
<scroll scrolling='dependency.scroll.h' scrolled='dependency.list'/>
|
||||
</action>
|
||||
<widget type='Listbox' name='dependency.list'>
|
||||
<widget_attribute listvariable='dependency.list'/>
|
||||
<grid_location row='0' column='0' padx='30' pady='30' sticky='NSWE'/>
|
||||
<variable name='dependency.list' type='StringVar'/>
|
||||
<action init='dependency_list_init'/>
|
||||
</widget>
|
||||
<widget type='Scrollbar' name='dependency.scroll.v'>
|
||||
<widget_attribute orient='vertical'/>
|
||||
<grid_location row='0' column='1' pady='30' sticky='NS'/>
|
||||
</widget>
|
||||
<widget type='Scrollbar' name='dependency.scroll.h'>
|
||||
<widget_attribute orient='horizontal'/>
|
||||
<grid_location row='1' column='0' padx='30' sticky='WE'/>
|
||||
</widget>
|
||||
</widget>
|
||||
|
||||
<!--
|
||||
column1 column2 column3
|
||||
_____________________________________________
|
||||
| _ _ _ |
|
||||
| |_|service 1 |_|service 2 |_|service 3 |
|
||||
| ...... |
|
||||
|_____________________________________________|
|
||||
-->
|
||||
<widget type='Frame' name='service' construct='service_construct'>
|
||||
<grid_management rows='x' columns='3'>
|
||||
<configure column='0' weight='1'/>
|
||||
<configure column='1' weight='1'/>
|
||||
<configure column='2' weight='1'/>
|
||||
</grid_management>
|
||||
<grid_location row='2' column='1' columnspan='2' sticky='NSWE'/>
|
||||
<action quit='service_quit'/>
|
||||
<!-- a template for service item -->
|
||||
<widget type='Checkbutton' name='service-item'>
|
||||
<widget_attribute text='' variable='' onvalue='yes' offvalue='no'/>
|
||||
<grid_location row='0' column='0' sticky='W'/>
|
||||
</widget>
|
||||
</widget>
|
||||
|
||||
<message_box name='previous' type='info' title='#install-sequence' message='#first-step'/>
|
||||
<message_box name='next' type='info' title='#install-sequence' message='#last-step'/>
|
||||
|
||||
@@ -615,5 +679,7 @@ row 4 | |
|
||||
<widget name='mount'/>
|
||||
<widget name='network'/>
|
||||
<widget name='software-group'/>
|
||||
<widget name='dependency'/>
|
||||
<widget name='service'/>
|
||||
</sequence>
|
||||
</interface>
|
||||
|
||||
Reference in New Issue
Block a user