|  | // 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', | 
|  | 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 items = json.listzonesresponse.zone; | 
|  | args.response.success({descriptionField: 'name', data: items}); | 
|  | } | 
|  | }); | 
|  | } | 
|  | }, | 
|  | 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(); | 
|  | } | 
|  | }); | 
|  | } | 
|  | } | 
|  |  | 
|  | , | 
|  | diskSize: { | 
|  | label: 'label.disk.size.gb', | 
|  | validation: { required: true, 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 | 
|  | }); | 
|  | } | 
|  |  | 
|  | $.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 items = json.listzonesresponse.zone; | 
|  | args.response.success({descriptionField: 'name', data: items}); | 
|  | } | 
|  | }); | 
|  | } | 
|  | }, | 
|  | 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; | 
|  |  | 
|  | 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: { | 
|  | 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 = decodeURIComponent(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 } | 
|  | } | 
|  | }, | 
|  | 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") | 
|  | }; | 
|  |  | 
|  | 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(); | 
|  | } | 
|  | } | 
|  | } | 
|  | }, | 
|  | tabs: { | 
|  | details: { | 
|  | title: 'label.details', | 
|  |  | 
|  | preFilter: function(args) { | 
|  | var hiddenFields; | 
|  | if(isAdmin()) { | 
|  | hiddenFields = []; | 
|  | } | 
|  | else { | 
|  | hiddenFields = ["storage"]; | 
|  | } | 
|  | 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); | 
|  | } | 
|  | }, | 
|  | 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 = {}; | 
|  | listViewDataProvider(args, data); | 
|  |  | 
|  | if(args.context != null) { | 
|  | if("volumes" in args.context) { | 
|  | $.extend(data, { | 
|  | volumeid: args.context.volumes[0].id | 
|  | }); | 
|  | } | 
|  | } | 
|  |  | 
|  | $.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 } | 
|  | } | 
|  | }, | 
|  | 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") | 
|  | }; | 
|  |  | 
|  | $.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 | 
|  | } | 
|  | }, | 
|  |  | 
|  | 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") { | 
|  | allowedActions.push("takeSnapshot"); | 
|  | allowedActions.push("recurringSnapshot"); | 
|  | } | 
|  | if(jsonObj.state != "Allocated") { | 
|  | if((jsonObj.vmstate == "Stopped" || jsonObj.virtualmachineid == null) && jsonObj.state == "Ready") { | 
|  | allowedActions.push("downloadVolume"); | 
|  | } | 
|  | } | 
|  | 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"); | 
|  | } | 
|  | allowedActions.push("remove"); | 
|  |  | 
|  | return allowedActions; | 
|  | } | 
|  |  | 
|  | })(cloudStack); |