Commit a2911611 by Kálmán Viktor

occi: link storage to computes

parent 33c94c56
import re import re
from django.shortcuts import get_object_or_404
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 django.utils import timezone from django.utils import timezone
...@@ -43,6 +44,8 @@ occi_os_tpl_regex = re.compile( ...@@ -43,6 +44,8 @@ occi_os_tpl_regex = re.compile(
'class="mixin"; ?location=".*"; ?title=".*"$' 'class="mixin"; ?location=".*"; ?title=".*"$'
) )
occi_attribute_link_regex = '^/%s/(?P<id>\d+)/?'
class Category(): class Category():
"""Represents a Category object """Represents a Category object
...@@ -395,7 +398,7 @@ class StorageLink(Link): ...@@ -395,7 +398,7 @@ class StorageLink(Link):
def init_attrs(self, instance, disk): def init_attrs(self, instance, disk):
self.attrs = {} self.attrs = {}
self.attrs['occi.core.id'] = "%d_at_%d" % (disk.pk, instance.pk) self.attrs['occi.core.id'] = "vm%d_disk%d" % (instance.pk, disk.pk)
self.attrs['occi.core.target'] = Storage(disk).render_location() self.attrs['occi.core.target'] = Storage(disk).render_location()
self.attrs['occi.core.source'] = Compute(instance).render_location() self.attrs['occi.core.source'] = Compute(instance).render_location()
# deviceid? mountpoint? # deviceid? mountpoint?
...@@ -404,10 +407,40 @@ class StorageLink(Link): ...@@ -404,10 +407,40 @@ class StorageLink(Link):
self.instance = instance self.instance = instance
self.disk = disk self.disk = disk
@classmethod
def create_object(cls, data):
attributes = {}
for d in data:
attr = occi_attribute_regex.match(d)
if attr:
attributes[attr.group("attribute")] = attr.group("value")
source = attributes.get("occi.core.source")
target = attributes.get("occi.core.target")
if not (source and target):
return None
# TODO user
user = User.objects.get(username="test")
g = re.match(occi_attribute_link_regex % "storage", target)
disk_pk = g.group("id")
g = re.match(occi_attribute_link_regex % "vm", source)
vm_pk = g.group("id")
disk = get_object_or_404(Disk, pk=disk_pk)
vm = get_object_or_404(Instance, pk=vm_pk)
vm.attach_disk(user=user, disk=disk)
cls.location = "%sstoragelink/%svm_%sdisk" % (OCCI_ADDR, vm_pk,
disk_pk)
return cls
def render_location(self): def render_location(self):
return "/link/storagelink/%d_at_%d" % (self.disk.pk, self.instance.pk) return "/link/storagelink/vm%d_disk%d" % (instance.pk, disk.pk)
def render_body(self): def render_as_link(self):
kind = STORAGE_LINK_KIND kind = STORAGE_LINK_KIND
return render_to_string("occi/link.html", { return render_to_string("occi/link.html", {
...@@ -417,6 +450,14 @@ class StorageLink(Link): ...@@ -417,6 +450,14 @@ class StorageLink(Link):
'attrs': self.attrs, 'attrs': self.attrs,
}) })
def render_as_category(self):
kind = STORAGE_LINK_KIND
return render_to_string("occi/storagelink.html", {
'kind': kind,
'attrs': self.attrs,
})
"""predefined stuffs """predefined stuffs
......
...@@ -9,5 +9,5 @@ Category: compute; scheme="{{ kind.scheme }}"; class="{{ kind.class }}"; ...@@ -9,5 +9,5 @@ Category: compute; scheme="{{ kind.scheme }}"; class="{{ kind.class }}";
{% endfor %} {% endfor %}
{% for l in links %} {% for l in links %}
{{ l.render_body }} {{ l.render_as_link }}
{% endfor %} {% endfor %}
Category: compute; scheme="{{ kind.scheme }}"; class="{{ kind.class }}";
{% for k, v in attrs.items %}
X-OCCI-Attribute: {{ k }}={% if v.isdigit == False or k == "occi.core.id" %}"{{ v }}"{% else %}{{ v }}{% endif %}
{% endfor %}
...@@ -20,7 +20,7 @@ from django.conf.urls import url, patterns ...@@ -20,7 +20,7 @@ from django.conf.urls import url, patterns
from occi.views import ( from occi.views import (
QueryInterface, ComputeInterface, VmInterface, OsTplInterface, QueryInterface, ComputeInterface, VmInterface, OsTplInterface,
StorageInterface, DiskInterface, StorageInterface, DiskInterface, StorageLinkInterface
) )
urlpatterns = patterns( urlpatterns = patterns(
...@@ -31,4 +31,8 @@ urlpatterns = patterns( ...@@ -31,4 +31,8 @@ urlpatterns = patterns(
url(r'^vm/(?P<pk>\d+)/$', VmInterface.as_view(), name="occi.vm"), url(r'^vm/(?P<pk>\d+)/$', VmInterface.as_view(), name="occi.vm"),
url(r'^storage/$', StorageInterface.as_view(), name="occi.storage"), url(r'^storage/$', StorageInterface.as_view(), name="occi.storage"),
url(r'^disk/(?P<pk>\d+)/$', DiskInterface.as_view(), name="occi.disk"), url(r'^disk/(?P<pk>\d+)/$', DiskInterface.as_view(), name="occi.disk"),
url(r'^link/storagelink/$', StorageLinkInterface.as_view()),
url(r'^link/storagelink/vm(?P<vm_pk>\d+)_disk(?P<disk_pk>\d+)/$',
StorageLinkInterface.as_view(), name="occi.storagelink"),
) )
from django.http import HttpResponse from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
from django.views.generic import View, DetailView from django.views.generic import View, DetailView
...@@ -10,6 +11,7 @@ from .occi import ( ...@@ -10,6 +11,7 @@ from .occi import (
Compute, Compute,
Storage, Storage,
OsTemplate, OsTemplate,
StorageLink,
COMPUTE_KIND, COMPUTE_KIND,
STORAGE_KIND, STORAGE_KIND,
LINK_KIND, LINK_KIND,
...@@ -184,3 +186,40 @@ class DiskInterface(DetailView): ...@@ -184,3 +186,40 @@ class DiskInterface(DetailView):
@method_decorator(csrf_exempt) @method_decorator(csrf_exempt)
def dispatch(self, *args, **kwargs): def dispatch(self, *args, **kwargs):
return super(DiskInterface, self).dispatch(*args, **kwargs) return super(DiskInterface, self).dispatch(*args, **kwargs)
class StorageLinkInterface(View):
def get_vm_and_disk(self):
vm = get_object_or_404(Instance, pk=self.kwargs['vm_pk'])
disk = get_object_or_404(Disk, pk=self.kwargs['disk_pk'])
return vm, disk
def get(self, request, *args, **kwargs):
vm, disk = self.get_vm_and_disk()
sl = StorageLink(instance=vm, disk=disk)
return HttpResponse(
sl.render_as_category(),
content_type="text/plain",
)
def post(self, request, *args, **kwargs):
# we don't support actions for storagelinks
# (they don't even exist in the model)
if request.GET.get("action"):
return HttpResponse("", status=500)
else:
data = get_post_data_from_request(request)
sl = StorageLink.create_object(data=data)
response = HttpResponse(
"X-OCCI-Location: %s" % sl.location,
status=201,
content_type="text/plain",
)
return response
return HttpResponse()
@method_decorator(csrf_exempt)
def dispatch(self, *args, **kwargs):
return super(StorageLinkInterface, self).dispatch(*args, **kwargs)
...@@ -817,7 +817,7 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin, ...@@ -817,7 +817,7 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
return acts return acts
def get_merged_activities(self, user=None): def get_merged_activities(self, user=None):
whitelist = ("create_disk", "download_disk") whitelist = ("create_disk", "download_disk", "attach_disk")
acts = self.get_activities(user) acts = self.get_activities(user)
merged_acts = [] merged_acts = []
latest = None latest = None
......
...@@ -1284,3 +1284,39 @@ class DetachNetwork(DetachMixin, AbstractNetworkOperation): ...@@ -1284,3 +1284,39 @@ class DetachNetwork(DetachMixin, AbstractNetworkOperation):
id = "_detach_network" id = "_detach_network"
name = _("detach network") name = _("detach network")
task = vm_tasks.detach_network task = vm_tasks.detach_network
@register_operation
class AttachDiskOperation(InstanceOperation):
id = 'attach_disk'
name = _("attach disk")
description = _("Attach an already created disk to the virtual machine.")
required_perms = ()
accept_states = ('STOPPED', 'PENDING', 'RUNNING')
def _operation(self, user, activity, disk):
devnums = list(ascii_lowercase)
for d in self.instance.disks.all():
devnums.remove(d.dev_num)
disk.dev_num = devnums.pop(0)
disk.save()
self.instance.disks.add(disk)
if self.instance.is_running:
with activity.sub_activity(
'deploying_disk',
readable_name=ugettext_noop("deploying disk")
):
disk.deploy()
self.instance._attach_disk(parent_activity=activity, disk=disk)
activity.result = create_readable(
ugettext_noop("%(name)s (#%(pk)s), dev num: %(dev_num)s"),
name=disk.name, pk=disk.pk, dev_num=disk.dev_num
)
def get_activity_name(self, kwargs):
return create_readable(
ugettext_noop("attach disk %(name)s"),
name=kwargs['disk'].name)
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