Stop using docker install script
[functest.git] / functest / core / cloudify.py
index 158929b..966d336 100644 (file)
 from __future__ import division
 
 import logging
+import os
 import time
+import traceback
 
 from cloudify_rest_client import CloudifyClient
+from cloudify_rest_client.executions import Execution
+import scp
 
 from functest.core import singlevm
 
@@ -25,24 +29,28 @@ class Cloudify(singlevm.SingleVm2):
     __logger = logging.getLogger(__name__)
 
     filename = ('/home/opnfv/functest/images/'
-                'cloudify-manager-premium-4.0.1.qcow2')
+                'ubuntu-18.04-server-cloudimg-amd64.img')
     flavor_ram = 4096
     flavor_vcpus = 2
     flavor_disk = 40
-    username = 'centos'
+    username = 'ubuntu'
     ssh_connect_loops = 12
-    create_server_timeout = 300
+    create_server_timeout = 600
     ports = [80, 443, 5671, 53333]
 
+    cloudify_archive = ('/home/opnfv/functest/images/'
+                        'cloudify-docker-manager-community-19.01.24.tar')
+    cloudify_container = "docker-cfy-manager:latest"
+
     def __init__(self, **kwargs):
         """Initialize Cloudify testcase object."""
         if "case_name" not in kwargs:
             kwargs["case_name"] = "cloudify"
-        super(Cloudify, self).__init__(**kwargs)
+        super().__init__(**kwargs)
         self.cfy_client = None
 
     def prepare(self):
-        super(Cloudify, self).prepare()
+        super().prepare()
         for port in self.ports:
             self.cloud.create_security_group_rule(
                 self.sec.id, port_range_min=port, port_range_max=port,
@@ -52,12 +60,28 @@ class Cloudify(singlevm.SingleVm2):
         """
         Deploy Cloudify Manager.
         """
+        scpc = scp.SCPClient(self.ssh.get_transport())
+        scpc.put(self.cloudify_archive,
+                 remote_path=os.path.basename(self.cloudify_archive))
+        (_, stdout, stderr) = self.ssh.exec_command(
+            "sudo apt-get update && "
+            "sudo apt-get install -y docker.io && "
+            "sudo docker load -i "
+            f"~/{os.path.basename(self.cloudify_archive)} && "
+            "sudo docker run --name cfy_manager_local -d "
+            "--restart unless-stopped -v /sys/fs/cgroup:/sys/fs/cgroup:ro "
+            "--tmpfs /run --tmpfs /run/lock --security-opt seccomp:unconfined "
+            f"--cap-add SYS_ADMIN --network=host {self.cloudify_container}")
+        self.__logger.debug("output:\n%s", stdout.read().decode("utf-8"))
+        self.__logger.debug("error:\n%s", stderr.read().decode("utf-8"))
         self.cfy_client = CloudifyClient(
-            host=self.fip.floating_ip_address,
-            username='admin', password='admin', tenant='default_tenant',
-            api_version='v3')
+            host=self.fip.floating_ip_address if self.fip else (
+                self.sshvm.public_v4),
+            username='admin', password='admin', tenant='default_tenant')
         self.__logger.info("Attemps running status of the Manager")
-        for loop in range(10):
+        secret_key = "foo"
+        secret_value = "bar"
+        for loop in range(20):
             try:
                 self.__logger.debug(
                     "status %s", self.cfy_client.manager.get_status())
@@ -66,18 +90,130 @@ class Cloudify(singlevm.SingleVm2):
                     "The current manager status is %s", cfy_status)
                 if str(cfy_status) != 'running':
                     raise Exception("Cloudify Manager isn't up and running")
-                self.cfy_client.secrets.create("foo", "bar")
-                self.__logger.debug(
-                    "List secrets: %s", self.cfy_client.secrets.list())
-                self.cfy_client.secrets.delete("foo")
+                for secret in iter(self.cfy_client.secrets.list()):
+                    if secret_key == secret["key"]:
+                        self.__logger.debug("Updating secrets: %s", secret_key)
+                        self.cfy_client.secrets.update(
+                            secret_key, secret_value)
+                        break
+                else:
+                    self.__logger.debug("Creating secrets: %s", secret_key)
+                    self.cfy_client.secrets.create(secret_key, secret_value)
+                self.cfy_client.secrets.delete(secret_key)
                 self.__logger.info("Secrets API successfully reached")
                 break
             except Exception:  # pylint: disable=broad-except
