Implement watcher datamodel list in watcherclient
1. Add data_model.py and data_model_shell.py for accept and process request. 2. Add relative unittest. Partically Implements: blueprint show-datamodel-api Change-Id: I5e080453acaedf7e20734d67922b64511dd5f7fd
This commit is contained in:
@@ -67,6 +67,8 @@ openstack.infra_optim.v1 =
|
||||
optimize_service_show = watcherclient.v1.service_shell:ShowService
|
||||
optimize_service_list = watcherclient.v1.service_shell:ListService
|
||||
|
||||
optimize_datamodel_list = watcherclient.v1.data_model_shell:ListDataModel
|
||||
|
||||
# The same as above but used by the 'watcher' command
|
||||
watcherclient.v1 =
|
||||
goal_show = watcherclient.v1.goal_shell:ShowGoal
|
||||
@@ -104,6 +106,8 @@ watcherclient.v1 =
|
||||
service_show = watcherclient.v1.service_shell:ShowService
|
||||
service_list = watcherclient.v1.service_shell:ListService
|
||||
|
||||
datamodel_list = watcherclient.v1.data_model_shell:ListDataModel
|
||||
|
||||
[pbr]
|
||||
autodoc_index_modules = True
|
||||
autodoc_exclude_modules =
|
||||
|
75
watcherclient/tests/unit/v1/test_data_model.py
Normal file
75
watcherclient/tests/unit/v1/test_data_model.py
Normal file
@@ -0,0 +1,75 @@
|
||||
# Copyright 2019 ZTE corporation.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 testtools
|
||||
|
||||
from watcherclient.tests.unit import utils
|
||||
import watcherclient.v1.data_model
|
||||
|
||||
DATA_MODEL = {
|
||||
'context': [{
|
||||
"server_uuid": "1bf91464-9b41-428d-a11e-af691e5563bb",
|
||||
"server_name": "fake-name",
|
||||
"server_state": "active",
|
||||
"node_uuid": "253e5dd0-9384-41ab-af13-4f2c2ce26112",
|
||||
"node_hostname": "localhost.localdomain",
|
||||
}]
|
||||
}
|
||||
|
||||
AUDIT = "81332bfc-36f8-444d-99e2-b7285d602528"
|
||||
|
||||
fake_responses = {
|
||||
'/v1/data_model/?data_model_type=compute':
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
DATA_MODEL,
|
||||
),
|
||||
},
|
||||
'/v1/data_model/?audit_uuid=%s&data_model_type=compute' % AUDIT:
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
DATA_MODEL,
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class DataModelManagerTest(testtools.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(DataModelManagerTest, self).setUp()
|
||||
self.api = utils.FakeAPI(fake_responses)
|
||||
self.mgr = watcherclient.v1.data_model.DataModelManager(self.api)
|
||||
|
||||
def test_data_model_list(self):
|
||||
data_model = self.mgr.list()
|
||||
expect = [
|
||||
('GET', '/v1/data_model/?data_model_type=compute', {}, None),
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertEqual(1, len(data_model.context))
|
||||
|
||||
def test_data_model_list_audit(self):
|
||||
data_model = self.mgr.list(
|
||||
audit='%s' % AUDIT)
|
||||
expect = [
|
||||
('GET', '/v1/data_model/?'
|
||||
'audit_uuid=81332bfc-36f8-444d-99e2-b7285d602528'
|
||||
'&data_model_type=compute',
|
||||
{}, None),
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertEqual(1, len(data_model.context))
|
129
watcherclient/tests/unit/v1/test_data_model_shell.py
Normal file
129
watcherclient/tests/unit/v1/test_data_model_shell.py
Normal file
@@ -0,0 +1,129 @@
|
||||
# Copyright 2019 ZTE Corporation.
|
||||
#
|
||||
# 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 mock
|
||||
import six
|
||||
|
||||
from watcherclient import shell
|
||||
from watcherclient.tests.unit.v1 import base
|
||||
from watcherclient import v1 as resource
|
||||
from watcherclient.v1 import resource_fields
|
||||
|
||||
|
||||
DATA_MODEL = {
|
||||
'context': [{
|
||||
"server_uuid": "1bf91464-9b41-428d-a11e-af691e5563bb",
|
||||
"server_name": "fake-name",
|
||||
"server_state": "active",
|
||||
"server_vcpus": "1",
|
||||
"server_memory": "512",
|
||||
"server_disk": "1",
|
||||
"node_uuid": "253e5dd0-9384-41ab-af13-4f2c2ce26112",
|
||||
"node_hostname": "localhost.localdomain",
|
||||
"node_vcpus": "4",
|
||||
"node_vcpu_ratio": "16.0",
|
||||
"node_memory": "16383",
|
||||
"node_memory_ratio": "1.5",
|
||||
"node_disk": "37",
|
||||
"node_disk_ratio": "1.0",
|
||||
"node_state": "up",
|
||||
}]
|
||||
}
|
||||
|
||||
LIST_RESULT = [{
|
||||
"Server UUID": "1bf91464-9b41-428d-a11e-af691e5563bb",
|
||||
"Server Name": "fake-name",
|
||||
"Server Vcpus": "1",
|
||||
"Server Memory": "512",
|
||||
"Server Disk": "1",
|
||||
"Server State": "active",
|
||||
"Node UUID": "253e5dd0-9384-41ab-af13-4f2c2ce26112",
|
||||
"Node Host Name": "localhost.localdomain",
|
||||
"Node Vcpus": "4",
|
||||
"Node Vcpu Ratio": "16.0",
|
||||
"Node Memory": "16383",
|
||||
"Node Memory Ratio": "1.5",
|
||||
"Node Disk": "37",
|
||||
"Node Disk Ratio": "1.0",
|
||||
"Node State": "up",
|
||||
}]
|
||||
|
||||
SHORT_LIST_RESULT = [{
|
||||
"Server UUID": "1bf91464-9b41-428d-a11e-af691e5563bb",
|
||||
"Server Name": "fake-name",
|
||||
"Server State": "active",
|
||||
"Node UUID": "253e5dd0-9384-41ab-af13-4f2c2ce26112",
|
||||
"Node Host Name": "localhost.localdomain",
|
||||
}]
|
||||
|
||||
|
||||
class DataModelShellTest(base.CommandTestCase):
|
||||
|
||||
SHORT_LIST_FIELDS = resource_fields.COMPUTE_MODEL_SHORT_LIST_FIELDS
|
||||
SHORT_LIST_FIELD_LABELS = (
|
||||
resource_fields.COMPUTE_MODEL_SHORT_LIST_FIELD_LABELS)
|
||||
FIELDS = resource_fields.COMPUTE_MODEL_LIST_FIELDS
|
||||
FIELD_LABELS = resource_fields.COMPUTE_MODEL_LIST_FIELD_LABELS
|
||||
|
||||
def setUp(self):
|
||||
super(self.__class__, self).setUp()
|
||||
|
||||
p_data_model_manager = mock.patch.object(
|
||||
resource, 'DataModelManager')
|
||||
|
||||
self.m_data_model_mgr_cls = p_data_model_manager.start()
|
||||
|
||||
self.addCleanup(p_data_model_manager.stop)
|
||||
|
||||
self.m_data_model_mgr = mock.Mock()
|
||||
|
||||
self.m_data_model_mgr_cls.return_value = self.m_data_model_mgr
|
||||
|
||||
self.stdout = six.StringIO()
|
||||
self.cmd = shell.WatcherShell(stdout=self.stdout)
|
||||
|
||||
def test_do_data_model_list(self):
|
||||
data_model = resource.DataModel(mock.Mock(), DATA_MODEL)
|
||||
self.m_data_model_mgr.list.return_value = data_model
|
||||
|
||||
exit_code, results = self.run_cmd('datamodel list')
|
||||
|
||||
self.assertEqual(0, exit_code)
|
||||
expect_values = sorted(SHORT_LIST_RESULT[0].values())
|
||||
result_values = sorted(results[0].values())
|
||||
self.assertEqual(expect_values, result_values)
|
||||
|
||||
def test_do_data_model_list_detail(self):
|
||||
data_model = resource.DataModel(mock.Mock(), DATA_MODEL)
|
||||
self.m_data_model_mgr.list.return_value = data_model
|
||||
|
||||
exit_code, results = self.run_cmd('datamodel list --detail')
|
||||
|
||||
self.assertEqual(0, exit_code)
|
||||
expect_values = sorted(LIST_RESULT[0].values())
|
||||
result_values = sorted(results[0].values())
|
||||
self.assertEqual(expect_values, result_values)
|
||||
|
||||
def test_do_data_model_list_filter_by_audit(self):
|
||||
data_model = resource.DataModel(mock.Mock(), DATA_MODEL)
|
||||
self.m_data_model_mgr.list.return_value = data_model
|
||||
|
||||
exit_code, results = self.run_cmd(
|
||||
'datamodel list --audit '
|
||||
'770ef053-ecb3-48b0-85b5-d55a2dbc6588')
|
||||
|
||||
self.assertEqual(0, exit_code)
|
||||
expect_values = sorted(SHORT_LIST_RESULT[0].values())
|
||||
result_values = sorted(results[0].values())
|
||||
self.assertEqual(expect_values, result_values)
|
@@ -17,6 +17,7 @@ from watcherclient.v1 import action
|
||||
from watcherclient.v1 import action_plan
|
||||
from watcherclient.v1 import audit
|
||||
from watcherclient.v1 import audit_template
|
||||
from watcherclient.v1 import data_model
|
||||
from watcherclient.v1 import goal
|
||||
from watcherclient.v1 import scoring_engine
|
||||
from watcherclient.v1 import service
|
||||
@@ -38,9 +39,12 @@ Service = service.Service
|
||||
ServiceManager = service.ServiceManager
|
||||
Strategy = strategy.Strategy
|
||||
StrategyManager = strategy.StrategyManager
|
||||
DataModel = data_model.DataModel
|
||||
DataModelManager = data_model.DataModelManager
|
||||
|
||||
__all__ = (
|
||||
"Action", "ActionManager", "ActionPlan", "ActionPlanManager",
|
||||
"Audit", "AuditManager", "AuditTemplate", "AuditTemplateManager",
|
||||
"Goal", "GoalManager", "ScoringEngine", "ScoringEngineManager",
|
||||
"Service", "ServiceManager", "Strategy", "StrategyManager")
|
||||
"Service", "ServiceManager", "Strategy", "StrategyManager",
|
||||
"DataModel", "DataModelManager")
|
||||
|
@@ -56,3 +56,4 @@ class Client(object):
|
||||
self.scoring_engine = v1.ScoringEngineManager(self.http_client)
|
||||
self.service = v1.ServiceManager(self.http_client)
|
||||
self.strategy = v1.StrategyManager(self.http_client)
|
||||
self.data_model = v1.DataModelManager(self.http_client)
|
||||
|
56
watcherclient/v1/data_model.py
Normal file
56
watcherclient/v1/data_model.py
Normal file
@@ -0,0 +1,56 @@
|
||||
# Copyright 2019 ZTE Corporation.
|
||||
#
|
||||
# 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 watcherclient.common import base
|
||||
from watcherclient.common import utils
|
||||
|
||||
|
||||
class DataModel(base.Resource):
|
||||
def __repr__(self):
|
||||
return "<DataModel %s>" % self._info
|
||||
|
||||
|
||||
class DataModelManager(base.Manager):
|
||||
resource_class = DataModel
|
||||
|
||||
@staticmethod
|
||||
def _path(filters=None):
|
||||
if filters:
|
||||
path = '/v1/data_model/%s' % filters
|
||||
else:
|
||||
path = '/v1/data_model'
|
||||
return path
|
||||
|
||||
def list(self, data_model_type='compute', audit=None):
|
||||
"""Retrieve a list of data model.
|
||||
|
||||
:param data_model_type: The type of data model user wants to list.
|
||||
Supported values: compute.
|
||||
Future support values: storage, baremetal.
|
||||
The default value is compute.
|
||||
:param audit: The UUID of the audit, used to filter data model
|
||||
by the scope in audit.
|
||||
|
||||
:returns: A list of data model.
|
||||
|
||||
"""
|
||||
path = ''
|
||||
filters = utils.common_filters()
|
||||
|
||||
if audit:
|
||||
filters.append('audit_uuid=%s' % audit)
|
||||
filters.append('data_model_type=%s' % data_model_type)
|
||||
|
||||
path += '?' + '&'.join(filters)
|
||||
|
||||
return self._list(self._path(path))[0]
|
77
watcherclient/v1/data_model_shell.py
Normal file
77
watcherclient/v1/data_model_shell.py
Normal file
@@ -0,0 +1,77 @@
|
||||
# Copyright 2019 ZTE Corporation.
|
||||
#
|
||||
# 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 watcherclient._i18n import _
|
||||
from watcherclient.common import command
|
||||
from watcherclient import exceptions
|
||||
from watcherclient.v1 import resource_fields as res_fields
|
||||
|
||||
|
||||
class ListDataModel(command.Lister):
|
||||
"""List information on retrieved data model."""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListDataModel, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'--type',
|
||||
metavar='<type>',
|
||||
dest='type',
|
||||
help=_('Type of Datamodel user want to list. '
|
||||
'Supported values: compute. '
|
||||
'Future support values: storage, baremetal. '
|
||||
'Default type is compute.'))
|
||||
parser.add_argument(
|
||||
'--audit',
|
||||
metavar='<audit>',
|
||||
dest='audit',
|
||||
help=_('UUID of the audit'))
|
||||
parser.add_argument(
|
||||
'--detail',
|
||||
dest='detail',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=_("Show detailed information about data model."))
|
||||
return parser
|
||||
|
||||
def get_tuple(self, dic, fields):
|
||||
ret_tup = []
|
||||
for item in fields:
|
||||
ret_tup.append(dic.get(item))
|
||||
return tuple(ret_tup)
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = getattr(self.app.client_manager, "infra-optim")
|
||||
allowed_type = ['compute', 'storage', 'baremetal']
|
||||
params = {}
|
||||
if parsed_args.audit:
|
||||
params["audit"] = parsed_args.audit
|
||||
if parsed_args.type:
|
||||
if parsed_args.type not in allowed_type:
|
||||
raise exceptions.CommandError(
|
||||
'Type %s error, '
|
||||
'Please check the valid type!' % parsed_args.type)
|
||||
params["data_model_type"] = parsed_args.type
|
||||
try:
|
||||
data_model = client.data_model.list(**params)
|
||||
except exceptions.HTTPNotFound as exc:
|
||||
raise exceptions.CommandError(str(exc))
|
||||
# TODO(chenker) Add Storage MODEL_FIELDS when using Storage Datamodel.
|
||||
if parsed_args.detail:
|
||||
fields = res_fields.COMPUTE_MODEL_LIST_FIELDS
|
||||
field_labels = res_fields.COMPUTE_MODEL_LIST_FIELD_LABELS
|
||||
else:
|
||||
fields = res_fields.COMPUTE_MODEL_SHORT_LIST_FIELDS
|
||||
field_labels = res_fields.COMPUTE_MODEL_SHORT_LIST_FIELD_LABELS
|
||||
return (field_labels,
|
||||
(self.get_tuple(item, fields) for item in data_model.context))
|
@@ -98,6 +98,28 @@ STRATEGY_FIELDS = ['uuid', 'name', 'display_name', 'goal_name',
|
||||
STRATEGY_FIELD_LABELS = ['UUID', 'Name', 'Display name', 'Goal',
|
||||
'Parameters spec']
|
||||
|
||||
# Data Model
|
||||
|
||||
COMPUTE_MODEL_LIST_FIELDS = [
|
||||
'server_uuid', 'server_name', 'server_vcpus',
|
||||
'server_memory', 'server_disk', 'server_state', 'node_uuid',
|
||||
'node_hostname', 'node_vcpus', 'node_vcpu_ratio', 'node_memory',
|
||||
'node_memory_ratio', 'node_disk', 'node_disk_ratio', 'node_state']
|
||||
|
||||
COMPUTE_MODEL_LIST_FIELD_LABELS = [
|
||||
'Server_UUID', 'Server Name', 'Server Vcpus',
|
||||
'Server Memory', 'Server Disk', 'Server State', 'Node UUID',
|
||||
'Node Host Name', 'Node Vcpus', 'Node Vcpu Ratio', 'Node Memory',
|
||||
'Node Memory Ratio', 'Node Disk', 'Node Disk Ratio', 'Node State']
|
||||
|
||||
COMPUTE_MODEL_SHORT_LIST_FIELDS = [
|
||||
'server_uuid', 'server_name',
|
||||
'server_state', 'node_uuid', 'node_hostname']
|
||||
|
||||
COMPUTE_MODEL_SHORT_LIST_FIELD_LABELS = [
|
||||
'Server UUID', 'Server Name',
|
||||
'Server State', 'Node UUID', 'Node Host Name']
|
||||
|
||||
STRATEGY_SHORT_LIST_FIELDS = ['uuid', 'name', 'display_name', 'goal_name']
|
||||
|
||||
STRATEGY_SHORT_LIST_FIELD_LABELS = ['UUID', 'Name', 'Display name', 'Goal']
|
||||
|
Reference in New Issue
Block a user