Add support for info actions for task

fuel2 task deployment-info download 1 --file deployment-info.yaml
  fuel2 task settings download 1 --file settings.yaml
  fuel2 task network-configuration download 1 --file networks.yaml

Closes-Bug: #1566462
DocImpact
Change-Id: If6fdeaf68c5dd4d8b3330e63f02205d425ae5021
(cherry picked from commit 3b1e95e235)
This commit is contained in:
Vladimir Sharshov (warpc)
2016-03-29 15:38:47 +03:00
committed by Vladimir Sharshov
parent a2388bc910
commit a4000b98db
12 changed files with 464 additions and 1 deletions

View File

@@ -48,10 +48,13 @@ def get_client(resource, version='v1'):
version_map = {
'v1': {
'cluster-settings': v1.cluster_settings,
'deployment_history': v1.deployment_history,
'deployment-info': v1.deployment_info,
'environment': v1.environment,
'fuel-version': v1.fuelversion,
'graph': v1.graph,
'network-configuration': v1.network_configuration,
'network-group': v1.network_group,
'node': v1.node,
'openstack-config': v1.openstack_config,

View File

@@ -12,6 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
import os
from fuelclient.cli.serializers import Serializer
from fuelclient.commands import base
from fuelclient.common import data_utils
@@ -19,6 +22,97 @@ from fuelclient.common import data_utils
class TaskMixIn(object):
entity_name = 'task'
@staticmethod
def add_file_arg(parser):
parser.add_argument(
'-f',
'--file',
required=False,
type=str,
help='YAML file that contains network configuration.'
)
@classmethod
def write_info_to_file(cls, info_type, data, transaction_id,
serializer=None, file_path=None):
"""Write additional info to the given path.
:param info_type: deployment_info | cluster_settings |
network_configuration
:type info_type: str
:param data: data
:type data: list of dict
:param serializer: serializer
:param transaction_id: Transaction ID
:type transaction_id: str or int
:param file_path: path
:type file_path: str
:return: path to resulting file
:rtype: str
"""
return (serializer or Serializer()).write_to_path(
(file_path or cls.get_default_info_path(info_type,
transaction_id)),
data)
@staticmethod
def get_default_info_path(info_type, transaction_id):
"""Generate default path for task additional info e.g. deployment info
:param info_type: deployment_info | cluster_settings |
network_configuration
:type info_type: str
:param transaction_id: Transaction ID
:type transaction_id: str or int
:return: path
:rtype: str
"""
return os.path.join(
os.path.abspath(os.curdir),
"{info_type}_{transaction_id}".format(
info_type=info_type,
transaction_id=transaction_id)
)
def download_info_to_file(self, transaction_id, info_type, file_path):
"""Get and save to path for task additional info e.g. deployment info
:param transaction_id: Transaction ID
:type transaction_id: str or int
:param info_type: deployment_info | cluster_settings |
network_configuration
:type info_type: str
:param file_path: path
:type file_path: str
:return: path
:rtype: str
"""
data = self.client.download(transaction_id=transaction_id)
data_file_path = TaskMixIn.write_info_to_file(
info_type,
data,
transaction_id,
file_path)
return data_file_path
class TaskInfoFileMixIn(TaskMixIn):
def get_parser(self, prog_name):
parser = super(TaskInfoFileMixIn, self).get_parser(
prog_name)
parser.add_argument('id', type=int, help='Id of the Task.')
self.add_file_arg(parser)
return parser
def download_info(self, parsed_args):
data_file_path = self.download_info_to_file(
transaction_id=parsed_args.id,
info_type=self.info_type,
file_path=parsed_args.file)
return data_file_path
class TaskList(TaskMixIn, base.BaseListCommand):
"""Show list of all available tasks."""
@@ -85,3 +179,42 @@ class TaskHistoryShow(TaskMixIn, base.BaseListCommand):
data = data_utils.get_display_data_multi(self.columns, data)
return (self.columns, data)
class TaskNetworkConfigurationDownload(TaskInfoFileMixIn, base.BaseCommand):
entity_name = 'network-configuration'
info_type = 'network_configuration'
def take_action(self, parsed_args):
self.app.stdout.write(
"Network configuration for task with id={0}"
" downloaded to {1}\n".format(parsed_args.id,
self.download_info(parsed_args))
)
class TaskDeploymentInfoDownload(TaskInfoFileMixIn, base.BaseCommand):
entity_name = 'deployment-info'
info_type = 'deployment_info'
def take_action(self, parsed_args):
self.app.stdout.write(
"Deployment info for task with id={0}"
" downloaded to {1}\n".format(parsed_args.id,
self.download_info(parsed_args))
)
class TaskClusterSettingsDownload(TaskInfoFileMixIn, base.BaseCommand):
entity_name = 'cluster-settings'
info_type = 'cluster_settings'
def take_action(self, parsed_args):
self.app.stdout.write(
"Cluster settings for task with id={0}"
" downloaded to {1}\n".format(parsed_args.id,
self.download_info(parsed_args))
)

View File

@@ -23,6 +23,10 @@ class Task(BaseObject):
class_api_path = "transactions/"
instance_api_path = "transactions/{0}/"
info_types_url_map = {
'deployment_info': 'deployment_info',
'cluster_settings': 'settings',
'network_configuration': 'network_configuration'}
def delete(self, force=False):
return self.connection.delete_request(
@@ -47,6 +51,31 @@ class Task(BaseObject):
while not self.is_finished:
sleep(0.5)
def deployment_info(self):
return self.connection.get_request(
self._get_additional_info_url('deployment_info'))
def network_configuration(self):
return self.connection.get_request(
self._get_additional_info_url('network_configuration'))
def cluster_settings(self):
return self.connection.get_request(
self._get_additional_info_url('cluster_settings'))
def _get_additional_info_url(self, info_type):
"""Generate additional info url.
:param info_type: one of deployment_info, cluster_settings,
network_configuration
:type info_type: str
:return: url
:rtype: str
"""
return self.instance_api_path.format(self.id) +\
self.info_types_url_map[info_type]
class DeployTask(Task):

View File

@@ -15,6 +15,7 @@
# under the License.
import mock
import yaml
from fuelclient.tests.unit.v2.cli import test_engine
from fuelclient.tests import utils
@@ -58,3 +59,41 @@ class TestTaskCommand(test_engine.BaseCLITest):
self.m_client.get_all.assert_called_once_with(transaction_id=task_id,
nodes=None,
statuses=None)
def _test_cmd(self, cmd, method, cmd_line, client,
return_data, expected_kwargs):
self.m_get_client.reset_mock()
self.m_client.get_filtered.reset_mock()
self.m_client.__getattr__(method).return_value =\
yaml.safe_load(return_data)
m_open = mock.mock_open()
with mock.patch('fuelclient.cli.serializers.open',
m_open, create=True):
self.exec_command('task {0} {1} {2}'.format(cmd, method,
cmd_line))
written_yaml = yaml.safe_load(m_open().write.mock_calls[0][1][0])
expected_yaml = yaml.safe_load(return_data)
self.assertEqual(written_yaml, expected_yaml)
self.m_get_client.assert_called_once_with(client, mock.ANY)
self.m_client.__getattr__(method).assert_called_once_with(
**expected_kwargs)
def test_task_deployment_info_download(self):
self._test_cmd('deployment-info', 'download', '1',
'deployment-info',
utils.get_fake_yaml_deployment_info(),
dict(transaction_id=1))
def test_task_cluster_settings_download(self):
self._test_cmd('settings', 'download', '1',
'cluster-settings',
utils.get_fake_yaml_cluster_settings(),
dict(transaction_id=1))
def test_task_network_configuration_download(self):
self._test_cmd('network-configuration', 'download', '1',
'network-configuration',
utils.get_fake_yaml_network_conf(),
dict(transaction_id=1))

View File

@@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
#
# Copyright 2016 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.
import yaml
import fuelclient
from fuelclient.tests.unit.v2.lib import test_api
from fuelclient.tests import utils
class TestTaskAdditionalInfoFacade(test_api.BaseLibTest):
def setUp(self):
super(TestTaskAdditionalInfoFacade, self).setUp()
self.version = 'v1'
self.task_id = 42
self.res_uri = (
'/api/{version}/transactions/{task_id}/'.format(
version=self.version, task_id=self.task_id))
def _test_info_download(self, client_name, yaml_data, uri):
client = fuelclient.get_client(client_name, self.version)
expected_body = yaml.load(yaml_data)
matcher = self.m_request.get("{0}{1}".format(self.res_uri, uri),
json=expected_body)
result = client.download(self.task_id)
self.assertTrue(matcher.called)
self.assertEqual(expected_body, result)
def test_network_configuration_download(self):
self._test_info_download('network-configuration',
utils.get_fake_yaml_network_conf(),
'network_configuration')
def test_cluster_settings_download(self):
self._test_info_download('cluster-settings',
utils.get_fake_yaml_cluster_settings(),
'settings')
def test_deployment_info_download(self):
self._test_info_download('deployment-info',
utils.get_fake_yaml_deployment_info(),
'deployment_info')

View File

@@ -15,6 +15,12 @@
# under the License.
from fuelclient.tests.utils.random_data import random_string
from fuelclient.tests.utils.fake_additional_info \
import get_fake_yaml_cluster_settings
from fuelclient.tests.utils.fake_additional_info \
import get_fake_yaml_deployment_info
from fuelclient.tests.utils.fake_additional_info \
import get_fake_yaml_network_conf
from fuelclient.tests.utils.fake_deployment_history \
import get_fake_deployment_history
from fuelclient.tests.utils.fake_net_conf import get_fake_interface_config
@@ -31,6 +37,9 @@ from fuelclient.tests.utils.fake_openstack_config \
__all__ = (get_fake_deployment_history,
get_fake_yaml_cluster_settings,
get_fake_yaml_deployment_info,
get_fake_yaml_network_conf,
get_fake_env,
get_fake_fuel_version,
get_fake_interface_config,

View File

@@ -0,0 +1,90 @@
# -*- coding: utf-8 -*-
#
# Copyright 2016 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.
CLUSTER_SETTINGS = '''---
editable:
service_user:
name:
type: "hidden"
value: "fuel"
sudo:
type: "hidden"
value: "ALL=(ALL) NOPASSWD: ALL"
homedir:
type: "hidden"
value: "/var/lib/fuel"
'''
DEPLOYMENT_INFO = '''---
glance_glare:
user_password: yBw0bY60owLC1C0AplHpEiEX
user_node_name: Untitled (5e:89)
uid: '5'
aodh:
db_password: JnEjYacrjxU2TLdTUQE9LdKq
user_password: 8MhyQgtWjWkl0Dv1r1worTjK
mysql:
root_password: bQhzpWjWIOTHOwEA4qNI8X4K
wsrep_password: 01QSoq3bYHgA7oS0OPYQurgX
murano-cfapi:
db_password: hGrAhxUjv3kAPEjiV7uYNwgZ
user_password: 43x0pvQMXugwd8JBaRSQXX4l
enabled: false
rabbit_password: ZqTnnw7lsGQNOFJRN6pTaI8t
'''
NETWORK_CONF = '''---
vips:
vrouter_pub:
network_role: "public/vip"
ipaddr: "10.109.3.2"
namespace: "vrouter"
is_user_defined: false
vendor_specific:
iptables_rules:
ns_start:
- "iptables -t nat -A POSTROUTING -o <%INT%> -j MASQUERADE"
'''
def get_fake_yaml_cluster_settings():
"""Create a fake cluster settings
Returns the serialized and parametrized representation of a dumped Fuel
Cluster Settings. Represents the average amount of data.
"""
return CLUSTER_SETTINGS
def get_fake_yaml_deployment_info():
"""Create a fake cluster settings
Returns the serialized and parametrized representation of a dumped Fuel
Deployment Info. Represents the average amount of data.
"""
return DEPLOYMENT_INFO
def get_fake_yaml_network_conf():
"""Create a fake cluster settings
Returns the serialized and parametrized representation of a dumped Fuel
Network Conf. Represents the average amount of data.
"""
return NETWORK_CONF

View File

@@ -12,10 +12,13 @@
# License for the specific language governing permissions and limitations
# under the License.
from fuelclient.v1 import cluster_settings
from fuelclient.v1 import deployment_history
from fuelclient.v1 import deployment_info
from fuelclient.v1 import environment
from fuelclient.v1 import fuelversion
from fuelclient.v1 import graph
from fuelclient.v1 import network_configuration
from fuelclient.v1 import network_group
from fuelclient.v1 import node
from fuelclient.v1 import openstack_config
@@ -24,10 +27,13 @@ from fuelclient.v1 import task
from fuelclient.v1 import vip
# Please keeps the list in alphabetical order
__all__ = ('deployment_history',
__all__ = ('cluster_settings',
'deployment_history',
'deployment_info',
'environment',
'fuelversion',
'graph',
'network_configuration',
'network_group',
'node',
'openstack_config',

View File

@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright 2016 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 import objects
from fuelclient.v1 import base_v1
class ClusterSettingsClient(base_v1.BaseV1Client):
_entity_wrapper = objects.Task
def download(self, transaction_id):
task = self._entity_wrapper(transaction_id)
return task.cluster_settings()
def get_client():
return ClusterSettingsClient()

View File

@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright 2016 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 import objects
from fuelclient.v1 import base_v1
class DeploymentInfoClient(base_v1.BaseV1Client):
_entity_wrapper = objects.Task
def download(self, transaction_id):
task = self._entity_wrapper(transaction_id)
return task.deployment_info()
def get_client():
return DeploymentInfoClient()

View File

@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright 2016 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 import objects
from fuelclient.v1 import base_v1
class NetworkConfigurationClient(base_v1.BaseV1Client):
_entity_wrapper = objects.Task
def download(self, transaction_id):
task = self._entity_wrapper(transaction_id)
return task.network_configuration()
def get_client():
return NetworkConfigurationClient()

View File

@@ -66,6 +66,9 @@ fuelclient =
task_list=fuelclient.commands.task:TaskList
task_show=fuelclient.commands.task:TaskShow
task_history_show=fuelclient.commands.task:TaskHistoryShow
task_settings_download=fuelclient.commands.task:TaskClusterSettingsDownload
task_deployment-info_download=fuelclient.commands.task:TaskDeploymentInfoDownload
task_network-configuration_download=fuelclient.commands.task:TaskNetworkConfigurationDownload
openstack-config_list=fuelclient.commands.openstack_config:OpenstackConfigList
openstack-config_upload=fuelclient.commands.openstack_config:OpenstackConfigUpload
openstack-config_download=fuelclient.commands.openstack_config:OpenstackConfigDownload