From a12ac14c6c707d8901a3a978e6f50c8df84a4594 Mon Sep 17 00:00:00 2001 From: Nico Wohlfarth Date: Tue, 25 Jun 2019 18:18:03 +0200 Subject: [PATCH] ui: add new way to create a volume snapshot from instance quick view tooltip (#3406) Added a shortcut to take a volume snapshot of a VM directly from the instance view. Therefor an option was added to the quick view tooltip. On activation a new dialog will pop up, which is based on the original dialog for creating a volume snapshot (Storage > Volumes > Take snapshot) extended with a select menu to choose the desired snapshot volume of the VM. --- ui/css/cloudstack3.css | 6 +- ui/css/src/scss/components/action-icons.scss | 6 +- ui/l10n/de_DE.js | 2 + ui/l10n/en.js | 4 +- ui/scripts/docs.js | 7 ++ ui/scripts/instances.js | 107 +++++++++++++++++++ 6 files changed, 127 insertions(+), 5 deletions(-) diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index b3b7490825f..a85dee1d909 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -12343,12 +12343,14 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it } .snapshot .icon, -.takeSnapshot .icon { +.takeSnapshot .icon, +.storageSnapshot .icon { background-position: -36px -91px; } .snapshot:hover .icon, -.takeSnapshot:hover .icon { +.takeSnapshot:hover .icon, +.storageSnapshot:hover .icon { background-position: -36px -673px; } diff --git a/ui/css/src/scss/components/action-icons.scss b/ui/css/src/scss/components/action-icons.scss index c35645d3a0d..686b6e395bd 100644 --- a/ui/css/src/scss/components/action-icons.scss +++ b/ui/css/src/scss/components/action-icons.scss @@ -173,12 +173,14 @@ } .snapshot .icon, -.takeSnapshot .icon { +.takeSnapshot .icon, +.storageSnapshot .icon { background-position: -36px -91px; } .snapshot:hover .icon, -.takeSnapshot:hover .icon { +.takeSnapshot:hover .icon, +.storageSnapshot:hover .icon { background-position: -36px -673px; } diff --git a/ui/l10n/de_DE.js b/ui/l10n/de_DE.js index cae753e7e40..13e96b58a6f 100644 --- a/ui/l10n/de_DE.js +++ b/ui/l10n/de_DE.js @@ -297,6 +297,7 @@ var dictionary = { "label.action.vmsnapshot.create": "VM-Schnappschuss machen", "label.action.vmsnapshot.delete": "VM-Schnappschuss löschen", "label.action.vmsnapshot.revert": "Auf VM-Schnappschuss zurückkehren", + "label.action.vmstoragesnapshot.create":"VM Speicher-Schnappschuss machen", "label.actions": "Aktionen", "label.activate.project": "Projekt aktivieren", "label.active.sessions": "Aktive Sitzungen", @@ -1891,6 +1892,7 @@ var dictionary = { "message.action.vmsnapshot.create": "Please confirm that you want to take a snapshot of this instance.
Please notice that the instance will be paused during the snapshoting, and resumed after snapshotting, if it runs on KVM.", "message.action.vmsnapshot.delete": "Bitte bestätigen Sie, dass Sie diesen VM Schnappschuss löschen wollen.", "message.action.vmsnapshot.revert": "VM-Schnappschuss zurücksetzen", + "message.action.vmstoragesnapshot.create":"Bitte wählen Sie einen Speicher aus, für den ein Schnappschuss erstellt werden soll.", "message.activate.project": "Sind Sie sicher, dass Sie dieses Projekt aktivieren wollen?", "message.add.VPN.gateway": "Bitte bestätigen Sie, dass sie ein VPN Gateway hinzufügen wollen.", "message.add.cluster": "Hinzufügen eines vom Hypervisor verwaltender Clusters für Zone , Pod ", diff --git a/ui/l10n/en.js b/ui/l10n/en.js index db269250860..aca4d998fbc 100644 --- a/ui/l10n/en.js +++ b/ui/l10n/en.js @@ -301,6 +301,7 @@ var dictionary = { "label.action.vmsnapshot.create":"Take VM Snapshot", "label.action.vmsnapshot.delete":"Delete VM snapshot", "label.action.vmsnapshot.revert":"Revert to VM snapshot", +"label.action.vmstoragesnapshot.create":"Take VM volume snapshot", "label.actions":"Actions", "label.activate.project":"Activate Project", "label.active.sessions":"Active Sessions", @@ -533,7 +534,7 @@ var dictionary = { "label.cidr":"CIDR", "label.cidr.account":"CIDR or Account/Security Group", "label.cidr.list":"Source CIDR", - "label.cidr.destination.list":"Destination CIDR", +"label.cidr.destination.list":"Destination CIDR", "label.cisco.nexus1000v.ip.address":"Nexus 1000v IP Address", "label.cisco.nexus1000v.password":"Nexus 1000v Password", "label.cisco.nexus1000v.username":"Nexus 1000v Username", @@ -1960,6 +1961,7 @@ var dictionary = { "message.action.vmsnapshot.create":"Please confirm that you want to take a snapshot of this instance.
Please notice that the instance will be paused during the snapshoting, and resumed after snapshotting, if it runs on KVM.", "message.action.vmsnapshot.delete":"Please confirm that you want to delete this VM snapshot.
Please notice that the instance will be paused before the snapshot deletion, and resumed after deletion, if it runs on KVM.", "message.action.vmsnapshot.revert":"Revert VM snapshot", +"message.action.vmstoragesnapshot.create":"Please choose a volume that you want to take a snapshot of.", "message.activate.project":"Are you sure you want to activate this project?", "message.add.VPN.gateway":"Please confirm that you want to add a VPN Gateway", "message.add.cluster":"Add a hypervisor managed cluster for zone , pod ", diff --git a/ui/scripts/docs.js b/ui/scripts/docs.js index aef5e77efbc..b032d4eaf3e 100755 --- a/ui/scripts/docs.js +++ b/ui/scripts/docs.js @@ -310,6 +310,13 @@ cloudStack.docs = { helpCreateInstanceSnapshotMemory: { desc: 'Check this to include CPU/memory state. Does not quiesce the VM. If not checked, the snapshot contain only volumes.' }, + // Create instance storage snapshot + helpCreateInstanceStorageSnapshotVolume: { + desc: 'Choose a volume that you want to take a snapshot of' + }, + helpCreateInstanceStorageSnapshotName: { + desc: 'Give the snapshot a name. A unique name will be automatically generated if you leave this blank' + }, // Add disk offering helpDiskOfferingName: { desc: 'Any desired name for the offering', diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js index c0693f7ef98..4cc1dbb18be 100644 --- a/ui/scripts/instances.js +++ b/ui/scripts/instances.js @@ -1054,6 +1054,111 @@ } }, snapshot: vmSnapshotAction(), + storageSnapshot: { + messages: { + notification: function() { + return 'label.action.take.snapshot'; + } + }, + label: 'label.action.vmstoragesnapshot.create', + createForm: { + title: 'label.action.vmstoragesnapshot.create', + desc: 'message.action.vmstoragesnapshot.create', + fields: { + volume: { + label: 'label.volume', + docID: 'helpCreateInstanceStorageSnapshotVolume', + select: function(args) { + var items = []; + var data = { + virtualMachineId: args.context.instances[0].id + }; + + $.ajax({ + url: createURL('listVolumes'), + data: data, + dataType: 'json', + async: false, + success: function(json) { + var volumes = json.listvolumesresponse.volume; + args.context['volumes'] = volumes; + $(volumes).each(function(index, volume) { + items.push({ + id: volume.id, + description: volume.name + }); + }); + + args.response.success({ + data: items + }); + } + }); + } + }, + quiescevm: { + label: 'label.quiesce.vm', + isBoolean: true, + dependsOn: 'volume', + isHidden: function(args) { + var selectedVolumeId = $('div[role=dialog] form .form-item[rel=volume] select').val(); + for (var i = 0; i < args.context.volumes.length; i++) { + var volume = args.context.volumes[i]; + if (volume.id === selectedVolumeId) { + return volume.quiescevm !== true; + } + } + return false; + } + }, + name: { + label: 'label.name', + docID: 'helpCreateInstanceStorageSnapshotName', + isInput: true + }, + asyncBackup: { + label: 'label.async.backup', + isBoolean: true + } + } + }, + action: function(args) { + var data = { + volumeId: args.data.volume, + quiescevm: args.data.quiescevm === 'on', + asyncBackup: args.data.asyncBackup === 'on' + }; + if (args.data.name != null && args.data.name.length > 0) { + $.extend(data, { + name: args.data.name + }); + } + $.ajax({ + url: createURL('createSnapshot'), + data: data, + dataType: 'json', + async: true, + success: function(json) { + var jid = json.createsnapshotresponse.jobid; + args.response.success({ + _custom: { + jobId: jid, + onComplete: function(json) { + var volumeId = json.queryasyncjobresultresponse.jobresult.snapshot.volumeid; + var snapshotId = json.queryasyncjobresultresponse.jobresult.snapshot.id; + cloudStack.dialog.notice({ + message: 'Created snapshot for volume ' + volumeId + ' with snapshot ID ' + snapshotId + }); + } + } + }); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + }, destroy: vmDestroyAction(), expunge: { label: 'label.action.expunge.instance', @@ -3437,6 +3542,7 @@ if (jsonObj.hypervisor != 'LXC') { allowedActions.push("snapshot"); + allowedActions.push("storageSnapshot"); } allowedActions.push("destroy"); @@ -3474,6 +3580,7 @@ if (jsonObj.hypervisor != 'KVM' && jsonObj.hypervisor != 'LXC') { allowedActions.push("snapshot"); + allowedActions.push("storageSnapshot"); } allowedActions.push("scaleUp"); //when vm is stopped, scaleUp is supported for all hypervisors