-                self.__logger.info(
-                    "try %s: Cloudify Manager isn't up and running", loop + 1)
+                self.__logger.debug(
+                    "try %s: Cloudify Manager isn't up and running \n%s",
+                    loop + 1, traceback.format_exc())
                 time.sleep(30)
         else:
             self.__logger.error("Cloudify Manager isn't up and running")
             return 1
         self.__logger.info("Cloudify Manager is up and running")
         return 0
+
+    def put_private_key(self):
+        """Put private keypair in manager"""
+        self.__logger.info("Put private keypair in manager")
+        scpc = scp.SCPClient(self.ssh.get_transport())
+        scpc.put(self.key_filename, remote_path='~/cloudify_ims.pem')
+        (_, stdout, stderr) = self.ssh.exec_command(
+            "sudo docker cp ~/cloudify_ims.pem "
+            "cfy_manager_local:/etc/cloudify/ && "
+            "sudo docker exec cfy_manager_local "
+            "chmod 444 /etc/cloudify/cloudify_ims.pem")
+        self.__logger.debug("output:\n%s", stdout.read().decode("utf-8"))
+        self.__logger.debug("error:\n%s", stderr.read().decode("utf-8"))
+
+    def upload_cfy_plugins(self, yaml, wgn):
+        """Upload Cloudify plugins"""
+        (_, stdout, stderr) = self.ssh.exec_command(
+            "sudo docker exec cfy_manager_local "
+            f"cfy plugins upload -y {yaml} {wgn} && "
+            "sudo docker exec cfy_manager_local cfy status")
+        self.__logger.debug("output:\n%s", stdout.read().decode("utf-8"))
+        self.__logger.debug("error:\n%s", stderr.read().decode("utf-8"))
+
+    def kill_existing_execution(self, dep_name):
+        """kill existing execution"""
+        try:
+            self.__logger.info('Deleting the current deployment')
+            exec_list = self.cfy_client.executions.list()
+            for execution in exec_list:
+                if execution['status'] == "started":
+                    try:
+                        self.cfy_client.executions.cancel(
+                            execution['id'], force=True)
+                    except Exception:  # pylint: disable=broad-except
+                        self.__logger.warning("Can't cancel the current exec")
+            execution = self.cfy_client.executions.start(
+                dep_name, 'uninstall', parameters=dict(ignore_failure=True))
+            wait_for_execution(self.cfy_client, execution, self.__logger)
+            self.cfy_client.deployments.delete(dep_name)
+            time.sleep(10)
+            self.cfy_client.blueprints.delete(dep_name)
+        except Exception:  # pylint: disable=broad-except
+            self.__logger.exception("Some issue during the undeployment ..")
+
+
+def wait_for_execution(client, execution, logger, timeout=3600, ):
+    """Wait for a workflow execution on Cloudify Manager."""
+    # if execution already ended - return without waiting
+    if execution.status in Execution.END_STATES:
+        return execution
+
+    if timeout is not None:
+        deadline = time.time() + timeout
+
+    # Poll for execution status and execution logs, until execution ends
+    # and we receive an event of type in WORKFLOW_END_TYPES
+    offset = 0
+    batch_size = 50
+    event_list = []
+    execution_ended = False
+    while True:
+        event_list = client.events.list(
+            execution_id=execution.id,
+            _offset=offset,
+            _size=batch_size,
+            include_logs=True,
+            sort='@timestamp').items
+
+        offset = offset + len(event_list)
+        for event in event_list:
+            logger.debug(event.get('message'))
+
+        if timeout is not None:
+            if time.time() > deadline:
+                raise RuntimeError(
+                    'execution of operation {execution.workflow_id} for '
+                    'deployment {execution.deployment_id} timed out')
+            # update the remaining timeout
+            timeout = deadline - time.time()
+
+        if not execution_ended:
+            execution = client.executions.get(execution.id)
+            execution_ended = execution.status in Execution.END_STATES
+
+        if execution_ended:
+            break
+
+        time.sleep(5)
+
+    return execution
+
+
+def get_execution_id(client, deployment_id):
+    """
+    Get the execution id of a env preparation.
+
+    network, security group, fip, VM creation
+    """
+    executions = client.executions.list(deployment_id=deployment_id)
+    for execution in executions:
+        if execution.workflow_id == 'create_deployment_environment':
+            return execution
+    raise RuntimeError('Failed to get create_deployment_environment '
+                       'workflow execution.'
+                       f'Available executions: {executions}')