Compare commits

...

27 Commits

Author SHA1 Message Date
OpenDev Sysadmins
1a9bbf244b OpenDev Migration Patch
This commit was bulk generated and pushed by the OpenDev sysadmins
as a part of the Git hosting and code review systems migration
detailed in these mailing list posts:

http://lists.openstack.org/pipermail/openstack-discuss/2019-March/003603.html
http://lists.openstack.org/pipermail/openstack-discuss/2019-April/004920.html

Attempts have been made to correct repository namespaces and
hostnames based on simple pattern matching, but it's possible some
were updated incorrectly or missed entirely. Please reach out to us
via the contact information listed at https://opendev.org/ with any
questions you may have.
2019-04-19 19:45:01 +00:00
Nguyen Hai
da805f8983 import zuul job settings from project-config
This is a mechanically generated patch to complete step 1 of moving
the zuul job settings out of project-config and into each project
repository.

Because there will be a separate patch on each branch, the branch
specifiers for branch-specific jobs have been removed.

Because this patch is generated by a script, there may be some
cosmetic changes to the layout of the YAML file(s) as the contents are
normalized.

See the python3-first goal document for details:
https://governance.openstack.org/tc/goals/stein/python3-first.html

Change-Id: I3a81add983bcd1accdfdd6915f689b5f37946402
Story: #2002586
Task: #24344
2018-08-19 00:59:03 +09:00
2142c8e51d Update UPPER_CONSTRAINTS_FILE for stable/queens
Change-Id: I7c170cc9ac357e5b9f6b3fd2bf4af3f4d9d8932c
2018-01-26 10:45:00 +00:00
ed55462a72 Update .gitreview for stable/queens
Change-Id: Ie4c4d3e3a6fd220c189811bd82801e8c598df410
2018-01-26 10:44:55 +00:00
Zuul
a1b6eed54c Merge "Add strategy state command" 2018-01-25 20:34:01 +00:00
Alexander Chadin
a907c2d0cd Add strategy state command
This patch set adds command "strategy state"
that allows to request strategy requirements to run.

Partially-Implements: blueprint check-strategy-requirements
Change-Id: I327cc4f5a887f62af700bd646576caa036faaf75
2018-01-24 14:55:01 +00:00
Zuul
d38bb255ed Merge "Updated from global requirements" 2018-01-24 14:03:31 +00:00
Zuul
30e2aad126 Merge "Audit Template Help Message" 2018-01-24 12:37:57 +00:00
OpenStack Proposal Bot
bc0fb4f051 Updated from global requirements
Change-Id: I420d547482d84c9cf8e39e2e2069c46f6d86e993
2018-01-24 01:34:14 +00:00
Zuul
ef533eb151 Merge "Updated from global requirements" 2018-01-22 11:24:34 +00:00
OpenStack Proposal Bot
3c160af376 Updated from global requirements
Change-Id: I65f25febf490e24d2bea4182890400191ce3a16a
I08b68c15c3906885ce3ca6fb410d227c3e585978
2018-01-19 13:50:22 +00:00
OpenStack Proposal Bot
186029ac87 Updated from global requirements
Change-Id: I08b68c15c3906885ce3ca6fb410d227c3e585978
I65f25febf490e24d2bea4182890400191ce3a16a
2018-01-19 12:01:23 +00:00
aditi
b9112a1199 Audit Template Help Message
This patch updates help message of "watcher audittemplate create"
It updates help about storage scoper.

Change-Id: I46be98c2819c2dfb2a7ef3fe1aa98caa90ececfd
Implements: blueprint audit-scoper-for-storage-data-model
2018-01-19 11:16:44 +00:00
Alexander Chadin
9d301fa14a Fix test_action_plan functional tests
Change-Id: Ie5b5bd330c68b696dce48e2475baf77a81f2e8c4
Closes-Bug: #1744262
2018-01-19 13:36:19 +03:00
Zuul
15d7d78b8b Merge "Fix watcher actionplan list command" 2018-01-05 09:25:24 +00:00
OpenStack Proposal Bot
81b84bcff5 Updated from global requirements
Change-Id: I8dcbe4616e7618c783097baecd62f67ef6501e30
2017-12-21 00:47:51 +00:00
Alexander Chadin
79880c2dff Fix watcher actionplan list command
This patch set replaces itervalues() method with values()
to get py3.* compatibility.

