253 lines
8.8 KiB
Python
253 lines
8.8 KiB
Python
# 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 triggers api."""
|
|
|
|
from datetime import datetime
|
|
from oslo_log import log as logging
|
|
from oslo_utils import uuidutils
|
|
from webob import exc
|
|
|
|
from karbor.api import common
|
|
from karbor.api.openstack import wsgi
|
|
from karbor.api.schemas import triggers as trigger_schema
|
|
from karbor.api import validation
|
|
from karbor import exception
|
|
from karbor.i18n import _
|
|
from karbor import objects
|
|
from karbor.policies import triggers as trigger_policy
|
|
from karbor.services.operationengine import api as operationengine_api
|
|
from karbor import utils
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class TriggerViewBuilder(common.ViewBuilder):
|
|
"""Model a trigger API response as a python dictionary."""
|
|
|
|
_collection_name = "triggers"
|
|
|
|
def detail(self, request, trigger):
|
|
"""Detailed view of a single trigger."""
|
|
|
|
trigger_ref = {
|
|
'trigger_info': {
|
|
'id': trigger.get('id'),
|
|
'name': trigger.get('name'),
|
|
'type': trigger.get('type'),
|
|
'properties': trigger.get('properties'),
|
|
}
|
|
}
|
|
return trigger_ref
|
|
|
|
def detail_list(self, request, triggers):
|
|
"""Detailed view of a list of triggers."""
|
|
return self._list_view(self.detail, request, triggers)
|
|
|
|
def _list_view(self, func, request, triggers):
|
|
triggers_list = [func(request, item)['trigger_info']
|
|
for item in triggers]
|
|
|
|
triggers_links = self._get_collection_links(request,
|
|
triggers,
|
|
self._collection_name,
|
|
)
|
|
ret = {'triggers': triggers_list}
|
|
if triggers_links:
|
|
ret['triggers_links'] = triggers_links
|
|
|
|
return ret
|
|
|
|
|
|
class TriggersController(wsgi.Controller):
|
|
"""The Triggers API controller for the OpenStack API."""
|
|
|
|
_view_builder_class = TriggerViewBuilder
|
|
|
|
def __init__(self):
|
|
self.operationengine_api = operationengine_api.API()
|
|
super(TriggersController, self).__init__()
|
|
|
|
@validation.schema(trigger_schema.create)
|
|
def create(self, req, body):
|
|
"""Creates a new trigger."""
|
|
|
|
LOG.debug('Create trigger start')
|
|
|
|
LOG.debug('Create a trigger, request body: %s', body)
|
|
|
|
context = req.environ['karbor.context']
|
|
context.can(trigger_policy.CREATE_POLICY)
|
|
trigger_info = body['trigger_info']
|
|
|
|
trigger_name = trigger_info.get("name", None)
|
|
trigger_type = trigger_info.get("type", None)
|
|
trigger_property = trigger_info.get("properties", None)
|
|
|
|
trigger_property.setdefault(
|
|
'start_time', datetime.utcnow().replace(microsecond=0))
|
|
trigger_definition = {
|
|
'id': uuidutils.generate_uuid(),
|
|
'name': trigger_name,
|
|
'project_id': context.project_id,
|
|
'type': trigger_type,
|
|
'properties': trigger_property,
|
|
}
|
|
try:
|
|
trigger = objects.Trigger(context=context, **trigger_definition)
|
|
self.operationengine_api.verify_trigger(context, trigger)
|
|
self.operationengine_api.create_trigger(context, trigger)
|
|
trigger.create()
|
|
except exception.Invalid as ex:
|
|
raise exc.HTTPBadRequest(explanation=ex.msg)
|
|
except Exception as ex:
|
|
self._raise_unknown_exception(ex)
|
|
|
|
return self._view_builder.detail(req, trigger)
|
|
|
|
def delete(self, req, id):
|
|
"""Delete a trigger."""
|
|
|
|
LOG.debug('Delete trigger(%s) start', id)
|
|
|
|
context = req.environ['karbor.context']
|
|
trigger = self._get_trigger_by_id(context, id)
|
|
|
|
context.can(trigger_policy.DELETE_POLICY, trigger)
|
|
|
|
try:
|
|
operations = objects.ScheduledOperationList.get_by_filters(
|
|
context, {"trigger_id": id}, limit=1)
|
|
except Exception as ex:
|
|
self._raise_unknown_exception(ex)
|
|
|
|
if operations:
|
|
msg = _("Trigger is being used by one or more operations")
|
|
raise exc.HTTPFailedDependency(explanation=msg)
|
|
|
|
try:
|
|
self.operationengine_api.delete_trigger(context, id)
|
|
except exception.TriggerNotFound as ex:
|
|
pass
|
|
except (exception.DeleteTriggerNotAllowed,
|
|
Exception) as ex:
|
|
self._raise_unknown_exception(ex)
|
|
|
|
trigger.destroy()
|
|
|
|
@validation.schema(trigger_schema.update)
|
|
def update(self, req, id, body):
|
|
"""Update a trigger"""
|
|
|
|
LOG.debug('Update trigger(%s) start', id)
|
|
|
|
context = req.environ['karbor.context']
|
|
trigger = self._get_trigger_by_id(context, id)
|
|
|
|
context.can(trigger_policy.UPDATE_POLICY, trigger)
|
|
|
|
trigger_info = body['trigger_info']
|
|
trigger_name = trigger_info.get("name", None)
|
|
trigger_property = trigger_info.get("properties", None)
|
|
|
|
if trigger_name:
|
|
self.validate_name_and_description(trigger_info)
|
|
trigger.name = trigger_name
|
|
|
|
if trigger_property:
|
|
start_time = trigger_property.get('start_time', None)
|
|
if not start_time:
|
|
msg = (_("start_time should be supplied"))
|
|
raise exc.HTTPBadRequest(explanation=msg)
|
|
try:
|
|
trigger.properties = trigger_property
|
|
self.operationengine_api.verify_trigger(context, trigger)
|
|
self.operationengine_api.update_trigger(context, trigger)
|
|
except exception.InvalidInput as ex:
|
|
raise exc.HTTPBadRequest(explanation=ex.msg)
|
|
except (exception.TriggerNotFound, Exception) as ex:
|
|
self._raise_unknown_exception(ex)
|
|
try:
|
|
trigger.save()
|
|
except Exception as ex:
|
|
self._raise_unknown_exception(ex)
|
|
|
|
return self._view_builder.detail(req, trigger)
|
|
|
|
def show(self, req, id):
|
|
"""Return data about the given trigger."""
|
|
|
|
LOG.debug('Get trigger(%s) start', id)
|
|
|
|
context = req.environ['karbor.context']
|
|
trigger = self._get_trigger_by_id(context, id)
|
|
|
|
context.can(trigger_policy.GET_POLICY, trigger)
|
|
return self._view_builder.detail(req, trigger)
|
|
|
|
def index(self, req):
|
|
"""Returns a list of triggers, transformed through view builder."""
|
|
|
|
context = req.environ['karbor.context']
|
|
context.can(trigger_policy.GET_ALL_POLICY)
|
|
|
|
params = req.params.copy()
|
|
LOG.debug('List triggers start, params=%s', params)
|
|
marker, limit, offset = common.get_pagination_params(params)
|
|
sort_keys, sort_dirs = common.get_sort_params(params)
|
|
filters = params
|
|
|
|
valid_filters = ["all_tenants", "name", "type", "properties"]
|
|
utils.remove_invalid_filter_options(context, filters, valid_filters)
|
|
utils.check_filters(filters)
|
|
|
|
all_tenants = utils.get_bool_param("all_tenants", filters)
|
|
if not (context.is_admin and all_tenants):
|
|
filters["project_id"] = context.project_id
|
|
|
|
try:
|
|
triggers = objects.TriggerList.get_by_filters(
|
|
context, filters, limit, marker, sort_keys, sort_dirs)
|
|
except Exception as ex:
|
|
self._raise_unknown_exception(ex)
|
|
|
|
return self._view_builder.detail_list(req, triggers)
|
|
|
|
def _get_trigger_by_id(self, context, id):
|
|
if not uuidutils.is_uuid_like(id):
|
|
msg = _("Invalid trigger id provided.")
|
|
raise exc.HTTPBadRequest(explanation=msg)
|
|
|
|
try:
|
|
trigger = objects.Trigger.get_by_id(context, id)
|
|
except exception.TriggerNotFound as error:
|
|
raise exc.HTTPNotFound(explanation=error.msg)
|
|
except Exception as ex:
|
|
self._raise_unknown_exception(ex)
|
|
|
|
return trigger
|
|
|
|
def _raise_unknown_exception(self, exception_instance):
|
|
LOG.exception('An unknown exception happened')
|
|
|
|
value = exception_instance.msg if isinstance(
|
|
exception_instance, exception.KarborException) else type(
|
|
exception_instance)
|
|
msg = (_('Unexpected API Error. Please report this at '
|
|
'http://bugs.launchpad.net/karbor/ and attach the '
|
|
'Karbor API log if possible.\n%s') % value)
|
|
raise exc.HTTPInternalServerError(explanation=msg)
|
|
|
|
|
|
def create_resource():
|
|
return wsgi.Resource(TriggersController())
|