837 lines
33 KiB
Python
837 lines
33 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
# Copyright 2011 Justin Santa Barbara
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
"""
|
|
Driver base-classes:
|
|
|
|
(Beginning of) the contract that compute drivers must follow, and shared
|
|
types that support that contract
|
|
"""
|
|
|
|
import sys
|
|
|
|
from nova.openstack.common import cfg
|
|
from nova.openstack.common import importutils
|
|
from nova.openstack.common import log as logging
|
|
from nova import utils
|
|
|
|
driver_opts = [
|
|
cfg.StrOpt('compute_driver',
|
|
help='Driver to use for controlling virtualization. Options '
|
|
'include: libvirt.LibvirtDriver, xenapi.XenAPIDriver, '
|
|
'fake.FakeDriver, baremetal.BareMetalDriver, '
|
|
'vmwareapi.VMWareESXDriver'),
|
|
]
|
|
|
|
CONF = cfg.CONF
|
|
CONF.register_opts(driver_opts)
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
def block_device_info_get_root(block_device_info):
|
|
block_device_info = block_device_info or {}
|
|
return block_device_info.get('root_device_name')
|
|
|
|
|
|
def block_device_info_get_swap(block_device_info):
|
|
block_device_info = block_device_info or {}
|
|
return block_device_info.get('swap') or {'device_name': None,
|
|
'swap_size': 0}
|
|
|
|
|
|
def swap_is_usable(swap):
|
|
return swap and swap['device_name'] and swap['swap_size'] > 0
|
|
|
|
|
|
def block_device_info_get_ephemerals(block_device_info):
|
|
block_device_info = block_device_info or {}
|
|
ephemerals = block_device_info.get('ephemerals') or []
|
|
return ephemerals
|
|
|
|
|
|
def block_device_info_get_mapping(block_device_info):
|
|
block_device_info = block_device_info or {}
|
|
block_device_mapping = block_device_info.get('block_device_mapping') or []
|
|
return block_device_mapping
|
|
|
|
|
|
class ComputeDriver(object):
|
|
"""Base class for compute drivers.
|
|
|
|
The interface to this class talks in terms of 'instances' (Amazon EC2 and
|
|
internal Nova terminology), by which we mean 'running virtual machine'
|
|
(XenAPI terminology) or domain (Xen or libvirt terminology).
|
|
|
|
An instance has an ID, which is the identifier chosen by Nova to represent
|
|
the instance further up the stack. This is unfortunately also called a
|
|
'name' elsewhere. As far as this layer is concerned, 'instance ID' and
|
|
'instance name' are synonyms.
|
|
|
|
Note that the instance ID or name is not human-readable or
|
|
customer-controlled -- it's an internal ID chosen by Nova. At the
|
|
nova.virt layer, instances do not have human-readable names at all -- such
|
|
things are only known higher up the stack.
|
|
|
|
Most virtualization platforms will also have their own identity schemes,
|
|
to uniquely identify a VM or domain. These IDs must stay internal to the
|
|
platform-specific layer, and never escape the connection interface. The
|
|
platform-specific layer is responsible for keeping track of which instance
|
|
ID maps to which platform-specific ID, and vice versa.
|
|
|
|
Some methods here take an instance of nova.compute.service.Instance. This
|
|
is the data structure used by nova.compute to store details regarding an
|
|
instance, and pass them into this layer. This layer is responsible for
|
|
translating that generic data structure into terms that are specific to the
|
|
virtualization platform.
|
|
|
|
"""
|
|
|
|
capabilities = {
|
|
"has_imagecache": False,
|
|
}
|
|
|
|
def __init__(self, virtapi):
|
|
self.virtapi = virtapi
|
|
|
|
def init_host(self, host):
|
|
"""Initialize anything that is necessary for the driver to function,
|
|
including catching up with currently running VM's on the given host."""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def get_info(self, instance):
|
|
"""Get the current status of an instance, by name (not ID!)
|
|
|
|
Returns a dict containing:
|
|
|
|
:state: the running state, one of the power_state codes
|
|
:max_mem: (int) the maximum memory in KBytes allowed
|
|
:mem: (int) the memory in KBytes used by the domain
|
|
:num_cpu: (int) the number of virtual CPUs for the domain
|
|
:cpu_time: (int) the CPU time used in nanoseconds
|
|
"""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def get_num_instances(self):
|
|
"""Return the total number of virtual machines.
|
|
|
|
Return the number of virtual machines that the hypervisor knows
|
|
about.
|
|
|
|
.. note::
|
|
|
|
This implementation works for all drivers, but it is
|
|
not particularly efficient. Maintainers of the virt drivers are
|
|
encouraged to override this method with something more
|
|
efficient.
|
|
"""
|
|
return len(self.list_instances())
|
|
|
|
def instance_exists(self, instance_id):
|
|
"""Checks existence of an instance on the host.
|
|
|
|
:param instance_id: The ID / name of the instance to lookup
|
|
|
|
Returns True if an instance with the supplied ID exists on
|
|
the host, False otherwise.
|
|
|
|
.. note::
|
|
|
|
This implementation works for all drivers, but it is
|
|
not particularly efficient. Maintainers of the virt drivers are
|
|
encouraged to override this method with something more
|
|
efficient.
|
|
"""
|
|
return instance_id in self.list_instances()
|
|
|
|
def list_instances(self):
|
|
"""
|
|
Return the names of all the instances known to the virtualization
|
|
layer, as a list.
|
|
"""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def list_instance_uuids(self):
|
|
"""
|
|
Return the UUIDS of all the instances known to the virtualization
|
|
layer, as a list.
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def spawn(self, context, instance, image_meta, injected_files,
|
|
admin_password, network_info=None, block_device_info=None):
|
|
"""
|
|
Create a new instance/VM/domain on the virtualization platform.
|
|
|
|
Once this successfully completes, the instance should be
|
|
running (power_state.RUNNING).
|
|
|
|
If this fails, any partial instance should be completely
|
|
cleaned up, and the virtualization platform should be in the state
|
|
that it was before this call began.
|
|
|
|
:param context: security context
|
|
:param instance: Instance object as returned by DB layer.
|
|
This function should use the data there to guide
|
|
the creation of the new instance.
|
|
:param image_meta: image object returned by nova.image.glance that
|
|
defines the image from which to boot this instance
|
|
:param injected_files: User files to inject into instance.
|
|
:param admin_password: Administrator password to set in instance.
|
|
:param network_info:
|
|
:py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info`
|
|
:param block_device_info: Information about block devices to be
|
|
attached to the instance.
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def destroy(self, instance, network_info, block_device_info=None,
|
|
destroy_disks=True):
|
|
"""Destroy (shutdown and delete) the specified instance.
|
|
|
|
If the instance is not found (for example if networking failed), this
|
|
function should still succeed. It's probably a good idea to log a
|
|
warning in that case.
|
|
|
|
:param instance: Instance object as returned by DB layer.
|
|
:param network_info:
|
|
:py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info`
|
|
:param block_device_info: Information about block devices that should
|
|
be detached from the instance.
|
|
:param destroy_disks: Indicates if disks should be destroyed
|
|
|
|
"""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def reboot(self, instance, network_info, reboot_type,
|
|
block_device_info=None):
|
|
"""Reboot the specified instance.
|
|
|
|
After this is called successfully, the instance's state
|
|
goes back to power_state.RUNNING. The virtualization
|
|
platform should ensure that the reboot action has completed
|
|
successfully even in cases in which the underlying domain/vm
|
|
is paused or halted/stopped.
|
|
|
|
:param instance: Instance object as returned by DB layer.
|
|
:param network_info:
|
|
:py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info`
|
|
:param reboot_type: Either a HARD or SOFT reboot
|
|
"""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def get_console_pool_info(self, console_type):
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def get_console_output(self, instance):
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def get_vnc_console(self, instance):
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def get_diagnostics(self, instance):
|
|
"""Return data about VM diagnostics."""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def get_all_bw_counters(self, instances):
|
|
"""Return bandwidth usage counters for each interface on each
|
|
running VM"""
|
|
raise NotImplementedError()
|
|
|
|
def get_all_volume_usage(self, context, compute_host_bdms):
|
|
"""Return usage info for volumes attached to vms on
|
|
a given host"""
|
|
raise NotImplementedError()
|
|
|
|
def get_host_ip_addr(self):
|
|
"""
|
|
Retrieves the IP address of the dom0
|
|
"""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def attach_volume(self, connection_info, instance, mountpoint):
|
|
"""Attach the disk to the instance at mountpoint using info."""
|
|
raise NotImplementedError()
|
|
|
|
def detach_volume(self, connection_info, instance, mountpoint):
|
|
"""Detach the disk attached to the instance."""
|
|
raise NotImplementedError()
|
|
|
|
def migrate_disk_and_power_off(self, context, instance, dest,
|
|
instance_type, network_info,
|
|
block_device_info=None):
|
|
"""
|
|
Transfers the disk of a running instance in multiple phases, turning
|
|
off the instance before the end.
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def snapshot(self, context, instance, image_id, update_task_state):
|
|
"""
|
|
Snapshots the specified instance.
|
|
|
|
:param context: security context
|
|
:param instance: Instance object as returned by DB layer.
|
|
:param image_id: Reference to a pre-created image that will
|
|
hold the snapshot.
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def finish_migration(self, context, migration, instance, disk_info,
|
|
network_info, image_meta, resize_instance,
|
|
block_device_info=None):
|
|
"""Completes a resize, turning on the migrated instance
|
|
|
|
:param network_info:
|
|
:py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info`
|
|
:param image_meta: image object returned by nova.image.glance that
|
|
defines the image from which this instance
|
|
was created
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def confirm_migration(self, migration, instance, network_info):
|
|
"""Confirms a resize, destroying the source VM."""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def finish_revert_migration(self, instance, network_info,
|
|
block_device_info=None):
|
|
"""Finish reverting a resize, powering back on the instance."""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def pause(self, instance):
|
|
"""Pause the specified instance."""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def unpause(self, instance):
|
|
"""Unpause paused VM instance."""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def suspend(self, instance):
|
|
"""suspend the specified instance."""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def resume(self, instance, network_info, block_device_info=None):
|
|
"""resume the specified instance."""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def resume_state_on_host_boot(self, context, instance, network_info,
|
|
block_device_info=None):
|
|
"""resume guest state when a host is booted."""
|
|
raise NotImplementedError()
|
|
|
|
def rescue(self, context, instance, network_info, image_meta,
|
|
rescue_password):
|
|
"""Rescue the specified instance."""
|
|
raise NotImplementedError()
|
|
|
|
def unrescue(self, instance, network_info):
|
|
"""Unrescue the specified instance."""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def power_off(self, instance):
|
|
"""Power off the specified instance."""
|
|
raise NotImplementedError()
|
|
|
|
def power_on(self, instance):
|
|
"""Power on the specified instance."""
|
|
raise NotImplementedError()
|
|
|
|
def soft_delete(self, instance):
|
|
"""Soft delete the specified instance."""
|
|
raise NotImplementedError()
|
|
|
|
def restore(self, instance):
|
|
"""Restore the specified instance."""
|
|
raise NotImplementedError()
|
|
|
|
def get_available_resource(self, nodename):
|
|
"""Retrieve resource information.
|
|
|
|
This method is called when nova-compute launches, and
|
|
as part of a periodic task
|
|
|
|
:param nodename:
|
|
node which the caller want to get resources from
|
|
a driver that manages only one node can safely ignore this
|
|
:returns: Dictionary describing resources
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def pre_live_migration(self, ctxt, instance_ref,
|
|
block_device_info, network_info,
|
|
migrate_data=None):
|
|
"""Prepare an instance for live migration
|
|
|
|
:param ctxt: security context
|
|
:param instance_ref: instance object that will be migrated
|
|
:param block_device_info: instance block device information
|
|
:param network_info: instance network information
|
|
:param migrate_data: implementation specific data dict.
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def pre_block_migration(self, ctxt, instance_ref, disk_info):
|
|
"""Prepare a block device for migration
|
|
|
|
:param ctxt: security context
|
|
:param instance_ref: instance object that will have its disk migrated
|
|
:param disk_info: information about disk to be migrated (as returned
|
|
from get_instance_disk_info())
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def live_migration(self, ctxt, instance_ref, dest,
|
|
post_method, recover_method, block_migration=False,
|
|
migrate_data=None):
|
|
"""Live migration of an instance to another host.
|
|
|
|
:params ctxt: security context
|
|
:params instance_ref:
|
|
nova.db.sqlalchemy.models.Instance object
|
|
instance object that is migrated.
|
|
:params dest: destination host
|
|
:params post_method:
|
|
post operation method.
|
|
expected nova.compute.manager.post_live_migration.
|
|
:params recover_method:
|
|
recovery method when any exception occurs.
|
|
expected nova.compute.manager.recover_live_migration.
|
|
:params block_migration: if true, migrate VM disk.
|
|
:params migrate_data: implementation specific params.
|
|
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def post_live_migration_at_destination(self, ctxt, instance_ref,
|
|
network_info,
|
|
block_migration=False):
|
|
"""Post operation of live migration at destination host.
|
|
|
|
:param ctxt: security context
|
|
:param instance_ref: instance object that is migrated
|
|
:param network_info: instance network information
|
|
:param block_migration: if true, post operation of block_migration.
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def check_can_live_migrate_destination(self, ctxt, instance_ref,
|
|
src_compute_info, dst_compute_info,
|
|
block_migration=False,
|
|
disk_over_commit=False):
|
|
"""Check if it is possible to execute live migration.
|
|
|
|
This runs checks on the destination host, and then calls
|
|
back to the source host to check the results.
|
|
|
|
:param ctxt: security context
|
|
:param instance_ref: nova.db.sqlalchemy.models.Instance
|
|
:param src_compute_info: Info about the sending machine
|
|
:param dst_compute_info: Info about the receiving machine
|
|
:param block_migration: if true, prepare for block migration
|
|
:param disk_over_commit: if true, allow disk over commit
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def check_can_live_migrate_destination_cleanup(self, ctxt,
|
|
dest_check_data):
|
|
"""Do required cleanup on dest host after check_can_live_migrate calls
|
|
|
|
:param ctxt: security context
|
|
:param dest_check_data: result of check_can_live_migrate_destination
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def check_can_live_migrate_source(self, ctxt, instance_ref,
|
|
dest_check_data):
|
|
"""Check if it is possible to execute live migration.
|
|
|
|
This checks if the live migration can succeed, based on the
|
|
results from check_can_live_migrate_destination.
|
|
|
|
:param context: security context
|
|
:param instance_ref: nova.db.sqlalchemy.models.Instance
|
|
:param dest_check_data: result of check_can_live_migrate_destination
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def refresh_security_group_rules(self, security_group_id):
|
|
"""This method is called after a change to security groups.
|
|
|
|
All security groups and their associated rules live in the datastore,
|
|
and calling this method should apply the updated rules to instances
|
|
running the specified security group.
|
|
|
|
An error should be raised if the operation cannot complete.
|
|
|
|
"""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def refresh_security_group_members(self, security_group_id):
|
|
"""This method is called when a security group is added to an instance.
|
|
|
|
This message is sent to the virtualization drivers on hosts that are
|
|
running an instance that belongs to a security group that has a rule
|
|
that references the security group identified by `security_group_id`.
|
|
It is the responsibility of this method to make sure any rules
|
|
that authorize traffic flow with members of the security group are
|
|
updated and any new members can communicate, and any removed members
|
|
cannot.
|
|
|
|
Scenario:
|
|
* we are running on host 'H0' and we have an instance 'i-0'.
|
|
* instance 'i-0' is a member of security group 'speaks-b'
|
|
* group 'speaks-b' has an ingress rule that authorizes group 'b'
|
|
* another host 'H1' runs an instance 'i-1'
|
|
* instance 'i-1' is a member of security group 'b'
|
|
|
|
When 'i-1' launches or terminates we will receive the message
|
|
to update members of group 'b', at which time we will make
|
|
any changes needed to the rules for instance 'i-0' to allow
|
|
or deny traffic coming from 'i-1', depending on if it is being
|
|
added or removed from the group.
|
|
|
|
In this scenario, 'i-1' could just as easily have been running on our
|
|
host 'H0' and this method would still have been called. The point was
|
|
that this method isn't called on the host where instances of that
|
|
group are running (as is the case with
|
|
:py:meth:`refresh_security_group_rules`) but is called where references
|
|
are made to authorizing those instances.
|
|
|
|
An error should be raised if the operation cannot complete.
|
|
|
|
"""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def refresh_provider_fw_rules(self):
|
|
"""This triggers a firewall update based on database changes.
|
|
|
|
When this is called, rules have either been added or removed from the
|
|
datastore. You can retrieve rules with
|
|
:py:meth:`nova.db.provider_fw_rule_get_all`.
|
|
|
|
Provider rules take precedence over security group rules. If an IP
|
|
would be allowed by a security group ingress rule, but blocked by
|
|
a provider rule, then packets from the IP are dropped. This includes
|
|
intra-project traffic in the case of the allow_project_net_traffic
|
|
flag for the libvirt-derived classes.
|
|
|
|
"""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def reset_network(self, instance):
|
|
"""reset networking for specified instance."""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
pass
|
|
|
|
def ensure_filtering_rules_for_instance(self, instance_ref, network_info):
|
|
"""Setting up filtering rules and waiting for its completion.
|
|
|
|
To migrate an instance, filtering rules to hypervisors
|
|
and firewalls are inevitable on destination host.
|
|
( Waiting only for filtering rules to hypervisor,
|
|
since filtering rules to firewall rules can be set faster).
|
|
|
|
Concretely, the below method must be called.
|
|
- setup_basic_filtering (for nova-basic, etc.)
|
|
- prepare_instance_filter(for nova-instance-instance-xxx, etc.)
|
|
|
|
to_xml may have to be called since it defines PROJNET, PROJMASK.
|
|
but libvirt migrates those value through migrateToURI(),
|
|
so , no need to be called.
|
|
|
|
Don't use thread for this method since migration should
|
|
not be started when setting-up filtering rules operations
|
|
are not completed.
|
|
|
|
:params instance_ref: nova.db.sqlalchemy.models.Instance object
|
|
|
|
"""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def filter_defer_apply_on(self):
|
|
"""Defer application of IPTables rules."""
|
|
pass
|
|
|
|
def filter_defer_apply_off(self):
|
|
"""Turn off deferral of IPTables rules and apply the rules now."""
|
|
pass
|
|
|
|
def unfilter_instance(self, instance, network_info):
|
|
"""Stop filtering instance."""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def set_admin_password(self, context, instance_id, new_pass=None):
|
|
"""
|
|
Set the root password on the specified instance.
|
|
|
|
The first parameter is an instance of nova.compute.service.Instance,
|
|
and so the instance is being specified as instance.name. The second
|
|
parameter is the value of the new password.
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def inject_file(self, instance, b64_path, b64_contents):
|
|
"""
|
|
Writes a file on the specified instance.
|
|
|
|
The first parameter is an instance of nova.compute.service.Instance,
|
|
and so the instance is being specified as instance.name. The second
|
|
parameter is the base64-encoded path to which the file is to be
|
|
written on the instance; the third is the contents of the file, also
|
|
base64-encoded.
|
|
"""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def change_instance_metadata(self, context, instance, diff):
|
|
"""
|
|
Applies a diff to the instance metadata.
|
|
|
|
This is an optional driver method which is used to publish
|
|
changes to the instance's metadata to the hypervisor. If the
|
|
hypervisor has no means of publishing the instance metadata to
|
|
the instance, then this method should not be implemented.
|
|
"""
|
|
pass
|
|
|
|
def inject_network_info(self, instance, nw_info):
|
|
"""inject network info for specified instance."""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
pass
|
|
|
|
def poll_rebooting_instances(self, timeout, instances):
|
|
"""Poll for rebooting instances
|
|
|
|
:param timeout: the currently configured timeout for considering
|
|
rebooting instances to be stuck
|
|
:param instances: instances that have been in rebooting state
|
|
longer than the configured timeout
|
|
"""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def host_power_action(self, host, action):
|
|
"""Reboots, shuts down or powers up the host."""
|
|
raise NotImplementedError()
|
|
|
|
def host_maintenance_mode(self, host, mode):
|
|
"""Start/Stop host maintenance window. On start, it triggers
|
|
guest VMs evacuation."""
|
|
raise NotImplementedError()
|
|
|
|
def set_host_enabled(self, host, enabled):
|
|
"""Sets the specified host's ability to accept new instances."""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def get_host_uptime(self, host):
|
|
"""Returns the result of calling "uptime" on the target host."""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def plug_vifs(self, instance, network_info):
|
|
"""Plug VIFs into networks."""
|
|
# TODO(Vek): Need to pass context in for access to auth_token
|
|
raise NotImplementedError()
|
|
|
|
def unplug_vifs(self, instance, network_info):
|
|
"""Unplug VIFs from networks."""
|
|
raise NotImplementedError()
|
|
|
|
def get_host_stats(self, refresh=False):
|
|
"""Return currently known host stats."""
|
|
raise NotImplementedError()
|
|
|
|
def block_stats(self, instance_name, disk_id):
|
|
"""
|
|
Return performance counters associated with the given disk_id on the
|
|
given instance_name. These are returned as [rd_req, rd_bytes, wr_req,
|
|
wr_bytes, errs], where rd indicates read, wr indicates write, req is
|
|
the total number of I/O requests made, bytes is the total number of
|
|
bytes transferred, and errs is the number of requests held up due to a
|
|
full pipeline.
|
|
|
|
All counters are long integers.
|
|
|
|
This method is optional. On some platforms (e.g. XenAPI) performance
|
|
statistics can be retrieved directly in aggregate form, without Nova
|
|
having to do the aggregation. On those platforms, this method is
|
|
unused.
|
|
|
|
Note that this function takes an instance ID.
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def interface_stats(self, instance_name, iface_id):
|
|
"""
|
|
Return performance counters associated with the given iface_id on the
|
|
given instance_id. These are returned as [rx_bytes, rx_packets,
|
|
rx_errs, rx_drop, tx_bytes, tx_packets, tx_errs, tx_drop], where rx
|
|
indicates receive, tx indicates transmit, bytes and packets indicate
|
|
the total number of bytes or packets transferred, and errs and dropped
|
|
is the total number of packets failed / dropped.
|
|
|
|
All counters are long integers.
|
|
|
|
This method is optional. On some platforms (e.g. XenAPI) performance
|
|
statistics can be retrieved directly in aggregate form, without Nova
|
|
having to do the aggregation. On those platforms, this method is
|
|
unused.
|
|
|
|
Note that this function takes an instance ID.
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def legacy_nwinfo(self):
|
|
"""
|
|
Indicate if the driver requires the legacy network_info format.
|
|
"""
|
|
# TODO(tr3buchet): update all subclasses and remove this
|
|
return True
|
|
|
|
def manage_image_cache(self, context, all_instances):
|
|
"""
|
|
Manage the driver's local image cache.
|
|
|
|
Some drivers chose to cache images for instances on disk. This method
|
|
is an opportunity to do management of that cache which isn't directly
|
|
related to other calls into the driver. The prime example is to clean
|
|
the cache and remove images which are no longer of interest.
|
|
"""
|
|
pass
|
|
|
|
def add_to_aggregate(self, context, aggregate, host, **kwargs):
|
|
"""Add a compute host to an aggregate."""
|
|
#NOTE(jogo) Currently only used for XenAPI-Pool
|
|
raise NotImplementedError()
|
|
|
|
def remove_from_aggregate(self, context, aggregate, host, **kwargs):
|
|
"""Remove a compute host from an aggregate."""
|
|
raise NotImplementedError()
|
|
|
|
def undo_aggregate_operation(self, context, op, aggregate,
|
|
host, set_error=True):
|
|
"""Undo for Resource Pools."""
|
|
raise NotImplementedError()
|
|
|
|
def get_volume_connector(self, instance):
|
|
"""Get connector information for the instance for attaching to volumes.
|
|
|
|
Connector information is a dictionary representing the ip of the
|
|
machine that will be making the connection, the name of the iscsi
|
|
initiator and the hostname of the machine as follows::
|
|
|
|
{
|
|
'ip': ip,
|
|
'initiator': initiator,
|
|
'host': hostname
|
|
}
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def get_available_nodes(self):
|
|
"""Returns nodenames of all nodes managed by the compute service.
|
|
|
|
This method is for multi compute-nodes support. If a driver supports
|
|
multi compute-nodes, this method returns a list of nodenames managed
|
|
by the service. Otherwise, this method should return
|
|
[hypervisor_hostname].
|
|
"""
|
|
stats = self.get_host_stats(refresh=True)
|
|
if not isinstance(stats, list):
|
|
stats = [stats]
|
|
return [s['hypervisor_hostname'] for s in stats]
|
|
|
|
def get_per_instance_usage(self):
|
|
"""Get information about instance resource usage.
|
|
|
|
:returns: dict of nova uuid => dict of usage info
|
|
"""
|
|
return {}
|
|
|
|
def instance_on_disk(self, instance):
|
|
"""Checks access of instance files on the host.
|
|
|
|
:param instance: instance to lookup
|
|
|
|
Returns True if files of an instance with the supplied ID accessible on
|
|
the host, False otherwise.
|
|
|
|
.. note::
|
|
Used in rebuild for HA implementation and required for validation
|
|
of access to instance shared disk files
|
|
"""
|
|
return False
|
|
|
|
|
|
def load_compute_driver(virtapi, compute_driver=None):
|
|
"""Load a compute driver module.
|
|
|
|
Load the compute driver module specified by the compute_driver
|
|
configuration option or, if supplied, the driver name supplied as an
|
|
argument.
|
|
|
|
Compute drivers constructors take a VirtAPI object as their first object
|
|
and this must be supplied.
|
|
|
|
:param virtapi: a VirtAPI instance
|
|
:param compute_driver: a compute driver name to override the config opt
|
|
:returns: a ComputeDriver instance
|
|
"""
|
|
if not compute_driver:
|
|
compute_driver = CONF.compute_driver
|
|
|
|
if not compute_driver:
|
|
LOG.error(_("Compute driver option required, but not specified"))
|
|
sys.exit(1)
|
|
|
|
LOG.info(_("Loading compute driver '%s'") % compute_driver)
|
|
try:
|
|
driver = importutils.import_object_ns('nova.virt',
|
|
compute_driver,
|
|
virtapi)
|
|
return utils.check_isinstance(driver, ComputeDriver)
|
|
except ImportError as e:
|
|
LOG.error(_("Unable to load the virtualization driver: %s") % (e))
|
|
sys.exit(1)
|
|
|
|
|
|
def compute_driver_matches(match):
|
|
return CONF.compute_driver.endswith(match)
|