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: Ie8d8785ee0133650ac56c499abca0260309032ebchanges/16/301516/5 0.3.0
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,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"
|
|
@ -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")
|
|
@ -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
|
|
@ -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)
|
|
@ -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'),
|
||||
]
|
|
@ -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 |