// 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 migrateVolumeCreateFormAction = {
            title: 'label.migrate.volume',
            fields: {
                storagePool: {
                    label: 'label.storage.pool',
                    validation: {
                        required: true
                    },
                    select: function(args) {
                        var mapStoragePoolsByUuid = new Map();
                        var volumeId = args.context.volumes[0].id;
                        var volumeBeingMigrated = undefined;
                        $.ajax({
                            url: createURL("listVolumes&id=" + volumeId),
                            dataType: "json",
                            async: false,
                            success: function(json){
                                volumeBeingMigrated = json.listvolumesresponse.volume[0]; 
                            }
                        });
                        var currentStoragePool = undefined;
                        $.ajax({
                            url: createURL("listStoragePools&id=" + volumeBeingMigrated.storageid),
                            dataType: "json",
                            async: false,
                            success: function(json){
                                currentStoragePool = json.liststoragepoolsresponse.storagepool[0]; 
                            }
                        });
                        var isVolumeNotAttachedToVm = volumeBeingMigrated.virtualmachineid == undefined;
                        var urlToRetrieveStoragePools = "findStoragePoolsForMigration&id=" + args.context.volumes[0].id;
                        if(isVolumeNotAttachedToVm){
                            urlToRetrieveStoragePools = "listStoragePools&zoneid=" + args.context.volumes[0].zoneid;
                        }
                        $.ajax({
                            url: createURL(urlToRetrieveStoragePools),
                            dataType: "json",
                            async: true,
                            success: function(json) {
                                var pools = undefined;
                                if(isVolumeNotAttachedToVm){
                                    pools = json.liststoragepoolsresponse.storagepool;
                                }else{
                                    pools = json.findstoragepoolsformigrationresponse.storagepool;
                                }
                                var items = [];
                                $(pools).each(function() {
                                    mapStoragePoolsByUuid.set(this.id, this);
                                    var description = this.name;
                                    if(!isVolumeNotAttachedToVm){
                                        description = description + " (" + (this.suitableformigration ? "Suitable" : "Not Suitable") + ")";
                                    }
                                    items.push({
                                        id: this.id,
                                        description: description
                                    });
                                });
                                args.response.success({
                                    data: items
                                });
                                var diskOfferings = cloudStack.listDiskOfferings({listAll: true});
                                $('select[name=storagePool]').change(function(){
                                    var uuidOfStoragePoolSelected = $(this).val();
                                    var storagePoolSelected = mapStoragePoolsByUuid.get(uuidOfStoragePoolSelected);
                                    if(currentStoragePool.scope === storagePoolSelected.scope){
                                        $('div[rel=newDiskOffering],div[rel=useNewDiskOffering]').hide();
                                    }else{
                                        $('div[rel=newDiskOffering],div[rel=useNewDiskOffering]').show();
                                    }
                                    var storageType = 'shared';
                                    if(storagePoolSelected.scope == 'HOST'){
                                        storageType = 'local';
                                    }
                                    $(diskOfferings).each(function(){
                                        var diskOfferingOption = $('option[value=' + this.id + ']');
                                        if(this.storagetype == storageType){
                                            diskOfferingOption.show();
                                        }else{
                                            diskOfferingOption.hide();
                                        }
                                    });
                                    var firstAvailableDiskOfferingForStorageType = $('select#label_disk_newOffering').children('option:visible').first().attr('value');
                                    $('select#label_disk_newOffering').attr('value', firstAvailableDiskOfferingForStorageType);
                                });
                                var functionHideShowNewDiskOfferint = function(){
                                    if($('div[rel=useNewDiskOffering] input[type=checkbox]').is(':checked')){
                                        $('div[rel=newDiskOffering]').show();
                                    }else{
                                        $('div[rel=newDiskOffering]').hide();
                                    }  
                                };
                                $('div[rel=useNewDiskOffering] input[type=checkbox]').click(functionHideShowNewDiskOfferint);
                                $('select[name=storagePool]').change();
                                functionHideShowNewDiskOfferint();
                            }
                        });
                    }
                },
            useNewDiskOffering:{
                label: 'label.migrate.volume.newDiskOffering',
                desc: 'label.migrate.volume.newDiskOffering.desc',
                validation: {
                    required: false
                   },
                isEditable: true, 
                isBoolean: true,
                defaultValue: 'Yes'
            },
            newDiskOffering: {
                label: 'label.disk.newOffering',
                desc: 'label.disk.newOffering.description',
                validation: {
                    required: false
                   },
                select: function(args){
                    var diskOfferings = cloudStack.listDiskOfferings({listAll: true});
                    var items = [];
                    $(diskOfferings).each(function() {
                        items.push({
                            id: this.id,
                            description: this.name
                        });
                    });
                    args.response.success({
                        data: items
                    });
                   }
               }
           }
        };
    var functionMigrateVolume = function(args) {
        var volumeBeingMigrated = args.context.volumes[0];
        var isLiveMigrate = volumeBeingMigrated.vmstate == 'Running';
        var migrateVolumeUrl = "migrateVolume&livemigrate="+ isLiveMigrate +"&storageid=" + args.data.storagePool + "&volumeid=" + volumeBeingMigrated.id;
        if($('div[rel=useNewDiskOffering] input[name=useNewDiskOffering]:checkbox').is(':checked')){
            migrateVolumeUrl = migrateVolumeUrl + '&newdiskofferingid=' + $('div[rel=newDiskOffering] select').val();
        }
        $.ajax({
            url: createURL(migrateVolumeUrl),
            dataType: "json",
            async: true,
            success: function(json) {
                $(window).trigger('cloudStack.fullRefresh');
                var jid = json.migratevolumeresponse.jobid;
                args.response.success({
                    _custom: {
                        jobId: jid
                    }
                });
            }
        });
    }

    var diskOfferingsObjList, selectedDiskOfferingObj = null;

    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');
                            hiddenFields.push('account');
                        }
                        return hiddenFields;
                    },
                    fields: {
                        name: {
                            label: 'label.name'
                        },
                        type: {
                            label: 'label.type'
                        },
                        vmdisplayname: {
                            label: 'label.vm.display.name'
                        },
                        hypervisor: {
                            label: 'label.hypervisor'
                        },
                        account: {
                            label: 'label.account'
                        },
                        zonename: {
                            label: 'label.zone'
                        },
                        vmdisplayname: {
                            label: 'label.vm.display.name'
                        },
                        state: {
                            label: 'label.metrics.state',
                            converter: function (str) {
                                // For localization
                                return str;
                            },
                            indicator: {
                                'Allocated': 'on',
                                'Ready': 'on',
                                'Destroy': 'off',
                                'Expunging': 'off',
                                'Expunged': 'off',
                                'Migrating': 'warning',
                                'UploadOp': 'warning',
                                'Snapshotting': 'warning',
                            }
                        }
                    },

                    // 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
                                                    });
                                                }
                                            });
                                            args.$select.change(function() {
                                                var diskOfferingSelect = $(this).closest('form').find('select[name=diskOffering]');
                                                if(diskOfferingSelect) {
                                                    $(diskOfferingSelect).find('option').remove().end();
                                                    var data = {
                                                        zoneid: $(this).val(),
                                                    };
                                                    console.log(data);
                                                    var diskOfferings = cloudStack.listDiskOfferings({ data: data });
                                                    diskOfferingsObjList = diskOfferings;
                                                    $(diskOfferings).each(function() {
                                                        $(diskOfferingSelect).append(new Option(this.displaytext, this.id));
                                                    });
                                                }
                                            });
                                        }
                                    },
                                    diskOffering: {
                                        label: 'label.disk.offering',
                                        docID: 'helpVolumeDiskOffering',
                                        select: function(args) {
                                            var diskOfferings = cloudStack.listDiskOfferings({});
                                            diskOfferingsObjList = diskOfferings;
                                            var items = [];
                                            $(diskOfferings).each(function() {
                                                items.push({
                                                    id: this.id,
                                                    description: this.displaytext
                                                });
                                            });
                                            args.response.success({
                                                data: items
                                            });
                                            args.$select.change(function() {
                                                var diskOfferingId = $(this).val();
                                                $(diskOfferingsObjList).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 diskOfferings = cloudStack.listDiskOfferings({});
                                            var items = [{
                                                id: '',
                                                description: ''
                                            }];
                                            $(diskOfferings).each(function() {
                                                if (this.iscustomized == true) {
                                                    items.push({
                                                        id: this.id,
                                                        description: this.name
                                                    });
                                                }
                                            });
                                            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;
                            }
                        },

                        state: {
                            label: 'label.state',
                            select: function(args) {
                                args.response.success({
                                    data: [{
                                        name: '',
                                        description: ''
                                    }, {
                                        name: 'Allocated',
                                        description: 'state.Allocated'
                                    }, {
                                        name: 'Ready',
                                        description: 'state.Ready'
                                    }, {
                                        name: 'Destroy',
                                        description: 'state.Destroy'
                                    }, {
                                        name: 'Expunging',
                                        description: 'state.Expunging'
                                    }, {
                                        name: 'Expunged',
                                        description: 'state.Expunged'
                                    }]
                                });
                            }
                        },

                        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: migrateVolumeCreateFormAction,

                                action: functionMigrateVolume,
                                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'
                                        },
                                        asyncBackup: {
                                            label: 'label.async.backup',
                                            isBoolean: true
                                        },
                                        tags: {
                                            label: 'label.tags',
                                            tagger: true
                                        }
                                    }
                                },
                                action: function(args) {
                                    var data = {
                                        volumeId: args.context.volumes[0].id,
                                        quiescevm: (args.data.quiescevm == 'on' ? true: false),
                                        asyncBackup: (args.data.asyncBackup == 'on' ? true: false)
                                    };
                                    if (args.data.name != null && args.data.name.length > 0) {
                                        $.extend(data, {
                                            name: args.data.name
                                        });
                                    }
                                    if (!$.isEmptyObject(args.data.tags)) {
                                        $(args.data.tags).each(function(idx, tagData) {
                                            var formattedTagData = {};
                                            formattedTagData["tags[" + _s(idx) + "].key"] = _s(tagData.key);
                                            formattedTagData["tags[" + _s(idx) + "].value"] = _s(tagData.value);
                                            $.extend(data, formattedTagData);
                                        });
                                    }

                                    $.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.
                                                    onComplete: function(json, customData) {
                                                        var volumeId = json.queryasyncjobresultresponse.jobresult.snapshot.volumeid;
                                                        var snapshotId = json.queryasyncjobresultresponse.jobresult.snapshot.id;
                                                        cloudStack.dialog.notice({
                                                            message: "Created snapshot for volume " + volumeId + " with snapshot ID " + snapshotId
                                                        });
                                                    }
                                                }
                                            });
                                        }
                                    });
                                },
                                notification: {
                                    poll: pollAsyncJobResult
                                }
                            },

                            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 = {
                                                    volumeid: args.context.volumes[0].id,
                                                    intervaltype: snap['snapshot-type'],
                                                    maxsnaps: 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;
                                                }

                                                if (!$.isEmptyObject(snap.tags)) {
                                                    $(snap.tags).each(function(idx, tagData) {
                                                        var formattedTagData = {};
                                                        formattedTagData["tags[" + _s(idx) + "].key"] = _s(tagData.key);
                                                        formattedTagData["tags[" + _s(idx) + "].value"] = _s(tagData.value);
                                                        $.extend(data, formattedTagData);
                                                    });
                                                }

                                                $.ajax({
                                                    url: createURL('createSnapshotPolicy'),
                                                    data: data,
                                                    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: cloudStack.createTemplateMethod(false),
                            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: $.extend({}, migrateVolumeCreateFormAction, {title: 'label.migrate.volume.to.primary.storage'}),
                                action: functionMigrateVolume,
                                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();
                                    }
                                }
                            },

                            destroy: {
                                label: 'label.action.destroy.volume',
                                createForm: {
                                    title: 'label.action.destroy.volume',
                                    desc: 'message.action.destroy.volume',
                                    isWarning: true,
                                    preFilter: function(args) {
                                        if (!isAdmin() && ! g_allowUserExpungeRecoverVolume) {
                                            args.$form.find('.form-item[rel=expunge]').hide();
                                        }
                                    },
                                    fields: {
                                        expunge: {
                                            label: 'label.expunge',
                                            isBoolean: true,
                                            isChecked: false
                                        }
                                    }
                                },
                                messages: {
                                    confirm: function(args) {
                                        return 'message.action.destroy.volume';
                                    },
                                    notification: function(args) {
                                        return 'label.action.destroy.volume';
                                    }
                                },
                                action: function(args) {
                                    var data = {
                                        id: args.context.volumes[0].id
                                    };
                                    if (args.data.expunge == 'on') {
                                        $.extend(data, {
                                            expunge: true
                                        });
                                    }
                                    $.ajax({
                                        url: createURL("destroyVolume"),
                                        data: data,
                                        dataType: "json",
                                        async: true,
                                        success: function(json) {
                                            var jid = json.destroyvolumeresponse.jobid;
                                            args.response.success({
                                                _custom: {
                                                    jobId: jid,
                                                    getUpdatedItem: function(json) {
                                                        if ('volume' in json.queryasyncjobresultresponse.jobresult) { //destroy without expunge
                                                            var volume = json.queryasyncjobresultresponse.jobresult.volume;
                                                            if (volume.state == 'Expunged') {
                                                                return { 'toRemove': true };
                                                            } else {
                                                                return volume;
                                                            }
                                                        } else //destroy with expunge
                                                            return { 'toRemove': true };
                                                    },
                                                    getActionFilter: function() {
                                                        return volumeActionfilter;
                                                    }
                                                }
                                            });
                                        }
                                    });
                                },
                                notification: {
                                    poll: pollAsyncJobResult
                                }
                            },

                            recover: {
                                label: 'label.action.recover.volume',
                                messages: {
                                    confirm: function(args) {
                                        return 'message.action.recover.volume';
                                    },
                                    notification: function(args) {
                                        return 'label.action.recover.volume';
                                    }
                                },
                                action: function(args) {
                                    $.ajax({
                                        url: createURL("recoverVolume&id=" + args.context.volumes[0].id),
                                        dataType: "json",
                                        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;
                                                }
                                                var diskOfferings = cloudStack.listDiskOfferings({});
                                                var items = [];
                                                $(diskOfferings).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();
                                                    $(diskOfferings).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 = [];
                                    if(args.$form.find('.form-item[rel=shrinkok]').css("display") != "none") {
                                        array1.push("&shrinkok=" + (args.data.shrinkok == "on"));
                                    }

                                    var newDiskOffering = args.data.newdiskoffering;
                                    if (newDiskOffering != null && newDiskOffering.length > 0) {
                                        array1.push("&diskofferingid=" + encodeURIComponent(newDiskOffering));
                                    }
                                    if (args.context.volumes[0].type == "ROOT" || selectedDiskOfferingObj.iscustomized == true) {
                                        cloudStack.addNewSizeToCommandUrlParameterArrayIfItIsNotNullAndHigherThanZero(array1, args.data.newsize);
                                    }

                                    var minIops;
                                    var maxIops
                                    if (selectedDiskOfferingObj != null && selectedDiskOfferingObj.iscustomizediops == true) {
                                        minIops = args.data.minIops;
                                        maxIops = args.data.maxIops;
                                    }

                                    if (minIops != null && minIops.length > 0) {
                                        array1.push("&miniops=" + encodeURIComponent(minIops));
                                    }

                                    if (maxIops != null && maxIops.length > 0) {
                                        array1.push("&maxiops=" + encodeURIComponent(maxIops));
                                    }
                                    //if original disk size > new disk size
                                    if (args.context.volumes[0].type == "ROOT" &&
                                        args.context.volumes[0].size > (args.data.newsize * (1024 * 1024 * 1024))) {
                                        return args.response.error('message.volume.root.shrink.disk.size');
                                    }

                                    $.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', 'virtualsize', 'physicalsize', 'utilization', 'clusterid', 'clustername'];
                                    }
                                    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);
                                        }
                                    },
                                    clusterid: {
                                        label: 'label.cluster'
                                    },
                                    clustername: {
                                        label: 'label.cluster.name'
                                    },
                                    physicalsize: {
                                        label: 'label.disk.physicalsize',
                                        converter: function(args) {
                                            if (args == null || args == 0)
                                                return "";
                                            else
                                                return cloudStack.converters.convertBytes(args);
                                        }
                                    },
                                    utilization: {
                                        label: 'label.disk.utilisation'
                                    },
                                    virtualsize: {
                                        label: 'label.disk.virtualsize',
                                        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: cloudStack.createTemplateFromSnapshotMethod(),

                            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();
                                        }
                                        if(args.context.snapshots[0].volumetype!='ROOT') {
                                            args.$form.find('.form-item[rel=diskOffering]').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
                                                        });
                                                    }
                                                });
                                            }
                                        },
                                        diskOffering: {
                                            label: 'label.disk.offering',
                                            docID: 'helpVolumeDiskOffering',
                                            select: function(args) {
                                                var snapshotSizeInGB = Math.floor(args.context.snapshots[0].virtualsize/(1024 * 1024 * 1024))
                                                $.ajax({
                                                    url: createURL("listDiskOfferings"),
                                                    dataType: "json",
                                                    async: false,
                                                    success: function(json) {
                                                        diskofferingObjs = json.listdiskofferingsresponse.diskoffering;
                                                        var items = [];
                                                        // Sort offerings list with size and keep custom offerings at end
                                                        for(var i=0;i<diskofferingObjs.length;i++) {
                                                            for(var j=i+1;j<diskofferingObjs.length;j++) {
                                                                if((diskofferingObjs[i].disksize>diskofferingObjs[j].disksize &&
                                                                    diskofferingObjs[j].disksize!=0) ||
                                                                    (diskofferingObjs[i].disksize==0 &&
                                                                        diskofferingObjs[j].disksize!=0)) {
                                                                    var temp = diskofferingObjs[i];
                                                                    diskofferingObjs[i] = diskofferingObjs[j];
                                                                    diskofferingObjs[j] = temp;
                                                                }
                                                            }
                                                        }
                                                        $(diskofferingObjs).each(function() {
                                                            if(this.disksize==0 || this.disksize>=snapshotSizeInGB) {
                                                                items.push({
                                                                    id: this.id,
                                                                    description: this.displaytext
                                                                });
                                                            }
                                                        });
                                                        args.response.success({
                                                            data: items
                                                        });
                                                    }
                                                });

                                                args.$select.change(function() {
                                                    var diskOfferingId = $(this).val();
                                                    selectedDiskOfferingObj = null;
                                                    $(diskofferingObjs).each(function() {
                                                        if (this.id == diskOfferingId) {
                                                            selectedDiskOfferingObj = this;
                                                            return false;
                                                        }
                                                    });

                                                    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');
                                                        $form.find('input[name=diskSize]').val(''+snapshotSizeInGB);
                                                    } 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,
                                        snapshotid: args.context.snapshots[0].id
                                    };

                                    if (args.$form.find('.form-item[rel=zoneid]').css("display") != "none" && args.data.zoneid != '') {
                                        $.extend(data, {
                                            zoneId: args.data.zoneid
                                        });
                                    }

                                    if (args.$form.find('.form-item[rel=diskOffering]').css("display") != "none") {
                                        if (args.data.diskOffering) {
                                            $.extend(data, {
                                                diskofferingid: args.data.diskOffering
                                            });
                                        }
                                        if (selectedDiskOfferingObj) {
                                            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 {}; //nothing in this snapshot needs to be updated
                                                    },
                                                    getActionFilter: function() {
                                                        return snapshotActionfilter;
                                                    }
                                                }
                                            });
                                        },
                                        error: function(json) {
                                            args.response.error(parseXMLHttpResponse(json));
                                        }
                                    });
                                },
                                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 = {
                            listAll: true
                        };
                                listViewDataProvider(args, data);

                        if (args.context != null) {
                            if ("instances" in args.context) {
                                        $.extend(data, {
                                            virtualMachineId: args.context.instances[0].id
                                        });
                            }
                        }
                        $.ajax({
                            url: createURL('listVMSnapshot'),
                                    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
                }
            },

            /**
             * Backups
             */
            backups: {
                type: 'select',
                title: 'label.backup',
                listView: {
                    id: 'backups',
                    isMaximized: true,
                    fields: {
                        virtualmachinename: {
                            label: 'label.vm.name'
                        },
                        status: {
                            label: 'label.state',
                            indicator: {
                                'BackedUp': 'on',
                                'Failed': 'off',
                                'Error': 'off'
                            }
                        },
                        type: {
                            label: 'label.type'
                        },
                        created: {
                            label: 'label.date'
                        },
                        account: {
                            label: 'label.account'
                        },
                        zone: {
                            label: 'label.zone'
                        }
                    },

                    dataProvider: function(args) {
                        var data = {
                            listAll: true
                        };
                        listViewDataProvider(args, data);

                        if (args.context != null) {
                            if ("instances" in args.context) {
                                $.extend(data, {
                                    virtualmachineid: args.context.instances[0].id
                                });
                            }
                        }

                        $.ajax({
                            url: createURL('listBackups'),
                            data: data,
                            dataType: "json",
                            async: true,
                            success: function(json) {
                                var jsonObj;
                                jsonObj = json.listbackupsresponse.backup;
                                args.response.success({
                                    actionFilter: backupActionfilter,
                                    data: jsonObj
                                });
                            }
                        });
                    },
                    //dataProvider end
                    detailView: {
                        tabs: {
                            details: {
                                title: 'label.details',
                                fields: {
                                    id: {
                                        label: 'label.id'
                                    },
                                    virtualmachinename: {
                                        label: 'label.vm.name'
                                    },
                                    virtualmachineid: {
                                        label: 'label.vm.id'
                                    },
                                    status: {
                                        label: 'label.state'
                                    },
                                    externalid: {
                                        label: 'label.external.id'
                                    },
                                    type: {
                                        label: 'label.type'
                                    },
                                    size: {
                                        label: 'label.size'
                                    },
                                    virtualsize: {
                                        label: 'label.virtual.size'
                                    },
                                    volumes: {
                                        label: 'label.volumes'
                                    },
                                    account: {
                                        label: 'label.account'
                                    },
                                    domain: {
                                        label: 'label.domain'
                                    },
                                    zone: {
                                        label: 'label.zone'
                                    },
                                    created: {
                                        label: 'label.date'
                                    }
                                },
                                dataProvider: function(args) {
                                    $.ajax({
                                        url: createURL("listBackups&id=" + args.context.backups[0].id),
                                        dataType: "json",
                                        async: true,
                                        success: function(json) {
                                            var jsonObj;
                                            jsonObj = json.listbackupsresponse.backup[0];
                                            args.response.success({
                                                actionFilter: backupActionfilter,
                                                data: jsonObj
                                            });
                                        }
                                    });
                                }
                            }
                        },
                        actions: {
                            remove: {
                                label: 'Delete Backup',
                                messages: {
                                    confirm: function(args) {
                                        return 'Are you sure you want to delete the backup?';
                                    },
                                    notification: function(args) {
                                        return 'Delete Backup';
                                    }
                                },
                                action: function(args) {
                                    $.ajax({
                                        url: createURL("deleteBackup&id=" + args.context.backups[0].id),
                                        dataType: "json",
                                        async: true,
                                        success: function(json) {
                                            var jid = json.deletebackupresponse.jobid;
                                            args.response.success({
                                                _custom: {
                                                    jobId: jid
                                                }
                                            });
                                        }
                                    });
                                },
                                notification: {
                                    poll: pollAsyncJobResult
                                }
                            },

                            restoreBackup: {
                                label: 'label.backup.restore',
                                messages: {
                                    confirm: function(args) {
                                        return 'Please confirm that you want to restore the vm backup?';
                                    },
                                    notification: function(args) {
                                        return 'label.backup.restore';
                                    }
                                },
                                action: function(args) {
                                    var data = {
                                        id: args.context.backups[0].id
                                    };
                                    $.ajax({
                                        url: createURL("restoreBackup"),
                                        data: data,
                                        dataType: "json",
                                        async: true,
                                        success: function(json) {
                                            var jid = json.restorebackupresponse.jobid;
                                            args.response.success({
                                                _custom: {
                                                    jobId: jid
                                                }
                                            });
                                        }
                                    });

                                },
                                notification: {
                                    poll: pollAsyncJobResult
                                }
                            },

                            restoreBackupVolume: {
                                label: 'Restore and Attach Backup Volume',
                                messages: {
                                    confirm: function(args) {
                                        return 'Please confirm that you want to restore and attach the volume from the backup?';
                                    },
                                    notification: function(args) {
                                        return 'Restore and Attach Backup Volume';
                                    }
                                },
                                createForm: {
                                    title: 'Restore and Attach Backup Volume',
                                    desc: 'Please select the volume you want to restore and attach to the VM.',
                                    fields: {
                                        volume: {
                                            label: 'label.volume',
                                            validation: {
                                                required: true
                                            },
                                            select: function(args) {
                                                var volumes = JSON.parse(args.context.backups[0].volumes);
                                                var items = [];
                                                $(volumes).each(function() {
                                                    items.push({
                                                        id: this.uuid,
                                                        description: '(' + this.type + ') ' + this.uuid
                                                    });
                                                });
                                                args.response.success({
                                                    data: items
                                                });
                                            }
                                        },
                                        virtualmachine: {
                                            label: 'label.virtual.machine',
                                            validation: {
                                                required: true
                                            },
                                            select: function(args) {
                                                $.ajax({
                                                    url: createURL("listVirtualMachines"),
                                                    dataType: "json",
                                                    async: true,
                                                    success: function(json) {
                                                        var vms = json.listvirtualmachinesresponse.virtualmachine;
                                                        var items = [];
                                                        $(vms).each(function() {
                                                            items.push({
                                                                id: this.id,
                                                                description: this.name
                                                            });
                                                        });
                                                        args.response.success({
                                                            data: items
                                                        });

                                                    }
                                                });
                                            }
                                        }
                                    }
                                },
                                action: function(args) {
                                    console.log(args);
                                    var data = {
                                        backupid: args.context.backups[0].id,
                                        volumeid: args.data.volume,
                                        virtualmachineid: args.data.virtualmachine
                                    };
                                    $.ajax({
                                        url: createURL("restoreVolumeFromBackupAndAttachToVM"),
                                        data: data,
                                        dataType: "json",
                                        async: true,
                                        success: function(json) {
                                            var jid = json.restorevolumefrombackupandattachtovmresponse.jobid;
                                            args.response.success({
                                                _custom: {
                                                    jobId: jid
                                                }
                                            });
                                        }
                                    });

                                },
                                notification: {
                                    poll: pollAsyncJobResult
                                }
                            },

                            removeBackupChain: {
                                label: 'Delete Backup Chain',
                                messages: {
                                    confirm: function(args) {
                                        return 'Are you sure you want to remove VM from backup offering and delete the backup chain?';
                                    },
                                    notification: function(args) {
                                        return 'Delete Backup Chain';
                                    }
                                },
                                action: function(args) {
                                    $.ajax({
                                        url: createURL("removeVirtualMachineFromBackupOffering"),
                                        data: {
                                          virtualmachineid: args.context.backups[0].virtualmachineid,
                                          forced: true
                                        },
                                        dataType: "json",
                                        async: true,
                                        success: function(json) {
                                            var jid = json.removevirtualmachinefrombackupofferingresponse.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 ((isAdmin() || g_allowUserExpungeRecoverVolume) && jsonObj.state == 'Destroy') {
            return ["recover", "remove"];
        } else if (jsonObj.state == 'Destroy') {
            return [];
        }

        if (jsonObj.state == 'Expunging' || jsonObj.state == 'Expunged') {
            return ["remove"];
        }

        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
                    if (jsonObj.state == "Allocated" || jsonObj.state == "Uploaded") {
                        allowedActions.push("remove");
                    } else {
                        allowedActions.push("createTemplate");
                        allowedActions.push("destroy");
                    }
                    if (jsonObj.state == "Ready" && isAdmin()) {
                        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");

            if (args && args.context && args.context.instances && args.context.instances[0].hypervisor && args.context.instances[0].hypervisor === "KVM") {
                allowedActions.push("takeSnapshot");
            }
        }

        return allowedActions;
    }

    var backupActionfilter = cloudStack.actionFilter.backupActionfilter = function(args) {
        var jsonObj = args.context.item;

        if (jsonObj.state == 'Destroyed') {
            return [];
        }

        var allowedActions = [];
        allowedActions.push("remove");
        allowedActions.push("restoreBackup");
        allowedActions.push("restoreBackupVolume");
        allowedActions.push("removeBackupChain");

        return allowedActions;
    };



})(cloudStack);
