Coverage for nova/virt/driver.py: 80%
369 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-04-24 11:16 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-04-24 11:16 +0000
1# Copyright 2011 Justin Santa Barbara
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
16"""
17Driver base-classes:
19 (Beginning of) the contract that compute drivers must follow, and shared
20 types that support that contract
21"""
23import dataclasses
24import itertools
25import sys
26import time
27import typing as ty
29import os_resource_classes as orc
30import os_traits
32from oslo_log import log as logging
33from oslo_utils import importutils
35import nova.conf
36import nova.virt.node
38from nova import context as nova_context
39from nova.i18n import _
40from nova.network import model as network_model
41from nova import objects
42from nova import version
43from nova.virt import event as virtevent
45CONF = nova.conf.CONF
46LOG = logging.getLogger(__name__)
49@dataclasses.dataclass
50class FlavorMeta:
51 name: str
52 memory_mb: int
53 vcpus: int
54 root_gb: int
55 ephemeral_gb: int
56 extra_specs: dict
57 swap: int
60@dataclasses.dataclass
61class ImageMeta:
62 id: str
63 name: str
64 properties: dict
67@dataclasses.dataclass
68class NovaInstanceMeta:
69 name: str
70 uuid: str
73@dataclasses.dataclass
74class OwnerMeta:
75 userid: str
76 username: str
77 projectid: str
78 projectname: str
81@dataclasses.dataclass
82class InstanceDriverMetadata:
83 root_type: str
84 root_id: str
85 instance_meta: NovaInstanceMeta
86 owner: OwnerMeta
87 image: ImageMeta
88 flavor: FlavorMeta
89 network_info: network_model.NetworkInfo
90 nova_package: str = dataclasses.field(
91 default_factory=version.version_string_with_package)
92 creation_time: float = dataclasses.field(default_factory=time.time)
95def get_block_device_info(instance, block_device_mapping):
96 """Converts block device mappings for an instance to driver format.
98 Virt drivers expect block device mapping to be presented in the format
99 of a dict containing the following keys:
101 - root_device_name: device name of the root disk
102 - image: An instance of DriverImageBlockDevice or None
103 - ephemerals: a (potentially empty) list of DriverEphemeralBlockDevice
104 instances
105 - swap: An instance of DriverSwapBlockDevice or None
106 - block_device_mapping: a (potentially empty) list of
107 DriverVolumeBlockDevice or any of it's more
108 specialized subclasses.
109 """
110 from nova.virt import block_device as virt_block_device
111 return {
112 'root_device_name': instance.root_device_name,
113 'image': virt_block_device.convert_local_images(
114 block_device_mapping),
115 'ephemerals': virt_block_device.convert_ephemerals(
116 block_device_mapping),
117 'block_device_mapping':
118 virt_block_device.convert_all_volumes(*block_device_mapping),
119 'swap':
120 virt_block_device.get_swap(
121 virt_block_device.convert_swap(block_device_mapping))
122 }
125def block_device_info_get_root_device(block_device_info):
126 block_device_info = block_device_info or {}
127 return block_device_info.get('root_device_name')
130def block_device_info_get_swap(block_device_info):
131 block_device_info = block_device_info or {}
132 return block_device_info.get('swap') or {'device_name': None,
133 'swap_size': 0}
136def swap_is_usable(swap):
137 return swap and swap['device_name'] and swap['swap_size'] > 0
140def block_device_info_get_image(block_device_info):
141 block_device_info = block_device_info or {}
142 # get_disk_mapping() supports block_device_info=None and thus requires that
143 # we return a list here.
144 image = block_device_info.get('image') or []
145 return image
148def block_device_info_get_ephemerals(block_device_info):
149 block_device_info = block_device_info or {}
150 ephemerals = block_device_info.get('ephemerals') or []
151 return ephemerals
154def block_device_info_get_mapping(block_device_info):
155 block_device_info = block_device_info or {}
156 block_device_mapping = block_device_info.get('block_device_mapping') or []
157 return block_device_mapping
160def block_device_info_get_encrypted_disks(
161 block_device_info: ty.Mapping[str, ty.Any],
162) -> ty.List['nova.virt.block_device.DriverBlockDevice']:
163 block_device_info = block_device_info or {}
165 # swap is a single device, not a list
166 swap = block_device_info.get('swap')
167 swap = [swap] if swap else []
169 return [
170 driver_bdm for driver_bdm in itertools.chain(
171 block_device_info.get('image', []),
172 block_device_info.get('ephemerals', []),
173 swap,
174 )
175 if driver_bdm.get('encrypted')
176 ]
179# NOTE(aspiers): When adding new capabilities, ensure they are
180# mirrored in ComputeDriver.capabilities, and that the corresponding
181# values should always be standard traits in os_traits. If something
182# isn't a standard trait, it doesn't need to be a compute node
183# capability trait; and if it needs to be a compute node capability
184# trait, it needs to be (made) standard, and must be prefixed with
185# "COMPUTE_".
186CAPABILITY_TRAITS_MAP = {
187 "supports_attach_interface": os_traits.COMPUTE_NET_ATTACH_INTERFACE,
188 "supports_device_tagging": os_traits.COMPUTE_DEVICE_TAGGING,
189 "supports_tagged_attach_interface":
190 os_traits.COMPUTE_NET_ATTACH_INTERFACE_WITH_TAG,
191 "supports_tagged_attach_volume": os_traits.COMPUTE_VOLUME_ATTACH_WITH_TAG,
192 "supports_extend_volume": os_traits.COMPUTE_VOLUME_EXTEND,
193 "supports_multiattach": os_traits.COMPUTE_VOLUME_MULTI_ATTACH,
194 "supports_trusted_certs": os_traits.COMPUTE_TRUSTED_CERTS,
195 "supports_accelerators": os_traits.COMPUTE_ACCELERATORS,
196 "supports_image_type_aki": os_traits.COMPUTE_IMAGE_TYPE_AKI,
197 "supports_image_type_ami": os_traits.COMPUTE_IMAGE_TYPE_AMI,
198 "supports_image_type_ari": os_traits.COMPUTE_IMAGE_TYPE_ARI,
199 "supports_image_type_iso": os_traits.COMPUTE_IMAGE_TYPE_ISO,
200 "supports_image_type_qcow2": os_traits.COMPUTE_IMAGE_TYPE_QCOW2,
201 "supports_image_type_raw": os_traits.COMPUTE_IMAGE_TYPE_RAW,
202 "supports_image_type_vdi": os_traits.COMPUTE_IMAGE_TYPE_VDI,
203 "supports_image_type_vhd": os_traits.COMPUTE_IMAGE_TYPE_VHD,
204 "supports_image_type_vhdx": os_traits.COMPUTE_IMAGE_TYPE_VHDX,
205 "supports_image_type_vmdk": os_traits.COMPUTE_IMAGE_TYPE_VMDK,
206 "supports_image_type_ploop": os_traits.COMPUTE_IMAGE_TYPE_PLOOP,
207 "supports_migrate_to_same_host": os_traits.COMPUTE_SAME_HOST_COLD_MIGRATE,
208 "supports_bfv_rescue": os_traits.COMPUTE_RESCUE_BFV,
209 "supports_secure_boot": os_traits.COMPUTE_SECURITY_UEFI_SECURE_BOOT,
210 "supports_socket_pci_numa_affinity":
211 os_traits.COMPUTE_SOCKET_PCI_NUMA_AFFINITY,
212 "supports_remote_managed_ports": os_traits.COMPUTE_REMOTE_MANAGED_PORTS,
213 "supports_ephemeral_encryption": os_traits.COMPUTE_EPHEMERAL_ENCRYPTION,
214 "supports_ephemeral_encryption_luks":
215 os_traits.COMPUTE_EPHEMERAL_ENCRYPTION_LUKS,
216 "supports_ephemeral_encryption_plain":
217 os_traits.COMPUTE_EPHEMERAL_ENCRYPTION_PLAIN,
218 "supports_address_space_passthrough":
219 os_traits.COMPUTE_ADDRESS_SPACE_PASSTHROUGH,
220 "supports_address_space_emulated":
221 os_traits.COMPUTE_ADDRESS_SPACE_EMULATED,
222 "supports_stateless_firmware":
223 os_traits.COMPUTE_SECURITY_STATELESS_FIRMWARE,
224 "supports_virtio_fs": os_traits.COMPUTE_STORAGE_VIRTIO_FS,
225 "supports_mem_backing_file": os_traits.COMPUTE_MEM_BACKING_FILE,
226}
229def _check_image_type_exclude_list(capability, supported):
230 """Enforce the exclusion list on image_type capabilities.
232 :param capability: The supports_image_type_foo capability being checked
233 :param supported: The flag indicating whether the virt driver *can*
234 support the given image type.
235 :returns: True if the virt driver *can* support the image type and
236 if it is not listed in the config to be excluded.
237 """
238 image_type = capability.replace('supports_image_type_', '')
239 return (supported and
240 image_type not in CONF.compute.image_type_exclude_list)
243class ComputeDriver(object):
244 """Base class for compute drivers.
246 The interface to this class talks in terms of 'instances' (Amazon EC2 and
247 internal Nova terminology), by which we mean 'running virtual machine' or
248 domain (libvirt terminology).
250 An instance has an ID, which is the identifier chosen by Nova to represent
251 the instance further up the stack. This is unfortunately also called a
252 'name' elsewhere. As far as this layer is concerned, 'instance ID' and
253 'instance name' are synonyms.
255 Note that the instance ID or name is not human-readable or
256 customer-controlled -- it's an internal ID chosen by Nova. At the
257 nova.virt layer, instances do not have human-readable names at all -- such
258 things are only known higher up the stack.
260 Most virtualization platforms will also have their own identity schemes,
261 to uniquely identify a VM or domain. These IDs must stay internal to the
262 platform-specific layer, and never escape the connection interface. The
263 platform-specific layer is responsible for keeping track of which instance
264 ID maps to which platform-specific ID, and vice versa.
266 Some methods here take an instance of nova.compute.service.Instance. This
267 is the data structure used by nova.compute to store details regarding an
268 instance, and pass them into this layer. This layer is responsible for
269 translating that generic data structure into terms that are specific to the
270 virtualization platform.
272 """
274 # NOTE(mriedem): When adding new capabilities, consider whether they
275 # should also be added to CAPABILITY_TRAITS_MAP; if so, any new traits
276 # must also be added to the os-traits library.
277 capabilities = {
278 "has_imagecache": False,
279 "supports_evacuate": False,
280 "supports_migrate_to_same_host": False,
281 "supports_attach_interface": False,
282 "supports_device_tagging": False,
283 "supports_tagged_attach_interface": False,
284 "supports_tagged_attach_volume": False,
285 "supports_extend_volume": False,
286 "supports_multiattach": False,
287 "supports_trusted_certs": False,
288 "supports_pcpus": False,
289 "supports_accelerators": False,
290 "supports_bfv_rescue": False,
291 "supports_vtpm": False,
292 "supports_secure_boot": False,
293 "supports_socket_pci_numa_affinity": False,
294 "supports_remote_managed_ports": False,
295 "supports_address_space_passthrough": False,
296 "supports_address_space_emulated": False,
297 "supports_virtio_fs": False,
298 "supports_mem_backing_file": False,
300 # Ephemeral encryption support flags
301 "supports_ephemeral_encryption": False,
302 "supports_ephemeral_encryption_luks": False,
303 "supports_ephemeral_encryption_plain": False,
305 # Image type support flags
306 "supports_image_type_aki": False,
307 "supports_image_type_ami": False,
308 "supports_image_type_ari": False,
309 "supports_image_type_iso": False,
310 "supports_image_type_qcow2": False,
311 "supports_image_type_raw": False,
312 "supports_image_type_vdi": False,
313 "supports_image_type_vhd": False,
314 "supports_image_type_vhdx": False,
315 "supports_image_type_vmdk": False,
316 "supports_image_type_ploop": False,
317 }
319 # Indicates if this driver will rebalance nodes among compute service
320 # hosts. This is really here for ironic and should not be used by any
321 # other driver.
322 rebalances_nodes = False
324 def __init__(self, virtapi):
325 self.virtapi = virtapi
326 self._compute_event_callback = None
328 def init_host(self, host):
329 """Initialize anything that is necessary for the driver to function,
330 including catching up with currently running VM's on the given host.
331 """
332 # TODO(Vek): Need to pass context in for access to auth_token
333 raise NotImplementedError()
335 def cleanup_host(self, host):
336 """Clean up anything that is necessary for the driver gracefully stop,
337 including ending remote sessions. This is optional.
338 """
339 pass
341 def get_info(self, instance, use_cache=True):
342 """Get the current status of an instance.
344 :param instance: nova.objects.instance.Instance object
345 :param use_cache: boolean to indicate if the driver should be allowed
346 to use cached data to return instance status.
347 This only applies to drivers which cache instance
348 state information. For drivers that do not use a
349 cache, this parameter can be ignored.
350 :returns: An InstanceInfo object
351 """
352 # TODO(Vek): Need to pass context in for access to auth_token
353 raise NotImplementedError()
355 @classmethod
356 def get_instance_driver_metadata(
357 cls, instance: 'nova.objects.instance.Instance',
358 network_info: network_model.NetworkInfo
359 ) -> InstanceDriverMetadata:
360 """Get driver metadata from instance and network info
362 :param instance: nova.objects.instance.Instance
363 :param network_info: instance network information
364 :returns: InstanceDriverMetadata
365 """
367 instance_name = instance.display_name or instance.uuid
368 system_meta = instance.system_metadata
369 instance_meta = NovaInstanceMeta(
370 str(instance_name), str(instance.uuid))
371 owner = OwnerMeta(
372 userid=instance.user_id,
373 username=system_meta.get('owner_user_name', 'N/A'),
374 projectid=instance.project_id,
375 projectname=system_meta.get('owner_project_name', 'N/A')
376 )
377 flavor = FlavorMeta(
378 name=instance.flavor.name,
379 memory_mb=instance.flavor.memory_mb,
380 vcpus=instance.flavor.vcpus,
381 ephemeral_gb=instance.flavor.ephemeral_gb,
382 root_gb=instance.flavor.root_gb,
383 swap=instance.flavor.swap,
384 extra_specs=instance.flavor.extra_specs,
385 )
386 image = ImageMeta(
387 id=instance.image_ref,
388 name=system_meta.get('image_name'),
389 properties=instance.image_meta.properties
390 )
391 meta = InstanceDriverMetadata(
392 instance_meta=instance_meta,
393 owner=owner,
394 flavor=flavor,
395 image=image,
396 root_type = 'image' if instance.image_ref else 'volume',
397 root_id = instance.image_ref,
398 creation_time = time.time(),
399 network_info=network_info
400 )
401 LOG.debug('InstanceDriverMetadata: %s', meta)
402 return meta
404 def get_num_instances(self):
405 """Return the total number of virtual machines.
407 Return the number of virtual machines that the hypervisor knows
408 about.
410 .. note::
412 This implementation works for all drivers, but it is
413 not particularly efficient. Maintainers of the virt drivers are
414 encouraged to override this method with something more
415 efficient.
416 """
417 return len(self.list_instances())
419 def instance_exists(self, instance):
420 """Checks existence of an instance on the host.
422 :param instance: The instance to lookup
424 Returns True if an instance with the supplied ID exists on
425 the host, False otherwise.
427 .. note::
429 This implementation works for all drivers, but it is
430 not particularly efficient. Maintainers of the virt drivers are
431 encouraged to override this method with something more
432 efficient.
433 """
434 try:
435 return instance.uuid in self.list_instance_uuids()
436 except NotImplementedError:
437 return instance.name in self.list_instances()
439 def list_instances(self):
440 """Return the names of all the instances known to the virtualization
441 layer, as a list.
442 """
443 # TODO(Vek): Need to pass context in for access to auth_token
444 raise NotImplementedError()
446 def list_instance_uuids(self):
447 """Return the UUIDS of all the instances known to the virtualization
448 layer, as a list.
449 """
450 raise NotImplementedError()
452 def rebuild(self, context, instance, image_meta, injected_files,
453 admin_password, allocations, bdms, detach_block_devices,
454 attach_block_devices, network_info=None,
455 evacuate=False, block_device_info=None,
456 preserve_ephemeral=False, accel_uuids=None,
457 reimage_boot_volume=False):
458 """Destroy and re-make this instance.
460 A 'rebuild' effectively purges all existing data from the system and
461 remakes the VM with given 'metadata' and 'personalities'.
463 This base class method shuts down the VM, detaches all block devices,
464 then spins up the new VM afterwards. It may be overridden by
465 hypervisors that need to - e.g. for optimisations, or when the 'VM'
466 is actually proxied and needs to be held across the shutdown + spin
467 up steps.
469 :param context: security context
470 :param instance: nova.objects.instance.Instance
471 This function should use the data there to guide
472 the creation of the new instance.
473 :param nova.objects.ImageMeta image_meta:
474 The metadata of the image of the instance.
475 :param injected_files: User files to inject into instance.
476 :param admin_password: Administrator password to set in instance.
477 :param allocations: Information about resources allocated to the
478 instance via placement, of the form returned by
479 SchedulerReportClient.get_allocations_for_consumer.
480 :param bdms: block-device-mappings to use for rebuild
481 :param detach_block_devices: function to detach block devices. See
482 nova.compute.manager.ComputeManager:_rebuild_default_impl for
483 usage.
484 :param attach_block_devices: function to attach block devices. See
485 nova.compute.manager.ComputeManager:_rebuild_default_impl for
486 usage.
487 :param network_info: instance network information
488 :param evacuate: True if the instance is being recreated on a new
489 hypervisor - all the cleanup of old state is skipped.
490 :param block_device_info: Information about block devices to be
491 attached to the instance.
492 :param preserve_ephemeral: True if the default ephemeral storage
493 partition must be preserved on rebuild
494 :param accel_uuids: Accelerator UUIDs.
495 :param reimage_boot_volume: Re-image the volume backed instance.
496 """
497 raise NotImplementedError()
499 def prepare_for_spawn(self, instance):
500 """Prepare to spawn instance.
502 Perform any pre-flight checks, tagging, etc. that the virt driver
503 must perform before executing the spawn process for a new instance.
505 :param instance: nova.objects.instance.Instance
506 This function should use the data there to guide
507 the creation of the new instance.
508 """
509 pass
511 def failed_spawn_cleanup(self, instance):
512 """Cleanup from the instance spawn.
514 Perform any hypervisor clean-up required should the spawn operation
515 fail, such as the removal of tags that were added during the
516 prepare_for_spawn method.
518 This method should be idempotent.
520 :param instance: nova.objects.instance.Instance
521 This function should use the data there to guide
522 the creation of the new instance.
524 """
525 pass
527 def spawn(self, context, instance, image_meta, injected_files,
528 admin_password, allocations, network_info=None,
529 block_device_info=None, power_on=True, accel_info=None):
530 """Create a new instance/VM/domain on the virtualization platform.
532 Once this successfully completes, the instance should be
533 running (power_state.RUNNING) if ``power_on`` is True, else the
534 instance should be stopped (power_state.SHUTDOWN).
536 If this fails, any partial instance should be completely
537 cleaned up, and the virtualization platform should be in the state
538 that it was before this call began.
540 :param context: security context
541 :param instance: nova.objects.instance.Instance
542 This function should use the data there to guide
543 the creation of the new instance.
544 :param nova.objects.ImageMeta image_meta:
545 The metadata of the image of the instance.
546 :param injected_files: User files to inject into instance.
547 :param admin_password: Administrator password to set in instance.
548 :param allocations: Information about resources allocated to the
549 instance via placement, of the form returned by
550 SchedulerReportClient.get_allocations_for_consumer.
551 :param network_info: instance network information
552 :param block_device_info: Information about block devices to be
553 attached to the instance.
554 :param power_on: True if the instance should be powered on, False
555 otherwise
556 :param arqs: List of bound accelerator requests for this instance.
557 [
558 {'uuid': $arq_uuid,
559 'device_profile_name': $dp_name,
560 'device_profile_group_id': $dp_request_group_index,
561 'state': 'Bound',
562 'device_rp_uuid': $resource_provider_uuid,
563 'hostname': $host_nodename,
564 'instance_uuid': $instance_uuid,
565 'attach_handle_info': { # PCI bdf
566 'bus': '0c', 'device': '0', 'domain': '0000', 'function': '0'},
567 'attach_handle_type': 'PCI'
568 # or 'TEST_PCI' for Cyborg fake driver
569 }
570 ]
571 Also doc'd in nova/accelerator/cyborg.py::get_arqs_for_instance()
572 """
573 raise NotImplementedError()
575 def destroy(self, context, instance, network_info, block_device_info=None,
576 destroy_disks=True, destroy_secrets=True):
577 """Destroy the specified instance from the Hypervisor.
579 If the instance is not found (for example if networking failed), this
580 function should still succeed. It's probably a good idea to log a
581 warning in that case.
583 :param context: security context
584 :param instance: Instance object as returned by DB layer.
585 :param network_info: instance network information
586 :param block_device_info: Information about block devices that should
587 be detached from the instance.
588 :param destroy_disks: Indicates if disks should be destroyed
589 :param destroy_secrets: Indicates if secrets should be destroyed
590 """
591 raise NotImplementedError()
593 def cleanup(self, context, instance, network_info, block_device_info=None,
594 destroy_disks=True, migrate_data=None, destroy_vifs=True,
595 destroy_secrets=True):
596 """Cleanup the instance resources .
598 Instance should have been destroyed from the Hypervisor before calling
599 this method.
601 :param context: security context
602 :param instance: Instance object as returned by DB layer.
603 :param network_info: instance network information
604 :param block_device_info: Information about block devices that should
605 be detached from the instance.
606 :param destroy_disks: Indicates if disks should be destroyed
607 :param migrate_data: implementation specific params
608 :param destroy_vifs: Indicates if vifs should be unplugged
609 :param destroy_secrets: Indicates if secrets should be destroyed
610 """
611 raise NotImplementedError()
613 def reboot(self, context, instance, network_info, reboot_type,
614 block_device_info=None, bad_volumes_callback=None,
615 accel_info=None, share_info=None):
616 """Reboot the specified instance.
618 After this is called successfully, the instance's state
619 goes back to power_state.RUNNING. The virtualization
620 platform should ensure that the reboot action has completed
621 successfully even in cases in which the underlying domain/vm
622 is paused or halted/stopped.
624 :param instance: nova.objects.instance.Instance
625 :param network_info: instance network information
626 :param reboot_type: Either a HARD or SOFT reboot
627 :param block_device_info: Info pertaining to attached volumes
628 :param bad_volumes_callback: Function to handle any bad volumes
629 encountered
630 :param accel_info: List of accelerator request dicts. The exact
631 data struct is doc'd in nova/virt/driver.py::spawn().
632 """
633 raise NotImplementedError()
635 def get_console_output(self, context, instance):
636 """Get console output for an instance
638 :param context: security context
639 :param instance: nova.objects.instance.Instance
640 """
641 raise NotImplementedError()
643 def get_vnc_console(self, context, instance):
644 """Get connection info for a vnc console.
646 :param context: security context
647 :param instance: nova.objects.instance.Instance
649 :returns: an instance of console.type.ConsoleVNC
650 """
651 raise NotImplementedError()
653 def get_spice_console(self, context, instance):
654 """Get connection info for a spice console.
656 :param context: security context
657 :param instance: nova.objects.instance.Instance
659 :returns: an instance of console.type.ConsoleSpice
660 """
661 raise NotImplementedError()
663 def get_serial_console(self, context, instance):
664 """Get connection info for a serial console.
666 :param context: security context
667 :param instance: nova.objects.instance.Instance
669 :returns: an instance of console.type.ConsoleSerial
670 """
671 raise NotImplementedError()
673 def get_mks_console(self, context, instance):
674 """Get connection info for a MKS console.
676 :param context: security context
677 :param instance: nova.objects.instance.Instance
679 :returns an instance of console.type.ConsoleMKS
680 """
681 raise NotImplementedError()
683 def get_diagnostics(self, instance):
684 """Return diagnostics data about the given instance.
686 :param nova.objects.instance.Instance instance:
687 The instance to which the diagnostic data should be returned.
689 :return: Has a big overlap to the return value of the newer interface
690 :func:`get_instance_diagnostics`
691 :rtype: dict
692 """
693 # TODO(Vek): Need to pass context in for access to auth_token
694 raise NotImplementedError()
696 def get_instance_diagnostics(self, instance):
697 """Return diagnostics data about the given instance.
699 :param nova.objects.instance.Instance instance:
700 The instance to which the diagnostic data should be returned.
702 :return: Has a big overlap to the return value of the older interface
703 :func:`get_diagnostics`
704 :rtype: nova.virt.diagnostics.Diagnostics
705 """
706 raise NotImplementedError()
708 def get_all_volume_usage(self, context, compute_host_bdms):
709 """Return usage info for volumes attached to vms on
710 a given host.-
711 """
712 raise NotImplementedError()
714 def get_host_ip_addr(self):
715 """Retrieves the IP address of the host running compute service
716 """
717 # TODO(Vek): Need to pass context in for access to auth_token
718 raise NotImplementedError()
720 def attach_volume(self, context, connection_info, instance, mountpoint,
721 disk_bus=None, device_type=None, encryption=None):
722 """Attach the disk to the instance at mountpoint using info.
724 :raises TooManyDiskDevices: if the maximum allowed devices to attach
725 to a single instance is exceeded.
726 """
727 raise NotImplementedError()
729 def detach_volume(self, context, connection_info, instance, mountpoint,
730 encryption=None):
731 """Detach the disk attached to the instance."""
732 raise NotImplementedError()
734 def swap_volume(self, context, old_connection_info, new_connection_info,
735 instance, mountpoint, resize_to):
736 """Replace the volume attached to the given `instance`.
738 :param context: The request context.
739 :param dict old_connection_info:
740 The volume for this connection gets detached from the given
741 `instance`.
742 :param dict new_connection_info:
743 The volume for this connection gets attached to the given
744 'instance'.
745 :param nova.objects.instance.Instance instance:
746 The instance whose volume gets replaced by another one.
747 :param str mountpoint:
748 The mountpoint in the instance where the volume for
749 `old_connection_info` is attached to.
750 :param int resize_to:
751 If the new volume is larger than the old volume, it gets resized
752 to the given size (in Gigabyte) of `resize_to`.
754 :return: None
755 """
756 raise NotImplementedError()
758 def extend_volume(self, context, connection_info, instance,
759 requested_size):
760 """Extend the disk attached to the instance.
762 :param context: The request context.
763 :param dict connection_info:
764 The connection for the extended volume.
765 :param nova.objects.instance.Instance instance:
766 The instance whose volume gets extended.
767 :param int requested_size
768 The requested new size of the volume in bytes
770 :return: None
771 """
772 raise NotImplementedError()
774 def prepare_networks_before_block_device_mapping(self, instance,
775 network_info):
776 """Prepare networks before the block devices are mapped to instance.
778 Drivers who need network information for block device preparation can
779 do some network preparation necessary for block device preparation.
781 :param nova.objects.instance.Instance instance:
782 The instance whose networks are prepared.
783 :param nova.network.model.NetworkInfoAsyncWrapper network_info:
784 The network information of the given `instance`.
785 """
786 pass
788 def clean_networks_preparation(self, instance, network_info):
789 """Clean networks preparation when block device mapping is failed.
791 Drivers who need network information for block device preparaion should
792 clean the preparation when block device mapping is failed.
794 :param nova.objects.instance.Instance instance:
795 The instance whose networks are prepared.
796 :param nova.network.model.NetworkInfoAsyncWrapper network_info:
797 The network information of the given `instance`.
798 """
799 pass
801 def attach_interface(self, context, instance, image_meta, vif):
802 """Use hotplug to add a network interface to a running instance.
804 The counter action to this is :func:`detach_interface`.
806 :param context: The request context.
807 :param nova.objects.instance.Instance instance:
808 The instance which will get an additional network interface.
809 :param nova.objects.ImageMeta image_meta:
810 The metadata of the image of the instance.
811 :param nova.network.model.VIF vif:
812 The object which has the information about the interface to attach.
814 :raise nova.exception.NovaException: If the attach fails.
816 :return: None
817 """
818 raise NotImplementedError()
820 def detach_interface(self, context, instance, vif):
821 """Use hotunplug to remove a network interface from a running instance.
823 The counter action to this is :func:`attach_interface`.
825 :param context: The request context.
826 :param nova.objects.instance.Instance instance:
827 The instance which gets a network interface removed.
828 :param nova.network.model.VIF vif:
829 The object which has the information about the interface to detach.
831 :raise nova.exception.NovaException: If the detach fails.
833 :return: None
834 """
835 raise NotImplementedError()
837 def migrate_disk_and_power_off(self, context, instance, dest,
838 flavor, network_info,
839 block_device_info=None,
840 timeout=0, retry_interval=0):
841 """Transfers the disk of a running instance in multiple phases, turning
842 off the instance before the end.
844 :param nova.objects.instance.Instance instance:
845 The instance whose disk should be migrated.
846 :param str dest:
847 The IP address of the destination host.
848 :param nova.objects.flavor.Flavor flavor:
849 The flavor of the instance whose disk get migrated.
850 :param nova.network.model.NetworkInfo network_info:
851 The network information of the given `instance`.
852 :param dict block_device_info:
853 Information about the block devices.
854 :param int timeout:
855 The time in seconds to wait for the guest OS to shutdown.
856 :param int retry_interval:
857 How often to signal guest while waiting for it to shutdown.
859 :return: A list of disk information dicts in JSON format.
860 :rtype: str
861 """
862 raise NotImplementedError()
864 def snapshot(self, context, instance, image_id, update_task_state):
865 """Snapshots the specified instance.
867 :param context: security context
868 :param instance: nova.objects.instance.Instance
869 :param image_id: Reference to a pre-created image that will
870 hold the snapshot.
871 :param update_task_state: Callback function to update the task_state
872 on the instance while the snapshot operation progresses. The
873 function takes a task_state argument and an optional
874 expected_task_state kwarg which defaults to
875 nova.compute.task_states.IMAGE_SNAPSHOT. See
876 nova.objects.instance.Instance.save for expected_task_state usage.
877 """
878 raise NotImplementedError()
880 def finish_migration(self, context, migration, instance, disk_info,
881 network_info, image_meta, resize_instance,
882 allocations, block_device_info=None, power_on=True):
883 """Completes a resize/migration.
885 :param context: the context for the migration/resize
886 :param migration: the migrate/resize information
887 :param instance: nova.objects.instance.Instance being migrated/resized
888 :param disk_info: the newly transferred disk information
889 :param network_info: instance network information
890 :param nova.objects.ImageMeta image_meta:
891 The metadata of the image of the instance.
892 :param resize_instance: True if the instance is being resized,
893 False otherwise
894 :param allocations: Information about resources allocated to the
895 instance via placement, of the form returned by
896 SchedulerReportClient.get_allocs_for_consumer.
897 :param block_device_info: instance volume block device info
898 :param power_on: True if the instance should be powered on, False
899 otherwise
900 """
901 raise NotImplementedError()
903 def confirm_migration(self, context, migration, instance, network_info):
904 """Confirms a resize/migration, destroying the source VM.
906 :param instance: nova.objects.instance.Instance
907 """
908 raise NotImplementedError()
910 def finish_revert_migration(self, context, instance, network_info,
911 migration, block_device_info=None,
912 power_on=True):
913 """Finish reverting a resize/migration.
915 :param context: the context for the finish_revert_migration
916 :param instance: nova.objects.instance.Instance being migrated/resized
917 :param network_info: instance network information
918 :param migration: nova.objects.Migration for the migration
919 :param block_device_info: instance volume block device info
920 :param power_on: True if the instance should be powered on, False
921 otherwise
922 """
923 raise NotImplementedError()
925 def pause(self, instance):
926 """Pause the given instance.
928 A paused instance doesn't use CPU cycles of the host anymore. The
929 state of the VM could be stored in the memory or storage space of the
930 host, depending on the underlying hypervisor technology.
931 A "stronger" version of `pause` is :func:'suspend'.
932 The counter action for `pause` is :func:`unpause`.
934 :param nova.objects.instance.Instance instance:
935 The instance which should be paused.
937 :return: None
938 """
939 # TODO(Vek): Need to pass context in for access to auth_token
940 raise NotImplementedError()
942 def unpause(self, instance):
943 """Unpause the given paused instance.
945 The paused instance gets unpaused and will use CPU cycles of the
946 host again. The counter action for 'unpause' is :func:`pause`.
947 Depending on the underlying hypervisor technology, the guest has the
948 same state as before the 'pause'.
950 :param nova.objects.instance.Instance instance:
951 The instance which should be unpaused.
953 :return: None
954 """
955 # TODO(Vek): Need to pass context in for access to auth_token
956 raise NotImplementedError()
958 def suspend(self, context, instance):
959 """Suspend the specified instance.
961 A suspended instance doesn't use CPU cycles or memory of the host
962 anymore. The state of the instance could be persisted on the host
963 and allocate storage space this way. A "softer" way of `suspend`
964 is :func:`pause`. The counter action for `suspend` is :func:`resume`.
966 :param nova.context.RequestContext context:
967 The context for the suspend.
968 :param nova.objects.instance.Instance instance:
969 The instance to suspend.
971 :return: None
972 """
973 raise NotImplementedError()
975 def resume(
976 self,
977 context,
978 instance,
979 network_info,
980 block_device_info=None,
981 share_info=None
982 ):
983 """resume the specified suspended instance.
985 The suspended instance gets resumed and will use CPU cycles and memory
986 of the host again. The counter action for 'resume' is :func:`suspend`.
987 Depending on the underlying hypervisor technology, the guest has the
988 same state as before the 'suspend'.
990 :param nova.context.RequestContext context:
991 The context for the resume.
992 :param nova.objects.instance.Instance instance:
993 The suspended instance to resume.
994 :param nova.network.model.NetworkInfo network_info:
995 Necessary network information for the resume.
996 :param dict block_device_info:
997 Instance volume block device info.
998 :param nova.objects.share_mapping.ShareMapingList share_info
999 optional list of share_mapping
1001 :return: None
1002 """
1003 raise NotImplementedError()
1005 def resume_state_on_host_boot(self, context, instance, network_info,
1006 share_info, block_device_info=None):
1007 """resume guest state when a host is booted.
1009 :param instance: nova.objects.instance.Instance
1010 :param nova.network.model.NetworkInfo network_info:
1011 Necessary network information for the resume.
1012 :param share_info: a ShareMappingList containing the attached shares.
1013 :param dict block_device_info:
1014 The block device mapping of the instance.
1015 """
1016 raise NotImplementedError()
1018 def rescue(self, context, instance, network_info, image_meta,
1019 rescue_password, block_device_info, share_info):
1020 """Rescue the specified instance.
1022 :param nova.context.RequestContext context:
1023 The context for the rescue.
1024 :param nova.objects.instance.Instance instance:
1025 The instance being rescued.
1026 :param nova.network.model.NetworkInfo network_info:
1027 Necessary network information for the resume.
1028 :param nova.objects.ImageMeta image_meta:
1029 The metadata of the image of the instance.
1030 :param rescue_password: new root password to set for rescue.
1031 :param dict block_device_info:
1032 The block device mapping of the instance.
1033 :param nova.objects.share_mapping.ShareMapingList share_info
1034 list of share_mapping
1035 """
1036 raise NotImplementedError()
1038 def unrescue(
1039 self,
1040 context: nova_context.RequestContext,
1041 instance: 'objects.Instance',
1042 ):
1043 """Unrescue the specified instance.
1045 :param context: security context
1046 :param instance: nova.objects.instance.Instance
1047 """
1048 raise NotImplementedError()
1050 def power_off(self, instance, timeout=0, retry_interval=0):
1051 """Power off the specified instance.
1053 :param instance: nova.objects.instance.Instance
1054 :param timeout: time to wait for GuestOS to shutdown
1055 :param retry_interval: How often to signal guest while
1056 waiting for it to shutdown
1057 """
1058 raise NotImplementedError()
1060 def power_on(self, context, instance, network_info,
1061 block_device_info=None, accel_info=None, share_info=None):
1062 """Power on the specified instance.
1064 :param context: security context
1065 :param instance: nova.objects.instance.Instance
1066 :param network_info: instance network information
1067 :param block_device_info: instance volume block device info
1068 :param accel_info: List of accelerator request dicts. The exact
1069 data struct is doc'd in nova/virt/driver.py::spawn().
1070 :param share_info: a ShareMappingList containing the attached shares.
1071 """
1072 raise NotImplementedError()
1074 def mount_share(self, context, instance, share_mapping):
1075 """Mount a manila share to the compute node.
1077 :param context: security context
1078 :param instance: nova.objects.instance.Instance
1079 :param share_mapping: nova.objects.share_mapping.ShareMapping object
1080 that define the share
1081 """
1082 raise NotImplementedError()
1084 def umount_share(self, context, instance, share_mapping):
1085 """Unmount a manila share from the compute node.
1087 :param context: security context
1088 :param instance: nova.objects.instance.Instance
1089 :param share_mapping: nova.objects.share_mapping.ShareMapping object
1090 that define the share
1091 :returns: True if the mountpoint is still in used by another instance
1092 """
1093 raise NotImplementedError()
1095 def power_update_event(self, instance, target_power_state):
1096 """Update power, vm and task states of the specified instance.
1098 Note that the driver is expected to set the task_state of the
1099 instance back to None.
1101 :param instance: nova.objects.instance.Instance
1102 :param target_power_state: The desired target power state for the
1103 instance; possible values are "POWER_ON"
1104 and "POWER_OFF".
1105 """
1106 raise NotImplementedError()
1108 def trigger_crash_dump(self, instance):
1109 """Trigger crash dump mechanism on the given instance.
1111 Stalling instances can be triggered to dump the crash data. How the
1112 guest OS reacts in details, depends on the configuration of it.
1114 :param nova.objects.instance.Instance instance:
1115 The instance where the crash dump should be triggered.
1117 :return: None
1118 """
1119 raise NotImplementedError()
1121 def soft_delete(self, instance):
1122 """Soft delete the specified instance.
1124 A soft-deleted instance doesn't allocate any resources anymore, but is
1125 still available as a database entry. The counter action :func:`restore`
1126 uses the database entry to create a new instance based on that.
1128 :param nova.objects.instance.Instance instance:
1129 The instance to soft-delete.
1131 :return: None
1132 """
1133 raise NotImplementedError()
1135 def restore(self, instance):
1136 """Restore the specified soft-deleted instance.
1138 The restored instance will be automatically booted. The counter action
1139 for `restore` is :func:`soft_delete`.
1141 :param nova.objects.instance.Instance instance:
1142 The soft-deleted instance which should be restored from the
1143 soft-deleted data.
1145 :return: None
1146 """
1147 raise NotImplementedError()
1149 @staticmethod
1150 def _get_reserved_host_disk_gb_from_config():
1151 import nova.compute.utils as compute_utils # avoid circular import
1152 return compute_utils.convert_mb_to_ceil_gb(CONF.reserved_host_disk_mb)
1154 @staticmethod
1155 def _get_allocation_ratios(inventory):
1156 """Get the cpu/ram/disk allocation ratios for the given inventory.
1158 This utility method is used to get the inventory allocation ratio
1159 for VCPU, MEMORY_MB and DISK_GB resource classes based on the following
1160 precedence:
1162 * Use ``[DEFAULT]/*_allocation_ratio`` if set - this overrides
1163 everything including externally set allocation ratios on the
1164 inventory via the placement API
1165 * Use ``[DEFAULT]/initial_*_allocation_ratio`` if a value does not
1166 exist for a given resource class in the ``inventory`` dict
1167 * Use what is already in the ``inventory`` dict for the allocation
1168 ratio if the above conditions are false
1170 :param inventory: dict, keyed by resource class, of inventory
1171 information.
1172 :returns: Return a dict, keyed by resource class, of allocation ratio
1173 """
1174 keys = {'cpu': orc.VCPU,
1175 'ram': orc.MEMORY_MB,
1176 'disk': orc.DISK_GB}
1177 result = {}
1178 for res, rc in keys.items():
1179 attr = '%s_allocation_ratio' % res
1180 conf_ratio = getattr(CONF, attr)
1181 if conf_ratio:
1182 result[rc] = conf_ratio
1183 elif rc not in inventory:
1184 result[rc] = getattr(CONF, 'initial_%s' % attr)
1185 else:
1186 result[rc] = inventory[rc]['allocation_ratio']
1187 return result
1189 def update_provider_tree(self, provider_tree, nodename, allocations=None):
1190 """Update a ProviderTree object with current resource provider and
1191 inventory information.
1193 When this method returns, provider_tree should represent the correct
1194 hierarchy of nested resource providers associated with this compute
1195 node, as well as the inventory, aggregates, and traits associated with
1196 those resource providers.
1198 Implementers of this interface are expected to set ``allocation_ratio``
1199 and ``reserved`` values for inventory records, which may be based on
1200 configuration options, e.g. ``[DEFAULT]/cpu_allocation_ratio``,
1201 depending on the driver and resource class. If not provided, allocation
1202 ratio defaults to 1.0 and reserved defaults to 0 in placement.
1204 :note: Renaming the root provider (by deleting it from provider_tree
1205 and re-adding it with a different name) is not supported at this time.
1207 See the developer reference documentation for more details:
1209 https://docs.openstack.org/nova/latest/reference/update-provider-tree.html # noqa
1211 :param nova.compute.provider_tree.ProviderTree provider_tree:
1212 A nova.compute.provider_tree.ProviderTree object representing all
1213 the providers in the tree associated with the compute node, and any
1214 sharing providers (those with the ``MISC_SHARES_VIA_AGGREGATE``
1215 trait) associated via aggregate with any of those providers (but
1216 not *their* tree- or aggregate-associated providers), as currently
1217 known by placement. This object is fully owned by the
1218 update_provider_tree method, and can therefore be modified without
1219 locking/concurrency considerations. In other words, the parameter
1220 is passed *by reference* with the expectation that the virt driver
1221 will modify the object. Note, however, that it may contain
1222 providers not directly owned/controlled by the compute host. Care
1223 must be taken not to remove or modify such providers inadvertently.
1224 In addition, providers may be associated with traits and/or
1225 aggregates maintained by outside agents. The
1226 `update_provider_tree`` method must therefore also be careful only
1227 to add/remove traits/aggregates it explicitly controls.
1228 :param nodename:
1229 String name of the compute node (i.e.
1230 ComputeNode.hypervisor_hostname) for which the caller is requesting
1231 updated provider information. Drivers may use this to help identify
1232 the compute node provider in the ProviderTree. Drivers managing
1233 more than one node (e.g. ironic) may also use it as a cue to
1234 indicate which node is being processed by the caller.
1235 :param allocations:
1236 Dict of allocation data of the form:
1237 { $CONSUMER_UUID: {
1238 # The shape of each "allocations" dict below is identical
1239 # to the return from GET /allocations/{consumer_uuid}
1240 "allocations": {
1241 $RP_UUID: {
1242 "generation": $RP_GEN,
1243 "resources": {
1244 $RESOURCE_CLASS: $AMOUNT,
1245 ...
1246 },
1247 },
1248 ...
1249 },
1250 "project_id": $PROJ_ID,
1251 "user_id": $USER_ID,
1252 "consumer_generation": $CONSUMER_GEN,
1253 },
1254 ...
1255 }
1256 If None, and the method determines that any inventory needs to be
1257 moved (from one provider to another and/or to a different resource
1258 class), the ReshapeNeeded exception must be raised. Otherwise, this
1259 dict must be edited in place to indicate the desired final state of
1260 allocations. Drivers should *only* edit allocation records for
1261 providers whose inventories are being affected by the reshape
1262 operation.
1263 :raises ReshapeNeeded: If allocations is None and any inventory needs
1264 to be moved from one provider to another and/or to a different
1265 resource class.
1266 :raises: ReshapeFailed if the requested tree reshape fails for
1267 whatever reason.
1268 """
1269 raise NotImplementedError()
1271 def capabilities_as_traits(self):
1272 """Returns this driver's capabilities dict where the keys are traits
1274 Traits can only be standard compute capabilities traits from
1275 the os-traits library.
1277 :returns: dict, keyed by trait, of this driver's capabilities where the
1278 values are booleans indicating if the driver supports the trait
1280 """
1281 traits = {}
1282 for capability, supported in self.capabilities.items():
1283 if capability.startswith('supports_image_type_'):
1284 supported = _check_image_type_exclude_list(capability,
1285 supported)
1287 if capability in CAPABILITY_TRAITS_MAP:
1288 traits[CAPABILITY_TRAITS_MAP[capability]] = supported
1290 return traits
1292 def get_available_resource(self, nodename):
1293 """Retrieve resource information.
1295 This method is called when nova-compute launches, and
1296 as part of a periodic task that records the results in the DB.
1298 :param nodename:
1299 node which the caller want to get resources from
1300 a driver that manages only one node can safely ignore this
1301 :returns: Dictionary describing resources
1302 """
1303 raise NotImplementedError()
1305 def is_node_deleted(self, nodename):
1306 """Check this compute node has been deleted.
1308 This method is called when the compute manager notices that a
1309 node that was previously reported as available is no longer
1310 available.
1311 In this case, we need to know if the node has actually been
1312 deleted, or if it is simply no longer managed by this
1313 nova-compute service.
1314 If True is returned, the database and placement records will
1315 be removed.
1317 :param nodename:
1318 node which the caller wants to check if its deleted
1319 :returns: True if the node is safe to delete
1320 """
1321 # For most driver, compute nodes should never get deleted
1322 # during a periodic task, they are only deleted via the API
1323 return False
1325 def pre_live_migration(self, context, instance, block_device_info,
1326 network_info, disk_info, migrate_data):
1327 """Prepare an instance for live migration
1329 :param context: security context
1330 :param instance: nova.objects.instance.Instance object
1331 :param block_device_info: instance block device information
1332 :param network_info: instance network information
1333 :param disk_info: instance disk information
1334 :param migrate_data: a LiveMigrateData object
1335 :returns: migrate_data modified by the driver
1336 :raises TooManyDiskDevices: if the maximum allowed devices to attach
1337 to a single instance is exceeded.
1338 """
1339 raise NotImplementedError()
1341 def live_migration(self, context, instance, dest,
1342 post_method, recover_method, block_migration=False,
1343 migrate_data=None):
1344 """Live migration of an instance to another host.
1346 :param context: security context
1347 :param instance:
1348 nova.db.main.models.Instance object
1349 instance object that is migrated.
1350 :param dest: destination host
1351 :param post_method:
1352 post operation method.
1353 expected nova.compute.manager._post_live_migration.
1354 :param recover_method:
1355 recovery method when any exception occurs.
1356 expected nova.compute.manager._rollback_live_migration.
1357 :param block_migration: if true, migrate VM disk.
1358 :param migrate_data: a LiveMigrateData object
1360 """
1361 raise NotImplementedError()
1363 def live_migration_force_complete(self, instance):
1364 """Force live migration to complete
1366 :param instance: Instance being live migrated
1368 """
1369 raise NotImplementedError()
1371 def live_migration_abort(self, instance):
1372 """Abort an in-progress live migration.
1374 :param instance: instance that is live migrating
1376 """
1377 raise NotImplementedError()
1379 def rollback_live_migration_at_source(self, context, instance,
1380 migrate_data):
1381 """Clean up source node after a failed live migration.
1383 :param context: security context
1384 :param instance: instance object that was being migrated
1385 :param migrate_data: a LiveMigrateData object
1386 """
1387 pass
1389 def rollback_live_migration_at_destination(self, context, instance,
1390 network_info,
1391 block_device_info,
1392 destroy_disks=True,
1393 migrate_data=None):
1394 """Clean up destination node after a failed live migration.
1396 :param context: security context
1397 :param instance: instance object that was being migrated
1398 :param network_info: instance network information
1399 :param block_device_info: instance block device information
1400 :param destroy_disks:
1401 if true, destroy disks at destination during cleanup
1402 :param migrate_data: a LiveMigrateData object
1404 """
1405 raise NotImplementedError()
1407 def post_live_migration(self, context, instance, block_device_info,
1408 migrate_data=None):
1409 """Post operation of live migration at source host.
1411 :param context: security context
1412 :instance: instance object that was migrated
1413 :block_device_info: instance block device information
1414 :param migrate_data: a LiveMigrateData object
1415 """
1416 pass
1418 def post_live_migration_at_source(self, context, instance, network_info):
1419 """Unplug VIFs from networks at source.
1421 :param context: security context
1422 :param instance: instance object reference
1423 :param network_info: instance network information
1424 """
1425 raise NotImplementedError(_("Hypervisor driver does not support "
1426 "post_live_migration_at_source method"))
1428 def post_live_migration_at_destination(self, context, instance,
1429 network_info,
1430 block_migration=False,
1431 block_device_info=None):
1432 """Post operation of live migration at destination host.
1434 :param context: security context
1435 :param instance: instance object that is migrated
1436 :param network_info: instance network information
1437 :param block_migration: if true, post operation of block_migration.
1438 """
1439 raise NotImplementedError()
1441 def check_instance_shared_storage_local(self, context, instance):
1442 """Check if instance files located on shared storage.
1444 This runs check on the destination host, and then calls
1445 back to the source host to check the results.
1447 :param context: security context
1448 :param instance: nova.objects.instance.Instance object
1449 """
1450 raise NotImplementedError()
1452 def check_instance_shared_storage_remote(self, context, data):
1453 """Check if instance files located on shared storage.
1455 :param context: security context
1456 :param data: result of check_instance_shared_storage_local
1457 """
1458 raise NotImplementedError()
1460 def check_instance_shared_storage_cleanup(self, context, data):
1461 """Do cleanup on host after check_instance_shared_storage calls
1463 :param context: security context
1464 :param data: result of check_instance_shared_storage_local
1465 """
1466 pass
1468 def check_can_live_migrate_destination(self, context, instance,
1469 src_compute_info, dst_compute_info,
1470 block_migration=False,
1471 disk_over_commit=False):
1472 """Check if it is possible to execute live migration.
1474 This runs checks on the destination host, and then calls
1475 back to the source host to check the results.
1477 :param context: security context
1478 :param instance: nova.db.main.models.Instance
1479 :param src_compute_info: Info about the sending machine
1480 :param dst_compute_info: Info about the receiving machine
1481 :param block_migration: if true, prepare for block migration
1482 :param disk_over_commit: if true, allow disk over commit
1483 :returns: a LiveMigrateData object (hypervisor-dependent)
1484 """
1485 raise NotImplementedError()
1487 def check_source_migrate_data_at_dest(self, ctxt, instance, migrate_data,
1488 migration, limits, allocs):
1489 """Runs the last checks on the destination after the source returned
1490 the migrate_data.
1492 :param ctxt: security context
1493 :param instance: nova.db.main.models.Instance
1494 :param migrate_data: result of check_can_live_migrate_source
1495 :param migration: The Migration object for this live migration
1496 :param limits: The SchedulerLimits object for this live migration
1497 :param allocs: Allocations for this instance
1498 :returns: a LibvirtLiveMigrateData object
1499 :raises: MigrationPreCheckError
1500 """
1501 return migrate_data
1503 def post_claim_migrate_data(self, context, instance, migrate_data, claim):
1504 """Returns migrate_data augmented with any information obtained from
1505 the claim. Intended to run on the destination of a live-migration
1506 operation, after resources have been claimed on it.
1508 :param context: The request context.
1509 :param instance: The instance being live-migrated.
1510 :param migrate_data: The existing LiveMigrateData object for this live
1511 migration.
1512 :param claim: The MoveClaim that was made on the destination for this
1513 live migration.
1514 :returns: A LiveMigrateData object augmented with information obtained
1515 from the Claim.
1516 """
1517 return migrate_data
1519 def cleanup_live_migration_destination_check(self, context,
1520 dest_check_data):
1521 """Do required cleanup on dest host after check_can_live_migrate calls
1523 :param context: security context
1524 :param dest_check_data: result of check_can_live_migrate_destination
1525 """
1526 raise NotImplementedError()
1528 def check_can_live_migrate_source(self, context, instance,
1529 dest_check_data, block_device_info=None):
1530 """Check if it is possible to execute live migration.
1532 This checks if the live migration can succeed, based on the
1533 results from check_can_live_migrate_destination.
1535 :param context: security context
1536 :param instance: nova.db.main.models.Instance
1537 :param dest_check_data: result of check_can_live_migrate_destination
1538 :param block_device_info: result of _get_instance_block_device_info
1539 :returns: a LiveMigrateData object
1540 """
1541 raise NotImplementedError()
1543 def get_instance_disk_info(self, instance,
1544 block_device_info=None):
1545 """Retrieve information about actual disk sizes of an instance.
1547 :param instance: nova.objects.Instance
1548 :param block_device_info:
1549 Optional; Can be used to filter out devices which are
1550 actually volumes.
1551 :return:
1552 json strings with below format::
1554 "[{'path':'disk',
1555 'type':'raw',
1556 'virt_disk_size':'10737418240',
1557 'backing_file':'backing_file',
1558 'disk_size':'83886080'
1559 'over_committed_disk_size':'10737418240'},
1560 ...]"
1561 """
1562 raise NotImplementedError()
1564 def set_admin_password(self, instance, new_pass):
1565 """Set the root password on the specified instance.
1567 :param instance: nova.objects.instance.Instance
1568 :param new_pass: the new password
1569 """
1570 raise NotImplementedError()
1572 def inject_network_info(self, instance, nw_info):
1573 """inject network info for specified instance."""
1574 # TODO(Vek): Need to pass context in for access to auth_token
1575 pass
1577 def poll_rebooting_instances(self, timeout, instances):
1578 """Perform a reboot on all given 'instances'.
1580 Reboots the given `instances` which are longer in the rebooting state
1581 than `timeout` seconds.
1583 :param int timeout:
1584 The timeout (in seconds) for considering rebooting instances
1585 to be stuck.
1586 :param list instances:
1587 A list of nova.objects.instance.Instance objects that have been
1588 in rebooting state longer than the configured timeout.
1590 :return: None
1591 """
1592 # TODO(Vek): Need to pass context in for access to auth_token
1593 raise NotImplementedError()
1595 def host_power_action(self, action):
1596 """Reboots, shuts down or powers up the host.
1598 :param str action:
1599 The action the host should perform. The valid actions are:
1600 ""startup", "shutdown" and "reboot".
1602 :return: The result of the power action
1603 :rtype: str
1604 """
1606 raise NotImplementedError()
1608 def host_maintenance_mode(self, host, mode):
1609 """Start/Stop host maintenance window.
1611 On start, it triggers the migration of all instances to other hosts.
1612 Consider the combination with :func:`set_host_enabled`.
1614 :param str host:
1615 The name of the host whose maintenance mode should be changed.
1616 :param bool mode:
1617 If `True`, go into maintenance mode. If `False`, leave the
1618 maintenance mode.
1620 :return: "on_maintenance" if switched to maintenance mode or
1621 "off_maintenance" if maintenance mode got left.
1622 :rtype: str
1623 """
1625 raise NotImplementedError()
1627 def set_host_enabled(self, enabled):
1628 """Sets the ability of this host to accept new instances.
1630 :param bool enabled:
1631 If this is `True`, the host will accept new instances. If it is
1632 `False`, the host won't accept new instances.
1634 :return: If the host can accept further instances, return "enabled",
1635 if further instances shouldn't be scheduled to this host,
1636 return "disabled".
1637 :rtype: str
1638 """
1639 # TODO(Vek): Need to pass context in for access to auth_token
1640 raise NotImplementedError()
1642 def get_host_uptime(self):
1643 """Returns the result of the time since start up of this hypervisor.
1645 :return: A text which contains the uptime of this host since the
1646 last boot.
1647 :rtype: str
1648 """
1649 # TODO(Vek): Need to pass context in for access to auth_token
1650 raise NotImplementedError()
1652 def plug_vifs(self, instance, network_info):
1653 """Plug virtual interfaces (VIFs) into the given `instance` at
1654 instance boot time.
1656 The counter action is :func:`unplug_vifs`.
1658 :param nova.objects.instance.Instance instance:
1659 The instance which gets VIFs plugged.
1660 :param nova.network.model.NetworkInfo network_info:
1661 The object which contains information about the VIFs to plug.
1663 :return: None
1664 """
1665 # TODO(Vek): Need to pass context in for access to auth_token
1666 raise NotImplementedError()
1668 def unplug_vifs(self, instance, network_info):
1669 """Unplug virtual interfaces (VIFs) from networks.
1671 The counter action is :func:`plug_vifs`.
1673 :param nova.objects.instance.Instance instance:
1674 The instance which gets VIFs unplugged.
1675 :param nova.network.model.NetworkInfo network_info:
1676 The object which contains information about the VIFs to unplug.
1678 :return: None
1679 """
1680 raise NotImplementedError()
1682 def get_host_cpu_stats(self):
1683 """Get the currently known host CPU stats.
1685 :returns: a dict containing the CPU stat info, eg:
1687 | {'kernel': kern,
1688 | 'idle': idle,
1689 | 'user': user,
1690 | 'iowait': wait,
1691 | 'frequency': freq},
1693 where kern and user indicate the cumulative CPU time
1694 (nanoseconds) spent by kernel and user processes
1695 respectively, idle indicates the cumulative idle CPU time
1696 (nanoseconds), wait indicates the cumulative I/O wait CPU
1697 time (nanoseconds), since the host is booting up; freq
1698 indicates the current CPU frequency (MHz). All values are
1699 long integers.
1701 """
1702 raise NotImplementedError()
1704 def block_stats(self, instance, disk_id):
1705 """Return performance counters associated with the given disk_id on the
1706 given instance. These are returned as [rd_req, rd_bytes, wr_req,
1707 wr_bytes, errs], where rd indicates read, wr indicates write, req is
1708 the total number of I/O requests made, bytes is the total number of
1709 bytes transferred, and errs is the number of requests held up due to a
1710 full pipeline.
1712 All counters are long integers.
1714 This method is optional. On some platforms performance statistics can
1715 be retrieved directly in aggregate form, without Nova having to do the
1716 aggregation. On those platforms, this method is unused.
1718 Note that this function takes an instance ID.
1720 :param instance: nova.objects.Instance to get block storage statistics
1721 :param disk_id: mountpoint name, e.g. "vda"
1722 :returns: None if block statistics could not be retrieved, otherwise a
1723 list of the form: [rd_req, rd_bytes, wr_req, wr_bytes, errs]
1724 :raises: NotImplementedError if the driver does not implement this
1725 method
1726 """
1727 raise NotImplementedError()
1729 def manage_image_cache(self, context, all_instances):
1730 """Manage the driver's local image cache.
1732 Some drivers chose to cache images for instances on disk. This method
1733 is an opportunity to do management of that cache which isn't directly
1734 related to other calls into the driver. The prime example is to clean
1735 the cache and remove images which are no longer of interest.
1737 :param all_instances: nova.objects.instance.InstanceList
1738 """
1739 pass
1741 def cache_image(self, context, image_id):
1742 """Download an image into the cache.
1744 Used by the compute manager in response to a request to pre-cache
1745 an image on the compute node. If the driver implements an image cache,
1746 it should implement this method as well and perform the same action
1747 as it does during an on-demand base image fetch in response to a
1748 spawn.
1750 :returns: A boolean indicating whether or not the image was fetched.
1751 True if it was fetched, or False if it already exists in
1752 the cache.
1753 :raises: An Exception on error
1754 """
1755 raise NotImplementedError()
1757 def get_volume_connector(self, instance):
1758 """Get connector information for the instance for attaching to volumes.
1760 Connector information is a dictionary representing the ip of the
1761 machine that will be making the connection, the name of the iscsi
1762 initiator and the hostname of the machine as follows::
1764 {
1765 'ip': ip,
1766 'initiator': initiator,
1767 'host': hostname
1768 }
1770 """
1771 raise NotImplementedError()
1773 def get_available_nodes(self, refresh=False):
1774 """Returns nodenames of all nodes managed by the compute service.
1776 This method is for multi compute-nodes support. If a driver supports
1777 multi compute-nodes, this method returns a list of nodenames managed
1778 by the service. Otherwise, this method should return
1779 [hypervisor_hostname].
1780 """
1781 raise NotImplementedError()
1783 def get_nodenames_by_uuid(self, refresh=False):
1784 """Returns a dict of {uuid: nodename} for all managed nodes."""
1785 nodename = self.get_available_nodes()[0]
1786 return {nova.virt.node.get_local_node_uuid(): nodename}
1788 def node_is_available(self, nodename):
1789 """Return whether this compute service manages a particular node."""
1790 if nodename in self.get_available_nodes(): 1790 ↛ 1793line 1790 didn't jump to line 1793 because the condition on line 1790 was always true
1791 return True
1792 # Refresh and check again.
1793 return nodename in self.get_available_nodes(refresh=True)
1795 def instance_on_disk(self, instance):
1796 """Checks access of instance files on the host.
1798 :param instance: nova.objects.instance.Instance to lookup
1800 Returns True if files of an instance with the supplied ID accessible on
1801 the host, False otherwise.
1803 .. note::
1804 Used in rebuild for HA implementation and required for validation
1805 of access to instance shared disk files
1806 """
1807 return False
1809 def register_event_listener(self, callback):
1810 """Register a callback to receive events.
1812 Register a callback to receive asynchronous event
1813 notifications from hypervisors. The callback will
1814 be invoked with a single parameter, which will be
1815 an instance of the nova.virt.event.Event class.
1816 """
1818 self._compute_event_callback = callback
1820 def emit_event(self, event):
1821 """Dispatches an event to the compute manager.
1823 Invokes the event callback registered by the
1824 compute manager to dispatch the event. This
1825 must only be invoked from a green thread.
1826 """
1828 if not self._compute_event_callback: 1828 ↛ 1829line 1828 didn't jump to line 1829 because the condition on line 1828 was never true
1829 LOG.debug("Discarding event %s", str(event))
1830 return
1832 if not isinstance(event, virtevent.Event):
1833 raise ValueError(
1834 _("Event must be an instance of nova.virt.event.Event"))
1836 try:
1837 LOG.debug("Emitting event %s", str(event))
1838 self._compute_event_callback(event)
1839 except Exception as ex:
1840 LOG.error("Exception dispatching event %(event)s: %(ex)s",
1841 {'event': event, 'ex': ex})
1843 def delete_instance_files(self, instance):
1844 """Delete any lingering instance files for an instance.
1846 :param instance: nova.objects.instance.Instance
1847 :returns: True if the instance was deleted from disk, False otherwise.
1848 """
1849 return True
1851 def volume_snapshot_create(self, context, instance, volume_id,
1852 create_info):
1853 """Snapshots volumes attached to a specified instance.
1855 The counter action to this is :func:`volume_snapshot_delete`
1857 :param nova.context.RequestContext context:
1858 The security context.
1859 :param nova.objects.instance.Instance instance:
1860 The instance that has the volume attached
1861 :param uuid volume_id:
1862 Volume to be snapshotted
1863 :param create_info: The data needed for nova to be able to attach
1864 to the volume. This is the same data format returned by
1865 Cinder's initialize_connection() API call. In the case of
1866 doing a snapshot, it is the image file Cinder expects to be
1867 used as the active disk after the snapshot operation has
1868 completed. There may be other data included as well that is
1869 needed for creating the snapshot.
1870 """
1871 raise NotImplementedError()
1873 def volume_snapshot_delete(self, context, instance, volume_id,
1874 snapshot_id, delete_info):
1875 """Deletes a snapshot of a volume attached to a specified instance.
1877 The counter action to this is :func:`volume_snapshot_create`
1879 :param nova.context.RequestContext context:
1880 The security context.
1881 :param nova.objects.instance.Instance instance:
1882 The instance that has the volume attached.
1883 :param uuid volume_id:
1884 Attached volume associated with the snapshot
1885 :param uuid snapshot_id:
1886 The snapshot to delete.
1887 :param dict delete_info:
1888 Volume backend technology specific data needed to be able to
1889 complete the snapshot. For example, in the case of qcow2 backed
1890 snapshots, this would include the file being merged, and the file
1891 being merged into (if appropriate).
1893 :return: None
1894 """
1895 raise NotImplementedError()
1897 def default_root_device_name(self, instance, image_meta, root_bdm):
1898 """Provide a default root device name for the driver.
1900 :param nova.objects.instance.Instance instance:
1901 The instance to get the root device for.
1902 :param nova.objects.ImageMeta image_meta:
1903 The metadata of the image of the instance.
1904 :param nova.objects.BlockDeviceMapping root_bdm:
1905 The description of the root device.
1906 :raises TooManyDiskDevices: if the maximum allowed devices to attach
1907 to a single instance is exceeded.
1908 """
1909 raise NotImplementedError()
1911 def default_device_names_for_instance(self, instance, root_device_name,
1912 *block_device_lists):
1913 """Default the missing device names in the block device mapping.
1915 :raises TooManyDiskDevices: if the maximum allowed devices to attach
1916 to a single instance is exceeded.
1917 """
1918 raise NotImplementedError()
1920 def get_device_name_for_instance(self, instance,
1921 bdms, block_device_obj):
1922 """Get the next device name based on the block device mapping.
1924 :param instance: nova.objects.instance.Instance that volume is
1925 requesting a device name
1926 :param bdms: a nova.objects.BlockDeviceMappingList for the instance
1927 :param block_device_obj: A nova.objects.BlockDeviceMapping instance
1928 with all info about the requested block
1929 device. device_name does not need to be set,
1930 and should be decided by the driver
1931 implementation if not set.
1933 :returns: The chosen device name.
1934 :raises TooManyDiskDevices: if the maximum allowed devices to attach
1935 to a single instance is exceeded.
1936 """
1937 raise NotImplementedError()
1939 def is_supported_fs_format(self, fs_type):
1940 """Check whether the file format is supported by this driver
1942 :param fs_type: the file system type to be checked,
1943 the validate values are defined at disk API module.
1944 """
1945 # NOTE(jichenjc): Return False here so that every hypervisor
1946 # need to define their supported file system
1947 # type and implement this function at their
1948 # virt layer.
1949 return False
1951 def quiesce(self, context, instance, image_meta):
1952 """Quiesce the specified instance to prepare for snapshots.
1954 If the specified instance doesn't support quiescing,
1955 InstanceQuiesceNotSupported is raised. When it fails to quiesce by
1956 other errors (e.g. agent timeout), NovaException is raised.
1958 :param context: request context
1959 :param instance: nova.objects.instance.Instance to be quiesced
1960 :param nova.objects.ImageMeta image_meta:
1961 The metadata of the image of the instance.
1962 """
1963 raise NotImplementedError()
1965 def unquiesce(self, context, instance, image_meta):
1966 """Unquiesce the specified instance after snapshots.
1968 If the specified instance doesn't support quiescing,
1969 InstanceQuiesceNotSupported is raised. When it fails to quiesce by
1970 other errors (e.g. agent timeout), NovaException is raised.
1972 :param context: request context
1973 :param instance: nova.objects.instance.Instance to be unquiesced
1974 :param nova.objects.ImageMeta image_meta:
1975 The metadata of the image of the instance.
1976 """
1977 raise NotImplementedError()
1979 def network_binding_host_id(self, context, instance):
1980 """Get host ID to associate with network ports.
1982 :param context: request context
1983 :param instance: nova.objects.instance.Instance that the network
1984 ports will be associated with
1985 :returns: a string representing the host ID
1986 """
1987 return instance.get('host')
1989 def manages_network_binding_host_id(self):
1990 """Compute driver manages port bindings.
1992 Used to indicate whether or not the compute driver is responsible
1993 for managing port binding details, such as the host_id.
1994 By default the ComputeManager will manage port bindings and the
1995 host_id associated with a binding using the network API.
1996 However, some backends, like Ironic, will manage the port binding
1997 host_id out-of-band and the compute service should not override what
1998 is set by the backing hypervisor.
1999 """
2000 return False
2002 def cleanup_lingering_instance_resources(self, instance):
2003 """Cleanup resources occupied by lingering instance.
2005 For example, cleanup other specific resources or whatever we
2006 add in the future.
2008 :param instance: nova.objects.instance.Instance
2009 :returns: True if the cleanup is successful, else false.
2010 """
2011 return True
2014def load_compute_driver(virtapi, compute_driver=None):
2015 """Load a compute driver module.
2017 Load the compute driver module specified by the compute_driver
2018 configuration option or, if supplied, the driver name supplied as an
2019 argument.
2021 Compute drivers constructors take a VirtAPI object as their first object
2022 and this must be supplied.
2024 :param virtapi: a VirtAPI instance
2025 :param compute_driver: a compute driver name to override the config opt
2026 :returns: a ComputeDriver instance
2027 """
2028 if not compute_driver:
2029 compute_driver = CONF.compute_driver
2031 if not compute_driver: 2031 ↛ 2032line 2031 didn't jump to line 2032 because the condition on line 2031 was never true
2032 LOG.error("Compute driver option required, but not specified")
2033 sys.exit(1)
2035 LOG.info("Loading compute driver '%s'", compute_driver)
2036 try:
2037 driver = importutils.import_object(
2038 'nova.virt.%s' % compute_driver,
2039 virtapi)
2040 if isinstance(driver, ComputeDriver): 2040 ↛ 2042line 2040 didn't jump to line 2042 because the condition on line 2040 was always true
2041 return driver
2042 raise ValueError()
2043 except ImportError:
2044 LOG.exception("Unable to load the virtualization driver")
2045 sys.exit(1)
2046 except ValueError:
2047 LOG.exception("Compute driver '%s' from 'nova.virt' is not of type "
2048 "'%s'", compute_driver, str(ComputeDriver))
2049 sys.exit(1)