Commit 760e8dc0 by Fukász Rómeó Ervin

occi query imterface and occi instances

parent 269156f0
...@@ -47,6 +47,14 @@ with requests.Session() as session: ...@@ -47,6 +47,14 @@ with requests.Session() as session:
print(error) print(error)
print print
# query interface
req = session.get(server + "occi/-/", headers=headers, verify=False)
print("query-interface")
print("---------------")
print("status_code: " + str(req.status_code))
print(req.text)
print
# osszes vm collectionkent # osszes vm collectionkent
req = session.get(server + "occi/compute/", headers=headers, req = session.get(server + "occi/compute/", headers=headers,
verify=False) verify=False)
...@@ -58,7 +66,7 @@ with requests.Session() as session: ...@@ -58,7 +66,7 @@ with requests.Session() as session:
# az elso vm a listabol # az elso vm a listabol
vmid = json.loads(req.text)["resources"][0]["id"] vmid = json.loads(req.text)["resources"][0]["id"]
req = session.get(server + "occi/compute/" + str(vmid), req = session.get(server + "occi/compute/" + str(vmid) + "/",
headers=headers, verify=False) headers=headers, verify=False)
print("compute-"+str(vmid)) print("compute-"+str(vmid))
print("------------") print("------------")
...@@ -66,6 +74,55 @@ with requests.Session() as session: ...@@ -66,6 +74,55 @@ with requests.Session() as session:
print(req.text) print(req.text)
print print
# ha nem active, akkor azza tesszuk
state = json.loads(req.text)["attributes"]["occi.compute.state"]
action = "http://schemas.ogf.org/occi/infrastructure/compute/action#"
if state != "active":
try:
headers["X-CSRFToken"] = req.cookies['csrftoken']
except:
pass
req = session.post(server + "occi/compute/" + str(vmid) + "/",
headers=headers, verify=False,
data=json.dumps({"action": action + "start"}))
print("compute-" + str(vmid) + "-start")
print("---------------")
print("status_code: " + str(req.status_code))
print(req.text)
print
# restart
try:
headers["X-CSRFToken"] = req.cookies['csrftoken']
except:
pass
actionatrs = {"method": "cold"}
actioninv = {"action": action + "restart", "attributes": actionatrs}
req = session.post(server + "occi/compute/" + str(vmid) + "/",
headers=headers, verify=False,
data=json.dumps(actioninv))
print("compute-"+str(vmid) + "-restart")
print("-----------------")
print("status_code: " + str(req.status_code))
print(req.text)
print
# suspend
try:
headers["X-CSRFToken"] = req.cookies['csrftoken']
except:
pass
actioninv["action"] = action + "suspend"
actioninv["attributes"]["method"] = "suspend"
req = session.post(server + "occi/compute/" + str(vmid) + "/",
headers=headers, verify=False,
data=json.dumps(actioninv))
print("compute-" + str(vmid) + "-suspend")
print("-----------------")
print("status_code: " + str(req.status_code))
print(req.text)
print
# Kijelentkezes # Kijelentkezes
req = session.get(server + "occi/logout/", headers=headers, req = session.get(server + "occi/logout/", headers=headers,
verify=False) verify=False)
......
""" Implementation of the OCCI - Core model classes """ """ Implementation of the OCCI - Core model classes """
from occi_utils import set_optional_attributes, serialize_attributes from occi_utils import set_optional_attributes
class Attribute: class Attribute:
...@@ -45,7 +45,8 @@ class Category(object): ...@@ -45,7 +45,8 @@ class Category(object):
class Kind(Category): class Kind(Category):
""" OCCI 1.2 - CORE - Classification - Kind """ """ OCCI 1.2 - CORE - Classification - Kind """
kind_optional_attributes = ("parent", "actions", "enitities") kind_optional_attributes = ("parent", "actions", "enitities",
"location",)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(Kind, self).__init__(*args, **kwargs) super(Kind, self).__init__(*args, **kwargs)
...@@ -61,9 +62,14 @@ class Kind(Category): ...@@ -61,9 +62,14 @@ class Kind(Category):
if hasattr(self, "location"): if hasattr(self, "location"):
json["location"] = self.location json["location"] = self.location
if hasattr(self, "attributes"): if hasattr(self, "attributes"):
json["attributes"] = serialize_attributes(self.attributes) json["attributes"] = {}
for attribute in self.attributes:
json["attributes"][attribute.name] = (attribute
.render_as_json())
if hasattr(self, "actions"): if hasattr(self, "actions"):
json["actions"] = serialize_attributes(self.actions) json["actions"] = []
for action in self.actions:
json["actions"].append(action.scheme + action.term)
return json return json
...@@ -77,7 +83,10 @@ class Action(Category): ...@@ -77,7 +83,10 @@ class Action(Category):
if hasattr(self, "title"): if hasattr(self, "title"):
json["title"] = self.title json["title"] = self.title
if hasattr(self, "attributes"): if hasattr(self, "attributes"):
json["attributes"] = serialize_attributes(self.attributes) json["attributes"] = {}
for attribute in self.attributes:
json["attributes"][attribute.name] = (attribute
.render_as_json())
return json return json
...@@ -93,8 +102,7 @@ class Mixin(Category): ...@@ -93,8 +102,7 @@ class Mixin(Category):
kwargs) kwargs)
def render_as_json(self): def render_as_json(self):
json = {"term": self.term, "scheme": self.scheme, json = {"term": self.term, "scheme": self.scheme}
"attributes": self.attributes, "actions": self.actions}
if hasattr(self, "title"): if hasattr(self, "title"):
json["title"] = self.title json["title"] = self.title
if hasattr(self, "location"): if hasattr(self, "location"):
...@@ -103,6 +111,15 @@ class Mixin(Category): ...@@ -103,6 +111,15 @@ class Mixin(Category):
json["depends"] = self.depends json["depends"] = self.depends
if hasattr(self, "applies"): if hasattr(self, "applies"):
json["applies"] = self.applies json["applies"] = self.applies
if hasattr(self, "attributes"):
json["attributes"] = {}
for attribute in self.attributes:
json["attributes"][attribute.name] = (attribute
.render_as_json())
if hasattr(self, "actions"):
json["actions"] = []
for action in self.actions:
json["actions"].append(action.scheme + action.term)
return json return json
...@@ -169,11 +186,3 @@ class Link(Entity): ...@@ -169,11 +186,3 @@ class Link(Entity):
if hasattr(self, "title"): if hasattr(self, "title"):
json["title"] = self.title json["title"] = self.title
return json return json
ENTITY_KIND = Kind("http://schemas.ogf.org/occi/core#", "entity",
title="Entity")
RESOURCE_KIND = Kind("http://schemas.ogf.org/occi/core#", "resource",
title="Resource",
parent="http://schemas.ogf.org/occi/core#entity")
""" Implementation of the OCCI - Infrastructure extension classes """ """ Implementation of the OCCI - Infrastructure extension classes """
from occi_core import Action, Attribute, Resource from occi_core import Resource
from occi_utils import action_list_for_resource from occi_utils import action_list_for_resource, OcciActionInvocationError
from occi_instances import COMPUTE_ACTIONS
from common.models import HumanReadableException
COMPUTE_ATTRIBUTES = [
Attribute("occi.compute.architecture", "Object", True, False,
description="CPU Architecture of the instance."),
Attribute("occi.compute.cores", "Object", True, False,
description="Number of virtual CPU cores assigned to " +
"the instance."),
Attribute("occi.compute.hostname", "Object", True, False,
description="Fully Qualified DNS hostname for the " +
"instance"),
Attribute("occi.compute.share", "Object", True, False,
description="Relative number of CPU shares for the " +
"instance."),
Attribute("occi.compute.memory", "Object", True, False,
description="Maximum RAM in gigabytes allocated to " +
"the instance."),
Attribute("occi.compute.state", "Object", False, True,
description="Current state of the instance."),
Attribute("occi.compute.state.message", "Object", False, False,
description="Human-readable explanation of the current " +
"instance state"),
]
COMPUTE_ACTIONS = [
Action("http://schemas.ogf.org/occi/infrastructure/compute/action#",
"start", title="Start compute instance"),
Action("http://schemas.ogf.org/occi/infrastructure/compute/action#",
"stop", title="Stop compute instance",
attributes=[Attribute("method", "Object", True, False), ]),
Action("http://schemas.ogf.org/occi/infrastructure/compute/action#",
"restart", title="Restart compute instance",
attributes=[Attribute("method", "Object",
True, False), ]),
Action("http://schemas.ogf.org/occi/infrastructure/compute/action#",
"suspend", title="Suspend compute instance",
attributes=[Attribute("method", "Object",
True, False), ]),
Action("http://schemas.ogf.org/occi/infrastructure/compute/action#",
"save", title="Create a template of compute instance",
attributes=[Attribute("method", "Object", True,
False),
Attribute("name", "Object", True, True), ]),
]
COMPUTE_STATES = { COMPUTE_STATES = {
"NOSTATE": "inactive", "NOSTATE": "inactive",
...@@ -82,7 +41,6 @@ class Compute(Resource): ...@@ -82,7 +41,6 @@ class Compute(Resource):
"http://schemas.ogf.org/occi/infrastructure#compute", vm.pk) "http://schemas.ogf.org/occi/infrastructure#compute", vm.pk)
self.vm = vm self.vm = vm
self.attributes = self.set_attributes() self.attributes = self.set_attributes()
self.actions = action_list_for_resource(COMPUTE_ACTIONS) self.actions = action_list_for_resource(COMPUTE_ACTIONS)
def set_attributes(self): def set_attributes(self):
...@@ -99,3 +57,91 @@ class Compute(Resource): ...@@ -99,3 +57,91 @@ class Compute(Resource):
attributes["occi.compute.state.message"] = (COMPUTE_STATE_MESSAGES attributes["occi.compute.state.message"] = (COMPUTE_STATE_MESSAGES
.get(self.vm.state)) .get(self.vm.state))
return attributes return attributes
def invoke_action(self, user, action, attributes):
base = "http://schemas.ogf.org/occi/infrastructure/compute/action#"
if action == (base + "start"):
self.start(user)
elif action == (base + "stop"):
self.stop(user, attributes)
elif action == (base + "restart"):
self.restart(user, attributes)
elif action == (base + "suspend"):
self.suspend(user, attributes)
elif action == (base + "save"):
self.save(user, attributes)
else:
raise OcciActionInvocationError(message="Undefined action.")
self.__init__(self.vm)
def start(self, user):
""" Start action on a compute instance """
try:
if self.vm.status == "SUSPENDED":
self.vm.wake_up(user=user)
else:
self.vm.deploy(user=user)
except HumanReadableException as e:
raise OcciActionInvocationError(message=e.get_user_text())
def stop(self, user, attributes):
""" Stop action on a compute instance """
if "method" not in attributes:
raise OcciActionInvocationError(message="No method given.")
if attributes["method"] in ("graceful", "acpioff",):
try:
# TODO: call shutdown properly
self.vm.shutdown(user=user)
except HumanReadableException as e:
raise OcciActionInvocationError(message=e.get_user_text())
elif attributes["method"] in ("poweroff",):
try:
self.vm.shut_off(user=user)
except HumanReadableException as e:
raise OcciActionInvocationError(message=e.get_user_text())
else:
raise OcciActionInvocationError(
message="Given method is not valid")
def restart(self, user, attributes):
""" Restart action on a compute instance """
if "method" not in attributes:
raise OcciActionInvocationError(message="No method given.")
if attributes["method"] in ("graceful", "warm",):
try:
# TODO: not working for some reason
self.vm.restart(user=user)
except HumanReadableException as e:
raise OcciActionInvocationError(message=e.get_user_text())
elif attributes["method"] in ("cold",):
try:
self.vm.reset(user=user)
except HumanReadableException as e:
raise OcciActionInvocationError(message=e.get_user_text())
else:
raise OcciActionInvocationError(
message="Given method is not valid")
def suspend(self, user, attributes):
""" Suspend action on a compute instance """
if "method" not in attributes:
raise OcciActionInvocationError(message="No method given.")
if attributes["method"] in ("hibernate", "suspend",):
try:
self.vm.sleep(user=user)
except HumanReadableException as e:
raise OcciActionInvocationError(message=e.get_user_text())
else:
raise OcciActionInvocationError(
message="Given method is not valid")
def save(self, user, attributes):
""" Save action on a compute instance """
# TODO: save template
raise OcciActionInvocationError(
message="Save action not implemented")
class Network(Resource):
# TODO: network
pass
"""" Utilities for the OCCI implementation of CIRCLE """ """" Utilities for the OCCI implementation of CIRCLE """
from django.http import JsonResponse, HttpResponse
import json
class OcciResourceInstanceNotExist(Exception):
def __init__(self):
message = "The resource instance does not exist."
super(OcciResourceInstanceNotExist, self).__init__(message)
self.response = JsonResponse({"error": message}, status=404,
charset="utf-8")
class OcciActionInvocationError(Exception):
def __init__(self, *args, **kwargs):
message = kwargs.get("message", "Could not invoke action.")
super(OcciActionInvocationError, self).__init__(message)
self.response = JsonResponse({"error": message}, status=400,
charset="utf-8")
class OcciResponse(HttpResponse):
""" A response class with its occi headers set """
# TODO: setting occi specific headers
def init(self, data, response_type, *args, **kwargs):
if response_type == "json":
data = json.dumps(data)
super(OcciResponse, self).__init__(data, status=418)
if response_type == "json":
self["Content-Type"] = "application/json"
else:
self["Content-Type"] = "text/plain"
self["Server"] = "OCCI/1.2"
def set_optional_attributes(self, optional_attributes, kwargs): def set_optional_attributes(self, optional_attributes, kwargs):
""" Sets the optional arguments of an instance. """ Sets the optional arguments of an instance.
......
from django.conf.urls import url from django.conf.urls import url
from views import (OcciLoginView, OcciLogoutView, OcciComputeView, from views import (OcciLoginView, OcciLogoutView, OcciQueryInterfaceView,
OcciComputeCollectionView) OcciComputeView, OcciComputeCollectionView)
urlpatterns = [ urlpatterns = [
url(r'^login/$', OcciLoginView.as_view()), url(r'^login/$', OcciLoginView.as_view()),
url(r'^logout/$', OcciLogoutView.as_view()), url(r'^logout/$', OcciLogoutView.as_view()),
url(r'^-/$', OcciQueryInterfaceView.as_view()),
url(r'^compute/$', OcciComputeCollectionView.as_view()), url(r'^compute/$', OcciComputeCollectionView.as_view()),
url(r'^compute/(?P<id>\d+)/$', OcciComputeView.as_view()), url(r'^compute/(?P<id>\d+)/$', OcciComputeView.as_view()),
] ]
...@@ -12,6 +12,9 @@ from django.utils.decorators import method_decorator ...@@ -12,6 +12,9 @@ from django.utils.decorators import method_decorator
from vm.models.instance import Instance from vm.models.instance import Instance
from forms import OcciAuthForm from forms import OcciAuthForm
from occi_infrastructure import Compute from occi_infrastructure import Compute
from occi_utils import (OcciResourceInstanceNotExist,
OcciActionInvocationError)
from occi_instances import ALL_KINDS, ALL_MIXINS, ALL_ACTIONS
class OcciLoginView(View): class OcciLoginView(View):
...@@ -27,9 +30,9 @@ class OcciLoginView(View): ...@@ -27,9 +30,9 @@ class OcciLoginView(View):
return JsonResponse(result, charset="utf-8") return JsonResponse(result, charset="utf-8")
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
data = json.loads(request.body.decode("utf-8"))
""" Returns a response with a cookie to be used for the OCCI api """ Returns a response with a cookie to be used for the OCCI api
requests. """ requests. """
data = json.loads(request.body.decode("utf-8"))
form = OcciAuthForm(data=data, request=request) form = OcciAuthForm(data=data, request=request)
if form.is_valid(): if form.is_valid():
result = {"result": "OK"} result = {"result": "OK"}
...@@ -49,7 +52,22 @@ class OcciLogoutView(View): ...@@ -49,7 +52,22 @@ class OcciLogoutView(View):
return JsonResponse(result, charset="utf-8") return JsonResponse(result, charset="utf-8")
class OcciQueryInterfaceView(View):
""" The view of the OCCI query interface """
@method_decorator(ensure_csrf_cookie)
def get(self, request, *args, **kwargs):
result = {"kinds": [], "mixins": [], "actions": []}
for kind in ALL_KINDS():
result["kinds"].append(kind.render_as_json())
for mixin in ALL_MIXINS():
result["mixins"].append(mixin.render_as_json())
for action in ALL_ACTIONS():
result["actions"].append(action.render_as_json())
return JsonResponse(result, charset="utf-8")
class OcciComputeCollectionView(View): class OcciComputeCollectionView(View):
@method_decorator(ensure_csrf_cookie)
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
if not request.user.is_authenticated(): if not request.user.is_authenticated():
return HttpResponse(status=403) return HttpResponse(status=403)
...@@ -63,14 +81,38 @@ class OcciComputeCollectionView(View): ...@@ -63,14 +81,38 @@ class OcciComputeCollectionView(View):
class OcciComputeView(View): class OcciComputeView(View):
""" View of a compute instance """ """ View of a compute instance """
def get_vm_object(self, request, vmid):
try:
vm = get_object_or_404(Instance.get_objects_with_level("user",
request.user), pk=vmid)
except Http404:
raise OcciResourceInstanceNotExist()
return Compute(vm)
@method_decorator(ensure_csrf_cookie)
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
if not request.user.is_authenticated(): if not request.user.is_authenticated():
return HttpResponse(status=403) return HttpResponse(status=403)
try: try:
vm = get_object_or_404(Instance.get_objects_with_level("user", compute = self.get_vm_object(request, kwargs["id"])
request.user), pk=kwargs['id']) except OcciResourceInstanceNotExist as e:
except Http404: return e.json_response
return JsonResponse({"error": "There is no instance with the" +
" id " + kwargs['id'] + "."}, status=400)
compute = Compute(vm)
return JsonResponse(compute.render_as_json(), charset="utf-8") return JsonResponse(compute.render_as_json(), charset="utf-8")
def post(self, request, *args, **kwargs):
requestData = json.loads(request.body.decode("utf-8"))
# TODO post request w/o action, compute creation
if not requestData["action"]:
return HttpResponse(status=404)
try:
compute = self.get_vm_object(request, kwargs["id"])
except OcciResourceInstanceNotExist as e:
return e.response
try:
compute.invoke_action(request.user,
requestData.get("action", None),
requestData.get("attributes", None))
except OcciActionInvocationError as e:
return e.response
# TODO: proper return value
return JsonResponse(compute.render_as_json(), status=200)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment