Commit ca527975 by Kálmán Viktor

occi: create vms with template

parent 452214f8
...@@ -3,14 +3,17 @@ import re ...@@ -3,14 +3,17 @@ import re
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.template.loader import render_to_string from django.template.loader import render_to_string
from vm.models import Instance, Lease from vm.models import Instance, InstanceTemplate, Lease
from vm.models.common import ARCHITECTURES from vm.models.common import ARCHITECTURES
from vm.models.instance import ACCESS_METHODS from vm.models.instance import ACCESS_METHODS, pwgen
OCCI_ADDR = "http://localhost:8080/" OCCI_ADDR = "http://localhost:8080/"
X86_ARCH = ARCHITECTURES[1][0]
X64_ARCH = ARCHITECTURES[0][0]
occi_attribute_regex = re.compile( occi_attribute_regex = re.compile(
'^X-OCCI-Attribute: ?method="(?P<method>[a-zA-Z]+)"$') '^X-OCCI-Attribute: ?(?P<attribute>[a-zA-Z\.]+)="?(?P<value>[^"]*)"?$')
occi_action_regex = re.compile( occi_action_regex = re.compile(
'^Category: (?P<term>[a-zA-Z]+); ?scheme=".+"; ?class="action"$') '^Category: (?P<term>[a-zA-Z]+); ?scheme=".+"; ?class="action"$')
...@@ -32,6 +35,12 @@ compute_action_to_operation = { ...@@ -32,6 +35,12 @@ compute_action_to_operation = {
} }
} }
occi_os_tpl_regex = re.compile(
'^Category: ?os_tpl_(?P<template_pk>\d+); ?'
'scheme=".*/infrastructure/os_tpl#"; ?'
'class="mixin"; ?location=".*"; ?title=".*"$'
)
class Category(): class Category():
"""Represents a Category object """Represents a Category object
...@@ -113,72 +122,116 @@ class Resource(Entity): ...@@ -113,72 +122,116 @@ class Resource(Entity):
class Compute(Resource): class Compute(Resource):
# TODO better init, for new resources """ Note: 100 priority = 5 Ghz
"""
def __init__(self, instance=None, attrs=None, **kwargs): def __init__(self, instance=None, data=None):
self.attrs = {} self.attrs = {}
if instance: if instance:
self.location = "%svm/%d/" % (OCCI_ADDR, instance.pk) self.location = "%svm/%d/" % (OCCI_ADDR, instance.pk)
self.instance = instance self.instance = instance
self.init_attrs() self.init_attrs()
elif attrs:
self.attrs = attrs
self._create_object()
translate = { @classmethod
'occi.core.id': "id", def create_object(cls, data):
'occi.compute.architecture': "arch", # TODO user
'occi.compute.cores': "num_cores", user = User.objects.get(username="test")
'occi.compute.hostname': "short_hostname", template = None
'occi.compute.speed': "priority", attributes = {}
'occi.compute.memory': "ram_size",
}
translate_arch = { for d in data:
tmpl = occi_os_tpl_regex.match(d)
if tmpl:
pk = tmpl.group("template_pk")
template = InstanceTemplate.objects.get(pk=pk)
} attr = occi_attribute_regex.match(d)
if attr:
attributes[attr.group("attribute")] = attr.group("value")
def _create_object(self):
params = {} params = {}
for a in self.attrs: params['owner'] = user
t = a.split("=") title = attributes.get("occi.core.title")
params[self.translate.get(t[0])] = t[1] if title:
params['name'] = title
if template:
inst = Instance.create_from_template(template=template, **params)
else:
# trivial
if "x86" in attributes['occi.compute.architecture']:
params['arch'] = X86_ARCH
else:
params['arch'] = X64_ARCH
params['num_cores'] = int(attributes['occi.compute.cores'])
speed = float(attributes['occi.compute.speed'])
if speed/5.0 > 1:
priority = 100
else:
priority = int(speed/5.0 * 100.0)
params['priority'] = priority
memory = float(attributes['occi.compute.memory']) * 1024
params['ram_size'] = params['max_ram_size'] = int(memory)
params['pw'] = pwgen()
# non trivial
params['system'] = "OCCI Blank Compute"
params['lease'] = Lease.objects.all()[0] params['lease'] = Lease.objects.all()[0]
params['priority'] = 10
params['max_ram_size'] = params['ram_size']
params['system'] = ""
params['pw'] = "killmenow"
params['arch'] = (ARCHITECTURES[0][0] if "64" in params['arch'] else
ARCHITECTURES[1][0])
params['access_method'] = ACCESS_METHODS[0][0] params['access_method'] = ACCESS_METHODS[0][0]
params['owner'] = User.objects.get(username="test")
params['name'] = "from occi yo" # if no name is given
i = Instance.create(params=params, disks=[], networks=[], if not params.get("name"):
params['name'] = "Created via OCCI by %s" % user
inst = Instance.create(params=params, disks=[], networks=[],
req_traits=[], tags=[]) req_traits=[], tags=[])
self.location = "%svm/%d/" % (OCCI_ADDR, i.pk)
cls.location = "%svm/%d" % (OCCI_ADDR, inst.pk)
return cls
def render_location(self): def render_location(self):
return "%s" % self.location return "%s" % self.location
def render_body(self): def render_body(self):
kind = COMPUTE_KIND kind = COMPUTE_KIND
mixins = []
if self.instance.template:
mixins.append(OsTemplate(self.instance.template))
return render_to_string("occi/compute.html", { return render_to_string("occi/compute.html", {
'kind': kind, 'kind': kind,
'attrs': self.attrs, 'attrs': self.attrs,
'mixins': mixins,
}) })
def init_attrs(self): def init_attrs(self):
for k, v in self.translate.items(): translate = {
'occi.core.id': "id",
'occi.compute.architecture': "arch",
'occi.compute.cores': "num_cores",
'occi.compute.hostname': "short_hostname",
'occi.compute.speed': "priority",
'occi.compute.memory': "ram_size",
}
for k, v in translate.items():
self.attrs[k] = getattr(self.instance, v, None) self.attrs[k] = getattr(self.instance, v, None)
priority = self.instance.priority
self.attrs['occi.compute.speed'] = priority/100.0 * 5.0
def trigger_action(self, data): def trigger_action(self, data):
method = None method = None
action_term = None action_term = None
for d in data: for d in data:
m = occi_attribute_regex.match(d) m = occi_attribute_regex.match(d)
if m: if m:
method = m.group("method") attribute = m.group("attribute")
if attribute == "method":
method = m.group("value")
m = occi_action_regex.match(d) m = occi_action_regex.match(d)
if m: if m:
action_term = m.group("term") action_term = m.group("term")
......
...@@ -2,4 +2,5 @@ Category: compute; scheme="{{ kind.scheme }}"; class="{{ kind.class }}"; ...@@ -2,4 +2,5 @@ Category: compute; scheme="{{ kind.scheme }}"; class="{{ kind.class }}";
{% spaceless %} {% spaceless %}
{% for k, v in attrs.items %} {% for k, v in attrs.items %}
X-OCCI-Attribute: {{ k }}={% if v.isdigit == False or k == "occi.core.id" %}"{{ v }}"{% else %}{{ v }}{% endif %}{% endfor %} X-OCCI-Attribute: {{ k }}={% if v.isdigit == False or k == "occi.core.id" %}"{{ v }}"{% else %}{{ v }}{% endif %}{% endfor %}
{% for m in mixins %}{{ m.render_body }}{% endfor %}
{% endspaceless %} {% endspaceless %}
...@@ -14,6 +14,26 @@ from .occi import ( ...@@ -14,6 +14,26 @@ from .occi import (
) )
def get_post_data_from_request(request):
""" Returns the post data in an array
"""
post_data = []
accept = request.META.get("HTTP_ACCEPT")
if accept and accept.split(",")[0] == "text/occi":
for k, v in request.META.iteritems():
if k.startswith("HTTP_X_OCCI_ATTRIBUTE"):
for l in v.split(","):
post_data.append("X-OCCI-Attribute: %s" % l.strip())
if k.startswith("HTTP_CATEGORY"):
for l in v.split(","):
post_data.append("Category: %s" % l.strip())
else: # text/plain or missing
for l in request.readlines():
if l:
post_data.append(l.strip())
return post_data
class QueryInterface(View): class QueryInterface(View):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
...@@ -50,17 +70,14 @@ class ComputeInterface(View): ...@@ -50,17 +70,14 @@ class ComputeInterface(View):
) )
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
occi_attrs = None data = get_post_data_from_request(request)
category = None
for k, v in request.META.iteritems():
if k.startswith("HTTP_X_OCCI_ATTRIBUTE"):
occi_attrs = v.split(",")
elif k.startswith("HTTP_CATEGORY") and category is None:
category = v
c = Compute(attrs=occi_attrs) c = Compute.create_object(data=data)
response = HttpResponse() response = HttpResponse(
response['Location'] = c.location "X-OCCI-Location: %s" % c.location,
status=201,
content_type="text/plain",
)
return response return response
@method_decorator(csrf_exempt) # decorator on post method doesn't work @method_decorator(csrf_exempt) # decorator on post method doesn't work
...@@ -80,24 +97,13 @@ class VmInterface(DetailView): ...@@ -80,24 +97,13 @@ class VmInterface(DetailView):
) )
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
data = self.get_post_data(request) data = get_post_data_from_request(request)
action = request.GET.get("action") action = request.GET.get("action")
vm = self.get_object() vm = self.get_object()
if action: if action:
Compute(instance=vm).trigger_action(data) Compute(instance=vm).trigger_action(data)
return HttpResponse() return HttpResponse()
def get_post_data(self, request):
post_data = []
accept = request.META.get("HTTP_ACCEPT")
if accept and accept.split(",")[0] == "text/occi":
pass
else: # text/plain or missing
for l in request.readlines():
if l:
post_data.append(l.strip())
return post_data
@method_decorator(csrf_exempt) # decorator on post method doesn't work @method_decorator(csrf_exempt) # decorator on post method doesn't work
def dispatch(self, *args, **kwargs): def dispatch(self, *args, **kwargs):
return super(VmInterface, self).dispatch(*args, **kwargs) return super(VmInterface, self).dispatch(*args, **kwargs)
......
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