Closes-Bug: #1738772
Change-Id: Ie13d15d6f407b08ba087168ac647669c0df2c30a
2017-12-18 15:45:33 +03:00
Zuul
32259fe287 Merge "Fix unnecessary retries during conflict" 2017-12-13 14:24:13 +00:00
Zuul
d36ba79e77 Merge "marker when retrive audit" 2017-12-13 11:43:17 +00:00
Zuul
4f5487b5e1 Merge "Update audit_template create help message" 2017-12-13 10:06:17 +00:00
Zuul
7bf192a981 Merge "marker when retrive action" 2017-12-13 08:36:22 +00:00
Zuul
f8b341c0f3 Merge "marker when retrive audit template" 2017-12-13 05:39:09 +00:00
Yumeng Bao
1a6703266f Update audit_template create help message
'id' should be an integer, not string.
Closes-Bug: #1734056
Change-Id: I4275127e7f76ba6ad05f478278204c3de535cf5c
2017-11-28 10:04:16 +08:00
suzhengwei
fada471714 marker when retrive audit
Change-Id: I72078850152e0ccf2abc0d35b06a5142df35c312
2017-11-27 06:56:01 +00:00
suzhengwei
1cd8c38d95 marker when retrive action
Change-Id: Ic733c3e79a31c7cd99226e6e49dfbbc8c3b58902
2017-11-27 06:54:42 +00:00
suzhengwei
0257aa9116 marker when retrive audit template
Change-Id: Ia2cd0598770359c2727ec569dd7f2531f7b5f40a
2017-11-22 13:34:18 +00:00
aditi
5378102cd6 Fix unnecessary retries during conflict
This patch removes retries from python-watcherclient in case
watcher-api responded with conflict case.

Change-Id: I830abe0a3cd67484e165a0a42d5a57b75ed4dac6
Closes-Bug: #1725088
2017-10-20 02:27:13 +00:00
27 changed files with 353 additions and 37 deletions

View File

@@ -1,4 +1,5 @@
[gerrit]
host=review.openstack.org
host=review.opendev.org
port=29418
project=openstack/python-watcherclient.git
defaultbranch=stable/queens

View File

@@ -1,8 +1,17 @@
- project:
templates:
- openstack-python-jobs
- openstack-python35-jobs
- publish-openstack-sphinx-docs
- check-requirements
- openstackclient-plugin-jobs
name: openstack/python-watcherclient
check:
jobs:
- watcherclient-tempest-functional
- openstack-tox-cover:
voting: false
gate:
jobs:
- watcherclient-tempest-functional

View File

@@ -4,9 +4,9 @@
Babel!=2.4.0,>=2.3.4 # BSD
cliff!=2.9.0,>=2.8.0 # Apache-2.0
osc-lib>=1.7.0 # Apache-2.0
osc-lib>=1.8.0 # Apache-2.0
oslo.i18n>=3.15.3 # Apache-2.0
oslo.utils>=3.31.0 # Apache-2.0
oslo.utils>=3.33.0 # Apache-2.0
pbr!=2.1.0,>=2.0.0 # Apache-2.0
PrettyTable<0.8,>=0.7.1 # BSD
keystoneauth1>=3.3.0 # Apache-2.0

View File

@@ -36,6 +36,7 @@ openstack.infra_optim.v1 =
optimize_strategy_show = watcherclient.v1.strategy_shell:ShowStrategy
optimize_strategy_list = watcherclient.v1.strategy_shell:ListStrategy
optimize_strategy_state = watcherclient.v1.strategy_shell:StateStrategy
optimize_audittemplate_show = watcherclient.v1.audit_template_shell:ShowAuditTemplate
optimize_audittemplate_list = watcherclient.v1.audit_template_shell:ListAuditTemplate
@@ -72,6 +73,7 @@ watcherclient.v1 =
strategy_show = watcherclient.v1.strategy_shell:ShowStrategy
strategy_list = watcherclient.v1.strategy_shell:ListStrategy
strategy_state = watcherclient.v1.strategy_shell:StateStrategy
audittemplate_show = watcherclient.v1.audit_template_shell:ShowAuditTemplate
audittemplate_list = watcherclient.v1.audit_template_shell:ListAuditTemplate

View File

