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 delete(self, vm_name, dev_name): conn = self.conn.get() try: bus_type = self.lookup(vm_name, dev_name)['bus'] dom = conn.lookupByName(vm_name) except NotFoundError: raise if (bus_type not in HOTPLUG_TYPE and DOM_STATE_MAP[dom.info()[0]] != 'shutoff'): raise InvalidOperation('KCHVMSTOR0011E') try: disk = get_device_node(dom, dev_name) path = get_vm_disk_info(dom, dev_name)['path'] if path is None or len(path) < 1: path = self.lookup(vm_name, dev_name)['path'] # This has to be done before it's detached. If it wasn't # in the obj store, its ref count would have been updated # by get_disk_ref_cnt() if path is not None: ref_cnt = get_disk_ref_cnt(self.objstore, self.conn, path) else: kimchi_log.error("Unable to decrement volume ref_cnt on" " delete because no path could be found.") dom.detachDeviceFlags(etree.tostring(disk), get_vm_config_flag(dom, 'all')) except Exception as e: raise OperationFailed("KCHVMSTOR0010E", {'error': e.message}) if ref_cnt is not None and ref_cnt > 0: set_disk_ref_cnt(self.objstore, path, ref_cnt - 1) else: kimchi_log.error("Unable to decrement %s:%s ref_cnt on delete." % (vm_name, dev_name))
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 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)) params['path'] = check_remote_disk_path(params['path'], self.caps.qemu_stream_dns) # 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