Esempio n. 1
0
    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
Esempio n. 2
0
    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
Esempio n. 3
0
    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')
Esempio n. 4
0
    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")
Esempio n. 5
0
    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')
Esempio n. 6
0
    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
Esempio n. 7
0
    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
Esempio n. 8
0
    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
Esempio n. 9
0
    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
Esempio n. 10
0
    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
Esempio n. 11
0
    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
Esempio n. 12
0
    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