Commit ca527975 by Kálmán Viktor

occi: create vms with template

parent 452214f8
......@@ -3,14 +3,17 @@ import re
from django.contrib.auth.models import User
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.instance import ACCESS_METHODS
from vm.models.instance import ACCESS_METHODS, pwgen
OCCI_ADDR = "http://localhost:8080/"
X86_ARCH = ARCHITECTURES[1][0]
X64_ARCH = ARCHITECTURES[0][0]
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(
'^Category: (?P<term>[a-zA-Z]+); ?scheme=".+"; ?class="action"$')
......@@ -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():
"""Represents a Category object
......@@ -113,72 +122,116 @@ class Resource(Entity):
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 = {}
if instance:
self.location = "%svm/%d/" % (OCCI_ADDR, instance.pk)
self.instance = instance
self.init_attrs()
elif attrs:
self.attrs = attrs
self._create_object()
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",
}
@classmethod
def create_object(cls, data):
# TODO user
user = User.objects.get(username="test")
template = None
attributes = {}
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 = {}
for a in self.attrs:
t = a.split("=")
params[self.translate.get(t[0])] = t[1]
params['owner'] = user
title = attributes.get("occi.core.title")
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['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['owner'] = User.objects.get(username="test")
params['name'] = "from occi yo"
i = Instance.create(params=params, disks=[], networks=[],
# if no name is given
if not params.get("name"):
params['name'] = "Created via OCCI by %s" % user
inst = Instance.create(params=params, disks=[], networks=[],
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):
return "%s" % self.location
def render_body(self):
kind = COMPUTE_KIND
mixins = []
if self.instance.template:
mixins.append(OsTemplate(self.instance.template))
return render_to_string("occi/compute.html", {
'kind': kind,
'attrs': self.attrs,
'mixins': mixins,
})
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)
priority = self.instance.priority
self.attrs['occi.compute.speed'] = priority/100.0 * 5.0
def trigger_action(self, data):
method = None
action_term = None
for d in data:
m = occi_attribute_regex.match(d)
if m:
method = m.group("method")
attribute = m.group("attribute")
if attribute == "method":
method = m.group("value")
m = occi_action_regex.match(d)
if m:
action_term = m.group("term")
......
......@@ -2,4 +2,5 @@ Category: compute; scheme="{{ kind.scheme }}"; class="{{ kind.class }}";
{% spaceless %}
{% for k, v in attrs.items %}
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 %}
......@@ -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):
def get(self, request, *args, **kwargs):
......@@ -50,17 +70,14 @@ class ComputeInterface(View):
)
def post(self, request, *args, **kwargs):
occi_attrs = None
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
data = get_post_data_from_request(request)
c = Compute(attrs=occi_attrs)
response = HttpResponse()
response['Location'] = c.location
c = Compute.create_object(data=data)
response = HttpResponse(
"X-OCCI-Location: %s" % c.location,
status=201,
content_type="text/plain",
)
return response
@method_decorator(csrf_exempt) # decorator on post method doesn't work
......@@ -80,24 +97,13 @@ class VmInterface(DetailView):
)
def post(self, request, *args, **kwargs):
data = self.get_post_data(request)
data = get_post_data_from_request(request)
action = request.GET.get("action")
vm = self.get_object()
if action:
Compute(instance=vm).trigger_action(data)
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
def dispatch(self, *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