@@ -6,10 +6,10 @@ coverage!=4.4,>=4.0 # Apache-2.0
fixtures>=3.0.0 # Apache-2.0/BSD
hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
mock>=2.0.0 # BSD
openstackdocstheme>=1.17.0 # Apache-2.0
oslotest>=1.10.0 # Apache-2.0
openstackdocstheme>=1.18.1 # Apache-2.0
oslotest>=3.2.0 # Apache-2.0
python-subunit>=1.0.0 # Apache-2.0/BSD
sphinx>=1.6.2 # BSD
sphinx!=1.6.6,>=1.6.2 # BSD
testrepository>=0.0.18 # Apache-2.0/BSD
testscenarios>=0.4 # Apache-2.0/BSD
testtools>=2.2.0 # MIT

View File

@@ -6,7 +6,7 @@ skipsdist = True
[testenv]
usedevelop = True
install_command =
constraints: pip install -U --force-reinstall -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
constraints: pip install -U --force-reinstall -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt?h=stable/queens} {opts} {packages}
pip install -U {opts} {packages}
setenv =
VIRTUAL_ENV={envdir}

View File

@@ -165,8 +165,7 @@ class VersionNegotiationMixin(object):
raise NotImplementedError()
_RETRY_EXCEPTIONS = (exceptions.Conflict,
exceptions.ServiceUnavailable,
_RETRY_EXCEPTIONS = (exceptions.ServiceUnavailable,
exceptions.ConnectionRefused,
kexceptions.RetriableConnectionFailure)

View File

@@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import time
from oslo_utils import uuidutils
from watcherclient.tests.functional.v1 import base
@@ -44,6 +46,15 @@ class ActionPlanTests(base.TestCase):
output = cls.parse_show(
cls.watcher('actionplan list --audit %s' % cls.audit_uuid))
action_plan_uuid = output[0].keys()[0]
retry = 10
while retry > 0:
output = cls.parse_show(
cls.watcher('actionplan show %s' % action_plan_uuid))
state = [x for x in output if x.keys()[0] == 'State'][0]['State']
if state == 'SUCCEEDED':
break
time.sleep(1)
retry -= 1
raw_output = cls.watcher('actionplan delete %s' % action_plan_uuid)
cls.assertOutput('', raw_output)
# Delete audit

View File

@@ -20,7 +20,9 @@ class StrategyTests(base.TestCase):
"""Functional tests for strategy."""
dummy_name = 'dummy'
basic_strategy = 'basic'
list_fields = ['UUID', 'Name', 'Display name', 'Goal']
state_fields = ['Datasource', 'Metrics', 'CDM', 'Name']
def test_strategy_list(self):
raw_output = self.watcher('strategy list')
@@ -39,3 +41,8 @@ class StrategyTests(base.TestCase):
self.assert_table_structure([raw_output],
self.list_fields + ['Parameters spec'])
self.assertNotIn('basic', raw_output)
def test_strategy_state(self):
raw_output = self.watcher('strategy state %s' % self.basic_strategy)
self.assertIn(self.basic_strategy, raw_output)
self.assert_table_structure([raw_output], self.state_fields)

View File

@@ -144,6 +144,16 @@ fake_responses_sorting = {
},
}
fake_responses_marker = {
'/v1/actions/?marker=770ef053-ecb3-48b0-85b5-d55a2dbc6588':
{
'GET': (
{},
{"actions": [ACTION2, ACTION3]}
),
},
}
class ActionManagerTest(testtools.TestCase):
@@ -231,6 +241,20 @@ class ActionManagerTest(testtools.TestCase):
self.assertEqual(expect, self.api.calls)
self.assertEqual(3, len(actions))
def test_actions_list_marker(self):
self.api = utils.FakeAPI(fake_responses_marker)
self.mgr = watcherclient.v1.action.ActionManager(self.api)
actions = self.mgr.list(
marker='770ef053-ecb3-48b0-85b5-d55a2dbc6588')
expect = [
('GET',
'/v1/actions/?marker=770ef053-ecb3-48b0-85b5-d55a2dbc6588',
{},
None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(actions))
def test_actions_show(self):
action = self.mgr.get(ACTION1['uuid'])
expect = [

21
watcherclient/tests/unit/v1/test_action_shell.py Executable file → Normal file
View File

@@ -132,6 +132,27 @@ class ActionShellTest(base.CommandTestCase):
self.m_action_mgr.list.assert_called_once_with(detail=True)
def test_do_action_list_marker(self):
action2 = resource.Action(mock.Mock(), ACTION_2)
action3 = resource.Action(mock.Mock(), ACTION_3)
self.m_action_mgr.list.return_value = [
action2, action3]
exit_code, results = self.run_cmd(
'action list --marker 770ef053-ecb3-48b0-85b5-d55a2dbc6588')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(action2, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS),
self.resource_as_dict(action3, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_action_mgr.list.assert_called_once_with(
detail=False,
marker='770ef053-ecb3-48b0-85b5-d55a2dbc6588')
def test_do_action_show_by_uuid(self):
action = resource.Action(mock.Mock(), ACTION_1)
self.m_action_mgr.get.return_value = action

View File

@@ -145,6 +145,16 @@ fake_responses_strategy = {
},
}
fake_responses_marker = {
'/v1/audits/?marker=5869da81-4876-4687-a1ed-12cd64cf53d9':
{
'GET': (
{},
{"audits": [AUDIT2]}
),
},
}
class AuditManagerTest(testtools.TestCase):
def setUp(self):
@@ -229,6 +239,17 @@ class AuditManagerTest(testtools.TestCase):
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(audits))
def test_audits_list_marker(self):
self.api = utils.FakeAPI(fake_responses_marker)
self.mgr = watcherclient.v1.audit.AuditManager(self.api)
audits = self.mgr.list(marker=AUDIT1['uuid'])
expect = [
('GET', '/v1/audits/?marker=5869da81-4876-4687-a1ed-12cd64cf53d9',
{}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(audits))
def test_audits_show(self):
audit = self.mgr.get(AUDIT1['uuid'])
expect = [

View File

@@ -172,6 +172,23 @@ class AuditShellTest(base.CommandTestCase):
self.m_audit_mgr.list.assert_called_once_with(detail=False)
def test_do_audit_list_marker(self):
audit2 = resource.Audit(mock.Mock(), AUDIT_2)
self.m_audit_mgr.list.return_value = [audit2]
exit_code, results = self.run_cmd(
'audit list --marker 5869da81-4876-4687-a1ed-12cd64cf53d9')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(audit2, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_audit_mgr.list.assert_called_once_with(
detail=False,
marker='5869da81-4876-4687-a1ed-12cd64cf53d9')
def test_do_audit_list_detail(self):
audit1 = resource.Audit(mock.Mock(), AUDIT_1)
audit2 = resource.Audit(mock.Mock(), AUDIT_2)

View File

@@ -178,6 +178,16 @@ fake_responses_sorting = {
},
}
fake_responses_marker = {
'/v1/audit_templates/?marker=f8e47706-efcf-49a4-a5c4-af604eb492f2':
{
'GET': (
{},
{"audit_templates": [AUDIT_TMPL2, AUDIT_TMPL3]}
),
},
}
fake_responses_filter_by_goal_uuid = {
'/v1/audit_templates/?goal=e75ee410-b32b-465f-88b5-4397705f9473':
{
@@ -389,6 +399,18 @@ class AuditTemplateManagerTest(utils.BaseTestCase):
self.assertEqual(expect, self.api.calls)
self.assertEqual(3, len(audit_templates))
def test_audit_templates_list_marker(self):
self.api = utils.FakeAPI(fake_responses_marker)
self.mgr = watcherclient.v1.audit_template.AuditTemplateManager(
self.api)
audit_templates = self.mgr.list(marker=AUDIT_TMPL1['uuid'])
expect_url = '/v1/audit_templates/?marker=%s' % AUDIT_TMPL1['uuid']
expect = [
('GET', expect_url, {}, None)
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(2, len(audit_templates))
def test_audit_templates_show(self):
audit_template = self.mgr.get(AUDIT_TMPL1['uuid'])
expect = [

View File

@@ -128,6 +128,24 @@ class AuditTemplateShellTest(base.CommandTestCase):
self.m_audit_template_mgr.list.assert_called_once_with(detail=False)
def test_do_audit_template_list_marker(self):
audit_template2 = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_2)
self.m_audit_template_mgr.list.return_value = [audit_template2]
exit_code, results = self.run_cmd(
'audittemplate list --marker '
'f8e47706-efcf-49a4-a5c4-af604eb492f2')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(audit_template2, self.SHORT_LIST_FIELDS,
self.SHORT_LIST_FIELD_LABELS)],
results)
self.m_audit_template_mgr.list.assert_called_once_with(
detail=False,
marker='f8e47706-efcf-49a4-a5c4-af604eb492f2')
def test_do_audit_template_list_detail(self):
audit_template1 = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_1)
audit_template2 = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_2)

View File

@@ -63,6 +63,13 @@ fake_responses = {
STRATEGY1,
),
},
'/v1/strategies/%s/state' % STRATEGY1['name']:
{
'GET': (
{},
STRATEGY1,
),
},
}
fake_responses_pagination = {
@@ -180,3 +187,10 @@ class StrategyManagerTest(testtools.TestCase):
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(STRATEGY1['name'], strategy.name)
def test_strategies_state(self):
self.mgr.state(STRATEGY1['name'])
expect = [
('GET', '/v1/strategies/%s/state' % STRATEGY1['name'], {}, None),
]
self.assertEqual(expect, self.api.calls)

View File

@@ -17,6 +17,8 @@ import datetime
import mock
import six
from oslo_serialization import jsonutils
from watcherclient import shell
from watcherclient.tests.unit.v1 import base
from watcherclient import v1 as resource
@@ -54,6 +56,8 @@ class StrategyShellTest(base.CommandTestCase):
resource_fields.STRATEGY_SHORT_LIST_FIELD_LABELS)
FIELDS = resource_fields.STRATEGY_FIELDS
FIELD_LABELS = resource_fields.STRATEGY_FIELD_LABELS
STATE_FIELDS = resource_fields.STRATEGY_STATE_FIELDS
STATE_FIELD_LABELS = resource_fields.STRATEGY_STATE_FIELD_LABELS
def setUp(self):
super(self.__class__, self).setUp()
@@ -155,3 +159,33 @@ class StrategyShellTest(base.CommandTestCase):
result)
self.m_strategy_mgr.get.assert_called_once_with(
'f8e47706-efcf-49a4-a5c4-af604eb492f2')
def test_do_strategy_state(self):
strategy1 = resource.Strategy(mock.Mock(), STRATEGY_1)
strategy_req = [
{'type': 'Datasource', 'mandatory': True,
'comment': '', 'state': 'gnocchi: True'},
{'type': 'Metrics', 'mandatory': False,
'comment': '', 'state': jsonutils.dumps([
{'compute.node.cpu.percent': 'available'},
{'cpu_util': 'available'},
{'memory.resident': 'available'},
{'hardware.memory.used': 'not available'}])},
{'type': 'CDM', 'mandatory': True,
'comment': '',
'state': jsonutils.dumps([{'compute_model': 'available'},
{'storage_model': 'not available'}])},
{'type': 'Name', 'mandatory': '', 'comment': '',
'state': strategy1.name}]
requirements = [resource.Strategy(mock.Mock(), req)
for req in strategy_req]
self.m_strategy_mgr.state.return_value = requirements
exit_code, results = self.run_cmd('strategy state basic')
self.assertEqual(0, exit_code)
self.assertEqual(
[self.resource_as_dict(req, self.STATE_FIELDS,
self.STATE_FIELD_LABELS)
for req in requirements],
results)

