diff --git a/scripts/network/domr/ipassoc.sh b/scripts/network/domr/ipassoc.sh index 1988d4c73f1..2d460bf7e5a 100755 --- a/scripts/network/domr/ipassoc.sh +++ b/scripts/network/domr/ipassoc.sh @@ -57,11 +57,11 @@ add_one_to_one_nat_entry() { local dIp=$3 ssh -p 3922 -o StrictHostKeyChecking=no -i $cert root@$dIp "\ iptables -t nat -A PREROUTING -i eth2 -d $publicIp -j DNAT --to-destination $guestIp - iptables -t nat -A POSTROUTING -o $eth2 -s $guestIp -j SNAT --to-source $publicIp + iptables -t nat -A POSTROUTING -o eth2 -s $guestIp -j SNAT --to-source $publicIp iptables -P FORWARD DROP iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT - iptables -A FORWARD -i $eth2 -o $eth1 -d $guestIp -m state --state NEW -j ACCEPT - iptables -A FORWARD -i $eth1 -o $eth2 -s $guestIp -m state --state NEW -j ACCEPT + iptables -A FORWARD -i eth2 -o eth0 -d $guestIp -m state --state NEW -j ACCEPT + iptables -A FORWARD -i eth0 -o eth2 -s $guestIp -m state --state NEW -j ACCEPT " return $? } @@ -184,10 +184,13 @@ do done #1:1 NAT -if [ "$Gflag" == "1" ] && [ "$fflag" == "1" ] && [ "$Aflag" == "1" ] +if [ "$Gflag" == "1" ] then add_nat_entry $domRIp $publicIp - add_one_to_one_nat_entry $guestIp $publicIp $domRIp + if [ $? -eq 0 ] + then + add_one_to_one_nat_entry $guestIp $publicIp $domRIp + fi exit $? fi diff --git a/server/src/com/cloud/api/commands/AssociateIPAddrCmd.java b/server/src/com/cloud/api/commands/AssociateIPAddrCmd.java index 8755e42a1eb..046425f438d 100644 --- a/server/src/com/cloud/api/commands/AssociateIPAddrCmd.java +++ b/server/src/com/cloud/api/commands/AssociateIPAddrCmd.java @@ -72,10 +72,7 @@ public class AssociateIPAddrCmd extends BaseCmd { String accountName = (String)params.get(BaseCmd.Properties.ACCOUNT.getName()); Long domainId = (Long)params.get(BaseCmd.Properties.DOMAIN_ID.getName()); Long vmId = (Long)params.get(BaseCmd.Properties.VIRTUAL_MACHINE_ID.getName()); - - //todo REMOVE - //vmId = new Long(3); - + String newIpAddr = null; String errorDesc = null; Long accountId = null; diff --git a/server/src/com/cloud/api/commands/ListVMsCmd.java b/server/src/com/cloud/api/commands/ListVMsCmd.java index 0041fcc31af..59d226340dc 100644 --- a/server/src/com/cloud/api/commands/ListVMsCmd.java +++ b/server/src/com/cloud/api/commands/ListVMsCmd.java @@ -118,6 +118,10 @@ public class ListVMsCmd extends BaseCmd { domainId = account.getDomainId(); } + if(account!=null && domainId==null){ + throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Please specify the domain id for this account:"+account.getId()); + } + Long[] accountIds = null; if (accountId != null) { accountIds = new Long[1]; @@ -290,10 +294,13 @@ public class ListVMsCmd extends BaseCmd { //root device related VolumeVO rootVolume = getManagementServer().findRootVolume(vmInstance.getId()); - vmData.add(new Pair(BaseCmd.Properties.ROOT_DEVICE_ID.getName(), rootVolume.getDeviceId())); + if(rootVolume!=null) + { + vmData.add(new Pair(BaseCmd.Properties.ROOT_DEVICE_ID.getName(), rootVolume.getDeviceId())); - StoragePoolVO storagePool = getManagementServer().findPoolById(rootVolume.getPoolId()); - vmData.add(new Pair(BaseCmd.Properties.ROOT_DEVICE_TYPE.getName(), storagePool.getPoolType().toString())); + StoragePoolVO storagePool = getManagementServer().findPoolById(rootVolume.getPoolId()); + vmData.add(new Pair(BaseCmd.Properties.ROOT_DEVICE_TYPE.getName(), storagePool.getPoolType().toString())); + } vmTag[i++] = vmData; } diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index 738921ac271..60f6ee24e15 100644 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -47,7 +47,7 @@ public enum Config { StorageOverprovisioningFactor("Storage", StoragePoolAllocator.class, String.class, "storage.overprovisioning.factor", "2", "Used for storage overprovisioning calculation; available storage will be (actualStorageSize * storage.overprovisioning.factor)", null), StorageStatsInterval("Storage", ManagementServer.class, String.class, "storage.stats.interval", "60000", "The interval in milliseconds when storage stats (per host) are retrieved from agents.", null), - MaxVolumeSize("Storage", ManagementServer.class, Integer.class, "max.volume.size.gb", "2093049000000", "The maximum size for a volume in bytes (2TB).", null), + MaxVolumeSize("Storage", ManagementServer.class, Integer.class, "max.volume.size.gb", "2000", "The maximum size for a volume in gigabytes.", null), TotalRetries("Storage", AgentManager.class, Integer.class, "total.retries", "4", "The number of times each command sent to a host should be retried in case of failure.", null), // Network diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 2df1bdf1cab..43648b83946 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -478,9 +478,9 @@ public class ManagementServerImpl implements ManagementServer { // and set them in the right places String maxVolumeSizeInTbString = _configs.get("max.volume.size.gb"); - long maxVolumeSizeBytes = NumbersUtil.parseLong(maxVolumeSizeInTbString, new Long("2093049000000")); + long maxVolumeSizeGBytes = NumbersUtil.parseLong(maxVolumeSizeInTbString, new Long("2000")); - _maxVolumeSizeInGb = maxVolumeSizeBytes/1000000000; + _maxVolumeSizeInGb = maxVolumeSizeGBytes; _routerRamSize = NumbersUtil.parseInt(_configs.get("router.ram.size"),NetworkManager.DEFAULT_ROUTER_VM_RAMSIZE); _proxyRamSize = NumbersUtil.parseInt(_configs.get("consoleproxy.ram.size"), ConsoleProxyManager.DEFAULT_PROXY_VM_RAMSIZE); @@ -1569,6 +1569,14 @@ public class ManagementServerImpl implements ManagementServer { _accountMgr.incrementResourceCount(accountId, ResourceType.public_ip); } + if(vmId!=0){ + VMInstanceVO vm = _vmInstanceDao.findById(vmId); + + if(vm == null){ + throw new InvalidParameterValueException("Invalid vm instance id:"+vmId+" specified"); + } + } + boolean success = true; String errorMsg = ""; diff --git a/ui/new/css/main.css b/ui/new/css/main.css index 2e7d0eede73..03f66313d22 100644 --- a/ui/new/css/main.css +++ b/ui/new/css/main.css @@ -1701,7 +1701,7 @@ a:hover.search_button { } .actionsdropdown_boxlist { - width:96px; + width:197px; height:auto; float:left; margin:0 0 5px 6px; @@ -1710,7 +1710,7 @@ a:hover.search_button { } .actionsdropdown_boxlist li{ - width:94px; + width:194px; height:auto; float:left; text-align:left; @@ -2622,7 +2622,7 @@ a:hover.search_button { } .grid_actionsdropdown_box { - width:109px; + width:209px; height:auto; float:left; position:absolute; diff --git a/ui/new/jsp/volume.jsp b/ui/new/jsp/volume.jsp index 179a6f4052d..a4cd0fb3263 100644 --- a/ui/new/jsp/volume.jsp +++ b/ui/new/jsp/volume.jsp @@ -218,3 +218,353 @@ + + + + + + + + + + + + diff --git a/ui/new/scripts/cloud.core2.js b/ui/new/scripts/cloud.core2.js index 9b307abad5a..0508c5f8a88 100644 --- a/ui/new/scripts/cloud.core2.js +++ b/ui/new/scripts/cloud.core2.js @@ -33,7 +33,8 @@ function buildActionLinkForDetailsTab(label, actionMap, $actionMenu, listAPIMap) $link.data("isAsyncJob", apiInfo.isAsyncJob); $link.data("asyncJobResponse", apiInfo.asyncJobResponse); $link.data("afterActionSeccessFn", apiInfo.afterActionSeccessFn); - $link.data("dialogBeforeActionFn", apiInfo.dialogBeforeActionFn); + $link.data("dialogBeforeActionFn", apiInfo.dialogBeforeActionFn); + $link.data("customActionFn", apiInfo.customActionFn); var $detailsTab = $("#right_panel_content #tab_content_details"); var id = $detailsTab.data("jsonObj").id; @@ -41,6 +42,13 @@ function buildActionLinkForDetailsTab(label, actionMap, $actionMenu, listAPIMap) $link.bind("click", function(event) { $actionMenu.hide(); var $actionLink = $(this); + + var customActionFn = $actionLink.data("customActionFn"); + if(customActionFn != null) { + customActionFn(); + return false; + } + var dialogBeforeActionFn = $actionLink.data("dialogBeforeActionFn"); if(dialogBeforeActionFn == null) { var apiCommand = "command="+$actionLink.data("api")+"&id="+id; @@ -48,7 +56,7 @@ function buildActionLinkForDetailsTab(label, actionMap, $actionMenu, listAPIMap) } else { dialogBeforeActionFn($actionLink, listAPIMap, $detailsTab); - } + } return false; }); } @@ -136,24 +144,28 @@ function doActionToDetailsTab(id, $actionLink, apiCommand, listAPIMap) { dataType: "json", async: false, success: function(json) { - $spinningWheel.hide(); - - //RecoverVirtualMachine API doesn't return an embedded object on success (Bug 6037) - //Before Bug 6037 get fixed, use the temporary solution below. - $.ajax({ - cache: false, - data: createURL("command="+listAPI+"&id="+id), - dataType: "json", - async: false, - success: function(json) { - $detailsTab.find("#action_message_box #description").text(label + " action succeeded."); - $detailsTab.find("#action_message_box").removeClass("error").show(); - - afterActionSeccessFn(json[listAPIResponse][listAPIResponseObj][0]); - } - }); - //After Bug 6037 is fixed, remove temporary solution above and uncomment the line below - //afterActionSeccessFn(json[listAPIResponse][listAPIResponseObj][0]); + $spinningWheel.hide(); + $detailsTab.find("#action_message_box #description").text(label + " action succeeded."); + $detailsTab.find("#action_message_box").removeClass("error").show(); + + if(apiCommand.indexOf("command=delete")!=0) { + //RecoverVirtualMachine API doesn't return an embedded object on success (Bug 6037) + //Before Bug 6037 get fixed, use the temporary solution below. + $.ajax({ + cache: false, + data: createURL("command="+listAPI+"&id="+id), + dataType: "json", + async: false, + success: function(json) { + afterActionSeccessFn(json[listAPIResponse][listAPIResponseObj][0]); + } + }); + //After Bug 6037 is fixed, remove temporary solution above and uncomment the line below + //afterActionSeccessFn(json[listAPIResponse][listAPIResponseObj][0]); + } + else { //apiCommand is deleteXXXXXXX + afterActionSeccessFn(id); + } }, error: function(XMLHttpResponse) { handleErrorInDetailsTab(XMLHttpResponse, $detailsTab, label); @@ -337,8 +349,20 @@ function handleErrorInMidMenu(XMLHttpResponse, $midmenuItem1) { if(errorMsg.length > 0) $midmenuItem1.find("#second_row").text(fromdb(errorMsg)); else - $midmenuItem1.find("#second_row").text(""); -} + $midmenuItem1.find("#second_row").html(" "); +} + +function handleAsyncJobFailInMidMenu(errorMsg, $midmenuItem1) { + $midmenuItem1.find("#content").removeClass("inaction"); + $midmenuItem1.find("#spinning_wheel").hide(); + $midmenuItem1.find("#info_icon").addClass("error").show(); + $midmenuItem1.find("#first_row").text("Adding failed"); + + if(errorMsg.length > 0) + $midmenuItem1.find("#second_row").text(fromdb(errorMsg)); + else + $midmenuItem1.find("#second_row").html(" "); +} //***** actions for middle menu (end) ************************************************************************** @@ -539,7 +563,8 @@ function clearMiddleMenu() { } function clearRightPanel() { - $("#right_panel_content #action_message_box").hide(); + $("#right_panel_content #action_message_box").hide(); + $("#right_panel_content #tab_content_details #action_link #action_menu #action_list").empty(); } var selected_leftmenu_id = null; @@ -1225,7 +1250,7 @@ function noNull(val) { // Prevent cross-site-script(XSS) attack. // used right before adding user input to the DOM tree. e.g. DOM_element.html(sanitizeXSS(user_input)); function sanitizeXSS(val) { - if(val == null) + if(val == null || typeof(val) != "string") return val; val = val.replace(//g, ">"); //replace > whose unicode is \u003e diff --git a/ui/new/scripts/cloud.core2.template.js b/ui/new/scripts/cloud.core2.template.js index 0bce422868f..a9f14436729 100644 --- a/ui/new/scripts/cloud.core2.template.js +++ b/ui/new/scripts/cloud.core2.template.js @@ -16,8 +16,8 @@ function afterLoadTemplateJSP() { else $("#dialog_add_template #add_template_featured_container, #dialog_edit_template #edit_template_featured_container").hide(); - $("#midmenu_add_link").show(); - + //add button *** + $("#midmenu_add_link").show(); $("#midmenu_add_link").unbind("click").bind("click", function(event) { $("#dialog_add_template") .dialog('option', 'buttons', { diff --git a/ui/new/scripts/cloud.core2.volume.js b/ui/new/scripts/cloud.core2.volume.js index 9e3b329e6de..38e3631b28e 100644 --- a/ui/new/scripts/cloud.core2.volume.js +++ b/ui/new/scripts/cloud.core2.volume.js @@ -5,10 +5,25 @@ function afterLoadVolumeJSP() { modal: true, zIndex: 2000 })); - - + activateDialog($("#dialog_create_snapshot").dialog({ + autoOpen: false, + modal: true, + zIndex: 2000 + })); + activateDialog($("#dialog_recurring_snapshot").dialog({ + width: 735, + autoOpen: false, + modal: true, + zIndex: 2000 + })); + activateDialog($("#dialog_add_volume").dialog({ + autoOpen: false, + modal: true, + zIndex: 2000 + })); + $.ajax({ - data: createURL("command=listOsTypes&response=json"), + data: createURL("command=listOsTypes"), dataType: "json", success: function(json) { types = json.listostypesresponse.ostype; @@ -19,7 +34,317 @@ function afterLoadVolumeJSP() { } } } - }); + }); + + $.ajax({ + data: createURL("command=listZones&available=true"+maxPageSize), + dataType: "json", + success: function(json) { + var zones = json.listzonesresponse.zone; + var volumeZoneSelect = $("#dialog_add_volume").find("#volume_zone").empty(); + if (zones != null && zones.length > 0) { + for (var i = 0; i < zones.length; i++) { + volumeZoneSelect.append(""); + } + } + } + }); + + $.ajax({ + data: createURL("command=listDiskOfferings"), + dataType: "json", + success: function(json) { + var offerings = json.listdiskofferingsresponse.diskoffering; + var volumeDiskOfferingSelect = $("#dialog_add_volume").find("#volume_diskoffering").empty(); + if (offerings != null && offerings.length > 0) { + if (offerings != null && offerings.length > 0) { + for (var i = 0; i < offerings.length; i++) + volumeDiskOfferingSelect.append(""); + } + } + } + }); + + //add button *** + $("#midmenu_add_link").show(); + $("#midmenu_add_link").unbind("click").bind("click", function(event) { + $("#dialog_add_volume") + .dialog('option', 'buttons', { + "Add": function() { + var thisDialog = $(this); + + // validate values + var isValid = true; + isValid &= validateString("Name", thisDialog.find("#add_volume_name"), thisDialog.find("#add_volume_name_errormsg")); + if (!isValid) return; + + thisDialog.dialog("close"); + + var name = trim(thisDialog.find("#add_volume_name").val()); + var zoneId = thisDialog.find("#volume_zone").val(); + var diskofferingId = thisDialog.find("#volume_diskoffering").val(); + + var $midmenuItem1 = beforeAddingMidMenuItem() ; + + $.ajax({ + data: createURL("command=createVolume&zoneId="+zoneId+"&name="+encodeURIComponent(name)+"&diskOfferingId="+diskofferingId+"&accountId="+"1"), + dataType: "json", + success: function(json) { + var jobId = json.createvolumeresponse.jobid; + var timerKey = "createVolumeJob_"+jobId; + + $("body").everyTime(2000, timerKey, function() { + $.ajax({ + data: createURL("command=queryAsyncJobResult&jobId="+json.createvolumeresponse.jobid), + dataType: "json", + success: function(json) { + var result = json.queryasyncjobresultresponse; + if (result.jobstatus == 0) { + return; //Job has not completed + } else { + $("body").stopTime(timerKey); + if (result.jobstatus == 1) { + // Succeeded + volumeToMidmenu(result.volume[0], $midmenuItem1); + bindClickToMidMenu($midmenuItem1, volumeToRigntPanel); + afterAddingMidMenuItem($midmenuItem1, true); + } else if (result.jobstatus == 2) { + handleAsyncJobFailInMidMenu(result.jobresult, $midmenuItem1); + } + } + }, + error: function(XMLHttpResponse) { + $("body").stopTime(timerKey); + handleErrorInMidMenu(XMLHttpResponse, $midmenuItem1); + } + }); + }, 0); + }, + error: function(XMLHttpResponse) { + handleErrorInMidMenu(XMLHttpResponse, $midmenuItem1); + } + }); + }, + "Cancel": function() { + $(this).dialog("close"); + } + }).dialog("open"); + + return false; + }); + + // *** recurring snapshot dialog - event binding (begin) ****************************** + $("#dialog_recurring_snapshot").bind("click", function(event) { + event.preventDefault(); + event.stopPropagation(); + + var target = event.target; + var targetId = target.id; + var thisDialog = $(this); + var volumeId = thisDialog.data("volumeId"); + var topPanel = thisDialog.find("#dialog_snapshotleft"); + var bottomPanel = thisDialog.find("#dialog_snapshotright"); + + if(targetId.indexOf("_edit_link")!=-1) { + clearBottomPanel(); + bottomPanel.animate({ + height: 200 + }, 1000, function() {} + ); + } + else if(targetId.indexOf("_delete_link")!=-1) { + clearBottomPanel(); + var snapshotPolicyId = $("#"+targetId).data("snapshotPolicyId"); + if(snapshotPolicyId == null || snapshotPolicyId.length==0) + return; + $.ajax({ + data: createURL("command=deleteSnapshotPolicies&id="+snapshotPolicyId), + dataType: "json", + success: function(json) { + clearTopPanel($("#"+targetId).data("intervalType")); + }, + error: function(XMLHttpResponse) { + handleError(XMLHttpResponse); + } + }); + } + + var thisLink; + switch(targetId) { + case "hourly_edit_link": + $("#edit_interval_type").text("Hourly"); + $("#edit_time_colon, #edit_hour_container, #edit_meridiem_container, #edit_day_of_week_container, #edit_day_of_month_container").hide(); + $("#edit_past_the_hour, #edit_minute_container").show(); + thisLink = thisDialog.find("#hourly_edit_link"); + thisDialog.find("#edit_minute").val(thisLink.data("minute")); + thisDialog.find("#edit_max").val(thisLink.data("max")); + thisDialog.find("#edit_timezone").val(thisLink.data("timezone")); + break; + case "daily_edit_link": + $("#edit_interval_type").text("Daily"); + $("#edit_past_the_hour, #edit_day_of_week_container, #edit_day_of_month_container").hide(); + $("#edit_minute_container, #edit_hour_container, #edit_meridiem_container").show(); + thisLink = thisDialog.find("#daily_edit_link"); + thisDialog.find("#edit_minute").val(thisLink.data("minute")); + thisDialog.find("#edit_hour").val(thisLink.data("hour12")); + thisDialog.find("#edit_meridiem").val(thisLink.data("meridiem")); + thisDialog.find("#edit_max").val(thisLink.data("max")); + thisDialog.find("#edit_timezone").val(thisLink.data("timezone")); + break; + case "weekly_edit_link": + $("#edit_interval_type").text("Weekly"); + $("#edit_past_the_hour, #edit_day_of_month_container").hide(); + $("#edit_minute_container, #edit_hour_container, #edit_meridiem_container, #edit_day_of_week_container").show(); + thisLink = thisDialog.find("#weekly_edit_link"); + thisDialog.find("#edit_minute").val(thisLink.data("minute")); + thisDialog.find("#edit_hour").val(thisLink.data("hour12")); + thisDialog.find("#edit_meridiem").val(thisLink.data("meridiem")); + thisDialog.find("#edit_day_of_week").val(thisLink.data("dayOfWeek")); + thisDialog.find("#edit_max").val(thisLink.data("max")); + thisDialog.find("#edit_timezone").val(thisLink.data("timezone")); + break; + case "monthly_edit_link": + $("#edit_interval_type").text("Monthly"); + $("#edit_past_the_hour, #edit_day_of_week_container").hide(); + $("#edit_minute_container, #edit_hour_container, #edit_meridiem_container, #edit_day_of_month_container").show(); + thisLink = thisDialog.find("#monthly_edit_link"); + thisDialog.find("#edit_minute").val(thisLink.data("minute")); + thisDialog.find("#edit_hour").val(thisLink.data("hour12")); + thisDialog.find("#edit_meridiem").val(thisLink.data("meridiem")); + thisDialog.find("#edit_day_of_month").val(thisLink.data("dayOfMonth")); + thisDialog.find("#edit_max").val(thisLink.data("max")); + thisDialog.find("#edit_timezone").val(thisLink.data("timezone")); + break; + case "apply_button": + var intervalType = bottomPanel.find("#edit_interval_type").text().toLowerCase(); + var minute, hour12, hour24, meridiem, dayOfWeek, dayOfWeekString, dayOfMonth, schedule, max, timezone; + switch(intervalType) { + case "hourly": + var isValid = true; + isValid &= validateNumber("Keep # of snapshots", bottomPanel.find("#edit_max"), bottomPanel.find("#edit_max_errormsg")); + if (!isValid) return; + + minute = bottomPanel.find("#edit_minute").val(); + schedule = minute; + max = bottomPanel.find("#edit_max").val(); + timezone = bottomPanel.find("#edit_timezone").val(); + break; + + case "daily": + var isValid = true; + isValid &= validateNumber("Keep # of snapshots", bottomPanel.find("#edit_max"), bottomPanel.find("#edit_max_errormsg")); + if (!isValid) return; + + minute = bottomPanel.find("#edit_minute").val(); + hour12 = bottomPanel.find("#edit_hour").val(); + meridiem = bottomPanel.find("#edit_meridiem").val(); + if(meridiem=="AM") + hour24 = hour12; + else //meridiem=="PM" + hour24 = (parseInt(hour12)+12).toString(); + schedule = minute + ":" + hour24; + max = bottomPanel.find("#edit_max").val(); + timezone = bottomPanel.find("#edit_timezone").val(); + break; + + case "weekly": + var isValid = true; + isValid &= validateNumber("Keep # of snapshots", bottomPanel.find("#edit_max"), bottomPanel.find("#edit_max_errormsg")); + if (!isValid) return; + + minute = bottomPanel.find("#edit_minute").val(); + hour12 = bottomPanel.find("#edit_hour").val(); + meridiem = bottomPanel.find("#edit_meridiem").val(); + if(meridiem=="AM") + hour24 = hour12; + else //meridiem=="PM" + hour24 = (parseInt(hour12)+12).toString(); + dayOfWeek = bottomPanel.find("#edit_day_of_week").val(); + dayOfWeekString = bottomPanel.find("#edit_day_of_week option:selected").text(); + schedule = minute + ":" + hour24 + ":" + dayOfWeek; + max = bottomPanel.find("#edit_max").val(); + timezone = bottomPanel.find("#edit_timezone").val(); + break; + + case "monthly": + var isValid = true; + isValid &= validateNumber("Keep # of snapshots", bottomPanel.find("#edit_max"), bottomPanel.find("#edit_max_errormsg")); + if (!isValid) return; + + minute = bottomPanel.find("#edit_minute").val(); + hour12 = bottomPanel.find("#edit_hour").val(); + meridiem = bottomPanel.find("#edit_meridiem").val(); + if(meridiem=="AM") + hour24 = hour12; + else //meridiem=="PM" + hour24 = (parseInt(hour12)+12).toString(); + dayOfMonth = bottomPanel.find("#edit_day_of_month").val(); + schedule = minute + ":" + hour24 + ":" + dayOfMonth; + max = bottomPanel.find("#edit_max").val(); + timezone = bottomPanel.find("#edit_timezone").val(); + break; + } + + var thisLink; + $.ajax({ + data: createURL("command=createSnapshotPolicy&intervaltype="+intervalType+"&schedule="+schedule+"&volumeid="+volumeId+"&maxsnaps="+max+"&timezone="+encodeURIComponent(timezone)), + dataType: "json", + success: function(json) { + switch(intervalType) { + case "hourly": + topPanel.find("#dialog_snapshot_hourly_info_unset").hide(); + topPanel.find("#dialog_snapshot_hourly_info_set").show(); + topPanel.find("#read_hourly_minute").text(minute); + topPanel.find("#read_hourly_timezone").text("("+timezones[timezone]+")"); + topPanel.find("#read_hourly_max").text(max); + topPanel.find("#hourly_edit_link, #hourly_delete_link").data("intervalType", "hourly").data("snapshotPolicyId", json.createsnapshotpolicyresponse.id).data("max",max).data("timezone",timezone).data("minute", minute); + break; + case "daily": + topPanel.find("#dialog_snapshot_daily_info_unset").hide(); + topPanel.find("#dialog_snapshot_daily_info_set").show(); + topPanel.find("#read_daily_minute").text(minute); + topPanel.find("#read_daily_hour").text(hour12); + topPanel.find("#read_daily_meridiem").text(meridiem); + topPanel.find("#read_daily_timezone").text("("+timezones[timezone]+")"); + topPanel.find("#read_daily_max").text(max); + topPanel.find("#daily_edit_link, #daily_delete_link").data("intervalType", "daily").data("snapshotPolicyId", json.createsnapshotpolicyresponse.id).data("max",max).data("timezone",timezone).data("minute", minute).data("hour12", hour12).data("meridiem", meridiem); + break; + case "weekly": + topPanel.find("#dialog_snapshot_weekly_info_unset").hide(); + topPanel.find("#dialog_snapshot_weekly_info_set").show(); + topPanel.find("#read_weekly_minute").text(minute); + topPanel.find("#read_weekly_hour").text(hour12); + topPanel.find("#read_weekly_meridiem").text(meridiem); + topPanel.find("#read_weekly_timezone").text("("+timezones[timezone]+")"); + topPanel.find("#read_weekly_day_of_week").text(dayOfWeekString); + topPanel.find("#read_weekly_max").text(max); + topPanel.find("#weekly_edit_link, #weekly_delete_link").data("intervalType", "weekly").data("snapshotPolicyId", json.createsnapshotpolicyresponse.id).data("max",max).data("timezone",timezone).data("minute", minute).data("hour12", hour12).data("meridiem", meridiem).data("dayOfWeek",dayOfWeek); + break; + case "monthly": + topPanel.find("#dialog_snapshot_monthly_info_unset").hide(); + topPanel.find("#dialog_snapshot_monthly_info_set").show(); + topPanel.find("#read_monthly_minute").text(minute); + topPanel.find("#read_monthly_hour").text(hour12); + topPanel.find("#read_monthly_meridiem").text(meridiem); + topPanel.find("#read_monthly_timezone").text("("+timezones[timezone]+")"); + topPanel.find("#read_monthly_day_of_month").text(toDayOfMonthDesp(dayOfMonth)); + topPanel.find("#read_monthly_max").text(max); + topPanel.find("#monthly_edit_link, #monthly_delete_link").data("intervalType", "monthly").data("snapshotPolicyId", json.createsnapshotpolicyresponse.id).data("max",max).data("timezone",timezone).data("minute", minute).data("hour12", hour12).data("meridiem", meridiem).data("dayOfMonth",dayOfMonth); + break; + } + + }, + error: function(XMLHttpResponse) { + handleError(XMLHttpResponse); + } + }); + + break; + + } + }); + // *** recurring snapshot dialog - event binding (end) ****************************** + } function volumeAfterDetailsTabAction(jsonObj) { @@ -68,36 +393,46 @@ function volumeJsonToDetailsTab(jsonObj){ var $actionMenu = $("#right_panel_content #tab_content_details #action_link #action_menu"); $actionMenu.find("#action_list").empty(); - //buildActionLinkForDetailsTab("Take Snapshot", volumeActionMap, $actionMenu, volumeListAPIMap); //show take snapshot - //buildActionLinkForDetailsTab("Recurring Snapshot", volumeActionMap, $actionMenu, volumeListAPIMap); //show Recurring Snapshot - - if(jsonObj.type=="ROOT") { - if (jsonObj.vmstate == "Stopped") - buildActionLinkForDetailsTab("Create Template", volumeActionMap, $actionMenu, volumeListAPIMap); //show create template - } - else { - if (jsonObj.virtualmachineid != null) { - if (jsonObj.storagetype == "shared" && (jsonObj.vmstate == "Running" || jsonObj.vmstate == "Stopped")) { - buildActionLinkForDetailsTab("Detach Disk", volumeActionMap, $actionMenu, volumeListAPIMap); //show detach disk - } - } else { - // Disk not attached - if (jsonObj.storagetype == "shared") { - buildActionLinkForDetailsTab("Detach Disk", volumeActionMap, $actionMenu, volumeListAPIMap); //show attach disk - - if(jsonObj.vmname == null || jsonObj.vmname == "none") - buildActionLinkForDetailsTab("Delete Volume", volumeActionMap, $actionMenu, volumeListAPIMap); //show delete volume - } - } + buildActionLinkForDetailsTab("Take Snapshot", volumeActionMap, $actionMenu, volumeListAPIMap); //show take snapshot + buildActionLinkForDetailsTab("Recurring Snapshot", volumeActionMap, $actionMenu, volumeListAPIMap); //show Recurring Snapshot + + if(jsonObj.state != "Creating" && jsonObj.state != "Corrupted" && jsonObj.name != "attaching") { + if(jsonObj.type=="ROOT") { + if (jsonObj.vmstate == "Stopped") + buildActionLinkForDetailsTab("Create Template", volumeActionMap, $actionMenu, volumeListAPIMap); //show create template + } + else { + if (jsonObj.virtualmachineid != null) { + if (jsonObj.storagetype == "shared" && (jsonObj.vmstate == "Running" || jsonObj.vmstate == "Stopped")) { + buildActionLinkForDetailsTab("Detach Disk", volumeActionMap, $actionMenu, volumeListAPIMap); //show detach disk + } + } else { + // Disk not attached + if (jsonObj.storagetype == "shared") { + buildActionLinkForDetailsTab("Detach Disk", volumeActionMap, $actionMenu, volumeListAPIMap); //show attach disk + + if(jsonObj.vmname == null || jsonObj.vmname == "none") + buildActionLinkForDetailsTab("Delete Volume", volumeActionMap, $actionMenu, volumeListAPIMap); //show delete volume + } + } + } } - - /* - if(jsonObj.state == "Creating" || jsonObj.state == "Corrupted" || jsonObj.name == "attaching") - template.find("#grid_links_container").hide(); //hide actions panel - else - template.find("#grid_links_container").show(); //show actions panel - */ } + +function volumeClearRightPanel() { + var $detailsTab = $("#right_panel_content #tab_content_details"); + $detailsTab.find("#id").text(""); + $detailsTab.find("#name").text(""); + $detailsTab.find("#zonename").text(""); + $detailsTab.find("#device_id").text(""); + $detailsTab.find("#state").text(""); + $detailsTab.find("#storage").text(""); + $detailsTab.find("#account").text(""); + $detailsTab.find("#type").text(""); + $detailsTab.find("#size").text(""); + $detailsTab.find("#vm_name").text(""); + $detailsTab.find("#created").text(""); +} var volumeActionMap = { "Detach Disk": { @@ -118,8 +453,23 @@ var volumeActionMap = { api: "deleteVolume", isAsyncJob: false, inProcessText: "Deleting volume....", + afterActionSeccessFn: function(id) { + var $midmenuItem1 = $("#midmenuItem_"+id); + $midmenuItem1.remove(); + clearRightPanel(); + volumeClearRightPanel(); + } + }, + "Take Snapshot": { + isAsyncJob: true, + asyncJobResponse: "createsnapshotresponse", + dialogBeforeActionFn : doTakeSnapshot, + inProcessText: "Taking Snapshot....", afterActionSeccessFn: function(){} - } + }, + "Recurring Snapshot": { + customActionFn : doRecurringSnapshot + } } var volumeListAPIMap = { @@ -158,4 +508,186 @@ function doCreateTemplateFromVolume($actionLink, listAPIMap, $detailsTab) { $(this).dialog("close"); } }).dialog("open"); -} \ No newline at end of file +} + +function doTakeSnapshot($actionLink, listAPIMap, $detailsTab) { + $("#dialog_create_snapshot") + .dialog('option', 'buttons', { + "Confirm": function() { + $(this).dialog("close"); + + var id = $detailsTab.data("jsonObj").id; + var apiCommand = "command=createSnapshot&volumeid="+id; + doActionToDetailsTab(id, $actionLink, apiCommand, listAPIMap); + }, + "Cancel": function() { + $(this).dialog("close"); + } + }).dialog("open"); +} + +function clearTopPanel(target) { // "target == null" means target at all (hourly + daily + weekly + monthly) + var dialogBox = $("#dialog_recurring_snapshot"); + if(target == "hourly" || target == null) { + dialogBox.find("#dialog_snapshot_hourly_info_unset").show(); + dialogBox.find("#dialog_snapshot_hourly_info_set").hide(); + dialogBox.find("#read_hourly_max, #read_hourly_minute").text("N/A"); + dialogBox.find("#hourly_edit_link, #hourly_delete_link").data("intervalType", "hourly").data("max", "").data("timezone", (g_timezone==null)?"Etc/GMT+12":g_timezone).data("minute", "00"); + } + if(target == "daily" || target == null) { + dialogBox.find("#dialog_snapshot_daily_info_unset").show(); + dialogBox.find("#dialog_snapshot_daily_info_set").hide(); + dialogBox.find("#read_daily_max, #read_daily_minute, #read_daily_hour, #read_daily_meridiem").text("N/A"); + dialogBox.find("#daily_edit_link, #daily_delete_link").data("intervalType", "daily").data("max", "").data("timezone", (g_timezone==null)?"Etc/GMT+12":g_timezone).data("minute", "00").data("hour12", "00").data("meridiem", "AM"); + } + if(target == "weekly" || target == null) { + dialogBox.find("#dialog_snapshot_weekly_info_unset").show(); + dialogBox.find("#dialog_snapshot_weekly_info_set").hide(); + dialogBox.find("#read_weekly_max, #read_weekly_minute, #read_weekly_hour, #read_weekly_meridiem, #read_weekly_day_of_week").text("N/A"); + dialogBox.find("#weekly_edit_link, #weekly_delete_link").data("intervalType", "weekly").data("max", "").data("timezone", (g_timezone==null)?"Etc/GMT+12":g_timezone).data("minute", "00").data("hour12", "00").data("meridiem", "AM").data("dayOfWeek", "1"); + } + if(target == "monthly" || target == null) { + dialogBox.find("#dialog_snapshot_monthly_info_unset").show(); + dialogBox.find("#dialog_snapshot_monthly_info_set").hide(); + dialogBox.find("#read_monthly_max, #read_monthly_minute, #read_monthly_hour, #read_monthly_meridiem, #read_monthly_day_of_month").text("N/A"); + dialogBox.find("#monthly_edit_link, #monthly_delete_link").data("intervalType", "monthly").data("max", "").data("timezone", (g_timezone==null)?"Etc/GMT+12":g_timezone).data("minute", "00").data("hour12", "00").data("meridiem", "AM").data("dayOfMonth", "1"); + } +} + +function clearBottomPanel() { + var dialogBox = $("#dialog_recurring_snapshot"); + + dialogBox.find("#edit_hour").val("00"); + cleanErrMsg(dialogBox.find("#edit_hour"), dialogBox.find("#edit_time_errormsg")); + + dialogBox.find("#edit_minute").val("00"); + cleanErrMsg(dialogBox.find("#edit_minute"), dialogBox.find("#edit_time_errormsg")); + + dialogBox.find("#edit_meridiem").val("AM"); + + dialogBox.find("#edit_max").val(""); + cleanErrMsg(dialogBox.find("#edit_max"), dialogBox.find("#edit_max_errormsg")); + + dialogBox.find("#edit_timezone").val((g_timezone==null)?"Etc/GMT+12":g_timezone); + cleanErrMsg(dialogBox.find("#edit_timezone"), dialogBox.find("#edit_timezone_errormsg")); + + dialogBox.find("#edit_day_of_week").val("1"); + cleanErrMsg(dialogBox.find("#edit_day_of_week"), dialogBox.find("#edit_day_of_week_errormsg")); + + dialogBox.find("#edit_day_of_month").val("1"); + cleanErrMsg(dialogBox.find("#edit_day_of_month"), dialogBox.find("#edit_day_of_month_errormsg")); +} + +function doRecurringSnapshot() { + var $detailsTab = $("#right_panel_content #tab_content_details"); + var volumeId = $detailsTab.data("jsonObj").id; + + var dialogBox = $("#dialog_recurring_snapshot"); + clearTopPanel(); + + $.ajax({ + data: createURL("command=listSnapshotPolicies&volumeid="+volumeId), + dataType: "json", + async: false, + success: function(json) { + var items = json.listsnapshotpoliciesresponse.snapshotpolicy; + if(items!=null && items.length>0) { + for(var i=0; iPlease confirm you want to destroy your virtual machine: "+vmName+". Destroying your virtual machine would include deleting the ROOT volume and all attached data disk volumes.

