Skip to content

Commit

Permalink
Merge 88daa53 into 08340a9
Browse files Browse the repository at this point in the history
  • Loading branch information
alvarolopez committed Apr 20, 2015
2 parents 08340a9 + 88daa53 commit 45056ee
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 5 deletions.
11 changes: 8 additions & 3 deletions ooi/api/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ def __init__(self, app, openstack_version):

def _get_req(self, req,
path=None,
content_type=None,
content_type="application/json",
body=None,
method=None):
method=None,
query_string=""):
"""Return a new Request object to interact with OpenStack.
This method will create a new request starting with the same WSGI
Expand All @@ -44,12 +45,16 @@ def _get_req(self, req,
:param req: the original request
:param path: new path for the request
:param content_type: new content type for the request
:param content_type: new content type for the request, defaults to
"application/json" if not specified
:param body: new body for the request
:param query_string: query string for the request, defaults to an empty
query if not specified
:returns: a Request object
"""
new_req = webob.Request(copy.copy(req.environ))
new_req.script_name = self.openstack_version
new_req.query_string = query_string
if path is not None:
new_req.path_info = path
if content_type is not None:
Expand Down
36 changes: 36 additions & 0 deletions ooi/api/compute.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import json

import ooi.api.base
from ooi import exception
from ooi.occi.core import collection
from ooi.occi.infrastructure import compute
from ooi.occi.infrastructure import storage
Expand All @@ -28,6 +29,10 @@


class Controller(ooi.api.base.Controller):
def __init__(self, *args, **kwargs):
super(Controller, self).__init__(*args, **kwargs)
self.compute_actions = compute.ComputeResource.actions

def _get_compute_resources(self, servers):
occi_compute_resources = []
if servers:
Expand Down Expand Up @@ -67,6 +72,37 @@ def index(self, req):

return collection.Collection(resources=occi_compute_resources)

def run_action(self, req, id, body):
action = req.GET.get("action", None)
actions = [a.term for a in compute.ComputeResource.actions]

if action is None or action not in actions:
raise exception.InvalidAction(action=action)

parser = req.get_parser()(req.headers, req.body)
obj = parser.parse()

if action == "stop":
scheme = {"category": compute.stop}
req_body = {"os-stop": None}
elif action == "start":
scheme = {"category": compute.start}
req_body = {"os-start": None}
else:
raise exception.NotImplemented

validator = occi_validator.Validator(obj)
validator.validate(scheme)

tenant_id = req.environ["keystone.token_auth"].user.project_id
path = "/%s/servers/%s/action" % (tenant_id, id)
req = self._get_req(req, path=path, body=json.dumps(req_body),
method="POST")
response = req.get_response(self.app)
if response.status_int != 202:
raise ooi.api.base.exception_from_response(response)
return []

def create(self, req, body):
tenant_id = req.environ["keystone.token_auth"].user.project_id
parser = req.get_parser()(req.headers, req.body)
Expand Down
4 changes: 4 additions & 0 deletions ooi/exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ class Invalid(OCCIException):
code = 400


class InvalidAction(Invalid):
msg_fmt = "Invalid action %(action)s provided."


class InvalidContentType(Invalid):
msg_fmt = "Invalid Content-type %(content_type)s."
code = 406
Expand Down
17 changes: 15 additions & 2 deletions ooi/tests/fakes.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,13 +274,14 @@ def __init__(self):
for tenant in tenants.values():
path = "/%s" % tenant["id"]

self._populate(path, "server", servers[tenant["id"]])
self._populate(path, "server", servers[tenant["id"]], actions=True)
self._populate(path, "volume", volumes[tenant["id"]], "os-volumes")
# NOTE(aloga): dict_values un Py3 is not serializable in JSON
self._populate(path, "image", list(images.values()))
self._populate(path, "flavor", list(flavors.values()))

def _populate(self, path_base, obj_name, obj_list, objs_path=None):
def _populate(self, path_base, obj_name, obj_list,
objs_path=None, actions=[]):
objs_name = "%ss" % obj_name
if objs_path:
path = "%s/%s" % (path_base, objs_path)
Expand All @@ -295,6 +296,10 @@ def _populate(self, path_base, obj_name, obj_list, objs_path=None):
obj_path = "%s/%s" % (path, o["id"])
self.routes[obj_path] = create_fake_json_resp({obj_name: o})

if actions:
action_path = "%s/action" % obj_path
self.routes[action_path] = webob.Response(status=202)

@webob.dec.wsgify()
def __call__(self, req):
if req.method == "GET":
Expand All @@ -315,9 +320,17 @@ def _do_create(self, req):
def _do_post(self, req):
if req.path_info.endswith("servers"):
return self._do_create(req)
elif req.path_info.endswith("action"):
body = req.json_body.copy()
action = body.popitem()
if action[0] in ["os-start", "os-stop"]:
return self._get_from_routes(req)
raise Exception

def _do_get(self, req):
return self._get_from_routes(req)

def _get_from_routes(self, req):
try:
ret = self.routes[req.path_info]
except KeyError:
Expand Down
55 changes: 55 additions & 0 deletions ooi/tests/middleware/test_compute_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,61 @@ def test_vm_not_found(self):
resp = req.get_response(app)
self.assertEqual(404, resp.status_code)

def test_action_vm(self):
tenant = fakes.tenants["foo"]
app = self.get_app()

for action in ("stop", "start"):
headers = {
'Category': (
'%s;'
'scheme="http://schemas.ogf.org/occi/infrastructure/'
'compute/action#";'
'class="action"' % action)
}
for server in fakes.servers[tenant["id"]]:
req = self._build_req("/compute/%s?action=%s" % (server["id"],
action),
tenant["id"], method="POST",
headers=headers)
resp = req.get_response(app)
self.assertDefaults(resp)
self.assertEqual(204, resp.status_code)

def test_invalid_action(self):
tenant = fakes.tenants["foo"]
app = self.get_app()

action = "foo"
for server in fakes.servers[tenant["id"]]:
req = self._build_req("/compute/%s?action=%s" % (server["id"],
action),
tenant["id"], method="POST")
resp = req.get_response(app)
self.assertDefaults(resp)
self.assertEqual(400, resp.status_code)

def test_action_body_mismatch(self):
tenant = fakes.tenants["foo"]
app = self.get_app()

action = "stop"
headers = {
'Category': (
'start;'
'scheme="http://schemas.ogf.org/occi/infrastructure/'
'compute/action#";'
'class="action"')
}
for server in fakes.servers[tenant["id"]]:
req = self._build_req("/compute/%s?action=%s" % (server["id"],
action),
tenant["id"], method="POST",
headers=headers)
resp = req.get_response(app)
self.assertDefaults(resp)
self.assertEqual(400, resp.status_code)

def test_create_vm(self):
tenant = fakes.tenants["foo"]

Expand Down
4 changes: 4 additions & 0 deletions ooi/wsgi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ def index(self, *args, **kwargs):
controller=self.resources["compute"],
action="delete_all",
conditions=dict(method=["DELETE"]))
self.mapper.connect("/compute/{id}",
controller=self.resources["compute"],
action="run_action",
conditions=dict(method=["POST"]))

self.resources["storage"] = self._create_resource(
ooi.api.storage.Controller)
Expand Down

0 comments on commit 45056ee

Please sign in to comment.