def _get_cdrom_xml(self, libvirt_stream_protocols): if 'cdrom' not in self.info: return '' params = {} params['type'] = 'cdrom' params['format'] = 'raw' params['bus'] = self.info['cdrom_bus'] params['index'] = self.info['cdrom_index'] params['path'] = self.info['cdrom'] if self.info.get('iso_stream', False): protocol = urlparse.urlparse(params['path']).scheme if protocol not in libvirt_stream_protocols: driveOpt = 'file=%(path)s,if=none,id=drive-%(bus)s0-1-0,' driveOpt += 'readonly=on,format=%(format)s' deviceOpt = '%(bus)s-cd,bus=%(bus)s.1,unit=0,' deviceOpt += 'drive=drive-%(bus)s0-1-0,id=%(bus)s0-1-0' args = {} args['-drive'] = driveOpt % params args['-device'] = deviceOpt % params # return qemucmdline XML return get_qemucmdline_xml(args) dev, xml = get_disk_xml(params) return xml
def _get_disks_xml(self, vm_uuid): # Current implementation just allows to create disk in one single # storage pool, so we cannot mix the types (scsi volumes vs img file) storage_type = self._get_storage_type() storage_path = self._get_storage_path() base_disk_params = {'type': 'disk', 'disk': 'file', 'bus': self.info['disk_bus'], 'format': 'qcow2'} logical_disk_params = {'format': 'raw'} iscsi_disk_params = {'disk': 'block', 'format': 'raw'} scsi_disk = 'volume' if self.fc_host_support else 'block' scsi_disk_params = {'disk': scsi_disk, 'type': 'lun', 'format': 'raw', 'bus': 'scsi'} disks_xml = '' pool_name = pool_name_from_uri(self.info['storagepool']) for index, disk in enumerate(self.info['disks']): params = dict(base_disk_params) params['format'] = disk.get('format', params['format']) params.update(locals().get('%s_disk_params' % storage_type, {})) params['index'] = index volume = disk.get('volume') if volume is not None: params['path'] = self._get_volume_path(pool_name, volume) else: volume = "%s-%s.img" % (vm_uuid, params['index']) params['path'] = os.path.join(storage_path, volume) disks_xml += get_disk_xml(params)[1] return unicode(disks_xml, 'utf-8')
def _get_disks_xml(self, vm_uuid): # Current implementation just allows to create disk in one single # storage pool, so we cannot mix the types (scsi volumes vs img file) storage_type = self._get_storage_type() storage_path = self._get_storage_path() base_disk_params = {"type": "disk", "disk": "file", "bus": self.info["disk_bus"], "format": "qcow2"} logical_disk_params = {"format": "raw"} iscsi_disk_params = {"disk": "block", "format": "raw"} scsi_disk = "volume" if self.fc_host_support else "block" scsi_disk_params = {"disk": scsi_disk, "type": "lun", "format": "raw", "bus": "scsi"} disks_xml = "" pool_name = pool_name_from_uri(self.info["storagepool"]) for index, disk in enumerate(self.info["disks"]): params = dict(base_disk_params) params["format"] = disk.get("format", params["format"]) params.update(locals().get("%s_disk_params" % storage_type, {})) params["index"] = index volume = disk.get("volume") if volume is not None: params["path"] = self._get_volume_path(pool_name, volume) else: volume = "%s-%s.img" % (vm_uuid, params["index"]) params["path"] = os.path.join(storage_path, volume) disks_xml += get_disk_xml(params)[1] return unicode(disks_xml, "utf-8")
def _get_disks_xml(self, vm_uuid): # Current implementation just allows to create disk in one single # storage pool, so we cannot mix the types (scsi volumes vs img file) storage_type = self._get_storage_type() storage_path = self._get_storage_path() base_disk_params = {'type': 'disk', 'disk': 'file', 'bus': self.info['disk_bus']} logical_disk_params = {'format': 'raw'} iscsi_disk_params = {'disk': 'block', 'format': 'raw'} scsi_disk = 'volume' if self.fc_host_support else 'block' scsi_disk_params = {'disk': scsi_disk, 'type': 'lun', 'format': 'raw', 'bus': 'scsi'} disks_xml = '' pool_name = pool_name_from_uri(self.info['storagepool']) for index, disk in enumerate(self.info['disks']): params = dict(base_disk_params) params['format'] = disk['format'] params.update(locals().get('%s_disk_params' % storage_type, {})) params['index'] = index volume = disk.get('volume') if volume is not None: params['path'] = self._get_volume_path(pool_name, volume) else: volume = "%s-%s.img" % (vm_uuid, params['index']) params['path'] = os.path.join(storage_path, volume) disks_xml += get_disk_xml(params)[1] return unicode(disks_xml, 'utf-8')
def _get_cdrom_xml(self, libvirt_stream_protocols): if "cdrom" not in self.info: return "" params = {} params["type"] = "cdrom" params["format"] = "raw" params["bus"] = self.info["cdrom_bus"] params["index"] = self.info["cdrom_index"] params["path"] = self.info["cdrom"] if self.info.get("iso_stream", False): protocol = urlparse.urlparse(params["path"]).scheme if protocol not in libvirt_stream_protocols: driveOpt = "file=%(path)s,if=none,id=drive-%(bus)s0-1-0," driveOpt += "readonly=on,format=%(format)s" deviceOpt = "%(bus)s-cd,bus=%(bus)s.1,unit=0," deviceOpt += "drive=drive-%(bus)s0-1-0,id=%(bus)s0-1-0" args = {} args["-drive"] = driveOpt % params args["-device"] = deviceOpt % params # return qemucmdline XML return get_qemucmdline_xml(args) dev, xml = get_disk_xml(params) return xml
def update(self, vm_name, dev_name, params): old_disk_used_by = None new_disk_used_by = None dom = VMModel.get_vm(vm_name, self.conn) dev_info = self.lookup(vm_name, dev_name) if dev_info['type'] != 'cdrom': raise InvalidOperation("KCHVMSTOR0006E") params['path'] = params.get('path', '') old_disk_path = dev_info['path'] new_disk_path = params['path'] if new_disk_path != old_disk_path: # An empty path means a CD-ROM was empty or ejected: if old_disk_path is not '': old_disk_used_by = get_disk_used_by(self.objstore, self.conn, old_disk_path) if new_disk_path is not '': new_disk_used_by = get_disk_used_by(self.objstore, self.conn, new_disk_path) dev_info.update(params) dev, xml = get_disk_xml(dev_info) try: dom.updateDeviceFlags(xml, get_vm_config_flag(dom, 'all')) except Exception as e: raise OperationFailed("KCHVMSTOR0009E", {'error': e.message}) try: if old_disk_used_by is not None and \ vm_name in old_disk_used_by: old_disk_used_by.remove(vm_name) set_disk_used_by(self.objstore, old_disk_path, old_disk_used_by) if new_disk_used_by is not None: new_disk_used_by.append(vm_name) set_disk_used_by(self.objstore, new_disk_path, new_disk_used_by) except Exception as e: kimchi_log.error("Unable to update dev used_by on update due to" " %s:" % e.message) return dev
def update(self, vm_name, dev_name, params): old_disk_used_by = None new_disk_used_by = None dom = VMModel.get_vm(vm_name, self.conn) dev_info = self.lookup(vm_name, dev_name) if dev_info['type'] != 'cdrom': raise InvalidOperation("KCHVMSTOR0006E") params['path'] = params.get('path', '') old_disk_path = dev_info['path'] new_disk_path = params['path'] if new_disk_path != old_disk_path: # An empty path means a CD-ROM was empty or ejected: if old_disk_path is not '': old_disk_used_by = get_disk_used_by( self.objstore, self.conn, old_disk_path) if new_disk_path is not '': new_disk_used_by = get_disk_used_by( self.objstore, self.conn, new_disk_path) dev_info.update(params) dev, xml = get_disk_xml(dev_info) try: dom.updateDeviceFlags(xml, get_vm_config_flag(dom, 'all')) except Exception as e: raise OperationFailed("KCHVMSTOR0009E", {'error': e.message}) try: if old_disk_used_by is not None and \ vm_name in old_disk_used_by: old_disk_used_by.remove(vm_name) set_disk_used_by(self.objstore, old_disk_path, old_disk_used_by) if new_disk_used_by is not None: new_disk_used_by.append(vm_name) set_disk_used_by(self.objstore, new_disk_path, new_disk_used_by) except Exception as e: kimchi_log.error("Unable to update dev used_by on update due to" " %s:" % e.message) return dev
def update(self, vm_name, dev_name, params): old_disk_ref_cnt = None new_disk_ref_cnt = None dom = VMModel.get_vm(vm_name, self.conn) dev_info = self.lookup(vm_name, dev_name) if dev_info['type'] != 'cdrom': raise InvalidOperation("KCHVMSTOR0006E") params['path'] = check_remote_disk_path(params.get('path', ''), self.caps.qemu_stream_dns) old_disk_path = dev_info['path'] new_disk_path = params['path'] if new_disk_path != old_disk_path: # An empty path means a CD-ROM was empty or ejected: if old_disk_path is not '': old_disk_ref_cnt = get_disk_ref_cnt( self.objstore, self.conn, old_disk_path) if new_disk_path is not '': new_disk_ref_cnt = get_disk_ref_cnt( self.objstore, self.conn, new_disk_path) dev_info.update(params) dev, xml = get_disk_xml(dev_info) try: dom.updateDeviceFlags(xml, get_vm_config_flag(dom, 'all')) except Exception as e: raise OperationFailed("KCHVMSTOR0009E", {'error': e.message}) try: if old_disk_ref_cnt is not None and \ old_disk_ref_cnt > 0: set_disk_ref_cnt(self.objstore, old_disk_path, old_disk_ref_cnt - 1) if new_disk_ref_cnt is not None: set_disk_ref_cnt(self.objstore, new_disk_path, new_disk_ref_cnt + 1) except Exception as e: kimchi_log.error("Unable to update dev ref_cnt on update due to" " %s:" % e.message) return dev
def update(self, vm_name, dev_name, params): old_disk_ref_cnt = None new_disk_ref_cnt = None dom = VMModel.get_vm(vm_name, self.conn) dev_info = self.lookup(vm_name, dev_name) if dev_info['type'] != 'cdrom': raise InvalidOperation("KCHVMSTOR0006E") params['path'] = check_remote_disk_path(params.get('path', ''), self.caps.qemu_stream_dns) old_disk_path = dev_info['path'] new_disk_path = params['path'] if new_disk_path != old_disk_path: # An empty path means a CD-ROM was empty or ejected: if old_disk_path is not '': old_disk_ref_cnt = get_disk_ref_cnt(self.objstore, self.conn, old_disk_path) if new_disk_path is not '': new_disk_ref_cnt = get_disk_ref_cnt(self.objstore, self.conn, new_disk_path) dev_info.update(params) dev, xml = get_disk_xml(dev_info) try: dom.updateDeviceFlags(xml, get_vm_config_flag(dom, 'all')) except Exception as e: raise OperationFailed("KCHVMSTOR0009E", {'error': e.message}) try: if old_disk_ref_cnt is not None and \ old_disk_ref_cnt > 0: set_disk_ref_cnt(self.objstore, old_disk_path, old_disk_ref_cnt - 1) if new_disk_ref_cnt is not None: set_disk_ref_cnt(self.objstore, new_disk_path, new_disk_ref_cnt + 1) except Exception as e: kimchi_log.error("Unable to update dev ref_cnt on update due to" " %s:" % e.message) return dev
def create(self, vm_name, params): vol_model = None # Path will never be blank due to API.json verification. # There is no need to cover this case here. if not ('vol' in params) ^ ('path' in params): raise InvalidParameter("KCHVMSTOR0017E") dom = VMModel.get_vm(vm_name, self.conn) params['bus'] = _get_device_bus(params['type'], dom, self.caps.metadata_support) params['format'] = 'raw' dev_list = [dev for dev, bus in get_vm_disks(dom).iteritems() if bus == params['bus']] dev_list.sort() if len(dev_list) == 0: params['index'] = 0 else: char = dev_list.pop()[2] params['index'] = string.ascii_lowercase.index(char) + 1 if (params['bus'] not in HOTPLUG_TYPE and DOM_STATE_MAP[dom.info()[0]] != 'shutoff'): raise InvalidOperation('KCHVMSTOR0011E') if params.get('vol'): try: pool = params['pool'] vol_model = StorageVolumeModel(conn=self.conn, objstore=self.objstore) vol_info = vol_model.lookup(pool, params['vol']) except KeyError: raise InvalidParameter("KCHVMSTOR0012E") except Exception as e: raise InvalidParameter("KCHVMSTOR0015E", {'error': e}) if vol_info['ref_cnt'] != 0: raise InvalidParameter("KCHVMSTOR0016E") valid_format = { "disk": ["raw", "bochs", "qcow", "qcow2", "qed", "vmdk"], "cdrom": "iso"} if vol_info['type'] == 'file': if (params['type'] == 'disk' and vol_info['format'] in valid_format[params['type']]): params['format'] = vol_info['format'] else: raise InvalidParameter("KCHVMSTOR0018E", {"format": vol_info['format'], "type": params['type']}) params['path'] = vol_info['path'] params['disk'] = vol_info['type'] params.update(self._get_available_bus_address(params['bus'], vm_name)) # Add device to VM dev, xml = get_disk_xml(params) try: conn = self.conn.get() dom = conn.lookupByName(vm_name) dom.attachDeviceFlags(xml, get_vm_config_flag(dom, 'all')) except Exception as e: raise OperationFailed("KCHVMSTOR0008E", {'error': e.message}) # Don't put a try-block here. Let the exception be raised. If we # allow disks ref_cnts to be out of sync, data corruption could # occour if a disk is added to two guests unknowingly. if params.get('vol'): set_disk_ref_cnt(self.objstore, params['path'], vol_info['ref_cnt'] + 1) return dev
def create(self, vm_name, params): vol_model = None # Path will never be blank due to API.json verification. # There is no need to cover this case here. if not ('vol' in params) ^ ('path' in params): raise InvalidParameter("KCHVMSTOR0017E") dom = VMModel.get_vm(vm_name, self.conn) params['bus'] = _get_device_bus(params['type'], dom, self.caps.metadata_support) params['format'] = 'raw' dev_list = [ dev for dev, bus in get_vm_disks(dom).iteritems() if bus == params['bus'] ] dev_list.sort() if len(dev_list) == 0: params['index'] = 0 else: char = dev_list.pop()[2] params['index'] = string.ascii_lowercase.index(char) + 1 if (params['bus'] not in HOTPLUG_TYPE and DOM_STATE_MAP[dom.info()[0]] != 'shutoff'): raise InvalidOperation('KCHVMSTOR0011E') if params.get('vol'): try: pool = params['pool'] vol_model = StorageVolumeModel(conn=self.conn, objstore=self.objstore) vol_info = vol_model.lookup(pool, params['vol']) except KeyError: raise InvalidParameter("KCHVMSTOR0012E") except Exception as e: raise InvalidParameter("KCHVMSTOR0015E", {'error': e}) if len(vol_info['used_by']) != 0: raise InvalidParameter("KCHVMSTOR0016E") valid_format = { "disk": ["raw", "bochs", "qcow", "qcow2", "qed", "vmdk"], "cdrom": "iso" } if vol_info['type'] == 'file': if (params['type'] == 'disk' and vol_info['format'] in valid_format[params['type']]): params['format'] = vol_info['format'] else: raise InvalidParameter("KCHVMSTOR0018E", { "format": vol_info['format'], "type": params['type'] }) params['path'] = vol_info['path'] params['disk'] = vol_info['type'] params.update(self._get_available_bus_address(params['bus'], vm_name)) # Add device to VM dev, xml = get_disk_xml(params) try: conn = self.conn.get() dom = conn.lookupByName(vm_name) dom.attachDeviceFlags(xml, get_vm_config_flag(dom, 'all')) except Exception as e: raise OperationFailed("KCHVMSTOR0008E", {'error': e.message}) # Don't put a try-block here. Let the exception be raised. If we # allow disks used_by to be out of sync, data corruption could # occour if a disk is added to two guests unknowingly. if params.get('vol'): used_by = vol_info['used_by'] used_by.append(vm_name) set_disk_used_by(self.objstore, params['path'], used_by) return dev