View File

@@ -30,7 +30,7 @@ class ActionManager(base.Manager):
return '/v1/actions/%s' % id if id else '/v1/actions'
def list(self, action_plan=None, audit=None, limit=None, sort_key=None,
sort_dir=None, detail=False):
sort_dir=None, detail=False, marker=None):
"""Retrieve a list of action.
:param action_plan: UUID of the action plan
@@ -52,13 +52,15 @@ class ActionManager(base.Manager):
:param detail: Optional, boolean whether to return detailed information
about actions.
:param marker: Optional, UUID of the last action in the previous page.
:returns: A list of actions.
"""
if limit is not None:
limit = int(limit)
filters = utils.common_filters(limit, sort_key, sort_dir)
filters = utils.common_filters(limit, sort_key, sort_dir, marker)
if action_plan is not None:
filters.append('action_plan_uuid=%s' % action_plan)
if audit is not None:

View File

@@ -162,7 +162,7 @@ class ListActionPlan(command.Lister):
yaml_format.YAMLFormatter().emit_one(
column_names=list(resource.capitalize()
for resource in formatted_global_efficacy),
data=[value for value in formatted_global_efficacy.itervalues()],
data=[value for value in formatted_global_efficacy.values()],
stdout=out,
parsed_args=parsed_args,
)

