def _deploy_vm(vm_parameters, logger=None): from opennode.cli import actions storage_pool = actions.storage.get_default_pool() if storage_pool is None: raise Exception("Storage pool not defined") assert type( vm_parameters) is dict, 'Parameters must be a dict: %s' % vm_parameters vm_type = vm_parameters['vm_type'] template = vm_parameters['template_name'] # convert diskspace from MBs to GBs if 'disk' in vm_parameters: assert float(vm_parameters['disk']) > 1 and float(vm_parameters['disk']) < 600,\ 'Provided disk size is strange - MB vs GB issue?' if not template: if logger: logger("Cannot deploy because template is '%s'" % (template)) raise Exception("Cannot deploy because template is '%s'" % (template)) if vm_type == 'openvz': uuid = vm_parameters['uuid'] try: conn = libvirt.open('openvz:///system') deployed_uuid_list = [ivm['uuid'] for ivm in _list_vms(conn)] if uuid in deployed_uuid_list: msg = ( 'Deployment failed: a VM with UUID %s is already deployed ' '(%s)' % (uuid, deployed_uuid_list)) logging.error(msg) return logging.info('Deploying %s: %s', uuid, deployed_uuid_list) finally: conn.close() ovf_file = OvfFile( os.path.join(get_pool_path(storage_pool), vm_type, "unpacked", template + ".ovf")) vm = actions.vm.get_module(vm_type) settings = vm.get_ovf_template_settings(ovf_file) settings.update(vm_parameters) for disk in settings.get("disks", []): if disk["deploy_type"] == "file": volume_name = disk.get("source_file") or "disk" disk["source_file"] = '%s--%s.%s' % ( volume_name, settings["uuid"], disk.get('template_format', 'qcow2')) if not get_config().getboolean('general', 'disable_vm_sys_adjustment', False): errors = vm.adjust_setting_to_systems_resources(settings) if errors: if logger: logger("Got %s" % (errors, )) raise Exception("got errors %s" % (errors, )) vm.deploy(settings, storage_pool)
def get_active_template_settings(vm_name, storage_pool): """ Reads ovf settings of the specified VM """ ovf_fnm = path.join(get_pool_path(storage_pool), "openvz", "unpacked", get_template_name(vm_name) + ".ovf") if path.exists(ovf_fnm): ovf_file = OvfFile(ovf_fnm) return get_ovf_template_settings(ovf_file) else: return read_default_ovf_settings()
def get_template_info(template_name, vm_type, storage_pool=None): config = get_config() if not storage_pool: storage_pool = config.getstring('general', 'default-storage-pool') ovf_file = OvfFile(os.path.join(storage.get_pool_path(storage_pool), vm_type, "unpacked", template_name + ".ovf")) vm = vm_ops.get_module(vm_type) template_settings = vm.get_ovf_template_settings(ovf_file) # XXX handle modification to system params #errors = vm.adjust_setting_to_systems_resources(template_settings) return template_settings
def _generate_ovf_file(vm_settings): """ Prepare OVF XML configuration file from Libvirt's KVM xml_dump. @return: KVM VM configuration in OVF standard @rtype: DOM Document """ ovf = OvfFile() # Workaround for broken OvfFile.__init__ ovf.files = [] ovf.createEnvelope() ovf.envelope.setAttribute( "xmlns:opennodens", "http://opennodecloud.com/schema/ovf/opennodens/1") instanceId = 0 virtualSystem = ovf.createVirtualSystem(ident=vm_settings["template_name"], info="KVM OpenNode template") hardwareSection = ovf.createVirtualHardwareSection( node=virtualSystem, ident="virtual_hardware", info="Virtual hardware requirements for a virtual machine") # add virtual system ovf.createSystem( hardwareSection, "Virtual Hardware Family", str(instanceId), { "VirtualSystemType": "%s-%s" % (vm_settings["domain_type"], vm_settings["arch"]) }) instanceId += 1 # add cpu section for bound, cpu in zip( ["normal", "min", "max"], [vm_settings.get("vcpu%s" % pfx) for pfx in ["", "_min", "_max"]]): if cpu: ovf.addResourceItem(hardwareSection, { "Caption": "%s virtual CPU" % cpu, "Description": "Number of virtual CPUs", "ElementName": "%s virtual CPU" % cpu, "InstanceID": str(instanceId), "ResourceType": "3", "VirtualQuantity": cpu }, bound=bound) instanceId += 1 # add memory section for bound, memory in zip( ["normal", "min", "max"], [vm_settings.get("memory%s" % pfx) for pfx in ["", "_min", "_max"]]): if memory: ovf.addResourceItem(hardwareSection, { "AllocationUnits": "GigaBytes", "Caption": "%s GB of memory" % memory, "Description": "Memory Size", "ElementName": "%s GB of memory" % memory, "InstanceID": str(instanceId), "ResourceType": "4", "VirtualQuantity": memory }, bound=bound) instanceId += 1 # add network interfaces network_list = [] for interface in vm_settings["interfaces"]: if interface["type"] == "bridge": ovf.addResourceItem( hardwareSection, { "Address": interface["mac_address"], "AutomaticAllocation": "true", "Caption": "Ethernet adapter on '%s'" % interface["source_bridge"], "Connection": interface["source_bridge"], "Description": "Network interface", "ElementName": "Ethernet adapter on '%s'" % interface["source_bridge"], "InstanceID": "%d" % instanceId, "ResourceSubType": "E1000", "ResourceType": "10", }) network_list.append({ "networkID": interface["source_bridge"], "networkName": interface["source_bridge"], "description": "Network for OVF appliance" }) instanceId += 1 ovf.createNetworkSection(network_list, "Network for OVF appliance") # add references of KVM VM disks (see http://gitorious.org/open-ovf/mainline/blobs/master/py/ovf/OvfReferencedFile.py) ovf_disk_list = [] for disk in vm_settings["disks"]: ref_file = OvfReferencedFile(path=disk["new_path"], href=disk["filename"], file_id=disk["file_id"], size=disk["file_size"]) ovf.addReferencedFile(ref_file) ovf_disk_list.append({ "diskId": disk["disk_id"], "fileRef": disk["file_id"], "capacity": str(disk["disk_capacity"]), "format": "qcow2", "parentRef": None, "populatedSize": None, "capacityAllocUnits": None }) ovf.createReferences() ovf.createDiskSection(ovf_disk_list, "KVM VM template disks") # Add OpenNode section to Virtual System node doc = xml.dom.minidom.Document() on_section = doc.createElement("opennodens:OpenNodeSection") on_section.setAttribute("ovf:required", "false") virtualSystem.appendChild(on_section) info_dom = doc.createElement("Info") on_section.appendChild(info_dom) info_value = doc.createTextNode( "OpenNode Section for template customization") info_dom.appendChild(info_value) features_dom = doc.createElement("Features") on_section.appendChild(features_dom) admin_password = doc.createElement('AdminPassword') on_section.appendChild(admin_password) password_value = doc.createTextNode(vm_settings['passwd']) admin_password.appendChild(password_value) for feature in vm_settings["features"]: feature_dom = doc.createElement(feature) features_dom.appendChild(feature_dom) return ovf
def _generate_ovf_file(vm_settings, ct_archive_fnm): ovf = OvfFile() # Workaround for broken OvfFile.__init__ ovf.files = [] ovf.createEnvelope() instanceId = 0 virtualSystem = ovf.createVirtualSystem(ident=vm_settings["template_name"], info="OpenVZ OpenNode template") # add OS section ovf.createOperatingSystem( node=virtualSystem, ident='operating_system', info='Operating system type deployed in a template', description=vm_settings.get('ostemplate', 'linux')) hardwareSection = ovf.createVirtualHardwareSection( node=virtualSystem, ident="virtual_hardware", info="Virtual hardware requirements for a virtual machine") ovf.createSystem(hardwareSection, "Virtual Hardware Family", str(instanceId), {"VirtualSystemType": "openvz"}) instanceId += 1 # add cpu section for bound, cpu in zip( ["normal", "min", "max"], [vm_settings.get("vcpu%s" % pfx) for pfx in ["", "_min", "_max"]]): if cpu: ovf.addResourceItem(hardwareSection, { "Caption": "%s virtual CPU" % cpu, "Description": "Number of virtual CPUs", "ElementName": "%s virtual CPU" % cpu, "InstanceID": str(instanceId), "ResourceType": "3", "VirtualQuantity": cpu }, bound=bound) instanceId += 1 # add memory section for bound, memory in zip( ["normal", "min", "max"], [vm_settings.get("memory%s" % pfx) for pfx in ["", "_min", "_max"]]): if memory: ovf.addResourceItem(hardwareSection, { "AllocationUnits": "GigaBytes", "Caption": "%s GB of memory" % memory, "Description": "Memory Size", "ElementName": "%s GB of memory" % memory, "InstanceID": str(instanceId), "ResourceType": "4", "VirtualQuantity": memory }, bound=bound) instanceId += 1 def get_checksum(fnm): # calculate checksum for the file chunk_size = 1024**2 # 1Mb sha = sha1() with open(fnm) as chkfile: while 1: data = chkfile.read(chunk_size) if not data: break sha.update(data) return sha.hexdigest() # add reference a file (see http://gitorious.org/open-ovf/mainline/blobs/master/py/ovf/OvfReferencedFile.py) ref_file = OvfReferencedFile(path.dirname(ct_archive_fnm), path.basename("%s.tar.gz" % vm_settings["template_name"]), file_id="diskfile1", size=str(get_file_size_bytes(ct_archive_fnm)), compression="gz", checksum=get_checksum(ct_archive_fnm)) ovf.addReferencedFile(ref_file) ovf.createReferences() def get_ct_disk_usage_bytes(ctid): return str( int(execute("du -s /vz/private/%s/" % ctid).split()[0]) * 1024) # add disk section ovf.createDiskSection( [{ "diskId": "vmdisk1", "capacity": str(round( float(vm_settings["disk"]) * 1024**3)), # in bytes "capacityAllocUnits": None, # bytes default "populatedSize": get_ct_disk_usage_bytes(vm_settings["vm_name"]), "fileRef": "diskfile1", "parentRef": None, "format": "tar.gz" }], "OpenVZ CT template disks") return ovf