Introduced command 'env redeploy' in v2 version of fuelclient
Example: `fuel2 env redeploy <env_id>` Fixed deployment tests. Fuel-web repo has been changed from 'stackforge' to 'openstack'. Partial-Bug: 1540558 Change-Id: I6bc18ff672bc119c523841033fde4bbacb9290fd Depends-On: Ibc89fdbfbd0a36a890412cd8e861d35bcf930690
This commit is contained in:
		@@ -201,14 +201,35 @@ class EnvDeploy(EnvMixIn, base.BaseCommand):
 | 
			
		||||
 | 
			
		||||
        parser.add_argument('id',
 | 
			
		||||
                            type=int,
 | 
			
		||||
                            help='Id of the nailgun entity to be processed.')
 | 
			
		||||
                            help='Id of the environment to be deployed.')
 | 
			
		||||
 | 
			
		||||
        return parser
 | 
			
		||||
 | 
			
		||||
    def take_action(self, parsed_args):
 | 
			
		||||
        task_id = self.client.deploy_changes(parsed_args.id)
 | 
			
		||||
 | 
			
		||||
        msg = 'Deploy task with id {t} for the environment {e} '\
 | 
			
		||||
        msg = 'Deployment task with id {t} for the environment {e} '\
 | 
			
		||||
              'has been started.\n'.format(t=task_id, e=parsed_args.id)
 | 
			
		||||
 | 
			
		||||
        self.app.stdout.write(msg)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EnvRedeploy(EnvMixIn, base.BaseCommand):
 | 
			
		||||
    """Redeploys changes on the specified environment."""
 | 
			
		||||
 | 
			
		||||
    def get_parser(self, prog_name):
 | 
			
		||||
        parser = super(EnvRedeploy, self).get_parser(prog_name)
 | 
			
		||||
 | 
			
		||||
        parser.add_argument('id',
 | 
			
		||||
                            type=int,
 | 
			
		||||
                            help='Id of the environment to be redeployed.')
 | 
			
		||||
 | 
			
		||||
        return parser
 | 
			
		||||
 | 
			
		||||
    def take_action(self, parsed_args):
 | 
			
		||||
        task_id = self.client.redeploy_changes(parsed_args.id)
 | 
			
		||||
 | 
			
		||||
        msg = 'Deployment task with id {t} for the environment {e} '\
 | 
			
		||||
              'has been started.\n'.format(t=task_id, e=parsed_args.id)
 | 
			
		||||
 | 
			
		||||
        self.app.stdout.write(msg)
 | 
			
		||||
 
 | 
			
		||||
@@ -14,4 +14,21 @@
 | 
			
		||||
#    License for the specific language governing permissions and limitations
 | 
			
		||||
#    under the License.
 | 
			
		||||
 | 
			
		||||
from collections import namedtuple
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def Enum(*values, **kwargs):
 | 
			
		||||
    names = kwargs.get('names')
 | 
			
		||||
    if names:
 | 
			
		||||
        return namedtuple('Enum', names)(*values)
 | 
			
		||||
    return namedtuple('Enum', values)(*values)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
SERIALIZATION_FORMAT_FLAG = 'serialization_format'
 | 
			
		||||
 | 
			
		||||