View File

@@ -83,6 +83,13 @@ class ListAction(command.Lister):
metavar='<direction>',
choices=['asc', 'desc'],
help=_('Sort direction: "asc" (the default) or "desc".'))
parser.add_argument(
'--marker',
dest='marker',
metavar='<marker>',
default=None,
help=_('UUID of the last action in the previous page; '
'displays list of actions after "marker".'))
return parser

View File

@@ -36,7 +36,8 @@ class AuditManager(base.Manager):
return '/v1/audits/%s' % id if id else '/v1/audits'
def list(self, audit_template=None, limit=None, sort_key=None,
sort_dir=None, detail=False, goal=None, strategy=None):
sort_dir=None, detail=False, goal=None, strategy=None,
marker=None):
"""Retrieve a list of audit.
:param audit_template: Name of the audit template
@@ -57,13 +58,15 @@ class AuditManager(base.Manager):
:param detail: Optional, boolean whether to return detailed information
about audits.
:param marker: Optional, UUID of the last audit in the previous page.
:returns: A list of audits.
"""
if limit is not None:
limit = int(limit)
filters = utils.common_filters(limit, sort_key, sort_dir)
filters = utils.common_filters(limit, sort_key, sort_dir, marker)
if audit_template is not None:
filters.append('audit_template=%s' % audit_template)
if goal is not None:

