Add create() method to Compute controller.

This commit is contained in:
Pablo Orviz
2015-03-04 09:12:50 +01:00
parent cf2ba6a1a3
commit 08773c9ab1
4 changed files with 165 additions and 8 deletions

View File

@@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Spanish National Research Council
#
# 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 collections
import shlex
import six.moves.urllib.parse as urlparse
from ooi import exception
def _lexize(s, separator, ignore_whitespace=False):
lex = shlex.shlex(instream=s, posix=True)
lex.commenters = ""
if ignore_whitespace:
lex.whitespace = separator
else:
lex.whitespace += separator
lex.whitespace_split = True
return list(lex)
def parse(f):
def _parse(obj, req, *args, **kwargs):
headers = {}
try:
l = []
params = {}
for ctg in _lexize(req.headers["Category"],
separator=',',
ignore_whitespace=True):
ll = _lexize(ctg, ';')
d = {"term": ll[0]} # assumes 1st element => term's value
d.update(dict([i.split('=') for i in ll[1:]]))
l.append(d)
params[urlparse.urlparse(d["scheme"]).path] = d["term"]
headers["Category"] = l
except KeyError:
raise exception.HeaderNotFound(header="Category")
return f(obj, req, headers, params, *args, **kwargs)
return _parse
def _get_header_by_class(headers, class_id):
return [h for h in headers["Category"] if h["class"] in [class_id]]
def validate(class_id, schemas, term=None):
def accepts(f):
def _validate(obj, req, headers, params, *args, **kwargs):
"""Category headers validation.
Arguments::
class_id: type of OCCI class (kind, mixin, ..).
schemas: dict mapping the mandatory schemas with its
occurrences.
term (optional): if present, validates its value.
Validation checks::
class_presence: asserts the existance of given class_id.
scheme_occurrences: enforces the number of occurrences of the
given schemas.
term_validation: asserts the correct term value of the
matching headers.
"""
header_l = _get_header_by_class(headers, class_id)
def class_presence():
if not header_l:
raise exception.OCCINoClassFound(class_id=class_id)
def scheme_occurrences():
d = collections.Counter([h["scheme"]
for h in header_l])
s = set(d.items()) ^ set(schemas.items())
if len(s) != 0:
mismatched_schemas = [(scheme, d[scheme])
for scheme in dict(s).keys()]
raise exception.OCCISchemaOcurrencesMismatch(
mismatched_schemas=mismatched_schemas)
def term_validation():
if [h for h in header_l if h["term"] not in [term]]:
raise exception.OCCINotCompliantTerm(term=term)
class_presence()
scheme_occurrences()
if term:
term_validation()
return f(obj, req, headers, params, *args, **kwargs)
return _validate
return accepts

View File

@@ -20,8 +20,12 @@ class Controller(object):
self.app = app
self.openstack_version = openstack_version
def _get_req(self, req, path=None):
def _get_req(self, req, path=None, content_type=None, body=None):
req.script_name = self.openstack_version
if path is not None:
req.path_info = path
if content_type is not None:
req.content_type = content_type
if body is not None:
req.body = body
return req

View File

@@ -14,19 +14,18 @@
# License for the specific language governing permissions and limitations
# under the License.
from ooi.api import base
import json
import ooi.api
import ooi.api.base
from ooi.occi.core import collection
from ooi.occi.infrastructure import compute
from ooi.openstack import helpers
from ooi.openstack import templates
class Controller(base.Controller):
def index(self, req):
tenant_id = req.environ["keystone.token_auth"].user.project_id
req = self._get_req(req, path="/%s/servers" % tenant_id)
response = req.get_response(self.app)
class Controller(ooi.api.base.Controller):
def _get_compute_resources(self, response):
servers = response.json_body.get("servers", [])
occi_compute_resources = []
if servers:
@@ -34,6 +33,37 @@ class Controller(base.Controller):
s = compute.ComputeResource(title=s["name"], id=s["id"])
occi_compute_resources.append(s)
return occi_compute_resources
def index(self, req):
tenant_id = req.environ["keystone.token_auth"].user.project_id
req = self._get_req(req, path="/%s/servers" % tenant_id)
response = req.get_response(self.app)
occi_compute_resources = self._get_compute_resources(response)
return collection.Collection(resources=occi_compute_resources)
@ooi.api.parse
@ooi.api.validate("kind",
{"http://schemas.ogf.org/occi/infrastructure#": 1},
term="compute")
@ooi.api.validate("mixin",
{"http://schemas.openstack.org/template/resource#": 1,
"http://schemas.openstack.org/template/os#": 1})
def create(self, req, headers, params, body):
tenant_id = req.environ["keystone.token_auth"].user.project_id
req = self._get_req(req,
path="/%s/servers" % tenant_id,
content_type="application/json",
body=json.dumps({
"server": {
"name": params["/occi/infrastructure"],
"imageRef": params["/template/os"],
"flavorRef": params["/template/resource"]
}}))
response = req.get_response(self.app)
occi_compute_resources = self._get_compute_resources(response)
return collection.Collection(resources=occi_compute_resources)
def show(self, id, req):

View File

@@ -88,3 +88,19 @@ class NotImplemented(OCCIException):
class HeaderNotFound(Invalid):
msg_fmt = "Header '%(header)s' not found."
class HeaderValidation(Invalid):
"""Parent class for header validation error exceptions."""
class OCCINoClassFound(HeaderValidation):
msg_fmt = "Found no headers matching class '%(class_id)s'."
class OCCISchemaOccurrencesMismatch(HeaderValidation):
msg_fmt = "Schema occurrences do not match: '%(mismatched_schemas)s'."
class OCCINotCompliantTerm(HeaderValidation):
msg_fmt = "Found a non-compliant term '%(term)s'."