blob: 9638f1e5e2aeeba942102ae5ac57b5eb836b45bf [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
(function(cloudStack) {
var diskofferingObjs, selectedDiskOfferingObj;
cloudStack.sections.storage = {
title: 'label.storage',
id: 'storage',
sectionSelect: {
label: 'label.select-view'
},
sections: {
/**
* Volumes
*/
volumes: {
type: 'select',
title: 'label.volumes',
listView: {
id: 'volumes',
label: 'label.volumes',
preFilter: function(args) {
var hiddenFields = [];
if (isAdmin() != true)
hiddenFields.push('hypervisor');
return hiddenFields;
},
fields: {
name: {
label: 'label.name'
},
type: {
label: 'label.type'
},
hypervisor: {
label: 'label.hypervisor'
},
vmdisplayname: {
label: 'label.vm.display.name'
}
},
// List view actions
actions: {
// Add volume
add: {
label: 'label.add',
preFilter: function(args) {
return !args.context.instances;
},
messages: {
confirm: function(args) {
return 'message.add.volume';
},
notification: function(args) {
return 'label.add.volume';
}
},
createForm: {
title: 'label.add.volume',
desc: 'message.add.volume',
fields: {
name: {
docID: 'helpVolumeName',
label: 'label.name'
},
availabilityZone: {
label: 'label.availability.zone',
docID: 'helpVolumeAvailabilityZone',
select: function(args) {
$.ajax({
url: createURL("listZones&available=true"),
dataType: "json",
async: true,
success: function(json) {
var zoneObjs = json.listzonesresponse.zone;
args.response.success({
descriptionField: 'name',
data: zoneObjs
});
}
});
}
},
diskOffering: {
label: 'label.disk.offering',
docID: 'helpVolumeDiskOffering',
select: function(args) {
$.ajax({
url: createURL("listDiskOfferings"),
dataType: "json",
async: false,
success: function(json) {
diskofferingObjs = json.listdiskofferingsresponse.diskoffering;
var items = [];
$(diskofferingObjs).each(function() {
items.push({
id: this.id,
description: this.displaytext
});
});
args.response.success({
data: items
});
}
});
args.$select.change(function() {
var diskOfferingId = $(this).val();
$(diskofferingObjs).each(function() {
if (this.id == diskOfferingId) {
selectedDiskOfferingObj = this;
return false; //break the $.each() loop
}
});
if (selectedDiskOfferingObj == null)
return;
var $form = $(this).closest('form');
var $diskSize = $form.find('.form-item[rel=diskSize]');
if (selectedDiskOfferingObj.iscustomized == true) {
$diskSize.css('display', 'inline-block');
} else {
$diskSize.hide();
}
var $minIops = $form.find('.form-item[rel=minIops]');
var $maxIops = $form.find('.form-item[rel=maxIops]');
if (selectedDiskOfferingObj.iscustomizediops == true) {
$minIops.css('display', 'inline-block');
$maxIops.css('display', 'inline-block');
} else {
$minIops.hide();
$maxIops.hide();
}
});
}
}
,
diskSize: {
label: 'label.disk.size.gb',
docID: 'helpVolumeSizeGb',
validation: {
required: true,
number: true
},
isHidden: true
},
minIops: {
label: 'label.disk.iops.min',
validation: {
required: false,
number: true
},
isHidden: true
},
maxIops: {
label: 'label.disk.iops.max',
validation: {
required: false,
number: true
},
isHidden: true
}
}
},
action: function(args) {
var data = {
name: args.data.name,
zoneId: args.data.availabilityZone,
diskOfferingId: args.data.diskOffering
};
// if(thisDialog.find("#size_container").css("display") != "none") { //wait for Brian to include $form in args
if (selectedDiskOfferingObj.iscustomized == true) {
$.extend(data, {
size: args.data.diskSize
});
}
if (selectedDiskOfferingObj.iscustomizediops == true) {
if (args.data.minIops != "" && args.data.minIops > 0) {
$.extend(data, {
miniops: args.data.minIops
});
}
if (args.data.maxIops != "" && args.data.maxIops > 0) {
$.extend(data, {
maxiops: args.data.maxIops
});
}
}
$.ajax({
url: createURL('createVolume'),
data: data,
success: function(json) {
var jid = json.createvolumeresponse.jobid;
args.response.success({
_custom: {
jobId: jid,
getUpdatedItem: function(json) {
return json.queryasyncjobresultresponse.jobresult.volume;
},
getActionFilter: function() {
return volumeActionfilter;
}
}
});
},
error: function(json) {
args.response.error(parseXMLHttpResponse(json));
}
});
},
notification: {
poll: pollAsyncJobResult
}
},
viewMetrics: {
label: 'label.metrics',
isHeader: true,
addRow: false,
action: {
custom: cloudStack.uiCustom.metricsView({resource: 'volumes'})
},
messages: {
notification: function (args) {
return 'label.metrics';
}
}
},
uploadVolume: {
isHeader: true,
label: 'label.upload',
preFilter: function(args) {
return !args.context.instances;
},
messages: {
notification: function() {
return 'label.upload.volume.from.url';
}
},
createForm: {
title: 'label.upload.volume.from.url',
fields: {
url: {
label: 'label.url',
docID: 'helpUploadVolumeURL',
validation: {
required: true
}
},
name: {
label: 'label.name',
validation: {
required: true
},
docID: 'helpUploadVolumeName'
},
availabilityZone: {
label: 'label.availability.zone',
docID: 'helpUploadVolumeZone',
select: function(args) {
$.ajax({
url: createURL("listZones&available=true"),
dataType: "json",
async: true,
success: function(json) {
var zoneObjs = json.listzonesresponse.zone;
args.response.success({
descriptionField: 'name',
data: zoneObjs
});
}
});
}
},
format: {
label: 'label.format',
docID: 'helpUploadVolumeFormat',
select: function(args) {
var items = [];
items.push({
id: 'RAW',
description: 'RAW'
});
items.push({
id: 'VHD',
description: 'VHD'
});
items.push({
id: 'VHDX',
description: 'VHDX'
});
items.push({
id: 'OVA',
description: 'OVA'
});
items.push({
id: 'QCOW2',
description: 'QCOW2'
});
args.response.success({
data: items
});
}
},
diskOffering: {
label: 'label.custom.disk.offering',
docID: 'helpVolumeDiskOffering',
select: function(args) {
var diskofferingObjs;
$.ajax({
url: createURL("listDiskOfferings"),
dataType: "json",
async: false,
success: function(json) {
diskofferingObjs = json.listdiskofferingsresponse.diskoffering;
var items = [{
id: '',
description: ''
}];
$(diskofferingObjs).each(function() {
if (this.iscustomized == true) {
items.push({
id: this.id,
description: this.displaytext
});
}
});
args.response.success({
data: items
});
}
});
}
},
diskOffering: {
label: 'label.custom.disk.offering',
docID: 'helpVolumeDiskOffering',
select: function(args) {
var diskofferingObjs;
$.ajax({
url: createURL("listDiskOfferings"),
dataType: "json",
async: false,
success: function(json) {
diskofferingObjs = json.listdiskofferingsresponse.diskoffering;
var items = [{
id: '',
description: ''
}];
$(diskofferingObjs).each(function() {
if (this.iscustomized == true) {
items.push({
id: this.id,
description: this.displaytext
});
}
});
args.response.success({
data: items
});
}
});
}
},
checksum: {
docID: 'helpUploadVolumeChecksum',
label: 'label.md5.checksum'
}
}
},
action: function(args) {
var data = {
name: args.data.name,
zoneId: args.data.availabilityZone,
format: args.data.format,
url: args.data.url
};
if (args.data.diskOffering != '' && args.data.diskOffering.length > 0) {
$.extend(data, {
diskofferingid: args.data.diskOffering
});
}
if (args.data.checksum != null && args.data.checksum.length > 0) {
$.extend(data, {
checksum: args.data.checksum
});
}
$.ajax({
url: createURL('uploadVolume'),
data: data,
success: function(json) {
var jid = json.uploadvolumeresponse.jobid;
args.response.success({
_custom: {
jobId: jid,
getUpdatedItem: function(json) {
return json.queryasyncjobresultresponse.jobresult.volume;
},
getActionFilter: function() {
return volumeActionfilter;
}
}
});
},
error: function(json) {
args.response.error(parseXMLHttpResponse(json));
}
});
},
notification: {
poll: pollAsyncJobResult
}
},
uploadVolumefromLocal: {
isHeader: true,
label: 'label.upload.from.local',
preFilter: function(args) {
return !args.context.instances;
},
messages: {
notification: function() {
return 'label.upload.volume.from.local';
}
},
createForm: {
title: 'label.upload.volume.from.local',
fileUpload: {
getURL: function(args) {
args.data = args.formData;
var data = {
name: args.data.name,
zoneId: args.data.availabilityZone,
format: args.data.format,
url: args.data.url
};
if (args.data.checksum != null && args.data.checksum.length > 0) {
$.extend(data, {
checksum: args.data.checksum
});
}
$.ajax({
url: createURL('getUploadParamsForVolume'),
data: data,
async: false,
success: function(json) {
var uploadparams = json.postuploadvolumeresponse.getuploadparams; //son.postuploadvolumeresponse.getuploadparams is an object, not an array of object.
var volumeId = uploadparams.id;
args.response.success({
url: uploadparams.postURL,
ajaxPost: true,
data: {
'X-signature': uploadparams.signature,
'X-expires': uploadparams.expires,
'X-metadata': uploadparams.metadata
}
});
}
});
},
postUpload: function(args) {
if(args.error) {
args.response.error(args.errorMsg);
} else {
cloudStack.dialog.notice({
message: "This volume file has been uploaded. Please check its status at Stroage menu > Volumes > " + args.data.name + " > Status field."
});
args.response.success();
}
}
},
fields: {
volumeFileUpload: {
label: 'label.local.file',
isFileUpload: true,
validation: {
required: true
}
},
name: {
label: 'label.name',
validation: {
required: true
},
docID: 'helpUploadVolumeName'
},
availabilityZone: {
label: 'label.availability.zone',
docID: 'helpUploadVolumeZone',
select: function(args) {
$.ajax({
url: createURL("listZones&available=true"),
dataType: "json",
async: true,
success: function(json) {
var zoneObjs = json.listzonesresponse.zone;
args.response.success({
descriptionField: 'name',
data: zoneObjs
});
}
});
}
},
format: {
label: 'label.format',
docID: 'helpUploadVolumeFormat',
select: function(args) {
var items = [];
items.push({
id: 'RAW',
description: 'RAW'
});
items.push({
id: 'VHD',
description: 'VHD'
});
items.push({
id: 'VHDX',
description: 'VHDX'
});
items.push({
id: 'OVA',
description: 'OVA'
});
items.push({
id: 'QCOW2',
description: 'QCOW2'
});
args.response.success({
data: items
});
}
},
checksum: {
docID: 'helpUploadVolumeChecksum',
label: 'label.md5.checksum'
}
}
},
action: function(args) {
return; //createForm.fileUpload.getURL() has executed the whole action. Therefore, nothing needs to be done here.
},
notification: {
poll: pollAsyncJobResult
}
}
},
advSearchFields: {
name: {
label: 'label.name'
},
zoneid: {
label: 'label.zone',
select: function(args) {
$.ajax({
url: createURL('listZones'),
data: {},
success: function(json) {
var zones = json.listzonesresponse.zone ? json.listzonesresponse.zone : [];
args.response.success({
data: $.map(zones, function(zone) {
return {
id: zone.id,
description: zone.name
};
})
});
}
});
}
},
domainid: {
label: 'label.domain',
select: function(args) {
if (isAdmin() || isDomainAdmin()) {
$.ajax({
url: createURL('listDomains'),
data: {
listAll: true,
details: 'min'
},
success: function(json) {
var array1 = [{
id: '',
description: ''
}];
var domains = json.listdomainsresponse.domain;
if (domains != null && domains.length > 0) {
for (var i = 0; i < domains.length; i++) {
array1.push({
id: domains[i].id,
description: domains[i].path
});
}
}
array1.sort(function(a, b) {
return a.description.localeCompare(b.description);
});
args.response.success({
data: array1
});
}
});
} else {
args.response.success({
data: null
});
}
},
isHidden: function(args) {
if (isAdmin() || isDomainAdmin())
return false;
else
return true;
}
},
account: {
label: 'label.account',
isHidden: function(args) {
if (isAdmin() || isDomainAdmin())
return false;
else
return true;
}
},
tagKey: {
label: 'label.tag.key'
},
tagValue: {
label: 'label.tag.value'
}
},
dataProvider: function(args) {
var data = {};
listViewDataProvider(args, data);
if (args.context != null) {
if ("instances" in args.context) {
$.extend(data, {
virtualMachineId: args.context.instances[0].id
});
}
if ("primarystorages" in args.context) {
$.extend(data, {
storageid: args.context.primarystorages[0].id
});
}
}
$.ajax({
url: createURL('listVolumes'),
data: data,
success: function(json) {
var items = json.listvolumesresponse.volume;
args.response.success({
actionFilter: volumeActionfilter,
data: items
});
},
error: function(XMLHttpResponse) {
cloudStack.dialog.notice({
message: parseXMLHttpResponse(XMLHttpResponse)
});
args.response.error();
}
});
},
detailView: {
name: 'label.volume.details',
viewAll: {
path: 'storage.snapshots',
label: 'label.snapshots'
},
actions: {
migrateVolume: {
label: 'label.migrate.volume',
messages: {
confirm: function(args) {
return 'message.confirm.migrate.volume';
},
notification: function(args) {
return 'label.volume.migrated';
}
},
createForm: {
title: 'label.migrate.volume',
desc: '',
fields: {
storagePool: {
label: 'label.storage.pool',
validation: {
required: true
},
select: function(args) {
$.ajax({
url: createURL("findStoragePoolsForMigration&id=" + args.context.volumes[0].id),
dataType: "json",
async: true,
success: function(json) {
var pools = json.findstoragepoolsformigrationresponse.storagepool;
var items = [];
$(pools).each(function() {
items.push({
id: this.id,
description: this.name + " (" + (this.suitableformigration ? "Suitable" : "Not Suitable") + ")"
});
});
args.response.success({
data: items
});
}
});
}
}
}
},
action: function(args) {
$.ajax({
url: createURL("migrateVolume&livemigrate=true&storageid=" + args.data.storagePool + "&volumeid=" + args.context.volumes[0].id),
dataType: "json",
async: true,
success: function(json) {
var jid = json.migratevolumeresponse.jobid;
args.response.success({
_custom: {
jobId: jid
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
},
takeSnapshot: {
label: 'label.action.take.snapshot',
messages: {
notification: function(args) {
return 'label.action.take.snapshot';
}
},
createForm: {
title: 'label.action.take.snapshot',
desc: 'message.action.take.snapshot',
fields: {
quiescevm: {
label: 'label.quiesce.vm',
isBoolean: true,
isHidden: function(args) {
if (args.context.volumes[0].quiescevm == true)
return false;
else
return true;
}
},
name: {
label: 'label.name'
}
}
},
action: function(args) {
var data = {
volumeId: args.context.volumes[0].id,
quiescevm: (args.data.quiescevm == 'on' ? true: false)
};
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 //take snapshot from a volume doesn't change any property in this volume. So, don't need to specify getUpdatedItem() to return updated volume. Besides, createSnapshot API doesn't return updated volume.
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
},
recurringSnapshot: {
label: 'label.snapshot.schedule',
action: {
custom: cloudStack.uiCustom.recurringSnapshots({
desc: 'message.snapshot.schedule',
dataProvider: function(args) {
$.ajax({
url: createURL('listSnapshotPolicies'),
data: {
volumeid: args.context.volumes[0].id
},
async: true,
dataType: 'json',
success: function(data) {
args.response.success({
data: $.map(
data.listsnapshotpoliciesresponse.snapshotpolicy ? data.listsnapshotpoliciesresponse.snapshotpolicy : [],
function(snapshot, index) {
return {
id: snapshot.id,
type: snapshot.intervaltype,
time: snapshot.intervaltype > 0 ? snapshot.schedule.split(':')[1] + ':' + snapshot.schedule.split(':')[0] : snapshot.schedule,
timezone: snapshot.timezone,
keep: snapshot.maxsnaps,
'day-of-week': snapshot.intervaltype == 2 ? snapshot.schedule.split(':')[2] : null,
'day-of-month': snapshot.intervaltype == 3 ? snapshot.schedule.split(':')[2] : null
};
}
)
});
}
});
},
actions: {
add: function(args) {
var snap = args.snapshot;
var data = {
keep: snap.maxsnaps,
timezone: snap.timezone
};
var convertTime = function(minute, hour, meridiem, extra) {
var convertedHour = meridiem == 'PM' ?
(hour != 12 ? parseInt(hour) + 12 : 12) : (hour != 12 ? hour : '00');
var time = minute + ':' + convertedHour;
if (extra) time += ':' + extra;
return time;
};
switch (snap['snapshot-type']) {
case 'hourly': // Hourly
$.extend(data, {
schedule: snap.schedule
});
break;
case 'daily': // Daily
$.extend(data, {
schedule: convertTime(
snap['time-minute'],
snap['time-hour'],
snap['time-meridiem']
)
});
break;
case 'weekly': // Weekly
$.extend(data, {
schedule: convertTime(
snap['time-minute'],
snap['time-hour'],
snap['time-meridiem'],
snap['day-of-week']
)
});
break;
case 'monthly': // Monthly
$.extend(data, {
schedule: convertTime(
snap['time-minute'],
snap['time-hour'],
snap['time-meridiem'],
snap['day-of-month']
)
});
break;
}
$.ajax({
url: createURL('createSnapshotPolicy'),
data: {
volumeid: args.context.volumes[0].id,
intervaltype: snap['snapshot-type'],
maxsnaps: snap.maxsnaps,
schedule: data.schedule,
timezone: snap.timezone
},
dataType: 'json',
async: true,
success: function(successData) {
var snapshot = successData.createsnapshotpolicyresponse.snapshotpolicy;
args.response.success({
data: {
id: snapshot.id,
type: snapshot.intervaltype,
time: snapshot.intervaltype > 0 ? snapshot.schedule.split(':')[1] + ':' + snapshot.schedule.split(':')[0] : snapshot.schedule,
timezone: snapshot.timezone,
keep: snapshot.maxsnaps,
'day-of-week': snapshot.intervaltype == 2 ? snapshot.schedule.split(':')[2] : null,
'day-of-month': snapshot.intervaltype == 3 ? snapshot.schedule.split(':')[2] : null
}
});
}
});
},
remove: function(args) {
$.ajax({
url: createURL('deleteSnapshotPolicies'),
data: {
id: args.snapshot.id
},
dataType: 'json',
async: true,
success: function(data) {
args.response.success();
}
});
}
},
// Select data
selects: {
schedule: function(args) {
var time = [];
for (var i = 1; i <= 59; i++) {
time.push({
id: i,
name: i
});
}
args.response.success({
data: time
});
},
timezone: function(args) {
args.response.success({
data: $.map(timezoneMap, function(value, key) {
return {
id: key,
name: value
};
})
});
},
'day-of-week': function(args) {
args.response.success({
data: [{
id: 1,
name: 'label.sunday'
}, {
id: 2,
name: 'label.monday'
}, {
id: 3,
name: 'label.tuesday'
}, {
id: 4,
name: 'label.wednesday'
}, {
id: 5,
name: 'label.thursday'
}, {
id: 6,
name: 'label.friday'
}, {
id: 7,
name: 'label.saturday'
}]
});
},
'day-of-month': function(args) {
var time = [];
for (var i = 1; i <= 28; i++) {
time.push({
id: i,
name: i
});
}
args.response.success({
data: time
});
},
'time-hour': function(args) {
var time = [];
for (var i = 1; i <= 12; i++) {
time.push({
id: i,
name: i
});
}
args.response.success({
data: time
});
},
'time-minute': function(args) {
var time = [];
for (var i = 0; i <= 59; i++) {
time.push({
id: i < 10 ? '0' + i : i,
name: i < 10 ? '0' + i : i
});
}
args.response.success({
data: time
});
},
'time-meridiem': function(args) {
args.response.success({
data: [{
id: 'AM',
name: 'AM'
}, {
id: 'PM',
name: 'PM'
}]
});
}
}
})
},
messages: {
notification: function(args) {
return 'label.snapshot.schedule';
}
}
},
attachDisk: {
addRow: 'false',
label: 'label.action.attach.disk',
messages: {
confirm: function(args) {
return 'message.confirm.attach.disk';
},
notification: function(args) {
return 'label.action.attach.disk';
}
},
createForm: {
title: 'label.action.attach.disk',
desc: 'label.action.attach.disk',
fields: {
virtualMachineId: {
label: 'label.instance',
select: function(args) {
var zoneid = args.context.volumes[0].zoneid;
var items = [];
var data;
if (!args.context.projects) {
data = {
zoneid: zoneid,
domainid: args.context.volumes[0].domainid,
account: args.context.volumes[0].account
};
} else {
data = {
zoneid: zoneid,
projectid: args.context.projects[0].id
};
}
if (args.context.volumes[0].hypervisor != null && args.context.volumes[0].hypervisor.length > 0 && args.context.volumes[0].hypervisor != 'None') {
data = $.extend(data, {
hypervisor: args.context.volumes[0].hypervisor
});
}
$(['Running', 'Stopped']).each(function() {
$.ajax({
url: createURL('listVirtualMachines'),
data: $.extend(data, {
state: this.toString()
}),
async: false,
success: function(json) {
var instanceObjs = json.listvirtualmachinesresponse.virtualmachine;
$(instanceObjs).each(function() {
items.push({
id: this.id,
description: this.displayname ? this.displayname : this.name
});
});
}
});
});
args.response.success({
data: items
});
}
}
}
},
action: function(args) {
$.ajax({
url: createURL("attachVolume&id=" + args.context.volumes[0].id + '&virtualMachineId=' + args.data.virtualMachineId),
dataType: "json",
async: true,
success: function(json) {
var jid = json.attachvolumeresponse.jobid;
args.response.success({
_custom: {
jobId: jid,
getUpdatedItem: function(json) {
return json.queryasyncjobresultresponse.jobresult.volume;
},
getActionFilter: function() {
return volumeActionfilter;
}
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
},
detachDisk: {
label: 'label.action.detach.disk',
messages: {
confirm: function(args) {
return 'message.detach.disk';
},
notification: function(args) {
return 'label.action.detach.disk';
}
},
action: function(args) {
$.ajax({
url: createURL("detachVolume&id=" + args.context.volumes[0].id),
dataType: "json",
async: true,
success: function(json) {
var jid = json.detachvolumeresponse.jobid;
args.response.success({
_custom: {
jobId: jid,
getUpdatedItem: function(json) {
return {
virtualmachineid: null,
vmdisplayname: null
};
},
getActionFilter: function() {
return volumeActionfilter;
}
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
},
downloadVolume: {
label: 'label.action.download.volume',
messages: {
confirm: function(args) {
return 'message.download.volume.confirm';
},
notification: function(args) {
return 'label.action.download.volume';
},
complete: function(args) {
var url = args.url;
var htmlMsg = _l('message.download.volume');
var htmlMsg2 = htmlMsg.replace(/#/, url).replace(/00000/, url);
//$infoContainer.find("#info").html(htmlMsg2);
return htmlMsg2;
}
},
action: function(args) {
$.ajax({
url: createURL("extractVolume&id=" + args.context.volumes[0].id + "&zoneid=" + args.context.volumes[0].zoneid + "&mode=HTTP_DOWNLOAD"),
dataType: "json",
async: true,
success: function(json) {
var jid = json.extractvolumeresponse.jobid;
args.response.success({
_custom: {
jobId: jid,
getUpdatedItem: function(json) {
return json.queryasyncjobresultresponse.jobresult.volume;
},
getActionFilter: function() {
return volumeActionfilter;
}
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
},
createTemplate: {
label: 'label.create.template',
messages: {
confirm: function(args) {
return 'message.create.template';
},
notification: function(args) {
return 'label.create.template';
}
},
createForm: {
title: 'label.create.template',
preFilter: cloudStack.preFilter.createTemplate,
desc: '',
preFilter: function(args) {
if (args.context.volumes[0].hypervisor == "XenServer") {
args.$form.find('.form-item[rel=xenserverToolsVersion61plus]').css('display', 'inline-block');
}
},
fields: {
name: {
label: 'label.name',
validation: {
required: true
}
},
displayText: {
label: 'label.description',
validation: {
required: true
}
},
xenserverToolsVersion61plus: {
label: 'label.xenserver.tools.version.61.plus',
isBoolean: true,
isChecked: function (args) {
var b = false;
var vmObj;
$.ajax({
url: createURL("listVirtualMachines"),
data: {
id: args.context.volumes[0].virtualmachineid
},
async: false,
success: function(json) {
vmObj = json.listvirtualmachinesresponse.virtualmachine[0];
}
});
if (vmObj == undefined) { //e.g. VM has failed over
if (isAdmin()) {
$.ajax({
url: createURL('listConfigurations'),
data: {
name: 'xenserver.pvdriver.version'
},
async: false,
success: function (json) {
if (json.listconfigurationsresponse.configuration != null && json.listconfigurationsresponse.configuration[0].value == 'xenserver61') {
b = true;
}
}
});
}
} else {
if ('details' in vmObj && 'hypervisortoolsversion' in vmObj.details) {
if (vmObj.details.hypervisortoolsversion == 'xenserver61')
b = true;
else
b = false;
}
}
return b;
},
isHidden: true
},
osTypeId: {
label: 'label.os.type',
select: function(args) {
$.ajax({
url: createURL("listOsTypes"),
dataType: "json",
async: true,
success: function(json) {
var ostypes = json.listostypesresponse.ostype;
var items = [];
$(ostypes).each(function() {
items.push({
id: this.id,
description: this.description
});
});
args.response.success({
data: items
});
}
});
}
},
isPublic: {
label: 'label.public',
isBoolean: true
},
isPasswordEnabled: {
label: 'label.password.enabled',
isBoolean: true
},
isFeatured: {
label: 'label.featured',
isBoolean: true
},
isdynamicallyscalable: {
label: 'label.dynamically.scalable',
isBoolean: true
}
}
},
action: function(args) {
var data = {
volumeId: args.context.volumes[0].id,
name: args.data.name,
displayText: args.data.displayText,
osTypeId: args.data.osTypeId,
isPublic: (args.data.isPublic == "on"),
passwordEnabled: (args.data.isPasswordEnabled == "on"),
isdynamicallyscalable: (args.data.isdynamicallyscalable == "on")
};
if (args.$form.find('.form-item[rel=isFeatured]').css("display") != "none") {
$.extend(data, {
isfeatured: (args.data.isFeatured == "on")
});
}
//XenServer only (starts here)
if (args.$form.find('.form-item[rel=xenserverToolsVersion61plus]').length > 0) {
if (args.$form.find('.form-item[rel=xenserverToolsVersion61plus]').css("display") != "none") {
$.extend(data, {
'details[0].hypervisortoolsversion': (args.data.xenserverToolsVersion61plus == "on") ? "xenserver61" : "xenserver56"
});
}
}
//XenServer only (ends here)
$.ajax({
url: createURL('createTemplate'),
data: data,
success: function(json) {
var jid = json.createtemplateresponse.jobid;
args.response.success({
_custom: {
jobId: jid,
getUpdatedItem: function(json) {
return {}; //no properties in this volume needs to be updated
},
getActionFilter: function() {
return volumeActionfilter;
}
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
},
migrateToAnotherStorage: {
label: 'label.migrate.volume.to.primary.storage',
messages: {
confirm: function(args) {
return 'message.migrate.volume';
},
notification: function(args) {
return 'label.migrate.volume.to.primary.storage';
}
},
createForm: {
title: 'label.migrate.volume.to.primary.storage',
desc: '',
fields: {
storageId: {
label: 'label.primary.storage',
validation: {
required: true
},
select: function(args) {
$.ajax({
url: createURL("listStoragePools&zoneid=" + args.context.volumes[0].zoneid),
dataType: "json",
async: true,
success: function(json) {
var pools = json.liststoragepoolsresponse.storagepool;
var items = [];
$(pools).each(function() {
items.push({
id: this.id,
description: this.name
});
});
args.response.success({
data: items
});
}
});
}
}
}
},
action: function(args) {
$.ajax({
url: createURL("migrateVolume&storageid=" + args.data.storageId + "&volumeid=" + args.context.volumes[0].id),
dataType: "json",
async: true,
success: function(json) {
var jid = json.migratevolumeresponse.jobid;
args.response.success({
_custom: {
jobId: jid,
getUpdatedItem: function(json) {
return json.queryasyncjobresultresponse.jobresult.volume;
},
getActionFilter: function() {
return volumeActionfilter;
}
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
},
remove: {
label: 'label.action.delete.volume',
messages: {
confirm: function(args) {
return 'message.action.delete.volume';
},
notification: function(args) {
return 'label.action.delete.volume';
}
},
action: function(args) {
$.ajax({
url: createURL("deleteVolume&id=" + args.context.volumes[0].id),
dataType: "json",
async: true,
success: function(json) {
args.response.success();
}
});
},
notification: {
poll: function(args) {
args.complete();
}
}
},
resize: {
label: 'label.action.resize.volume',
messages: {
notification: function(args) {
return 'label.action.resize.volume';
}
},
createForm: {
title: 'label.action.resize.volume',
preFilter: function(args) {
var vol;
if (args.context.volumes != null) vol = args.context.volumes[0];
if (vol.type == "ROOT" && (vol.hypervisor == "XenServer" || vol.hypervisor == "KVM" || vol.hypervisor == "VMware")) {
args.$form.find('.form-item[rel=newdiskoffering]').hide();
args.$form.find('.form-item[rel=newsize]').css('display', 'inline-block');
} else {
args.$form.find('.form-item[rel=newdiskoffering]').css('display', 'inline-block');
args.$form.find('.form-item[rel=newsize]').hide();
}
},
fields: {
newdiskoffering: {
label: 'label.resize.new.offering.id',
isHidden: true,
select: function(args) {
if (args.context.volumes != null && args.context.volumes[0].type == 'ROOT') {
args.response.success({
data: []
});
return;
}
$.ajax({
url: createURL("listDiskOfferings"),
dataType: "json",
success: function(json) {
diskofferingObjs = json.listdiskofferingsresponse.diskoffering;
var items = [];
$(diskofferingObjs).each(function() {
items.push({
id: this.id,
description: this.displaytext
});
});
args.response.success({
data: items
});
}
});
args.$select.change(function() {
if(args.context.volumes[0].type == "ROOT") {
selectedDiskOfferingObj = null;
return;
}
var diskOfferingId = $(this).val();
$(diskofferingObjs).each(function() {
if (this.id == diskOfferingId) {
selectedDiskOfferingObj = this;
return false; //break the $.each() loop
}
});
if (selectedDiskOfferingObj == null)
return;
var $form = $(this).closest('form');
var $shrinkok = $form.find('.form-item[rel=shrinkok]');
//unit of args.context.volumes[0].size is "byte"
//unit of selectedDiskOfferingObj.disksize is "gigabyte" ("GB"), so transfer it into "byte" by multiply (1024 * 1024 * 1024)
if (args.context.volumes[0].size > selectedDiskOfferingObj.disksize * (1024 * 1024 * 1024)) { //if original disk size > new disk size
$shrinkok.css('display', 'inline-block');
} else {
$shrinkok.hide();
}
var $newsize = $form.find('.form-item[rel=newsize]');
if (selectedDiskOfferingObj.iscustomized == true) {
$newsize.css('display', 'inline-block');
} else {
$newsize.hide();
}
var $minIops = $form.find('.form-item[rel=minIops]');
var $maxIops = $form.find('.form-item[rel=maxIops]');
if (selectedDiskOfferingObj.iscustomizediops == true) {
$minIops.css('display', 'inline-block');
$maxIops.css('display', 'inline-block');
} else {
$minIops.hide();
$maxIops.hide();
}
});
}
},
newsize: {
label: 'label.resize.new.size',
validation: {
required: true,
number: true
}
},
shrinkok: {
label: 'label.resize.shrink.ok',
isBoolean: true,
isChecked: false,
isHidden: true
},
minIops: {
label: 'label.disk.iops.min',
validation: {
required: false,
number: true
},
isHidden: true
},
maxIops: {
label: 'label.disk.iops.max',
validation: {
required: false,
number: true
},
isHidden: true
}
}
},
action: function(args) {
var array1 = [];
var newSize;
if (selectedDiskOfferingObj == null || selectedDiskOfferingObj.iscustomized == true) {
newSize = args.data.newsize;
if (newSize != null && newSize.length > 0) {
array1.push("&size=" + todb(newSize));
}
} else {
if(args.$form.find('.form-item[rel=shrinkok]').css("display") != "none") {
array1.push("&shrinkok=" + (args.data.shrinkok == "on"));
}
var newDiskOffering = args.data.newdiskoffering;
if (selectedDiskOfferingObj.iscustomized == true) {
newSize = args.data.newsize;
}
if (newDiskOffering != null && newDiskOffering.length > 0) {
array1.push("&diskofferingid=" + todb(newDiskOffering));
}
if (newSize != null && newSize.length > 0) {
array1.push("&size=" + todb(newSize));
}
var minIops;
var maxIops
if (selectedDiskOfferingObj.iscustomizediops == true) {
minIops = args.data.minIops;
maxIops = args.data.maxIops;
}
if (minIops != null && minIops.length > 0) {
array1.push("&miniops=" + todb(minIops));
}
if (maxIops != null && maxIops.length > 0) {
array1.push("&maxiops=" + todb(maxIops));
}
}
$.ajax({
url: createURL("resizeVolume&id=" + args.context.volumes[0].id + array1.join("")),
dataType: "json",
async: true,
success: function(json) {
var jid = json.resizevolumeresponse.jobid;
args.response.success({
_custom: {
jobId: jid,
getUpdatedItem: function(json) {
return json.queryasyncjobresultresponse.jobresult.volume;
},
getActionFilter: function() {
return volumeActionfilter;
}
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
}
},
tabs: {
details: {
title: 'label.details',
preFilter: function(args) {
var hiddenFields;
if (isAdmin()) {
hiddenFields = [];
} else {
hiddenFields = ['storage', 'hypervisor'];
}
return hiddenFields;
},
fields: [{
name: {
label: 'label.name',
isEditable: true
}
}, {
id: {
label: 'label.id'
},
zonename: {
label: 'label.zone'
},
state: {
label: 'label.state',
pollAgainIfValueIsIn: {
'UploadNotStarted': 1
},
pollAgainFn: function(context) {
var toClearInterval = false;
$.ajax({
url: createURL("listVolumes&id=" + context.volumes[0].id),
dataType: "json",
async: false,
success: function(json) {
var jsonObj = json.listvolumesresponse.volume[0];
if (jsonObj.state != context.volumes[0].state) {
toClearInterval = true; //to clear interval
}
}
});
return toClearInterval;
}
},
status: {
label: 'label.status'
},
diskofferingdisplaytext: {
label: 'label.disk.offering'
},
type: {
label: 'label.type'
},
storagetype: {
label: 'label.storage.type'
},
provisioningtype: {
label: 'label.disk.provisioningtype'
},
hypervisor: {
label: 'label.hypervisor'
},
size: {
label: 'label.size',
converter: function(args) {
if (args == null || args == 0)
return "";
else
return cloudStack.converters.convertBytes(args);
}
},
miniops: {
label: 'label.disk.iops.min',
converter: function(args) {
if (args == null || args == 0)
return "";
else
return args;
}
},
maxiops: {
label: 'label.disk.iops.max',
converter: function(args) {
if (args == null || args == 0)
return "";
else
return args;
}
},
virtualmachineid: {
label: 'label.vm.id',
converter: function(args) {
if (args == null)
return _l('state.detached');
else
return args;
}
},
//vmname: { label: 'label.vm.name' },
vmdisplayname: {
label: 'label.vm.display.name'
},
vmstate: {
label: 'label.vm.state'
},
deviceid: {
label: 'label.device.id'
},
storage: {
label: 'label.storage'
},
created: {
label: 'label.created',
converter: cloudStack.converters.toLocalDate
},
domain: {
label: 'label.domain'
},
account: {
label: 'label.account'
}
}],
tags: cloudStack.api.tags({
resourceType: 'Volume',
contextId: 'volumes'
}),
dataProvider: function(args) {
$.ajax({
url: createURL("listVolumes&id=" + args.context.volumes[0].id),
dataType: "json",
async: true,
success: function(json) {
var jsonObj = json.listvolumesresponse.volume[0];
$(window).trigger('cloudStack.module.sharedFunctions.addExtraProperties', {
obj: jsonObj,
objType: "Volume"
});
args.response.success({
actionFilter: volumeActionfilter,
data: jsonObj
});
}
});
}
}
}
}
}
},
/**
* Snapshots
*/
snapshots: {
type: 'select',
title: 'label.snapshots',
listView: {
id: 'snapshots',
label: 'label.snapshots',
fields: {
volumename: {
label: 'label.volume'
},
name: {
label: 'label.name'
},
intervaltype: {
label: 'label.interval.type'
},
created: {
label: 'label.created',
converter: cloudStack.converters.toLocalDate
},
state: {
label: 'label.state',
indicator: {
'BackedUp': 'on',
'Destroyed': 'off'
}
}
},
advSearchFields: {
name: {
label: 'label.name'
},
domainid: {
label: 'label.domain',
select: function(args) {
if (isAdmin() || isDomainAdmin()) {
$.ajax({
url: createURL('listDomains'),
data: {
listAll: true,
details: 'min'
},
success: function(json) {
var array1 = [{
id: '',
description: ''
}];
var domains = json.listdomainsresponse.domain;
if (domains != null && domains.length > 0) {
for (var i = 0; i < domains.length; i++) {
array1.push({
id: domains[i].id,
description: domains[i].path
});
}
}
array1.sort(function(a, b) {
return a.description.localeCompare(b.description);
});
args.response.success({
data: array1
});
}
});
} else {
args.response.success({
data: null
});
}
},
isHidden: function(args) {
if (isAdmin() || isDomainAdmin())
return false;
else
return true;
}
},
account: {
label: 'label.account',
isHidden: function(args) {
if (isAdmin() || isDomainAdmin())
return false;
else
return true;
}
},
tagKey: {
label: 'label.tag.key'
},
tagValue: {
label: 'label.tag.value'
}
},
dataProvider: function(args) {
var data = {};
var instanceVolumeIds = [];
listViewDataProvider(args, data);
if (args.context != null) {
if ("volumes" in args.context) {
$.extend(data, {
volumeid: args.context.volumes[0].id
});
} else if (args.context.instances) {
$.ajax({
url: createURL('listVolumes'),
data: {
virtualmachineid: args.context.instances[0].id,
listAll: true
},
async: false,
success: function(json) {
instanceVolumeIds = $.map(json.listvolumesresponse.volume, function(volume) {
return volume.id;
})
}
});
data.volumeid = instanceVolumeIds.join(',');
}
}
$.ajax({
url: createURL('listSnapshots'),
data: data,
success: function(json) {
var items = json.listsnapshotsresponse.snapshot;
args.response.success({
actionFilter: snapshotActionfilter,
data: items
});
},
error: function(XMLHttpResponse) {
cloudStack.dialog.notice({
message: parseXMLHttpResponse(XMLHttpResponse)
});
args.response.error();
}
});
},
detailView: {
name: 'Snapshot detail',
actions: {
createTemplate: {
label: 'label.create.template',
messages: {
confirm: function(args) {
return 'message.create.template';
},
notification: function(args) {
return 'label.create.template';
}
},
createForm: {
title: 'label.create.template',
desc: '',
fields: {
name: {
label: 'label.name',
validation: {
required: true
}
},
displayText: {
label: 'label.description',
validation: {
required: true
}
},
osTypeId: {
label: 'label.os.type',
select: function(args) {
$.ajax({
url: createURL("listOsTypes"),
dataType: "json",
async: true,
success: function(json) {
var ostypes = json.listostypesresponse.ostype;
var items = [];
$(ostypes).each(function() {
items.push({
id: this.id,
description: this.description
});
});
args.response.success({
data: items
});
}
});
}
},
isPublic: {
label: 'label.public',
isBoolean: true
},
isPasswordEnabled: {
label: 'label.password.enabled',
isBoolean: true
},
isdynamicallyscalable: {
label: 'label.dynamically.scalable',
isBoolean: true
}
}
},
action: function(args) {
var data = {
snapshotid: args.context.snapshots[0].id,
name: args.data.name,
displayText: args.data.displayText,
osTypeId: args.data.osTypeId,
isPublic: (args.data.isPublic == "on"),
passwordEnabled: (args.data.isPasswordEnabled == "on"),
isdynamicallyscalable: (args.data.isdynamicallyscalable == "on")
};
$.ajax({
url: createURL('createTemplate'),
data: data,
success: function(json) {
var jid = json.createtemplateresponse.jobid;
args.response.success({
_custom: {
jobId: jid,
getUpdatedItem: function(json) {
return {}; //nothing in this snapshot needs to be updated
},
getActionFilter: function() {
return snapshotActionfilter;
}
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
},
createVolume: {
label: 'label.action.create.volume',
messages: {
confirm: function(args) {
return 'message.confirm.create.volume';
},
notification: function(args) {
return 'label.action.create.volume';
}
},
createForm: {
title: 'label.action.create.volume',
desc: '',
preFilter: function(args) {
if (g_regionsecondaryenabled == true) {
args.$form.find('.form-item[rel=zoneid]').css('display', 'inline-block');
} else {
args.$form.find('.form-item[rel=zoneid]').hide();
}
},
fields: {
name: {
label: 'label.name',
validation: {
required: true
}
},
zoneid: {
label: 'label.availability.zone',
isHidden: true,
select: function(args) {
$.ajax({
url: createURL("listZones&available=true"),
dataType: "json",
async: true,
success: function(json) {
var zoneObjs = json.listzonesresponse.zone;
var items = [{
id: '',
description: ''
}];
if (zoneObjs != null) {
for (i = 0; i < zoneObjs.length; i++) {
items.push({
id: zoneObjs[i].id,
description: zoneObjs[i].name
});
}
}
args.response.success({
data: items
});
}
});
}
}
}
},
action: function(args) {
var data = {
snapshotid: args.context.snapshots[0].id,
name: args.data.name
};
if (args.$form.find('.form-item[rel=zoneid]').css("display") != "none" && args.data.zoneid != '') {
$.extend(data, {
zoneId: args.data.zoneid
});
}
$.ajax({
url: createURL('createVolume'),
data: data,
success: function(json) {
var jid = json.createvolumeresponse.jobid;
args.response.success({
_custom: {
jobId: jid,
getUpdatedItem: function(json) {
return {}; //nothing in this snapshot needs to be updated
},
getActionFilter: function() {
return snapshotActionfilter;
}
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
},
revertSnapshot: {
label: 'label.action.revert.snapshot',
messages: {
confirm: function(args) {
return 'message.action.revert.snapshot';
},
notification: function(args) {
return 'label.action.revert.snapshot';
}
},
action: function(args) {
$.ajax({
url: createURL("revertSnapshot&id="+args.context.snapshots[0].id),
dataType: "json",
async: true,
success: function(json) {
var jid = json.revertsnapshotresponse.jobid;
args.response.success({
_custom: {
jobId: jid
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
},
remove: {
label: 'label.action.delete.snapshot',
messages: {
confirm: function(args) {
return 'message.action.delete.snapshot';
},
notification: function(args) {
return 'label.action.delete.snapshot';
}
},
action: function(args) {
$.ajax({
url: createURL("deleteSnapshot&id=" + args.context.snapshots[0].id),
dataType: "json",
async: true,
success: function(json) {
var jid = json.deletesnapshotresponse.jobid;
args.response.success({
_custom: {
jobId: jid
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
}
},
tabs: {
details: {
title: 'label.details',
fields: [{
name: {
label: 'label.name'
}
}, {
id: {
label: 'label.id'
},
volumename: {
label: 'label.volume.name'
},
state: {
label: 'label.state'
},
intervaltype: {
label: 'label.interval.type'
},
domain: {
label: 'label.domain'
},
account: {
label: 'label.account'
},
created: {
label: 'label.created',
converter: cloudStack.converters.toLocalDate
}
}],
tags: cloudStack.api.tags({
resourceType: 'Snapshot',
contextId: 'snapshots'
}),
dataProvider: function(args) {
$.ajax({
url: createURL("listSnapshots&id=" + args.context.snapshots[0].id),
dataType: "json",
async: true,
success: function(json) {
var jsonObj = json.listsnapshotsresponse.snapshot[0];
args.response.success({
actionFilter: snapshotActionfilter,
data: jsonObj
});
}
});
}
}
}
}
},
},
/**
* VM Snapshots
*/
vmsnapshots: {
type: 'select',
title: 'label.vmsnapshot',
listView: {
id: 'vmsnapshots',
isMaximized: true,
fields: {
displayname: {
label: 'label.name'
},
state: {
label: 'label.state',
indicator: {
'Ready': 'on',
'Error': 'off'
}
},
type: {
label: 'label.vmsnapshot.type'
},
current: {
label: 'label.vmsnapshot.current',
converter: cloudStack.converters.toBooleanText
},
parentName: {
label: 'label.vmsnapshot.parentname'
},
created: {
label: 'label.date',
converter: cloudStack.converters.toLocalDate
}
},
advSearchFields: {
name: {
label: 'label.name'
},
domainid: {
label: 'label.domain',
select: function(args) {
if (isAdmin() || isDomainAdmin()) {
$.ajax({
url: createURL('listDomains'),
data: {
listAll: true,
details: 'min'
},
success: function(json) {
var array1 = [{
id: '',
description: ''
}];
var domains = json.listdomainsresponse.domain;
if (domains != null && domains.length > 0) {
for (var i = 0; i < domains.length; i++) {
array1.push({
id: domains[i].id,
description: domains[i].path
});
}
}
array1.sort(function(a, b) {
return a.description.localeCompare(b.description);
});
args.response.success({
data: array1
});
}
});
} else {
args.response.success({
data: null
});
}
},
isHidden: function(args) {
if (isAdmin() || isDomainAdmin())
return false;
else
return true;
}
},
account: {
label: 'label.account',
isHidden: function(args) {
if (isAdmin() || isDomainAdmin())
return false;
else
return true;
}
},
tagKey: {
label: 'label.tag.key'
},
tagValue: {
label: 'label.tag.value'
}
},
dataProvider: function(args) {
var data = {};
listViewDataProvider(args, data);
if (args.context != null) {
if ("instances" in args.context) {
$.extend(data, {
virtualMachineId: args.context.instances[0].id
});
}
}
$.ajax({
url: createURL('listVMSnapshot&listAll=true'),
data: data,
dataType: "json",
async: true,
success: function(json) {
var jsonObj;
jsonObj = json.listvmsnapshotresponse.vmSnapshot;
args.response.success({
actionFilter: vmSnapshotActionfilter,
data: jsonObj
});
}
});
},
//dataProvider end
detailView: {
tabs: {
details: {
title: 'label.details',
fields: {
id: {
label: 'label.id'
},
name: {
label: 'label.name'
},
displayname: {
label: 'label.display.name'
},
type: {
label: 'label.vmsnapshot.type'
},
description: {
label: 'label.description'
},
state: {
label: 'label.state',
indicator: {
'Ready': 'on',
'Error': 'off'
}
},
current: {
label: 'label.vmsnapshot.current',
converter: cloudStack.converters.toBooleanText
},
parentName: {
label: 'label.vmsnapshot.parentname'
},
domain: {
label: 'label.domain'
},
account: {
label: 'label.account'
},
virtualmachineid: {
label: 'label.vm.id'
},
created: {
label: 'label.date',
converter: cloudStack.converters.toLocalDate
}
},
dataProvider: function(args) {
$.ajax({
url: createURL("listVMSnapshot&listAll=true&vmsnapshotid=" + args.context.vmsnapshots[0].id),
dataType: "json",
async: true,
success: function(json) {
var jsonObj;
jsonObj = json.listvmsnapshotresponse.vmSnapshot[0];
args.response.success({
actionFilter: vmSnapshotActionfilter,
data: jsonObj
});
}
});
},
tags: cloudStack.api.tags({
resourceType: 'VMSnapshot',
contextId: 'vmsnapshots'
})
}
},
actions: {
//delete a snapshot
remove: {
label: 'label.action.vmsnapshot.delete',
messages: {
confirm: function(args) {
return 'message.action.vmsnapshot.delete';
},
notification: function(args) {
return 'label.action.vmsnapshot.delete';
}
},
action: function(args) {
$.ajax({
url: createURL("deleteVMSnapshot&vmsnapshotid=" + args.context.vmsnapshots[0].id),
dataType: "json",
async: true,
success: function(json) {
var jid = json.deletevmsnapshotresponse.jobid;
args.response.success({
_custom: {
jobId: jid
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
},
revertToVMSnapshot: {
label: 'label.action.vmsnapshot.revert',
messages: {
confirm: function(args) {
return 'label.action.vmsnapshot.revert';
},
notification: function(args) {
return 'message.action.vmsnapshot.revert';
}
},
action: function(args) {
$.ajax({
url: createURL("revertToVMSnapshot&vmsnapshotid=" + args.context.vmsnapshots[0].id),
dataType: "json",
async: true,
success: function(json) {
var jid = json.reverttovmsnapshotresponse.jobid;
args.response.success({
_custom: {
jobId: jid
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
},
takeSnapshot: {
label: 'Create Snapshot From VM Snapshot',
messages: {
confirm: function(args) {
return 'Please confirm that you want to create a volume snapshot from the vm snapshot.';
},
notification: function(args) {
return 'Volume snapshot is created from vm snapshot';
}
},
createForm: {
title: 'label.action.take.snapshot',
desc: 'message.action.take.snapshot',
fields: {
name: {
label: 'label.name',
},
volume: {
label: 'label.volume',
validation: {
required: true
},
select: function(args) {
$.ajax({
url: createURL("listVolumes&virtualMachineId=" + args.context.vmsnapshots[0].virtualmachineid),
dataType: "json",
async: true,
success: function(json) {
var volumes = json.listvolumesresponse.volume;
var items = [];
$(volumes).each(function() {
items.push({
id: this.id,
description: this.name
});
});
args.response.success({
data: items
});
}
});
}
}
}
},
action: function(args) {
var data = {
volumeid: args.data.volume,
vmsnapshotid: args.context.vmsnapshots[0].id
};
if (args.data.name != null && args.data.name.length > 0) {
$.extend(data, {
name: args.data.name
});
}
$.ajax({
url: createURL("createSnapshotFromVMSnapshot"),
data: data,
dataType: "json",
async: true,
success: function(json) {
var jid = json.createsnapshotfromvmsnapshotresponse.jobid;
args.response.success({
_custom: {
jobId: jid
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
}
}
}
//detailview end
}
}
}
};
var volumeActionfilter = cloudStack.actionFilter.volumeActionfilter = function(args) {
var jsonObj = args.context.item;
var allowedActions = [];
if (jsonObj.state == 'Destroyed' || jsonObj.state == 'Migrating' || jsonObj.state == 'Uploading') {
return [];
}
if (jsonObj.state == 'UploadError') {
return ["remove"];
}
if (jsonObj.hypervisor != "Ovm" && jsonObj.state == "Ready") {
if (jsonObj.hypervisor == 'KVM') {
if (jsonObj.vmstate == 'Running') {
if (g_kvmsnapshotenabled == true) { //"kvm.snapshot.enabled" flag should be taken to account only when snapshot is being created for Running vm (CLOUDSTACK-4428)
allowedActions.push("takeSnapshot");
allowedActions.push("recurringSnapshot");
}
} else {
allowedActions.push("takeSnapshot");
allowedActions.push("recurringSnapshot");
}
} else {
allowedActions.push("takeSnapshot");
allowedActions.push("recurringSnapshot");
}
}
if ((jsonObj.type == "DATADISK" || jsonObj.type == "ROOT") && (jsonObj.state == "Ready" || jsonObj.state == "Allocated")) {
allowedActions.push("resize");
}
if (jsonObj.state != "Allocated") {
if ((jsonObj.vmstate == "Stopped" || jsonObj.virtualmachineid == null) && jsonObj.state == "Ready") {
allowedActions.push("downloadVolume");
}
}
if (jsonObj.type == "ROOT" || jsonObj.type == "DATADISK") {
if (jsonObj.state == "Ready" && isAdmin() && jsonObj.virtualmachineid != null) {
allowedActions.push("migrateVolume");
}
}
if (jsonObj.state != "Creating") {
if (jsonObj.type == "ROOT") {
if (jsonObj.vmstate == "Stopped") {
allowedActions.push("createTemplate");
}
} else { //jsonObj.type == "DATADISK"
if (jsonObj.virtualmachineid != null) {
if (jsonObj.vmstate == "Running" || jsonObj.vmstate == "Stopped" || jsonObj.vmstate == "Destroyed") {
allowedActions.push("detachDisk");
}
} else { // Disk not attached
allowedActions.push("remove");
if (jsonObj.state == "Ready" && isAdmin() && jsonObj.storagetype == "shared") {
allowedActions.push("migrateToAnotherStorage");
}
allowedActions.push("attachDisk");
}
}
}
return allowedActions;
};
var snapshotActionfilter = cloudStack.actionFilter.snapshotActionfilter = function(args) {
var jsonObj = args.context.item;
if (jsonObj.state == 'Destroyed') {
return [];
}
var allowedActions = [];
if (jsonObj.state == "BackedUp") {
allowedActions.push("createTemplate");
allowedActions.push("createVolume");
if (jsonObj.revertable) {
allowedActions.push("revertSnapshot");
}
}
allowedActions.push("remove");
return allowedActions;
};
var vmSnapshotActionfilter = cloudStack.actionFilter.vmSnapshotActionfilter = function(args) {
var jsonObj = args.context.item;
if (jsonObj.state == 'Error') {
return ["remove"];
}
var allowedActions = [];
if (jsonObj.state == "Ready") {
allowedActions.push("remove");
allowedActions.push("revertToVMSnapshot");
allowedActions.push("takeSnapshot");
}
return allowedActions;
}
})(cloudStack);