Added documentation to the nova.virt interface.
This commit is contained in:
@@ -27,6 +27,15 @@ FLAGS = flags.FLAGS
|
||||
|
||||
|
||||
def get_connection(read_only=False):
|
||||
"""Returns an object representing the connection to a virtualization
|
||||
platform. This could be nova.virt.fake.FakeConnection in test mode,
|
||||
a connection to KVM or QEMU via libvirt, or a connection to XenServer
|
||||
or Xen Cloud Platform via XenAPI.
|
||||
|
||||
Any object returned here must conform to the interface documented by
|
||||
FakeConnection.
|
||||
"""
|
||||
|
||||
# TODO(termie): maybe lazy load after initial check for permissions
|
||||
# TODO(termie): check whether we can be disconnected
|
||||
t = FLAGS.connection_type
|
||||
|
||||
+128
-1
@@ -19,6 +19,7 @@
|
||||
|
||||
"""
|
||||
A fake (in-memory) hypervisor+api. Allows nova testing w/o a hypervisor.
|
||||
This module also documents the semantics of real hypervisor connections.
|
||||
"""
|
||||
|
||||
import logging
|
||||
@@ -32,6 +33,38 @@ def get_connection(_):
|
||||
|
||||
|
||||
class FakeConnection(object):
|
||||
"""
|
||||
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.
|
||||
|
||||
In contrast, the list_disks and list_interfaces calls may return
|
||||
platform-specific IDs. These identify a specific virtual disk or specific
|
||||
virtual network interface, and these IDs are opaque to the rest of Nova.
|
||||
|
||||
Some methods here take an instance of nova.compute.service.Instance. This
|
||||
is the datastructure used by nova.compute to store details regarding an
|
||||
instance, and pass them into this layer. This layer is responsible for
|
||||
translating that generic datastructure into terms that are specific to the
|
||||
virtualization platform.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.instances = {}
|
||||
|
||||
@@ -42,20 +75,59 @@ class FakeConnection(object):
|
||||
return cls._instance
|
||||
|
||||
def list_instances(self):
|
||||
"""
|
||||
Return the names of all the instances known to the virtualization
|
||||
layer, as a list.
|
||||
"""
|
||||
return self.instances.keys()
|
||||
|
||||
def spawn(self, instance):
|
||||
"""
|
||||
Create a new instance/VM/domain on the virtualization platform.
|
||||
|
||||
The given parameter is an instance of nova.compute.service.Instance.
|
||||
This function should use the data there to guide the creation of
|
||||
the new instance.
|
||||
|
||||
Once this function successfully completes, the instance should be
|
||||
running (power_state.RUNNING).
|
||||
|
||||
If this function 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.
|
||||
"""
|
||||
|
||||
fake_instance = FakeInstance()
|
||||
self.instances[instance.name] = fake_instance
|
||||
fake_instance._state = power_state.RUNNING
|
||||
|
||||
def reboot(self, instance):
|
||||
"""
|
||||
Reboot the specified instance.
|
||||
|
||||
The given parameter is an instance of nova.compute.service.Instance,
|
||||
and so the instance is being specified as instance.name.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def destroy(self, instance):
|
||||
"""
|
||||
Destroy (shutdown and delete) the specified instance.
|
||||
|
||||
The given parameter is an instance of nova.compute.service.Instance,
|
||||
and so the instance is being specified as instance.name.
|
||||
"""
|
||||
del self.instances[instance.name]
|
||||
|
||||
def get_info(self, instance_id):
|
||||
"""
|
||||
Get a block of information about the given instance. This is returned
|
||||
as a dictionary containing 'state': The power_state of the instance,
|
||||
'max_mem': The maximum memory for the instance, in KiB, 'mem': The
|
||||
current memory the instance has, in KiB, 'num_cpu': The current number
|
||||
of virtual CPUs the instance has, 'cpu_time': The total CPU time used
|
||||
by the instance, in nanoseconds.
|
||||
"""
|
||||
i = self.instances[instance_id]
|
||||
return {'state': i._state,
|
||||
'max_mem': 0,
|
||||
@@ -64,15 +136,70 @@ class FakeConnection(object):
|
||||
'cpu_time': 0}
|
||||
|
||||
def list_disks(self, instance_id):
|
||||
"""
|
||||
Return the IDs of all the virtual disks attached to the specified
|
||||
instance, as a list. These IDs are opaque to the caller (they are
|
||||
only useful for giving back to this layer as a parameter to
|
||||
disk_stats). These IDs only need to be unique for a given instance.
|
||||
|
||||
Note that this function takes an instance ID, not a
|
||||
compute.service.Instance, so that it can be called by compute.monitor.
|
||||
"""
|
||||
return ['A_DISK']
|
||||
|
||||
def list_interfaces(self, instance_id):
|
||||
"""
|
||||
Return the IDs of all the virtual network interfaces attached to the
|
||||
specified instance, as a list. These IDs are opaque to the caller
|
||||
(they are only useful for giving back to this layer as a parameter to
|
||||
interface_stats). These IDs only need to be unique for a given
|
||||
instance.
|
||||
|
||||
Note that this function takes an instance ID, not a
|
||||
compute.service.Instance, so that it can be called by compute.monitor.
|
||||
"""
|
||||
return ['A_VIF']
|
||||
|
||||
def block_stats(self, instance_id, disk_id):
|
||||
"""
|
||||
Return performance counters associated with the given disk_id on the
|
||||
given instance_id. 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, not a
|
||||
compute.service.Instance, so that it can be called by compute.monitor.
|
||||
"""
|
||||
return [0L, 0L, 0L, 0L, null]
|
||||
|
||||
def interface_stats(self, instance_id, 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, not a
|
||||
compute.service.Instance, so that it can be called by compute.monitor.
|
||||
"""
|
||||
return [0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L]
|
||||
|
||||
|
||||
|
||||
@@ -261,12 +261,6 @@ class LibvirtConnection(object):
|
||||
|
||||
|
||||
def get_disks(self, instance_id):
|
||||
"""
|
||||
Note that this function takes an instance ID, not an Instance, so
|
||||
that it can be called by monitor.
|
||||
|
||||
Returns a list of all block devices for this domain.
|
||||
"""
|
||||
domain = self._conn.lookupByName(instance_id)
|
||||
# TODO(devcamcar): Replace libxml2 with etree.
|
||||
xml = domain.XMLDesc(0)
|
||||
@@ -304,12 +298,6 @@ class LibvirtConnection(object):
|
||||
|
||||
|
||||
def get_interfaces(self, instance_id):
|
||||
"""
|
||||
Note that this function takes an instance ID, not an Instance, so
|
||||
that it can be called by monitor.
|
||||
|
||||
Returns a list of all network interfaces for this instance.
|
||||
"""
|
||||
domain = self._conn.lookupByName(instance_id)
|
||||
# TODO(devcamcar): Replace libxml2 with etree.
|
||||
xml = domain.XMLDesc(0)
|
||||
@@ -347,18 +335,10 @@ class LibvirtConnection(object):
|
||||
|
||||
|
||||
def block_stats(self, instance_id, disk):
|
||||
"""
|
||||
Note that this function takes an instance ID, not an Instance, so
|
||||
that it can be called by monitor.
|
||||
"""
|
||||
domain = self._conn.lookupByName(instance_id)
|
||||
return domain.blockStats(disk)
|
||||
|
||||
|
||||
def interface_stats(self, instance_id, interface):
|
||||
"""
|
||||
Note that this function takes an instance ID, not an Instance, so
|
||||
that it can be called by monitor.
|
||||
"""
|
||||
domain = self._conn.lookupByName(instance_id)
|
||||
return domain.interfaceStats(interface)
|
||||
|
||||
Reference in New Issue
Block a user