Merge "libvirt: Acquire TCP ports for console during live migration" into stable/newton
This commit is contained in:
commit
663b582ddc
|
@ -3588,15 +3588,21 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
self.assertEqual(cfg.devices[5].type, "spice")
|
||||
self.assertEqual(cfg.devices[6].type, "qxl")
|
||||
|
||||
@mock.patch.object(host.Host, 'get_guest')
|
||||
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
||||
'_get_serial_ports_from_guest')
|
||||
@mock.patch('nova.console.serial.acquire_port')
|
||||
@mock.patch('nova.virt.hardware.get_number_of_serial_ports',
|
||||
return_value=1)
|
||||
@mock.patch.object(libvirt_driver.libvirt_utils, 'get_arch',)
|
||||
def test_create_serial_console_devices_based_on_arch(self, mock_get_arch,
|
||||
mock_get_port_number,
|
||||
mock_acquire_port):
|
||||
mock_get_port_number,
|
||||
mock_acquire_port,
|
||||
mock_ports,
|
||||
mock_guest):
|
||||
self.flags(enabled=True, group='serial_console')
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
instance = objects.Instance(**self.test_instance)
|
||||
|
||||
expected = {arch.X86_64: vconfig.LibvirtConfigGuestSerial,
|
||||
arch.S390: vconfig.LibvirtConfigGuestConsole,
|
||||
|
@ -3605,19 +3611,22 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
for guest_arch, device_type in expected.items():
|
||||
mock_get_arch.return_value = guest_arch
|
||||
guest = vconfig.LibvirtConfigGuest()
|
||||
drvr._create_serial_console_devices(guest, instance=None,
|
||||
drvr._create_serial_console_devices(guest, instance=instance,
|
||||
flavor={}, image_meta={})
|
||||
self.assertEqual(1, len(guest.devices))
|
||||
console_device = guest.devices[0]
|
||||
self.assertIsInstance(console_device, device_type)
|
||||
self.assertEqual("tcp", console_device.type)
|
||||
|
||||
@mock.patch.object(host.Host, 'get_guest')
|
||||
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
||||
'_get_serial_ports_from_guest')
|
||||
@mock.patch('nova.virt.hardware.get_number_of_serial_ports',
|
||||
return_value=4)
|
||||
@mock.patch.object(libvirt_driver.libvirt_utils, 'get_arch',
|
||||
side_effect=[arch.X86_64, arch.S390, arch.S390X])
|
||||
def test_create_serial_console_devices_with_limit_exceeded_based_on_arch(
|
||||
self, mock_get_arch, mock_get_port_number):
|
||||
self, mock_get_arch, mock_get_port_number, mock_ports, mock_guest):
|
||||
self.flags(enabled=True, group='serial_console')
|
||||
self.flags(virt_type="qemu", group='libvirt')
|
||||
flavor = 'fake_flavor'
|
||||
|
@ -7841,24 +7850,27 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
drvr._get_volume_config)
|
||||
self.assertEqual(target_xml, config)
|
||||
|
||||
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
||||
'_get_serial_ports_from_guest')
|
||||
@mock.patch.object(fakelibvirt.virDomain, "migrateToURI2")
|
||||
@mock.patch.object(fakelibvirt.virDomain, "XMLDesc")
|
||||
def test_live_migration_update_serial_console_xml(self, mock_xml,
|
||||
mock_migrate):
|
||||
mock_migrate, mock_get):
|
||||
self.compute = importutils.import_object(CONF.compute_manager)
|
||||
instance_ref = self.test_instance
|
||||
|
||||
xml_tmpl = ("<domain type='kvm'>"
|
||||
"<devices>"
|
||||
"<console type='tcp'>"
|
||||
"<source mode='bind' host='{addr}' service='10000'/>"
|
||||
"<source mode='bind' host='{addr}' service='{port}'/>"
|
||||
"<target type='serial' port='0'/>"
|
||||
"</console>"
|
||||
"</devices>"
|
||||
"</domain>")
|
||||
|
||||
initial_xml = xml_tmpl.format(addr='9.0.0.1')
|
||||
initial_xml = xml_tmpl.format(addr='9.0.0.1', port='10100')
|
||||
|
||||
target_xml = xml_tmpl.format(addr='9.0.0.12')
|
||||
target_xml = xml_tmpl.format(addr='9.0.0.12', port='10200')
|
||||
target_xml = etree.tostring(etree.fromstring(target_xml))
|
||||
|
||||
# Preparing mocks
|
||||
|
@ -7873,7 +7885,8 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
serial_listen_addr='9.0.0.12',
|
||||
target_connect_addr=None,
|
||||
bdms=[],
|
||||
block_migration=False)
|
||||
block_migration=False,
|
||||
serial_listen_ports=[10200])
|
||||
dom = fakelibvirt.virDomain
|
||||
guest = libvirt_guest.Guest(dom)
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
||||
|
|
|
@ -4080,6 +4080,19 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
guest_arch = libvirt_utils.get_arch(image_meta)
|
||||
|
||||
if CONF.serial_console.enabled:
|
||||
try:
|
||||
# TODO(sahid): the guest param of this method should
|
||||
# be renamed as guest_cfg then guest_obj to guest.
|
||||
guest_obj = self._host.get_guest(instance)
|
||||
if list(self._get_serial_ports_from_guest(guest_obj)):
|
||||
# Serial port are already configured for instance that
|
||||
# means we are in a context of migration.
|
||||
return
|
||||
except exception.InstanceNotFound:
|
||||
LOG.debug(
|
||||
"Instance does not exist yet on libvirt, we can "
|
||||
"safely pass on looking for already defined serial "
|
||||
"ports in its domain XML", instance=instance)
|
||||
num_ports = hardware.get_number_of_serial_ports(
|
||||
flavor, image_meta)
|
||||
|
||||
|
@ -5950,12 +5963,25 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
libvirt.VIR_MIGRATE_TUNNELLED != 0):
|
||||
params.pop('migrate_disks')
|
||||
|
||||
# TODO(sahid): This should be in
|
||||
# post_live_migration_at_source but no way to retrieve
|
||||
# ports acquired on the host for the guest at this
|
||||
# step. Since the domain is going to be removed from
|
||||
# libvird on source host after migration, we backup the
|
||||
# serial ports to release them if all went well.
|
||||
serial_ports = []
|
||||
if CONF.serial_console.enabled:
|
||||
serial_ports = list(self._get_serial_ports_from_guest(guest))
|
||||
|
||||
guest.migrate(self._live_migration_uri(dest),
|
||||
migrate_uri=migrate_uri,
|
||||
flags=migration_flags,
|
||||
params=params,
|
||||
domain_xml=new_xml_str,
|
||||
bandwidth=CONF.libvirt.live_migration_bandwidth)
|
||||
|
||||
for hostname, port in serial_ports:
|
||||
serial_console.release_port(host=hostname, port=port)
|
||||
except Exception as e:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE("Live Migration failure: %s"), e,
|
||||
|
@ -6448,6 +6474,13 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
is_shared_instance_path = True
|
||||
if migrate_data:
|
||||
is_shared_instance_path = migrate_data.is_shared_instance_path
|
||||
if (migrate_data.obj_attr_is_set("serial_listen_ports")
|
||||
and migrate_data.serial_listen_ports):
|
||||
# Releases serial ports reserved.
|
||||
for port in migrate_data.serial_listen_ports:
|
||||
serial_console.release_port(
|
||||
host=migrate_data.serial_listen_addr, port=port)
|
||||
|
||||
if not is_shared_instance_path:
|
||||
instance_dir = libvirt_utils.get_instance_path_at_destination(
|
||||
instance, migrate_data)
|
||||
|
@ -6579,6 +6612,15 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
CONF.libvirt.live_migration_inbound_addr
|
||||
migrate_data.supported_perf_events = self._supported_perf_events
|
||||
|
||||
migrate_data.serial_listen_ports = []
|
||||
if CONF.serial_console.enabled:
|
||||
num_ports = hardware.get_number_of_serial_ports(
|
||||
instance.flavor, instance.image_meta)
|
||||
for port in six.moves.range(num_ports):
|
||||
migrate_data.serial_listen_ports.append(
|
||||
serial_console.acquire_port(
|
||||
migrate_data.serial_listen_addr))
|
||||
|
||||
for vol in block_device_mapping:
|
||||
connection_info = vol['connection_info']
|
||||
if connection_info.get('serial'):
|
||||
|
|
Loading…
Reference in New Issue