TASK_STATUSES = Enum(
 | 
			
		||||
    'error',
 | 
			
		||||
    'pending',
 | 
			
		||||
    'ready',
 | 
			
		||||
    'running'
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -12,24 +12,27 @@
 | 
			
		||||
#    License for the specific language governing permissions and limitations
 | 
			
		||||
#    under the License.
 | 
			
		||||
 | 
			
		||||
import json
 | 
			
		||||
import logging
 | 
			
		||||
import os
 | 
			
		||||
import re
 | 
			
		||||
import shutil
 | 
			
		||||
import subprocess
 | 
			
		||||
import sys
 | 
			
		||||
import tempfile
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
from oslotest import base as oslo_base
 | 
			
		||||
 | 
			
		||||
from fuelclient import consts
 | 
			
		||||
from fuelclient.objects import Release
 | 
			
		||||
 | 
			
		||||
from oslotest import base as oslo_base
 | 
			
		||||
 | 
			
		||||
logging.basicConfig(stream=sys.stderr)
 | 
			
		||||
log = logging.getLogger("CliTest.ExecutionLog")
 | 
			
		||||
log.setLevel(logging.DEBUG)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CliExectutionResult(object):
 | 
			
		||||
class CliExecutionResult(object):
 | 
			
		||||
    def __init__(self, process_handle, out, err):
 | 
			
		||||
        self.return_code = process_handle.returncode
 | 
			
		||||
        self.stdout = out
 | 
			
		||||
@@ -45,6 +48,8 @@ class CliExectutionResult(object):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseTestCase(oslo_base.BaseTestCase):
 | 
			
		||||
 | 
			
		||||
    handler = ''
 | 
			
		||||
    nailgun_root = os.environ.get('NAILGUN_ROOT', '/tmp/fuel_web/nailgun')
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
@@ -91,7 +96,7 @@ class BaseTestCase(oslo_base.BaseTestCase):
 | 
			
		||||
    def run_cli_command(self, command_line,
 | 
			
		||||
                        check_errors=True, env=os.environ.copy()):
 | 
			
		||||
 | 
			
		||||
        command_args = [" ".join(('fuel', command_line))]
 | 
			
		||||
        command_args = [" ".join((self.handler, command_line))]
 | 
			
		||||
        process_handle = subprocess.Popen(
 | 
			
		||||
            command_args,
 | 
			
		||||
            stdout=subprocess.PIPE,
 | 
			
		||||
@@ -100,7 +105,7 @@ class BaseTestCase(oslo_base.BaseTestCase):
 | 
			
		||||
            env=env
 | 
			
		||||
        )
 | 
			
		||||
        out, err = process_handle.communicate()
 | 
			
		||||
        result = CliExectutionResult(process_handle, out, err)
 | 
			
		||||
        result = CliExecutionResult(process_handle, out, err)
 | 
			
		||||
        log.debug("command_args: '%s',stdout: '%s', stderr: '%s'",
 | 
			
		||||
                  command_args[0], out, err)
 | 
			
		||||
        if check_errors:
 | 
			
		||||
@@ -129,6 +134,12 @@ class BaseTestCase(oslo_base.BaseTestCase):
 | 
			
		||||
        call = self.run_cli_command(command, check_errors=check_errors)
 | 
			
		||||
        self.assertEqual(call.stdout, msg)
 | 
			
		||||
 | 
			
		||||
    def check_for_stdout_by_regexp(self, command, pattern, check_errors=True):
 | 
			
		||||
        call = self.run_cli_command(command, check_errors=check_errors)
 | 
			
		||||
        result = re.search(pattern, call.stdout)
 | 
			
		||||
        self.assertIsNotNone(result)
 | 
			
		||||
        return result
 | 
			
		||||
 | 
			
		||||
    def check_for_stderr(self, command, msg, check_errors=True):
 | 
			
		||||
        call = self.run_cli_command(command, check_errors=check_errors)
 | 
			
		||||
        self.assertIn(msg, call.stderr)
 | 
			
		||||
@@ -147,3 +158,59 @@ class BaseTestCase(oslo_base.BaseTestCase):
 | 
			
		||||
    def check_number_of_rows_in_table(self, command, number_of_rows):
 | 
			
		||||
        output = self.run_cli_command(command)
 | 
			
		||||
        self.assertEqual(len(output.stdout.split("\n")), number_of_rows + 3)
 | 
			
		||||
 | 
			
		||||
    def _get_task_info(self, task_id):
 | 
			
		||||
        """Get info about task with given ID.
 | 
			
		||||
 | 
			
		||||
        :param task_id: Task ID
 | 
			
		||||
        :type task_id: str or int
 | 
			
		||||
        :return: Task info
 | 
			
		||||
        :rtype: dict
 | 
			
		||||
        """
 | 
			
		||||
        return {}
 | 
			
		||||
 | 
			
		||||
    def wait_task_ready(self, task_id, timeout=60, interval=3):
 | 
			
		||||
        """Wait for changing task status to 'ready'.
 | 
			
		||||
 | 
			
		||||
        :param task_id: Task ID
 | 
			
		||||
        :type task_id: str or int
 | 
			
		||||
        :param timeout: Max time of waiting, in seconds
 | 
			
		||||
        :type timeout: int
 | 
			
		||||
        :param interval: Interval of getting task info, in seconds
 | 
			
		||||
        :type interval: int
 | 
			
		||||
        """
 | 
			
		||||
        wait_until_in_statuses = (consts.TASK_STATUSES.running,
 | 
			
		||||
                                  consts.TASK_STATUSES.pending)
 | 
			
		||||
        timer = time.time()
 | 
			
		||||
        while True:
 | 
			
		||||
            task = self._get_task_info(task_id)
 | 
			
		||||
            status = task.get('status', '')
 | 
			
		||||
            if status not in wait_until_in_statuses:
 | 
			
		||||
                self.assertEqual(status, consts.TASK_STATUSES.ready)
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
            if time.time() - timer > timeout:
 | 
			
		||||
                raise Exception(
 | 
			
		||||
                    "Task '{0}' seems to be hanged".format(task['name'])
 | 
			
		||||
                )
 | 
			
		||||
            time.sleep(interval)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CLIv1TestCase(BaseTestCase):
 | 
			
		||||
 | 
			
		||||
    handler = 'fuel'
 | 
			
		||||
 | 
			
		||||
    def _get_task_info(self, task_id):
 | 
			
		||||
        command = "task --task {0} --json".format(str(task_id))
 | 
			
		||||
        call = self.run_cli_command(command)
 | 
			
		||||
        return json.loads(call.stdout)[0]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CLIv2TestCase(BaseTestCase):
 | 
			
		||||
 | 
			
		||||
    handler = 'fuel2'
 | 
			
		||||
 | 
			
		||||
    def _get_task_info(self, task_id):
 | 
			
		||||
        command = "task show -f json {0}".format(str(task_id))
 | 
			
		||||
        call = self.run_cli_command(command)
 | 
			
		||||
        return json.loads(call.stdout)
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ import tempfile
 | 
			
		||||
from fuelclient.tests.functional import base
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestHandlers(base.BaseTestCase):
 | 
			
		||||
class TestHandlers(base.CLIv1TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_env_action(self):
 | 
			
		||||
        # check env help
 | 
			
		||||
@@ -289,7 +289,7 @@ class TestHandlers(base.BaseTestCase):
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestCharset(base.BaseTestCase):
 | 
			
		||||
class TestCharset(base.CLIv1TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_charset_problem(self):
 | 
			
		||||
        self.load_data_to_nailgun_server()
 | 
			
		||||
@@ -301,7 +301,7 @@ class TestCharset(base.BaseTestCase):
 | 
			
		||||
        ))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestFiles(base.BaseTestCase):
 | 
			
		||||
class TestFiles(base.CLIv1TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_file_creation(self):
 | 
			
		||||
        self.load_data_to_nailgun_server()
 | 
			
		||||
@@ -393,7 +393,7 @@ class TestFiles(base.BaseTestCase):
 | 
			
		||||
            ))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestDownloadUploadNodeAttributes(base.BaseTestCase):
 | 
			
		||||
