Commit a9d62221 by Fukász Rómeó Ervin

os templates, credentials, compute creation, compute delete

parent 760e8dc0
...@@ -25,7 +25,9 @@ with requests.Session() as session: ...@@ -25,7 +25,9 @@ with requests.Session() as session:
print("csrf-token") print("csrf-token")
print("----------") print("----------")
print("status_code: " + str(req.status_code)) print("status_code: " + str(req.status_code))
print(json.loads(req.text)["result"]) print
print(json.dumps(json.loads(req.text), sort_keys=True,
indent=4, separators=(",", ": ")))
print print
# Bejelentkezes # Bejelentkezes
...@@ -38,13 +40,9 @@ with requests.Session() as session: ...@@ -38,13 +40,9 @@ with requests.Session() as session:
print("login") print("login")
print("-----") print("-----")
print("status_code: " + str(req.status_code)) print("status_code: " + str(req.status_code))
if req.status_code == 200: print
print(json.loads(req.text)["result"]) print(json.dumps(json.loads(req.text), sort_keys=True,
else: indent=4, separators=(",", ": ")))
print(json.loads(req.text)["result"])
errors = json.loads(req.text)["errors"]
for error in errors:
print(error)
print print
# query interface # query interface
...@@ -52,7 +50,9 @@ with requests.Session() as session: ...@@ -52,7 +50,9 @@ with requests.Session() as session:
print("query-interface") print("query-interface")
print("---------------") print("---------------")
print("status_code: " + str(req.status_code)) print("status_code: " + str(req.status_code))
print(req.text) print
print(json.dumps(json.loads(req.text), sort_keys=True,
indent=4, separators=(",", ": ")))
print print
# osszes vm collectionkent # osszes vm collectionkent
...@@ -61,17 +61,21 @@ with requests.Session() as session: ...@@ -61,17 +61,21 @@ with requests.Session() as session:
print("compute-collection") print("compute-collection")
print("------------------") print("------------------")
print("status_code: " + str(req.status_code)) print("status_code: " + str(req.status_code))
print(req.text) print
print(json.dumps(json.loads(req.text), sort_keys=True,
indent=4, separators=(",", ": ")))
print print
# 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/" + vmid + "/",
headers=headers, verify=False) headers=headers, verify=False)
print("compute-"+str(vmid)) print("compute-"+str(vmid))
print("------------") print("------------")
print("status_code: " + str(req.status_code)) print("status_code: " + str(req.status_code))
print(req.text) print
print(json.dumps(json.loads(req.text), sort_keys=True,
indent=4, separators=(",", ": ")))
print print
# ha nem active, akkor azza tesszuk # ha nem active, akkor azza tesszuk
...@@ -82,13 +86,15 @@ with requests.Session() as session: ...@@ -82,13 +86,15 @@ with requests.Session() as session:
headers["X-CSRFToken"] = req.cookies['csrftoken'] headers["X-CSRFToken"] = req.cookies['csrftoken']
except: except:
pass pass
req = session.post(server + "occi/compute/" + str(vmid) + "/", req = session.post(server + "occi/compute/" + vmid + "/",
headers=headers, verify=False, headers=headers, verify=False,
data=json.dumps({"action": action + "start"})) data=json.dumps({"action": action + "start"}))
print("compute-" + str(vmid) + "-start") print("compute-" + str(vmid) + "-start")
print("---------------") print("---------------")
print("status_code: " + str(req.status_code)) print("status_code: " + str(req.status_code))
print(req.text) print
print(json.dumps(json.loads(req.text), sort_keys=True,
indent=4, separators=(",", ": ")))
print print
# restart # restart
...@@ -98,13 +104,15 @@ with requests.Session() as session: ...@@ -98,13 +104,15 @@ with requests.Session() as session:
pass pass
actionatrs = {"method": "cold"} actionatrs = {"method": "cold"}
actioninv = {"action": action + "restart", "attributes": actionatrs} actioninv = {"action": action + "restart", "attributes": actionatrs}
req = session.post(server + "occi/compute/" + str(vmid) + "/", req = session.post(server + "occi/compute/" + vmid + "/",
headers=headers, verify=False, headers=headers, verify=False,
data=json.dumps(actioninv)) data=json.dumps(actioninv))
print("compute-"+str(vmid) + "-restart") print("compute-"+str(vmid) + "-restart")
print("-----------------") print("-----------------")
print("status_code: " + str(req.status_code)) print("status_code: " + str(req.status_code))
print(req.text) print
print(json.dumps(json.loads(req.text), sort_keys=True,
indent=4, separators=(",", ": ")))
print print
# suspend # suspend
...@@ -114,21 +122,82 @@ with requests.Session() as session: ...@@ -114,21 +122,82 @@ with requests.Session() as session:
pass pass
actioninv["action"] = action + "suspend" actioninv["action"] = action + "suspend"
actioninv["attributes"]["method"] = "suspend" actioninv["attributes"]["method"] = "suspend"
req = session.post(server + "occi/compute/" + str(vmid) + "/", req = session.post(server + "occi/compute/" + vmid + "/",
headers=headers, verify=False, headers=headers, verify=False,
data=json.dumps(actioninv)) data=json.dumps(actioninv))
print("compute-" + str(vmid) + "-suspend") print("compute-" + str(vmid) + "-suspend")
print("-----------------") print("-----------------")
print("status_code: " + str(req.status_code)) print("status_code: " + str(req.status_code))
print(req.text) print
print(json.dumps(json.loads(req.text), sort_keys=True,
indent=4, separators=(",", ": ")))
print
# nem letezo action
try:
headers["X-CSRFToken"] = req.cookies["csrftoken"]
except:
pass
actioninv["action"] = action + "noaction"
req = session.post(server + "occi/compute/" + vmid + "/",
headers=headers, verify=False,
data=json.dumps(actioninv))
print("compute-" + str(vmid) + "-noaction")
print("-------------------")
print("status_code: " + str(req.status_code))
print
print(json.dumps(json.loads(req.text), sort_keys=True,
indent=4, separators=(",", ": ")))
print print
# vm krealas
try:
headers["X-CSRFToken"] = req.cookies["csrftoken"]
except:
pass
# a template mixinje benne kell legyen az adatokban
# az osszes template a query interfacen megjelenik mint mixin
# azok a mixinek templatek amik az os_tpl mixintol fuggnek
putdata = {"mixins": [
"http://circlecloud.org/occi/templates/os#os_template_1"],
"other_occi_compute_data": "may be provided"}
req = session.put(server + "occi/compute/1/",
headers=headers, verify=False,
data=json.dumps(putdata))
print("create_compute")
print("--------------")
print("status_code: " + str(req.status_code))
print
print(json.dumps(json.loads(req.text), sort_keys=True,
indent=4, separators=(",", ": ")))
print
# vm torles
try:
headers["X-CSRFToken"] = req.cookies["csrftoken"]
except:
pass
vmid = json.loads(req.text)["id"]
req = session.delete(server + "occi/compute/" + vmid + "/",
headers=headers, verify=False,
data=json.dumps(putdata))
print("delete_compute")
print("--------------")
print("status_code: " + str(req.status_code))
print
print(json.dumps(json.loads(req.text), sort_keys=True,
indent=4, separators=(",", ": ")))
print
# Kijelentkezes # Kijelentkezes
req = session.get(server + "occi/logout/", headers=headers, req = session.get(server + "occi/logout/", headers=headers,
verify=False) verify=False)
print("logout") print("logout")
print("------") print("------")
print("status_code: " + str(req.status_code)) print("status_code: " + str(req.status_code))
print(json.loads(req.text)["result"]) print
print(json.dumps(json.loads(req.text), sort_keys=True,
indent=4, separators=(",", ": ")))
except ConnectionError as e: except ConnectionError as e:
print(e) print(e)
...@@ -38,24 +38,43 @@ class Compute(Resource): ...@@ -38,24 +38,43 @@ class Compute(Resource):
def __init__(self, vm): def __init__(self, vm):
""" Creates a Compute instance of a VM instance object """ """ Creates a Compute instance of a VM instance object """
super(Compute, self).__init__( super(Compute, self).__init__(
"http://schemas.ogf.org/occi/infrastructure#compute", vm.pk) "http://schemas.ogf.org/occi/infrastructure#compute",
str(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)
self.mixins = [
"http://circlecloud.org/occi/infrastructure#credentials",
]
if vm.template:
self.mixins.append(
"http://circlecloud.org/occi/templates/os#os_template_" +
str(vm.template.pk))
def set_attributes(self): def set_attributes(self):
""" Sets the attributes of the Compute object based on the VM """ Sets the attributes of the Compute object based on the VM
instance. """ instance. """
attributes = {} attributes = {}
attributes["occi.compute.architecture"] = (COMPUTE_ARCHITECTURES attributes["occi.compute.architecture"] = (
.get(self.vm.arch)) COMPUTE_ARCHITECTURES.get(self.vm.arch))
attributes["occi.compute.cores"] = self.vm.num_cores attributes["occi.compute.cores"] = self.vm.num_cores
attributes["occi.compute.hostname"] = self.vm.short_hostname attributes["occi.compute.hostname"] = self.vm.short_hostname
attributes["occi.compute.share"] = self.vm.priority attributes["occi.compute.share"] = self.vm.priority
attributes["occi.compute.memory"] = self.vm.ram_size / 1024.0 attributes["occi.compute.memory"] = self.vm.ram_size / 1024.0
attributes["occi.compute.state"] = COMPUTE_STATES.get(self.vm.state) attributes["occi.compute.state"] = COMPUTE_STATES.get(self.vm.state)
attributes["occi.compute.state.message"] = (COMPUTE_STATE_MESSAGES attributes["occi.compute.state.message"] = (
.get(self.vm.state)) COMPUTE_STATE_MESSAGES.get(self.vm.state))
attributes["org.circlecloud.occi.credentials.protocol"] = (
self.vm.access_method)
attributes["org.circlecloud.occi.credentials.host"] = (
self.vm.get_connect_host())
attributes["org.circlecloud.occi.credentials.port"] = (
self.vm.get_connect_port())
attributes["org.circlecloud.occi.credentials.username"] = "cloud"
attributes["org.circlecloud.occi.credentials.password"] = (
self.vm.pw)
attributes["org.circlecloud.occi.credentials.command"] = (
self.vm.get_connect_command())
return attributes return attributes
def invoke_action(self, user, action, attributes): def invoke_action(self, user, action, attributes):
...@@ -140,8 +159,3 @@ class Compute(Resource): ...@@ -140,8 +159,3 @@ class Compute(Resource):
# TODO: save template # TODO: save template
raise OcciActionInvocationError( raise OcciActionInvocationError(
message="Save action not implemented") message="Save action not implemented")
class Network(Resource):
# TODO: network
pass
""" Required instances of the OCCI classes """ """ Required instances of the OCCI classes """
from vm.models.instance import InstanceTemplate
from occi_core import Kind, Mixin, Attribute, Action from occi_core import Kind, Mixin, Attribute, Action
...@@ -103,7 +104,6 @@ IPNETWORK_ATTRIBUTES = [ ...@@ -103,7 +104,6 @@ IPNETWORK_ATTRIBUTES = [
IPNETWORK_MIXIN = Mixin("http://schemas.ogf.org/occi/infrastructure/network#", IPNETWORK_MIXIN = Mixin("http://schemas.ogf.org/occi/infrastructure/network#",
"ipnetwork", title="IP Network Mixin", "ipnetwork", title="IP Network Mixin",
location="/network/ipnetwork",
applies=("http://shemas.ogf.org/occi/infrastructure" + applies=("http://shemas.ogf.org/occi/infrastructure" +
"#network")) "#network"))
...@@ -166,8 +166,6 @@ IPNETWORKINTERFACE_MIXIN = Mixin("http://schemas.ogf.org/occi/" + ...@@ -166,8 +166,6 @@ IPNETWORKINTERFACE_MIXIN = Mixin("http://schemas.ogf.org/occi/" +
"infrastructure/networkinterface#", "infrastructure/networkinterface#",
"ipnetworkinterface", "ipnetworkinterface",
title="IP Network Interface Mixin", title="IP Network Interface Mixin",
location="/networkinterface" +
"/ipnetworkinterface/",
applies="http://schemas.ogf.org/occi/" + applies="http://schemas.ogf.org/occi/" +
"infrastructure#networkinterface") "infrastructure#networkinterface")
...@@ -191,18 +189,81 @@ STORAGELINK_KIND = Kind("http://schemas.ogf.org/occi/infrastructure#", ...@@ -191,18 +189,81 @@ STORAGELINK_KIND = Kind("http://schemas.ogf.org/occi/infrastructure#",
parent="http://schemas.ogf.org/occi/core#link", parent="http://schemas.ogf.org/occi/core#link",
atrributes=STORAGELINK_ATTRIBUTES) atrributes=STORAGELINK_ATTRIBUTES)
# TODO: OS Templates and Credentials
ACTION_ARRAYS = [COMPUTE_ACTIONS, NETWORK_ACTIONS, STORAGE_ACTIONS] CREDENTIALS_ATTRIBUTES = [
Attribute("org.circlecloud.occi.credentials.protocol", "String", False,
False, description="The protocol to be used to access the "
"compute instance."),
Attribute("org.circlecloud.occi.credentials.host", "String", False,
False, description="The host to be used to access the compute " +
"instance."),
Attribute("org.circlecloud.occi.credentials.port", "Integer", False,
False, description="The port to be used to access the compute " +
"instance."),
Attribute("org.circlecloud.occi.credentials.username", "String", False,
False, description="The username to be used to access the " +
"compute instance."),
Attribute("org.circlecloud.occi.credentials.password", "String", False,
False, description="The password to be used to acces the " +
"compute instance."),
Attribute("org.circlecloud.occi.credentials.command", "String", False,
False, description="The full command that may be used to " +
"connect to the compute instance."),
]
CREDENTIALS_MIXIN = Mixin("http://circlecloud.org/occi/infrastructure#",
"credentials",
title="Credentials Mixin",
attributes=CREDENTIALS_ATTRIBUTES,
applies="http://schemas.ogf.org/occi/infrastructure" +
"#compute")
OS_TPL_MIXIN = Mixin("http://schemas.ogf.org/occi/infrastructure#",
"os_tpl",
title="OS Template")
ACTION_ARRAYS = [
COMPUTE_ACTIONS,
# NETWORK_ACTIONS,
# STORAGE_ACTIONS,
]
def ALL_KINDS(): def ALL_KINDS():
return [ENTITY_KIND, RESOURCE_KIND, LINK_KIND, COMPUTE_KIND, NETWORK_KIND, return [
STORAGE_KIND, NETWORKINTERFACE_KIND] ENTITY_KIND,
RESOURCE_KIND,
LINK_KIND,
COMPUTE_KIND,
# NETWORK_KIND,
# STORAGE_KIND,
# NETWORKINTERFACE_KIND
]
def os_tpl_mixins(user):
""" Returns an array of all the templates the user has access to. """
templates = InstanceTemplate.get_objects_with_level("user", user)
result = []
for template in templates:
result.append(Mixin("http://circlecloud.org/occi/templates/os#",
"os_template_" + str(template.pk),
title=template.name,
depends=(OS_TPL_MIXIN.scheme + OS_TPL_MIXIN.term)))
return result
def ALL_MIXINS(): def ALL_MIXINS(user):
return [IPNETWORK_MIXIN, IPNETWORKINTERFACE_MIXIN] mixins = [
# IPNETWORK_MIXIN,
# IPNETWORKINTERFACE_MIXIN,
CREDENTIALS_MIXIN,
OS_TPL_MIXIN,
]
template_mixins = os_tpl_mixins(user)
for template in template_mixins:
mixins.append(template)
return mixins
def ALL_ACTIONS(): def ALL_ACTIONS():
......
"""" Utilities for the OCCI implementation of CIRCLE """ """" Utilities for the OCCI implementation of CIRCLE """
from django.http import JsonResponse, HttpResponse from django.http import HttpResponse
import json import json
class OcciResourceInstanceNotExist(Exception): class OcciException(Exception):
def __init__(self): """ The superclass for OCCI exceptions. It creates a response to be
message = "The resource instance does not exist." returned when an error occures. """
super(OcciResourceInstanceNotExist, self).__init__(message) def __init__(self, *args, **kwargs):
self.response = JsonResponse({"error": message}, status=404, message = kwargs.get("message", "An error occured.")
charset="utf-8") status = kwargs.get("status", 400)
super(OcciException, self).__init__(message)
self.response = occi_response({"error": message}, status=status)
class OcciResourceInstanceNotExist(OcciException):
""" An exception to be raised when a resource instance which has been
asked for does not exist. """
def __init__(self, *args, **kwargs):
if "message" not in kwargs:
kwargs["message"] = "The resource instance does not exist."
super(OcciResourceInstanceNotExist, self).__init__(self, **kwargs)
class OcciActionInvocationError(OcciException):
""" An exception to be raised when an action could not be invoked on
an entity instance for some reason """
def __init__(self, *args, **kwargs):
if "message" not in kwargs:
kwargs["message"] = "Could not invoke action."
super(OcciActionInvocationError, self).__init__(self, **kwargs)
class OcciResourceCreationError(OcciException):
""" An exception to be raised when a resource instance could not be
created for a reason. """
def __init__(self, *args, **kwargs):
if "message" not in kwargs:
kwargs["message"] = "Could not create resource instance."
super(OcciResourceCreationError, self).__init__(self, **kwargs)
class OcciActionInvocationError(Exception): class OcciResourceDeletionError(OcciException):
""" An exception to be raised when a resource instance could not be
deleted for some reason. """
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
message = kwargs.get("message", "Could not invoke action.") if "message" not in kwargs:
super(OcciActionInvocationError, self).__init__(message) kwargs["message"] = "Could not delete resource instance."
self.response = JsonResponse({"error": message}, status=400, super(OcciResourceDeletionError, self).__init__(self, **kwargs)
charset="utf-8")
class OcciRequestNotValid(OcciException):
class OcciResponse(HttpResponse): """ An exception to be raised when the request sent by the client is
""" A response class with its occi headers set """ not valid for a reason. (e.g, wrong content type, etc.) """
# TODO: setting occi specific headers def __init__(self, *args, **kwargs):
def init(self, data, response_type, *args, **kwargs): if "message" not in kwargs:
if response_type == "json": kwargs["message"] = "The request is not valid."
data = json.dumps(data) super(OcciRequestNotValid, self).__init__(self, **kwargs)
super(OcciResponse, self).__init__(data, status=418)
if response_type == "json":
self["Content-Type"] = "application/json" def occi_response(data, *args, **kwargs):
else: """ This function returns a response with its headers set, like occi
self["Content-Type"] = "text/plain" server. The content_type of the response is application/json
self["Server"] = "OCCI/1.2" by default. """
status = kwargs.get("status", 200)
# TODO: support for renderings other than json (e.g., text/plain)
data = json.dumps(data)
response = HttpResponse(data, charset="utf-8", status=status,
content_type="application/json; charset=utf-8")
# TODO: use Server header instead of OCCI-Server
response["OCCI-Server"] = "OCCI/1.2"
response["Accept"] = "application/json"
return response
def validate_request(request, authentication_required=True,
has_data=False, **kwargs):
""" This function checks if the request's content type is
application/json and if the data is a valid json object. If the
authentication_required parameter is True, it will also check if
the user is authenticated. """
# checking if the user is authenticated
if authentication_required:
if not request.user.is_authenticated():
raise OcciRequestNotValid("Authentication required.", status=403)
if has_data:
# checking content type
if request.META.get("CONTENT_TYPE") != "application/json":
raise OcciRequestNotValid("Only application/json content type is " +
"allowed.")
# checking if the data is a valid json
try:
data = json.loads(request.body.decode("utf-8"))
except KeyError:
raise OcciRequestNotValid("The json provided in the request is " +
"not valid.")
# checking if provided keys are in the json
if "data_keys" in kwargs:
for key in kwargs["data_keys"]:
if key not in data:
raise OcciRequestNotValid(key + " key is required.")
# if validation was successful, the function returns the parsed
# json data
return data
def set_optional_attributes(self, optional_attributes, kwargs): def set_optional_attributes(self, optional_attributes, kwargs):
...@@ -43,15 +114,6 @@ def set_optional_attributes(self, optional_attributes, kwargs): ...@@ -43,15 +114,6 @@ def set_optional_attributes(self, optional_attributes, kwargs):
setattr(self, k, v) setattr(self, k, v)
def serialize_attributes(attributes):
""" Creates a list of attributes, that are serializable to json from
a list of Attribute class objects. """
atrs = []
for attribute in attributes:
atrs.append(attribute.render_as_json())
return atrs
def action_list_for_resource(actions): def action_list_for_resource(actions):
""" Creates a list of actions for Resource object rendering """ """ Creates a list of actions for Resource object rendering """
acts = [] acts = []
......
...@@ -5,15 +5,20 @@ ...@@ -5,15 +5,20 @@
import json import json
from django.views.generic import View from django.views.generic import View
from django.contrib.auth import logout from django.contrib.auth import logout
from django.http import HttpResponse, JsonResponse, Http404 from django.http import Http404
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.csrf import ensure_csrf_cookie
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from vm.models.instance import Instance from vm.models.instance import Instance, InstanceTemplate
from forms import OcciAuthForm from forms import OcciAuthForm
from occi_infrastructure import Compute from occi_infrastructure import Compute
from occi_utils import (OcciResourceInstanceNotExist, from occi_utils import (OcciResourceInstanceNotExist,
OcciActionInvocationError) OcciActionInvocationError,
OcciRequestNotValid,
OcciResourceCreationError,
OcciResourceDeletionError,
occi_response,
validate_request)
from occi_instances import ALL_KINDS, ALL_MIXINS, ALL_ACTIONS from occi_instances import ALL_KINDS, ALL_MIXINS, ALL_ACTIONS
...@@ -27,7 +32,7 @@ class OcciLoginView(View): ...@@ -27,7 +32,7 @@ class OcciLoginView(View):
""" Returns a response with a cookie to be used for requests other """ Returns a response with a cookie to be used for requests other
than get. """ than get. """
result = {"result": "OK"} result = {"result": "OK"}
return JsonResponse(result, charset="utf-8") return occi_response(result)
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
""" 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
...@@ -36,12 +41,12 @@ class OcciLoginView(View): ...@@ -36,12 +41,12 @@ class OcciLoginView(View):
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"}
return JsonResponse(result, charset="utf-8") return occi_response(result)
else: else:
errors = dict([(k, [unicode(e) for e in v]) errors = dict([(k, [unicode(e) for e in v])
for k, v in form.errors.items()]) for k, v in form.errors.items()])
result = {"result": "ERROR", "errors": errors["__all__"]} result = {"result": "ERROR", "errors": errors["__all__"]}
return JsonResponse(result, status=400, charset="utf-8") return occi_response(result, status=400)
class OcciLogoutView(View): class OcciLogoutView(View):
...@@ -49,42 +54,70 @@ class OcciLogoutView(View): ...@@ -49,42 +54,70 @@ class OcciLogoutView(View):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
logout(request) logout(request)
result = {"result": "OK"} result = {"result": "OK"}
return JsonResponse(result, charset="utf-8") return occi_response(result)
class OcciQueryInterfaceView(View): class OcciQueryInterfaceView(View):
""" The view of the OCCI query interface """ """ The view of the OCCI query interface """
@method_decorator(ensure_csrf_cookie) @method_decorator(ensure_csrf_cookie)
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
try:
validate_request(request)
except OcciRequestNotValid as e:
return e.response
result = {"kinds": [], "mixins": [], "actions": []} result = {"kinds": [], "mixins": [], "actions": []}
for kind in ALL_KINDS(): for kind in ALL_KINDS():
result["kinds"].append(kind.render_as_json()) result["kinds"].append(kind.render_as_json())
for mixin in ALL_MIXINS(): for mixin in ALL_MIXINS(request.user):
result["mixins"].append(mixin.render_as_json()) result["mixins"].append(mixin.render_as_json())
for action in ALL_ACTIONS(): for action in ALL_ACTIONS():
result["actions"].append(action.render_as_json()) result["actions"].append(action.render_as_json())
return JsonResponse(result, charset="utf-8") return occi_response(result)
def post(self, request, *args, **kwargs):
return occi_response({"error": "User defined mixins are not " +
"supported."}, status=405)
def delete(self, request, *args, **kwargs):
return occi_response({"error": "User defined mixins are not " +
"supported."}, status=405)
def put(self, request, *args, **kwargs):
return occi_response({"error": "Put method is not defined on the " +
"query interface."}, status=400)
class OcciComputeCollectionView(View): class OcciComputeCollectionView(View):
@method_decorator(ensure_csrf_cookie) @method_decorator(ensure_csrf_cookie)
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
if not request.user.is_authenticated(): try:
return HttpResponse(status=403) validate_request(request)
except OcciRequestNotValid as e:
return e.response
vms = (Instance.get_objects_with_level("user", request.user) vms = (Instance.get_objects_with_level("user", request.user)
.filter(destroyed_at=None)) .filter(destroyed_at=None))
json = {"resources": []} json = {"resources": []}
for vm in vms: for vm in vms:
json["resources"].append(Compute(vm).render_as_json()) json["resources"].append(Compute(vm).render_as_json())
return JsonResponse(json, charset="utf-8") return occi_response(json)
def put(self, request, *args, **kwargs):
# TODO: vm creation
return occi_response({"message": "TODO"})
try:
Instance.create_from_template(
InstanceTemplate.objects.get(pk=1), request.user)
except Exception:
return occi_response({"test": "tset"})
return occi_response({})
class OcciComputeView(View): class OcciComputeView(View):
""" View of a compute instance """ """ View of a compute instance """
def get_vm_object(self, request, vmid): def get_vm_object(self, user, vmid):
try: try:
vm = get_object_or_404(Instance.get_objects_with_level("user", vm = get_object_or_404(Instance.get_objects_with_level("user",
request.user), pk=vmid) user).filter(destroyed_at=None), pk=vmid)
except Http404: except Http404:
raise OcciResourceInstanceNotExist() raise OcciResourceInstanceNotExist()
return Compute(vm) return Compute(vm)
...@@ -92,20 +125,22 @@ class OcciComputeView(View): ...@@ -92,20 +125,22 @@ class OcciComputeView(View):
@method_decorator(ensure_csrf_cookie) @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 occi_response({"error": "Authentication required."},
status=403)
try: try:
compute = self.get_vm_object(request, kwargs["id"]) compute = self.get_vm_object(request.user, kwargs["id"])
except OcciResourceInstanceNotExist as e: except OcciResourceInstanceNotExist as e:
return e.json_response return e.response
return JsonResponse(compute.render_as_json(), charset="utf-8") return occi_response(compute.render_as_json(), charset="utf-8")
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
requestData = json.loads(request.body.decode("utf-8")) requestData = json.loads(request.body.decode("utf-8"))
# TODO post request w/o action, compute creation
if not requestData["action"]: if not requestData["action"]:
return HttpResponse(status=404) return occi_response({"error": "Action invocation rendering " +
"is not supplied."},
status=400)
try: try:
compute = self.get_vm_object(request, kwargs["id"]) compute = self.get_vm_object(request.user, kwargs["id"])
except OcciResourceInstanceNotExist as e: except OcciResourceInstanceNotExist as e:
return e.response return e.response
try: try:
...@@ -114,5 +149,49 @@ class OcciComputeView(View): ...@@ -114,5 +149,49 @@ class OcciComputeView(View):
requestData.get("attributes", None)) requestData.get("attributes", None))
except OcciActionInvocationError as e: except OcciActionInvocationError as e:
return e.response return e.response
# TODO: proper return value return occi_response(compute.render_as_json(), status=200)
return JsonResponse(compute.render_as_json(), status=200)
def put(self, request, *args, **kwargs):
# checking if the requested resource exists
try:
self.get_vm_object(request.user, kwargs["id"])
except OcciResourceInstanceNotExist:
# there has to be a mixins array in the provided rendering
data_keys = ["mixins"]
try:
requestData = validate_request(request, True, True,
data_keys=data_keys)
except OcciRequestNotValid as e:
return e.response
ostpl = "http://circlecloud.org/occi/templates/os#os_template_"
for mixin in requestData["mixins"]:
if ostpl in mixin:
tpl_id = int(mixin.replace(ostpl, ""))
try:
template = get_object_or_404(
InstanceTemplate.get_objects_with_level(
"user", request.user), pk=tpl_id)
except Http404:
return occi_response({"error": "Template does not" +
"exist."})
try:
vm = Instance.create_from_template(template,
request.user)
except:
return OcciResourceCreationError().response
compute = Compute(vm)
return occi_response(compute.render_as_json())
# TODO: update compute instance
return occi_response({"error": "Update of compute instances is " +
"not implemented."}, status=501)
def delete(self, request, *args, **kwargs):
try:
compute = self.get_vm_object(request.user, kwargs["id"])
except OcciResourceInstanceNotExist as e:
return e.response
try:
compute.vm.destroy(user=request.user)
except:
return OcciResourceDeletionError().response
return occi_response({"result": "Compute instance deleted."})
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