Ejemplo 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
Ejemplo n.º 2
0
    def _get_cdrom_xml(self, libvirt_stream_protocols):
        if 'cdrom' not in self.info:
            return None

        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
Ejemplo n.º 3
0
    def _get_disks_xml(self, vm_uuid):
        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 = ''
        for index, disk in enumerate(self.info['disks']):
            params = dict(base_disk_params)
            params['format'] = disk['format']
            params['index'] = index
            params.update(locals().get('%s_disk_params' %
                                       disk['pool']['type'], {}))

            volume = disk.get('volume')
            if volume is not None:
                params['path'] = self._get_volume_path(disk['pool']['name'],
                                                       volume)
            else:
                img = "%s-%s.img" % (vm_uuid, params['index'])
                storage_path = self._get_storage_path(disk['pool']['name'])
                params['path'] = os.path.join(storage_path, img)
                params['pool_type'] = disk['pool']['type']
            disks_xml += get_disk_xml(params)[1]

        return unicode(disks_xml, 'utf-8')
Ejemplo n.º 4
0
    def _get_disks_xml(self, vm_uuid):
        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 = ''
        for index, disk in enumerate(self.info['disks']):
            params = dict(base_disk_params)
            params['format'] = disk['format']
            params['index'] = index
            if disk.get('pool'):
	            params.update(locals().get('%s_disk_params' %
                                       disk['pool']['type'], {}))

            volume = disk.get('volume')
            if volume is not None:
                params['path'] = self._get_volume_path(disk['pool']['name'],
                                                       volume)
            else:
                img = "%s-%s.img" % (vm_uuid, params['index'])
                if disk.get('pool'):
	                storage_path = self._get_storage_path(disk['pool']['name'])
                	params['pool_type'] = disk['pool']['type']
                elif disk.get('path'):
			storage_path = disk.get('path')
                params['path'] = os.path.join(storage_path, img)
            disks_xml += get_disk_xml(params)[1]

        return unicode(disks_xml, 'utf-8')
Ejemplo 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')
Ejemplo n.º 6
0
    def _get_disks_xml(self, vm_uuid):
        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 = ""
        for index, disk in enumerate(self.info["disks"]):
            params = dict(base_disk_params)
            params["format"] = disk["format"]
            params["index"] = index
            if disk.get("pool"):
                params.update(locals().get("%s_disk_params" % disk["pool"]["type"], {}))

            volume = disk.get("volume")
            if volume is not None:
                params["path"] = self._get_volume_path(disk["pool"]["name"], volume)
            else:
                img = "%s-%s.img" % (vm_uuid, params["index"])
                if disk.get("pool"):
                    storage_path = self._get_storage_path(disk["pool"]["name"])
                    params["pool_type"] = disk["pool"]["type"]
                elif disk.get("path"):
                    storage_path = disk.get("path")
                    params["pool_type"] = None
                params["path"] = os.path.join(storage_path, img)
            disks_xml += get_disk_xml(params)[1]

        return unicode(disks_xml, "utf-8")
Ejemplo n.º 7
0
    def _get_cdrom_xml(self, libvirt_stream_protocols):
        if "cdrom" not in self.info:
            return None

        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
Ejemplo 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:
            wok_log.error("Unable to update dev used_by on update due to"
                          " %s:" % e.message)
        return dev
Ejemplo n.º 9
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:
            wok_log.error("Unable to update dev used_by on update due to"
                          " %s:" % e.message)
        return dev
Ejemplo n.º 10
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 != '':
                old_disk_used_by = get_disk_used_by(self.conn, old_disk_path)
            if new_disk_path != '':
                new_disk_used_by = get_disk_used_by(self.conn, new_disk_path)

        dev_info.update(params)
        dev, xml = get_disk_xml(dev_info)

        try:
            # FIXME: when updating from local file to remote file (http)
            # libvirt adds a new device with same name instead of replacing
            # the existing one
            dom.updateDeviceFlags(xml, get_vm_config_flag(dom, 'all'))
        except Exception as e:
            raise OperationFailed('KCHVMSTOR0009E', {'error': str(e)})

        try:
            if old_disk_used_by is not None and vm_name in old_disk_used_by:
                old_disk_used_by.remove(vm_name)
            if new_disk_used_by is not None:
                new_disk_used_by.append(vm_name)
        except Exception as e:
            wok_log.error(
                'Unable to update dev used_by on update due to' ' %s:' % str(e)
            )
        return dev
