From c0ef57f8ec086c07053d529510992c869c30c9d2 Mon Sep 17 00:00:00 2001 From: ahothan Date: Sun, 14 Oct 2018 15:15:36 -0700 Subject: NFVBENCH-103 Add --hypervisor cli options and fix vm placement for multi-chain Change-Id: I80ab8b7c39221132ff43b95cd453dbfd4edd580c Signed-off-by: ahothan --- nfvbench/compute.py | 128 +++++++--------------------------------------------- 1 file changed, 16 insertions(+), 112 deletions(-) (limited to 'nfvbench/compute.py') diff --git a/nfvbench/compute.py b/nfvbench/compute.py index 3f97166..d5a8119 100644 --- a/nfvbench/compute.py +++ b/nfvbench/compute.py @@ -11,6 +11,8 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. +"""Module to interface with nova and glance.""" + import time import traceback @@ -26,12 +28,16 @@ from log import LOG class Compute(object): + """Class to interface with nova and glance.""" + def __init__(self, nova_client, glance_client, config): + """Create a new compute instance to interact with nova and glance.""" self.novaclient = nova_client self.glance_client = glance_client self.config = config def find_image(self, image_name): + """Find an image by name.""" try: return next(self.glance_client.images.list(filters={'name': image_name}), None) except (novaclient.exceptions.NotFound, keystoneauth1.exceptions.http.NotFound, @@ -78,6 +84,7 @@ class Compute(object): return True def delete_image(self, img_name): + """Delete an image by name.""" try: LOG.log("Deleting image %s...", img_name) img = self.find_image(image_name=img_name) @@ -93,7 +100,7 @@ class Compute(object): def create_server(self, vmname, image, flavor, key_name, nic, sec_group, avail_zone=None, user_data=None, config_drive=None, files=None): - + """Create a new server.""" if sec_group: security_groups = [sec_group['id']] else: @@ -113,16 +120,20 @@ class Compute(object): return instance def poll_server(self, instance): + """Poll a server from its reference.""" return self.novaclient.servers.get(instance.id) def get_server_list(self): + """Get the list of all servers.""" servers_list = self.novaclient.servers.list() return servers_list def delete_server(self, server): + """Delete a server from its object reference.""" self.novaclient.servers.delete(server) def find_flavor(self, flavor_type): + """Find a flavor by name.""" try: flavor = self.novaclient.flavors.find(name=flavor_type) return flavor @@ -130,122 +141,15 @@ class Compute(object): return None def create_flavor(self, name, ram, vcpus, disk, ephemeral=0): + """Create a flavor.""" return self.novaclient.flavors.create(name=name, ram=ram, vcpus=vcpus, disk=disk, ephemeral=ephemeral) - def normalize_az_host(self, az, host): - if not az: - az = self.config.availability_zone - return az + ':' + host - - def auto_fill_az(self, host_list, host): - """Auto fill az:host. - - no az provided, if there is a host list we can auto-fill the az - else we use the configured az if available - else we return an error - """ - if host_list: - for hyp in host_list: - if hyp.host == host: - return self.normalize_az_host(hyp.zone, host) - # no match on host - LOG.error('Passed host name does not exist: %s', host) - return None - if self.config.availability_zone: - return self.normalize_az_host(None, host) - LOG.error('--hypervisor passed without an az and no az configured') - return None - - def sanitize_az_host(self, host_list, az_host): - """Sanitize the az:host string. + def get_hypervisor(self, hyper_name): + """Get the hypervisor from its name. - host_list: list of hosts as retrieved from openstack (can be empty) - az_host: either a host or a az:host string - if a host, will check host is in the list, find the corresponding az and - return az:host - if az:host is passed will check the host is in the list and az matches - if host_list is empty, will return the configured az if there is no - az passed - """ - if ':' in az_host: - # no host_list, return as is (no check) - if not host_list: - return az_host - # if there is a host_list, extract and verify the az and host - az_host_list = az_host.split(':') - zone = az_host_list[0] - host = az_host_list[1] - for hyp in host_list: - if hyp.host == host: - if hyp.zone == zone: - # matches - return az_host - # else continue - another zone with same host name? - # no match - LOG.error('No match for availability zone and host %s', az_host) - return None - else: - return self.auto_fill_az(host_list, az_host) - - # - # Return a list of 0, 1 or 2 az:host - # - # The list is computed as follows: - # The list of all hosts is retrieved first from openstack - # if this fails, checks and az auto-fill are disabled - # - # If the user provides a configured az name (config.availability_zone) - # up to the first 2 hosts from the list that match the az are returned - # - # If the user did not configure an az name - # up to the first 2 hosts from the list are returned - # Possible return values: - # [ az ] - # [ az:hyp ] - # [ az1:hyp1, az2:hyp2 ] - # [] if an error occurred (error message printed to console) - # - def get_enabled_az_host_list(self, required_count=1): - """Check which hypervisors are enabled and on which compute nodes they are running. - - Pick up to the required count of hosts (can be less or zero) - - :param required_count: count of compute-nodes to return - :return: list of enabled available compute nodes + Can raise novaclient.exceptions.NotFound """ - host_list = [] - hypervisor_list = [] - - try: - hypervisor_list = self.novaclient.hypervisors.list() - host_list = self.novaclient.services.list() - except novaclient.exceptions.Forbidden: - LOG.warning('Operation Forbidden: could not retrieve list of hypervisors' - ' (likely no permission)') - - hypervisor_list = [h for h in hypervisor_list if h.status == 'enabled' and h.state == 'up'] - if self.config.availability_zone: - host_list = [h for h in host_list if h.zone == self.config.availability_zone] - - if self.config.compute_nodes: - host_list = [h for h in host_list if h.host in self.config.compute_nodes] - - hosts = [h.hypervisor_hostname for h in hypervisor_list] - host_list = [h for h in host_list if h.host in hosts] - - avail_list = [] - for host in host_list: - candidate = self.normalize_az_host(host.zone, host.host) - if candidate: - avail_list.append(candidate) - if len(avail_list) == required_count: - return avail_list - - return avail_list - - def get_hypervisor(self, hyper_name): - # can raise novaclient.exceptions.NotFound # first get the id from name hyper = self.novaclient.hypervisors.search(hyper_name)[0] # get full hypervisor object -- cgit 1.2.3-korg