diff options
Diffstat (limited to 'tools/laas-fog/source/domain.py')
-rw-r--r-- | tools/laas-fog/source/domain.py | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/tools/laas-fog/source/domain.py b/tools/laas-fog/source/domain.py new file mode 100644 index 00000000..6f00239a --- /dev/null +++ b/tools/laas-fog/source/domain.py @@ -0,0 +1,244 @@ +""" +############################################################################# +#Copyright 2017 Parker Berberian and others # +# # +#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 xml.dom +import xml.dom.minidom +import yaml + + +class Domain: + """ + This class defines a libvirt vm abstraction that can parse our simple + config file and add all necessary boiler plate and info to write a full xml + definition of itself for libvirt. + """ + + def __init__(self, propertiesDict): + """ + init function. + properiesDict should be one of the dictionaries returned by the static + method parseConfigFile + """ + self.name = propertiesDict['name'] + self.memory = propertiesDict['memory'] + self.vcpus = propertiesDict['vcpus'] + self.disk = propertiesDict['disk'] + self.iso = propertiesDict['iso'] + # the vm will either boot from an iso or pxe + self.netBoot = not self.iso['used'] + self.interfaces = propertiesDict['interfaces'] + + def toXML(self): + """ + combines the given configuration with a lot of + boiler plate to create a valid libvirt xml + definition of a domain. + returns a string + """ + definition = xml.dom.minidom.parseString("<domain>\n</domain>") + definition.documentElement.setAttribute('type', 'kvm') + + nameElem = definition.createElement('name') + nameElem.appendChild(definition.createTextNode(self.name)) + definition.documentElement.appendChild(nameElem) + + memElem = definition.createElement('memory') + memElem.appendChild(definition.createTextNode(str(self.memory))) + definition.documentElement.appendChild(memElem) + + curMemElem = definition.createElement('currentMemory') + curMemElem.appendChild(definition.createTextNode(str(self.memory))) + definition.documentElement.appendChild(curMemElem) + + vcpuElem = definition.createElement('vcpu') + vcpuElem.appendChild(definition.createTextNode(str(self.vcpus))) + definition.documentElement.appendChild(vcpuElem) + + osElem = definition.createElement('os') + + typeElem = definition.createElement('type') + typeElem.setAttribute('arch', 'x86_64') + typeElem.appendChild(definition.createTextNode('hvm')) + osElem.appendChild(typeElem) + + if self.netBoot: + bootElem = definition.createElement('boot') + bootElem.setAttribute('dev', 'network') + osElem.appendChild(bootElem) + + bootElem = definition.createElement('boot') + bootElem.setAttribute('dev', 'hd') + osElem.appendChild(bootElem) + + if self.iso['used']: + bootElem = definition.createElement('boot') + bootElem.setAttribute('dev', 'cdrom') + osElem.appendChild(bootElem) + + definition.documentElement.appendChild(osElem) + + featureElem = definition.createElement('feature') + featureElem.appendChild(definition.createElement('acpi')) + featureElem.appendChild(definition.createElement('apic')) + + definition.documentElement.appendChild(featureElem) + + cpuElem = definition.createElement('cpu') + cpuElem.setAttribute('mode', 'custom') + cpuElem.setAttribute('match', 'exact') + modelElem = definition.createElement('model') + modelElem.appendChild(definition.createTextNode('Broadwell')) + cpuElem.appendChild(modelElem) + + definition.documentElement.appendChild(cpuElem) + + clockElem = definition.createElement('clock') + clockElem.setAttribute('offset', 'utc') + + timeElem = definition.createElement('timer') + timeElem.setAttribute('name', 'rtc') + timeElem.setAttribute('tickpolicy', 'catchup') + clockElem.appendChild(timeElem) + + timeElem = definition.createElement('timer') + timeElem.setAttribute('name', 'pit') + timeElem.setAttribute('tickpolicy', 'delay') + clockElem.appendChild(timeElem) + + timeElem = definition.createElement('timer') + timeElem.setAttribute('name', 'hpet') + timeElem.setAttribute('present', 'no') + clockElem.appendChild(timeElem) + + definition.documentElement.appendChild(clockElem) + + poweroffElem = definition.createElement('on_poweroff') + poweroffElem.appendChild(definition.createTextNode('destroy')) + + definition.documentElement.appendChild(poweroffElem) + + rebootElem = definition.createElement('on_reboot') + rebootElem.appendChild(definition.createTextNode('restart')) + + definition.documentElement.appendChild(rebootElem) + + crashElem = definition.createElement('on_reboot') + crashElem.appendChild(definition.createTextNode('restart')) + + definition.documentElement.appendChild(crashElem) + + pmElem = definition.createElement('pm') + memElem = definition.createElement('suspend-to-mem') + memElem.setAttribute('enabled', 'no') + pmElem.appendChild(memElem) + diskElem = definition.createElement('suspend-to-disk') + diskElem.setAttribute('enabled', 'no') + pmElem.appendChild(diskElem) + + definition.documentElement.appendChild(pmElem) + + deviceElem = definition.createElement('devices') + + emuElem = definition.createElement('emulator') + emuElem.appendChild(definition.createTextNode('/usr/libexec/qemu-kvm')) + deviceElem.appendChild(emuElem) + + diskElem = definition.createElement('disk') + diskElem.setAttribute('type', 'file') + diskElem.setAttribute('device', 'disk') + + driverElem = definition.createElement('driver') + driverElem.setAttribute('name', 'qemu') + driverElem.setAttribute('type', 'qcow2') + diskElem.appendChild(driverElem) + + sourceElem = definition.createElement('source') + sourceElem.setAttribute('file', self.disk) + diskElem.appendChild(sourceElem) + + targetElem = definition.createElement('target') + targetElem.setAttribute('dev', 'hda') + targetElem.setAttribute('bus', 'ide') + diskElem.appendChild(targetElem) + + deviceElem.appendChild(diskElem) + + if self.iso['used']: + diskElem = definition.createElement('disk') + diskElem.setAttribute('type', 'file') + diskElem.setAttribute('device', 'cdrom') + + driverElem = definition.createElement('driver') + driverElem.setAttribute('name', 'qemu') + driverElem.setAttribute('type', 'raw') + diskElem.appendChild(driverElem) + + sourceElem = definition.createElement('source') + sourceElem.setAttribute('file', self.iso['location']) + diskElem.appendChild(sourceElem) + + targetElem = definition.createElement('target') + targetElem.setAttribute('dev', 'hdb') + targetElem.setAttribute('bus', 'ide') + diskElem.appendChild(targetElem) + + diskElem.appendChild(definition.createElement('readonly')) + deviceElem.appendChild(diskElem) + + for iface in self.interfaces: + ifaceElem = definition.createElement('interface') + ifaceElem.setAttribute('type', iface['type']) + sourceElem = definition.createElement('source') + sourceElem.setAttribute(iface['type'], iface['name']) + modelElem = definition.createElement('model') + modelElem.setAttribute('type', 'e1000') + ifaceElem.appendChild(sourceElem) + ifaceElem.appendChild(modelElem) + deviceElem.appendChild(ifaceElem) + + graphicElem = definition.createElement('graphics') + graphicElem.setAttribute('type', 'vnc') + graphicElem.setAttribute('port', '-1') + deviceElem.appendChild(graphicElem) + + consoleElem = definition.createElement('console') + consoleElem.setAttribute('type', 'pty') + deviceElem.appendChild(consoleElem) + + definition.documentElement.appendChild(deviceElem) + return definition.toprettyxml() + + def writeXML(self, filePath): + """ + writes this domain's xml definition to the given file. + """ + f = open(filePath, 'w') + f.write(self.toXML()) + f.close() + + @staticmethod + def parseConfigFile(path): + """ + parses the domains config file + """ + configFile = open(path, 'r') + try: + config = yaml.safe_load(configFile) + except Exception: + print "Invalid domain configuration. exiting" + return config |