From 0923ed5d8586ad06e233d7e45a6d254c52f708e7 Mon Sep 17 00:00:00 2001 From: grossmj Date: Sun, 2 Aug 2015 23:02:02 -0600 Subject: [PATCH] Support for Qemu disk interfaces, cd/dvd-rom image and boot priority. Fixes #278. --- gns3server/modules/qemu/qemu_vm.py | 170 ++++++++++++++++++++++++++++- gns3server/schemas/qemu.py | 91 ++++++++++++++- 2 files changed, 254 insertions(+), 7 deletions(-) diff --git a/gns3server/modules/qemu/qemu_vm.py b/gns3server/modules/qemu/qemu_vm.py index 4da1a1db..73f45840 100644 --- a/gns3server/modules/qemu/qemu_vm.py +++ b/gns3server/modules/qemu/qemu_vm.py @@ -88,6 +88,12 @@ class QemuVM(BaseVM): self._hdb_disk_image = "" self._hdc_disk_image = "" self._hdd_disk_image = "" + self._hda_disk_interface = "ide" + self._hdb_disk_interface = "ide" + self._hdc_disk_interface = "ide" + self._hdd_disk_interface = "ide" + self._cdrom_image = "" + self._boot_priority = "c" self._mac_address = "" self._options = "" self._ram = 256 @@ -264,6 +270,143 @@ class QemuVM(BaseVM): id=self._id, disk_image=self._hdd_disk_image)) + @property + def hda_disk_interface(self): + """ + Returns the hda disk interface this QEMU VM. + + :returns: QEMU hda disk interface + """ + + return self._hda_disk_interface + + @hda_disk_interface.setter + def hda_disk_interface(self, hda_disk_interface): + """ + Sets the hda disk interface for this QEMU VM. + + :param hda_disk_interface: QEMU hda disk interface + """ + + self._hda_disk_interface = hda_disk_interface + log.info('QEMU VM "{name}" [{id}] has set the QEMU hda disk interface to {interface}'.format(name=self._name, + id=self._id, + interface=self._hda_disk_interface)) + + @property + def hdb_disk_interface(self): + """ + Returns the hdb disk interface this QEMU VM. + + :returns: QEMU hdb disk interface + """ + + return self._hda_disk_interface + + @hdb_disk_interface.setter + def hdb_disk_interface(self, hdb_disk_interface): + """ + Sets the hda disk interface for this QEMU VM. + + :param hdb_disk_interface: QEMU hdb disk interface + """ + + self._hdb_disk_interface = hdb_disk_interface + log.info('QEMU VM "{name}" [{id}] has set the QEMU hdb disk interface to {interface}'.format(name=self._name, + id=self._id, + interface=self._hdb_disk_interface)) + + @property + def hdc_disk_interface(self): + """ + Returns the hdc disk interface this QEMU VM. + + :returns: QEMU hdc disk interface + """ + + return self._hdc_disk_interface + + @hdc_disk_interface.setter + def hdc_disk_interface(self, hdc_disk_interface): + """ + Sets the hdc disk interface for this QEMU VM. + + :param hdc_disk_interface: QEMU hdc disk interface + """ + + self._hdc_disk_interface = hdc_disk_interface + log.info('QEMU VM "{name}" [{id}] has set the QEMU hdc disk interface to {interface}'.format(name=self._name, + id=self._id, + interface=self._hdc_disk_interface)) + + @property + def hdd_disk_interface(self): + """ + Returns the hda disk interface this QEMU VM. + + :returns: QEMU hda disk interface + """ + + return self._hdd_disk_interface + + @hdd_disk_interface.setter + def hdd_disk_interface(self, hdd_disk_interface): + """ + Sets the hdd disk interface for this QEMU VM. + + :param hdd_disk_interface: QEMU hdd disk interface + """ + + self._hdd_disk_interface = hdd_disk_interface + log.info('QEMU VM "{name}" [{id}] has set the QEMU hdd disk interface to {interface}'.format(name=self._name, + id=self._id, + interface=self._hdd_disk_interface)) + + @property + def cdrom_image(self): + """ + Returns the cdrom image path for this QEMU VM. + + :returns: QEMU cdrom image path + """ + + return self._cdrom_image + + @cdrom_image.setter + def cdrom_image(self, cdrom_image): + """ + Sets the cdrom image for this QEMU VM. + + :param cdrom_image: QEMU cdrom image path + """ + self._cdrom_image = self.manager.get_abs_image_path(cdrom_image) + log.info('QEMU VM "{name}" [{id}] has set the QEMU cdrom image path to {cdrom_image}'.format(name=self._name, + id=self._id, + cdrom_image=self._cdrom_image)) + + @property + def boot_priority(self): + """ + Returns the boot priority for this QEMU VM. + + :returns: QEMU boot priority + """ + + return self._boot_priority + + @boot_priority.setter + def boot_priority(self, boot_priority): + """ + Sets the boot priority for this QEMU VM. + + :param boot_priority: QEMU boot priority + """ + + self._boot_priority = boot_priority + log.info('QEMU VM "{name}" [{id}] has set the boot priority to {boot_priority}'.format(name=self._name, + id=self._id, + boot_priority=self._boot_priority)) + @property def adapters(self): """ @@ -1043,7 +1186,7 @@ class QemuVM(BaseVM): log.info("{} returned with {}".format(qemu_img_path, retcode)) except (OSError, subprocess.SubprocessError) as e: raise QemuError("Could not create hda disk image {}".format(e)) - options.extend(["-hda", hda_disk]) + options.extend(["-drive", 'file={},if={},index=0,media=disk'.format(hda_disk, self.hda_disk_interface)]) if self._hdb_disk_image: if not os.path.isfile(self._hdb_disk_image) or not os.path.exists(self._hdb_disk_image): @@ -1061,7 +1204,7 @@ class QemuVM(BaseVM): log.info("{} returned with {}".format(qemu_img_path, retcode)) except (OSError, subprocess.SubprocessError) as e: raise QemuError("Could not create hdb disk image {}".format(e)) - options.extend(["-hdb", hdb_disk]) + options.extend(["-drive", 'file={},if={},index=1,media=disk'.format(hdb_disk, self.hdb_disk_interface)]) if self._hdc_disk_image: if not os.path.isfile(self._hdc_disk_image) or not os.path.exists(self._hdc_disk_image): @@ -1079,7 +1222,7 @@ class QemuVM(BaseVM): log.info("{} returned with {}".format(qemu_img_path, retcode)) except (OSError, subprocess.SubprocessError) as e: raise QemuError("Could not create hdc disk image {}".format(e)) - options.extend(["-hdc", hdc_disk]) + options.extend(["-drive", 'file={},if={},index=2,media=disk'.format(hdc_disk, self.hdc_disk_interface)]) if self._hdd_disk_image: if not os.path.isfile(self._hdd_disk_image) or not os.path.exists(self._hdd_disk_image): @@ -1097,10 +1240,24 @@ class QemuVM(BaseVM): log.info("{} returned with {}".format(qemu_img_path, retcode)) except (OSError, subprocess.SubprocessError) as e: raise QemuError("Could not create hdd disk image {}".format(e)) - options.extend(["-hdd", hdd_disk]) + options.extend(["-drive", 'file={},if={},index=3,media=disk'.format(hdd_disk, self.hdd_disk_interface)]) return options + def _cdrom_option(self): + + options = [] + if self._cdrom_image: + if not os.path.isfile(self._cdrom_image) or not os.path.exists(self._cdrom_image): + if os.path.islink(self._cdrom_image): + raise QemuError("cdrom image '{}' linked to '{}' is not accessible".format(self._cdrom_image, os.path.realpath(self._cdrom_image))) + else: + raise QemuError("cdrom image '{}' is not accessible".format(self._cdrom_image)) + if self._hdc_disk_image: + raise QemuError("You cannot use a disk image on hdc disk and a CDROM image at the same time") + options.extend(["-cdrom", self._cdrom_image]) + return options + def _linux_boot_options(self): options = [] @@ -1192,8 +1349,11 @@ class QemuVM(BaseVM): if not os.path.exists("/dev/kvm"): raise QemuError("KVM acceleration cannot be used (/dev/kvm doesn't exist)") command.extend(["-enable-kvm"]) + command.extend(["-boot", "order={}".format(self._boot_priority)]) disk_options = yield from self._disk_options() command.extend(disk_options) + cdrom_option = self._cdrom_option() + command.extend(cdrom_option) command.extend(self._linux_boot_options()) if self._console_type == "telnet": command.extend(self._serial_options()) @@ -1234,6 +1394,8 @@ class QemuVM(BaseVM): answer["hdc_disk_image_md5sum"] = md5sum(self._hdc_disk_image) answer["hdd_disk_image"] = self.manager.get_relative_image_path(self._hdd_disk_image) answer["hdd_disk_image_md5sum"] = md5sum(self._hdd_disk_image) + answer["cdrom_image"] = self.manager.get_relative_image_path(self._cdrom_image) + answer["cdrom_image_md5sum"] = md5sum(self._cdrom_image) answer["initrd"] = self.manager.get_relative_image_path(self._initrd) answer["initrd_md5sum"] = md5sum(self._initrd) diff --git a/gns3server/schemas/qemu.py b/gns3server/schemas/qemu.py index 20015ec1..c335f35c 100644 --- a/gns3server/schemas/qemu.py +++ b/gns3server/schemas/qemu.py @@ -61,6 +61,10 @@ QEMU_CREATE_SCHEMA = { "description": "QEMU hda disk image path", "type": "string", }, + "hda_disk_interface": { + "description": "QEMU hda interface", + "type": "string", + }, "hda_disk_image_md5sum": { "description": "QEMU hda disk image checksum", "type": ["string", "null"] @@ -69,6 +73,10 @@ QEMU_CREATE_SCHEMA = { "description": "QEMU hdb disk image path", "type": "string", }, + "hdb_disk_interface": { + "description": "QEMU hdb interface", + "type": "string", + }, "hdb_disk_image_md5sum": { "description": "QEMU hdb disk image checksum", "type": ["string", "null"], @@ -77,6 +85,10 @@ QEMU_CREATE_SCHEMA = { "description": "QEMU hdc disk image path", "type": "string", }, + "hdc_disk_interface": { + "description": "QEMU hdc interface", + "type": "string", + }, "hdc_disk_image_md5sum": { "description": "QEMU hdc disk image checksum", "type": ["string", "null"], @@ -85,10 +97,26 @@ QEMU_CREATE_SCHEMA = { "description": "QEMU hdd disk image path", "type": "string", }, + "hdd_disk_interface": { + "description": "QEMU hdd interface", + "type": "string", + }, "hdd_disk_image_md5sum": { "description": "QEMU hdd disk image checksum", "type": ["string", "null"], }, + "cdrom_image": { + "description": "QEMU cdrom image path", + "type": "string", + }, + "cdrom_image_md5sum": { + "description": "QEMU cdrom image checksum", + "type": ["string", "null"], + }, + "boot_priority": { + "description": "QEMU boot priority", + "enum": ["c", "d"] + }, "ram": { "description": "amount of RAM in MB", "type": ["integer", "null"] @@ -196,6 +224,10 @@ QEMU_UPDATE_SCHEMA = { "description": "QEMU hda disk image path", "type": "string", }, + "hda_disk_interface": { + "description": "QEMU hda interface", + "type": "string", + }, "hda_disk_image_md5sum": { "description": "QEMU hda disk image checksum", "type": ["string", "null"] @@ -204,6 +236,10 @@ QEMU_UPDATE_SCHEMA = { "description": "QEMU hdb disk image path", "type": "string", }, + "hdb_disk_interface": { + "description": "QEMU hdb interface", + "type": "string", + }, "hdb_disk_image_md5sum": { "description": "QEMU hdb disk image checksum", "type": ["string", "null"], @@ -212,6 +248,10 @@ QEMU_UPDATE_SCHEMA = { "description": "QEMU hdc disk image path", "type": "string", }, + "hdc_disk_interface": { + "description": "QEMU hdc interface", + "type": "string", + }, "hdc_disk_image_md5sum": { "description": "QEMU hdc disk image checksum", "type": ["string", "null"], @@ -220,10 +260,26 @@ QEMU_UPDATE_SCHEMA = { "description": "QEMU hdd disk image path", "type": "string", }, + "hdd_disk_interface": { + "description": "QEMU hdd interface", + "type": "string", + }, "hdd_disk_image_md5sum": { "description": "QEMU hdd disk image checksum", "type": ["string", "null"], }, + "cdrom_image": { + "description": "QEMU cdrom image path", + "type": "string", + }, + "cdrom_image_md5sum": { + "description": "QEMU cdrom image checksum", + "type": ["string", "null"], + }, + "boot_priority": { + "description": "QEMU boot priority", + "enum": ["c", "d"] + }, "ram": { "description": "amount of RAM in MB", "type": ["integer", "null"] @@ -330,6 +386,10 @@ QEMU_OBJECT_SCHEMA = { "description": "QEMU hda disk image path", "type": "string", }, + "hda_disk_interface": { + "description": "QEMU hda interface", + "type": "string", + }, "hda_disk_image_md5sum": { "description": "QEMU hda disk image checksum", "type": ["string", "null"] @@ -338,6 +398,10 @@ QEMU_OBJECT_SCHEMA = { "description": "QEMU hdb disk image path", "type": "string", }, + "hdb_disk_interface": { + "description": "QEMU hdb interface", + "type": "string", + }, "hdb_disk_image_md5sum": { "description": "QEMU hdb disk image checksum", "type": ["string", "null"], @@ -346,6 +410,10 @@ QEMU_OBJECT_SCHEMA = { "description": "QEMU hdc disk image path", "type": "string", }, + "hdc_disk_interface": { + "description": "QEMU hdc interface", + "type": "string", + }, "hdc_disk_image_md5sum": { "description": "QEMU hdc disk image checksum", "type": ["string", "null"], @@ -354,10 +422,26 @@ QEMU_OBJECT_SCHEMA = { "description": "QEMU hdd disk image path", "type": "string", }, + "hdd_disk_interface": { + "description": "QEMU hdd interface", + "type": "string", + }, "hdd_disk_image_md5sum": { "description": "QEMU hdd disk image checksum", "type": ["string", "null"], }, + "cdrom_image": { + "description": "QEMU cdrom image path", + "type": "string", + }, + "cdrom_image_md5sum": { + "description": "QEMU cdrom image checksum", + "type": ["string", "null"], + }, + "boot_priority": { + "description": "QEMU boot priority", + "enum": ["c", "d"] + }, "vm_directory": { "decription": "Path to the VM working directory", "type": "string" @@ -444,8 +528,9 @@ QEMU_OBJECT_SCHEMA = { "additionalProperties": False, "required": ["vm_id", "project_id", "name", "qemu_path", "platform", "console_type", "hda_disk_image", "hdb_disk_image", "hdc_disk_image", "hdd_disk_image", "hda_disk_image_md5sum", "hdb_disk_image_md5sum", - "hdc_disk_image_md5sum", "hdd_disk_image_md5sum", "ram", "adapters", "adapter_type", "mac_address", - "console", "initrd", "kernel_image", "initrd_md5sum", "kernel_image_md5sum", "kernel_command_line", + "hdc_disk_image_md5sum", "hdd_disk_image_md5sum", "hda_disk_interface", "hdb_disk_interface", "hdc_disk_interface", + "hdd_disk_interface", "cdrom_image", "cdrom_image_md5sum", "boot_priority", "ram", "adapters", "adapter_type", + "mac_address", "console", "initrd", "kernel_image", "initrd_md5sum", "kernel_image_md5sum", "kernel_command_line", "legacy_networking", "acpi_shutdown", "cpu_throttling", "process_priority", "options", "vm_directory"] } @@ -495,7 +580,7 @@ QEMU_LIST_IMAGES_SCHEMA = { QEMU_IMAGE_CREATE_SCHEMA = { "$schema": "http://json-schema.org/draft-04/schema#", - "description": "Create a new qemu image. Options can be specific to a format. Read qemu-img manual for more informations.", + "description": "Create a new qemu image. Options can be specific to a format. Read qemu-img manual for more information", "type": "object", "properties": { "qemu_img": {