Merge "Add ODL HA testcase"
[yardstick.git] / yardstick / common / openstack_utils.py
index 0902d29..53f0ccc 100644 (file)
@@ -7,19 +7,21 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 
+import copy
+import logging
 import os
 import sys
-import logging
 
+from cinderclient import client as cinderclient
+from novaclient import client as novaclient
+from glanceclient import client as glanceclient
 from keystoneauth1 import loading
 from keystoneauth1 import session
+from neutronclient.neutron import client as neutronclient
 import shade
 from shade import exc
 
-from cinderclient import client as cinderclient
-from novaclient import client as novaclient
-from glanceclient import client as glanceclient
-from neutronclient.neutron import client as neutronclient
+from yardstick.common import constants
 
 
 log = logging.getLogger(__name__)
@@ -155,8 +157,21 @@ def get_glance_client():    # pragma: no cover
     return glanceclient.Client(get_glance_client_version(), session=sess)
 
 
-def get_shade_client():
-    return shade.openstack_cloud()
+def get_shade_client(**os_cloud_config):
+    """Get Shade OpenStack cloud client
+
+    By default, the input parameters given to "shade.openstack_cloud" method
+    are stored in "constants.OS_CLOUD_DEFAULT_CONFIG". The input parameters
+    passed in this function, "os_cloud_config", will overwrite the default
+    ones.
+
+    :param os_cloud_config: (kwargs) input arguments for
+                            "shade.openstack_cloud" method.
+    :return: ``shade.OpenStackCloud`` object.
+    """
+    params = copy.deepcopy(constants.OS_CLOUD_DEFAULT_CONFIG)
+    params.update(os_cloud_config)
+    return shade.openstack_cloud(**params)
 
 
 # *********************************************
@@ -264,17 +279,36 @@ def create_instance_and_wait_for_active(shade_client, name, image,
                   "Exception message, '%s'", o_exc.orig_message)
 
 
-def attach_server_volume(server_id, volume_id,
-                         device=None):    # pragma: no cover
+def attach_volume_to_server(shade_client, server_name_or_id, volume_name_or_id,
+                            device=None, wait=True, timeout=None):
+    """Attach a volume to a server.
+
+    This will attach a volume, described by the passed in volume
+    dict, to the server described by the passed in server dict on the named
+    device on the server.
+
+    If the volume is already attached to the server, or generally not
+    available, then an exception is raised. To re-attach to a server,
+    but under a different device, the user must detach it first.
+
+    :param server_name_or_id:(string) The server name or id to attach to.
+    :param volume_name_or_id:(string) The volume name or id to attach.
+    :param device:(string) The device name where the volume will attach.
+    :param wait:(bool) If true, waits for volume to be attached.
+    :param timeout: Seconds to wait for volume attachment. None is forever.
+
+    :returns: True if attached successful, False otherwise.
+    """
     try:
-        get_nova_client().volumes.create_server_volume(server_id,
-                                                       volume_id, device)
-    except Exception:  # pylint: disable=broad-except
-        log.exception("Error [attach_server_volume(nova_client, '%s', '%s')]",
-                      server_id, volume_id)
-        return False
-    else:
+        server = shade_client.get_server(name_or_id=server_name_or_id)
+        volume = shade_client.get_volume(volume_name_or_id)
+        shade_client.attach_volume(
+            server, volume, device=device, wait=wait, timeout=timeout)
         return True
+    except exc.OpenStackCloudException as o_exc:
+        log.error("Error [attach_volume_to_server(shade_client)]. "
+                  "Exception message: %s", o_exc.orig_message)
+        return False
 
 
 def delete_instance(shade_client, name_or_id, wait=False, timeout=180,
@@ -302,12 +336,26 @@ def delete_instance(shade_client, name_or_id, wait=False, timeout=180,
         return False
 
 
-def get_server_by_name(name):   # pragma: no cover
+def get_server(shade_client, name_or_id=None, filters=None, detailed=False,
+               bare=False):
+    """Get a server by name or ID.
+
+    :param name_or_id: Name or ID of the server.
+    :param filters:(dict) A dictionary of meta data to use for further
+                   filtering.
+    :param detailed:(bool) Whether or not to add detailed additional
+                    information.
+    :param bare:(bool) Whether to skip adding any additional information to the
+                server record.
+
+    :returns: A server ``munch.Munch`` or None if no matching server is found.
+    """
     try:
-        return get_nova_client().servers.list(search_opts={'name': name})[0]
-    except IndexError:
-        log.exception('Failed to get nova client')
-        raise
+        return shade_client.get_server(name_or_id=name_or_id, filters=filters,
+                                       detailed=detailed, bare=bare)
+    except exc.OpenStackCloudException as o_exc:
+        log.error("Error [get_server(shade_client, '%s')]. "
+                  "Exception message: %s", name_or_id, o_exc.orig_message)
 
 
 def create_flavor(name, ram, vcpus, disk, **kwargs):   # pragma: no cover
@@ -330,12 +378,22 @@ def get_flavor_id(nova_client, flavor_name):    # pragma: no cover
     return flavor_id
 
 
-def get_flavor_by_name(name):   # pragma: no cover
-    flavors = get_nova_client().flavors.list()
+def get_flavor(shade_client, name_or_id, filters=None, get_extra=True):
+    """Get a flavor by name or ID.
+
+    :param name_or_id: Name or ID of the flavor.
+    :param filters: A dictionary of meta data to use for further filtering.
+    :param get_extra: Whether or not the list_flavors call should get the extra
+    flavor specs.
+
+    :returns: A flavor ``munch.Munch`` or None if no matching flavor is found.
+    """
     try:
-        return next((a for a in flavors if a.name == name))
-    except StopIteration:
-        log.exception('No flavor matched')
+        return shade_client.get_flavor(name_or_id, filters=filters,
+                                       get_extra=get_extra)
+    except exc.OpenStackCloudException as o_exc:
+        log.error("Error [get_flavor(shade_client, '%s')]. "
+                  "Exception message: %s", name_or_id, o_exc.orig_message)
 
 
 def delete_flavor(flavor_id):    # pragma: no cover