class TestDownloadUploadNodeAttributes(base.CLIv1TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_upload_download_interfaces(self):
 | 
			
		||||
        self.load_data_to_nailgun_server()
 | 
			
		||||
@@ -415,35 +415,43 @@ class TestDownloadUploadNodeAttributes(base.BaseTestCase):
 | 
			
		||||
                              self.upload_command(cmd)))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestDeployChanges(base.BaseTestCase):
 | 
			
		||||
class TestDeployChanges(base.CLIv1TestCase):
 | 
			
		||||
 | 
			
		||||
    create_env = "env create --name=test --release={0}"
 | 
			
		||||
    add_node = "--env-id=1 node set --node 1 --role=controller"
 | 
			
		||||
    deploy_changes = "deploy-changes --env 1"
 | 
			
		||||
    redeploy_changes = "redeploy-changes --env 1"
 | 
			
		||||
    cmd_create_env = "env create --name=test --release={0}"
 | 
			
		||||
    cmd_add_node = "--env-id=1 node set --node 1 --role=controller"
 | 
			
		||||
    cmd_deploy_changes = "deploy-changes --env 1"
 | 
			
		||||
    cmd_redeploy_changes = "redeploy-changes --env 1"
 | 
			
		||||
 | 
			
		||||
    messages_success = [
 | 
			
		||||
        "Deploying changes to environment with id=1\n",
 | 
			
		||||
        "Finished deployment!\n"
 | 
			
		||||
    ]
 | 
			
		||||
    message_error = "(No changes to deploy)\n"
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(TestDeployChanges, self).setUp()
 | 
			
		||||
        self.load_data_to_nailgun_server()
 | 
			
		||||
        release_id = self.get_first_deployable_release_id()
 | 
			
		||||
        self.create_env = self.create_env.format(release_id)
 | 
			
		||||
        self.run_cli_commands((self.create_env, self.add_node))
 | 
			
		||||
        self.cmd_create_env = self.cmd_create_env.format(release_id)
 | 
			
		||||
        self.run_cli_commands((
 | 
			
		||||
            self.cmd_create_env,
 | 
			
		||||
            self.cmd_add_node
 | 
			
		||||
        ))
 | 
			
		||||
 | 
			
		||||
    def test_deploy_changes(self):
 | 
			
		||||
        self.run_cli_commands((self.deploy_changes,))
 | 
			
		||||
 | 
			
		||||
    def test_no_changes_to_deploy(self):
 | 
			
		||||
        self.run_cli_commands((self.deploy_changes,))
 | 
			
		||||
        self.check_for_stderr(self.deploy_changes,
 | 
			
		||||
                              "(No changes to deploy)\n",
 | 
			
		||||
                              check_errors=False)
 | 
			
		||||
        self.check_all_in_msg(self.cmd_deploy_changes,
 | 
			
		||||
                              self.messages_success)
 | 
			
		||||
 | 
			
		||||
    def test_redeploy_changes(self):
 | 
			
		||||
        self.run_cli_commands((self.deploy_changes,
 | 
			
		||||
                               self.redeploy_changes))
 | 
			
		||||
        self.run_cli_command(self.cmd_deploy_changes)
 | 
			
		||||
        self.check_for_stderr(self.cmd_deploy_changes,
 | 
			
		||||
                              self.message_error,
 | 
			
		||||
                              check_errors=False)
 | 
			
		||||
        self.check_all_in_msg(self.cmd_redeploy_changes,
 | 
			
		||||
                              self.messages_success)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestDirectoryDoesntExistErrorMessages(base.BaseTestCase):
 | 
			
		||||
