Add support for Audit Scope
This patch set adds audit scope support in python-watcherclient. Change-Id: I2a94320bec0fd7051a38bee1c872148e39f69d0c Partially-Implements: blueprint define-the-audit-scope
This commit is contained in:
parent
11056302b4
commit
c185f32ebb
@ -11,3 +11,4 @@ pbr>=1.6 # Apache-2.0
|
||||
PrettyTable<0.8,>=0.7.1 # BSD
|
||||
python-keystoneclient!=2.1.0,>=2.0.0 # Apache-2.0
|
||||
six>=1.9.0 # MIT
|
||||
PyYAML>=3.10.0 # MIT
|
||||
|
@ -43,4 +43,8 @@ class Lister(Command, lister.Lister):
|
||||
|
||||
|
||||
class ShowOne(Command, show.ShowOne):
|
||||
pass
|
||||
def get_parser(self, prog_name, formatter_class=None):
|
||||
parser = super(ShowOne, self).get_parser(prog_name)
|
||||
if formatter_class:
|
||||
parser.formatter_class = formatter_class
|
||||
return parser
|
||||
|
@ -19,7 +19,9 @@ from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import uuid
|
||||
import yaml
|
||||
|
||||
from oslo_utils import importutils
|
||||
|
||||
@ -192,3 +194,10 @@ def is_uuid_like(val):
|
||||
return str(uuid.UUID(val)) == val
|
||||
except (TypeError, ValueError, AttributeError):
|
||||
return False
|
||||
|
||||
|
||||
def serialize_file_to_dict(filename):
|
||||
filename = os.path.expanduser(filename)
|
||||
with open(filename, "rb") as stream:
|
||||
scope = yaml.safe_load(stream.read())
|
||||
return scope
|
||||
|
@ -29,7 +29,6 @@ AUDIT_TEMPLATE_1 = {
|
||||
'uuid': 'f8e47706-efcf-49a4-a5c4-af604eb492f2',
|
||||
'name': 'at1',
|
||||
'description': 'Audit Template 1 description',
|
||||
'host_aggregate': 5,
|
||||
'extra': {'automatic': False},
|
||||
'goal_uuid': 'fc087747-61be-4aad-8126-b701731ae836',
|
||||
'strategy_uuid': '2cf86250-d309-4b81-818e-1537f3dba6e5',
|
||||
@ -64,7 +63,6 @@ AUDIT_1 = {
|
||||
'state': 'PENDING',
|
||||
'audit_template_uuid': 'f8e47706-efcf-49a4-a5c4-af604eb492f2',
|
||||
'audit_template_name': 'at1',
|
||||
'host_aggregate': 5,
|
||||
'goal_name': 'SERVER_CONSOLIDATION',
|
||||
'strategy_name': 'basic',
|
||||
'created_at': datetime.datetime.now().isoformat(),
|
||||
@ -72,6 +70,7 @@ AUDIT_1 = {
|
||||
'deleted_at': None,
|
||||
'parameters': None,
|
||||
'interval': None,
|
||||
'scope': '',
|
||||
}
|
||||
|
||||
AUDIT_2 = {
|
||||
@ -81,7 +80,6 @@ AUDIT_2 = {
|
||||
'state': 'PENDING',
|
||||
'audit_template_uuid': 'f8e47706-efcf-49a4-a5c4-af604eb492f2',
|
||||
'audit_template_name': 'at1',
|
||||
'host_aggregate': None,
|
||||
'goal_name': 'fc087747-61be-4aad-8126-b701731ae836',
|
||||
'strategy_name': None,
|
||||
'created_at': datetime.datetime.now().isoformat(),
|
||||
@ -89,6 +87,7 @@ AUDIT_2 = {
|
||||
'deleted_at': None,
|
||||
'parameters': None,
|
||||
'interval': None,
|
||||
'scope': '',
|
||||
}
|
||||
|
||||
AUDIT_3 = {
|
||||
@ -98,7 +97,6 @@ AUDIT_3 = {
|
||||
'state': 'PENDING',
|
||||
'audit_template_uuid': 'f8e47706-efcf-49a4-a5c4-af604eb492f2',
|
||||
'audit_template_name': 'at1',
|
||||
'host_aggregate': 3,
|
||||
'goal_name': None,
|
||||
'strategy_name': None,
|
||||
'created_at': datetime.datetime.now().isoformat(),
|
||||
@ -106,6 +104,7 @@ AUDIT_3 = {
|
||||
'deleted_at': None,
|
||||
'parameters': None,
|
||||
'interval': 3600,
|
||||
'scope': '',
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,7 +28,6 @@ AUDIT_TMPL1 = {
|
||||
'uuid': 'f8e47706-efcf-49a4-a5c4-af604eb492f2',
|
||||
'name': 'Audit Template 1',
|
||||
'description': 'Audit Template 1 description',
|
||||
'host_aggregate': 5,
|
||||
'extra': {'automatic': False},
|
||||
'goal_uuid': '7568667b-51fe-4087-9eb1-29b26891036f',
|
||||
'goal_name': 'SERVER_CONSOLIDATION',
|
||||
@ -41,7 +40,6 @@ AUDIT_TMPL2 = {
|
||||
'uuid': 'a5199d0e-0702-4613-9234-5ae2af8dafea',
|
||||
'name': 'Audit Template 2',
|
||||
'description': 'Audit Template 2 description',
|
||||
'host_aggregate': 8,
|
||||
'extra': {'automatic': True},
|
||||
'goal_uuid': 'e75ee410-b32b-465f-88b5-4397705f9473',
|
||||
'goal_name': 'DUMMY',
|
||||
@ -54,7 +52,6 @@ AUDIT_TMPL3 = {
|
||||
'uuid': '770ef053-ecb3-48b0-85b5-d55a2dbc6588',
|
||||
'name': 'Audit Template 3',
|
||||
'description': 'Audit Template 3 description',
|
||||
'host_aggregate': 7,
|
||||
'extra': {'automatic': True},
|
||||
'goal_uuid': '7568667b-51fe-4087-9eb1-29b26891036f',
|
||||
'goal_name': 'SERVER_CONSOLIDATION',
|
||||
@ -407,8 +404,6 @@ class AuditTemplateManagerTest(utils.BaseTestCase):
|
||||
self.assertEqual(AUDIT_TMPL1['name'], audit_template.name)
|
||||
self.assertEqual(AUDIT_TMPL1['description'],
|
||||
audit_template.description)
|
||||
self.assertEqual(AUDIT_TMPL1['host_aggregate'],
|
||||
audit_template.host_aggregate)
|
||||
self.assertEqual(AUDIT_TMPL1['goal_uuid'], audit_template.goal_uuid)
|
||||
self.assertEqual(AUDIT_TMPL1['strategy_uuid'],
|
||||
audit_template.strategy_uuid)
|
||||
@ -427,8 +422,6 @@ class AuditTemplateManagerTest(utils.BaseTestCase):
|
||||
self.assertEqual(AUDIT_TMPL1['name'], audit_template.name)
|
||||
self.assertEqual(AUDIT_TMPL1['description'],
|
||||
audit_template.description)
|
||||
self.assertEqual(AUDIT_TMPL1['host_aggregate'],
|
||||
audit_template.host_aggregate)
|
||||
self.assertEqual(AUDIT_TMPL1['goal_uuid'], audit_template.goal_uuid)
|
||||
self.assertEqual(AUDIT_TMPL1['strategy_uuid'],
|
||||
audit_template.strategy_uuid)
|
||||
|
@ -47,7 +47,6 @@ AUDIT_TEMPLATE_1 = {
|
||||
'uuid': 'f8e47706-efcf-49a4-a5c4-af604eb492f2',
|
||||
'name': 'at1',
|
||||
'description': 'Audit Template 1 description',
|
||||
'host_aggregate': 5,
|
||||
'extra': {'automatic': False},
|
||||
'goal_uuid': 'fc087747-61be-4aad-8126-b701731ae836',
|
||||
'goal_name': 'SERVER_CONSOLIDATION',
|
||||
@ -56,13 +55,13 @@ AUDIT_TEMPLATE_1 = {
|
||||
'created_at': datetime.datetime.now().isoformat(),
|
||||
'updated_at': None,
|
||||
'deleted_at': None,
|
||||
'scope': []
|
||||
}
|
||||
|
||||
AUDIT_TEMPLATE_2 = {
|
||||
'uuid': '2a60ca9b-09b0-40ff-8674-de8a36fc4bc8',
|
||||
'name': 'at2',
|
||||
'description': 'Audit Template 2',
|
||||
'host_aggregate': 3,
|
||||
'extra': {'automatic': False},
|
||||
'goal_uuid': 'fc087747-61be-4aad-8126-b701731ae836',
|
||||
'goal_name': 'SERVER_CONSOLIDATION',
|
||||
@ -71,6 +70,7 @@ AUDIT_TEMPLATE_2 = {
|
||||
'created_at': datetime.datetime.now().isoformat(),
|
||||
'updated_at': None,
|
||||
'deleted_at': None,
|
||||
'scope': []
|
||||
}
|
||||
|
||||
|
||||
@ -299,7 +299,7 @@ class AuditTemplateShellTest(base.CommandTestCase):
|
||||
self.m_audit_template_mgr.update.return_value = audit_template
|
||||
|
||||
exit_code, result = self.run_cmd(
|
||||
'audittemplate update at1 replace host_aggregate=5')
|
||||
'audittemplate update at1 replace description="New description"')
|
||||
|
||||
self.assertEqual(0, exit_code)
|
||||
self.assertEqual(self.resource_as_dict(audit_template, self.FIELDS,
|
||||
@ -307,7 +307,8 @@ class AuditTemplateShellTest(base.CommandTestCase):
|
||||
result)
|
||||
self.m_audit_template_mgr.update.assert_called_once_with(
|
||||
'at1',
|
||||
[{'op': 'replace', 'path': '/host_aggregate', 'value': 5}])
|
||||
[{'op': 'replace', 'path': '/description',
|
||||
'value': 'New description'}])
|
||||
|
||||
def test_do_audit_template_create(self):
|
||||
audit_template = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_1)
|
||||
@ -346,8 +347,7 @@ class AuditTemplateShellTest(base.CommandTestCase):
|
||||
self.m_audit_template_mgr.create.return_value = audit_template
|
||||
|
||||
exit_code, result = self.run_cmd(
|
||||
'audittemplate create at1 fc087747-61be-4aad-8126-b701731ae836 '
|
||||
'-a 5')
|
||||
'audittemplate create at1 fc087747-61be-4aad-8126-b701731ae836')
|
||||
|
||||
self.assertEqual(0, exit_code)
|
||||
self.assertEqual(self.resource_as_dict(audit_template, self.FIELDS,
|
||||
@ -355,8 +355,7 @@ class AuditTemplateShellTest(base.CommandTestCase):
|
||||
result)
|
||||
self.m_audit_template_mgr.create.assert_called_once_with(
|
||||
goal='fc087747-61be-4aad-8126-b701731ae836',
|
||||
name='at1',
|
||||
host_aggregate='5')
|
||||
name='at1')
|
||||
|
||||
def test_do_audit_template_create_with_extra(self):
|
||||
audit_template = resource.AuditTemplate(mock.Mock(), AUDIT_TEMPLATE_1)
|
||||
|
@ -19,9 +19,8 @@ from watcherclient.common import utils
|
||||
from watcherclient import exceptions as exc
|
||||
|
||||
|
||||
CREATION_ATTRIBUTES = ['audit_template_uuid', 'host_aggregate',
|
||||
'deadline', 'audit_type', 'interval',
|
||||
'parameters', 'goal', 'strategy']
|
||||
CREATION_ATTRIBUTES = ['audit_template_uuid', 'deadline', 'audit_type',
|
||||
'interval', 'parameters', 'goal', 'strategy']
|
||||
|
||||
|
||||
class Audit(base.Resource):
|
||||
|
@ -162,12 +162,6 @@ class CreateAudit(command.ShowOne):
|
||||
dest='strategy',
|
||||
metavar='<strategy>',
|
||||
help=_('Strategy UUID or name associated to this audit.'))
|
||||
parser.add_argument(
|
||||
'-r', '--host-aggregate',
|
||||
dest='host_aggregate',
|
||||
metavar='<host-aggregate>',
|
||||
help=_('Name or UUID of the host aggregate targeted '
|
||||
'by this audit.'))
|
||||
parser.add_argument(
|
||||
'-a', '--audit-template',
|
||||
dest='audit_template_uuid',
|
||||
@ -178,9 +172,8 @@ class CreateAudit(command.ShowOne):
|
||||
def take_action(self, parsed_args):
|
||||
client = getattr(self.app.client_manager, "infra-optim")
|
||||
|
||||
field_list = ['audit_template_uuid', 'host_aggregate',
|
||||
'audit_type', 'deadline', 'parameters', 'interval',
|
||||
'goal', 'strategy']
|
||||
field_list = ['audit_template_uuid', 'audit_type', 'deadline',
|
||||
'parameters', 'interval', 'goal', 'strategy']
|
||||
|
||||
fields = dict((k, v) for (k, v) in vars(parsed_args).items()
|
||||
if k in field_list and v is not None)
|
||||
|
@ -18,8 +18,8 @@ from watcherclient.common import base
|
||||
from watcherclient.common import utils
|
||||
from watcherclient import exceptions as exc
|
||||
|
||||
CREATION_ATTRIBUTES = ['host_aggregate', 'description', 'name',
|
||||
'extra', 'goal', 'strategy']
|
||||
CREATION_ATTRIBUTES = ['description', 'name', 'extra', 'goal', 'strategy',
|
||||
'scope']
|
||||
|
||||
|
||||
class AuditTemplate(base.Resource):
|
||||
|
@ -14,6 +14,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import argparse
|
||||
|
||||
from osc_lib import utils
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
@ -126,7 +128,17 @@ class CreateAuditTemplate(command.ShowOne):
|
||||
"""Create new audit template."""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CreateAuditTemplate, self).get_parser(prog_name)
|
||||
class SmartFormatter(argparse.HelpFormatter):
|
||||
|
||||
def _split_lines(self, text, width):
|
||||
if '\n' in text:
|
||||
return text.splitlines()
|
||||
else:
|
||||
return argparse.HelpFormatter._split_lines(
|
||||
self, text, width)
|
||||
|
||||
parser = super(CreateAuditTemplate, self).get_parser(
|
||||
prog_name, formatter_class=SmartFormatter)
|
||||
parser.add_argument(
|
||||
'name',
|
||||
metavar='<name>',
|
||||
@ -151,19 +163,53 @@ class CreateAuditTemplate(command.ShowOne):
|
||||
help=_("Record arbitrary key/value metadata. "
|
||||
"Can be specified multiple times."))
|
||||
parser.add_argument(
|
||||
'-a', '--host-aggregate',
|
||||
dest='host_aggregate',
|
||||
metavar='<host-aggregate>',
|
||||
help=_('Name or UUID of the host aggregate targeted '
|
||||
'by this audit template.'))
|
||||
'--scope',
|
||||
metavar='<path>',
|
||||
help=_("Part of the cluster on which an audit will be done.\n"
|
||||
"Can be provided either in yaml or json file.\n"
|
||||
"YAML example:\n"
|
||||
"---\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"
|
||||
" - compute_nodes:\n"
|
||||
" - name: compute1\n"
|
||||
"\n"
|
||||
"JSON example:\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"
|
||||
)
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = getattr(self.app.client_manager, "infra-optim")
|
||||
|
||||
field_list = ['host_aggregate', 'description', 'name', 'extra',
|
||||
'goal', 'strategy']
|
||||
field_list = ['description', 'name', 'extra', 'goal', 'strategy',
|
||||
'scope']
|
||||
fields = dict((k, v) for (k, v) in vars(parsed_args).items()
|
||||
if k in field_list and v is not None)
|
||||
|
||||
@ -176,6 +222,9 @@ class CreateAuditTemplate(command.ShowOne):
|
||||
if not uuidutils.is_uuid_like(fields['strategy']):
|
||||
fields['strategy'] = client.strategy.get(
|
||||
fields['strategy']).uuid
|
||||
if fields.get('scope'):
|
||||
fields['scope'] = common_utils.serialize_file_to_dict(
|
||||
fields['scope'])
|
||||
|
||||
fields = common_utils.args_array_to_dict(fields, 'extra')
|
||||
audit_template = client.audit_template.create(**fields)
|
||||
|
@ -19,13 +19,11 @@
|
||||
# Audit Template
|
||||
AUDIT_TEMPLATE_FIELDS = [
|
||||
'uuid', 'created_at', 'updated_at', 'deleted_at',
|
||||
'description', 'host_aggregate', 'name',
|
||||
'extra', 'goal_name', 'strategy_name']
|
||||
'description', 'name', 'extra', 'goal_name', 'strategy_name', 'scope']
|
||||
|
||||
AUDIT_TEMPLATE_FIELD_LABELS = [
|
||||
'UUID', 'Created At', 'Updated At', 'Deleted At',
|
||||
'Description', 'Host Aggregate ID or Name', 'Name',
|
||||
'Extra', 'Goal', 'Strategy']
|
||||
'Description', 'Name', 'Extra', 'Goal', 'Strategy', 'Audit Scope']
|
||||
|
||||
AUDIT_TEMPLATE_SHORT_LIST_FIELDS = [
|
||||
'uuid', 'name', 'goal_name', 'strategy_name']
|
||||
@ -35,13 +33,13 @@ AUDIT_TEMPLATE_SHORT_LIST_FIELD_LABELS = ['UUID', 'Name', 'Goal', 'Strategy']
|
||||
# Audit
|
||||
AUDIT_FIELDS = ['uuid', 'created_at', 'updated_at', 'deleted_at',
|
||||
'deadline', 'state', 'audit_type',
|
||||
'parameters', 'interval',
|
||||
'host_aggregate', 'goal_name', 'strategy_name']
|
||||
'parameters', 'interval', 'goal_name', 'strategy_name',
|
||||
'scope']
|
||||
|
||||
AUDIT_FIELD_LABELS = ['UUID', 'Created At', 'Updated At', 'Deleted At',
|
||||
'Deadline', 'State', 'Audit Type',
|
||||
'Parameters', 'Interval', 'Host Aggregate ID or Name',
|
||||
'Goal', 'Strategy']
|
||||
'Parameters', 'Interval', 'Goal', 'Strategy',
|
||||
'Audit Scope']
|
||||
|
||||
AUDIT_SHORT_LIST_FIELDS = ['uuid', 'audit_type',
|
||||
'state', 'goal_name', 'strategy_name']
|
||||
|
Loading…
x
Reference in New Issue
Block a user