Commit 238c23ba by Bálint Máhonfai

Start implementing export and import

parent 3615d835
......@@ -830,6 +830,34 @@ class VmCreateDiskForm(OperationForm):
return size_in_bytes
class VmDiskExportForm(OperationForm):
def __init__(self, *args, **kwargs):
choices = kwargs.pop('choices')
self.disk = kwargs.pop('default')
super(VmDiskExportForm, self).__init__(*args, **kwargs)
self.fields['disk'] = forms.ModelChoiceField(
queryset=choices, initial=self.disk, required=True,
empty_label=None, label=_('Disk'))
if self.disk:
self.fields['disk'].widget = HiddenInput()
@property
def helper(self):
helper = super(VmDiskExportForm, self).helper
if self.disk:
helper.layout = Layout(
AnyTag(
"div",
HTML(_("<label>Disk:</label> %s") % escape(self.disk)),
css_class="form-group",
),
Field("disk"),
)
return helper
class VmDiskResizeForm(OperationForm):
size = forms.CharField(
widget=FileSizeWidget, initial=(10 << 30), label=_('Size'),
......@@ -858,7 +886,7 @@ class VmDiskResizeForm(OperationForm):
" GB or MB!"))
if int(size_in_bytes) < int(disk.size):
raise forms.ValidationError(_("Disk size must be greater than the "
"actual size."))
"actual size."))
return cleaned_data
@property
......@@ -899,6 +927,11 @@ class VmDiskRemoveForm(OperationForm):
return helper
class VmImportDiskForm(OperationForm):
name = forms.CharField(max_length=50, label=_('Name'))
disk_file = forms.FileField(label=_('File'))
class VmDownloadDiskForm(OperationForm):
name = forms.CharField(max_length=100, label=_("Name"), required=False)
url = forms.CharField(label=_('URL'), validators=[URLValidator(), ])
......
......@@ -61,9 +61,10 @@ from .util import (
)
from ..forms import (
AclUserOrGroupAddForm, VmResourcesForm, TraitsForm, RawDataForm,
VmAddInterfaceForm, VmCreateDiskForm, VmDownloadDiskForm, VmSaveForm,
VmAddInterfaceForm, VmCreateDiskForm, VmDownloadDiskForm,
VmImportDiskForm, VmSaveForm,
VmRenewForm, VmStateChangeForm, VmListSearchForm, VmCustomizeForm,
VmDiskResizeForm, RedeployForm, VmDiskRemoveForm,
VmDiskExportForm, VmDiskResizeForm, RedeployForm, VmDiskRemoveForm,
VmMigrateForm, VmDeployForm,
VmPortRemoveForm, VmPortAddForm,
VmRemoveInterfaceForm,
......@@ -269,7 +270,7 @@ class VmDetailView(GraphMixin, CheckedDetailView):
return JsonResponse({'message': message})
else:
return redirect(reverse_lazy("dashboard.views.detail",
kwargs={'pk': self.object.pk}))
kwargs={'pk': self.object.pk}))
def __abort_operation(self, request):
self.object = self.get_object()
......@@ -408,6 +409,17 @@ class VmCreateDiskView(FormOperationMixin, VmOperationView):
return val
class VmImportDiskView(FormOperationMixin, VmOperationView):
op = 'import_disk'
form_class = VmImportDiskForm
show_in_toolbar = False
icon = 'upload'
effect = "success"
is_disk_operation = True
with_reload = True
class VmDownloadDiskView(FormOperationMixin, VmOperationView):
op = 'download_disk'
......@@ -769,7 +781,11 @@ vm_ops = OrderedDict([
extra_bases=[TokenOperationView],
op='destroy', icon='times', effect='danger')),
('create_disk', VmCreateDiskView),
('import_disk', VmImportDiskView),
('download_disk', VmDownloadDiskView),
('export_disk', VmDiskModifyView.factory(
op='export_disk', form_class=VmDiskExportForm,
icon='download', effect='info')),
('resize_disk', VmDiskModifyView.factory(
op='resize_disk', form_class=VmDiskResizeForm,
icon='arrows-alt', effect="warning")),
......
......@@ -149,7 +149,9 @@ class Disk(TimeStampedModel):
permissions = (
('create_empty_disk', _('Can create an empty disk.')),
('download_disk', _('Can download a disk.')),
('resize_disk', _('Can resize a disk.'))
('resize_disk', _('Can resize a disk.')),
('import_disk', _('Can import a disk.')),
('export_disk', _('Can export a disk.'))
)
class DiskError(HumanReadableException):
......@@ -550,3 +552,7 @@ class Disk(TimeStampedModel):
@property
def is_resizable(self):
return self.type in ('qcow2-norm', 'raw-rw', 'qcow2-snap', )
@property
def is_exportable(self):
return self.type in ('qcow2-norm', 'qcow2-snap', 'raw-rw', 'raw-ro')
......@@ -352,6 +352,34 @@ class DownloadDiskOperation(InstanceOperation):
@register_operation
class ImportDiskOperation(InstanceOperation):
id = 'import_disk'
name = _('import disk')
description = _('Import and attach a disk image to the virtual machine.')
abortable = True
has_percentage = True
required_perms = ('storage.import_disk',)
accept_states = ('STOPPED', 'PENDING', 'RUNNING')
async_queue = 'localhost.man.slow'
def _operation(self, **kwargs):
from storage.models import Disk
@register_operation
class ExportDiskOperation(InstanceOperation):
id = 'export_disk'
name = _('export disk')
description = _('Export disk to VMDK format.')
required_perms = ('storage.export_disk',)
accept_states = ('STOPPED', 'PENDING', 'RUNNING')
def _operation(self, **kwargs):
from storage.models import Disk
@register_operation
class DeployOperation(InstanceOperation):
id = 'deploy'
name = _("deploy")
......
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