") + .html("

Please confirm you want to destroy your virtual machine: "+vmName+". Destroying your virtual machine will also delete the ROOT volume, but not attached data disk volumes.

") .dialog('option', 'buttons', { "Confirm": function() { $(this).dialog("close"); diff --git a/ui/scripts/cloud.core.js b/ui/scripts/cloud.core.js index 9c527906e4e..fca118859e2 100644 --- a/ui/scripts/cloud.core.js +++ b/ui/scripts/cloud.core.js @@ -626,7 +626,7 @@ function noNull(val) { // Prevent cross-site-script(XSS) attack. // used right before adding user input to the DOM tree. e.g. DOM_element.html(sanitizeXSS(user_input)); function sanitizeXSS(val) { - if(val == null) + if(val == null || typeof(val) != "string") return val; val = val.replace(//g, ">"); //replace > whose unicode is \u003e diff --git a/ui/scripts/cloud.core.storage.js b/ui/scripts/cloud.core.storage.js index 5cca44dee3f..2f8bcf6557f 100644 --- a/ui/scripts/cloud.core.storage.js +++ b/ui/scripts/cloud.core.storage.js @@ -23,7 +23,7 @@ function showStorageTab(domainId, targetTab) { var populateZoneField = function(isAdmin) { $.ajax({ - data: createURL("command=listZones&available=true&response=json"+maxPageSize), + data: createURL("command=listZones&available=true&response=json"+maxPageSize), dataType: "json", success: function(json) { var zones = json.listzonesresponse.zone; @@ -50,7 +50,7 @@ function showStorageTab(domainId, targetTab) { var populateDiskOfferingField = function() { $.ajax({ - data: createURL("command=listDiskOfferings&response=json"), + data: createURL("command=listDiskOfferings&response=json"), dataType: "json", success: function(json) { var offerings = json.listdiskofferingsresponse.diskoffering; @@ -75,7 +75,7 @@ function showStorageTab(domainId, targetTab) { var volumeVmSelect = $("#dialog_attach_volume").find("#volume_vm").empty(); if (instances != null && instances.length > 0) { for (var i = 0; i < instances.length; i++) { - volumeVmSelect.append(""); + volumeVmSelect.append(""); } } $.ajax({ @@ -86,7 +86,7 @@ function showStorageTab(domainId, targetTab) { var instances = json.listvirtualmachinesresponse.virtualmachine; if (instances != null && instances.length > 0) { for (var i = 0; i < instances.length; i++) { - volumeVmSelect.append(""); + volumeVmSelect.append(""); } } } diff --git a/ui/test/scripts/cloud.core.test.js b/ui/test/scripts/cloud.core.test.js index 0aacfd85a66..364c33add56 100644 --- a/ui/test/scripts/cloud.core.test.js +++ b/ui/test/scripts/cloud.core.test.js @@ -102,7 +102,7 @@ function trim(val) { // Prevent cross-site-script(XSS) attack. // used right before adding user input to the DOM tree. e.g. DOM_element.html(sanitizeXSS(user_input)); function sanitizeXSS(val) { - if(val == null) + if(val == null || typeof(val) != "string") return val; val = val.replace(//g, ">"); //replace > whose unicode is \u003e