Commit f068881e by Czémán Arnold

dashboard, vm, storage: add datastore attribute for VirtualMachineDescModel, add…

dashboard, vm, storage: add datastore attribute for VirtualMachineDescModel, add datastore selector for vm and template views, modify sleep, wake up, and delete mem dump operation
parent f601f261
......@@ -1450,6 +1450,25 @@ class RawDataForm(forms.ModelForm):
return helper
class VmDataStoreForm(forms.ModelForm):
datastore = forms.ModelChoiceField(queryset=DataStore.objects.all(),
empty_label=None)
class Meta:
model = Instance
fields = ('datastore', )
@property
def helper(self):
helper = FormHelper()
helper.form_show_labels = False
helper.form_action = reverse_lazy("dashboard.views.vm-data-store",
kwargs={'pk': self.instance.pk})
helper.add_input(Submit("submit", _("Save"),
css_class="btn btn-success", ))
return helper
class GroupPermissionForm(forms.ModelForm):
permissions = forms.ModelMultipleChoiceField(
queryset=None,
......
......@@ -30,6 +30,7 @@
<fieldset>
<legend>{% trans "External resources" %}</legend>
{{ form.networks|as_crispy_field }}
{{ form.datastore|as_crispy_field }}
{{ form.lease|as_crispy_field }}
{% if show_lease_create %}
......
......@@ -57,6 +57,7 @@
<legend>{% trans "External resources" %}</legend>
{{ form.networks|as_crispy_field }}
{{ form.lease|as_crispy_field }}
{{ form.datastore|as_crispy_field }}
{{ form.tags|as_crispy_field }}
</fieldset>
......
......@@ -91,6 +91,17 @@
</div>
</div>
<hr/>
<div class="row">
<div class="col-sm-12">
<h3>
{% trans "Data store" %}
</h3>
{% crispy data_store_form %}
</div>
</div>
{% endif %}
{% block extra_js %}
......
......@@ -42,7 +42,7 @@ from .views import (
ConnectCommandDelete, ConnectCommandDetail, ConnectCommandCreate,
StoreList, store_download, store_upload, store_get_upload_url, StoreRemove,
store_new_directory, store_refresh_toplist,
VmTraitsUpdate, VmRawDataUpdate,
VmTraitsUpdate, VmRawDataUpdate, VmDataStoreUpdate,
GroupPermissionsView,
LeaseAclUpdateView,
toggle_template_tutorial,
......@@ -114,6 +114,8 @@ urlpatterns = patterns(
name='dashboard.views.vm-traits'),
url(r'^vm/(?P<pk>\d+)/raw_data/$', VmRawDataUpdate.as_view(),
name='dashboard.views.vm-raw-data'),
url(r'^vm/(?P<pk>\d+)/data_store/$', VmDataStoreUpdate.as_view(),
name='dashboard.views.vm-data-store'),
url(r'^vm/(?P<pk>\d+)/toggle_tutorial/$', toggle_template_tutorial,
name='dashboard.views.vm-toggle-tutorial'),
......
......@@ -64,7 +64,7 @@ from ..forms import (
VmDiskResizeForm, RedeployForm, VmDiskRemoveForm,
VmMigrateForm, VmDeployForm,
VmPortRemoveForm, VmPortAddForm,
VmRemoveInterfaceForm,
VmRemoveInterfaceForm, VmDataStoreForm,
)
from request.models import TemplateAccessType, LeaseType
from request.forms import LeaseRequestForm, TemplateRequestForm
......@@ -158,6 +158,7 @@ class VmDetailView(GraphMixin, CheckedDetailView):
if self.request.user.is_superuser:
context['traits_form'] = TraitsForm(instance=instance)
context['raw_data_form'] = RawDataForm(instance=instance)
context['data_store_form'] = VmDataStoreForm(instance=instance)
# resources change perm
context['can_change_resources'] = self.request.user.has_perm(
......@@ -311,6 +312,14 @@ class VmRawDataUpdate(SuperuserRequiredMixin, UpdateView):
return self.get_object().get_absolute_url() + "#resources"
class VmDataStoreUpdate(SuperuserRequiredMixin, UpdateView):
form_class = VmDataStoreForm
model = Instance
def get_success_url(self):
return self.get_object().get_absolute_url() + "#resources"
class VmOperationView(AjaxOperationMixin, OperationView):
model = Instance
......
......@@ -44,7 +44,7 @@ def delete(disk_desc):
@celery.task(name='storagedriver.delete_dump')
def delete_dump(data_store_type, path):
def delete_dump(data_store_type, dir, filename):
pass
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('storage', '0005_auto_20160331_1823'),
('vm', '0002_interface_model'),
]
operations = [
migrations.AddField(
model_name='instance',
name='datastore',
field=models.ForeignKey(default=1, verbose_name='Data store', to='storage.DataStore', help_text="The target of VM's dump."),
preserve_default=False,
),
migrations.AddField(
model_name='instancetemplate',
name='datastore',
field=models.ForeignKey(default=1, verbose_name='Data store', to='storage.DataStore', help_text="The target of VM's dump."),
preserve_default=False,
),
]
......@@ -50,6 +50,7 @@ from .activity import (ActivityInProgressError, InstanceActivity)
from .common import BaseResourceConfigModel, Lease
from .network import Interface
from .node import Node, Trait
from storage.models import DataStore
logger = getLogger(__name__)
pre_state_changed = Signal(providing_args=["new_state"])
......@@ -93,6 +94,7 @@ class VirtualMachineDescModel(BaseResourceConfigModel):
"""Abstract base for virtual machine describing models.
"""
access_method = CharField(max_length=10, choices=ACCESS_METHODS,
verbose_name=_('access method'),
help_text=_('Primary remote access method.'))
......@@ -116,6 +118,8 @@ class VirtualMachineDescModel(BaseResourceConfigModel):
help_text=_(
'If the machine has agent installed, and '
'the manager should wait for its start.'))
datastore = ForeignKey(DataStore, verbose_name=_("Data store"),
help_text=_("The target of VM's dump."))
class Meta:
abstract = True
......@@ -482,16 +486,10 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
def mem_dump(self):
"""Return the path and datastore for the memory dump.
It is always on the first hard drive storage named cloud-<id>.dump
It named cloud-<id>.dump
"""
try:
datastore = self.disks.all()[0].datastore
except IndexError:
from storage.models import DataStore
datastore = DataStore.get_default_datastore()
path = datastore.path + '/' + self.vm_name + '.dump'
return {'datastore': datastore, 'path': path}
filename = self.vm_name + '.dump'
return {'datastore': self.datastore, 'filename': filename}
@property
def primary_host(self):
......
......@@ -530,7 +530,9 @@ class DestroyOperation(InstanceOperation):
"storage", "fast")
def _get_remote_args(self, **kwargs):
return [self.instance.mem_dump['path']]
return [self.instance.mem_dump['datastore'].type,
self.instance.mem_dump['datastore'].path,
self.instance.mem_dump['filename']]
@register_operation
......@@ -772,6 +774,7 @@ class SaveAsTemplateOperation(InstanceOperation):
'ram_size': self.instance.ram_size,
'raw_data': self.instance.raw_data,
'system': self.instance.system,
'datastore': self.instance.datastore,
}
params.update(kwargs)
params.pop("parent_activity", None)
......@@ -923,7 +926,9 @@ class SleepOperation(InstanceOperation):
def _get_remote_args(self, **kwargs):
return (super(SleepOperation.SuspendVmOperation, self)
._get_remote_args(**kwargs) +
[self.instance.mem_dump['path']])
[self.instance.mem_dump['datastore'].type,
self.instance.mem_dump['datastore'].path,
self.instance.mem_dump['filename']])
@register_operation
......@@ -977,7 +982,9 @@ class WakeUpOperation(InstanceOperation):
def _get_remote_args(self, **kwargs):
return (super(WakeUpOperation.WakeUpVmOperation, self)
._get_remote_args(**kwargs) +
[self.instance.mem_dump['path']])
[self.instance.mem_dump['datastore'].type,
self.instance.mem_dump['datastore'].path,
self.instance.mem_dump['filename']])
@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