diff --git a/nova/conf/libvirt.py b/nova/conf/libvirt.py index c4ccb4107c4..c717bf66567 100644 --- a/nova/conf/libvirt.py +++ b/nova/conf/libvirt.py @@ -104,7 +104,7 @@ """), cfg.StrOpt('virt_type', default='kvm', - choices=('kvm', 'lxc', 'qemu', 'parallels'), + choices=('kvm', 'lxc', 'qemu', 'parallels', 'ch'), help=""" Describes the virtualization type (or so called domain type) libvirt should use. diff --git a/nova/privsep/libvirt.py b/nova/privsep/libvirt.py index 6ca99b98b42..4c0d9d877d4 100644 --- a/nova/privsep/libvirt.py +++ b/nova/privsep/libvirt.py @@ -156,15 +156,20 @@ def readpty(path): # exception here... Some platforms (I'm looking at you Windows) # don't have a fcntl and we may as well let them know that # with an ImportError, not that they should be calling this at all. - import fcntl + import select try: + epoll = select.epoll() with open(path, 'r') as f: - current_flags = fcntl.fcntl(f.fileno(), fcntl.F_GETFL) - fcntl.fcntl(f.fileno(), fcntl.F_SETFL, - current_flags | os.O_NONBLOCK) - - return f.read() + os.set_blocking(f.fileno(), False) + epoll.register(f.fileno(), select.EPOLLIN) + poll_list = epoll.poll(1) + data = '' + for _ in poll_list: + data += f.read() + epoll.unregister(f.fileno()) + epoll.close() + return data except Exception as exc: # NOTE(mikal): dear internet, I see you looking at me with your diff --git a/nova/virt/libvirt/blockinfo.py b/nova/virt/libvirt/blockinfo.py index 4efc6fbaeb1..124aa1b7e5c 100644 --- a/nova/virt/libvirt/blockinfo.py +++ b/nova/virt/libvirt/blockinfo.py @@ -95,6 +95,7 @@ 'qemu': ['virtio', 'scsi', 'ide', 'usb', 'fdc', 'sata'], 'kvm': ['virtio', 'scsi', 'ide', 'usb', 'fdc', 'sata'], 'lxc': ['lxc'], + 'ch': ['virtio'], 'parallels': ['ide', 'scsi'], # we no longer support UML or Xen, but we keep track of their bus types so # we can reject them for other virt types @@ -276,6 +277,8 @@ def get_disk_bus_for_device_type(instance, return "ide" elif device_type == "disk": return "scsi" + elif virt_type == "ch": + return "virtio" else: # If virt-type not in list then it is unsupported raise exception.UnsupportedVirtType(virt=virt_type) diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 71dca0410ac..d0e6f132099 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -884,6 +884,10 @@ def _update_host_specific_capabilities(self) -> None: lv_ver=MIN_LIBVIRT_MAXPHYSADDR, hv_ver=MIN_QEMU_MAXPHYSADDR, hv_type=host.HV_DRIVER_QEMU, + ) or self._host.has_min_version( + lv_ver=MIN_LIBVIRT_MAXPHYSADDR, + hv_ver=(0,0,0), + hv_type=host.HV_DRIVER_CH, ) # NOTE(nmiki): Currently libvirt does not provide a distinction @@ -1379,6 +1383,8 @@ def _uri(): uri = CONF.libvirt.connection_uri or 'lxc:///' elif CONF.libvirt.virt_type == 'parallels': uri = CONF.libvirt.connection_uri or 'parallels:///system' + elif CONF.libvirt.virt_type == 'ch': + uri = CONF.libvirt.connection_uri or 'ch:///system' else: uri = CONF.libvirt.connection_uri or 'qemu:///system' return uri @@ -1389,6 +1395,7 @@ def _live_migration_uri(dest): 'kvm': 'qemu+%(scheme)s://%(dest)s/system', 'qemu': 'qemu+%(scheme)s://%(dest)s/system', 'parallels': 'parallels+tcp://%(dest)s/system', + 'ch': 'ch+%(scheme)s://%(dest)s/system', } dest = oslo_netutils.escape_ipv6(dest) @@ -4494,7 +4501,8 @@ def get_console_output(self, context, instance): path_sources = [ ('file', "./devices/console[@type='file']/source[@path]", 'path'), ('tcp', "./devices/console[@type='tcp']/log[@file]", 'file'), - ('pty', "./devices/console[@type='pty']/source[@path]", 'path')] + ('pty', "./devices/console[@type='pty']/source[@path]", 'path'), + ('pty', "./devices/serial[@type='pty']/source[@path]", 'path'), ] console_type = "" console_path = "" for c_type, epath, attrib in path_sources: @@ -6735,6 +6743,9 @@ def _configure_guest_by_virt_type( guest.os_init_path = "/sbin/init" guest.os_cmdline = CONSOLE guest.os_init_env["product_name"] = "OpenStack Nova" + elif CONF.libvirt.virt_type == "ch": + guest.virt_type = 'kvm' + guest.os_kernel = "/usr/share/cloud-hypervisor/CLOUDHV_EFI.fd" elif CONF.libvirt.virt_type == "parallels": if guest.os_type == fields.VMMode.EXE: guest.os_init_path = "/sbin/init" @@ -6780,6 +6791,11 @@ def _create_consoles(self, guest_cfg, instance, flavor, image_meta): self._create_pty_device( guest_cfg, vconfig.LibvirtConfigGuestConsole, log_path=log_path) + elif CONF.libvirt.virt_type == "ch": + consolepty = vconfig.LibvirtConfigGuestSerial() + consolepty.type = "pty" + guest_cfg.add_device(consolepty) + else: # qemu, kvm if self._is_s390x_guest(image_meta): self._create_consoles_s390x( @@ -6969,6 +6985,8 @@ def _guest_add_usb_root_controller(self, guest, image_meta): here explicitly so that we can _disable_ it (by setting the model to 'none') if it's not necessary. """ + if CONF.libvirt.virt_type == "ch": + return usbhost = vconfig.LibvirtConfigGuestUSBHostController() usbhost.index = 0 # an unset model means autodetect, while 'none' means don't add a @@ -7378,6 +7396,8 @@ def _guest_add_accel_pci_devices(self, guest, accel_info): def _guest_add_video_device(guest): if CONF.libvirt.virt_type == 'lxc': return False + elif CONF.libvirt.virt_type == "ch": + return False # NB some versions of libvirt support both SPICE and VNC # at the same time. We're not trying to second guess which diff --git a/nova/virt/libvirt/host.py b/nova/virt/libvirt/host.py index f67ccf9bbf7..3599b6ff78d 100644 --- a/nova/virt/libvirt/host.py +++ b/nova/virt/libvirt/host.py @@ -85,6 +85,7 @@ # This list is for libvirt hypervisor drivers that need special handling. # This is *not* the complete list of supported hypervisor drivers. HV_DRIVER_QEMU = "QEMU" +HV_DRIVER_CH = "CH" SEV_KERNEL_PARAM_FILE = '/sys/module/kvm_amd/parameters/sev' @@ -1241,6 +1242,7 @@ def write_instance_config(self, xml): :returns: an instance of Guest """ + LOG.info(xml) domain = self.get_connection().defineXML(xml) return libvirt_guest.Guest(domain) diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py index 6e9069fa50f..30456e678d2 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -78,6 +78,9 @@ network_model.VIF_MODEL_RTL8139, network_model.VIF_MODEL_E1000, ], + 'ch': [ + network_model.VIF_MODEL_VIRTIO, + ], } @@ -172,7 +175,7 @@ def get_vif_model(self, image_meta=None, vif_model=None): # If the virt type is KVM/QEMU/VZ(Parallels), then use virtio according # to the global config parameter if (model is None and CONF.libvirt.virt_type in - ('kvm', 'qemu', 'parallels') and + ('kvm', 'qemu', 'parallels', 'ch') and CONF.libvirt.use_virtio_for_bridges): model = network_model.VIF_MODEL_VIRTIO