View File

@@ -88,6 +88,13 @@ class ListAudit(command.Lister):
metavar='<direction>',
choices=['asc', 'desc'],
help=_('Sort direction: "asc" (the default) or "desc".'))
parser.add_argument(
'--marker',
dest='marker',
metavar='<marker>',
default=None,
help=_('UUID of the last audit in the previous page; '
'displays list of audits after "marker".'))
return parser

View File

@@ -33,7 +33,7 @@ class AuditTemplateManager(base.Manager):
return '/v1/audit_templates/%s' % id_ if id_ else '/v1/audit_templates'
def list(self, name=None, goal=None, strategy=None, limit=None,
sort_key=None, sort_dir=None, detail=False):
sort_key=None, sort_dir=None, detail=False, marker=None):
"""Retrieve a list of audit template.
:param name: Name of the audit template
@@ -54,13 +54,16 @@ class AuditTemplateManager(base.Manager):
:param detail: Optional, boolean whether to return detailed information
about audit_templates.
:param marker: Optional, UUID of the last audit template of
the previous page.
:returns: A list of audit templates.
"""
if limit is not None:
limit = int(limit)
filters = utils.common_filters(limit, sort_key, sort_dir)
filters = utils.common_filters(limit, sort_key, sort_dir, marker)
if name is not None:
filters.append('name=%s' % name)
if goal is not None:

View File

@@ -91,6 +91,13 @@ class ListAuditTemplate(command.Lister):
metavar='<direction>',
choices=['asc', 'desc'],
help=_('Sort direction: "asc" (the default) or "desc".'))
parser.add_argument(
'--marker',
dest='marker',
metavar='<marker>',
default=None,
help=_('UUID of the last audit template of the previous page; '
'displays list of audit templates after "marker".'))
return parser
@@ -176,26 +183,67 @@ class CreateAuditTemplate(command.ShowOne):
" - uuid: UUID2\n"
" - compute_nodes:\n"
" - name: compute1\n"
" - storage: \n"
" - availability_zones:\n"
" - name: AZ1\n"
" - name: AZ2\n"
" - volume_types:\n"
" - name: lvm1\n"
" - name: lvm2\n"
" - exclude:\n"
" - storage_pools:\n"
" - name: host0@backend0#pool0\n"
" - name: host1@backend1#pool1\n"
" - volumes:\n"
" - uuid: UUID1\n"
" - uuid: UUID2\n"
" - projects:\n"
" - uuid: UUID1\n"
" - uuid: UUID2\n"
"\n"
"JSON example:\n"
"[{\"compute\":\n"
" [{\"host_aggregates\": [\n"
" {\"id\": \"1\"},\n"
" {\"id\": \"2\"},\n"
" {\"id\": \"3\"}]},\n"
" {\"availability_zones\": [\n"
" {\"name\": \"AZ1\"},\n"
" {\"name\": \"AZ2\"}]},\n"
" {\"exclude\": [\n"
" {\"instances\": [\n"
" {\"uuid\": \"UUID1\"},\n"
" {\"uuid\": \"UUID2\"}\n"
" ]},\n"
" {\"compute_nodes\": [\n"
" {\"name\": \"compute1\"}\n"
" ]}\n"
" ]}]\n"
"}]\n"
"[\n"
" {\"compute\":\n"
" [{\"host_aggregates\": [\n"
" {\"id\": 1},\n"
" {\"id\": 2},\n"
" {\"id\": 3}]},\n"
" {\"availability_zones\": [\n"
" {\"name\": \"AZ1\"},\n"
" {\"name\": \"AZ2\"}]},\n"
" {\"exclude\": [\n"
" {\"instances\": [\n"
" {\"uuid\": \"UUID1\"},\n"
" {\"uuid\": \"UUID2\"}\n"
" ]},\n"
" {\"compute_nodes\": [\n"
" {\"name\": \"compute1\"}\n"
" ]}\n"
" ]}]\n"
" },\n"
" {\"storage\":\n"
" [{\"availability_zones\": [\n"
" {\"name\": \"AZ1\"},\n"
" {\"name\": \"AZ2\"}]},\n"
" {\"volume_types\": [\n"
" {\"name\": \"lvm1\"},\n"
" {\"name\": \"lvm2\"}]},\n"
" {\"exclude\": [\n"
" {\"storage_pools\": [\n"
" {\"name\": \"host0@backend0#pool0\"},\n"
" {\"name\": \"host1@backend1#pool1\"}\n"
" ]},\n"
" {\"volumes\": [\n"
" {\"uuid\": \"UUID1\"},\n"
" {\"uuid\": \"UUID2\"}\n"
" ]},\n"
" {\"projects\": [\n"
" {\"uuid\": \"UUID1\"},\n"
" {\"uuid\": \"UUID2\"}\n"
" ]},\n"
" ]}]\n"
" }\n"
" ]\n"
)
)

