Commit ba26b3e5 by Szabolcs Gelencser

Remove Instance model from current state, use nova.Server instead

parent ef0ed6be
......@@ -49,8 +49,6 @@ class Operation(object):
def __prelude(self, request, kwargs):
"""This method contains the shared prelude of call and async.
"""
self._operation.im_self.get_from_os(request)
defaults = {'system': False, 'user': None}
allargs = dict(defaults, **kwargs) # all arguments
......@@ -229,12 +227,26 @@ def register_operation(op_cls, op_id=None, target_cls=None):
assert not hasattr(target_cls, op_id), (
"target class already has an attribute with this id")
if not issubclass(target_cls, OperatedMixin):
raise TypeError("%r is not a subclass of %r" %
(target_cls.__name__, OperatedMixin.__name__))
if not hasattr(target_cls, operation_registry_name):
setattr(target_cls, operation_registry_name, dict())
getattr(target_cls, operation_registry_name)[op_id] = op_cls
def get_operation_class(cls, name):
ops = getattr(cls, operation_registry_name, {})
op = ops.get(name)
if op:
return op
else:
raise AttributeError("%r object has no attribute %r" %
(cls.__name__, name))
def __getattr__(self, name):
# NOTE: __getattr__ is only called if the attribute doesn't already
# exist in your __dict__
return get_operation_class(type(self), name)(self)
target_cls.__getattr__ = __getattr__
return op_cls
{% load i18n %}
{% load instance_tags %}
<div class="panel panel-default">
<div class="panel-heading">
<div class="pull-right toolbar">
......@@ -26,10 +28,10 @@
<div class="list-group" id="vm-list-view">
<div id="dashboard-vm-list">
{% for i in instances %}
<a href="{{ i.get_absolute_url }}" class="list-group-item
<a href="{% url 'dashboard.views.detail' i.id %}" class="list-group-item
{% if forloop.last and instances|length < 5 %} list-group-item-last{% endif %}">
<span class="index-vm-list-name">
<i class="fa {{ i.get_status_icon }}" title="{{ i.get_status_display }}"></i>
<i class="fa {{ i | get_status_icon }}" title="{{ i.get_status_display }}"></i>
{{ i.name }}
</span>
<small class="text-muted index-vm-list-host">
......
......@@ -2,6 +2,7 @@
{% load staticfiles %}
{% load i18n %}
{% load pipeline %}
{% load instance_tags %}
{% block title-page %}{{ instance.name }} | vm{% endblock %}
......@@ -101,8 +102,9 @@
{% if is_new_state %}
fa-spinner fa-spin
{% else %}
{{ instance.get_status_icon }}{% endif %}"></i>
<span>{{ instance.get_status_display|upper }}</span>
{{ instance | get_status_icon }}
{% endif %}"></i>
<span>{{ instance|get_status_display|upper }}</span>
</span>
</div>
......@@ -223,7 +225,7 @@
</li>
<li>
<a href="#activity" data-toggle="pill" data-target="#_activity" class="text-center"
data-activity-url="{% url "dashboard.views.vm-activity-list" instance.pk %}">
data-activity-url="{% url "dashboard.views.vm-activity-list" instance.id %}">
<i class="fa fa-clock-o fa-2x"></i><br>
{% trans "Activity" %}</a>
</li>
......
......@@ -5,48 +5,6 @@
<div class="alert alert-warning">
{% trans "You are not authorized to access the VNC console." %}
</div>
{% endif %}
<div class="row">
<div class="col-xs-7">
<div class="btn-toolbar">
{% if perms.vm.access_console %}
<button id="sendCtrlAltDelButton" class="btn btn-danger btn-sm">
{% trans "Send Ctrl+Alt+Del" %}
</button>
<button id="sendPasswordButton" class="btn btn-default btn-sm">
{% trans "Type password" %}
</button>
{% endif %}
</div>
</div>
<div class="col-xs-5 text-right">
<button id="getScreenshotButton" class="btn btn-info btn-sm" data-vm-pk="{{ instance.pk }}">
<i class="fa fa-photo"></i> {% trans "Screenshot" %}
</button>
</div>
</div>
{% if True %}
<div class="alert alert-info" id="noVNC_status"></div>
{% endif %}
<div id="vm-console-screenshot">
<h3>
<button class="btn btn-danger btn-sm pull-right">{% trans "Close" %}</button>
{% trans "Screenshot" %}
</h3>
<img alt="{% trans "Screenshot" %}"/>
<hr />
</div>
{% if True %}
{% else %}
<iframe src="{{ vnc_url }}" style="width: 100%; height: 664px;"></iframe>
{#<canvas id="noVNC_canvas" width="640" height="20">Canvas not supported.#}
{#</canvas>#}
{#<script>#}
{#var INCLUDE_URI = '{% static "no-vnc/include/" %}';#}
{#var VNC_URL = "{{ vnc_url }}";#}
{#</script>#}
{% endif %}
......@@ -4,7 +4,7 @@
<div class="col-md-4">
<dl id="home_name_and_description">
<dt>{% trans "System" %}:</dt>
<dd><i class="fa fa-{{ os_type_icon }}"></i> {{ instance.system }}</dd>
<dd><i class="fa fa-{{ os_type_icon }}"></i> {{ instance.image_name }}</dd>
<dt style="margin-top: 5px;">
{% trans "Name" %}:
{% if is_operator %}
......
......@@ -32,7 +32,7 @@
<input type="submit" class="btn btn-success btn-sm"/>
</div>
<a href="{% url "request.views.request-resource" vm_pk=object.pk %}"
<a href="{% url "request.views.request-resource" vm_pk=object.id %}"
class="btn btn-primary btn-sm" id="vm-request-resource">
<i class="fa fa-tasks"></i>
{% trans "Request resources" %}
......
from django.template import Library
from django.utils.translation import ugettext_lazy as _
register = Library()
@register.filter
def get_status_icon(instance):
return {
'BUILDING': 'fa-rocket',
'ACTIVE': 'fa-play',
'SHUTOFF': 'fa-stop',
'SUSPENDED': 'fa-pause',
'ERROR': 'fa-warning',
'SOFT_DELETED': 'fa-trash-o',
'HARD_DELETED': 'fa-trash-o',
}.get(instance.status, 'fa-question')
@register.filter
def get_status_display(instance):
DISPLAYS = {
'PAUSED': _('paused'),
'SUSPENDED': _('suspended'),
'ACTIVE': _('active'),
'SHUTOFF': _('shutoff'),
'RESCUED': _('rescued'),
'STOPPED': _('stopped'),
'SOFT_DELETED': _('soft deleted'),
'ERROR': _('error'),
'BUILDING': _('building'),
}
return DISPLAYS[instance.status] if instance.status in DISPLAYS else instance.status
\ No newline at end of file
......@@ -18,6 +18,7 @@ from __future__ import unicode_literals, absolute_import
import logging
import openstack_api
from braces.views import LoginRequiredMixin
from dashboard.models import GroupProfile
from django.conf import settings
......@@ -40,7 +41,7 @@ class IndexView(LoginRequiredMixin, TemplateView):
user = self.request.user
context = super(IndexView, self).get_context_data(**kwargs)
instances = Instance.list_from_os(self.request)
instances = openstack_api.nova.server_list(self.request)[0] #TODO: flatten?
context.update({
'instances': instances[:5],
......@@ -106,7 +107,8 @@ class IndexView(LoginRequiredMixin, TemplateView):
'operator', user, disregard_superuser=True).all()[:5]
# vxlan
context['vxlans'] = Vxlan.list_from_os(self.request)[:5]
all_vxlans = openstack_api.neutron.network_list_for_tenant(self.request, self.request.user.tenant_id)
context['vxlans'] = all_vxlans[:5]
# toplist
if settings.STORE_URL:
......
......@@ -20,6 +20,7 @@ import logging
import re
from collections import OrderedDict
import openstack_api
from braces.views import LoginRequiredMixin
from common.models import HumanReadableException
from django.conf import settings
......@@ -200,7 +201,6 @@ class CheckedDetailView(LoginRequiredMixin, DetailView):
#
class OperationView(RedirectToLoginMixin, DetailView):
template_name = 'dashboard/operate.html'
show_in_toolbar = True
effect = None
......@@ -220,7 +220,7 @@ class OperationView(RedirectToLoginMixin, DetailView):
@classmethod
def get_urlname(cls):
return 'dashboard.%s.op.%s' % (cls.model._meta.model_name, cls.op)
return 'dashboard.%s.op.%s' % (type(cls.model).__name__, cls.op)
@classmethod
def get_instance_url(cls, pk, key=None, *args, **kwargs):
......@@ -231,7 +231,7 @@ class OperationView(RedirectToLoginMixin, DetailView):
return "%s?k=%s" % (url, key)
def get_url(self, **kwargs):
return self.get_instance_url(self.get_object().pk, **kwargs)
return self.get_instance_url(self.get_object().id, **kwargs)
def get_template_names(self):
if self.request.is_ajax():
......@@ -239,9 +239,6 @@ class OperationView(RedirectToLoginMixin, DetailView):
else:
return ['dashboard/_base.html']
def get_object(self):
return Instance(os_server_id=self.kwargs['pk']).get_from_os(self.request)
@classmethod
def get_op_by_object(cls, obj):
return getattr(obj, cls.op)
......@@ -275,7 +272,6 @@ class OperationView(RedirectToLoginMixin, DetailView):
cls.get_operation_class().check_perms(user)
def get(self, request, *args, **kwargs):
self.get_op().instance.get_from_os(request)
self.check_auth(request)
return super(OperationView, self).get(request, *args, **kwargs)
......@@ -292,9 +288,7 @@ class OperationView(RedirectToLoginMixin, DetailView):
return extra
def post(self, request, extra=None, *args, **kwargs):
self.get_op().instance.get_from_os(request)
self.check_auth(request)
self.object = self.get_object()
if extra is None:
extra = {}
result = None
......@@ -338,8 +332,8 @@ class OperationView(RedirectToLoginMixin, DetailView):
return HttpResponse(json.dumps(data),
content_type="application/json")
else:
return HttpResponseRedirect("%s#activity" %
self.object.get_absolute_url())
return HttpResponseRedirect("#activity")
#TODO: removed full path from this redirect but it does not seem to matter if i remove response at all
@classmethod
def factory(cls, op, icon='cog', effect='info', extra_bases=(), **kwargs):
......
......@@ -26,7 +26,7 @@ from django.conf import settings
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse_lazy
from django.core.urlresolvers import reverse_lazy, reverse
from django.http import (
HttpResponse, Http404, HttpResponseRedirect, JsonResponse
)
......@@ -48,6 +48,7 @@ from common.models import (
)
from firewall.models import Vlan, Host, Rule
from manager.scheduler import SchedulerError
from openstack_api.nova import Server
from request.forms import TemplateRequestForm
from request.models import TemplateAccessType
from storage.models import Disk
......@@ -92,7 +93,6 @@ logger = logging.getLogger(__name__)
class VmDetailView(LoginRequiredMixin, GraphMixin, DetailView):
template_name = "dashboard/vm-detail.html"
model = Instance
def get(self, *args, **kwargs):
if self.request.is_ajax():
......@@ -108,16 +108,16 @@ class VmDetailView(LoginRequiredMixin, GraphMixin, DetailView):
"password": instance.pw}
def get_object(self, queryset=None):
return Instance(os_server_id=self.kwargs['pk']).get_from_os(self.request)
return openstack_api.nova.server_get(self.request, self.kwargs['pk'])
def get_context_data(self, **kwargs):
context = super(VmDetailView, self).get_context_data(**kwargs)
instance = context['instance']
instance = self.object
user = self.request.user
ops = get_operations(instance, user, self.request)
hide_tutorial = self.request.COOKIES.get(
"hide_tutorial_for_%s" % instance.pk) == "True"
vnc_console = openstack_api.nova.server_vnc_console(self.request, instance.os_server_id)
"hide_tutorial_for_%s" % instance.id) == "True"
vnc_console = openstack_api.nova.server_vnc_console(self.request, instance.id)
context.update({
'graphite_enabled': settings.GRAPHITE_URL is not None,
'vnc_url': vnc_console.url,
......@@ -125,7 +125,8 @@ class VmDetailView(LoginRequiredMixin, GraphMixin, DetailView):
'op': {i.op: i for i in ops},
# 'connect_commands': user.profile.get_connect_commands(instance),
'hide_tutorial': hide_tutorial,
'fav': instance.favourite_set.filter(user=user).exists(),
'fav': [], #instance.favourite_set.filter(user=user).exists(),
'instance': self.object
})
# activity data
......@@ -139,7 +140,7 @@ class VmDetailView(LoginRequiredMixin, GraphMixin, DetailView):
# latest.resultant_state is not None and
# instance.status != latest.resultant_state)
activities = openstack_api.nova.instance_action_list(self.request, instance.os_server_id)
activities = openstack_api.nova.instance_action_list(self.request, instance.id)
# context['vlans'] = Vlan.get_objects_with_level(
# 'user', self.request.user
......@@ -147,16 +148,16 @@ class VmDetailView(LoginRequiredMixin, GraphMixin, DetailView):
# pk__in=Interface.objects.filter(
# instance=self.get_object()).values_list("vlan", flat=True)
# ).all()
context['os_type_icon'] = instance.os_type.replace("unknown",
"question")
# context['os_type_icon'] = instance.os_type.replace("unknown",
# "question")
# ipv6 infos
context['ipv6_host'] = instance.get_connect_host(use_ipv6=True)
# context['ipv6_host'] = instance.get_connect_host(use_ipv6=True)
# context['ipv6_port'] = instance.get_connect_port(use_ipv6=True)
# resources forms
can_edit = True
context['resources_form'] = VmResourcesForm(
can_edit=can_edit, instance=instance)
# context['resources_form'] = VmResourcesForm(
# can_edit=can_edit, instance=instance)
# if self.request.user.is_superuser:
# context['traits_form'] = TraitsForm(instance=instance)
......@@ -170,7 +171,7 @@ class VmDetailView(LoginRequiredMixin, GraphMixin, DetailView):
context['client_download'] = self.request.COOKIES.get(
'downloaded_client')
# can link template
context['can_link_template'] = instance.template
# context['can_link_template'] = instance.template
# operation also allows RUNNING (if with_shutdown is present)
context['save_resources_enabled'] = instance.status in (
......@@ -284,15 +285,18 @@ class VmDetailView(LoginRequiredMixin, GraphMixin, DetailView):
#
#
class VmOperationView(AjaxOperationMixin, OperationView):
model = Instance
model = Server
context_object_name = 'instance' # much simpler to mock object
def get_context_data(self, **kwargs):
ctx = super(VmOperationView, self).get_context_data(**kwargs)
self.object.get_from_os(self.request)
return ctx
def get_object(self):
return openstack_api.nova.server_get(self.request, self.kwargs['pk'])
def getModelUrl(self):
return reverse('dashboard.views.detail', self.get_object().id)
def get_operations(instance, user, request):
ops = []
......@@ -304,7 +308,7 @@ def get_operations(instance, user, request):
except PermissionDenied as e:
logger.debug('Not showing operation %s for %s: %s',
k, instance, unicode(e))
except Exception:
except Exception as e:
ops.append(v.bind_to_object(instance, disabled=True))
else:
ops.append(v.bind_to_object(instance))
......@@ -1249,8 +1253,7 @@ class VmCreate(LoginRequiredMixin, TemplateView):
#
@require_GET
def vm_activity(request, pk):
instance = Instance.objects.get(pk=pk)
instance.get_from_os(request)
instance = openstack_api.nova.server_get(request, pk)
response = {}
show_all = request.GET.get("show_all", "false") == "true"
......@@ -1260,14 +1263,14 @@ def vm_activity(request, pk):
# if not show_all:
# activities = activities[:10]
response['connect_uri'] = instance.get_connect_uri()
response['human_readable_status'] = instance.get_status_display()
# response['connect_uri'] = instance.get_connect_uri()
# response['human_readable_status'] = instance.get_status_display()
response['status'] = instance.status
response['icon'] = instance.get_status_icon()
latest = instance.get_latest_activity_in_progress()
response['is_new_state'] = (latest and
latest.resultant_state is not None and
instance.status != latest.resultant_state)
# response['icon'] = instance.get_status_icon()
# latest = instance.get_latest_activity_in_progress()
# response['is_new_state'] = (latest and
# latest.resultant_state is not None and
# instance.status != latest.resultant_state)
context = {
'instance': instance,
......
......@@ -70,10 +70,6 @@ class Vxlan(models.Model):
class Meta:
app_label = 'network'
@classmethod
def list_from_os(cls, request):
return openstack_api.neutron.network_list_for_tenant(request, request.user.tenant_id)
def __unicode__(self):
return self.name
......
......@@ -368,30 +368,6 @@ class Instance(OperatedMixin, TimeStampedModel):
return inst
@classmethod
def list_from_os(cls, request):
def get_or_create_from_os_server(os_server):
try:
i = Instance.objects.get(os_server_id=os_server.id)
i._os_server = os_server
return i
except:
i = Instance()
# i.full_clean()
# i.set_level(i.owner, 'owner')
i.os_server_id = os_server.id
i._os_server = os_server
i.save()
return i
os_servers = openstack_api.nova.server_list(request)[0] #TODO: flatten
return [get_or_create_from_os_server(os_server) for os_server in os_servers]
def get_from_os(self, request):
self._os_server = openstack_api.nova.server_get(request, self.os_server_id)
return self
@classmethod
def create_from_template(cls, template, owner, disks=None, networks=None,
req_traits=None, tags=None, **kwargs):
"""Create a new instance based on an InstanceTemplate.
......
......@@ -34,6 +34,7 @@ from django.utils import timezone
from django.utils.translation import ugettext_lazy as _, ugettext_noop
from django.conf import settings
from django.db.models import Q
from openstack_api.nova import Server
from sizefield.utils import filesizeformat
......@@ -61,7 +62,6 @@ from storage.tasks import storage_tasks
logger = getLogger(__name__)
class RemoteOperationMixin(object):
remote_timeout = 30
......@@ -96,7 +96,7 @@ class AbortableRemoteOperationMixin(object):
class InstanceOperation(Operation):
acl_level = 'owner'
host_cls = Instance
host_cls = Server
concurrency_check = True
accept_states = None
deny_states = None
......@@ -128,7 +128,7 @@ class InstanceOperation(Operation):
check = import_string("openstack_auth.policy.check")
has_rights = check(self.os_policy_actions, request,
{'project_id': self.instance._os_server.tenant_id})
{'project_id': self.instance.tenant_id})
if not has_rights:
raise humanize_exception(ugettext_noop(
......@@ -142,9 +142,6 @@ class InstanceOperation(Operation):
"""
return False
def get_from_os(self, request):
self.instance.get_from_os(request)
class RemoteInstanceOperation(RemoteOperationMixin, InstanceOperation):
remote_queue = ('vm', 'fast')
......@@ -310,7 +307,7 @@ class DeployOperation(InstanceOperation):
self.instance.status == self.instance.STATUS.SHUTOFF)
def _operation(self, request, node=None):
openstack_api.nova.server_start(request, self.instance.os_server_id)
openstack_api.nova.server_start(request, self.instance.id)
@register_operation
......@@ -660,7 +657,7 @@ class ShutOffOperation(InstanceOperation):
os_policy_actions = (("compute", "compute:stop"),)
def _operation(self, request):
openstack_api.nova.server_stop(request, self.instance.os_server_id)
openstack_api.nova.server_stop(request, self.instance.id)
@register_operation
......
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