mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
commit c9ee0d12e191e803fb341f3f96e95ca434a36f6c
Author: Wei Zhou <w.zhou@leaseweb.com>
Date: Wed Oct 23 16:55:10 2013 +0200
CLOUDSTACK-4931, CLOUDSTACK-4937: setDetails to user VMs only
(cherry picked from commit a94acc5a43aeaf5f18f1912e2653a92f6041a6e5)
commit fe1586c71377bc6d219db2dcf088c40b65dd1fc4
Author: Anthony Xu <anthony.xu@citrix.com>
Date: Tue Oct 22 11:20:27 2013 -0700
CLOUDSTACK-4649:
vm sync tracks the pv driver version for xenserver
Anthony
commit 56a218f66eda540b4b4b04030ee71fc6863f8532
Author: Anthony Xu <anthony.xu@citrix.com>
Date: Mon Oct 21 16:10:07 2013 -0700
CLOUDSTACK-4649:
xs 6.1/6.2 introduce the new virtual platform, so there are two virtual platforms, windows PV driver version must match virtual platforms,
this patch tracks PV driver versions in vm details and template details.
Anthony
commit 4e85d28c678a6f96b5b70d8d33fc60f9d1ea3df6
Author: Laszlo Hornyak <laszlo.hornyak@gmail.com>
Date: Mon Oct 21 21:17:33 2013 +0200
removed unused static field
- s_httpClientManager was not used
Signed-off-by: Laszlo Hornyak <laszlo.hornyak@gmail.com>
commit d4121fa26023db236f7396cea455ef090672ae9a
Author: Chris Suich <chris.suich@netapp.com>
Date: Tue Oct 22 10:45:22 2013 -0400
Updated DataMotionServiceImpl and ApiResponseHelper based on review feedback.
commit aaf026e1e4204d405bcda2ae4f1a01b1d0f7e7cb
Author: Chris Suich <chris.suich@netapp.com>
Date: Thu Oct 17 14:27:12 2013 -0400
Added context to strategy sorting error responses
Added TODOs for DRYing out pickStrategy() overloading
commit a221f4aa3fb2ddc255bc35cf753f98f88f5bf44e
Author: Chris Suich <chris.suich@netapp.com>
Date: Wed Oct 16 09:57:28 2013 -0400
Updated inefficient strategy sorting/selection
Removed unnecessary canRevertSnapshot from PrimaryDataStoreDriver
Other general cleaup and fixes from reviews
commit 7d58949c6a1b7e853e891b59387a9620e8cd7a91
Author: Chris Suich <chris.suich@netapp.com>
Date: Mon Oct 14 14:01:22 2013 -0400
Added volume snapshot revert capability to SnapshotResponse
Updated UI to hide/show snapshot revert action per snapshot
Signed-off-by: Edison Su <sudison@gmail.com>
1973 lines
106 KiB
JavaScript
1973 lines
106 KiB
JavaScript
// 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'
|
|
}
|
|
|
|
/*
|
|
state: {
|
|
label: 'State',
|
|
indicator: {
|
|
'Ready': 'on'
|
|
}
|
|
}
|
|
*/
|
|
},
|
|
|
|
// List view actions
|
|
actions: {
|
|
// Add volume
|
|
add: {
|
|
label: 'label.add.volume',
|
|
|
|
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',
|
|
validation: {
|
|
required: true
|
|
}
|
|
},
|
|
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',
|
|
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
|
|
}
|
|
},
|
|
|
|
uploadVolume: {
|
|
isHeader: true,
|
|
label: 'label.upload.volume',
|
|
messages: {
|
|
notification: function() {
|
|
return 'label.upload.volume';
|
|
}
|
|
},
|
|
createForm: {
|
|
title: 'label.upload.volume',
|
|
fields: {
|
|
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: 'OVA',
|
|
description: 'OVA'
|
|
});
|
|
items.push({
|
|
id: 'QCOW2',
|
|
description: 'QCOW2'
|
|
});
|
|
args.response.success({
|
|
data: items
|
|
});
|
|
}
|
|
},
|
|
url: {
|
|
label: 'label.url',
|
|
docID: 'helpUploadVolumeURL',
|
|
validation: {
|
|
required: true
|
|
}
|
|
},
|
|
checksum: {
|
|
docID: 'helpUploadVolumeChecksum',
|
|
label: 'label.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.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
|
|
}
|
|
}
|
|
},
|
|
|
|
advSearchFields: {
|
|
name: {
|
|
label: 'Name'
|
|
},
|
|
zoneid: {
|
|
label: 'Zone',
|
|
select: function(args) {
|
|
$.ajax({
|
|
url: createURL('listZones'),
|
|
data: {
|
|
listAll: true
|
|
},
|
|
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: '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
|
|
});
|
|
}
|
|
}
|
|
args.response.success({
|
|
data: array1
|
|
});
|
|
}
|
|
});
|
|
} else {
|
|
args.response.success({
|
|
data: null
|
|
});
|
|
}
|
|
},
|
|
isHidden: function(args) {
|
|
if (isAdmin() || isDomainAdmin())
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
},
|
|
|
|
account: {
|
|
label: 'Account',
|
|
isHidden: function(args) {
|
|
if (isAdmin() || isDomainAdmin())
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
},
|
|
|
|
tagKey: {
|
|
label: 'Tag Key'
|
|
},
|
|
tagValue: {
|
|
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('listVolumes'),
|
|
data: data,
|
|
success: function(json) {
|
|
var items = json.listvolumesresponse.volume;
|
|
args.response.success({
|
|
actionFilter: volumeActionfilter,
|
|
data: items
|
|
});
|
|
}
|
|
});
|
|
},
|
|
|
|
detailView: {
|
|
name: 'Volume details',
|
|
viewAll: {
|
|
path: 'storage.snapshots',
|
|
label: 'label.snapshots'
|
|
},
|
|
actions: {
|
|
|
|
migrateVolume: {
|
|
label: 'Migrate Volume',
|
|
messages: {
|
|
confirm: function(args) {
|
|
return 'Do you want to migrate this volume ?';
|
|
},
|
|
notification: function(args) {
|
|
return 'Volume migrated';
|
|
}
|
|
},
|
|
|
|
createForm: {
|
|
title: 'Migrate Volume',
|
|
desc: '',
|
|
fields: {
|
|
storagePool: {
|
|
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: {
|
|
confirm: function(args) {
|
|
return 'message.action.take.snapshot';
|
|
},
|
|
notification: function(args) {
|
|
return 'label.action.take.snapshot';
|
|
}
|
|
},
|
|
action: function(args) {
|
|
$.ajax({
|
|
url: createURL("createSnapshot&volumeid=" + args.context.volumes[0].id),
|
|
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 <= 31; 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 'Are you sure you want to 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,
|
|
vmname: 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: '',
|
|
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
|
|
},
|
|
isFeatured: {
|
|
label: "label.featured",
|
|
isBoolean: true
|
|
},
|
|
isdynamicallyscalable: {
|
|
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")
|
|
});
|
|
}
|
|
|
|
$.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',
|
|
messages: {
|
|
confirm: function(args) {
|
|
return 'message.migrate.volume';
|
|
},
|
|
notification: function(args) {
|
|
return 'label.migrate.volume';
|
|
}
|
|
},
|
|
createForm: {
|
|
title: 'label.migrate.volume',
|
|
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',
|
|
fields: {
|
|
newdiskoffering: {
|
|
label: 'label.resize.new.offering.id',
|
|
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 $newsize = $form.find('.form-item[rel=newsize]');
|
|
if (selectedDiskOfferingObj.iscustomized == true) {
|
|
$newsize.css('display', 'inline-block');
|
|
} else {
|
|
$newsize.hide();
|
|
}
|
|
});
|
|
}
|
|
},
|
|
newsize: {
|
|
label: 'label.resize.new.size',
|
|
validation: {
|
|
required: true,
|
|
number: true
|
|
},
|
|
isHidden: true
|
|
},
|
|
shrinkok: {
|
|
label: 'label.resize.shrink.ok',
|
|
isBoolean: true,
|
|
isChecked: false
|
|
}
|
|
}
|
|
},
|
|
action: function(args) {
|
|
var array1 = [];
|
|
array1.push("&shrinkok=" + (args.data.shrinkok == "on"));
|
|
var newDiskOffering = args.data.newdiskoffering;
|
|
var newSize;
|
|
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));
|
|
}
|
|
$.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: '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'
|
|
},
|
|
type: {
|
|
label: 'label.type'
|
|
},
|
|
storagetype: {
|
|
label: 'label.storage.type'
|
|
},
|
|
hypervisor: {
|
|
label: 'label.hypervisor'
|
|
},
|
|
size: {
|
|
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: 'VM ID',
|
|
converter: function(args) {
|
|
if (args == null)
|
|
return "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];
|
|
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'
|
|
},
|
|
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: 'Name'
|
|
},
|
|
|
|
domainid: {
|
|
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
|
|
});
|
|
}
|
|
}
|
|
args.response.success({
|
|
data: array1
|
|
});
|
|
}
|
|
});
|
|
} else {
|
|
args.response.success({
|
|
data: null
|
|
});
|
|
}
|
|
},
|
|
isHidden: function(args) {
|
|
if (isAdmin() || isDomainAdmin())
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
},
|
|
|
|
account: {
|
|
label: 'Account',
|
|
isHidden: function(args) {
|
|
if (isAdmin() || isDomainAdmin())
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
},
|
|
tagKey: {
|
|
label: 'Tag Key'
|
|
},
|
|
tagValue: {
|
|
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
|
|
});
|
|
}
|
|
});
|
|
},
|
|
|
|
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: "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 'Are you sure you want to create volume?';
|
|
},
|
|
notification: function(args) {
|
|
return 'label.action.create.volume';
|
|
}
|
|
},
|
|
createForm: {
|
|
title: 'label.action.create.volume',
|
|
desc: '',
|
|
fields: {
|
|
name: {
|
|
label: 'label.name',
|
|
validation: {
|
|
required: true
|
|
}
|
|
}
|
|
}
|
|
},
|
|
action: function(args) {
|
|
var data = {
|
|
snapshotid: args.context.snapshots[0].id,
|
|
name: args.data.name
|
|
};
|
|
|
|
$.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: function(args) {
|
|
args.complete();
|
|
}
|
|
}
|
|
}
|
|
},
|
|
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
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
var 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 (g_KVMsnapshotenabled == true) {
|
|
allowedActions.push("takeSnapshot");
|
|
allowedActions.push("recurringSnapshot");
|
|
} else {
|
|
if(jsonObj.vmstate == 'Stopped') {
|
|
allowedActions.push("takeSnapshot");
|
|
}
|
|
}
|
|
} else {
|
|
allowedActions.push("takeSnapshot");
|
|
allowedActions.push("recurringSnapshot");
|
|
}
|
|
|
|
if (jsonObj.type == "DATADISK") {
|
|
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 = 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 && args.context.volumes[0].vmstate == "Stopped") {
|
|
allowedActions.push("revertSnapshot");
|
|
}
|
|
}
|
|
allowedActions.push("remove");
|
|
|
|
return allowedActions;
|
|
}
|
|
|
|
})(cloudStack);
|