View File

@@ -99,6 +99,10 @@ STRATEGY_SHORT_LIST_FIELDS = ['uuid', 'name', 'display_name', 'goal_name']
STRATEGY_SHORT_LIST_FIELD_LABELS = ['UUID', 'Name', 'Display name', 'Goal']
STRATEGY_STATE_FIELDS = ['type', 'state', 'mandatory', 'comment']
STRATEGY_STATE_FIELD_LABELS = ['Type', 'State', 'Mandatory', 'Comment']
# Metric Collector
METRIC_COLLECTOR_FIELDS = ['uuid', 'created_at', 'updated_at', 'deleted_at',
'endpoint', 'category']

View File

@@ -28,9 +28,14 @@ class StrategyManager(base.Manager):
resource_class = Strategy
@staticmethod
def _path(strategy=None):
return ('/v1/strategies/%s' % strategy
if strategy else '/v1/strategies')
def _path(strategy=None, state=False):
if strategy:
path = '/v1/strategies/%s' % strategy
if state:
path = '/v1/strategies/%s/state' % strategy
else:
path = '/v1/strategies'
return path
def list(self, goal=None, limit=None, sort_key=None,
sort_dir=None, detail=False):
@@ -82,3 +87,6 @@ class StrategyManager(base.Manager):
return self._list(self._path(strategy))[0]
except IndexError:
return None
def state(self, strategy):
return self._list(self._path(strategy, state=True))

View File

@@ -57,6 +57,40 @@ class ShowStrategy(command.ShowOne):
return column_headers, utils.get_item_properties(strategy, columns)
class StateStrategy(command.Lister):
"""Retrieve information about strategy requirements."""
def get_parser(self, prog_name):
parser = super(StateStrategy, self).get_parser(prog_name)
parser.add_argument(
'strategy',
metavar='<strategy>',
help=_('Name of the strategy'),
)
return parser
def _format_spec(self, requirements):
for req in requirements:
if type(req.state) == list:
req.state = jsonutils.dumps(req.state, indent=2)
return requirements
def take_action(self, parsed_args):
client = getattr(self.app.client_manager, "infra-optim")
try:
requirements = client.strategy.state(parsed_args.strategy)
except exceptions.HTTPNotFound as exc:
raise exceptions.CommandError(str(exc))
requirements = self._format_spec(requirements)
columns = res_fields.STRATEGY_STATE_FIELDS
column_headers = res_fields.STRATEGY_STATE_FIELD_LABELS
return (column_headers,
(utils.get_item_properties(item, columns)
for item in requirements))
class ListStrategy(command.Lister):
"""List information on retrieved strategies."""