aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/resources/env_action.py3
-rw-r--r--tests/unit/common/test_openstack_utils.py28
-rw-r--r--yardstick/common/openstack_utils.py348
-rw-r--r--yardstick/common/utils.py17
4 files changed, 361 insertions, 35 deletions
diff --git a/api/resources/env_action.py b/api/resources/env_action.py
index 2d3496cbc..ea94bc123 100644
--- a/api/resources/env_action.py
+++ b/api/resources/env_action.py
@@ -27,6 +27,7 @@ from api.utils.common import result_handler
from docker import Client
from yardstick.common import constants as config
from yardstick.common import utils as yardstick_utils
+from yardstick.common import openstack_utils
from yardstick.common.httpClient import HttpClient
logger = logging.getLogger(__name__)
@@ -263,7 +264,7 @@ def _get_remote_rc_file(rc_file, installer_ip, installer_type):
def _append_external_network(rc_file):
- neutron_client = yardstick_utils.get_neutron_client()
+ neutron_client = openstack_utils.get_neutron_client()
networks = neutron_client.list_networks()['networks']
try:
ext_network = next(n['name'] for n in networks if n['router:external'])
diff --git a/tests/unit/common/test_openstack_utils.py b/tests/unit/common/test_openstack_utils.py
index d610e181c..b3dc2d9c4 100644
--- a/tests/unit/common/test_openstack_utils.py
+++ b/tests/unit/common/test_openstack_utils.py
@@ -22,21 +22,25 @@ class GetCredentialsTestCase(unittest.TestCase):
@mock.patch('yardstick.common.openstack_utils.os')
def test_get_credentials(self, mock_os):
- mock_os.getenv.return_value = ('2')
- openstack_utils.get_credentials()
+ with mock.patch.dict('os.environ', {'OS_IDENTITY_API_VERSION': '2'},
+ clear=True):
+ openstack_utils.get_credentials()
class GetHeatApiVersionTestCase(unittest.TestCase):
- @mock.patch('yardstick.common.openstack_utils.os')
- def test_get_heat_api_version(self, mock_os):
+ def test_get_heat_api_version_check_result(self):
API = 'HEAT_API_VERSION'
- openstack_utils.get_heat_api_version()
- mock_os.getenv.assert_called_with(API)
-
- @mock.patch('yardstick.common.openstack_utils.os')
- def test_get_heat_api_version(self, mock_os):
- mock_os.getenv.return_value = ('2')
expected_result = '2'
- api_version = openstack_utils.get_heat_api_version()
- self.assertEqual(api_version, expected_result)
+
+ with mock.patch.dict('os.environ', {API: '2'}, clear=True):
+ api_version = openstack_utils.get_heat_api_version()
+ self.assertEqual(api_version, expected_result)
+
+
+def main():
+ unittest.main()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/yardstick/common/openstack_utils.py b/yardstick/common/openstack_utils.py
index 5026e819d..aa369b896 100644
--- a/yardstick/common/openstack_utils.py
+++ b/yardstick/common/openstack_utils.py
@@ -8,17 +8,26 @@
##############################################################################
from __future__ import absolute_import
+
import os
+import time
import logging
from keystoneauth1 import loading
from keystoneauth1 import session
+from novaclient import client as novaclient
+from glanceclient import client as glanceclient
+from neutronclient.neutron import client as neutronclient
log = logging.getLogger(__name__)
DEFAULT_HEAT_API_VERSION = '1'
+DEFAULT_API_VERSION = '2'
+# *********************************************
+# CREDENTIALS
+# *********************************************
def get_credentials():
"""Returns a creds dictionary filled with parsed from env"""
creds = {}
@@ -64,7 +73,7 @@ def get_credentials():
"ca_file": cacert})
creds.update({"insecure": "True", "https_insecure": "True"})
if not os.path.isfile(cacert):
- log.info("WARNING: The 'OS_CACERT' environment variable is set\
+ log.info("WARNING: The 'OS_CACERT' environment variable is set \
to %s but the file does not exist.", cacert)
return creds
@@ -89,9 +98,338 @@ def get_endpoint(service_type, endpoint_type='publicURL'):
endpoint_type=endpoint_type)
-def get_heat_api_version():
- api_version = os.getenv('HEAT_API_VERSION')
- if api_version is not None:
+# *********************************************
+# CLIENTS
+# *********************************************
+def get_heat_api_version(): # pragma: no cover
+ try:
+ api_version = os.environ['HEAT_API_VERSION']
+ except KeyError:
+ return DEFAULT_HEAT_API_VERSION
+ else:
log.info("HEAT_API_VERSION is set in env as '%s'", api_version)
return api_version
- return DEFAULT_HEAT_API_VERSION
+
+
+def get_nova_client_version(): # pragma: no cover
+ try:
+ api_version = os.environ['OS_COMPUTE_API_VERSION']
+ except KeyError:
+ return DEFAULT_API_VERSION
+ else:
+ log.info("OS_COMPUTE_API_VERSION is set in env as '%s'", api_version)
+ return api_version
+
+
+def get_nova_client(): # pragma: no cover
+ sess = get_session()
+ return novaclient.Client(get_nova_client_version(), session=sess)
+
+
+def get_neutron_client_version(): # pragma: no cover
+ try:
+ api_version = os.environ['OS_NETWORK_API_VERSION']
+ except KeyError:
+ return DEFAULT_API_VERSION
+ else:
+ log.info("OS_NETWORK_API_VERSION is set in env as '%s'", api_version)
+ return api_version
+
+
+def get_neutron_client(): # pragma: no cover
+ sess = get_session()
+ return neutronclient.Client(get_neutron_client_version(), session=sess)
+
+
+def get_glance_client_version(): # pragma: no cover
+ try:
+ api_version = os.environ['OS_IMAGE_API_VERSION']
+ except KeyError:
+ return DEFAULT_API_VERSION
+ else:
+ log.info("OS_IMAGE_API_VERSION is set in env as '%s'", api_version)
+ return api_version
+
+
+def get_glance_client(): # pragma: no cover
+ sess = get_session()
+ return glanceclient.Client(get_glance_client_version(), session=sess)
+
+
+# *********************************************
+# NOVA
+# *********************************************
+def get_instances(nova_client): # pragma: no cover
+ try:
+ return nova_client.servers.list(search_opts={'all_tenants': 1})
+ except Exception:
+ log.exception("Error [get_instances(nova_client)]")
+
+
+def get_instance_status(nova_client, instance): # pragma: no cover
+ try:
+ return nova_client.servers.get(instance.id).status
+ except Exception:
+ log.exception("Error [get_instance_status(nova_client)]")
+
+
+def get_instance_by_name(nova_client, instance_name): # pragma: no cover
+ try:
+ return nova_client.servers.find(name=instance_name)
+ except Exception:
+ log.exception("Error [get_instance_by_name(nova_client, '%s')]",
+ instance_name)
+
+
+def get_aggregates(nova_client): # pragma: no cover
+ try:
+ return nova_client.aggregates.list()
+ except Exception:
+ log.exception("Error [get_aggregates(nova_client)]")
+
+
+def get_availability_zones(nova_client): # pragma: no cover
+ try:
+ return nova_client.availability_zones.list()
+ except Exception:
+ log.exception("Error [get_availability_zones(nova_client)]")
+
+
+def get_availability_zone_names(nova_client): # pragma: no cover
+ try:
+ return [az.zoneName for az in get_availability_zones(nova_client)]
+ except Exception:
+ log.exception("Error [get_availability_zone_names(nova_client)]")
+
+
+def create_aggregate(nova_client, aggregate_name, av_zone): # pragma: no cover
+ try:
+ nova_client.aggregates.create(aggregate_name, av_zone)
+ except Exception:
+ log.exception("Error [create_aggregate(nova_client, %s, %s)]",
+ aggregate_name, av_zone)
+ return False
+ else:
+ return True
+
+
+def get_aggregate_id(nova_client, aggregate_name): # pragma: no cover
+ try:
+ aggregates = get_aggregates(nova_client)
+ _id = next((ag.id for ag in aggregates if ag.name == aggregate_name))
+ except Exception:
+ log.exception("Error [get_aggregate_id(nova_client, %s)]",
+ aggregate_name)
+ else:
+ return _id
+
+
+def add_host_to_aggregate(nova_client, aggregate_name,
+ compute_host): # pragma: no cover
+ try:
+ aggregate_id = get_aggregate_id(nova_client, aggregate_name)
+ nova_client.aggregates.add_host(aggregate_id, compute_host)
+ except Exception:
+ log.exception("Error [add_host_to_aggregate(nova_client, %s, %s)]",
+ aggregate_name, compute_host)
+ return False
+ else:
+ return True
+
+
+def create_aggregate_with_host(nova_client, aggregate_name, av_zone,
+ compute_host): # pragma: no cover
+ try:
+ create_aggregate(nova_client, aggregate_name, av_zone)
+ add_host_to_aggregate(nova_client, aggregate_name, compute_host)
+ except Exception:
+ log.exception("Error [create_aggregate_with_host("
+ "nova_client, %s, %s, %s)]",
+ aggregate_name, av_zone, compute_host)
+ return False
+ else:
+ return True
+
+
+def create_instance(flavor_name,
+ image_id,
+ network_id,
+ instance_name="instance-vm",
+ confdrive=True,
+ userdata=None,
+ av_zone='',
+ fixed_ip=None,
+ files=None): # pragma: no cover
+ nova_client = get_nova_client()
+ try:
+ flavor = nova_client.flavors.find(name=flavor_name)
+ except:
+ flavors = nova_client.flavors.list()
+ log.exception("Error: Flavor '%s' not found. Available flavors are: "
+ "\n%s", flavor_name, flavors)
+ return None
+ if fixed_ip is not None:
+ nics = {"net-id": network_id, "v4-fixed-ip": fixed_ip}
+ else:
+ nics = {"net-id": network_id}
+ if userdata is None:
+ instance = nova_client.servers.create(
+ name=instance_name,
+ flavor=flavor,
+ image=image_id,
+ nics=[nics],
+ availability_zone=av_zone,
+ files=files
+ )
+ else:
+ instance = nova_client.servers.create(
+ name=instance_name,
+ flavor=flavor,
+ image=image_id,
+ nics=[nics],
+ config_drive=confdrive,
+ userdata=userdata,
+ availability_zone=av_zone,
+ files=files
+ )
+ return instance
+
+
+def create_instance_and_wait_for_active(flavor_name,
+ image_id,
+ network_id,
+ instance_name="instance-vm",
+ config_drive=False,
+ userdata="",
+ av_zone='',
+ fixed_ip=None,
+ files=None): # pragma: no cover
+ SLEEP = 3
+ VM_BOOT_TIMEOUT = 180
+ nova_client = get_nova_client()
+ instance = create_instance(flavor_name,
+ image_id,
+ network_id,
+ instance_name,
+ config_drive,
+ userdata,
+ av_zone=av_zone,
+ fixed_ip=fixed_ip,
+ files=files)
+ count = VM_BOOT_TIMEOUT / SLEEP
+ for n in range(count, -1, -1):
+ status = get_instance_status(nova_client, instance)
+ if status.lower() == "active":
+ return instance
+ elif status.lower() == "error":
+ log.error("The instance %s went to ERROR status.", instance_name)
+ return None
+ time.sleep(SLEEP)
+ log.error("Timeout booting the instance %s.", instance_name)
+ return None
+
+
+def delete_instance(nova_client, instance_id): # pragma: no cover
+ try:
+ nova_client.servers.force_delete(instance_id)
+ except Exception:
+ log.exception("Error [delete_instance(nova_client, '%s')]",
+ instance_id)
+ return False
+ else:
+ return True
+
+
+def remove_host_from_aggregate(nova_client, aggregate_name,
+ compute_host): # pragma: no cover
+ try:
+ aggregate_id = get_aggregate_id(nova_client, aggregate_name)
+ nova_client.aggregates.remove_host(aggregate_id, compute_host)
+ except Exception:
+ log.exception("Error remove_host_from_aggregate(nova_client, %s, %s)",
+ aggregate_name, compute_host)
+ return False
+ else:
+ return True
+
+
+def remove_hosts_from_aggregate(nova_client,
+ aggregate_name): # pragma: no cover
+ aggregate_id = get_aggregate_id(nova_client, aggregate_name)
+ hosts = nova_client.aggregates.get(aggregate_id).hosts
+ assert(
+ all(remove_host_from_aggregate(nova_client, aggregate_name, host)
+ for host in hosts))
+
+
+def delete_aggregate(nova_client, aggregate_name): # pragma: no cover
+ try:
+ remove_hosts_from_aggregate(nova_client, aggregate_name)
+ nova_client.aggregates.delete(aggregate_name)
+ except Exception:
+ log.exception("Error [delete_aggregate(nova_client, %s)]",
+ aggregate_name)
+ return False
+ else:
+ return True
+
+
+def get_server_by_name(name): # pragma: no cover
+ try:
+ return get_nova_client().servers.list(search_opts={'name': name})[0]
+ except IndexError:
+ log.exception('Failed to get nova client')
+ raise
+
+
+def get_image_by_name(name): # pragma: no cover
+ images = get_nova_client().images.list()
+ try:
+ return next((a for a in images if a.name == name))
+ except StopIteration:
+ log.exception('No image matched')
+
+
+def get_flavor_by_name(name): # pragma: no cover
+ flavors = get_nova_client().flavors.list()
+ try:
+ return next((a for a in flavors if a.name == name))
+ except StopIteration:
+ log.exception('No flavor matched')
+
+
+def check_status(status, name, iterations, interval): # pragma: no cover
+ for i in range(iterations):
+ try:
+ server = get_server_by_name(name)
+ except IndexError:
+ log.error('Cannot found %s server', name)
+ raise
+
+ if server.status == status:
+ return True
+
+ time.sleep(interval)
+ return False
+
+
+# *********************************************
+# NEUTRON
+# *********************************************
+def get_network_id(neutron_client, network_name): # pragma: no cover
+ networks = neutron_client.list_networks()['networks']
+ return next((n['id'] for n in networks if n['name'] == network_name), None)
+
+
+def get_port_id_by_ip(neutron_client, ip_address): # pragma: no cover
+ ports = neutron_client.list_ports()['ports']
+ return next((i['id'] for i in ports for j in i.get(
+ 'fixed_ips') if j['ip_address'] == ip_address), None)
+
+
+# *********************************************
+# GLANCE
+# *********************************************
+def get_image_id(glance_client, image_name): # pragma: no cover
+ images = glance_client.images.list()
+ return next((i.id for i in images if i.name == image_name), None)
diff --git a/yardstick/common/utils.py b/yardstick/common/utils.py
index 04536190b..3c5895f1e 100644
--- a/yardstick/common/utils.py
+++ b/yardstick/common/utils.py
@@ -26,9 +26,6 @@ import sys
from functools import reduce
import yaml
-from keystoneauth1 import identity
-from keystoneauth1 import session
-from neutronclient.v2_0 import client
from oslo_utils import importutils
from oslo_serialization import jsonutils
@@ -134,20 +131,6 @@ def source_env(env_file):
return env
-def get_openstack_session():
- auth = identity.Password(auth_url=os.environ.get('OS_AUTH_URL'),
- username=os.environ.get('OS_USERNAME'),
- password=os.environ.get('OS_PASSWORD'),
- tenant_name=os.environ.get('OS_TENANT_NAME'))
- return session.Session(auth=auth)
-
-
-def get_neutron_client():
- sess = get_openstack_session()
- neutron_client = client.Client(session=sess)
- return neutron_client
-
-
def read_json_from_file(path):
with open(path, 'r') as f:
return jsonutils.load(f)