def prepareData(self): ipv4 = self.guest.getIPv4() ipv6 = self.guest.getIPv6() self.values['dns-servers'] = self.getDNSServers() self.values['domain'] = DC.get("network", "domain") config = "" config += self.config.get("settings", "all", False, self.values) ipv4Values = {} ipv6Values = {} if not ipv4: ipv4Settings = self.config.get("settings", "ipv4-disabled", False, ipv4Values) elif isinstance(ipv4, IP.IPv4): ipv4Values = { "address": ipv4.getAddress(), "netmask-full": ipv4.getLongNetmask(), "netmask-prefix": ipv4.getShortNetmask(), "gateway": ipv4.getGateway(), "domain": DC.get("network", "domain"), } ipv4Settings = self.config.get("settings", "ipv4-static", False, ipv4Values) elif isinstance(ipv4, IP.DHCP): ipv4Settings = self.config.get("settings", "ipv4-dhcp", False, ipv4Values) config += "%s\n" % ipv4Settings if not ipv6: ipv6Settings = self.config.get("settings", "ipv6-disabled", False, ipv6Values) elif isinstance(ipv6, IP.IPv6): ipv6Values = { "address": ipv6.getAddress(), "netmask-full": ipv6.getLongNetmask(), "netmask-prefix": ipv6.getShortNetmask(), "gateway": ipv6.getGateway(), "domain": DC.get("network", "domain"), } ipv6Settings = self.config.get("settings", "ipv6-static", False, ipv6Values) elif isinstance(ipv6, IP.DHCP): ipv6Settings = self.config.get("settings", "ipv6-dhcp", False, ipv6Values) config += "%s\n" % ipv6Settings return config
class Httpd: #defaultCmd = "/root/svn/xchury1_bp/httpd.py %(path)s %(port)i" defaultCmd = DC.get("httpd", "command", True) ports = eval(DC.get("httpd", "ports")) def __init__(self, path, guest, command=defaultCmd): self.path = path self.guest = guest self.command = command self.process = None self.port = Httpd.getPort() def __str__(self): #hostIP = System.getHostPrivateIP("installvm") hostIP = self.guest.network.network.getIPv4Address() return "http://%s:%i" % (hostIP, self.port) @staticmethod def getPort(): if Httpd.ports: port = Httpd.ports[0] Httpd.ports = Httpd.ports[1:] return port else: return random.randrange(20000, 40000) def start(self): values = {'path': self.path, 'port': self.port} devnull = open("/dev/null", "w") self.process = subprocess.Popen(self.command % values, shell=True, stdout=devnull, stderr=devnull) return self.process def kill(self): Httpd.ports.append(self.port) return self.process.kill() def running(self): return self.process and self.process.poll() == None
def create(self): conn = libvirt.open(DC.get("virsh", "connect")) try: storagePool = conn.storagePoolLookupByName(self.pool) storagePool.refresh(0) except: Logging.errorExit("There is no '%s' libvirt storage pool." % self.pool) path = os.path.basename(self.path) size = Units(self.size).convertTo("B") diskXML = """ <volume> <name>%s</name> <capacity>%i</capacity> <allocation>0</allocation> <target> <format type='raw'/> </target> </volume> """ diskXML = diskXML % (path, size) try: storage = storagePool.createXML(diskXML, 0) except Exception as e: Logging.errorExit("%s (name: %s)" % (str(e), path)) return storage
def getTotalMemory(filePath=DC.get("system", "memory-info")): if os.path.exists(filePath): memfree = System.getLineStartsWith(filePath, "MemTotal") line = memfree.split(":") if len(line) == 2: return line[1].strip() return None
def checkCPU(filePath=DC.get("system", "cpu-info")): if os.path.exists(filePath): flags = System.getLineStartsWith(filePath, "flags") line = flags.split(":") if len(line) == 2: return "vmx" in line[1] or "svm" in line[1] return None
def start(self): master, slave = pty.openpty() self.stdin = os.fdopen(master, "w") self.stdout = tempfile.NamedTemporaryFile("w") virshStart = DC.get("virsh", "start", False, self.values) self.process = subprocess.Popen(virshStart, shell=True, stdin=slave, stdout=self.stdout, stderr=self.stdout, close_fds=True)
def create(self): Logging.info("Creating the network ...") conn = libvirt.open(DC.get("virsh", "connect")) configFile = file(self.config, "r") #print configFile.read() self.network = conn.networkDefineXML(configFile.read()) self.network.setAutostart(1) self.network.create() return
def insertDNS(self, dnsDict): conn = libvirt.open(DC.get("virsh", "connect")) xmlDesc = self.network.XMLDesc(0) Logging.debug("Inserting DNS entries: %s" % str(dnsDict)) localDns = self.makeDNS(dnsDict) networkXml = xml.parseString(xmlDesc) dns = networkXml.getElementsByTagName("dns") if dns: dns = dns[0] for entry in localDns.getElementsByTagName("host"): dns.appendChild(entry) else: networkXml.documentElement.appendChild(localDns) self.network.destroy() self.network.undefine() self.network = conn.networkDefineXML( networkXml.documentElement.toxml()) self.network.setAutostart(1) self.network.create() values = { 'addr': self.getIPv6Address(), 'prefix': self.getIPv6Prefix(), 'interface': self.getInterface() } if (DC.has_option("network", "manual-route") and DC.get("network", "manual-route", True)): cmd = DC.get("network", "manual-route", False, values) cmd = cmd.replace("\n", " ") subprocess.Popen(cmd, shell=True) else: Logging.warning("Manual route not set. Skipping.") return
def check(self): network = self.parseName() Logging.info("Checking network '%s'..." % network) conn = libvirt.open(DC.get("virsh", "connect")) networks = conn.listNetworks() if not network in networks: return True return False
def insertDNS(self, dnsDict): conn = libvirt.open(DC.get("virsh", "connect")) xmlDesc = self.network.XMLDesc(0) Logging.debug("Inserting DNS entries: %s" % str(dnsDict)) localDns = self.makeDNS(dnsDict) networkXml = xml.parseString(xmlDesc) dns = networkXml.getElementsByTagName("dns") if dns: dns = dns[0] for entry in localDns.getElementsByTagName("host"): dns.appendChild(entry) else: networkXml.documentElement.appendChild(localDns) self.network.destroy() self.network.undefine() self.network = conn.networkDefineXML(networkXml.documentElement.toxml()) self.network.setAutostart(1) self.network.create() values = {'addr': self.getIPv6Address(), 'prefix': self.getIPv6Prefix(), 'interface': self.getInterface()} if (DC.has_option("network", "manual-route") and DC.get("network", "manual-route", True)): cmd = DC.get("network", "manual-route", False, values) cmd = cmd.replace("\n", " ") subprocess.Popen(cmd, shell=True) else: Logging.warning("Manual route not set. Skipping.") return
def stop(self): self.stdin.write("\n\npoweroff\n\n") for i in xrange(0, 30): if self.process.poll() != None: break if i > 20: virshDestroy = DC.get("virsh", "destroy", False, self.values) subprocess.Popen(virshDestroy, shell=True) time.sleep(1)
def getHostPrivateIP(network="default"): conn = libvirt.open(DC.get("virsh", "connect")) virtNetwork = conn.networkLookupByName(network) #process = subprocess.Popen(command, shell=True, stdin=None, #stdout=subprocess.PIPE, stderr=subprocess.PIPE) #process.wait() document = xml.parseString(virtNetwork.XMLDesc(0)) ip = document.getElementsByTagName("ip") if ip: ip = filter(lambda x: not x.hasAttribute("family") or x.getAttribute("family") == "ipv4", ip) return ip[0].getAttribute("address")
def getHostPrivateIP(network="default"): conn = libvirt.open(DC.get("virsh", "connect")) virtNetwork = conn.networkLookupByName(network) #process = subprocess.Popen(command, shell=True, stdin=None, #stdout=subprocess.PIPE, stderr=subprocess.PIPE) #process.wait() document = xml.parseString(virtNetwork.XMLDesc(0)) ip = document.getElementsByTagName("ip") if ip: ip = filter( lambda x: not x.hasAttribute("family") or x.getAttribute( "family") == "ipv4", ip) return ip[0].getAttribute("address")
def makeDNS(self, dnsDict): document = xml.Document() dns = document.createElement("dns") for host in dnsDict: hostXml = document.createElement("host") hostXml.setAttribute("ip", host) hostname1 = document.createTextNode("%s.%s" % (dnsDict[host], DC.get("network", "domain"))) hostname2 = document.createTextNode("%s" % dnsDict[host]) hostnameXml1 = document.createElement("hostname") hostnameXml1.appendChild(hostname1) hostnameXml2 = document.createElement("hostname") hostnameXml2.appendChild(hostname2) hostXml.appendChild(hostnameXml1) hostXml.appendChild(hostnameXml2) dns.appendChild(hostXml) return dns
def makeDNS(self, dnsDict): document = xml.Document() dns = document.createElement("dns") for host in dnsDict: hostXml = document.createElement("host") hostXml.setAttribute("ip", host) hostname1 = document.createTextNode( "%s.%s" % (dnsDict[host], DC.get("network", "domain"))) hostname2 = document.createTextNode("%s" % dnsDict[host]) hostnameXml1 = document.createElement("hostname") hostnameXml1.appendChild(hostname1) hostnameXml2 = document.createElement("hostname") hostnameXml2.appendChild(hostname2) hostXml.appendChild(hostnameXml1) hostXml.appendChild(hostnameXml2) dns.appendChild(hostXml) return dns
class System: hostMemory = Units(DC.get("system", "host-memory")).getValue() @staticmethod def getLineStartsWith(filePath, text): try: fileObj = open(filePath) except: return None for line in fileObj: if line.lower().startswith(text.lower()): fileObj.close() return line fileObj.close() return None @staticmethod def getTotalMemory(filePath=DC.get("system", "memory-info")): if os.path.exists(filePath): memfree = System.getLineStartsWith(filePath, "MemTotal") line = memfree.split(":") if len(line) == 2: return line[1].strip() return None @staticmethod def checkCPU(filePath=DC.get("system", "cpu-info")): if os.path.exists(filePath): flags = System.getLineStartsWith(filePath, "flags") line = flags.split(":") if len(line) == 2: return "vmx" in line[1] or "svm" in line[1] return None @staticmethod def getFreeSpace(path): if os.path.exists(path): vfstat = os.statvfs(path) return int(vfstat.f_bavail * vfstat.f_frsize) return None @staticmethod def checkEnoughMemory(guests): totalMemory = Units(System.getTotalMemory()).getValue() memoryForGuests = 0.0 memory = map(lambda g: Units(g.getMemorySize()).getValue(), guests) if None in memory: raise ValueError("Some of guests hasn't set memory size" " or cannot be parsed.") memoryForGuests = reduce(lambda x, y: x + y, memory) return (totalMemory - memoryForGuests) > System.hostMemory @staticmethod def getHostPrivateIP(network="default"): conn = libvirt.open(DC.get("virsh", "connect")) virtNetwork = conn.networkLookupByName(network) #process = subprocess.Popen(command, shell=True, stdin=None, #stdout=subprocess.PIPE, stderr=subprocess.PIPE) #process.wait() document = xml.parseString(virtNetwork.XMLDesc(0)) ip = document.getElementsByTagName("ip") if ip: ip = filter( lambda x: not x.hasAttribute("family") or x.getAttribute( "family") == "ipv4", ip) return ip[0].getAttribute("address")
class HttpIso(LocalIso): #defaultTempStorage = "/tmp" defaultTempStorage = DC.get("location", "iso-temp-storage") def __init__(self, path, mountPoint=LocalIso.defaultMountPoint, tempStorage=defaultTempStorage): LocalIso.__init__(self, path, mountPoint) self.tempStorage = tempStorage self.downloaded = False def download(self): fileName = self.path.rsplit("/", 1) filePath = "%s/%i-%s" % (self.tempStorage, hash(self), fileName[1]) if os.path.exists(filePath): self.path = filePath self.downloaded = True return self.downloaded Logging.debug("Trying download %s to %s." % (self.path, filePath)) try: httpRequest = urllib2.urlopen(self.path) except urllib2.HTTPError as e: return None if (not os.path.exists(self.tempStorage) or not os.access(self.tempStorage, os.W_OK) or System.getFreeSpace(self.tempStorage) < int(httpRequest.info().get("Content-Length"))): return None try: iso = file(filePath, "w") while 1: buf = httpRequest.read(16*1024) if not buf: break iso.write(buf) iso.close() except IOError as e: return None self.path = filePath self.downloaded = os.path.exists(filePath) return self.downloaded def prepare(self): if not self.downloaded: self.download() return LocalIso.prepare(self) def finalize(self): return LocalIso.finalize(self) def __del__(self): if self.downloaded and os.path.exists(self.path): Logging.debug("Trying unlink file %s." % self.path) os.unlink(self.path)
class LocalIso(_Image): #defaultMountPoint = "/media/install-virt" defaultMountPoint = DC.get("location", "mount-point") def __init__(self, path, mountPoint=defaultMountPoint): _Image.__init__(self, path) self.createdMountPoint = False self.mountPoint = mountPoint def getInstallPath(self): return self.mountPoint def mount(self): if not os.path.exists(self.mountPoint) or not os.path.isdir(self.mountPoint): Logging.debug("Creating mounting point: %s" % self.mountPoint) os.makedirs(self.mountPoint) self.createdMountPoint = True if not os.path.exists(self.getPath()): raise IOError("Path '%s' does not exists." % self.getPath()) Logging.debug("Mounting %s to %s." % (self.getPath(), self.mountPoint)) mountProcess = subprocess.Popen(["/bin/mount", '-o', 'loop', self.getPath(), self.mountPoint]) mountProcess.wait() if mountProcess.returncode == 0 and len(os.listdir(self.mountPoint)) > 0: treeinfo = "%s/.treeinfo" % self.mountPoint if not os.path.exists(treeinfo): Logging.warn("The image doesn't contain .treeinfo file.") else: cp = ConfigParser.ConfigParser() cp.read(treeinfo) if cp.has_section("general") and cp.has_option("general", "arch"): arch = cp.get("general", "arch") imagesArch = "images-%s" % arch if cp.has_section(imagesArch): if (not cp.has_option(imagesArch, "kernel") or not cp.has_option(imagesArch, "initrd")): raise IOError("There's no kernel or initrd option" " in '%s' section in .treeinfo file." % imagesArch) return True return False def umount(self): if os.path.exists(self.mountPoint) and os.path.isdir(self.mountPoint): Logging.debug("Unmounting %s." % self.mountPoint) mountProcess = subprocess.Popen(["/bin/umount", self.mountPoint]) mountProcess.wait() if mountProcess.returncode == 0 and len(os.listdir(self.mountPoint)) == 0: if self.createdMountPoint: Logging.debug("Deleting mounting point: %s" % self.mountPoint) os.rmdir(self.mountPoint) self.createdMountPoint = False return True return False def prepare(self): return self.mount() def finalize(self): return self.umount() def runHttpd(self): return True
class VirtInstall: #defaultInstall = ("/usr/bin/virt-install" #" --name '%(hostname)s'" #" --ram %(memorysize)i" #" --vcpus %(vcpus)i" #" --location '%(location)s'" #" --disk '%(storage)s'" #" --network '%(network)s'" #" --graphics none" #" --extra-args 'ks=%(kspath)s console=tty0 console=ttyS0,115200'" ##" --memballoon none" #" --wait 120" #" --noreboot") #defaultDestroy = "/usr/bin/virsh destroy %(hostname)s" #defaultLog = "/tmp/installVM-%(hostname)s.log" #defaultKsFile = "/root/svn/xchury1_bp/ks/fedora18.cfg" defaultInstall = DC.get("virt-install", "install", True) defaultDestroy = DC.get("virsh", "destroy", True) defaultLog = DC.get("virt-install", "log", True) defaultKsFile = DC.get("virt-install", "default-ks") def __init__(self, guest, cmdInstall=defaultInstall, cmdDestroy=defaultDestroy, log=defaultLog, ksFile=defaultKsFile): self.guest = guest self.cmdInstall = cmdInstall self.cmdDestroy = cmdDestroy self.log = log self.ksFile = ksFile self.values = {} def install(self, handler=DefaultHandler): self.setValues() destroy = None servers = self.startHttpd() master, slave = pty.openpty() stdin = os.fdopen(master, "w") logPath = self.log % self.values Logging.debug("Trying write install log of VM '%s' to %s." % (self.guest.getHostName(), logPath)) stdout = open(logPath, "w") try: self.cmdInstall = self.cmdInstall.replace("\n", " ") Logging.info("Trying install guest '%s'..." % self.guest.getHostName()) Logging.debug(self.cmdInstall % self.values) process = subprocess.Popen(self.cmdInstall % self.values, shell=True, stdin=slave, stdout=stdout, stderr=stdout, close_fds=True) analyzator = handler(stdin, stdout, process) analyzator.handle() except InstallationError as e: destroy = subprocess.Popen(self.cmdDestroy % self.values, shell=True) Logging.info("Check installation log for details: %s" % logPath) raise e finally: if servers[0]: servers[0].kill() if servers[1]: servers[1].kill() if destroy: return not destroy.wait() Logging.info("Guest '%s' installed." % self.guest.getHostName()) return def setValues(self): self.values = { "hostname": self.guest.getHostName(), "memorysize": Units(self.guest.getMemorySize()).convertTo("MB"), "storage": self.guest.getStorageFile(), "vcpus": self.guest.getVcpuCount() or 1, "network": self.guest.getNetwork(), } def startHttpd(self): locationHttpd = ksHttpd = None imageFile = self.guest.getImageFile() ksFile = self.guest.getKsFile() if imageFile.runHttpd(): locationHttpd = Httpd(imageFile.getInstallPath(), self.guest) locationHttpd.start() self.values["location"] = str(locationHttpd) else: self.values["location"] = imageFile.getInstallPath() if ksFile and ksFile.startswith("http://"): self.values["kspath"] = ksFile else: ksFile = ksFile if ksFile else self.ksFile if (not os.path.exists(ksFile) or not os.access(ksFile, os.R_OK)): raise InstallationError("Kickstart file does not exists!") ksHttpd = Httpd(os.path.dirname(ksFile), self.guest) ksHttpd.start() self.values["kspath"] = "%s/%s" % (ksHttpd, os.path.basename(ksFile)) if ((locationHttpd and not locationHttpd.running()) or (ksHttpd and not ksHttpd.running())): raise InstallationError("Httpd for installation is not running." " Used port is propablby allocated" " by another process.") return (locationHttpd, ksHttpd)
def getAddresses(self): conn = libvirt.open(DC.get("virsh", "connect")) xmlDescStr = self.network.XMLDesc(0) xmlDesc = xml.parseString(xmlDescStr) return xmlDesc.getElementsByTagName("ip")
class Network: #defaultConfig = "../etc/network.xml" defaultConfig = DC.get("network", "config") def __init__(self, config=defaultConfig): self.config = config self.network = None def getAddresses(self): conn = libvirt.open(DC.get("virsh", "connect")) xmlDescStr = self.network.XMLDesc(0) xmlDesc = xml.parseString(xmlDescStr) return xmlDesc.getElementsByTagName("ip") def _getIPInformation(self, filterFunction): addresses = self.getAddresses() if addresses: ip = filter(filterFunction, addresses) return ip[0] def _getIPAddress(self, filterFunction): return self._getIPInformation(filterFunction).getAttribute("address") def _getIPv6Prefix(self, filterFunction): return self._getIPInformation(filterFunction).getAttribute("prefix") def getIPv4Address(self): return self._getIPAddress(lambda x: not x.hasAttribute("family") or x. getAttribute("family") == "ipv4") def getIPv6Address(self): return self._getIPAddress(lambda x: x.getAttribute("family") == "ipv6") def getIPv6Prefix(self): return self._getIPv6Prefix( lambda x: x.getAttribute("family") == "ipv6") def getInterface(self): xmlDesc = self.network.XMLDesc(0) networkXml = xml.parseString(xmlDesc) bridges = networkXml.getElementsByTagName("bridge") if bridges: bridge = bridges[0] return bridge.getAttribute("name") def parseName(self): def parseElementData(element): textNodes = filter(lambda x: x.nodeType == x.TEXT_NODE, element.childNodes) data = map(lambda x: x.data.strip(), textNodes) return "".join(data) configFile = file(self.config, "r") xmlConfig = xml.parse(configFile) name = xmlConfig.getElementsByTagName("name") return parseElementData(name[0]) def check(self): network = self.parseName() Logging.info("Checking network '%s'..." % network) conn = libvirt.open(DC.get("virsh", "connect")) networks = conn.listNetworks() if not network in networks: return True return False def create(self): Logging.info("Creating the network ...") conn = libvirt.open(DC.get("virsh", "connect")) configFile = file(self.config, "r") #print configFile.read() self.network = conn.networkDefineXML(configFile.read()) self.network.setAutostart(1) self.network.create() return def makeDNS(self, dnsDict): document = xml.Document() dns = document.createElement("dns") for host in dnsDict: hostXml = document.createElement("host") hostXml.setAttribute("ip", host) hostname1 = document.createTextNode( "%s.%s" % (dnsDict[host], DC.get("network", "domain"))) hostname2 = document.createTextNode("%s" % dnsDict[host]) hostnameXml1 = document.createElement("hostname") hostnameXml1.appendChild(hostname1) hostnameXml2 = document.createElement("hostname") hostnameXml2.appendChild(hostname2) hostXml.appendChild(hostnameXml1) hostXml.appendChild(hostnameXml2) dns.appendChild(hostXml) return dns def insertDNS(self, dnsDict): conn = libvirt.open(DC.get("virsh", "connect")) xmlDesc = self.network.XMLDesc(0) Logging.debug("Inserting DNS entries: %s" % str(dnsDict)) localDns = self.makeDNS(dnsDict) networkXml = xml.parseString(xmlDesc) dns = networkXml.getElementsByTagName("dns") if dns: dns = dns[0] for entry in localDns.getElementsByTagName("host"): dns.appendChild(entry) else: networkXml.documentElement.appendChild(localDns) self.network.destroy() self.network.undefine() self.network = conn.networkDefineXML( networkXml.documentElement.toxml()) self.network.setAutostart(1) self.network.create() values = { 'addr': self.getIPv6Address(), 'prefix': self.getIPv6Prefix(), 'interface': self.getInterface() } if (DC.has_option("network", "manual-route") and DC.get("network", "manual-route", True)): cmd = DC.get("network", "manual-route", False, values) cmd = cmd.replace("\n", " ") subprocess.Popen(cmd, shell=True) else: Logging.warning("Manual route not set. Skipping.") return