You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
583 lines
24 KiB
583 lines
24 KiB
#-*- coding: utf-8 -*-
|
|
|
|
# Copyright 2010 Calculate Ltd. http://www.calculate-linux.org
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import re
|
|
import sys
|
|
|
|
from cl_install import cl_install, InstallError, __app__, __version__,\
|
|
get_install_errors
|
|
from cl_vars_share import varsShare
|
|
from cl_opt import opt
|
|
from cl_share_cmd import share_cmd
|
|
from utils import ip as iputils
|
|
from cl_utils import isPkgInstalled
|
|
|
|
from cl_lang import lang
|
|
lang().setLanguage(sys.modules[__name__])
|
|
OSSYSTEM_LIST=sorted(varsShare.dictNameSystem.keys())
|
|
NM_LIST=sorted(varsShare.dictNetworkManagers.keys())
|
|
|
|
DESCRIPTION = _("The Calculate Linux installation and configuration utility")
|
|
CMD_OPTIONS = [{'shortOption':"d",
|
|
'longOption':"disk",
|
|
'optVal':"DISK[:[DIR:FILESYSTEM:OPTIONS]]",
|
|
'action':'append',
|
|
'help':_("the DISK for installation, which mounted to DIR") +
|
|
". " +
|
|
_("DIR with value 'none' will cancels the mount point transfer")
|
|
+ ". " +_("For creating bind mount point need specify source directory as DISK")
|
|
},
|
|
{'shortOption':"w",
|
|
'longOption':"swap",
|
|
'optVal':"SWAP_DISK",
|
|
'action':'append',
|
|
'help':_("swap disk for installation")
|
|
},
|
|
{'longOption':"mbr",
|
|
'optVal':"DEVICE",
|
|
'help':_("boot disk for the installed system \
|
|
(to be recorded MBR), off - disable MBR writing")
|
|
},
|
|
{'longOption':"type",
|
|
'optVal':"DISKTYPE",
|
|
'type':'choice',
|
|
'choices':['flash','hdd','usb-hdd'],
|
|
'help':_("device type for installed system")
|
|
},
|
|
{'longOption':'iso',
|
|
'optVal':"ISO",
|
|
'help':_("ISO image for installation")},
|
|
{'shortOption':"s",
|
|
'longOption':"os",
|
|
'optVal':"SYSTEM",
|
|
'type':'choice',
|
|
'choices_regignore': OSSYSTEM_LIST,
|
|
'help':_("select operation system")
|
|
},
|
|
{'longOption':"march",
|
|
'optVal':"ARCH",
|
|
'type':'choice',
|
|
'choices':['i686','x86_64'],
|
|
'help':_("select processor architecture")
|
|
},
|
|
{'longOption':"build",
|
|
'help':_("installation for assembling")
|
|
},
|
|
{'shortOption':"l",
|
|
'longOption':"lang",
|
|
'optVal':"LANG",
|
|
'help':_("set language")
|
|
},
|
|
{'shortOption':"u",
|
|
'longOption':"user",
|
|
'optVal':"USER",
|
|
'action':'append',
|
|
'help':_("add user to installed system")
|
|
},
|
|
{'longOption':"hostname",
|
|
'optVal':"HOSTNAME",
|
|
'help':_("set short hostname of full hostname")
|
|
},
|
|
{'longOption':"netconf",
|
|
'optVal':"NETMANAGER",
|
|
'type':'choice',
|
|
'choices_regignore': NM_LIST,
|
|
'help':_("network manager (%s)"%
|
|
"%s or %s" % (",".join(NM_LIST[0:-1]),NM_LIST[-1]))},
|
|
{'longOption':"dhcp",
|
|
'optVal':"IFACE",
|
|
'action':'append',
|
|
'help':_("get ip address by %s for specified interface")%"DHCP"
|
|
},
|
|
{'longOption':"ip",
|
|
'optVal':"[IFACE:]IP",
|
|
'action':'append',
|
|
'help':_("ip address with net (example:%s)")%"192.168.1.1/24"
|
|
},
|
|
{'longOption':"route",
|
|
'optVal':"NETWORK:[GATEWAY][:DEV[:SOURCE]]",
|
|
'action':'append',
|
|
'help':_("add routing rule")
|
|
},
|
|
{'longOption':"dns",
|
|
'optVal':"DNS",
|
|
'help':_("domain name servers (comma delimeter)")
|
|
},
|
|
{'longOption':"proxy",
|
|
'optVal':"PROXY",
|
|
'help':_("set proxy server for system")
|
|
},
|
|
{'longOption':"ntp",
|
|
'optVal':"NTP",
|
|
'help':_("set ntp server for system")
|
|
},
|
|
{'longOption':"video",
|
|
'optVal':"VIDEODRV",
|
|
'help':_("set video driver")
|
|
},
|
|
{'shortOption':"X",
|
|
'optVal':"<width>x<height>",
|
|
'help':_("set Xorg resolution")
|
|
},
|
|
{'longOption':"fb",
|
|
'optVal':"<width>x<height>",
|
|
'help':_("set frame buffer resolution")
|
|
},
|
|
{'longOption':"timezone",
|
|
'optVal':"TIMEZONE",
|
|
'help':_("set timezone")
|
|
},
|
|
{'longOption':"nouuid",
|
|
'help':_("do not use UUID")
|
|
},
|
|
{'longOption':'set'},
|
|
{'shortOption':"U",
|
|
'longOption':"update",
|
|
'help':_("install only newer images")},
|
|
{'shortOption':"f",
|
|
'longOption':"force",
|
|
'help':_("no questions during the install process")
|
|
},
|
|
{'longOption':"startup",
|
|
'help':_("configure current system")
|
|
},
|
|
{'longOption':"install",
|
|
'help':_("install package")
|
|
},
|
|
{'longOption':"uninstall",
|
|
'help':_("uninstall package")
|
|
},
|
|
{'longOption':"nospinner",
|
|
'help':_("disable spinner")
|
|
},
|
|
{'shortOption':"P",
|
|
'help':_("use passwords for the users accounts \
|
|
(from standard input)")
|
|
},
|
|
{'shortOption':'p',
|
|
'longOption':"show-partitions",
|
|
'help':_("display all partitions")}
|
|
]
|
|
|
|
class OptException(Exception):
|
|
pass
|
|
|
|
class install_cmd(share_cmd):
|
|
"""Class for work with cl_install by console"""
|
|
def __init__(self):
|
|
setpos = \
|
|
filter(lambda x:x[1].get('longOption')=="set",
|
|
enumerate(CMD_OPTIONS))[0][0]
|
|
CMD_OPTIONS[setpos] = opt.variable_set[0]
|
|
self.optobj = opt(package=__app__,
|
|
version=__version__,
|
|
description=DESCRIPTION,
|
|
option_list= CMD_OPTIONS + opt.variable_view +
|
|
opt.color_control,
|
|
check_values=self.checkOpts)
|
|
self.logicObj = cl_install()
|
|
# names incompatible options with --startup
|
|
self.optionsStartupIncompatible = ["type","d", "b", "mbr",
|
|
"w", "f","U", "s","install","uninstall","build","u"]
|
|
self.optionsDhcpIncompatible = ["ip","gateway","dns"]
|
|
self.errorWithExample = \
|
|
_("option {optname}: {errormess}:"
|
|
" '{value}' (example: '{example}')")
|
|
|
|
def _getNamesAllSetOptions(self):
|
|
"""Get list set options"""
|
|
setOptDict = self.optobj.values.__dict__.items()
|
|
defaultOptDict = self.optobj.get_default_values().__dict__.items()
|
|
return reduce(lambda x,y: x+[y[0][0]],
|
|
filter(lambda x:x[0][1] != x[1][1],
|
|
zip(setOptDict,defaultOptDict)), [])
|
|
|
|
def getStringIncompatibleOptions(self,listOpt):
|
|
"""Форматированная строка несовместимых опций разделенных ','"""
|
|
return ", ".join(map(lambda x: len(x) == 1 and "'-%s'"%x or "'--%s'"%x,
|
|
listOpt))
|
|
|
|
def checkIncompatibleStartup(self):
|
|
"""Check incompatible options for option --startup"""
|
|
incompatible = list(set(self._getNamesAllSetOptions()) &
|
|
set(self.optionsStartupIncompatible))
|
|
if incompatible:
|
|
self.optobj.error(_("incompatible options")+":"+" %s"\
|
|
%self.getStringIncompatibleOptions(incompatible+["startup"]))
|
|
|
|
def checkIncompatibleDhcp(self):
|
|
"""Check incompatible options for option --dchp"""
|
|
incompatible = list(set(self._getNamesAllSetOptions()) &
|
|
set(self.optionsDhcpIncompatible))
|
|
if incompatible:
|
|
self.optobj.error(_("incompatible options")+":"+" %s"\
|
|
%self.getStringIncompatibleOptions(incompatible+["dhcp"]))
|
|
|
|
def checkIncompatibleInstallUninstall(self):
|
|
"""Check incompatible options for options --install and --uninstall"""
|
|
opts = self._getNamesAllSetOptions()
|
|
if len(opts)>1:
|
|
self.optobj.error(_("incompatible options")+":"+" %s"\
|
|
%self.getStringIncompatibleOptions(opts))
|
|
|
|
def __checkByReg(self,reg="",value="",valueopt="",valuename="",example=""):
|
|
"""Check option specifed by value"""
|
|
if value:
|
|
if not re.match(reg,value):
|
|
self.optobj.error(self.errorWithExample.format(
|
|
optname=valueopt,
|
|
errormess=_("%s specifing error")%valuename,
|
|
value=value,
|
|
example=example))
|
|
|
|
|
|
def checkOpts(self, values, args):
|
|
"""Check values all specified options."""
|
|
if len(args) > 0:
|
|
self.optobj.error(_("unrecognized option") + ": %s"% "".join(args))
|
|
if values.install or values.uninstall:
|
|
self.checkIncompatibleInstallUninstall()
|
|
if values.startup:
|
|
self.checkIncompatibleStartup()
|
|
if values.dhcp:
|
|
self.checkIncompatibleDhcp()
|
|
if not values.v:
|
|
if values.filter:
|
|
errMsg = _("incorrect option") + ":" + " %s" %"--filter" +\
|
|
": " + _("use with option '-v'")
|
|
self.optobj.error(errMsg)
|
|
if values.xml:
|
|
errMsg = _("incorrect option") + ":" + " %s" %"--xml" +\
|
|
": " + _("use with option '-v'")
|
|
self.optobj.error(errMsg)
|
|
self.__checkByReg(reg="^\d+x\d+$",value=values.X,valueopt="-X",
|
|
valuename=_("X resolution"),example="1024x768")
|
|
self.__checkByReg(reg="^\d+x\d+$",value=values.fb,valueopt="--fb",
|
|
valuename=_("frame buffer resolution"),
|
|
example="1024x768")
|
|
if values.ip:
|
|
for ipaddr in values.ip:
|
|
if not re.match("^(\w+:)?%s$"%iputils.IP_ADDR_NET,ipaddr):
|
|
self.optobj.error(self.errorWithExample.format(
|
|
optname="--ip",
|
|
errormess=_("%s specifing error")%"ip",
|
|
value=ipaddr,
|
|
example="eth0:192.168.0.21/16"))
|
|
if not values.dns is None:
|
|
if not re.match("(^{0}(,{0})*|)$".format(iputils.IP_ADDR),values.dns):
|
|
self.optobj.error(self.errorWithExample.format(
|
|
optname="--dns",
|
|
errormess=_("%s specifing error")%"dns",
|
|
value=values.dns,
|
|
example="8.8.8.8"))
|
|
if values.route:
|
|
for route in values.route:
|
|
if not re.match("^({net}|default):(({ipaddr})?"
|
|
"(:\w+(:{ipaddr})?)?)?$".format(
|
|
net=iputils.IP_ADDR_NET,ipaddr=iputils.IP_ADDR),route):
|
|
self.optobj.error(self.errorWithExample.format(
|
|
optname="--route",
|
|
errormess=_("%s specifing error")%_("route"),
|
|
value=route,
|
|
example="default:192.168.1.1"))
|
|
if not (values.install or values.uninstall or values.startup):
|
|
if values.v is False and \
|
|
not values.p and \
|
|
values.d is None and \
|
|
not self.logicObj.clVars.Get('os_install_dev_from'):
|
|
self.optobj.error(_("need specify disk by '-d' option"))
|
|
# check syntax DISK:DIR:FS:'Do I need to format the disk'
|
|
if values.d:
|
|
reTrueDisk = re.compile("^[^:]+(:[^:]*){0,3}$")
|
|
wrongValue = filter(lambda x: not reTrueDisk.match(x),values.d)
|
|
if wrongValue:
|
|
self.optobj.error(self.errorWithExample.format(
|
|
optname="-d",
|
|
errormess=_("%s specifing error")%_("disk"),
|
|
value=", ".join(wrongValue),
|
|
example="/dev/sda2:/:ext4"))
|
|
# check syntax SWAP_DISK
|
|
if values.w:
|
|
reTrueBind = re.compile("^[^:]+$")
|
|
wrongValue = filter(lambda x: not reTrueBind.match(x),values.w)
|
|
if wrongValue:
|
|
self.optobj.error(self.errorWithExample.format(
|
|
optname="-w",
|
|
errormess=_("%s specifing error")%_("disk"),
|
|
value=", ".join(wrongValue),
|
|
example="/dev/sda1"))
|
|
#check boot device
|
|
if values.mbr:
|
|
bootDisk = values.mbr
|
|
reBootDisk = re.compile("^/dev/.+[^\d]|off$")
|
|
if not reBootDisk.match(bootDisk):
|
|
self.optobj.error(_("option %s:") %"mbr" + " " +\
|
|
_("disk specifing error: '%s'")%bootDisk)
|
|
# check syntax --set
|
|
self.optobj.checkVarSyntax(values)
|
|
return (values, args)
|
|
|
|
def setLang(self,lang):
|
|
"""Process set locales by lang"""
|
|
if self.logicObj.setAllLocaleByLang(lang):
|
|
return True
|
|
else:
|
|
self.printERROR(_("specified lang %s is unsupported")%lang)
|
|
return False
|
|
|
|
def setProxyNtpHostname(self,proxy,ntp,hostname):
|
|
"""Process set locales by lang"""
|
|
getVar = self.logicObj.clVars.Get
|
|
setVar = self.logicObj.clVars.Set
|
|
setWriteVar = self.logicObj.clVars.SetWriteVar
|
|
if proxy:
|
|
if not setWriteVar('os_install_proxy',proxy):
|
|
self.printERROR(get_install_errors(),printBR=False)
|
|
return False
|
|
if ntp:
|
|
if not setWriteVar('os_install_ntp',ntp):
|
|
self.printERROR(get_install_errors(),printBR=False)
|
|
return False
|
|
if hostname:
|
|
if "." in hostname:
|
|
hostname, op, domain = hostname.partition('.')
|
|
setVar('os_install_net_hostname', hostname,True)
|
|
setVar('os_install_net_domain', domain,True)
|
|
dns_search = getVar("os_install_net_dns_search")
|
|
if not domain in dns_search:
|
|
setVar("os_install_net_dns_search",domain,True)
|
|
else:
|
|
setVar('os_install_net_hostname', hostname,True)
|
|
return True
|
|
|
|
def setNetworkParams(self,ipaddrs,routes,dns,setup,dhcps):
|
|
"""Set nework params"""
|
|
if not dns is None:
|
|
self.logicObj.clVars.Set("os_install_net_dns",
|
|
dns.replace(',',' '), True)
|
|
ipaddrs = map(lambda x:x.split(":"),ipaddrs or [])
|
|
routes = map(lambda x:x+[""]*(4-len(x)),
|
|
map(lambda x:x.split(":"),routes or []))
|
|
dhcps = dhcps or []
|
|
if not self.logicObj.setNetwork(ipaddrs,dhcps,routes):
|
|
return False
|
|
if setup:
|
|
if not isPkgInstalled(setup):
|
|
self.printERROR(_("Network manager %s is not installed")%setup)
|
|
return False
|
|
self.logicObj.clVars.Set("os_install_net_conf",setup,True)
|
|
return True
|
|
|
|
def setVars(self,options):
|
|
"""Process setting values for variables"""
|
|
values = self.optobj.values
|
|
if values.video:
|
|
if not self.logicObj.setVideo(values.video,
|
|
startup=values.startup):
|
|
return False
|
|
if values.X:
|
|
if not self.clVars.Set('os_install_x11_resolution', values.X,
|
|
force=True):
|
|
return False
|
|
if values.fb:
|
|
if not self.clVars.Set('os_install_fb_resolution',
|
|
"%s-32"%values.fb,
|
|
force=True):
|
|
return False
|
|
if values.timezone:
|
|
if not self.logicObj.setTimezone(values.timezone):
|
|
return False
|
|
if options.set:
|
|
for vals in options.set:
|
|
for val in vals.split(','):
|
|
k,o,v = val.partition('=')
|
|
if self.logicObj.clVars.exists(k):
|
|
if self.logicObj.clVars.SetWriteVar(k,v) == False:
|
|
self.printERROR(get_install_errors(),printBR=False)
|
|
return False
|
|
else:
|
|
self.printERROR(_('variable %s not found')%k)
|
|
return False
|
|
return True
|
|
|
|
def setAction(self,startup):
|
|
"""Set action by configuration or install system"""
|
|
self.logicObj.clVars.Set('cl_action',
|
|
"merge" if startup else "system",True)
|
|
|
|
def checkAndSetInstallOptions(self,diskOptions, swapOptions,
|
|
usersOptions):
|
|
"""Check and set disk, swap and bind cmd options"""
|
|
if self.optobj.values.s:
|
|
self.logicObj.setLinuxName(self.optobj.values.s.upper())
|
|
if self.optobj.values.march:
|
|
self.logicObj.clVars.Set('os_install_arch_machine',
|
|
self.optobj.values.march,True)
|
|
if self.optobj.values.nouuid:
|
|
self.logicObj.clVars.Set('cl_uuid_set','off',True)
|
|
if self.optobj.values.build:
|
|
self.logicObj.clVars.Set('os_install_scratch',"on",True)
|
|
else:
|
|
self.logicObj.clVars.Set('os_install_scratch',"off",True)
|
|
if self.optobj.values.type:
|
|
self.logicObj.clVars.Set('os_install_root_type',
|
|
self.optobj.values.type, True)
|
|
|
|
if self.optobj.values.iso:
|
|
if not self.logicObj.setIso(self.optobj.values.iso):
|
|
return False
|
|
|
|
listDiskOptions = []
|
|
listBindOptions = []
|
|
listSwapOptions = []
|
|
if diskOptions:
|
|
listDiskOptions = self._parseOptDisk(diskOptions)
|
|
if listDiskOptions is False:
|
|
return False
|
|
listBindOptions = self._parseOptBind(diskOptions)
|
|
if listBindOptions is False:
|
|
return False
|
|
if swapOptions:
|
|
listSwapOptions = self._parseOptSwap(swapOptions)
|
|
if listSwapOptions is False:
|
|
return False
|
|
if not self.logicObj.setInstallOptions(listDiskOptions, listBindOptions,
|
|
listSwapOptions, usersOptions,
|
|
self.optobj.values.mbr):
|
|
return False
|
|
return True
|
|
|
|
def _parseOptSwap(self, listOpt):
|
|
"""Parse value cmd option --swap"""
|
|
listNameOptions = ["dev"]
|
|
lenOptions = len(listNameOptions)
|
|
itemOptions = map(lambda x: (x,''), listNameOptions)
|
|
rawListOpt = map(lambda x: filter(lambda y: y, x.split(':')), listOpt)
|
|
sameLenListOpt = []
|
|
for listData in rawListOpt:
|
|
lenListData = len(listData)
|
|
if lenListData>1:
|
|
errOpt = ":".join(filter(lambda x: x, listData))
|
|
self.printERROR(_("incorrect '%s'")%errOpt)
|
|
return False
|
|
dictOpt = {}
|
|
dictOpt.update(zip(map(lambda x:x[0],itemOptions),listData))
|
|
sameLenListOpt.append(dictOpt)
|
|
return sameLenListOpt
|
|
|
|
def _parseOptBind(self, listOpt):
|
|
"""Parse value cmd option --bind"""
|
|
listOpt = filter(lambda x:not x.startswith('/dev/'),listOpt)
|
|
listNameOptions = ["srcMountPoint", "destMountPoint"]
|
|
lenOptions = len(listNameOptions)
|
|
itemOptions = map(lambda x: (x,''), listNameOptions)
|
|
rawListOpt = map(lambda x: filter(lambda y: y, x.split(':')), listOpt)
|
|
sameLenListOpt = []
|
|
for listData in rawListOpt:
|
|
lenListData = len(listData)
|
|
if lenListData < lenOptions:
|
|
listData += ['']*(lenOptions-lenListData)
|
|
dictOpt = {}
|
|
dictOpt.update(zip(map(lambda x: x[0], itemOptions),listData))
|
|
srcDir = dictOpt["srcMountPoint"]
|
|
destDir = dictOpt["destMountPoint"]
|
|
if not (srcDir and destDir):
|
|
errOpt = ":".join(filter(lambda x: x, listData))
|
|
self.printERROR(_("incorrect '%s'")%errOpt)
|
|
return False
|
|
sameLenListOpt.append(dictOpt)
|
|
return sameLenListOpt
|
|
|
|
def _parseOptDisk(self, listOpt):
|
|
"""Parse value cmd option --disk"""
|
|
listOpt = filter(lambda x:x.startswith('/dev/'),listOpt)
|
|
listNameOptions = ["dev","mountPoint","fileSystem","options"]
|
|
lenOptions = len(listNameOptions)
|
|
itemOptions = map(lambda x: (x,''), listNameOptions)
|
|
rawListOpt = map(lambda x: x.split(':'), listOpt)
|
|
sameLenListOpt = []
|
|
for listData in rawListOpt:
|
|
lenListData = len(listData)
|
|
if lenListData < lenOptions:
|
|
listData += ['']*(lenOptions-lenListData)
|
|
dictOpt = {}
|
|
dictOpt.update(zip(map(lambda x: x[0],itemOptions), listData))
|
|
options = []
|
|
strOptions = dictOpt["options"]
|
|
if strOptions:
|
|
options = filter(lambda x: x, strOptions.split(','))
|
|
dictOpt["options"] = options
|
|
sameLenListOpt.append(dictOpt)
|
|
return sameLenListOpt
|
|
|
|
def templateSelect(self,template):
|
|
"""Process template appling"""
|
|
if self.logicObj.applyTemplatesForSystem():
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def installSystem(self, force=False, bootDisk=None, users=[],
|
|
stdinReadPwd=False, builder=False, flagSpinner=True,
|
|
update=False):
|
|
"""Run install system"""
|
|
if self.logicObj.installSystem(force=force, bootDisk=bootDisk,
|
|
stdinReadPwd=stdinReadPwd, builder=builder,
|
|
flagSpinner=flagSpinner,update=update):
|
|
if self.logicObj.clVars.Get('os_install_root_type') != "flash":
|
|
self.defaultPrint("\n")
|
|
self.defaultPrint(_("To apply changes you have to reboot")+
|
|
".\n")
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def showPartitions(self):
|
|
self.logicObj.printAllPartitonsTable()
|
|
|
|
def configureSystem(self):
|
|
"""Run configure system"""
|
|
if self.logicObj.configureSystem():
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def installPackage(self):
|
|
"""Run package installation"""
|
|
if self.logicObj.installPackage():
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def uninstallPackage(self):
|
|
"""Run package uninstallation"""
|
|
if self.logicObj.uninstallPackage():
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def parse_args(self, args=None, values=None):
|
|
"""
|
|
Preparse for catch non option --live
|
|
"""
|
|
rargs = self.optobj._get_args(args)
|
|
if rargs:
|
|
for arg in rargs:
|
|
if arg == "--live":
|
|
self.optobj.error(_("option %s:") %"--live" +\
|
|
" " + _("option is depricated, use '--startup' option"))
|
|
return self.optobj.parse_args(args,values)
|