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 @@
+
+
+
+ Please confirm you want to create snapshot for this volume.
+
+
+
+
+
+
+
+
+
+
+ Hourly:
+
+
Please click 'Edit' to set your hourly recurring snapshot schedule
+
+
+ mm Minute(s) Past the Hour
+
+
+
+
+
+
+ Daily:
+
+
Please click 'Edit' to set your daily recurring snapshot schedule
+
+
+ hh : mm
+ AM
+
+
+
+
+
+
+ Weekly:
+
+
Please click 'Edit' to set your weekly recurring snapshot schedule
+
+
+ hh : mm
+ AM
+ day-of-week
+
+
+
+
+
+
+ Monthly:
+
+
Please click 'Edit' to set your monthly recurring snapshot schedule
+
+
+ hh : mm
+ AM
+ day-of-month
+
+
+
+
+
+
+
Cick Edit to Schedule
+
+
+
Edit:
+
Interval Type
+
+
+
+
+
+
+
+
+
+
+
+ Please fill in the following data to add a new volume.
+
+
+
+
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("" + sanitizeXSS(zones[i].name) + " ");
+ }
+ }
+ }
+ });
+
+ $.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("" + sanitizeXSS(offerings[i].displaytext) + " ");
+ }
+ }
+ }
+ });
+
+ //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("" + getVmName(instances[i].name, instances[i].displayname)+ " ");
+ volumeVmSelect.append("" + getVmName(instances[i].name, instances[i].displayname) + " ");
}
}
$.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("" + sanitizeXSS(instances[i].name) + " ");
+ volumeVmSelect.append("" + getVmName(instances[i].name, instances[i].displayname) + " ");
}
}
}
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