class TestDirectoryDoesntExistErrorMessages(base.CLIv1TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_settings_upload(self):
 | 
			
		||||
        self.check_for_stderr(
 | 
			
		||||
@@ -520,7 +528,7 @@ class TestDirectoryDoesntExistErrorMessages(base.BaseTestCase):
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestUploadSettings(base.BaseTestCase):
 | 
			
		||||
class TestUploadSettings(base.CLIv1TestCase):
 | 
			
		||||
 | 
			
		||||
    create_env = "env create --name=test --release={0}"
 | 
			
		||||
    add_node = "--env-id=1 node set --node 1 --role=controller"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										56
									
								
								fuelclient/tests/functional/v2/test_client.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								fuelclient/tests/functional/v2/test_client.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,56 @@
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
#
 | 
			
		||||
#    Copyright 2013-2014 Mirantis, Inc.
 | 
			
		||||
#
 | 
			
		||||
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 | 
			
		||||
#    not use this file except in compliance with the License. You may obtain
 | 
			
		||||
#    a copy of the License at
 | 
			
		||||
#
 | 
			
		||||
#         http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
#
 | 
			
		||||
#    Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
#    License for the specific language governing permissions and limitations
 | 
			
		||||
#    under the License.
 | 
			
		||||
 | 
			
		||||
from fuelclient.tests.functional import base
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestDeployChanges(base.CLIv2TestCase):
 | 
			
		||||
 | 
			
		||||
    cmd_create_env = "env create -r {0} cluster-test"
 | 
			
		||||
    cmd_add_node = "env add nodes -e 1 -n 1 -r controller"
 | 
			
		||||
    cmd_deploy_changes = "env deploy 1"
 | 
			
		||||
    cmd_redeploy_changes = "env redeploy 1"
 | 
			
		||||
 | 
			
		||||
    pattern_success = (r"^Deployment task with id (\d{1,}) "
 | 
			
		||||
                       r"for the environment 1 has been started.\n$")
 | 
			
		||||
    message_error = "(No changes to deploy)\n"
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(TestDeployChanges, self).setUp()
 | 
			
		||||
        self.load_data_to_nailgun_server()
 | 
			
		||||
        release_id = self.get_first_deployable_release_id()
 | 
			
		||||
        self.cmd_create_env = self.cmd_create_env.format(release_id)
 | 
			
		||||
        self.run_cli_commands((
 | 
			
		||||
            self.cmd_create_env,
 | 
			
		||||
            self.cmd_add_node
 | 
			
		||||
        ))
 | 
			
		||||
 | 
			
		||||
    def test_deploy_changes(self):
 | 
			
		||||
        self.check_for_stdout_by_regexp(self.cmd_deploy_changes,
 | 
			
		||||
                                        self.pattern_success)
 | 
			
		||||
 | 
			
		||||
    def test_redeploy_changes(self):
 | 
			
		||||
        result = self.check_for_stdout_by_regexp(self.cmd_deploy_changes,
 | 
			
		||||
                                                 self.pattern_success)
 | 
			
		||||
        task_id = result.group(1)
 | 
			
		||||
        self.wait_task_ready(task_id)
 | 
			
		||||
 | 
			
		||||
        self.check_for_stderr(self.cmd_deploy_changes,
 | 
			
		||||
                              self.message_error,
 | 
			
		||||
                              check_errors=False)
 | 
			
		||||
 | 
			
		||||
        self.check_for_stdout_by_regexp(self.cmd_redeploy_changes,
 | 
			
		||||
                                        self.pattern_success)
 | 
			
		||||
@@ -95,6 +95,13 @@ class TestEnvCommand(test_engine.BaseCLITest):
 | 
			
		||||
        self.m_get_client.assert_called_once_with('environment', mock.ANY)
 | 
			
		||||
        self.m_client.deploy_changes.assert_called_once_with(42)
 | 
			
		||||
 | 
			
		||||
    def test_env_redeploy(self):
 | 
			
		||||
        args = 'env redeploy 42'
 | 
			
		||||
        self.exec_command(args)
 | 
			
		||||
 | 
			
		||||
        self.m_get_client.assert_called_once_with('environment', mock.ANY)
 | 
			
		||||
        self.m_client.redeploy_changes.assert_called_once_with(42)
 | 
			
		||||
 | 
			
		||||
    def test_env_add_nodes(self):
 | 
			
		||||
        args = 'env add nodes -e 42 -n 24 25 -r compute cinder'
 | 
			
		||||
        self.exec_command(args)
 | 
			
		||||
 
 | 
			
		||||
@@ -71,6 +71,12 @@ class EnvironmentClient(base_v1.BaseV1Client):
 | 
			
		||||
 | 
			
		||||
        return deploy_task.id
 | 
			
		||||
 | 
			
		||||
    def redeploy_changes(self, environment_id):
 | 
			
		||||
        env = self._entity_wrapper(obj_id=environment_id)
 | 
			
		||||
        redeploy_task = env.redeploy_changes()
 | 
			
		||||
 | 
			
		||||
        return redeploy_task.id
 | 
			
		||||
 | 
			
		||||
    def spawn_vms(self, environment_id):
 | 
			
		||||
        env = self._entity_wrapper(obj_id=environment_id)
 | 
			
		||||
        return env.spawn_vms()
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,7 @@ fuelclient =
 | 
			
		||||
    env_delete=fuelclient.commands.environment:EnvDelete
 | 
			
		||||
    env_deploy=fuelclient.commands.environment:EnvDeploy
 | 
			
		||||
    env_list=fuelclient.commands.environment:EnvList
 | 
			
		||||
    env_redeploy=fuelclient.commands.environment:EnvRedeploy
 | 
			
		||||
    env_show=fuelclient.commands.environment:EnvShow
 | 
			
		||||
    env_spawn-vms=fuelclient.commands.environment:EnvSpawnVms
 | 
			
		||||
    env_update=fuelclient.commands.environment:EnvUpdate
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								tox.ini
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								tox.ini
									
									
									
									
									
								
							@@ -16,7 +16,7 @@ setenv = VIRTUAL_ENV={envdir}
 | 
			
		||||
 | 
			
		||||
         # Functional env settings
 | 
			
		||||
         FUEL_WEB_CLONE={env:FUEL_WEB_CLONE:yes}
 | 
			
		||||
         FUEL_WEB_REPO={env:FUEL_WEB_REPO:https://github.com/stackforge/fuel-web.git}
 | 
			
		||||
         FUEL_WEB_REPO={env:FUEL_WEB_REPO:https://github.com/openstack/fuel-web.git}
 | 
			
		||||
         FUEL_WEB_ROOT={env:FUEL_WEB_ROOT:/tmp/fuel_web}
 | 
			
		||||
         FETCH_REPO={env:FETCH_REPO:}
 | 
			
		||||
         FETCH_REFSPEC={env:FETCH_REFSPEC:}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user