// 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. var g_mySession = null; var g_sessionKey = null; var g_role = null; // roles - root, domain-admin, ro-admin, user var g_username = null; var g_account = null; var g_domainid = null; var g_loginCmdText = null; var g_enableLogging = false; var g_timezoneoffset = null; var g_timezone = null; var g_supportELB = null; var g_userPublicTemplateEnabled = "true"; var g_cloudstackversion = null; var g_queryAsyncJobResultInterval = 3000; //keyboard keycode var keycode_Enter = 13; //XMLHttpResponse.status var ERROR_ACCESS_DENIED_DUE_TO_UNAUTHORIZED = 401; var ERROR_INTERNET_NAME_NOT_RESOLVED = 12007; var ERROR_INTERNET_CANNOT_CONNECT = 12029; var ERROR_VMOPS_ACCOUNT_ERROR = 531; // Default password is MD5 hashed. Set the following variable to false to disable this. var md5Hashed = false; var md5HashedLogin = false; //page size for API call (e.g."listXXXXXXX&pagesize=N" ) var pageSize = 20; var rootAccountId = 1; var havingSwift = false; var havingS3 = false; //async action var pollAsyncJobResult = function(args) { $.ajax({ url: createURL("queryAsyncJobResult&jobId=" + args._custom.jobId), dataType: "json", async: false, success: function(json) { var result = json.queryasyncjobresultresponse; if (result.jobstatus == 0) { return; //Job has not completed } else { if (result.jobstatus == 1) { // Succeeded if(args._custom.getUpdatedItem != null && args._custom.getActionFilter != null) { args.complete({ data: args._custom.getUpdatedItem(json), actionFilter: args._custom.getActionFilter() }); } else if(args._custom.getUpdatedItem != null && args._custom.getActionFilter == null) { args.complete({ data: args._custom.getUpdatedItem(json) }); } else { args.complete({ data: json.queryasyncjobresultresponse.jobresult }); } if(args._custom.fullRefreshAfterComplete == true) { setTimeout(function() { $(window).trigger('cloudStack.fullRefresh'); }, 500); } if (args._custom.onComplete) { args._custom.onComplete(json, args._custom); } } else if (result.jobstatus == 2) { // Failed var msg = (result.jobresult.errortext == null)? "": result.jobresult.errortext; if (args._custom.getUpdatedItemWhenAsyncJobFails != null && args._custom.getActionFilter != null) { args.error({message: msg, updatedData: args._custom.getUpdatedItemWhenAsyncJobFails(), actionFilter: args._custom.getActionFilter()}); } else if (args._custom.getUpdatedItemWhenAsyncJobFails != null && args._custom.getActionFilter == null) { args.error({message: msg, updatedData: args._custom.getUpdatedItemWhenAsyncJobFails()}); } else { args.error({message: msg}); } } } }, error: function(XMLHttpResponse) { args.error(); } }); } //API calls function createURL(apiName, options) { if (!options) options = {}; var urlString = clientApiUrl + "?" + "command=" + apiName +"&response=json&sessionkey=" + g_sessionKey; if (cloudStack.context && cloudStack.context.projects && !options.ignoreProject) { urlString = urlString + '&projectid=' + cloudStack.context.projects[0].id; } return urlString; } /* function fromdb(val) { return sanitizeXSS(noNull(val)); } */ function todb(val) { return encodeURIComponent(val); } /* function noNull(val) { if(val == null) return ""; else return val; } */ /* function sanitizeXSS(val) { // Prevent cross-site-script(XSS) attack if(val == null || typeof(val) != "string") return val; val = val.replace(//g, ">"); //replace > whose unicode is \u003e return unescape(val); } */ // Role Functions function isAdmin() { return (g_role == 1); } function isDomainAdmin() { return (g_role == 2); } function isUser() { return (g_role == 0); } function isSelfOrChildDomainUser(username, useraccounttype, userdomainid, iscallerchilddomain) { if(username == g_username) { //is self return true; } else if(isDomainAdmin() && iscallerchilddomain && (useraccounttype == 0)) { //domain admin to user return true; } else if(isDomainAdmin() && iscallerchilddomain && (userdomainid != g_domainid) ) { //domain admin to subdomain admin and user return true; } else { return false; } } // FUNCTION: Handles AJAX error callbacks. You can pass in an optional function to // handle errors that are not already handled by this method. function handleError(XMLHttpResponse, handleErrorCallback) { // User Not authenticated if (XMLHttpResponse.status == ERROR_ACCESS_DENIED_DUE_TO_UNAUTHORIZED) { $("#dialog_session_expired").dialog("open"); } else if (XMLHttpResponse.status == ERROR_INTERNET_NAME_NOT_RESOLVED) { $("#dialog_error_internet_not_resolved").dialog("open"); } else if (XMLHttpResponse.status == ERROR_INTERNET_CANNOT_CONNECT) { $("#dialog_error_management_server_not_accessible").dialog("open"); } else if (XMLHttpResponse.status == ERROR_VMOPS_ACCOUNT_ERROR && handleErrorCallback != undefined) { handleErrorCallback(); } else if (handleErrorCallback != undefined) { handleErrorCallback(); } else { var errorMsg = parseXMLHttpResponse(XMLHttpResponse); $("#dialog_error").text(_s(errorMsg)).dialog("open"); } } function parseXMLHttpResponse(XMLHttpResponse) { if(isValidJsonString(XMLHttpResponse.responseText) == false) { return ""; } //var json = jQuery.parseJSON(XMLHttpResponse.responseText); var json = JSON.parse(XMLHttpResponse.responseText); if (json != null) { var property; for(property in json) { var errorObj = json[property]; if(errorObj.errorcode == 401 && errorObj.errortext == "unable to verify user credentials and/or request signature") return _l('label.session.expired'); else return _s(errorObj.errortext); } } else { return ""; } } function isValidJsonString(str) { try { JSON.parse(str); } catch (e) { return false; } return true; } cloudStack.validate = { vmHostName: function(args) { // 1 ~ 63 characters long // ASCII letters 'a' through 'z', 'A' through 'Z', digits '0' through '9', hyphen ('-') // must start with a letter // must end with a letter or a digit (must not end with a hyphen) var regexp = /^[a-zA-Z]{1}[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]{0,1}$/; var b = regexp.test(args); //true or false if(b == false) cloudStack.dialog.notice({ message: 'message.validate.instance.name' }); return b; } } cloudStack.preFilter = { createTemplate: function(args) { if(isAdmin()) { args.$form.find('.form-item[rel=isPublic]').css('display', 'inline-block'); args.$form.find('.form-item[rel=isFeatured]').css('display', 'inline-block'); } else { if (g_userPublicTemplateEnabled == "true") { args.$form.find('.form-item[rel=isPublic]').css('display', 'inline-block'); } else { args.$form.find('.form-item[rel=isPublic]').hide(); } args.$form.find('.form-item[rel=isFeatured]').hide(); } }, addLoadBalancerDevice: function(args) { //add netscaler device OR add F5 device args.$form.find('.form-item[rel=dedicated]').bind('change', function() { var $dedicated = args.$form.find('.form-item[rel=dedicated]'); var $capacity = args.$form.find('.form-item[rel=capacity]'); if($dedicated.find('input[type=checkbox]:checked').length > 0) { $capacity.hide(); $capacity.find('input[type=text]').val('1'); } else if($dedicated.find('input[type=checkbox]:unchecked').length > 0) { $capacity.css('display', 'inline-block'); $capacity.find('input[type=text]').val(''); } }); args.$form.change(); } } cloudStack.actionFilter = { guestNetwork: function(args) { var jsonObj = args.context.item; var allowedActions = []; if(jsonObj.type == 'Isolated') { allowedActions.push('edit'); //only Isolated network is allowed to upgrade to a different network offering (Shared network is not allowed to) allowedActions.push('restart'); allowedActions.push('remove'); } else if(jsonObj.type == 'Shared') { if(isAdmin()) { allowedActions.push('restart'); allowedActions.push('remove'); } } return allowedActions; } } var roleTypeUser = "0"; var roleTypeAdmin = "1"; var roleTypeDomainAdmin = "2"; cloudStack.converters = { convertBytes: function(bytes) { if (bytes < 1024 * 1024) { return (bytes / 1024).toFixed(2) + " KB"; } else if (bytes < 1024 * 1024 * 1024) { return (bytes / 1024 / 1024).toFixed(2) + " MB"; } else if (bytes < 1024 * 1024 * 1024 * 1024) { return (bytes / 1024 / 1024 / 1024).toFixed(2) + " GB"; } else { return (bytes / 1024 / 1024 / 1024 / 1024).toFixed(2) + " TB"; } }, toLocalDate: function(UtcDate) { var localDate = ""; if (UtcDate != null && UtcDate.length > 0) { var disconnected = new Date(); disconnected.setISO8601(UtcDate); if(g_timezoneoffset != null) localDate = disconnected.getTimePlusTimezoneOffset(g_timezoneoffset); else localDate = disconnected.getTimePlusTimezoneOffset(0); } return localDate; }, toBooleanText: function(booleanValue) { if(booleanValue == true) return "Yes"; else if(booleanValue == false) return "No"; }, convertHz: function(hz) { if (hz == null) return ""; if (hz < 1000) { return hz + " MHz"; } else { return (hz / 1000).toFixed(2) + " GHz"; } }, toDayOfWeekDesp: function(dayOfWeek) { if (dayOfWeek == "1") return "Sunday"; else if (dayOfWeek == "2") return "Monday"; else if (dayOfWeek == "3") return "Tuesday"; else if (dayOfWeek == "4") return "Wednesday"; else if (dayOfWeek == "5") return "Thursday" else if (dayOfWeek == "6") return "Friday"; else if (dayOfWeek == "7") return "Saturday"; }, toDayOfWeekDesp: function(dayOfWeek) { if (dayOfWeek == "1") return "Sunday"; else if (dayOfWeek == "2") return "Monday"; else if (dayOfWeek == "3") return "Tuesday"; else if (dayOfWeek == "4") return "Wednesday"; else if (dayOfWeek == "5") return "Thursday" else if (dayOfWeek == "6") return "Friday"; else if (dayOfWeek == "7") return "Saturday"; }, toNetworkType: function(usevirtualnetwork) { if(usevirtualnetwork == true || usevirtualnetwork == "true") return "Public"; else return "Direct"; }, toRole: function(type) { if (type == roleTypeUser) { return "User"; } else if (type == roleTypeAdmin) { return "Admin"; } else if (type == roleTypeDomainAdmin) { return "Domain-Admin"; } }, toAlertType: function(alertCode) { switch (alertCode) { case 0 : return _l('label.memory'); case 1 : return _l('label.cpu'); case 2 : return _l('label.storage'); case 3 : return _l('label.primary.storage'); case 4 : return _l('label.public.ips'); case 5 : return _l('label.management.ips'); case 6 : return _l('label.secondary.storage'); case 7 : return _l('label.host'); case 9 : return _l('label.domain.router'); case 10 : return _l('label.console.proxy'); // These are old values -- can be removed in the future case 8 : return "User VM"; case 11 : return "Routing Host"; case 12 : return "Storage"; case 13 : return "Usage Server"; case 14 : return "Management Server"; case 15 : return "Domain Router"; case 16 : return "Console Proxy"; case 17 : return "User VM"; case 18 : return "VLAN"; case 19 : return "Secondary Storage VM"; case 20 : return "Usage Server"; case 21 : return "Storage"; case 22 : return "Update Resource Count"; case 23 : return "Usage Sanity Result"; case 24 : return "Direct Attached Public IP"; case 25 : return "Local Storage"; case 26 : return "Resource Limit Exceeded"; } }, convertByType: function(alertCode, value) { switch(alertCode) { case 0: return cloudStack.converters.convertBytes(value); case 1: return cloudStack.converters.convertHz(value); case 2: return cloudStack.converters.convertBytes(value); case 3: return cloudStack.converters.convertBytes(value); case 6: return cloudStack.converters.convertBytes(value); case 9: return cloudStack.converters.convertBytes(value); case 11: return cloudStack.converters.convertBytes(value); } return value; } } //data parameter passed to API call in listView function listViewDataProvider(args, data) { //search if(args.filterBy != null) { if(args.filterBy.advSearch != null && typeof(args.filterBy.advSearch) == "object") { //advanced search for(var key in args.filterBy.advSearch) { if(key == 'tagKey' && args.filterBy.advSearch[key].length > 0) { $.extend(data, { 'tags[0].key': args.filterBy.advSearch[key] }); } else if(key == 'tagValue' && args.filterBy.advSearch[key].length > 0) { $.extend(data, { 'tags[0].value': args.filterBy.advSearch[key] }); } else if(args.filterBy.advSearch[key] != null && args.filterBy.advSearch[key].length > 0) { data[key] = args.filterBy.advSearch[key]; //do NOT use $.extend(data, { key: args.filterBy.advSearch[key] }); which will treat key variable as "key" string } } } else if(args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) { //basic search switch(args.filterBy.search.by) { case "name": if(args.filterBy.search.value.length > 0) { $.extend(data, { keyword: args.filterBy.search.value }); } break; } } } //pagination $.extend(data, { listAll: true, page: args.page, pagesize: pageSize }); } //used by infrastruct page and network page var addExtraPropertiesToGuestNetworkObject = function(jsonObj) { jsonObj.networkdomaintext = jsonObj.networkdomain; jsonObj.networkofferingidText = jsonObj.networkofferingid; if(jsonObj.acltype == "Domain") { if(jsonObj.domainid == rootAccountId) jsonObj.scope = "All"; else jsonObj.scope = "Domain (" + jsonObj.domain + ")"; } else if (jsonObj.acltype == "Account"){ if(jsonObj.project != null) jsonObj.scope = "Account (" + jsonObj.domain + ", " + jsonObj.project + ")"; else jsonObj.scope = "Account (" + jsonObj.domain + ", " + jsonObj.account + ")"; } if(jsonObj.vlan == null && jsonObj.broadcasturi != null) { jsonObj.vlan = jsonObj.broadcasturi.replace("vlan://", ""); } } //find service object in network object function ipFindNetworkServiceByName(pName, networkObj) { if(networkObj == null) return null; if(networkObj.service != null) { for(var i=0; i