Ejemplo n.º 11
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')
Ejemplo n.º 12
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 != '':
                old_disk_used_by = get_disk_used_by(self.conn, old_disk_path)
            if new_disk_path != '':
                new_disk_used_by = get_disk_used_by(self.conn, new_disk_path)

        dev_info.update(params)
        dev, xml = get_disk_xml(dev_info)

        try:
            # FIXME: when updating from local file to remote file (http)
            # libvirt adds a new device with same name instead of replacing
            # the existing one
            dom.updateDeviceFlags(xml, get_vm_config_flag(dom, 'all'))
        except Exception as e:
            raise OperationFailed('KCHVMSTOR0009E', {'error': str(e)})

        try:
            if old_disk_used_by is not None and vm_name in old_disk_used_by:
                old_disk_used_by.remove(vm_name)
            if new_disk_used_by is not None:
                new_disk_used_by.append(vm_name)
        except Exception as e:
            wok_log.error('Unable to update dev used_by on update due to'
                          ' %s:' % str(e))
        return dev
Ejemplo n.º 13
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)
        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", "qcow", "qcow2", "qed", "vmdk", "vpc"],
                "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']})

            if (params['format'] == 'raw' and not vol_info['isvalid']):
                message = 'This is not a valid RAW disk image.'
                raise OperationFailed('KCHVMSTOR0008E', {'error': message})

            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:
            dom = VMModel.get_vm(vm_name, self.conn)
            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
Ejemplo n.º 14
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)
        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']})

            if (params['format'] == 'raw' and not vol_info['isvalid']):
                message = 'This is not a valid RAW disk image.'
                raise OperationFailed('KCHVMSTOR0008E', {'error': message})

            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:
            dom = VMModel.get_vm(vm_name, self.conn)
            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
Ejemplo n.º 15
0
    def create(self, vm_name, params):
        # 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):

            if not is_s390x():
                raise InvalidParameter('KCHVMSTOR0017E')

            if 'dir_path' not in params:
                raise InvalidParameter('KCHVMSTOR0019E')

        dom = VMModel.get_vm(vm_name, self.conn)
        params['bus'] = _get_device_bus(params['type'], dom)

        if is_s390x() and params['type'] == 'disk' and 'dir_path' in params:
            if 'format' not in params:
                raise InvalidParameter('KCHVMSTOR0020E')
            size = params['size']
            name = params['name']
            dir_path = params.get('dir_path')
            params['path'] = dir_path + '/' + name
            if os.path.exists(params['path']):
                raise InvalidParameter('KCHVMSTOR0021E',
                                       {'disk_path': params['path']})
            create_disk_image(format_type=params['format'],
                              path=params['path'],
                              capacity=size)
        else:
            params['format'] = 'raw'

        dev_list = [
            dev for dev, bus in get_vm_disks(dom).items()
            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'):
            vol_info = self._get_vol_info(params)

            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:
            dom = VMModel.get_vm(vm_name, self.conn)
            dom.attachDeviceFlags(xml, get_vm_config_flag(dom, 'all'))
        except Exception as e:
            raise OperationFailed('KCHVMSTOR0008E', {'error': str(e)})

        # 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
        #   occur if a disk is added to two guests unknowingly.
        if params.get('vol'):
            used_by = vol_info['used_by']
            used_by.append(vm_name)

        return dev
Ejemplo n.º 16
0
    def create(self, vm_name, params):
        # 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):

            if not is_s390x():
                raise InvalidParameter('KCHVMSTOR0017E')

            if 'dir_path' not in params:
                raise InvalidParameter('KCHVMSTOR0019E')

        dom = VMModel.get_vm(vm_name, self.conn)
        params['bus'] = _get_device_bus(params['type'], dom)

        if is_s390x() and params['type'] == 'disk' and 'dir_path' in params:
            if 'format' not in params:
                raise InvalidParameter('KCHVMSTOR0020E')
            size = params['size']
            name = params['name']
            dir_path = params.get('dir_path')
            params['path'] = dir_path + '/' + name
            if os.path.exists(params['path']):
                raise InvalidParameter(
                    'KCHVMSTOR0021E', {'disk_path': params['path']})
            create_disk_image(
                format_type=params['format'], path=params['path'], capacity=size
            )
        else:
            params['format'] = 'raw'

        dev_list = [
            dev for dev, bus in get_vm_disks(dom).items() 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'):
            vol_info = self._get_vol_info(params)

            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:
            dom = VMModel.get_vm(vm_name, self.conn)
            dom.attachDeviceFlags(xml, get_vm_config_flag(dom, 'all'))
        except Exception as e:
            raise OperationFailed('KCHVMSTOR0008E', {'error': str(e)})

        # 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
        #   occur if a disk is added to two guests unknowingly.
        if params.get('vol'):
            used_by = vol_info['used_by']
            used_by.append(vm_name)

        return dev