Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion nova/conf/libvirt.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
22 changes: 16 additions & 6 deletions nova/privsep/libvirt.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"""

import binascii
import fcntl
import os
import stat

Expand Down Expand Up @@ -156,15 +157,24 @@ 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()
# this is not accepted by the unit test
# os.set_blocking(f.fileno(), False)
# therefore we use fnctl directly
flags = fcntl.fcntl(f.fileno(), fcntl.F_GETFL)
fcntl.fcntl(f.fileno(), fcntl.F_SETFL, flags | os.O_NONBLOCK)
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
Expand Down
3 changes: 3 additions & 0 deletions nova/tests/unit/privsep/test_libvirt.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import ddt
import os

import logging
import nova.privsep.libvirt
from nova import test
from nova.tests import fixtures
Expand Down Expand Up @@ -146,6 +147,8 @@ def fake_import(module, *args):
[mock.call(mock_fileno, mock_fcntl.F_GETFL),
mock.call(mock_fileno,
mock_fcntl.F_SETFL, 32769 | os.O_NONBLOCK)])
# Print all calls recorded by mock_open
logging.getLogger().info("mock_open.mock_calls: %s", mock_open.mock_calls)
self.assertIn(mock.call('/fake/path', 'r'), mock_open.mock_calls)

def test_create_nmdev(self):
Expand Down
3 changes: 3 additions & 0 deletions nova/virt/libvirt/blockinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
17 changes: 16 additions & 1 deletion nova/virt/libvirt/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -1379,6 +1379,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:///session'
else:
uri = CONF.libvirt.connection_uri or 'qemu:///system'
return uri
Expand Down Expand Up @@ -4494,7 +4496,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:
Expand Down Expand Up @@ -6735,6 +6738,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"
Expand Down Expand Up @@ -6780,6 +6786,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(
Expand Down Expand Up @@ -6969,6 +6980,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
Expand Down Expand Up @@ -7378,6 +7391,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
Expand Down
1 change: 1 addition & 0 deletions nova/virt/libvirt/host.py
Original file line number Diff line number Diff line change
Expand Up @@ -1241,6 +1241,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)

Expand Down
5 changes: 4 additions & 1 deletion nova/virt/libvirt/vif.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@
network_model.VIF_MODEL_RTL8139,
network_model.VIF_MODEL_E1000,
],
'ch': [
network_model.VIF_MODEL_VIRTIO,
],
}


Expand Down Expand Up @@ -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

Expand Down