From 1f9a8879c1e9f189244c5467f1d4bd0855ff9896 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 3 Aug 2017 12:04:22 -0700 Subject: [PATCH] quick pass at small xen code cleanup and usage of double quotes --- daemon/core/xen/xen.py | 319 +++++++++++++++++------------------ daemon/core/xen/xenconfig.py | 107 +++++++----- 2 files changed, 223 insertions(+), 203 deletions(-) diff --git a/daemon/core/xen/xen.py b/daemon/core/xen/xen.py index aaa39bec..bb656faf 100644 --- a/daemon/core/xen/xen.py +++ b/daemon/core/xen/xen.py @@ -54,8 +54,7 @@ UDEVADM_PATH = "/sbin/udevadm" class XenVEth(PyCoreNetIf): - def __init__(self, node, name, localname, mtu=1500, net=None, - start=True, hwaddr=None): + def __init__(self, node, name, localname, mtu=1500, net=None, start=True, hwaddr=None): # note that net arg is ignored PyCoreNetIf.__init__(self, node=node, name=name, mtu=mtu) self.localname = localname @@ -65,10 +64,9 @@ class XenVEth(PyCoreNetIf): self.startup() def startup(self): - cmd = [XM_PATH, 'network-attach', self.node.vmname, - 'vifname=%s' % self.localname, 'script=vif-core'] + cmd = [XM_PATH, "network-attach", self.node.vmname, "vifname=%s" % self.localname, "script=vif-core"] if self.hwaddr is not None: - cmd.append('mac=%s' % self.hwaddr) + cmd.append("mac=%s" % self.hwaddr) subprocess.check_call(cmd) subprocess.check_call([constants.IP_BIN, "link", "set", self.localname, "up"]) self.up = True @@ -79,8 +77,8 @@ class XenVEth(PyCoreNetIf): if self.localname: if self.hwaddr is not None: pass - # this should be doable, but some argument isn't a string - # check_call([XM_PATH, 'network-detach', self.node.vmname, + # this should be doable, but some argument isn"t a string + # check_call([XM_PATH, "network-detach", self.node.vmname, # self.hwaddr]) self.up = False @@ -88,51 +86,50 @@ class XenVEth(PyCoreNetIf): class XenNode(PyCoreNode): apitype = NodeTypes.XEN.value - FilesToIgnore = frozenset([ - # 'ipforward.sh', - 'quaggaboot.sh', + files_to_ignore = frozenset([ + # "ipforward.sh", + "quaggaboot.sh", ]) - FilesRedirection = { - 'ipforward.sh': '/core-tmp/ipforward.sh', + files_redirection = { + "ipforward.sh": "/core-tmp/ipforward.sh", } - CmdsToIgnore = frozenset([ - # 'sh ipforward.sh', - # 'sh quaggaboot.sh zebra', - # 'sh quaggaboot.sh ospfd', - # 'sh quaggaboot.sh ospf6d', - 'killall zebra', - 'killall ospfd', - 'killall ospf6d', - 'pidof zebra', 'pidof ospfd', 'pidof ospf6d', + cmds_to_ignore = frozenset([ + # "sh ipforward.sh", + # "sh quaggaboot.sh zebra", + # "sh quaggaboot.sh ospfd", + # "sh quaggaboot.sh ospf6d", + "killall zebra", + "killall ospfd", + "killall ospf6d", + "pidof zebra", "pidof ospfd", "pidof ospf6d", ]) - def RedirCmd_ipforward(self): - sysctlFile = open(os.path.join(self.mountdir, self.etcdir, 'sysctl.conf'), 'a') - p1 = subprocess.Popen([AWK_PATH, '/^\/sbin\/sysctl -w/ {print $NF}', - os.path.join(self.nodedir, 'core-tmp/ipforward.sh')], stdout=sysctlFile) + def redir_cmd_ipforward(self): + sysctl_file = open(os.path.join(self.mountdir, self.etcdir, "sysctl.conf"), "a") + p1 = subprocess.Popen([AWK_PATH, "/^\/sbin\/sysctl -w/ {print $NF}", + os.path.join(self.nodedir, "core-tmp/ipforward.sh")], stdout=sysctl_file) p1.wait() - sysctlFile.close() + sysctl_file.close() - def RedirCmd_zebra(self): - subprocess.check_call([SED_PATH, '-i', '-e', 's/^zebra=no/zebra=yes/', - os.path.join(self.mountdir, self.etcdir, 'quagga/daemons')]) + def redir_cmd_zebra(self): + subprocess.check_call([SED_PATH, "-i", "-e", "s/^zebra=no/zebra=yes/", + os.path.join(self.mountdir, self.etcdir, "quagga/daemons")]) - def RedirCmd_ospfd(self): - subprocess.check_call([SED_PATH, '-i', '-e', 's/^ospfd=no/ospfd=yes/', - os.path.join(self.mountdir, self.etcdir, 'quagga/daemons')]) + def redir_cmd_ospfd(self): + subprocess.check_call([SED_PATH, "-i", "-e", "s/^ospfd=no/ospfd=yes/", + os.path.join(self.mountdir, self.etcdir, "quagga/daemons")]) - def RedirCmd_ospf6d(self): - subprocess.check_call([SED_PATH, '-i', '-e', - 's/^ospf6d=no/ospf6d=yes/', - os.path.join(self.mountdir, self.etcdir, 'quagga/daemons')]) + def redir_cmd_ospf6d(self): + subprocess.check_call([SED_PATH, "-i", "-e", "s/^ospf6d=no/ospf6d=yes/", + os.path.join(self.mountdir, self.etcdir, "quagga/daemons")]) - CmdsRedirection = { - 'sh ipforward.sh': RedirCmd_ipforward, - 'sh quaggaboot.sh zebra': RedirCmd_zebra, - 'sh quaggaboot.sh ospfd': RedirCmd_ospfd, - 'sh quaggaboot.sh ospf6d': RedirCmd_ospf6d, + cmds_redirection = { + "sh ipforward.sh": redir_cmd_ipforward, + "sh quaggaboot.sh zebra": redir_cmd_zebra, + "sh quaggaboot.sh ospfd": redir_cmd_ospfd, + "sh quaggaboot.sh ospf6d": redir_cmd_ospf6d, } # CoreNode: no __init__, take from LxcNode & SimpleLxcNode @@ -154,34 +151,32 @@ class XenNode(PyCoreNode): # domU name self.vmname = "c" + str(session.session_id) + "-" + name # LVM volume group name - self.vgname = self.getconfigitem('vg_name', vgname) + self.vgname = self.getconfigitem("vg_name", vgname) # LVM logical volume name - self.lvname = self.vmname + '-' + self.lvname = self.vmname + "-" # LVM logical volume device path name - self.lvpath = os.path.join('/dev', self.vgname, self.lvname) - self.disksize = self.getconfigitem('disk_size', disksize) - self.ramsize = int(self.getconfigitem('ram_size', ramsize)) - self.isofile = self.getconfigitem('iso_file', isofile) + self.lvpath = os.path.join("/dev", self.vgname, self.lvname) + self.disksize = self.getconfigitem("disk_size", disksize) + self.ramsize = int(self.getconfigitem("ram_size", ramsize)) + self.isofile = self.getconfigitem("iso_file", isofile) # temporary mount point for paused VM persistent filesystem self.mountdir = None - self.etcdir = self.getconfigitem('etc_path') + self.etcdir = self.getconfigitem("etc_path") # TODO: remove this temporary hack - self.FilesRedirection['/usr/local/etc/quagga/Quagga.conf'] = \ - os.path.join(self.getconfigitem('mount_path'), self.etcdir, - 'quagga/Quagga.conf') + self.files_redirection["/usr/local/etc/quagga/Quagga.conf"] = os.path.join( + self.getconfigitem("mount_path"), self.etcdir, "quagga/Quagga.conf") # LxcNode initialization # self.makenodedir() if self.nodedir is None: self.nodedir = os.path.join(session.session_dir, self.name + ".conf") - self.mountdir = self.nodedir + self.getconfigitem('mount_path') + self.mountdir = self.nodedir + self.getconfigitem("mount_path") if not os.path.isdir(self.mountdir): os.makedirs(self.mountdir) self.tmpnodedir = True else: raise Exception("Xen PVM node requires a temporary nodedir") - self.tmpnodedir = False self.bootsh = bootsh if start: self.startup() @@ -197,7 +192,7 @@ class XenNode(PyCoreNode): # from class LxcNode (also SimpleLxcNode) def startup(self): - logger.warn("XEN PVM startup() called: preparing disk for %s" % self.name) + logger.warn("XEN PVM startup() called: preparing disk for %s", self.name) self.lock.acquire() try: if self.up: @@ -205,12 +200,12 @@ class XenNode(PyCoreNode): self.createlogicalvolume() self.createpartitions() persistdev = self.createfilesystems() - subprocess.check_call([constants.MOUNT_BIN, '-t', 'ext4', persistdev, self.mountdir]) - self.untarpersistent(tarname=self.getconfigitem('persist_tar_iso'), + subprocess.check_call([constants.MOUNT_BIN, "-t", "ext4", persistdev, self.mountdir]) + self.untarpersistent(tarname=self.getconfigitem("persist_tar_iso"), iso=True) - self.setrootpassword(pw=self.getconfigitem('root_password')) - self.sethostname(old='UBASE', new=self.name) - self.setupssh(keypath=self.getconfigitem('ssh_key_path')) + self.setrootpassword(pw=self.getconfigitem("root_password")) + self.sethostname(old="UBASE", new=self.name) + self.setupssh(keypath=self.getconfigitem("ssh_key_path")) self.createvm() self.up = True finally: @@ -229,22 +224,22 @@ class XenNode(PyCoreNode): return self.session.services.bootnodeservices(self) - tarname = self.getconfigitem('persist_tar') + tarname = self.getconfigitem("persist_tar") if tarname: self.untarpersistent(tarname=tarname, iso=False) try: subprocess.check_call([constants.UMOUNT_BIN, self.mountdir]) self.unmount_all(self.mountdir) - subprocess.check_call([UDEVADM_PATH, 'settle']) - subprocess.check_call([KPARTX_PATH, '-d', self.lvpath]) + subprocess.check_call([UDEVADM_PATH, "settle"]) + subprocess.check_call([KPARTX_PATH, "-d", self.lvpath]) # time.sleep(5) # time.sleep(1) # unpause VM - logger.warn("XEN PVM boot() unpause domU %s" % self.vmname) - utils.mutecheck_call([XM_PATH, 'unpause', self.vmname]) + logger.warn("XEN PVM boot() unpause domU %s", self.vmname) + utils.mutecheck_call([XM_PATH, "unpause", self.vmname]) self.booted = True finally: @@ -268,25 +263,25 @@ class XenNode(PyCoreNode): try: # RJE XXX what to do here if self.booted: - utils.mutecheck_call([XM_PATH, 'destroy', self.vmname]) + utils.mutecheck_call([XM_PATH, "destroy", self.vmname]) self.booted = False except (OSError, subprocess.CalledProcessError): # ignore this error too, the VM may have exited already logger.exception("error during shutdown") # discard LVM volume - lvmRemoveCount = 0 + lvm_remove_count = 0 while os.path.exists(self.lvpath): try: - subprocess.check_call([UDEVADM_PATH, 'settle']) - utils.mutecall([LVCHANGE_PATH, '-an', self.lvpath]) - lvmRemoveCount += 1 - utils.mutecall([LVREMOVE_PATH, '-f', self.lvpath]) + subprocess.check_call([UDEVADM_PATH, "settle"]) + utils.mutecall([LVCHANGE_PATH, "-an", self.lvpath]) + lvm_remove_count += 1 + utils.mutecall([LVREMOVE_PATH, "-f", self.lvpath]) except OSError: logger.exception("error during shutdown") - if lvmRemoveCount > 1: - logger.warn("XEN PVM shutdown() required %d lvremove executions." % lvmRemoveCount) + if lvm_remove_count > 1: + logger.warn("XEN PVM shutdown() required %d lvremove executions.", lvm_remove_count) self._netif.clear() del self.session @@ -303,8 +298,8 @@ class XenNode(PyCoreNode): """ if os.path.exists(self.lvpath): raise Exception, "LVM volume already exists" - utils.mutecheck_call([LVCREATE_PATH, '--size', self.disksize, - '--name', self.lvname, self.vgname]) + utils.mutecheck_call([LVCREATE_PATH, "--size", self.disksize, + "--name", self.lvname, self.vgname]) def createpartitions(self): """ @@ -313,7 +308,7 @@ class XenNode(PyCoreNode): """ dev = parted.Device(path=self.lvpath) dev.removeFromCache() - disk = parted.freshDisk(dev, 'msdos') + disk = parted.freshDisk(dev, "msdos") constraint = parted.Constraint(device=dev) persist_size = int(0.75 * constraint.maxSize) self.createpartition(device=dev, disk=disk, start=1, @@ -338,14 +333,14 @@ class XenNode(PyCoreNode): Make an ext4 filesystem and swap space. Return the device name for the persistent partition so we can mount it. """ - output = subprocess.Popen([KPARTX_PATH, '-l', self.lvpath], + output = subprocess.Popen([KPARTX_PATH, "-l", self.lvpath], stdout=subprocess.PIPE).communicate()[0] lines = output.splitlines() - persistdev = '/dev/mapper/' + lines[0].strip().split(' ')[0].strip() - swapdev = '/dev/mapper/' + lines[1].strip().split(' ')[0].strip() - subprocess.check_call([KPARTX_PATH, '-a', self.lvpath]) - utils.mutecheck_call([MKFSEXT4_PATH, '-L', 'persist', persistdev]) - utils.mutecheck_call([MKSWAP_PATH, '-f', '-L', 'swap', swapdev]) + persistdev = "/dev/mapper/" + lines[0].strip().split(" ")[0].strip() + swapdev = "/dev/mapper/" + lines[1].strip().split(" ")[0].strip() + subprocess.check_call([KPARTX_PATH, "-a", self.lvpath]) + utils.mutecheck_call([MKFSEXT4_PATH, "-L", "persist", persistdev]) + utils.mutecheck_call([MKSWAP_PATH, "-f", "-L", "swap", swapdev]) return persistdev def untarpersistent(self, tarname, iso): @@ -353,7 +348,8 @@ class XenNode(PyCoreNode): Unpack a persistent template tar file to the mounted mount dir. Uses fsimage library to read from an ISO file. """ - tarname = tarname.replace('%h', self.name) # filename may use hostname + # filename may use hostname + tarname = tarname.replace("%h", self.name) if iso: try: fs = fsimage.open(self.isofile, 0) @@ -375,8 +371,8 @@ class XenNode(PyCoreNode): except IOError: logger.exception("Failed to open tar file: %s", tarname) return - p = subprocess.Popen([TAR_PATH, '-C', self.mountdir, '--numeric-owner', - '-xf', '-'], stdin=subprocess.PIPE) + p = subprocess.Popen([TAR_PATH, "-C", self.mountdir, "--numeric-owner", + "-xf", "-"], stdin=subprocess.PIPE) p.communicate(input=tardata) p.wait() @@ -385,39 +381,38 @@ class XenNode(PyCoreNode): Set the root password by updating the shadow password file that is on the filesystem mounted in the temporary area. """ - saltedpw = crypt.crypt(pw, '$6$' + base64.b64encode(os.urandom(12))) - subprocess.check_call([SED_PATH, '-i', '-e', - '/^root:/s_^root:\([^:]*\):_root:' + saltedpw + ':_', - os.path.join(self.mountdir, self.etcdir, 'shadow')]) + saltedpw = crypt.crypt(pw, "$6$" + base64.b64encode(os.urandom(12))) + subprocess.check_call([SED_PATH, "-i", "-e", + "/^root:/s_^root:\([^:]*\):_root:" + saltedpw + ":_", + os.path.join(self.mountdir, self.etcdir, "shadow")]) def sethostname(self, old, new): """ Set the hostname by updating the hostname and hosts files that reside on the filesystem mounted in the temporary area. """ - subprocess.check_call([SED_PATH, '-i', '-e', 's/%s/%s/' % (old, new), - os.path.join(self.mountdir, self.etcdir, 'hostname')]) - subprocess.check_call([SED_PATH, '-i', '-e', 's/%s/%s/' % (old, new), - os.path.join(self.mountdir, self.etcdir, 'hosts')]) + subprocess.check_call([SED_PATH, "-i", "-e", "s/%s/%s/" % (old, new), + os.path.join(self.mountdir, self.etcdir, "hostname")]) + subprocess.check_call([SED_PATH, "-i", "-e", "s/%s/%s/" % (old, new), + os.path.join(self.mountdir, self.etcdir, "hosts")]) def setupssh(self, keypath): """ Configure SSH access by installing host keys and a system-wide authorized_keys file. """ - sshdcfg = os.path.join(self.mountdir, self.etcdir, 'ssh/sshd_config') - subprocess.check_call([SED_PATH, '-i', '-e', - 's/PermitRootLogin no/PermitRootLogin yes/', sshdcfg]) - sshdir = os.path.join(self.getconfigitem('mount_path'), self.etcdir, - 'ssh') - sshdir = sshdir.replace('/', '\\/') # backslash slashes for use in sed - subprocess.check_call([SED_PATH, '-i', '-e', - 's/#AuthorizedKeysFile %h\/.ssh\/authorized_keys/' + \ - 'AuthorizedKeysFile ' + sshdir + '\/authorized_keys/', + sshdcfg = os.path.join(self.mountdir, self.etcdir, "ssh/sshd_config") + subprocess.check_call([SED_PATH, "-i", "-e", "s/PermitRootLogin no/PermitRootLogin yes/", sshdcfg]) + sshdir = os.path.join(self.getconfigitem("mount_path"), self.etcdir, "ssh") + # backslash slashes for use in sed + sshdir = sshdir.replace("/", "\\/") + subprocess.check_call([SED_PATH, "-i", "-e", + "s/#AuthorizedKeysFile %h\/.ssh\/authorized_keys/" + \ + "AuthorizedKeysFile " + sshdir + "\/authorized_keys/", sshdcfg]) - for f in 'ssh_host_rsa_key', 'ssh_host_rsa_key.pub', 'authorized_keys': + for f in "ssh_host_rsa_key", "ssh_host_rsa_key.pub", "authorized_keys": src = os.path.join(keypath, f) - dst = os.path.join(self.mountdir, self.etcdir, 'ssh', f) + dst = os.path.join(self.mountdir, self.etcdir, "ssh", f) shutil.copy(src, dst) if f[-3:] != "pub": os.chmod(dst, 0600) @@ -428,16 +423,16 @@ class XenNode(PyCoreNode): Instantiate it now, so we can add network interfaces, pause it so we can have the filesystem open for configuration. """ - args = [XM_PATH, 'create', os.devnull, '--paused'] - args.extend(['name=' + self.vmname, 'memory=' + str(self.ramsize)]) - args.append('disk=tap:aio:' + self.isofile + ',hda,r') - args.append('disk=phy:' + self.lvpath + ',hdb,w') - args.append('bootloader=pygrub') - bootargs = '--kernel=/isolinux/vmlinuz --ramdisk=/isolinux/initrd' - args.append('bootargs=' + bootargs) - for action in ('poweroff', 'reboot', 'suspend', 'crash', 'halt'): - args.append('on_%s=destroy' % action) - args.append('extra=' + self.getconfigitem('xm_create_extra')) + args = [XM_PATH, "create", os.devnull, "--paused"] + args.extend(["name=" + self.vmname, "memory=" + str(self.ramsize)]) + args.append("disk=tap:aio:" + self.isofile + ",hda,r") + args.append("disk=phy:" + self.lvpath + ",hdb,w") + args.append("bootloader=pygrub") + bootargs = "--kernel=/isolinux/vmlinuz --ramdisk=/isolinux/initrd" + args.append("bootargs=" + bootargs) + for action in ("poweroff", "reboot", "suspend", "crash", "halt"): + args.append("on_%s=destroy" % action) + args.append("extra=" + self.getconfigitem("xm_create_extra")) utils.mutecheck_call(args) # from class LxcNode @@ -456,7 +451,7 @@ class XenNode(PyCoreNode): def openpausednodefile(self, filename, mode="w"): dirname, basename = os.path.split(filename) if not basename: - raise ValueError, "no basename for filename: " + filename + raise ValueError("no basename for filename: %s" % filename) if dirname and dirname[0] == "/": dirname = dirname[1:] # dirname = dirname.replace("/", ".") @@ -468,16 +463,16 @@ class XenNode(PyCoreNode): # from class LxcNode def nodefile(self, filename, contents, mode=0644): - if filename in self.FilesToIgnore: + if filename in self.files_to_ignore: # self.warn("XEN PVM nodefile(filename=%s) ignored" % [filename]) return - if filename in self.FilesRedirection: - redirFilename = self.FilesRedirection[filename] - logger.warn("XEN PVM nodefile(filename=%s) redirected to %s" % (filename, redirFilename)) - filename = redirFilename + if filename in self.files_redirection: + redirection_filename = self.files_redirection[filename] + logger.warn("XEN PVM nodefile(filename=%s) redirected to %s", filename, redirection_filename) + filename = redirection_filename - logger.warn("XEN PVM nodefile(filename=%s) called" % [filename]) + logger.warn("XEN PVM nodefile(filename=%s) called", filename) self.lock.acquire() if not self.up: self.lock.release() @@ -492,7 +487,7 @@ class XenNode(PyCoreNode): f.write(contents) os.chmod(f.name, mode) f.close() - logger.info("created nodefile: '%s'; mode: 0%o" % (f.name, mode)) + logger.info("created nodefile: %s; mode: 0%o", f.name, mode) finally: self.lock.release() @@ -502,33 +497,33 @@ class XenNode(PyCoreNode): return False # XXX def cmd(self, args, wait=True): - cmdAsString = string.join(args, ' ') - if cmdAsString in self.CmdsToIgnore: + cmd_string = string.join(args, " ") + if cmd_string in self.cmds_to_ignore: # self.warn("XEN PVM cmd(args=[%s]) called and ignored" % cmdAsString) return 0 - if cmdAsString in self.CmdsRedirection: - self.CmdsRedirection[cmdAsString](self) + if cmd_string in self.cmds_redirection: + self.cmds_redirection[cmd_string](self) return 0 - logger("XEN PVM cmd(args=[%s]) called, but not yet implemented" % cmdAsString) + logger("XEN PVM cmd(args=[%s]) called, but not yet implemented", cmd_string) return 0 def cmdresult(self, args): - cmdAsString = string.join(args, ' ') - if cmdAsString in self.CmdsToIgnore: + cmd_string = string.join(args, " ") + if cmd_string in self.cmds_to_ignore: # self.warn("XEN PVM cmd(args=[%s]) called and ignored" % cmdAsString) return 0, "" - logger.warn("XEN PVM cmdresult(args=[%s]) called, but not yet implemented" % cmdAsString) + logger.warn("XEN PVM cmdresult(args=[%s]) called, but not yet implemented", cmd_string) return 0, "" def popen(self, args): - cmdAsString = string.join(args, ' ') - logger.warn("XEN PVM popen(args=[%s]) called, but not yet implemented" % cmdAsString) + cmd_string = string.join(args, " ") + logger.warn("XEN PVM popen(args=[%s]) called, but not yet implemented", cmd_string) return def icmd(self, args): - cmdAsString = string.join(args, ' ') - logger.warn("XEN PVM icmd(args=[%s]) called, but not yet implemented" % cmdAsString) + cmd_string = string.join(args, " ") + logger.warn("XEN PVM icmd(args=[%s]) called, but not yet implemented", cmd_string) return def term(self, sh="/bin/sh"): @@ -537,30 +532,30 @@ class XenNode(PyCoreNode): def termcmdstring(self, sh="/bin/sh"): """ - We may add 'sudo' to the command string because the GUI runs as a + We may add "sudo" to the command string because the GUI runs as a normal user. Use SSH if control interface is available, otherwise use Xen console with a keymapping for easy login. """ controlifc = None for ifc in self.netifs(): - if hasattr(ifc, 'control') and ifc.control == True: + if hasattr(ifc, "control") and ifc.control is True: controlifc = ifc break cmd = "xterm " # use SSH if control interface is available if controlifc: - controlip = controlifc.addrlist[0].split('/')[0] + controlip = controlifc.addrlist[0].split("/")[0] cmd += "-e ssh root@%s" % controlip return cmd - # otherwise use 'xm console' - # pw = self.getconfigitem('root_password') - # cmd += "-xrm 'XTerm*VT100.translations: #override F1: " - # cmd += "string(\"root\\n\") \\n F2: string(\"%s\\n\")' " % pw + # otherwise use "xm console" + # pw = self.getconfigitem("root_password") + # cmd += "-xrm "XTerm*VT100.translations: #override F1: " + # cmd += "string(\"root\\n\") \\n F2: string(\"%s\\n\")" " % pw cmd += "-e sudo %s console %s" % (XM_PATH, self.vmname) return cmd def shcmd(self, cmdstr, sh="/bin/sh"): - logger("XEN PVM shcmd(args=[%s]) called, but not yet implemented" % cmdstr) + logger("XEN PVM shcmd(args=[%s]) called, but not yet implemented", cmdstr) return def mount(self, source, target): @@ -595,8 +590,7 @@ class XenNode(PyCoreNode): PyCoreNode.delnetif(self, ifindex) def newveth(self, ifindex=None, ifname=None, net=None, hwaddr=None): - logger.warn("XEN PVM newveth(ifindex=%s, ifname=%s) called" % - (ifindex, ifname)) + logger.warn("XEN PVM newveth(ifindex=%s, ifname=%s) called", ifindex, ifname) self.lock.acquire() try: @@ -656,8 +650,7 @@ class XenNode(PyCoreNode): addr = self.getaddr(self.ifname(ifindex), rescan=True) for t in addrtypes: if t not in self.valid_deladdrtype: - raise ValueError, "addr type must be in: " + \ - " ".join(self.valid_deladdrtype) + raise ValueError("addr type must be in: " + " ".join(self.valid_deladdrtype)) for a in addr[t]: self.deladdr(ifindex, a) # update cached information @@ -668,10 +661,8 @@ class XenNode(PyCoreNode): # if self.up: # self.cmd([IP_BIN, "link", "set", self.ifname(ifindex), "up"]) - def newnetif(self, net=None, addrlist=[], hwaddr=None, - ifindex=None, ifname=None): - logger.warn("XEN PVM newnetif(ifindex=%s, ifname=%s) called" % - (ifindex, ifname)) + def newnetif(self, net=None, addrlist=[], hwaddr=None, ifindex=None, ifname=None): + logger.warn("XEN PVM newnetif(ifindex=%s, ifname=%s) called", ifindex, ifname) self.lock.acquire() @@ -705,18 +696,18 @@ class XenNode(PyCoreNode): if net is not None: self.attachnet(ifindex, net) - rulefile = os.path.join(self.getconfigitem('mount_path'), + rulefile = os.path.join(self.getconfigitem("mount_path"), self.etcdir, - 'udev/rules.d/70-persistent-net.rules') + "udev/rules.d/70-persistent-net.rules") f = self.openpausednodefile(rulefile, "a") f.write( - '\n# Xen PVM virtual interface #%s %s with MAC address %s\n' % (ifindex, self.ifname(ifindex), hwaddr)) - # Using MAC address as we're now loading PVM net driver "early" - # OLD: Would like to use MAC address, but udev isn't working with paravirtualized NICs. Perhaps the "set hw address" isn't triggering a rescan. + "\n# Xen PVM virtual interface #%s %s with MAC address %s\n" % (ifindex, self.ifname(ifindex), hwaddr)) + # Using MAC address as we"re now loading PVM net driver "early" + # OLD: Would like to use MAC address, but udev isn"t working with paravirtualized NICs. Perhaps the "set hw address" isn"t triggering a rescan. f.write( 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="%s", KERNEL=="eth*", NAME="%s"\n' % ( hwaddr, self.ifname(ifindex))) - # f.write('SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", DEVPATH=="/devices/vif-%s/?*", KERNEL=="eth*", NAME="%s"\n' % (ifindex, self.ifname(ifindex))) + # f.write("SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", DEVPATH=="/devices/vif-%s/?*", KERNEL=="eth*", NAME="%s"\n" % (ifindex, self.ifname(ifindex))) f.close() if hwaddr: @@ -748,7 +739,7 @@ class XenNode(PyCoreNode): # othernode.addnetif(PyCoreNetIf(othernode, otherifname), # othernode.newifindex()) - def addfile(self, srcname, filename): + def addfile(self, srcname, filename, mode=0644): self.lock.acquire() if not self.up: self.lock.release() @@ -758,14 +749,14 @@ class XenNode(PyCoreNode): self.lock.release() raise Exception("Can't access VM file as VM is already running") - if filename in self.FilesToIgnore: + if filename in self.files_to_ignore: # self.warn("XEN PVM addfile(filename=%s) ignored" % [filename]) return - if filename in self.FilesRedirection: - redirFilename = self.FilesRedirection[filename] - logger.warn("XEN PVM addfile(filename=%s) redirected to %s" % (filename, redirFilename)) - filename = redirFilename + if filename in self.files_redirection: + redirection_filename = self.files_redirection[filename] + logger.warn("XEN PVM addfile(filename=%s) redirected to %s", filename, redirection_filename) + filename = redirection_filename try: fin = open(srcname, "r") @@ -776,13 +767,13 @@ class XenNode(PyCoreNode): fout.write(contents) os.chmod(fout.name, mode) fout.close() - logger.info("created nodefile: '%s'; mode: 0%o" % (fout.name, mode)) + logger.info("created nodefile: %s; mode: 0%o", fout.name, mode) finally: self.lock.release() - logger.warn("XEN PVM addfile(filename=%s) called" % [filename]) + logger.warn("XEN PVM addfile(filename=%s) called", filename) - # shcmd = "mkdir -p $(dirname '%s') && mv '%s' '%s' && sync" % \ + # shcmd = "mkdir -p $(dirname "%s") && mv "%s" "%s" && sync" % \ # (filename, srcname, filename) # self.shcmd(shcmd) diff --git a/daemon/core/xen/xenconfig.py b/daemon/core/xen/xenconfig.py index c5cbd390..7e3c6c46 100644 --- a/daemon/core/xen/xenconfig.py +++ b/daemon/core/xen/xenconfig.py @@ -3,10 +3,10 @@ xenconfig.py: Implementation of the XenConfigManager class for managing configurable items for XenNodes. Configuration for a XenNode is available at these three levels: -Global config: XenConfigManager.configs[0] = (type='xen', values) +Global config: XenConfigManager.configs[0] = (type="xen", values) Nodes of this machine type have this config. These are the default values. XenConfigManager.default_config comes from defaults + xen.conf -Node type config: XenConfigManager.configs[0] = (type='mytype', values) +Node type config: XenConfigManager.configs[0] = (type="mytype", values) All nodes of this type have this config. Node-specific config: XenConfigManager.configs[nodenumber] = (type, values) The node having this specific number has this config. @@ -50,27 +50,43 @@ class XenConfigManager(ConfigurableManager): def setconfig(self, nodenum, conftype, values): """ - add configuration values for a node to a dictionary; values are + Add configuration values for a node to a dictionary; values are usually received from a Configuration Message, and may refer to a node for which no object exists yet + + :param int nodenum: node id to configure + :param str conftype: configuration type + :param tuple values: values to configure + :return: None """ + # used for storing the global default config if nodenum is None: - nodenum = 0 # used for storing the global default config + nodenum = 0 return ConfigurableManager.setconfig(self, nodenum, conftype, values) def getconfig(self, nodenum, conftype, defaultvalues): """ - get configuration values for a node; if the values don't exist in + Get configuration values for a node; if the values don"t exist in our dictionary then return the default values supplied; if conftype is None then we return a match on any conftype. + + :param int nodenum: node id to configure + :param str conftype: configuration type + :param tuple defaultvalues: default values to return + :return: configuration for node and config type + :rtype: tuple """ + # used for storing the global default config if nodenum is None: - nodenum = 0 # used for storing the global default config + nodenum = 0 return ConfigurableManager.getconfig(self, nodenum, conftype, defaultvalues) def clearconfig(self, nodenum): """ - remove configuration values for a node + Remove configuration values for a node + + :param int nodenum: node id to clear config + :return: nothing """ ConfigurableManager.clearconfig(self, nodenum) if 0 in self.configs: @@ -87,16 +103,19 @@ class XenConfigManager(ConfigurableManager): def loadconfigfile(self, filename=None): """ Load defaults from the /etc/core/xen.conf file into dict object. + + :param str filename: file name of configuration to load + :return: nothing """ if filename is None: - filename = os.path.join(constants.CORE_CONF_DIR, 'xen.conf') + filename = os.path.join(constants.CORE_CONF_DIR, "xen.conf") cfg = ConfigParser.SafeConfigParser() if filename not in cfg.read(filename): - logger.warn("unable to read Xen config file: %s" % filename) + logger.warn("unable to read Xen config file: %s", filename) return section = "xen" if not cfg.has_section(section): - logger.warn("%s is missing a xen section!" % filename) + logger.warn("%s is missing a xen section!", filename) return self.configfile = dict(cfg.items(section)) # populate default config items from config file entries @@ -105,7 +124,7 @@ class XenConfigManager(ConfigurableManager): for i in range(len(names)): if names[i] in self.configfile: vals[i] = self.configfile[names[i]] - # this sets XenConfigManager.configs[0] = (type='xen', vals) + # this sets XenConfigManager.configs[0] = (type="xen", vals) self.setconfig(None, self.default_config.name, vals) def getconfigitem(self, name, model=None, node=None, value=None): @@ -113,6 +132,12 @@ class XenConfigManager(ConfigurableManager): Get a config item of the given name, first looking for node-specific configuration, then model specific, and finally global defaults. If a value is supplied, it will override any stored config. + + :param str name: name of config item to get + :param model: model config to get + :param node: node config to get + :param value: value to override stored config, if provided + :return: nothing """ if value is not None: return value @@ -122,13 +147,10 @@ class XenConfigManager(ConfigurableManager): (t, v) = self.getconfig(nodenum=n, conftype=model, defaultvalues=None) if n is not None and v is None: # get item from default config for the node type - (t, v) = self.getconfig(nodenum=None, conftype=model, - defaultvalues=None) + (t, v) = self.getconfig(nodenum=None, conftype=model, defaultvalues=None) if v is None: # get item from default config for the machine type - (t, v) = self.getconfig(nodenum=None, - conftype=self.default_config.name, - defaultvalues=None) + (t, v) = self.getconfig(nodenum=None, conftype=self.default_config.name, defaultvalues=None) confignames = self.default_config.getnames() if v and name in confignames: @@ -139,7 +161,7 @@ class XenConfigManager(ConfigurableManager): if name in self.configfile: return self.configfile[name] else: - # logger.warn("missing config item '%s'" % name) + # logger.warn("missing config item "%s"" % name) return None @@ -167,7 +189,7 @@ class XenConfig(Configurable): nodetype = object_name if opaque is not None: - opaque_items = opaque.split(':') + opaque_items = opaque.split(":") if len(opaque_items) != 2: logger.warn("xen config: invalid opaque data in conf message") return None @@ -211,7 +233,7 @@ class XenConfig(Configurable): values = xen.getconfig(node_id, cls.name, defaults)[1] else: # use new values supplied from the conf message - values = values_str.split('|') + values = values_str.split("|") xen.setconfig(node_id, nodetype, values) return reply @@ -222,8 +244,15 @@ class XenConfig(Configurable): Convert this class to a Config API message. Some TLVs are defined by the class, but node number, conf type flags, and values must be passed in. + + :param int flags: configuration flags + :param int node_id: node id + :param int type_flags: type flags + :param int nodetype: node type + :param tuple values: values + :return: configuration message """ - values_str = string.join(values, '|') + values_str = string.join(values, "|") tlvdata = "" tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.NODE.value, node_id) tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.OBJECT.value, cls.name) @@ -231,9 +260,9 @@ class XenConfig(Configurable): datatypes = tuple(map(lambda x: x[1], cls.config_matrix)) tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.DATA_TYPES.value, datatypes) tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.VALUES.value, values_str) - captions = reduce(lambda a, b: a + '|' + b, map(lambda x: x[4], cls.config_matrix)) + captions = reduce(lambda a, b: a + "|" + b, map(lambda x: x[4], cls.config_matrix)) tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.CAPTIONS, captions) - possiblevals = reduce(lambda a, b: a + '|' + b, map(lambda x: x[3], cls.config_matrix)) + possiblevals = reduce(lambda a, b: a + "|" + b, map(lambda x: x[3], cls.config_matrix)) tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.POSSIBLE_VALUES.value, possiblevals) if cls.bitmap is not None: tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.BITMAP.value, cls.bitmap) @@ -251,24 +280,24 @@ class XenDefaultConfig(XenConfig): """ name = "xen" # Configuration items: - # ('name', 'type', 'default', 'possible-value-list', 'caption') + # ("name", "type", "default", "possible-value-list", "caption") config_matrix = [ - ('ram_size', ConfigDataTypes.STRING.value, '256', '', - 'ram size (MB)'), - ('disk_size', ConfigDataTypes.STRING.value, '256M', '', - 'disk size (use K/M/G suffix)'), - ('iso_file', ConfigDataTypes.STRING.value, '', '', - 'iso file'), - ('mount_path', ConfigDataTypes.STRING.value, '', '', - 'mount path'), - ('etc_path', ConfigDataTypes.STRING.value, '', '', - 'etc path'), - ('persist_tar_iso', ConfigDataTypes.STRING.value, '', '', - 'iso persist tar file'), - ('persist_tar', ConfigDataTypes.STRING.value, '', '', - 'persist tar file'), - ('root_password', ConfigDataTypes.STRING.value, 'password', '', - 'root password'), + ("ram_size", ConfigDataTypes.STRING.value, "256", "", + "ram size (MB)"), + ("disk_size", ConfigDataTypes.STRING.value, "256M", "", + "disk size (use K/M/G suffix)"), + ("iso_file", ConfigDataTypes.STRING.value, "", "", + "iso file"), + ("mount_path", ConfigDataTypes.STRING.value, "", "", + "mount path"), + ("etc_path", ConfigDataTypes.STRING.value, "", "", + "etc path"), + ("persist_tar_iso", ConfigDataTypes.STRING.value, "", "", + "iso persist tar file"), + ("persist_tar", ConfigDataTypes.STRING.value, "", "", + "persist tar file"), + ("root_password", ConfigDataTypes.STRING.value, "password", "", + "root password"), ] config_groups = "domU properties:1-%d" % len(config_matrix)