Added Goals and Strategies to Dashboard
In this changeset I added 2 new panels: Goals and Strategies. I also update the Audit Template panel to take into account the new model fields. Partially Implements: get-goal-from-strategy Change-Id: Ie8d8785ee0133650ac56c499abca0260309032eb
This commit is contained in:
parent
d5b54a8c5d
commit
387e51ee96
@ -6,6 +6,7 @@ pbr>=1.8
|
||||
Django>=1.8,<1.9 # BSD
|
||||
django_compressor>=1.4 # MIT
|
||||
django_openstack_auth>=2.0.0 # Apache-2.0
|
||||
httplib2>=0.7.5 # MIT
|
||||
python-keystoneclient>=1.6.0,!=1.8.0,!=2.1.0 # Apache-2.0
|
||||
pytz>=2013.6 # MIT
|
||||
|
||||
|
@ -343,7 +343,7 @@ function run_tests {
|
||||
fi
|
||||
|
||||
if [ $with_selenium -eq 0 -a $integration -eq 0 ]; then
|
||||
testopts="$testopts --exclude=watcher_dashboard/test/integration_tests/"
|
||||
testopts="$testopts --exclude=watcher_dashboard/test/integration_tests/ "
|
||||
fi
|
||||
|
||||
if [ $selenium_headless -eq 1 ]; then
|
||||
|
2
tox.ini
2
tox.ini
@ -22,7 +22,7 @@ deps = -r{toxinidir}/requirements.txt
|
||||
commands =
|
||||
python manage.py test --settings=watcher_dashboard.test.settings \
|
||||
--exclude-dir=watcher_dashboard/test/integration_tests \
|
||||
watcher_dashboard.test
|
||||
watcher_dashboard
|
||||
|
||||
[testenv:pep8]
|
||||
commands = flake8
|
||||
|
@ -46,7 +46,7 @@ def watcherclient(request, password=None):
|
||||
return client
|
||||
|
||||
|
||||
class Audit(base.APIResourceWrapper):
|
||||
class Audit(base.APIDictWrapper):
|
||||
_attrs = ('uuid', 'created_at', 'modified_at', 'deleted_at',
|
||||
'deadline', 'state', 'type', 'audit_template_uuid',
|
||||
'audit_template_name')
|
||||
@ -62,8 +62,8 @@ class Audit(base.APIResourceWrapper):
|
||||
:param request: request object
|
||||
:type request: django.http.HttpRequest
|
||||
|
||||
:param audit_template: audit audit_template
|
||||
:type audit_template: string
|
||||
:param audit_template_uuid: related audit template UUID
|
||||
:type audit_template_uuid: string
|
||||
|
||||
:param type: audit type
|
||||
:type type: string
|
||||
@ -72,12 +72,11 @@ class Audit(base.APIResourceWrapper):
|
||||
:type deadline: string
|
||||
|
||||
:return: the created Audit object
|
||||
:rtype: watcher_dashboard.api.watcher.Audit
|
||||
:rtype: :py:class:`~.Audit`
|
||||
"""
|
||||
audit = watcherclient(request).audit.create(
|
||||
return watcherclient(request).audit.create(
|
||||
audit_template_uuid=audit_template_uuid, type=type,
|
||||
deadline=deadline)
|
||||
return cls(audit, request=request)
|
||||
|
||||
@classmethod
|
||||
def list(cls, request, audit_template_filter):
|
||||
@ -90,11 +89,10 @@ class Audit(base.APIResourceWrapper):
|
||||
:type audit_template_filter: string
|
||||
|
||||
:return: list of audits, or an empty list if there are none
|
||||
:rtype: list of watcher_dashboard.api.watcher.Audit
|
||||
:rtype: list of :py:class:`~.Audit`
|
||||
"""
|
||||
audits = watcherclient(request).audit.list(
|
||||
return watcherclient(request).audit.list(
|
||||
audit_template=audit_template_filter)
|
||||
return [cls(audit, request=request) for audit in audits]
|
||||
|
||||
@classmethod
|
||||
@errors_utils.handle_errors(_("Unable to retrieve audit"))
|
||||
@ -109,10 +107,9 @@ class Audit(base.APIResourceWrapper):
|
||||
|
||||
:return: matching audit, or None if no audit matches
|
||||
the ID
|
||||
:rtype: watcher_dashboard.api.watcher.Audit
|
||||
:rtype: :py:class:`~.Audit`
|
||||
"""
|
||||
audit = watcherclient(request).audit.get(audit_id=audit_id)
|
||||
return cls(audit, request=request)
|
||||
return watcherclient(request).audit.get(audit_id=audit_id)
|
||||
|
||||
@classmethod
|
||||
def delete(cls, request, audit_id):
|
||||
@ -134,14 +131,15 @@ class Audit(base.APIResourceWrapper):
|
||||
class AuditTemplate(base.APIDictWrapper):
|
||||
_attrs = ('uuid', 'created_at', 'updated_at', 'deleted_at',
|
||||
'description', 'host_aggregate', 'name',
|
||||
'extra', 'goal')
|
||||
'extra', 'goal_uuid' 'strategy_uuid')
|
||||
|
||||
def __init__(self, apiresource, request=None):
|
||||
super(AuditTemplate, self).__init__(apiresource)
|
||||
self._request = request
|
||||
|
||||
@classmethod
|
||||
def create(cls, request, name, goal, description, host_aggregate):
|
||||
def create(cls, request, name, goal_uuid, strategy_uuid,
|
||||
description, host_aggregate):
|
||||
"""Create an audit template in Watcher
|
||||
|
||||
:param request: request object
|
||||
@ -150,25 +148,29 @@ class AuditTemplate(base.APIDictWrapper):
|
||||
:param name: Name for this audit template
|
||||
:type name: string
|
||||
|
||||
:param goal: Goal Type associated to this audit template
|
||||
:type goal: string
|
||||
:param goal_uuid: Goal UUID associated to this audit template
|
||||
:type goal_uuid: string
|
||||
|
||||
:param strategy_uuid: Strategy UUID associated to this audit template
|
||||
:type strategy_uuid: string
|
||||
|
||||
:param description: Descrition of the audit template
|
||||
:type description: string
|
||||
|
||||
:param host_aggregate: Name or ID of the host aggregate targeted\
|
||||
by this audit template
|
||||
:param host_aggregate: Name or UUID of the host aggregate targeted
|
||||
by this audit template
|
||||
:type host_aggregate: string
|
||||
|
||||
:param audit_template: audit audit_template
|
||||
:param audit_template: audit template
|
||||
:type audit_template: string
|
||||
|
||||
:return: the created Audit Template object
|
||||
:rtype: watcher_dashboard.api.watcher.AuditTemplate
|
||||
:rtype: :py:class:`~.AuditTemplate`
|
||||
"""
|
||||
audit_template = watcherclient(request).audit_template.create(
|
||||
name=name,
|
||||
goal=goal,
|
||||
goal_uuid=goal_uuid,
|
||||
strategy_uuid=strategy_uuid,
|
||||
description=description,
|
||||
host_aggregate=host_aggregate
|
||||
)
|
||||
@ -189,7 +191,7 @@ class AuditTemplate(base.APIDictWrapper):
|
||||
:type parameters: dict
|
||||
|
||||
:return: the updated Audit Template object
|
||||
:rtype: watcher_dashboard.api.watcher.AuditTemplate
|
||||
:rtype: :py:class:`~.AuditTemplate`
|
||||
"""
|
||||
parameter_list = [{
|
||||
'name': str(name),
|
||||
@ -200,22 +202,18 @@ class AuditTemplate(base.APIDictWrapper):
|
||||
return audit_template
|
||||
|
||||
@classmethod
|
||||
def list(cls, request, filter):
|
||||
def list(cls, request, **filters):
|
||||
"""Return a list of audit templates in Watcher
|
||||
|
||||
:param request: request object
|
||||
:type request: django.http.HttpRequest
|
||||
|
||||
:param filter: audit template filter
|
||||
:type filter: string
|
||||
:param filters: key/value kwargs used as filters
|
||||
|
||||
:return: list of audit templates, or an empty list if there are none
|
||||
:rtype: list of watcher_dashboard.api.watcher.AuditTemplate
|
||||
:rtype: list of :py:class:`~.AuditTemplate`
|
||||
"""
|
||||
|
||||
audit_templates = watcherclient(request).audit_template.list(
|
||||
name=filter)
|
||||
return audit_templates
|
||||
return watcherclient(request).audit_template.list(**filters)
|
||||
|
||||
@classmethod
|
||||
@errors_utils.handle_errors(_("Unable to retrieve audit template"))
|
||||
@ -230,31 +228,10 @@ class AuditTemplate(base.APIDictWrapper):
|
||||
|
||||
:return: matching audit template, or None if no audit template matches
|
||||
the ID
|
||||
:rtype: watcher_dashboard.api.watcher.AuditTemplate
|
||||
:rtype: :py:class:`~.AuditTemplate`
|
||||
"""
|
||||
audit_template = watcherclient(request).audit_template.get(
|
||||
return watcherclient(request).audit_template.get(
|
||||
audit_template_id=audit_template_id)
|
||||
# return cls(audit, request=request)
|
||||
return audit_template
|
||||
|
||||
@classmethod
|
||||
@errors_utils.handle_errors(_("Unable to retrieve audit template goal"))
|
||||
def get_goals(cls, request):
|
||||
"""Return the audit template goal that matches the ID
|
||||
|
||||
:param request: request object
|
||||
:type request: django.http.HttpRequest
|
||||
|
||||
:param audit_template_id: id of audit template to be retrieved
|
||||
:type audit_template_id: int
|
||||
|
||||
:return: matching audit template, or None if no audit template matches
|
||||
the ID
|
||||
:rtype: watcher_dashboard.api.watcher.AuditTemplate
|
||||
"""
|
||||
|
||||
goals = watcherclient(request).goal.list()
|
||||
return map(lambda goal: goal.name, goals)
|
||||
|
||||
@classmethod
|
||||
def delete(cls, request, audit_template_id):
|
||||
@ -274,7 +251,7 @@ class AuditTemplate(base.APIDictWrapper):
|
||||
return self.uuid
|
||||
|
||||
|
||||
class ActionPlan(base.APIResourceWrapper):
|
||||
class ActionPlan(base.APIDictWrapper):
|
||||
_attrs = ('uuid', 'created_at', 'updated_at', 'deleted_at',
|
||||
'audit_uuid', 'state')
|
||||
|
||||
@ -293,12 +270,10 @@ class ActionPlan(base.APIResourceWrapper):
|
||||
:type audit_filter: string
|
||||
|
||||
:return: list of action plans, or an empty list if there are none
|
||||
:rtype: list of watcher_dashboard.api.watcher.ActionPlan
|
||||
:rtype: list of :py:class:`~.ActionPlan`
|
||||
"""
|
||||
action_plans = watcherclient(request).action_plan.list(
|
||||
return watcherclient(request).action_plan.list(
|
||||
audit=audit_filter)
|
||||
return [cls(action_plan, request=request)
|
||||
for action_plan in action_plans]
|
||||
|
||||
@classmethod
|
||||
@errors_utils.handle_errors(_("Unable to retrieve action plan"))
|
||||
@ -313,11 +288,10 @@ class ActionPlan(base.APIResourceWrapper):
|
||||
|
||||
:return: matching action plan, or None if no action plan matches
|
||||
the ID
|
||||
:rtype: watcher_dashboard.api.watcher.ActionPlan
|
||||
:rtype: :py:class:`~.ActionPlan`
|
||||
"""
|
||||
action_plan = watcherclient(request).action_plan.get(
|
||||
return watcherclient(request).action_plan.get(
|
||||
action_plan_id=action_plan_id)
|
||||
return cls(action_plan, request=request)
|
||||
|
||||
@classmethod
|
||||
def delete(cls, request, action_plan_id):
|
||||
@ -351,7 +325,7 @@ class ActionPlan(base.APIResourceWrapper):
|
||||
return self.uuid
|
||||
|
||||
|
||||
class Action(base.APIResourceWrapper):
|
||||
class Action(base.APIDictWrapper):
|
||||
_attrs = ('uuid', 'created_at', 'updated_at', 'deleted_at', 'next_uuid',
|
||||
'description', 'state', 'action_plan_uuid',
|
||||
'action_type', 'applies_to', 'src', 'dst', 'parameter')
|
||||
@ -371,13 +345,11 @@ class Action(base.APIResourceWrapper):
|
||||
:type action_plan_filter: string
|
||||
|
||||
:return: list of actions, or an empty list if there are none
|
||||
:rtype: list of watcher_dashboard.api.watcher.Action
|
||||
:rtype: list of :py:class:`~.Action`
|
||||
"""
|
||||
|
||||
actions = watcherclient(request).action.list(
|
||||
return watcherclient(request).action.list(
|
||||
action_plan=action_plan_filter, detail=True)
|
||||
return [cls(action, request=request)
|
||||
for action in actions]
|
||||
|
||||
@classmethod
|
||||
@errors_utils.handle_errors(_("Unable to retrieve action"))
|
||||
@ -392,11 +364,9 @@ class Action(base.APIResourceWrapper):
|
||||
|
||||
:return: matching action, or None if no action matches
|
||||
the ID
|
||||
:rtype: watcher_dashboard.api.watcher.Action
|
||||
:rtype: :py:class:`~.Action`
|
||||
"""
|
||||
action = watcherclient(request).action.get(
|
||||
action_id=action_id)
|
||||
return cls(action, request=request)
|
||||
return watcherclient(request).action.get(action_id=action_id)
|
||||
|
||||
@classmethod
|
||||
def delete(cls, request, action_id):
|
||||
@ -428,3 +398,94 @@ class Action(base.APIResourceWrapper):
|
||||
@property
|
||||
def id(self):
|
||||
return self.uuid
|
||||
|
||||
|
||||
class Goal(base.APIDictWrapper):
|
||||
"""Goal resource."""
|
||||
|
||||
_attrs = ('uuid', 'name', 'display_name', 'created_at',
|
||||
'updated_at', 'deleted_at')
|
||||
|
||||
def __init__(self, apiresource, request=None):
|
||||
super(Goal, self).__init__(apiresource)
|
||||
self._request = request
|
||||
|
||||
@classmethod
|
||||
def list(cls, request, **filters):
|
||||
"""Return a list of goals in Watcher
|
||||
|
||||
:param request: request object
|
||||
:type request: django.http.HttpRequest
|
||||
|
||||
:return: list of goals, or an empty list if there are none
|
||||
:rtype: list of :py:class:`~.Goal` instance
|
||||
"""
|
||||
return watcherclient(request).goal.list(detail=True, **filters)
|
||||
|
||||
@classmethod
|
||||
@errors_utils.handle_errors(_("Unable to retrieve goal"))
|
||||
def get(cls, request, goal_uuid):
|
||||
"""Return the goal that matches the ID
|
||||
|
||||
:param request: request object
|
||||
:type request: django.http.HttpRequest
|
||||
|
||||
:param goal_uuid: uuid of goal to be retrieved
|
||||
:type goal_uuid: int
|
||||
|
||||
:return: matching goal, or None if no goal matches the UUID
|
||||
:rtype: :py:class:`~.Goal` instance
|
||||
"""
|
||||
return watcherclient(request).goal.get(goal_uuid)
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self.uuid
|
||||
|
||||
|
||||
class Strategy(base.APIDictWrapper):
|
||||
"""Strategy resource."""
|
||||
|
||||
_attrs = ('uuid', 'name', 'display_name', 'goal_uuid', 'created_at',
|
||||
'updated_at', 'deleted_at')
|
||||
|
||||
def __init__(self, apiresource, request=None):
|
||||
super(Strategy, self).__init__(apiresource)
|
||||
self._request = request
|
||||
|
||||
@classmethod
|
||||
def list(cls, request, **filters):
|
||||
"""Return a list of strategies in Watcher
|
||||
|
||||
:param request: request object
|
||||
:type request: django.http.HttpRequest
|
||||
|
||||
:param goal_uuid: goal uuid filter
|
||||
:type goal_uuid: string
|
||||
|
||||
:return: list of strategies, or an empty list if there are none
|
||||
:rtype: list of :py:class:`~.Strategy` instances
|
||||
"""
|
||||
goal_uuid = filters.get('goal_uuid', None)
|
||||
return watcherclient(request).strategy.list(
|
||||
goal_uuid=goal_uuid, detail=True)
|
||||
|
||||
@classmethod
|
||||
@errors_utils.handle_errors(_("Unable to retrieve strategy"))
|
||||
def get(cls, request, strategy_uuid):
|
||||
"""Return the strategy that matches the UUID
|
||||
|
||||
:param request: request object
|
||||
:type request: django.http.HttpRequest
|
||||
|
||||
:param strategy_uuid: uuid of strategy to be retrieved
|
||||
:type strategy_uuid: str
|
||||
|
||||
:return: matching strategy, or None if no strategy matches the UUID
|
||||
:rtype: :py:class:`~.Strategy` instance
|
||||
"""
|
||||
return watcherclient(request).strategy.get(strategy_uuid)
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self.uuid
|
||||
|
@ -32,7 +32,7 @@ LOG = logging.getLogger(__name__)
|
||||
ACTION_PLAN_STATE_DISPLAY_CHOICES = (
|
||||
("NO STATE", pgettext_lazy("State of an action plan", u"No State")),
|
||||
("ONGOING", pgettext_lazy("State of an action plan", u"On Going")),
|
||||
("SUCCESS", pgettext_lazy("State of an action plan", u"Sucess")),
|
||||
("SUCCEEDED", pgettext_lazy("State of an action plan", u"Succeeded")),
|
||||
("SUBMITTED", pgettext_lazy("State of an action plan", u"Submitted")),
|
||||
("FAILED", pgettext_lazy("State of an action plan", u"Failed")),
|
||||
("DELETED", pgettext_lazy("State of an action plan", u"Deleted")),
|
||||
@ -124,31 +124,10 @@ class UpdateRow(horizon.tables.Row):
|
||||
return action_plan
|
||||
|
||||
|
||||
# class CancelActionPlan(horizon.tables.DeleteAction):
|
||||
# verbose_name = _(u"Cancel ActionPlans")
|
||||
# icon = "trash"
|
||||
|
||||
# @staticmethod
|
||||
# def action_present(count):
|
||||
# return ungettext_lazy(
|
||||
# u"Cancel ActionPlan",
|
||||
# u"Cancel ActionPlans",
|
||||
# count
|
||||
# )
|
||||
|
||||
# @staticmethod
|
||||
# def action_past(count):
|
||||
# return ungettext_lazy(
|
||||
# u"Canceled ActionPlan",
|
||||
# u"canceled ActionPlans",
|
||||
# count
|
||||
# )
|
||||
|
||||
|
||||
class ActionPlansTable(horizon.tables.DataTable):
|
||||
name = horizon.tables.Column(
|
||||
'id',
|
||||
verbose_name=_("ID"),
|
||||
'uuid',
|
||||
verbose_name=_("UUID"),
|
||||
link="horizon:admin:action_plans:detail")
|
||||
audit = horizon.tables.Column(
|
||||
'audit_uuid',
|
||||
@ -165,6 +144,9 @@ class ActionPlansTable(horizon.tables.DataTable):
|
||||
status=True,
|
||||
status_choices=ACTION_PLAN_STATE_DISPLAY_CHOICES)
|
||||
|
||||
def get_object_id(self, datum):
|
||||
return datum.uuid
|
||||
|
||||
class Meta(object):
|
||||
name = "action_plans"
|
||||
verbose_name = _("ActionPlans")
|
||||
|
@ -19,12 +19,11 @@ from django.conf import urls
|
||||
from watcher_dashboard.content.action_plans import views
|
||||
|
||||
|
||||
urlpatterns = urls.patterns(
|
||||
'watcher_dashboard.content.action_plans.views',
|
||||
urlpatterns = [
|
||||
urls.url(r'^$',
|
||||
views.IndexView.as_view(), name='index'),
|
||||
urls.url(r'^(?P<action_plan_id>[^/]+)/detail$',
|
||||
urls.url(r'^(?P<action_plan_uuid>[^/]+)/detail$',
|
||||
views.DetailView.as_view(), name='detail'),
|
||||
urls.url(r'^archive/$',
|
||||
views.ArchiveView.as_view(), name='archive'),
|
||||
)
|
||||
]
|
||||
|
@ -85,13 +85,14 @@ class DetailView(horizon.tables.MultiTableView):
|
||||
|
||||
@memoized.memoized_method
|
||||
def _get_data(self):
|
||||
action_plan_id = None
|
||||
action_plan_uuid = None
|
||||
try:
|
||||
action_plan_id = self.kwargs['action_plan_id']
|
||||
action_plan = watcher.ActionPlan.get(self.request, action_plan_id)
|
||||
action_plan_uuid = self.kwargs['action_plan_uuid']
|
||||
action_plan = watcher.ActionPlan.get(
|
||||
self.request, action_plan_uuid)
|
||||
except Exception:
|
||||
msg = _('Unable to retrieve details for action_plan "%s".') \
|
||||
% action_plan_id
|
||||
% action_plan_uuid
|
||||
horizon.exceptions.handle(
|
||||
self.request, msg,
|
||||
redirect=self.redirect_url)
|
||||
|
@ -32,7 +32,7 @@ LOG = logging.getLogger(__name__)
|
||||
ACTION_STATE_DISPLAY_CHOICES = (
|
||||
("NO STATE", pgettext_lazy("Power state of an Instance", u"No State")),
|
||||
("ONGOING", pgettext_lazy("Power state of an Instance", u"On Going")),
|
||||
("SUCCESS", pgettext_lazy("Power state of an Instance", u"Success")),
|
||||
("SUCCEEDED", pgettext_lazy("Power state of an Instance", u"Succeeded")),
|
||||
("CANCELLED", pgettext_lazy("Power state of an Instance", u"Cancelled")),
|
||||
("FAILED", pgettext_lazy("Power state of an Instance", u"Failed")),
|
||||
("DELETED", pgettext_lazy("Power state of an Instance", u"Deleted")),
|
||||
@ -62,8 +62,8 @@ class ActionsFilterAction(horizon.tables.FilterAction):
|
||||
|
||||
class ActionsTable(horizon.tables.DataTable):
|
||||
name = horizon.tables.Column(
|
||||
'id',
|
||||
verbose_name=_("ID"))
|
||||
'uuid',
|
||||
verbose_name=_("UUID"))
|
||||
action_type = horizon.tables.Column(
|
||||
'action_type',
|
||||
verbose_name=_('Type'),
|
||||
@ -81,6 +81,9 @@ class ActionsTable(horizon.tables.DataTable):
|
||||
verbose_name=_('Next Action'))
|
||||
ajax = True
|
||||
|
||||
def get_object_id(self, datum):
|
||||
return datum.uuid
|
||||
|
||||
class Meta(object):
|
||||
name = "wactions"
|
||||
verbose_name = _("Actions")
|
||||
|
@ -19,10 +19,9 @@ from django.conf import urls
|
||||
from watcher_dashboard.content.actions import views
|
||||
|
||||
|
||||
urlpatterns = urls.patterns(
|
||||
'watcher_dashboard.content.actions.views',
|
||||
urlpatterns = [
|
||||
urls.url(r'^$',
|
||||
views.IndexView.as_view(), name='index'),
|
||||
urls.url(r'^(?P<action_id>[^/]+)/$',
|
||||
urls.url(r'^(?P<action_uuid>[^/]+)/$',
|
||||
views.DetailView.as_view(), name='details'),
|
||||
)
|
||||
]
|
||||
|
@ -70,13 +70,13 @@ class DetailView(horizon.tabs.TabbedTableView):
|
||||
|
||||
@memoized.memoized_method
|
||||
def _get_data(self):
|
||||
action_plan_id = None
|
||||
action_plan_uuid = None
|
||||
try:
|
||||
action_plan_id = self.kwargs['action_plan_id']
|
||||
action = watcher.Action.get(self.request, action_plan_id)
|
||||
action_plan_uuid = self.kwargs['action_plan_uuid']
|
||||
action = watcher.Action.get(self.request, action_plan_uuid)
|
||||
except Exception:
|
||||
msg = _('Unable to retrieve details for action "%s".') \
|
||||
% action_plan_id
|
||||
% action_plan_uuid
|
||||
horizon.exceptions.handle(
|
||||
self.request, msg,
|
||||
redirect=self.redirect_url)
|
||||
|
@ -34,23 +34,29 @@ class CreateForm(forms.SelfHandlingForm):
|
||||
name = forms.CharField(max_length=255, label=_("Name"))
|
||||
description = forms.CharField(max_length=255, label=_("Description"),
|
||||
required=False)
|
||||
goal = forms.ChoiceField(label=_('Goal'),
|
||||
required=True,
|
||||
)
|
||||
goal_uuid = forms.ChoiceField(label=_('Goal'), required=True)
|
||||
strategy_uuid = forms.ChoiceField(label=_('Strategy'), required=False)
|
||||
|
||||
failure_url = 'horizon:admin:audit_templates:index'
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(CreateForm, self).__init__(request, *args, **kwargs)
|
||||
goals = self._get_goal_list(request)
|
||||
strategies = self._get_strategy_list(request, goals)
|
||||
|
||||
if goals:
|
||||
self.fields['goal'].choices = goals
|
||||
self.fields['goal_uuid'].choices = goals
|
||||
else:
|
||||
del self.fields['goal']
|
||||
del self.fields['goal_uuid']
|
||||
|
||||
if strategies:
|
||||
self.fields['strategy_uuid'].choices = strategies
|
||||
else:
|
||||
del self.fields['strategy_uuid']
|
||||
|
||||
def _get_goal_list(self, request):
|
||||
try:
|
||||
goals = watcher.AuditTemplate.get_goals(self.request)
|
||||
goals = watcher.Goal.list(self.request)
|
||||
except Exception as exc:
|
||||
msg = _('Failed to get goals list.')
|
||||
LOG.info(msg)
|
||||
@ -59,7 +65,7 @@ class CreateForm(forms.SelfHandlingForm):
|
||||
goals = []
|
||||
|
||||
choices = [
|
||||
(goal, goal)
|
||||
(goal.uuid, goal.display_name)
|
||||
for goal in goals
|
||||
]
|
||||
|
||||
@ -67,16 +73,41 @@ class CreateForm(forms.SelfHandlingForm):
|
||||
choices.insert(0, ("", _("Select Goal")))
|
||||
return choices
|
||||
|
||||
def _get_strategy_list(self, request, goals):
|
||||
try:
|
||||
strategies = watcher.Strategy.list(self.request)
|
||||
except Exception as exc:
|
||||
msg = _('Failed to get the list of available strategies.')
|
||||
LOG.info(msg)
|
||||
messages.warning(request, msg)
|
||||
messages.warning(request, exc)
|
||||
strategies = []
|
||||
|
||||
_goals = {}
|
||||
for goal in goals:
|
||||
_goals[goal[0]] = goal[1]
|
||||
|
||||
choices = [
|
||||
(strategy.uuid, strategy.display_name +
|
||||
' (GOAL: ' + _goals[strategy.goal_uuid] + ')')
|
||||
for strategy in strategies
|
||||
]
|
||||
|
||||
if choices:
|
||||
choices.insert(0, ("", _("Select Strategy")))
|
||||
return choices
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
params = {'name': data['name']}
|
||||
params['goal'] = data['goal']
|
||||
params['description'] = data['description']
|
||||
params['goal_uuid'] = data['goal_uuid']
|
||||
params['strategy_uuid'] = data['strategy_uuid'] or None
|
||||
params['host_aggregate'] = None
|
||||
audit_temp = watcher.AuditTemplate.create(request, **params)
|
||||
audit_tpl = watcher.AuditTemplate.create(request, **params)
|
||||
message = _('Audit Template was successfully created.')
|
||||
messages.success(request, message)
|
||||
return audit_temp
|
||||
return audit_tpl
|
||||
except Exception as exc:
|
||||
msg = _('Failed to create audit template"%s".') % data['name']
|
||||
LOG.info(exc)
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.utils.translation import pgettext_lazy
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ungettext_lazy
|
||||
import horizon.exceptions
|
||||
@ -26,25 +25,6 @@ import horizon.tables
|
||||
from watcher_dashboard.api import watcher
|
||||
|
||||
|
||||
AUDIT_TEMPLATE_GOAL_DISPLAY_CHOICES = (
|
||||
("BASIC_CONSOLIDATION", pgettext_lazy(
|
||||
"Goal of an Audit",
|
||||
"Consolidate Servers")),
|
||||
("MINIMIZE_ENERGY_CONSUMPTION", pgettext_lazy(
|
||||
"Goal of an Audit",
|
||||
"Minimize Energy")),
|
||||
("BALANCE_LOAD", pgettext_lazy(
|
||||
"Goal of an Audit",
|
||||
"Load Balancing")),
|
||||
("MINIMIZE_LICENSING_COST", pgettext_lazy(
|
||||
"Goal of an Audit",
|
||||
"Minimize Licensing Cost")),
|
||||
("PREPARED_PLAN_OPERATION", pgettext_lazy(
|
||||
"Goal of an Audit",
|
||||
"Prepared Plan Operation")),
|
||||
)
|
||||
|
||||
|
||||
class CreateAuditTemplates(horizon.tables.LinkAction):
|
||||
name = "create"
|
||||
verbose_name = _("Create Template")
|
||||
@ -55,7 +35,9 @@ class CreateAuditTemplates(horizon.tables.LinkAction):
|
||||
class AuditTemplatesFilterAction(horizon.tables.FilterAction):
|
||||
filter_type = "server"
|
||||
filter_choices = (
|
||||
('name', _("Template Name ="), True),
|
||||
('name', _("Name ="), True),
|
||||
('goal_uuid', _("Goal ="), True),
|
||||
('strategy_uuid', _("Strategy ="), True),
|
||||
)
|
||||
|
||||
|
||||
@ -65,8 +47,6 @@ class LaunchAudit(horizon.tables.BatchAction):
|
||||
data_type_singular = _("Launch Audit")
|
||||
data_type_plural = _("Launch Audits")
|
||||
success_url = "horizon:admin:audits:index"
|
||||
# icon = "cloud-upload"
|
||||
# policy_rules = (("compute", "compute:create"),)
|
||||
|
||||
@staticmethod
|
||||
def action_present(count):
|
||||
@ -120,10 +100,14 @@ class AuditTemplatesTable(horizon.tables.DataTable):
|
||||
verbose_name=_("Name"),
|
||||
link="horizon:admin:audit_templates:detail")
|
||||
goal = horizon.tables.Column(
|
||||
'goal',
|
||||
'goal_uuid',
|
||||
verbose_name=_('Goal'),
|
||||
status=True,
|
||||
status_choices=AUDIT_TEMPLATE_GOAL_DISPLAY_CHOICES
|
||||
)
|
||||
strategy = horizon.tables.Column(
|
||||
'strategy_uuid',
|
||||
verbose_name=_('Strategy'),
|
||||
status=True,
|
||||
)
|
||||
|
||||
def get_object_id(self, datum):
|
||||
@ -136,10 +120,7 @@ class AuditTemplatesTable(horizon.tables.DataTable):
|
||||
CreateAuditTemplates,
|
||||
DeleteAuditTemplates,
|
||||
AuditTemplatesFilterAction,
|
||||
# LaunchAuditTemplates,
|
||||
)
|
||||
row_actions = (
|
||||
LaunchAudit,
|
||||
# CreateAuditTemplates,
|
||||
# DeleteAuditTemplates,
|
||||
)
|
||||
|
@ -34,20 +34,17 @@ DETAILS_VIEW = 'horizon:admin:audit_templates:detail'
|
||||
|
||||
class AuditTemplatesTest(test.BaseAdminViewTests):
|
||||
|
||||
goal_list = [
|
||||
'BASIC_CONSOLIDATION',
|
||||
'MINIMIZE_ENERGY_CONSUMPTION',
|
||||
'BALANCE_LOAD',
|
||||
'MINIMIZE_LICENSING_COST',
|
||||
'PREPARED_PLAN_OPERATION',
|
||||
]
|
||||
def setUp(self):
|
||||
super(AuditTemplatesTest, self).setUp()
|
||||
self.goal_list = self.goals.list()
|
||||
self.strategy_list = self.strategies.list()
|
||||
|
||||
@test.create_stubs({api.watcher.AuditTemplate: ('list',)})
|
||||
def test_index(self):
|
||||
search_opts = None
|
||||
search_opts = {}
|
||||
api.watcher.AuditTemplate.list(
|
||||
IsA(http.HttpRequest),
|
||||
filter=search_opts).MultipleTimes().AndReturn(
|
||||
**search_opts).MultipleTimes().AndReturn(
|
||||
self.audit_templates.list())
|
||||
self.mox.ReplayAll()
|
||||
|
||||
@ -68,34 +65,45 @@ class AuditTemplatesTest(test.BaseAdminViewTests):
|
||||
resp = self.client.get(INDEX_URL)
|
||||
self.assertMessageCount(resp, error=1, warning=0)
|
||||
|
||||
@test.create_stubs({api.watcher.AuditTemplate: ('get_goals',)})
|
||||
@test.create_stubs({api.watcher.Strategy: ('list',)})
|
||||
@test.create_stubs({api.watcher.Goal: ('list',)})
|
||||
def test_create_get(self):
|
||||
api.watcher.AuditTemplate.get_goals(
|
||||
api.watcher.Goal.list(
|
||||
IsA(http.HttpRequest)).AndReturn(self.goal_list)
|
||||
api.watcher.Strategy.list(
|
||||
IsA(http.HttpRequest)).AndReturn(self.strategy_list)
|
||||
self.mox.ReplayAll()
|
||||
res = self.client.get(CREATE_URL)
|
||||
self.assertTemplateUsed(res, 'infra_optim/audit_templates/create.html')
|
||||
|
||||
@test.create_stubs({api.watcher.AuditTemplate: ('create',
|
||||
'get_goals')})
|
||||
@test.create_stubs({api.watcher.Strategy: ('list',)})
|
||||
@test.create_stubs({api.watcher.Goal: ('list',)})
|
||||
@test.create_stubs({api.watcher.AuditTemplate: ('create',)})
|
||||
def test_create_post(self):
|
||||
at = self.audit_templates.first()
|
||||
api.watcher.AuditTemplate.get_goals(
|
||||
params = {
|
||||
'name': at.name,
|
||||
'goal_uuid': at.goal_uuid,
|
||||
'strategy_uuid': at.strategy_uuid,
|
||||
'description': at.description,
|
||||
'host_aggregate': at.host_aggregate,
|
||||
}
|
||||
api.watcher.Goal.list(
|
||||
IsA(http.HttpRequest)).AndReturn(self.goal_list)
|
||||
params = {'name': at.name,
|
||||
'goal': at.goal,
|
||||
'description': at.description,
|
||||
'host_aggregate': at.host_aggregate,
|
||||
}
|
||||
api.watcher.Strategy.list(
|
||||
IsA(http.HttpRequest)).AndReturn(self.strategy_list)
|
||||
|
||||
api.watcher.AuditTemplate.create(
|
||||
IsA(http.HttpRequest), **params).AndReturn(at)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
form_data = {'name': at.name,
|
||||
'goal': at.goal,
|
||||
'description': at.description,
|
||||
'host_aggregate': at.host_aggregate,
|
||||
}
|
||||
form_data = {
|
||||
'name': at.name,
|
||||
'goal_uuid': at.goal_uuid,
|
||||
'strategy_uuid': at.strategy_uuid,
|
||||
'description': at.description,
|
||||
'host_aggregate': at.host_aggregate,
|
||||
}
|
||||
res = self.client.post(CREATE_URL, form_data)
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
@ -130,14 +138,13 @@ class AuditTemplatesTest(test.BaseAdminViewTests):
|
||||
|
||||
@test.create_stubs({api.watcher.AuditTemplate: ('delete', 'list')})
|
||||
def test_delete(self):
|
||||
search_opts = None
|
||||
search_opts = {}
|
||||
at_list = self.audit_templates.list()
|
||||
at = self.audit_templates.first()
|
||||
at_id = at.uuid
|
||||
api.watcher.AuditTemplate.list(
|
||||
IsA(http.HttpRequest),
|
||||
filter=search_opts).MultipleTimes().AndReturn(
|
||||
at_list)
|
||||
**search_opts).MultipleTimes().AndReturn(at_list)
|
||||
api.watcher.AuditTemplate.delete(IsA(http.HttpRequest), at_id)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
|
@ -19,11 +19,10 @@ from django.conf import urls
|
||||
from watcher_dashboard.content.audit_templates import views
|
||||
|
||||
|
||||
urlpatterns = urls.patterns(
|
||||
'watcher_dashboard.content.audit_templates.views',
|
||||
urlpatterns = [
|
||||
urls.url(r'^$', views.IndexView.as_view(), name='index'),
|
||||
urls.url(r'^create/$', views.CreateView.as_view(), name='create'),
|
||||
urls.url(r'^(?P<audit_template_id>[^/]+)/detail$',
|
||||
urls.url(r'^(?P<audit_template_uuid>[^/]+)/detail$',
|
||||
views.DetailView.as_view(),
|
||||
name='detail'),
|
||||
)
|
||||
]
|
||||
|
@ -44,8 +44,8 @@ class IndexView(horizon.tables.DataTableView):
|
||||
audit_templates = []
|
||||
search_opts = self.get_filters()
|
||||
try:
|
||||
audit_templates = watcher.AuditTemplate.list(self.request,
|
||||
filter=search_opts)
|
||||
audit_templates = watcher.AuditTemplate.list(
|
||||
self.request, **search_opts)
|
||||
except Exception:
|
||||
horizon.exceptions.handle(
|
||||
self.request,
|
||||
@ -56,15 +56,15 @@ class IndexView(horizon.tables.DataTableView):
|
||||
return len(self.get_data())
|
||||
|
||||
def get_filters(self):
|
||||
filter = None
|
||||
filters = {}
|
||||
filter_action = self.table._meta._filter_action
|
||||
if filter_action:
|
||||
filter_field = self.table.get_filter_field()
|
||||
if filter_action.is_api_filter(filter_field):
|
||||
filter_string = self.table.get_filter_string()
|
||||
if filter_field and filter_string:
|
||||
filter = filter_string
|
||||
return filter
|
||||
filters[filter_field] = filter_string
|
||||
return filters
|
||||
|
||||
|
||||
class CreateView(forms.ModalFormView):
|
||||
@ -85,15 +85,15 @@ class DetailView(horizon.tabs.TabbedTableView):
|
||||
page_title = _("Audit Template Details: {{ audit_template.name }}")
|
||||
|
||||
def _get_data(self):
|
||||
audit_template_id = None
|
||||
audit_template_uuid = None
|
||||
try:
|
||||
LOG.info(self.kwargs)
|
||||
audit_template_id = self.kwargs['audit_template_id']
|
||||
audit_template = watcher.AuditTemplate.get(self.request,
|
||||
audit_template_id)
|
||||
audit_template_uuid = self.kwargs['audit_template_uuid']
|
||||
audit_template = watcher.AuditTemplate.get(
|
||||
self.request, audit_template_uuid)
|
||||
except Exception:
|
||||
msg = _('Unable to retrieve details for audit template "%s".') \
|
||||
% audit_template_id
|
||||
% audit_template_uuid
|
||||
horizon.exceptions.handle(
|
||||
self.request, msg,
|
||||
redirect=self.redirect_url)
|
||||
|
@ -45,7 +45,7 @@ class CreateForm(forms.SelfHandlingForm):
|
||||
|
||||
def _get_audit_template_list(self, request):
|
||||
try:
|
||||
audit_templates = watcher.AuditTemplate.list(self.request, None)
|
||||
audit_templates = watcher.AuditTemplate.list(self.request)
|
||||
except Exception:
|
||||
msg = _('Failed to get audit template list.')
|
||||
LOG.info(msg)
|
||||
|
@ -14,6 +14,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import logging
|
||||
|
||||
from django.core import urlresolvers
|
||||
from django import shortcuts
|
||||
from django.template.defaultfilters import title # noqa
|
||||
@ -23,15 +25,15 @@ import horizon.exceptions
|
||||
import horizon.messages
|
||||
import horizon.tables
|
||||
from horizon.utils import filters
|
||||
|
||||
from watcher_dashboard.api import watcher
|
||||
|
||||
import logging
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
AUDIT_STATE_DISPLAY_CHOICES = (
|
||||
("NO STATE", pgettext_lazy("State of an audit", u"No State")),
|
||||
("ONGOING", pgettext_lazy("State of an audit", u"On Going")),
|
||||
("SUCCESS", pgettext_lazy("State of an audit", u"Sucess")),
|
||||
("SUCCEEDED", pgettext_lazy("State of an audit", u"Succeeeded")),
|
||||
("SUBMITTED", pgettext_lazy("State of an audit", u"Submitted")),
|
||||
("FAILED", pgettext_lazy("State of an audit", u"Failed")),
|
||||
("DELETED", pgettext_lazy("State of an audit", u"Deleted")),
|
||||
@ -55,19 +57,10 @@ class CreateAudit(horizon.tables.LinkAction):
|
||||
# policy_rules = (("compute", "compute:create"),)
|
||||
|
||||
|
||||
# class ArchiveAudits(horizon.tables.LinkAction):
|
||||
# name = "archive_audits"
|
||||
# verbose_name = _("Archive Audits")
|
||||
# url = "horizon:project:instances:launch"
|
||||
# classes = ("ajax-modal", "btn-launch")
|
||||
# icon = "folder-open"
|
||||
|
||||
class GoToActionPlan(horizon.tables.Action):
|
||||
name = "go_to_action_plan"
|
||||
verbose_name = _("Go to Action Plan")
|
||||
url = "horizon:admin:action_plans:detail"
|
||||
# classes = ("ajax-modal", "btn-launch")
|
||||
# icon = "send"
|
||||
|
||||
def allowed(self, request, audit):
|
||||
return ((audit is None) or
|
||||
@ -117,8 +110,8 @@ class GoToAuditTemplate(horizon.tables.Action):
|
||||
|
||||
class AuditsTable(horizon.tables.DataTable):
|
||||
name = horizon.tables.Column(
|
||||
'id',
|
||||
verbose_name=_("ID"),
|
||||
'uuid',
|
||||
verbose_name=_("UUID"),
|
||||
link="horizon:admin:audits:detail")
|
||||
audit_template = horizon.tables.Column(
|
||||
'audit_template_name',
|
||||
@ -130,6 +123,9 @@ class AuditsTable(horizon.tables.DataTable):
|
||||
status=True,
|
||||
status_choices=AUDIT_STATE_DISPLAY_CHOICES)
|
||||
|
||||
def get_object_id(self, datum):
|
||||
return datum.uuid
|
||||
|
||||
class Meta(object):
|
||||
name = "audits"
|
||||
verbose_name = _("Audits")
|
||||
|
@ -19,12 +19,11 @@ from django.conf import urls
|
||||
from watcher_dashboard.content.audits import views
|
||||
|
||||
|
||||
urlpatterns = urls.patterns(
|
||||
'watcher_dashboard.audits.views',
|
||||
urlpatterns = [
|
||||
urls.url(r'^$',
|
||||
views.IndexView.as_view(), name='index'),
|
||||
urls.url(r'^create/$',
|
||||
views.CreateView.as_view(), name='create'),
|
||||
urls.url(r'^(?P<audit_id>[^/]+)/detail$',
|
||||
urls.url(r'^(?P<audit_uuid>[^/]+)/detail$',
|
||||
views.DetailView.as_view(), name='detail'),
|
||||
)
|
||||
]
|
||||
|
@ -91,13 +91,13 @@ class DetailView(horizon.tabs.TabbedTableView):
|
||||
|
||||
@memoized.memoized_method
|
||||
def _get_data(self):
|
||||
audit_id = None
|
||||
audit_uuid = None
|
||||
try:
|
||||
audit_id = self.kwargs['audit_id']
|
||||
audit = watcher.Audit.get(self.request, audit_id)
|
||||
audit_uuid = self.kwargs['audit_uuid']
|
||||
audit = watcher.Audit.get(self.request, audit_uuid)
|
||||
except Exception:
|
||||
msg = _('Unable to retrieve details for audit "%s".') \
|
||||
% audit_id
|
||||
% audit_uuid
|
||||
horizon.exceptions.handle(
|
||||
self.request, msg,
|
||||
redirect=self.redirect_url)
|
||||
|
0
watcher_dashboard/content/goals/__init__.py
Normal file
0
watcher_dashboard/content/goals/__init__.py
Normal file
0
watcher_dashboard/content/goals/forms.py
Normal file
0
watcher_dashboard/content/goals/forms.py
Normal file
23
watcher_dashboard/content/goals/panel.py
Normal file
23
watcher_dashboard/content/goals/panel.py
Normal file
@ -0,0 +1,23 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2016 b<>com
|
||||
#
|
||||
# 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 django.utils.translation import ugettext_lazy as _
|
||||
import horizon
|
||||
|
||||
|
||||
class Goals(horizon.Panel):
|
||||
name = _("Goals")
|
||||
slug = "goals"
|
38
watcher_dashboard/content/goals/tables.py
Normal file
38
watcher_dashboard/content/goals/tables.py
Normal file
@ -0,0 +1,38 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2016 b<>com
|
||||
#
|
||||
# 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 django.template.defaultfilters import title # noqa
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
import horizon.exceptions
|
||||
import horizon.messages
|
||||
import horizon.tables
|
||||
|
||||
|
||||
class GoalsTable(horizon.tables.DataTable):
|
||||
uuid = horizon.tables.Column(
|
||||
'uuid',
|
||||
verbose_name=_("UUID"),
|
||||
link="horizon:admin:goals:detail")
|
||||
display_name = horizon.tables.Column(
|
||||
'display_name',
|
||||
verbose_name=_('Name'))
|
||||
|
||||
def get_object_id(self, datum):
|
||||
return datum.uuid
|
||||
|
||||
class Meta(object):
|
||||
name = "goals"
|
||||
verbose_name = _("Goals")
|
33
watcher_dashboard/content/goals/tabs.py
Normal file
33
watcher_dashboard/content/goals/tabs.py
Normal file
@ -0,0 +1,33 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2016 b<>com
|
||||
#
|
||||
# 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 django.utils.translation import ugettext_lazy as _
|
||||
from horizon import tabs
|
||||
|
||||
|
||||
class OverviewTab(tabs.Tab):
|
||||
name = _("Overview")
|
||||
slug = "overview"
|
||||
template_name = "infra_optim/goals/_detail_overview.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
return {"goal": self.tab_group.kwargs['goal']}
|
||||
|
||||
|
||||
class GoalDetailTabs(tabs.TabGroup):
|
||||
slug = "goal_details"
|
||||
tabs = (OverviewTab,)
|
||||
sticky = True
|
82
watcher_dashboard/content/goals/tests.py
Normal file
82
watcher_dashboard/content/goals/tests.py
Normal file
@ -0,0 +1,82 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2016 b<>com
|
||||
#
|
||||
# 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 logging
|
||||
|
||||
from django.core import urlresolvers
|
||||
from django import http
|
||||
from mox3.mox import IsA # noqa
|
||||
|
||||
from watcher_dashboard import api
|
||||
from watcher_dashboard.test import helpers as test
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
INDEX_URL = urlresolvers.reverse('horizon:admin:goals:index')
|
||||
DETAILS_VIEW = 'horizon:admin:goals:detail'
|
||||
|
||||
|
||||
class GoalsTest(test.BaseAdminViewTests):
|
||||
|
||||
@test.create_stubs({api.watcher.Goal: ('list',)})
|
||||
def test_index(self):
|
||||
search_opts = {}
|
||||
api.watcher.Goal.list(
|
||||
IsA(http.HttpRequest), **search_opts
|
||||
).MultipleTimes().AndReturn(self.goals.list())
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(INDEX_URL)
|
||||
self.assertTemplateUsed(res, 'infra_optim/goals/index.html')
|
||||
goals = res.context['goals_table'].data
|
||||
self.assertItemsEqual(goals, self.goals.list())
|
||||
|
||||
@test.create_stubs({api.watcher.Goal: ('list',)})
|
||||
def test_goal_list_unavailable(self):
|
||||
search_opts = {}
|
||||
api.watcher.Goal.list(
|
||||
IsA(http.HttpRequest), **search_opts
|
||||
).MultipleTimes().AndRaise(self.exceptions.watcher)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
resp = self.client.get(INDEX_URL)
|
||||
self.assertMessageCount(resp, error=1, warning=0)
|
||||
|
||||
@test.create_stubs({api.watcher.Goal: ('get',)})
|
||||
def test_details(self):
|
||||
goal = self.goals.first()
|
||||
goal_id = goal.uuid
|
||||
api.watcher.Goal.get(
|
||||
IsA(http.HttpRequest), goal_id).MultipleTimes().AndReturn(goal)
|
||||
self.mox.ReplayAll()
|
||||
DETAILS_URL = urlresolvers.reverse(DETAILS_VIEW, args=[goal_id])
|
||||
res = self.client.get(DETAILS_URL)
|
||||
self.assertTemplateUsed(res, 'infra_optim/goals/details.html')
|
||||
goals = res.context['goal']
|
||||
self.assertItemsEqual([goals], [goal])
|
||||
|
||||
@test.create_stubs({api.watcher.Goal: ('get',)})
|
||||
def test_details_exception(self):
|
||||
at = self.goals.first()
|
||||
at_id = at.uuid
|
||||
api.watcher.Goal.get(IsA(http.HttpRequest), at_id) \
|
||||
.AndRaise(self.exceptions.watcher)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
DETAILS_URL = urlresolvers.reverse(DETAILS_VIEW, args=[at_id])
|
||||
res = self.client.get(DETAILS_URL)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
27
watcher_dashboard/content/goals/urls.py
Normal file
27
watcher_dashboard/content/goals/urls.py
Normal file
@ -0,0 +1,27 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2016 b<>com
|
||||
#
|
||||
# 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 django.conf import urls
|
||||
|
||||
from watcher_dashboard.content.goals import views
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
urls.url(r'^$',
|
||||
views.IndexView.as_view(), name='index'),
|
||||
urls.url(r'^(?P<goal_uuid>[^/]+)/detail$',
|
||||
views.DetailView.as_view(), name='detail'),
|
||||
]
|
95
watcher_dashboard/content/goals/views.py
Normal file
95
watcher_dashboard/content/goals/views.py
Normal file
@ -0,0 +1,95 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2016 b<>com
|
||||
#
|
||||
# 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 django.utils.translation import ugettext_lazy as _
|
||||
import horizon.exceptions
|
||||
import horizon.tables
|
||||
import horizon.tabs
|
||||
from horizon.utils import memoized
|
||||
import horizon.workflows
|
||||
|
||||
from watcher_dashboard.api import watcher
|
||||
from watcher_dashboard.content.goals import tables
|
||||
from watcher_dashboard.content.goals import tabs as wtabs
|
||||
|
||||
|
||||
class IndexView(horizon.tables.DataTableView):
|
||||
table_class = tables.GoalsTable
|
||||
template_name = 'infra_optim/goals/index.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(IndexView, self).get_context_data(**kwargs)
|
||||
context['goals_count'] = self.get_goals_count()
|
||||
return context
|
||||
|
||||
def get_data(self):
|
||||
goals = []
|
||||
search_opts = self.get_filters()
|
||||
try:
|
||||
goals = watcher.Goal.list(self.request, **search_opts)
|
||||
except Exception:
|
||||
horizon.exceptions.handle(
|
||||
self.request,
|
||||
_("Unable to retrieve goal information."))
|
||||
return goals
|
||||
|
||||
def get_goals_count(self):
|
||||
return len(self.get_data())
|
||||
|
||||
def get_filters(self):
|
||||
filters = {}
|
||||
filter_action = self.table._meta._filter_action
|
||||
if filter_action:
|
||||
filter_field = self.table.get_filter_field()
|
||||
if filter_action.is_api_filter(filter_field):
|
||||
filter_string = self.table.get_filter_string()
|
||||
if filter_field and filter_string:
|
||||
filters[filter_field] = filter_string
|
||||
return filters
|
||||
|
||||
|
||||
class DetailView(horizon.tabs.TabbedTableView):
|
||||
tab_group_class = wtabs.GoalDetailTabs
|
||||
template_name = 'infra_optim/goals/details.html'
|
||||
redirect_url = 'horizon:admin:goals:index'
|
||||
page_title = _("Goal Details: {{ goal.name }}")
|
||||
|
||||
@memoized.memoized_method
|
||||
def _get_data(self):
|
||||
goal_uuid = None
|
||||
try:
|
||||
goal_uuid = self.kwargs['goal_uuid']
|
||||
goal = watcher.Goal.get(self.request, goal_uuid)
|
||||
except Exception:
|
||||
msg = _('Unable to retrieve details for goal "%s".') \
|
||||
% goal_uuid
|
||||
horizon.exceptions.handle(
|
||||
self.request, msg,
|
||||
redirect=self.redirect_url)
|
||||
return goal
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(DetailView, self).get_context_data(**kwargs)
|
||||
goal = self._get_data()
|
||||
context["goal"] = goal
|
||||
return context
|
||||
|
||||
def get_tabs(self, request, *args, **kwargs):
|
||||
goal = self._get_data()
|
||||
# ports = self._get_ports()
|
||||
return self.tab_group_class(request, goal=goal,
|
||||
# ports=ports,
|
||||
**kwargs)
|
0
watcher_dashboard/content/strategies/__init__.py
Normal file
0
watcher_dashboard/content/strategies/__init__.py
Normal file
0
watcher_dashboard/content/strategies/forms.py
Normal file
0
watcher_dashboard/content/strategies/forms.py
Normal file
23
watcher_dashboard/content/strategies/panel.py
Normal file
23
watcher_dashboard/content/strategies/panel.py
Normal file
@ -0,0 +1,23 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2016 b<>com
|
||||
#
|
||||
# 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 django.utils.translation import ugettext_lazy as _
|
||||
import horizon
|
||||
|
||||
|
||||
class Strategies(horizon.Panel):
|
||||
name = _("Strategies")
|
||||
slug = "strategies"
|
44
watcher_dashboard/content/strategies/tables.py
Normal file
44
watcher_dashboard/content/strategies/tables.py
Normal file
@ -0,0 +1,44 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2016 b<>com
|
||||
#
|
||||
# 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 django.template.defaultfilters import title # noqa
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
import horizon.exceptions
|
||||
import horizon.messages
|
||||
import horizon.tables
|
||||
from horizon.utils import filters
|
||||
|
||||
|
||||
class StrategiesTable(horizon.tables.DataTable):
|
||||
uuid = horizon.tables.Column(
|
||||
'uuid',
|
||||
verbose_name=_("UUID"),
|
||||
link="horizon:admin:strategies:detail")
|
||||
display_name = horizon.tables.Column(
|
||||
'display_name',
|
||||
verbose_name=_('Name'),
|
||||
filters=(title, filters.replace_underscores))
|
||||
goal_uuid = horizon.tables.Column(
|
||||
'goal_uuid',
|
||||
verbose_name=_("Goal UUID"),
|
||||
)
|
||||
|
||||
def get_object_id(self, datum):
|
||||
return datum.uuid
|
||||
|
||||
class Meta(object):
|
||||
name = "strategies"
|
||||
verbose_name = _("Strategies")
|
33
watcher_dashboard/content/strategies/tabs.py
Normal file
33
watcher_dashboard/content/strategies/tabs.py
Normal file
@ -0,0 +1,33 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2016 b<>com
|
||||
#
|
||||
# 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 django.utils.translation import ugettext_lazy as _
|
||||
from horizon import tabs
|
||||
|
||||
|
||||
class OverviewTab(tabs.Tab):
|
||||
name = _("Overview")
|
||||
slug = "overview"
|
||||
template_name = "infra_optim/strategies/_detail_overview.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
return {"strategy": self.tab_group.kwargs['strategy']}
|
||||
|
||||
|
||||
class StrategyDetailTabs(tabs.TabGroup):
|
||||
slug = "strategy_details"
|
||||
tabs = (OverviewTab,)
|
||||
sticky = True
|
93
watcher_dashboard/content/strategies/tests.py
Normal file
93
watcher_dashboard/content/strategies/tests.py
Normal file
@ -0,0 +1,93 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2016 b<>com
|
||||
#
|
||||
# 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 logging
|
||||
|
||||
from django.core import urlresolvers
|
||||
from django import http
|
||||
from mox3.mox import IsA # noqa
|
||||
|
||||
from watcher_dashboard import api
|
||||
from watcher_dashboard.test import helpers as test
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
INDEX_URL = urlresolvers.reverse(
|
||||
'horizon:admin:strategies:index')
|
||||
DETAILS_VIEW = 'horizon:admin:strategies:detail'
|
||||
|
||||
|
||||
class StrategiesTest(test.BaseAdminViewTests):
|
||||
|
||||
goal_list = [
|
||||
'BASIC_CONSOLIDATION',
|
||||
'MINIMIZE_ENERGY_CONSUMPTION',
|
||||
'BALANCE_LOAD',
|
||||
'MINIMIZE_LICENSING_COST',
|
||||
'PREPARED_PLAN_OPERATION',
|
||||
]
|
||||
|
||||
@test.create_stubs({api.watcher.Strategy: ('list',)})
|
||||
def test_index(self):
|
||||
search_opts = {}
|
||||
api.watcher.Strategy.list(
|
||||
IsA(http.HttpRequest), **search_opts
|
||||
).MultipleTimes().AndReturn(self.strategies.list())
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(INDEX_URL)
|
||||
self.assertTemplateUsed(res, 'infra_optim/strategies/index.html')
|
||||
strategies = res.context['strategies_table'].data
|
||||
self.assertItemsEqual(strategies, self.strategies.list())
|
||||
|
||||
@test.create_stubs({api.watcher.Strategy: ('list',)})
|
||||
def test_strategy_list_unavailable(self):
|
||||
search_opts = {}
|
||||
api.watcher.Strategy.list(
|
||||
IsA(http.HttpRequest), **search_opts).MultipleTimes().AndRaise(
|
||||
self.exceptions.watcher)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
resp = self.client.get(INDEX_URL)
|
||||
self.assertMessageCount(resp, error=1, warning=0)
|
||||
|
||||
@test.create_stubs({api.watcher.Strategy: ('get',)})
|
||||
def test_details(self):
|
||||
at = self.strategies.first()
|
||||
at_id = at.uuid
|
||||
api.watcher.Strategy.get(
|
||||
IsA(http.HttpRequest), at_id).\
|
||||
MultipleTimes().AndReturn(at)
|
||||
self.mox.ReplayAll()
|
||||
DETAILS_URL = urlresolvers.reverse(DETAILS_VIEW, args=[at_id])
|
||||
res = self.client.get(DETAILS_URL)
|
||||
self.assertTemplateUsed(res,
|
||||
'infra_optim/strategies/details.html')
|
||||
strategies = res.context['strategy']
|
||||
self.assertItemsEqual([strategies], [at])
|
||||
|
||||
@test.create_stubs({api.watcher.Strategy: ('get',)})
|
||||
def test_details_exception(self):
|
||||
at = self.strategies.first()
|
||||
at_id = at.uuid
|
||||
api.watcher.Strategy.get(IsA(http.HttpRequest), at_id) \
|
||||
.AndRaise(self.exceptions.watcher)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
DETAILS_URL = urlresolvers.reverse(DETAILS_VIEW, args=[at_id])
|
||||
res = self.client.get(DETAILS_URL)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
27
watcher_dashboard/content/strategies/urls.py
Normal file
27
watcher_dashboard/content/strategies/urls.py
Normal file
@ -0,0 +1,27 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2016 b<>com
|
||||
#
|
||||
# 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 django.conf import urls
|
||||
|
||||
from watcher_dashboard.content.strategies import views
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
urls.url(r'^$',
|
||||
views.IndexView.as_view(), name='index'),
|
||||
urls.url(r'^(?P<strategy_uuid>[^/]+)/detail$',
|
||||
views.DetailView.as_view(), name='detail'),
|
||||
]
|
95
watcher_dashboard/content/strategies/views.py
Normal file
95
watcher_dashboard/content/strategies/views.py
Normal file
@ -0,0 +1,95 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2016 b<>com
|
||||
#
|
||||
# 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 django.utils.translation import ugettext_lazy as _
|
||||
import horizon.exceptions
|
||||
import horizon.tables
|
||||
import horizon.tabs
|
||||
from horizon.utils import memoized
|
||||
import horizon.workflows
|
||||
|
||||
from watcher_dashboard.api import watcher
|
||||
from watcher_dashboard.content.strategies import tables
|
||||
from watcher_dashboard.content.strategies import tabs as wtabs
|
||||
|
||||
|
||||
class IndexView(horizon.tables.DataTableView):
|
||||
table_class = tables.StrategiesTable
|
||||
template_name = 'infra_optim/strategies/index.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(IndexView, self).get_context_data(**kwargs)
|
||||
context['strategies_count'] = self.get_strategies_count()
|
||||
return context
|
||||
|
||||
def get_data(self):
|
||||
strategies = []
|
||||
search_opts = self.get_filters()
|
||||
try:
|
||||
strategies = watcher.Strategy.list(self.request, **search_opts)
|
||||
except Exception:
|
||||
horizon.exceptions.handle(
|
||||
self.request,
|
||||
_("Unable to retrieve strategy information."))
|
||||
return strategies
|
||||
|
||||
def get_strategies_count(self):
|
||||
return len(self.get_data())
|
||||
|
||||
def get_filters(self):
|
||||
filters = {}
|
||||
filter_action = self.table._meta._filter_action
|
||||
if filter_action:
|
||||
filter_field = self.table.get_filter_field()
|
||||
if filter_action.is_api_filter(filter_field):
|
||||
filter_string = self.table.get_filter_string()
|
||||
if filter_field and filter_string:
|
||||
filters[filter_field] = filter_string
|
||||
return filters
|
||||
|
||||
|
||||
class DetailView(horizon.tabs.TabbedTableView):
|
||||
tab_group_class = wtabs.StrategyDetailTabs
|
||||
template_name = 'infra_optim/strategies/details.html'
|
||||
redirect_url = 'horizon:admin:strategies:index'
|
||||
page_title = _("Strategy Details: {{ strategy.name }}")
|
||||
|
||||
@memoized.memoized_method
|
||||
def _get_data(self):
|
||||
strategy_uuid = None
|
||||
try:
|
||||
strategy_uuid = self.kwargs['strategy_uuid']
|
||||
strategy = watcher.Strategy.get(self.request, strategy_uuid)
|
||||
except Exception:
|
||||
msg = _('Unable to retrieve details for strategy "%s".') \
|
||||
% strategy_uuid
|
||||
horizon.exceptions.handle(
|
||||
self.request, msg,
|
||||
redirect=self.redirect_url)
|
||||
return strategy
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(DetailView, self).get_context_data(**kwargs)
|
||||
strategy = self._get_data()
|
||||
context["strategy"] = strategy
|
||||
return context
|
||||
|
||||
def get_tabs(self, request, *args, **kwargs):
|
||||
strategy = self._get_data()
|
||||
# ports = self._get_ports()
|
||||
return self.tab_group_class(request, strategy=strategy,
|
||||
# ports=ports,
|
||||
**kwargs)
|
21
watcher_dashboard/enabled/_31000_goals_panel.py
Normal file
21
watcher_dashboard/enabled/_31000_goals_panel.py
Normal file
@ -0,0 +1,21 @@
|
||||
# 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.
|
||||
|
||||
# The slug of the panel to be added to HORIZON_CONFIG. Required.
|
||||
PANEL = 'goals'
|
||||
# The slug of the dashboard the PANEL associated with. Required.
|
||||
PANEL_DASHBOARD = 'admin'
|
||||
# The slug of the panel group the PANEL is associated with.
|
||||
PANEL_GROUP = 'watcher'
|
||||
|
||||
# Python panel class of the PANEL to be added.
|
||||
ADD_PANEL = 'watcher_dashboard.content.goals.panel.Goals'
|
21
watcher_dashboard/enabled/_31010_strategies_panel.py
Normal file
21
watcher_dashboard/enabled/_31010_strategies_panel.py
Normal file
@ -0,0 +1,21 @@
|
||||
# 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.
|
||||
|
||||
# The slug of the panel to be added to HORIZON_CONFIG. Required.
|
||||
PANEL = 'strategies'
|
||||
# The slug of the dashboard the PANEL associated with. Required.
|
||||
PANEL_DASHBOARD = 'admin'
|
||||
# The slug of the panel group the PANEL is associated with.
|
||||
PANEL_GROUP = 'watcher'
|
||||
|
||||
# Python panel class of the PANEL to be added.
|
||||
ADD_PANEL = 'watcher_dashboard.content.strategies.panel.Strategies'
|
@ -16,8 +16,6 @@ PANEL = 'audit_templates'
|
||||
PANEL_DASHBOARD = 'admin'
|
||||
# The slug of the panel group the PANEL is associated with.
|
||||
PANEL_GROUP = 'watcher'
|
||||
# If set, it will update the default panel of the PANEL_DASHBOARD.
|
||||
DEFAULT_PANEL = 'audit_templates'
|
||||
|
||||
# Python panel class of the PANEL to be added.
|
||||
ADD_PANEL = 'watcher_dashboard.content.audit_templates.panel.AuditTemplates'
|
@ -16,8 +16,6 @@ PANEL = 'audits'
|
||||
PANEL_DASHBOARD = 'admin'
|
||||
# The slug of the panel group the PANEL is associated with.
|
||||
PANEL_GROUP = 'watcher'
|
||||
# If set, it will update the default panel of the PANEL_DASHBOARD.
|
||||
DEFAULT_PANEL = 'audits'
|
||||
|
||||
# Python panel class of the PANEL to be added.
|
||||
ADD_PANEL = 'watcher_dashboard.content.audits.panel.Audits'
|
@ -16,8 +16,6 @@ PANEL = 'action_plans'
|
||||
PANEL_DASHBOARD = 'admin'
|
||||
# The slug of the panel group the PANEL is associated with.
|
||||
PANEL_GROUP = 'watcher'
|
||||
# If set, it will update the default panel of the PANEL_DASHBOARD.
|
||||
DEFAULT_PANEL = 'action_plans'
|
||||
|
||||
# Python panel class of the PANEL to be added.
|
||||
ADD_PANEL = 'watcher_dashboard.content.action_plans.panel.ActionPlans'
|
@ -16,8 +16,6 @@ PANEL = 'actions'
|
||||
PANEL_DASHBOARD = 'admin'
|
||||
# The slug of the panel group the PANEL is associated with.
|
||||
PANEL_GROUP = 'watcher'
|
||||
# If set, it will update the default panel of the PANEL_DASHBOARD.
|
||||
DEFAULT_PANEL = 'actions'
|
||||
|
||||
# Python panel class of the PANEL to be added.
|
||||
ADD_PANEL = 'watcher_dashboard.content.actions.panel.Actions'
|
@ -1,3 +1,3 @@
|
||||
/* Additional CSS for infra_optim. */
|
||||
@import "/dashboard/scss/variables";
|
||||
@import "/bootstrap/scss/bootstrap/variables";
|
||||
// /* Additional CSS for infra_optim. */
|
||||
// @import "/dashboard/scss/variables";
|
||||
// @import "/bootstrap/scss/bootstrap/variables";
|
||||
|
@ -11,7 +11,7 @@
|
||||
<div class="detail col-md-6">
|
||||
<h4>{% trans "Audit Info" %}</h4>
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dt>{% trans "UUID" %}</dt>
|
||||
<dd>{{ action.uuid|default:"—" }}</dd>
|
||||
<dt>{% trans "Type" %}</dt>
|
||||
<dd>{{ action.type|default:"—" }}</dd>
|
||||
|
@ -4,4 +4,7 @@
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Creates an audit template with specified parameters." %}</p>
|
||||
<p>
|
||||
<span>{% trans "Define the optimization goal to achieve, among those which are available." %}</span>
|
||||
<span>{% trans "Optionaly, you can select the strategy used to achieve your goal. If not set, a strategy will be automatically selected among those which can be used for your goal" %}</span></p>
|
||||
{% endblock %}
|
@ -1,11 +1,11 @@
|
||||
{% extends 'infra_optim/base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans 'Audit Templates: ' %}{{ audit_template.name }}{% endblock %}
|
||||
|
||||
|
||||
{% block page_header %}
|
||||
{% include 'horizon/common/_page_header.html' with title=_('Audit Templates: ')|add:audit_template.name %}
|
||||
{% endblock page_header %}
|
||||
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="detail col-md-6">
|
||||
@ -13,10 +13,12 @@
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "Name" %}</dt>
|
||||
<dd>{{ audit_template.name|default:"—" }}</dd>
|
||||
<dt>{% trans "Id" %}</dt>
|
||||
<dt>{% trans "UUID" %}</dt>
|
||||
<dd>{{ audit_template.uuid|default:"—" }}</dd>
|
||||
<dt>{% trans "Goal" %}</dt>
|
||||
<dd>{{ audit_template.goal|default:"—" }}</dd>
|
||||
<dt>{% trans "Goal UUID" %}</dt>
|
||||
<dd>{{ audit_template.goal_uuid|default:"—" }}</dd>
|
||||
<dt>{% trans "Strategy UUID" %}</dt>
|
||||
<dd>{{ audit_template.strategy_uuid|default:"—" }}</dd>
|
||||
<dt>{% trans "Created At" %}</dt>
|
||||
<dd>{{ audit_template.created_at|default:"—" }}</dd>
|
||||
<dt>{% trans "Update At" %}</dt>
|
||||
@ -31,5 +33,5 @@
|
||||
{{ table.render }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
@ -1,17 +1,17 @@
|
||||
{% extends 'infra_optim/base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans 'Audits: ' %}{{ audit.uuid }}{% endblock %}
|
||||
|
||||
|
||||
{% block page_header %}
|
||||
{% include 'horizon/common/_page_header.html' with title=_('Audits: ')|add:audit.uuid %}
|
||||
{% endblock page_header %}
|
||||
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="detail col-md-6">
|
||||
<h4>{% trans "Audit Info" %}</h4>
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dt>{% trans "UUID" %}</dt>
|
||||
<dd>{{ audit.uuid|default:"—" }}</dd>
|
||||
<dt>{% trans "Type" %}</dt>
|
||||
<dd>{{ audit.type|default:"—" }}</dd>
|
||||
@ -34,5 +34,5 @@
|
||||
{{ table.render }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
31
watcher_dashboard/templates/infra_optim/goals/details.html
Normal file
31
watcher_dashboard/templates/infra_optim/goals/details.html
Normal file
@ -0,0 +1,31 @@
|
||||
{% extends 'infra_optim/base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans 'Goals: ' %}{{ goal.display_name }}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include 'horizon/common/_page_header.html' with title=_('Goals: ')|add:goal.display_name %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="detail col-md-6">
|
||||
<h4>{% trans "Goal Info" %}</h4>
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "UUID" %}</dt>
|
||||
<dd>{{ goal.uuid|default:"—" }}</dd>
|
||||
<dt>{% trans "Name" %}</dt>
|
||||
<dd>{{ goal.display_name|default:"—" }}</dd>
|
||||
<dt>{% trans "Created At" %}</dt>
|
||||
<dd>{{ goal.created_at|default:"—" }}</dd>
|
||||
<dt>{% trans "Update At" %}</dt>
|
||||
<dd>{{ goal.updated_at|default:"—" }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
{{ table.render }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
14
watcher_dashboard/templates/infra_optim/goals/index.html
Normal file
14
watcher_dashboard/templates/infra_optim/goals/index.html
Normal file
@ -0,0 +1,14 @@
|
||||
{% extends 'infra_optim/base.html' %}
|
||||
{% load i18n %}
|
||||
{% load url from future %}
|
||||
{% block title %}{% trans 'Goals' %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include 'horizon/common/_page_header.html' with title=_('Goals') items_count=goal_count %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div id="goals">
|
||||
{{ goals_table.render }}
|
||||
</div>
|
||||
{% endblock %}
|
@ -0,0 +1,34 @@
|
||||
{% extends 'infra_optim/base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans 'Strategies: ' %}{{ strategy.display_name }}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include 'horizon/common/_page_header.html' with title=_('Strategies: ')|add:strategy.display_name %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="detail col-md-6">
|
||||
<h4>{% trans "Strategy Info" %}</h4>
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "UUID" %}</dt>
|
||||
<dd>{{ strategy.uuid|default:"—" }}</dd>
|
||||
<dt>{% trans "Name" %}</dt>
|
||||
<dd>{{ strategy.display_name|default:"—" }}</dd>
|
||||
<dt>{% trans "Goal UUID" %}</dt>
|
||||
{% url 'horizon:admin:goals:detail' strategy.goal_uuid as goal_url %}
|
||||
<dd><a href="{{ goal_url }}">{{ strategy.goal_uuid|default:"—" }}</a></dd>
|
||||
<dt>{% trans "Created At" %}</dt>
|
||||
<dd>{{ strategy.created_at|default:"—" }}</dd>
|
||||
<dt>{% trans "Update At" %}</dt>
|
||||
<dd>{{ strategy.updated_at|default:"—" }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
{{ table.render }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -0,0 +1,14 @@
|
||||
{% extends 'infra_optim/base.html' %}
|
||||
{% load i18n %}
|
||||
{% load url from future %}
|
||||
{% block title %}{% trans 'Strategies' %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include 'horizon/common/_page_header.html' with title=_('Strategies') items_count=strategy_count %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div id="goals">
|
||||
{{ strategies_table.render }}
|
||||
</div>
|
||||
{% endblock %}
|
@ -21,37 +21,95 @@ from watcher_dashboard.test import helpers as test
|
||||
|
||||
class WatcherAPITests(test.APITestCase):
|
||||
|
||||
def test_goal_list(self):
|
||||
goals = {'goals': self.api_goals.list()}
|
||||
watcherclient = self.stub_watcherclient()
|
||||
|
||||
watcherclient.goal = self.mox.CreateMockAnything()
|
||||
watcherclient.goal.list(detail=True).AndReturn(goals)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.watcher.Goal.list(self.request)
|
||||
self.assertIsInstance(ret_val, dict)
|
||||
self.assertIn('goals', ret_val)
|
||||
for n in ret_val['goals']:
|
||||
self.assertIsInstance(n, dict)
|
||||
|
||||
def test_goal_get(self):
|
||||
goal = self.api_goals.first()
|
||||
goal_id = self.api_goals.first()['uuid']
|
||||
|
||||
watcherclient = self.stub_watcherclient()
|
||||
watcherclient.goal = self.mox.CreateMockAnything()
|
||||
watcherclient.goal.get(goal_id).AndReturn(goal)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.watcher.Goal.get(self.request, goal_id)
|
||||
self.assertIsInstance(ret_val, dict)
|
||||
|
||||
def test_strategy_list(self):
|
||||
strategies = {'strategies': self.api_strategies.list()}
|
||||
watcherclient = self.stub_watcherclient()
|
||||
|
||||
watcherclient.strategy = self.mox.CreateMockAnything()
|
||||
watcherclient.strategy.list(
|
||||
goal_uuid=None, detail=True).AndReturn(strategies)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.watcher.Strategy.list(self.request)
|
||||
self.assertIn('strategies', ret_val)
|
||||
for n in ret_val['strategies']:
|
||||
self.assertIsInstance(n, dict)
|
||||
|
||||
def test_strategy_get(self):
|
||||
strategy = self.api_strategies.first()
|
||||
strategy_id = self.api_strategies.first()['uuid']
|
||||
|
||||
watcherclient = self.stub_watcherclient()
|
||||
watcherclient.strategy = self.mox.CreateMockAnything()
|
||||
watcherclient.strategy.get(strategy_id).AndReturn(strategy)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.watcher.Strategy.get(self.request, strategy_id)
|
||||
self.assertIsInstance(ret_val, dict)
|
||||
|
||||
def test_audit_template_list(self):
|
||||
audit_templates = {'audit_templates': self.api_audit_templates.list()}
|
||||
watcherclient = self.stub_watcherclient()
|
||||
|
||||
watcherclient.audit_template = self.mox.CreateMockAnything()
|
||||
watcherclient.audit_template.list(name=None).AndReturn(audit_templates)
|
||||
watcherclient.audit_template.list().AndReturn(audit_templates)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.watcher.AuditTemplate.list(self.request, filter=None)
|
||||
for n in ret_val:
|
||||
self.assertTrue(type(n), 'dict')
|
||||
ret_val = api.watcher.AuditTemplate.list(self.request)
|
||||
|
||||
self.assertIn('audit_templates', ret_val)
|
||||
for n in ret_val['audit_templates']:
|
||||
self.assertIsInstance(n, dict)
|
||||
|
||||
def test_audit_template_list_with_filters(self):
|
||||
search_opts = 'Audit Template 1'
|
||||
audit_templates = self.api_audit_templates.filter(name=search_opts)
|
||||
search_opts = {'name': 'Audit Template 1'}
|
||||
audit_templates = {
|
||||
'audit_templates': self.api_audit_templates.filter(**search_opts)}
|
||||
watcherclient = self.stub_watcherclient()
|
||||
|
||||
watcherclient.audit_template = self.mox.CreateMockAnything()
|
||||
|
||||
watcherclient.audit_template.list(name=search_opts)\
|
||||
.AndReturn(audit_templates)
|
||||
watcherclient.audit_template.list(
|
||||
**search_opts).AndReturn(audit_templates)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.watcher.AuditTemplate\
|
||||
.list(self.request, filter=search_opts)
|
||||
for n in ret_val:
|
||||
self.assertTrue(type(n), 'dict')
|
||||
ret_val = api.watcher.AuditTemplate.list(
|
||||
self.request, **search_opts)
|
||||
|
||||
self.assertIn('audit_templates', ret_val)
|
||||
for n in ret_val['audit_templates']:
|
||||
self.assertIsInstance(n, dict)
|
||||
|
||||
self.assertEqual(ret_val, audit_templates)
|
||||
|
||||
def test_audit_template_get(self):
|
||||
audit_template = {'audit_template': self.api_audit_templates.first()}
|
||||
audit_template = self.api_audit_templates.first()
|
||||
audit_template_id = self.api_audit_templates.first()['uuid']
|
||||
|
||||
watcherclient = self.stub_watcherclient()
|
||||
@ -62,30 +120,33 @@ class WatcherAPITests(test.APITestCase):
|
||||
|
||||
ret_val = api.watcher.AuditTemplate.get(self.request,
|
||||
audit_template_id)
|
||||
self.assertTrue(type(ret_val), 'dict')
|
||||
self.assertIsInstance(ret_val, dict)
|
||||
|
||||
def test_audit_template_create(self):
|
||||
audit_template = {'audit_template': self.api_audit_templates.first()}
|
||||
name = self.api_audit_templates.first()['name']
|
||||
goal = self.api_audit_templates.first()['goal']
|
||||
description = self.api_audit_templates.first()['description']
|
||||
host_aggregate = self.api_audit_templates.first()['host_aggregate']
|
||||
audit_template = self.api_audit_templates.first()
|
||||
name = audit_template['name']
|
||||
goal_uuid = audit_template['goal_uuid']
|
||||
strategy_uuid = audit_template['strategy_uuid']
|
||||
description = audit_template['description']
|
||||
host_aggregate = audit_template['host_aggregate']
|
||||
|
||||
watcherclient = self.stub_watcherclient()
|
||||
watcherclient.audit_template = self.mox.CreateMockAnything()
|
||||
watcherclient.audit_template.create(
|
||||
name=name,
|
||||
goal=goal,
|
||||
goal_uuid=goal_uuid,
|
||||
strategy_uuid=strategy_uuid,
|
||||
description=description,
|
||||
host_aggregate=host_aggregate).AndReturn(audit_template)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.watcher.AuditTemplate.create(
|
||||
self.request, name, goal, description, host_aggregate)
|
||||
self.assertTrue(type(ret_val), 'dict')
|
||||
self.request, name, goal_uuid, strategy_uuid,
|
||||
description, host_aggregate)
|
||||
self.assertIsInstance(ret_val, dict)
|
||||
|
||||
def test_audit_template_patch(self):
|
||||
audit_template = {'audit_template': self.api_audit_templates.first()}
|
||||
audit_template = self.api_audit_templates.first()
|
||||
audit_template_id = self.api_audit_templates.first()['uuid']
|
||||
form_data = {'name': 'new Audit Template 1'}
|
||||
|
||||
@ -100,7 +161,7 @@ class WatcherAPITests(test.APITestCase):
|
||||
ret_val = api.watcher.AuditTemplate.patch(
|
||||
self.request, audit_template_id,
|
||||
form_data)
|
||||
self.assertTrue(type(ret_val), 'dict')
|
||||
self.assertIsInstance(ret_val, dict)
|
||||
|
||||
def test_audit_template_delete(self):
|
||||
audit_template_list = self.api_audit_templates.list()
|
||||
@ -127,26 +188,26 @@ class WatcherAPITests(test.APITestCase):
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.watcher.Audit.list(
|
||||
self.request,
|
||||
audit_template_filter=None)
|
||||
for n in ret_val:
|
||||
self.assertIsInstance(n, api.watcher.Audit)
|
||||
self.request, audit_template_filter=None)
|
||||
|
||||
self.assertIn('audits', ret_val)
|
||||
for n in ret_val['audits']:
|
||||
self.assertIsInstance(n, dict)
|
||||
|
||||
def test_audit_get(self):
|
||||
audit = {'audit': self.api_audits.first()}
|
||||
audit_id = self.api_audits.first()['id']
|
||||
audit = self.api_audits.first()
|
||||
audit_id = self.api_audits.first()['uuid']
|
||||
|
||||
watcherclient = self.stub_watcherclient()
|
||||
watcherclient.audit = self.mox.CreateMockAnything()
|
||||
watcherclient.audit.get(
|
||||
audit_id=audit_id).AndReturn(audit)
|
||||
watcherclient.audit.get(audit_id=audit_id).AndReturn(audit)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.watcher.Audit.get(self.request, audit_id)
|
||||
self.assertIsInstance(ret_val, api.watcher.Audit)
|
||||
self.assertIsInstance(ret_val, dict)
|
||||
|
||||
def test_audit_create(self):
|
||||
audit = {'audit': self.api_audits.first()}
|
||||
audit = self.api_audits.first()
|
||||
audit_template_id = self.api_audit_templates.first()['uuid']
|
||||
|
||||
deadline = self.api_audits.first()['deadline']
|
||||
@ -163,10 +224,10 @@ class WatcherAPITests(test.APITestCase):
|
||||
|
||||
ret_val = api.watcher.Audit.create(
|
||||
self.request, audit_template_uuid, _type, deadline)
|
||||
self.assertIsInstance(ret_val, api.watcher.Audit)
|
||||
self.assertIsInstance(ret_val, dict)
|
||||
|
||||
def test_audit_delete(self):
|
||||
audit_id = self.api_audits.first()['id']
|
||||
audit_id = self.api_audits.first()['uuid']
|
||||
|
||||
watcherclient = self.stub_watcherclient()
|
||||
watcherclient.audit = self.mox.CreateMockAnything()
|
||||
@ -185,15 +246,15 @@ class WatcherAPITests(test.APITestCase):
|
||||
watcherclient.action_plan.list(audit=None).AndReturn(action_plans)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.watcher.ActionPlan.list(
|
||||
self.request,
|
||||
audit_filter=None)
|
||||
for n in ret_val:
|
||||
self.assertIsInstance(n, api.watcher.ActionPlan)
|
||||
ret_val = api.watcher.ActionPlan.list(self.request, audit_filter=None)
|
||||
|
||||
self.assertIn('action_plans', ret_val)
|
||||
for n in ret_val['action_plans']:
|
||||
self.assertIsInstance(n, dict)
|
||||
|
||||
def test_action_plan_get(self):
|
||||
action_plan = {'action_plan': self.api_action_plans.first()}
|
||||
action_plan_id = self.api_action_plans.first()['id']
|
||||
action_plan = self.api_action_plans.first()
|
||||
action_plan_id = self.api_action_plans.first()['uuid']
|
||||
|
||||
watcherclient = self.stub_watcherclient()
|
||||
watcherclient.action_plan = self.mox.CreateMockAnything()
|
||||
@ -202,10 +263,10 @@ class WatcherAPITests(test.APITestCase):
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.watcher.ActionPlan.get(self.request, action_plan_id)
|
||||
self.assertIsInstance(ret_val, api.watcher.ActionPlan)
|
||||
self.assertIsInstance(ret_val, dict)
|
||||
|
||||
def test_action_plan_start(self):
|
||||
action_plan_id = self.api_action_plans.first()['id']
|
||||
action_plan_id = self.api_action_plans.first()['uuid']
|
||||
patch = []
|
||||
patch.append({'path': '/state', 'value': 'PENDING', 'op': 'replace'})
|
||||
|
||||
@ -217,7 +278,7 @@ class WatcherAPITests(test.APITestCase):
|
||||
api.watcher.ActionPlan.start(self.request, action_plan_id)
|
||||
|
||||
def test_action_plan_delete(self):
|
||||
action_plan_id = self.api_action_plans.first()['id']
|
||||
action_plan_id = self.api_action_plans.first()['uuid']
|
||||
|
||||
watcherclient = self.stub_watcherclient()
|
||||
watcherclient.action_plan = self.mox.CreateMockAnything()
|
||||
@ -237,7 +298,8 @@ class WatcherAPITests(test.APITestCase):
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.watcher.Action.list(
|
||||
self.request,
|
||||
action_plan_filter=None)
|
||||
for n in ret_val:
|
||||
self.assertIsInstance(n, api.watcher.Action)
|
||||
self.request, action_plan_filter=None)
|
||||
|
||||
self.assertIn('actions', ret_val)
|
||||
for n in ret_val['actions']:
|
||||
self.assertIsInstance(n, dict)
|
||||
|
@ -223,7 +223,7 @@ class TestCase(horizon_helpers.TestCase):
|
||||
Asserts that the given response issued a 302 redirect without
|
||||
processing the view which is redirected to.
|
||||
"""
|
||||
assert (response.status_code / 100 == 3), \
|
||||
assert (300 <= response.status_code < 400), \
|
||||
"The response did not return a redirect."
|
||||
self.assertEqual(response._headers.get('location', None),
|
||||
('Location', settings.TESTSERVER + expected_url))
|
||||
|
@ -29,7 +29,7 @@ class AuditsTable(tables.TableRegion):
|
||||
launch_button.click()
|
||||
return forms.BaseFormRegion(self.driver, self.conf)
|
||||
|
||||
@tables.bind_row_action('go_to_action_plan', primary=True)
|
||||
@tables.bind_row_action('go_to_action_plan')
|
||||
def go_to_action_plan(self, goto_button):
|
||||
goto_button.click()
|
||||
return forms.BaseFormRegion(self.driver, self.conf)
|
||||
|
@ -21,7 +21,8 @@ class AuditTemplatesTable(tables.TableRegion):
|
||||
|
||||
name = 'audit_templates'
|
||||
|
||||
CREATE_AUDIT_TEMPLATE_FORM_FIELDS = ("name", "description", "goal")
|
||||
CREATE_AUDIT_TEMPLATE_FORM_FIELDS = ("name", "description",
|
||||
"goal_id", "strategy_id")
|
||||
|
||||
@tables.bind_table_action('create')
|
||||
def create_audit_template(self, create_button):
|
||||
@ -35,7 +36,7 @@ class AuditTemplatesTable(tables.TableRegion):
|
||||
delete_button.click()
|
||||
return forms.BaseFormRegion(self.driver, self.conf, None)
|
||||
|
||||
@tables.bind_row_action('launch_audit', primary=True)
|
||||
@tables.bind_row_action('launch_audit')
|
||||
def launch_audit(self, launch_button, row):
|
||||
launch_button.click()
|
||||
return forms.BaseFormRegion(self.driver, self.conf)
|
||||
@ -44,7 +45,7 @@ class AuditTemplatesTable(tables.TableRegion):
|
||||
class AudittemplatesPage(basepage.BaseNavigationPage):
|
||||
|
||||
DEFAULT_DESCRIPTION = "Fake description from integration tests"
|
||||
DEFAULT_GOAL = "BASIC_CONSOLIDATION"
|
||||
DEFAULT_GOAL = "SERVER_CONSOLIDATION"
|
||||
|
||||
AUDITS_PAGE_TITLE = "Audits - OpenStack Dashboard"
|
||||
|
||||
@ -86,11 +87,11 @@ class AudittemplatesPage(basepage.BaseNavigationPage):
|
||||
def create_audit_template(self,
|
||||
name,
|
||||
description=DEFAULT_DESCRIPTION,
|
||||
goal=DEFAULT_GOAL):
|
||||
goal_id=DEFAULT_GOAL):
|
||||
self.audittemplates_table.create_audit_template()
|
||||
self.audit_templates__action_create_form.name.text = name
|
||||
self.audit_templates__action_create_form.description.text = description
|
||||
self.audit_templates__action_create_form.goal.value = goal
|
||||
self.audit_templates__action_create_form.goal_id.value = goal_id
|
||||
self.audit_templates__action_create_form.submit()
|
||||
|
||||
def is_audit_template_present(self, name):
|
||||
|
@ -10,7 +10,6 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import unittest
|
||||
import uuid
|
||||
|
||||
from openstack_dashboard.test.integration_tests import helpers
|
||||
@ -66,7 +65,6 @@ class AuditTemplatePanelTests(helpers.AdminTestCase):
|
||||
audit_template_page.show_audit_template_info(
|
||||
self.audit_template_name))
|
||||
|
||||
@unittest.skip(reason="https://bugs.launchpad.net/horizon/+bug/1537526")
|
||||
def test_launch_audit(self):
|
||||
"""Test the audit template panel "Launch Audit" row button
|
||||
|
||||
|
@ -34,6 +34,50 @@ def data(TEST):
|
||||
"publicURL": "http://public.watcher2.example.com:9322"}]},
|
||||
)
|
||||
|
||||
TEST.goals = utils.TestDataContainer()
|
||||
TEST.api_goals = utils.TestDataContainer()
|
||||
goal_dict1 = {
|
||||
'uuid': 'gggggggg-1111-1111-1111-gggggggggggg',
|
||||
'name': 'MINIMIZE_LICENSING_COST',
|
||||
'display_name': 'Dummy',
|
||||
}
|
||||
goal_dict2 = {
|
||||
'uuid': 'gggggggg-2222-2222-2222-gggggggggggg',
|
||||
'name': 'SERVER_CONSOLIDATION',
|
||||
'display_name': 'Server consolidation',
|
||||
}
|
||||
TEST.api_goals.add(goal_dict1)
|
||||
TEST.api_goals.add(goal_dict2)
|
||||
_goal_dict1 = copy.deepcopy(goal_dict1)
|
||||
_goal_dict2 = copy.deepcopy(goal_dict2)
|
||||
|
||||
TEST.strategies = utils.TestDataContainer()
|
||||
TEST.api_strategies = utils.TestDataContainer()
|
||||
strategy_dict1 = {
|
||||
'uuid': 'ssssssss-1111-1111-1111-ssssssssssss',
|
||||
'name': 'minimize_licensing_cost1',
|
||||
'goal_uuid': 'gggggggg-1111-1111-1111-gggggggggggg',
|
||||
'display_name': 'Fake licensing cost strategy1',
|
||||
}
|
||||
strategy_dict2 = {
|
||||
'uuid': 'ssssssss-2222-2222-2222-ssssssssssss',
|
||||
'name': 'minimize_licensing_cost2',
|
||||
'goal_uuid': 'gggggggg-1111-1111-1111-gggggggggggg',
|
||||
'display_name': 'Fake licensing cost strategy2',
|
||||
}
|
||||
strategy_dict3 = {
|
||||
'uuid': 'ssssssss-3333-3333-3333-ssssssssssss',
|
||||
'name': 'sercon',
|
||||
'goal_uuid': 'gggggggg-2222-2222-2222-gggggggggggg',
|
||||
'display_name': 'Fake Sercon',
|
||||
}
|
||||
TEST.api_strategies.add(strategy_dict1)
|
||||
TEST.api_strategies.add(strategy_dict2)
|
||||
TEST.api_strategies.add(strategy_dict3)
|
||||
_strategy_dict1 = copy.deepcopy(strategy_dict1)
|
||||
_strategy_dict2 = copy.deepcopy(strategy_dict2)
|
||||
_strategy_dict3 = copy.deepcopy(strategy_dict3)
|
||||
|
||||
TEST.audit_templates = utils.TestDataContainer()
|
||||
TEST.api_audit_templates = utils.TestDataContainer()
|
||||
audit_template_dict = {
|
||||
@ -42,7 +86,8 @@ def data(TEST):
|
||||
'description': 'Audit Template 1 description',
|
||||
'host_aggregate': None,
|
||||
'extra': {'automatic': False},
|
||||
'goal': 'MINIMIZE_LICENSING_COST'
|
||||
'goal_uuid': 'gggggggg-1111-1111-1111-gggggggggggg',
|
||||
'strategy_uuid': 'ssssssss-1111-1111-1111-ssssssssssss',
|
||||
}
|
||||
audit_template_dict2 = {
|
||||
'uuid': '11111111-2222-2222-2222-111111111111',
|
||||
@ -50,7 +95,8 @@ def data(TEST):
|
||||
'description': 'Audit Template 2 description',
|
||||
'host_aggregate': None,
|
||||
'extra': {'automatic': False},
|
||||
'goal': 'MINIMIZE_LICENSING_COST'
|
||||
'goal_uuid': 'gggggggg-1111-1111-1111-gggggggggggg',
|
||||
'strategy_uuid': 'ssssssss-2222-2222-2222-ssssssssssss',
|
||||
}
|
||||
audit_template_dict3 = {
|
||||
'uuid': '11111111-3333-3333-3333-111111111111',
|
||||
@ -58,7 +104,8 @@ def data(TEST):
|
||||
'description': 'Audit Template 3 description',
|
||||
'host_aggregate': None,
|
||||
'extra': {'automatic': False},
|
||||
'goal': 'MINIMIZE_LICENSING_COST'
|
||||
'goal_uuid': 'gggggggg-2222-2222-2222-gggggggggggg',
|
||||
'strategy_uuid': None,
|
||||
}
|
||||
TEST.api_audit_templates.add(audit_template_dict)
|
||||
TEST.api_audit_templates.add(audit_template_dict2)
|
||||
@ -67,13 +114,10 @@ def data(TEST):
|
||||
_audit_template_dict2 = copy.deepcopy(audit_template_dict2)
|
||||
_audit_template_dict3 = copy.deepcopy(audit_template_dict3)
|
||||
|
||||
TEST.goals = utils.TestDataContainer()
|
||||
TEST.api_goals = utils.TestDataContainer()
|
||||
|
||||
TEST.audits = utils.TestDataContainer()
|
||||
TEST.api_audits = utils.TestDataContainer()
|
||||
audit_dict = {
|
||||
'id': '22222222-2222-2222-2222-222222222222',
|
||||
'uuid': '22222222-2222-2222-2222-222222222222',
|
||||
'deadline': None,
|
||||
'type': 'ONESHOT',
|
||||
'audit_template_uuid': '11111111-1111-1111-1111-111111111111'
|
||||
@ -84,7 +128,7 @@ def data(TEST):
|
||||
TEST.action_plans = utils.TestDataContainer()
|
||||
TEST.api_action_plans = utils.TestDataContainer()
|
||||
action_plan_dict = {
|
||||
'id': '33333333-3333-3333-3333-333333333333',
|
||||
'uuid': '33333333-3333-3333-3333-333333333333',
|
||||
'state': 'RECOMMENDED',
|
||||
'first_action_uuid': '44444444-4444-4444-4444-111111111111',
|
||||
'audit_uuid': '22222222-2222-2222-2222-222222222222'
|
||||
@ -95,7 +139,7 @@ def data(TEST):
|
||||
TEST.actions = utils.TestDataContainer()
|
||||
TEST.api_actions = utils.TestDataContainer()
|
||||
action_dict1 = {
|
||||
'id': '44444444-4444-4444-4444-111111111111',
|
||||
'uuid': '44444444-4444-4444-4444-111111111111',
|
||||
'state': 'PENDING',
|
||||
'next_uuid': '44444444-4444-4444-4444-222222222222',
|
||||
'action_plan_uuid': '33333333-3333-3333-3333-333333333333'
|
||||
@ -103,7 +147,7 @@ def data(TEST):
|
||||
TEST.api_actions.add(action_dict1)
|
||||
|
||||
action_dict2 = {
|
||||
'id': '44444444-4444-4444-4444-222222222222',
|
||||
'uuid': '44444444-4444-4444-4444-222222222222',
|
||||
'state': 'PENDING',
|
||||
'next_uuid': None,
|
||||
'action_plan_uuid': '33333333-3333-3333-3333-333333333333'
|
||||
@ -121,11 +165,23 @@ def data(TEST):
|
||||
_audit_dict['action_plans'] = [action_plan]
|
||||
audit = watcher.Audit(_audit_dict)
|
||||
|
||||
# _audit_template_dict['audits'] = [audit]
|
||||
goal1 = watcher.Goal(_goal_dict1)
|
||||
goal2 = watcher.Goal(_goal_dict2)
|
||||
|
||||
strategy1 = watcher.Strategy(_strategy_dict1)
|
||||
strategy2 = watcher.Strategy(_strategy_dict2)
|
||||
strategy3 = watcher.Strategy(_strategy_dict3)
|
||||
|
||||
audit_template1 = watcher.AuditTemplate(_audit_template_dict)
|
||||
audit_template2 = watcher.AuditTemplate(_audit_template_dict2)
|
||||
audit_template3 = watcher.AuditTemplate(_audit_template_dict3)
|
||||
|
||||
TEST.goals.add(goal1)
|
||||
TEST.goals.add(goal2)
|
||||
TEST.strategies.add(strategy1)
|
||||
TEST.strategies.add(strategy2)
|
||||
TEST.strategies.add(strategy3)
|
||||
|
||||
TEST.audit_templates.add(audit_template1)
|
||||
TEST.audit_templates.add(audit_template2)
|
||||
TEST.audit_templates.add(audit_template3)
|
||||
|
@ -14,7 +14,6 @@
|
||||
from django.conf import urls
|
||||
import openstack_dashboard.urls
|
||||
|
||||
urlpatterns = urls.patterns(
|
||||
'',
|
||||
urlpatterns = [
|
||||
urls.url(r'', urls.include(openstack_dashboard.urls))
|
||||
)
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user