diff --git a/core/src/com/cloud/server/ManagementServer.java b/core/src/com/cloud/server/ManagementServer.java index 60b2b7a3f1d..c3794a40303 100755 --- a/core/src/com/cloud/server/ManagementServer.java +++ b/core/src/com/cloud/server/ManagementServer.java @@ -2200,4 +2200,5 @@ public interface ManagementServer { VolumeVO findVolumeByInstanceAndDeviceId(long instanceId, long deviceId); VolumeVO getRootVolume(Long instanceId); long getPsMaintenanceCount(long podId); + boolean isPoolUp(long instanceId); } diff --git a/core/src/com/cloud/storage/dao/StoragePoolDao.java b/core/src/com/cloud/storage/dao/StoragePoolDao.java index 85b5b33b40e..06d10c88b8a 100644 --- a/core/src/com/cloud/storage/dao/StoragePoolDao.java +++ b/core/src/com/cloud/storage/dao/StoragePoolDao.java @@ -103,5 +103,7 @@ public interface StoragePoolDao extends GenericDao { long countBy(long podId, Status... statuses); List findIfDuplicatePoolsExistByUUID(String uuid); + + List listPoolsByStatus(Status status); } diff --git a/core/src/com/cloud/storage/dao/StoragePoolDaoImpl.java b/core/src/com/cloud/storage/dao/StoragePoolDaoImpl.java index 12a1c8cc799..a5d716b16ae 100644 --- a/core/src/com/cloud/storage/dao/StoragePoolDaoImpl.java +++ b/core/src/com/cloud/storage/dao/StoragePoolDaoImpl.java @@ -59,6 +59,7 @@ public class StoragePoolDaoImpl extends GenericDaoBase imp protected final SearchBuilder HostPathDcSearch; protected final SearchBuilder DcPodAnyClusterSearch; protected final SearchBuilder DeleteLvmSearch; + protected final SearchBuilder StatusSearch; protected final GenericSearchBuilder MaintenanceCountSearch; @@ -109,6 +110,10 @@ public class StoragePoolDaoImpl extends GenericDaoBase imp HostSearch.and("host", HostSearch.entity().getHostAddress(), SearchCriteria.Op.EQ); HostSearch.done(); + StatusSearch = createSearchBuilder(); + StatusSearch.and("status",StatusSearch.entity().getStatus(),SearchCriteria.Op.EQ); + StatusSearch.done(); + HostPathDcPodSearch = createSearchBuilder(); HostPathDcPodSearch.and("hostAddress", HostPathDcPodSearch.entity().getHostAddress(), SearchCriteria.Op.EQ); HostPathDcPodSearch.and("path", HostPathDcPodSearch.entity().getPath(), SearchCriteria.Op.EQ); @@ -183,6 +188,13 @@ public class StoragePoolDaoImpl extends GenericDaoBase imp sc.setParameters("host", hostFqdnOrIp); return listBy(sc); } + + @Override + public List listPoolsByStatus(Status status){ + SearchCriteria sc = StatusSearch.create(); + sc.setParameters("status", status); + return listBy(sc); + } @Override public StoragePoolVO findPoolByHostPath(long datacenterId, Long podId, String host, String path) { diff --git a/server/src/com/cloud/api/commands/CreateVolumeCmd.java b/server/src/com/cloud/api/commands/CreateVolumeCmd.java index 2733228d4e4..360c7e45087 100644 --- a/server/src/com/cloud/api/commands/CreateVolumeCmd.java +++ b/server/src/com/cloud/api/commands/CreateVolumeCmd.java @@ -185,8 +185,9 @@ public class CreateVolumeCmd extends BaseCmd { if(s_logger.isDebugEnabled()) s_logger.debug("CreateVolume command has been accepted, job id: " + jobId); } - + long volumeId = waitInstanceCreation(jobId); + List> returnValues = new ArrayList>(); returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId))); returnValues.add(new Pair(BaseCmd.Properties.VOLUME_ID.getName(), Long.valueOf(volumeId))); diff --git a/server/src/com/cloud/api/commands/PreparePrimaryStorageForMaintenanceCmd.java b/server/src/com/cloud/api/commands/PreparePrimaryStorageForMaintenanceCmd.java index c2de2923cdc..08a087165fe 100644 --- a/server/src/com/cloud/api/commands/PreparePrimaryStorageForMaintenanceCmd.java +++ b/server/src/com/cloud/api/commands/PreparePrimaryStorageForMaintenanceCmd.java @@ -73,7 +73,7 @@ public class PreparePrimaryStorageForMaintenanceCmd extends BaseCmd { } if(getManagementServer().getPsMaintenanceCount(storagePool.getPodId()) > 0){ - throw new ServerApiException(BaseCmd.INTERNAL_ERROR,"There already exist other storage pools in maintenance"); + throw new ServerApiException(BaseCmd.INTERNAL_ERROR,"There already exist other storage pools in maintenance process"); } long jobId = 0; diff --git a/server/src/com/cloud/api/commands/StartVMCmd.java b/server/src/com/cloud/api/commands/StartVMCmd.java index 6c70304d573..7f4af063117 100644 --- a/server/src/com/cloud/api/commands/StartVMCmd.java +++ b/server/src/com/cloud/api/commands/StartVMCmd.java @@ -78,7 +78,10 @@ public class StartVMCmd extends BaseCmd { throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid virtual machine id (" + vmId + ") given, unable to start virtual machine."); } } - + + if(!getManagementServer().isPoolUp(vmId)){ + throw new ServerApiException(BaseCmd.INTERNAL_ERROR,"Storage pool for this vm is under maintenance"); + } if (userId == null) { userId = Long.valueOf(1); } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index e826a2edc9d..4ecb921ebc9 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -1762,11 +1762,22 @@ public class ManagementServerImpl implements ManagementServer { // Check that there is a shared primary storage pool in the specified zone List storagePools = _poolDao.listByDataCenterId(zoneId); + boolean sharedPoolExists = false; + boolean readyPoolExists = false; for (StoragePoolVO storagePool : storagePools) { if (storagePool.isShared()) { sharedPoolExists = true; } + //check if there are any pools in the UP state + //if not, throw an error + if(storagePool.getStatus().equals(Status.Up)){ + readyPoolExists = true; + } + } + + if(!readyPoolExists){ + throw new InternalErrorException("There are no ready pools for volume creation"); } // Check that there is at least one host in the specified zone @@ -8722,7 +8733,31 @@ public class ManagementServerImpl implements ManagementServer { @Override public long getPsMaintenanceCount(long podId){ - return _poolDao.countBy(podId, Status.Maintenance); + List poolsInTransition = new ArrayList(); + poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.Maintenance)); + poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.PrepareForMaintenance)); + poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.ErrorInMaintenance)); + + if(poolsInTransition==null) + return 0; + else + return poolsInTransition.size(); + } + + @Override + public boolean isPoolUp(long instanceId){ + VolumeVO rootVolume = _volumeDao.findByInstance(instanceId).get(0); + + if(rootVolume!=null){ + Status poolStatus = _poolDao.findById(rootVolume.getPoolId()).getStatus(); + + if(!poolStatus.equals(Status.Up)) + return false; + else + return true; + } + + return false; } } diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index ddf4d493045..864825ed87a 100644 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -440,7 +440,9 @@ public class StorageManagerImpl implements StorageManager { for (StoragePoolHostVO poolHost: poolHosts) { try { - return _agentMgr.send(poolHost.getHostId(), cmds, stopOnError); + Answer[] answerRet = _agentMgr.send(poolHost.getHostId(), cmds, stopOnError); + return answerRet; + } catch (AgentUnavailableException e) { s_logger.debug("Moving on because unable to send to " + poolHost.getHostId() + " due to " + e.getMessage()); } catch (OperationTimedoutException e) { @@ -1664,7 +1666,7 @@ public class StorageManagerImpl implements StorageManager { _asyncMgr.updateAsyncJobAttachment(job.getId(), "volume", volume.getId()); _asyncMgr.updateAsyncJobStatus(job.getId(), BaseCmd.PROGRESS_INSTANCE_CREATED, volume.getId()); } - + List poolsToAvoid = new ArrayList(); Set podsToAvoid = new HashSet(); Pair pod = null; @@ -2007,9 +2009,9 @@ public class StorageManagerImpl implements StorageManager { //check to see if other ps exist //if they do, then we can migrate over the system vms to them //if they dont, then just stop all vms on this one - count = _storagePoolDao.countBy(primaryStorage.getPodId(), Status.Up); + List upPools = _storagePoolDao.listPoolsByStatus(Status.Up); - if(count == 0) + if(upPools==null || upPools.size()==0) restart = false; //2. Get a list of all the volumes within this storage pool diff --git a/ui/new/css/main.css b/ui/new/css/main.css index 8998cae70fe..ecb08741008 100644 --- a/ui/new/css/main.css +++ b/ui/new/css/main.css @@ -2141,6 +2141,41 @@ a:visited { background:url(../images/grid_actions_hover.png) no-repeat top left; } +.gridheader_loaderbox { + width:auto; + height:20px; + float:right; + position:absolute; + background:#99b2c3 url(../images/gridheader_loadingbg.gif) repeat-x top left; + border-left:1px solid #999; + margin:0px 0 0 0; + padding:0; + z-index:1001; + right:0; +} + +.gridheader_loaderbox p{ + width:auto; + height:auto; + float:left; + color:#FFF; + font-size:11px; + font-weight:bold; + margin:2px 5px 0 5px; + display:inline; + padding:0; +} + +.gridheader_loader { + width:16px; + height:16px; + float:left; + background:url(../images/grid_actionloader.gif) no-repeat top left; + margin:0 0 0 5px; + display:inline; + padding:0; +} + .grid_editbox { width:27px; height:17px; diff --git a/ui/new/images/grid_actionloader.gif b/ui/new/images/grid_actionloader.gif new file mode 100644 index 00000000000..6b096585f80 Binary files /dev/null and b/ui/new/images/grid_actionloader.gif differ diff --git a/ui/new/images/gridheader_loadingbg.gif b/ui/new/images/gridheader_loadingbg.gif new file mode 100644 index 00000000000..6cb13eabcf2 Binary files /dev/null and b/ui/new/images/gridheader_loadingbg.gif differ diff --git a/ui/new/images/account_admin_midmenuicon.png b/ui/new/images/midmenuicon_account_admin.png similarity index 100% rename from ui/new/images/account_admin_midmenuicon.png rename to ui/new/images/midmenuicon_account_admin.png diff --git a/ui/new/images/account_domain_midmenuicon.png b/ui/new/images/midmenuicon_account_domain.png similarity index 100% rename from ui/new/images/account_domain_midmenuicon.png rename to ui/new/images/midmenuicon_account_domain.png diff --git a/ui/new/images/account_user_midmenuicon.png b/ui/new/images/midmenuicon_account_user.png similarity index 100% rename from ui/new/images/account_user_midmenuicon.png rename to ui/new/images/midmenuicon_account_user.png diff --git a/ui/new/images/events_error_midmenuicon.png b/ui/new/images/midmenuicon_events_error.png similarity index 100% rename from ui/new/images/events_error_midmenuicon.png rename to ui/new/images/midmenuicon_events_error.png diff --git a/ui/new/images/events_info_midmenuicon.png b/ui/new/images/midmenuicon_events_info.png similarity index 100% rename from ui/new/images/events_info_midmenuicon.png rename to ui/new/images/midmenuicon_events_info.png diff --git a/ui/new/images/events_warning_midmenuicon.png b/ui/new/images/midmenuicon_events_warning.png similarity index 100% rename from ui/new/images/events_warning_midmenuicon.png rename to ui/new/images/midmenuicon_events_warning.png diff --git a/ui/new/images/midmenuicon_network_networkgroup.png b/ui/new/images/midmenuicon_network_networkgroup.png new file mode 100644 index 00000000000..2107efa2038 Binary files /dev/null and b/ui/new/images/midmenuicon_network_networkgroup.png differ diff --git a/ui/new/jsp/instance.jsp b/ui/new/jsp/instance.jsp index fad0ab5f9c2..b81431769bc 100644 --- a/ui/new/jsp/instance.jsp +++ b/ui/new/jsp/instance.jsp @@ -145,17 +145,21 @@ + + @@ -773,7 +778,9 @@
- + + +
diff --git a/ui/new/scripts/cloud.core2.init.js b/ui/new/scripts/cloud.core2.init.js index 828380aa88e..e2d12c5e167 100644 --- a/ui/new/scripts/cloud.core2.init.js +++ b/ui/new/scripts/cloud.core2.init.js @@ -19,36 +19,28 @@ $(document).ready(function() { $("#midmenu_container").selectable({ selecting: function(event, ui) { if(ui.selecting.id.indexOf("midmenuItem") != -1) { - var $t = $("#"+ui.selecting.id); - if($t.find("#content").hasClass("inaction") == false) { //only items not in action are allowed to be selected - var id =$t.data("id"); - selectedItemIds[id] = $t; - $t.find("#content").addClass("selected"); + var $midmenuItem1 = $("#"+ui.selecting.id); + if($midmenuItem1.find("#content").hasClass("inaction") == false) { //only items not in action are allowed to be selected + var id =$midmenuItem1.data("id"); + selectedItemsInMidMenu[id] = $midmenuItem1; + $midmenuItem1.find("#content").addClass("selected"); } - var toRightPanelFn = $t.data("toRightPanelFn"); - toRightPanelFn($t); + var toRightPanelFn = $midmenuItem1.data("toRightPanelFn"); + toRightPanelFn($midmenuItem1); } }, unselecting: function(event, ui) { if(ui.unselecting.id.indexOf("midmenuItem") != -1) { - var $t = $("#"+ui.unselecting.id); - var id = $t.data("id"); - if(id in selectedItemIds) { - delete selectedItemIds[id]; - $t.find("#content").removeClass("selected"); + var $midmenuItem1 = $("#"+ui.unselecting.id); + var id = $midmenuItem1.data("id"); + if(id in selectedItemsInMidMenu) { + delete selectedItemsInMidMenu[id]; + $midmenuItem1.find("#content").removeClass("selected"); } } } }); - - var $rightPanel = $("#right_panel"); - var $addLink = $("#add_link"); - //var $actionLink = $("#action_link"); - //var $actionMenu = $("#action_menu"); - //var $actionList = $("#action_menu #action_list"); - var $midmenuContainer = $("#midmenu_container"); - //var $actionListItem = $("#action_list_item"); - + $("#leftmenu_instance_group_header").bind("click", function(event) { var $arrowIcon = $(this).find("#arrow_icon"); clickInstanceGroupHeader($arrowIcon); @@ -75,14 +67,16 @@ $(document).ready(function() { data: createURL("command="+apiName+"&response=json"), dataType: "json", success: function(json) { - $midmenuContainer.empty(); + $("#midmenu_container").empty(); + selectedItemsInMidMenu = {}; + var items = json[jsonResponse1][jsonResponse2]; if(items != null && items.length > 0) { for(var i=0; iPlease confirm you want to detach an ISO from the virtual machine(s)

") .dialog('option', 'buttons', { "Confirm": function() { $(this).dialog("close"); - for(var id in selectedItemIds) { + for(var id in selectedItemsInMidMenu) { var apiCommand = "command=detachIso&virtualmachineid="+id; - doAction(id, $t, apiCommand, vmListAPIMap); + doActionForMidMenu(id, $t, apiCommand, vmListAPIMap); } }, "Cancel": function() { @@ -153,14 +145,14 @@ function clickInstanceGroupHeader($arrowIcon) { }).dialog("open"); } - function doResetPassword($t, selectedItemIds, vmListAPIMap) { + function doResetPassword($t, selectedItemsInMidMenu, vmListAPIMap) { $("#dialog_confirmation") .html("

Please confirm you want to change the ROOT password for your virtual machine(s)

") .dialog('option', 'buttons', { "Confirm": function() { $(this).dialog("close"); - for(var id in selectedItemIds) { - var $midMenuItem = selectedItemIds[id]; + for(var id in selectedItemsInMidMenu) { + var $midMenuItem = selectedItemsInMidMenu[id]; var jsonObj = $midMenuItem.data("jsonObj"); if(jsonObj.state != "Stopped") { $midMenuItem.find("#info_icon").addClass("error").show(); @@ -173,7 +165,7 @@ function clickInstanceGroupHeader($arrowIcon) { continue; } var apiCommand = "command=resetPasswordForVirtualMachine&id="+id; - doAction(id, $t, apiCommand, vmListAPIMap); + doActionForMidMenu(id, $t, apiCommand, vmListAPIMap); } }, "Cancel": function() { @@ -182,7 +174,7 @@ function clickInstanceGroupHeader($arrowIcon) { }).dialog("open"); } - function doChangeName($t, selectedItemIds, vmListAPIMap) { + function doChangeName($t, selectedItemsInMidMenu, vmListAPIMap) { $("#dialog_change_name") .dialog('option', 'buttons', { "Confirm": function() { @@ -196,9 +188,9 @@ function clickInstanceGroupHeader($arrowIcon) { var name = trim(thisDialog.find("#change_instance_name").val()); - for(var id in selectedItemIds) { + for(var id in selectedItemsInMidMenu) { var apiCommand = "command=updateVirtualMachine&id="+id+"&displayName="+todb(name); - doAction(id, $t, apiCommand, vmListAPIMap); + doActionForMidMenu(id, $t, apiCommand, vmListAPIMap); } }, "Cancel": function() { @@ -207,7 +199,7 @@ function clickInstanceGroupHeader($arrowIcon) { }).dialog("open"); } - function doChangeService($t, selectedItemIds, vmListAPIMap) { + function doChangeService($t, selectedItemsInMidMenu, vmListAPIMap) { $.ajax({ //data: createURL("command=listServiceOfferings&VirtualMachineId="+vmId), //can not specifiy VirtualMachineId since we allow multiple-item-selection. data: createURL("command=listServiceOfferings"), //can not specifiy VirtualMachineId since we support multiple-item-selection. @@ -231,8 +223,8 @@ function clickInstanceGroupHeader($arrowIcon) { var thisDialog = $(this); thisDialog.dialog("close"); - for(var id in selectedItemIds) { - var $midMenuItem = selectedItemIds[id]; + for(var id in selectedItemsInMidMenu) { + var $midMenuItem = selectedItemsInMidMenu[id]; var jsonObj = $midMenuItem.data("jsonObj"); if(jsonObj.state != "Stopped") { $midMenuItem.find("#info_icon").addClass("error").show(); @@ -240,7 +232,7 @@ function clickInstanceGroupHeader($arrowIcon) { continue; } var apiCommand = "command=changeServiceForVirtualMachine&id="+id+"&serviceOfferingId="+thisDialog.find("#change_service_offerings").val(); - doAction(id, $t, apiCommand, vmListAPIMap); + doActionForMidMenu(id, $t, apiCommand, vmListAPIMap); } }, "Cancel": function() { @@ -249,7 +241,7 @@ function clickInstanceGroupHeader($arrowIcon) { }).dialog("open"); } - function doChangeGroup($t, selectedItemIds, vmListAPIMap) { + function doChangeGroup($t, selectedItemsInMidMenu, vmListAPIMap) { $("#dialog_change_group") .dialog('option', 'buttons', { "Confirm": function() { @@ -261,12 +253,12 @@ function clickInstanceGroupHeader($arrowIcon) { isValid &= validateString("Group", thisDialog.find("#change_group_name"), thisDialog.find("#change_group_name_errormsg"), true); //group name is optional if (!isValid) return; - for(var id in selectedItemIds) { - var $midMenuItem = selectedItemIds[id]; + for(var id in selectedItemsInMidMenu) { + var $midMenuItem = selectedItemsInMidMenu[id]; var jsonObj = $midMenuItem.data("jsonObj"); var group = trim(thisDialog.find("#change_group_name").val()); var apiCommand = "command=updateVirtualMachine&id="+id+"&group="+todb(group); - doAction(id, $t, apiCommand, vmListAPIMap); + doActionForMidMenu(id, $t, apiCommand, vmListAPIMap); } }, "Cancel": function() { @@ -275,7 +267,7 @@ function clickInstanceGroupHeader($arrowIcon) { }).dialog("open"); } - function doEnableHA($t, selectedItemIds, vmListAPIMap) { + function doEnableHA($t, selectedItemsInMidMenu, vmListAPIMap) { var message = "

Please confirm you want to enable HA for your virtual machine. Once HA is enabled, your Virtual Instance will be automatically restarted in the event it is detected to have failed.

"; $("#dialog_confirmation") @@ -283,11 +275,11 @@ function clickInstanceGroupHeader($arrowIcon) { .dialog('option', 'buttons', { "Confirm": function() { $(this).dialog("close"); - for(var id in selectedItemIds) { - var $midMenuItem = selectedItemIds[id]; + for(var id in selectedItemsInMidMenu) { + var $midMenuItem = selectedItemsInMidMenu[id]; var jsonObj = $midMenuItem.data("jsonObj"); var apiCommand = "command=updateVirtualMachine&id="+id+"&haenable=true"; - doAction(id, $t, apiCommand, vmListAPIMap); + doActionForMidMenu(id, $t, apiCommand, vmListAPIMap); } }, "Cancel": function() { @@ -296,7 +288,7 @@ function clickInstanceGroupHeader($arrowIcon) { }).dialog("open"); } - function doDisableHA($t, selectedItemIds, vmListAPIMap) { + function doDisableHA($t, selectedItemsInMidMenu, vmListAPIMap) { var message = "

Please confirm you want to disable HA for your virtual machine. Once HA is disabled, your Virtual Instance will no longer be be automatically restarted in the event of a failure.

"; $("#dialog_confirmation") @@ -304,11 +296,11 @@ function clickInstanceGroupHeader($arrowIcon) { .dialog('option', 'buttons', { "Confirm": function() { $(this).dialog("close"); - for(var id in selectedItemIds) { - var $midMenuItem = selectedItemIds[id]; + for(var id in selectedItemsInMidMenu) { + var $midMenuItem = selectedItemsInMidMenu[id]; var jsonObj = $midMenuItem.data("jsonObj"); var apiCommand = "command=updateVirtualMachine&id="+id+"&haenable=false"; - doAction(id, $t, apiCommand, vmListAPIMap); + doActionForMidMenu(id, $t, apiCommand, vmListAPIMap); } }, "Cancel": function() { @@ -445,11 +437,11 @@ function clickInstanceGroupHeader($arrowIcon) { setDateField(json.created, template.find("#created")); if(json.type=="ROOT") { //"create template" is allowed(when stopped), "detach disk" is disallowed. - //if (json.vmstate == "Stopped") - buildActionLink("Create Template", volumeActionMap, $("#volume_action_menu"), volumeListAPIMap); + if (json.vmstate == "Stopped") + buildActionLink("Create Template", volumeActionMap, template.find("#volume_action_menu"), volumeListAPIMap); } else { //json.type=="DATADISK": "detach disk" is allowed, "create template" is disallowed. - buildActionLink("Detach Disk", volumeActionMap, $("#volume_action_menu"), volumeListAPIMap); + buildActionLink("Detach Disk", volumeActionMap, template.find("#volume_action_menu"), volumeListAPIMap); } } @@ -480,12 +472,14 @@ function clickInstanceGroupHeader($arrowIcon) { } for(var i=0; i < instanceGroupArray.length; i++) { if(instanceGroupArray[i]!=null && instanceGroupArray[i].length>0) { - var $groupTemplate = $instanceGroupTemplate.clone().show(); + var $groupTemplate = $("#leftmenu_instance_group_template").clone().show(); $groupTemplate.find("#group_name").text(instanceGroupArray[i]); $groupTemplate.bind("click", function(event) { //$(this).removeClass("leftmenu_content").addClass("leftmenu_content_selected"); $("#midmenu_container").empty(); + selectedItemsInMidMenu = {}; + var groupName = $(this).find("#group_name").text(); $.ajax({ @@ -511,7 +505,7 @@ function clickInstanceGroupHeader($arrowIcon) { return false; }); - $instanceGroupContainer.append($groupTemplate); + $("#leftmenu_instance_group_container").append($groupTemplate); } } @@ -525,7 +519,7 @@ function clickInstanceGroupHeader($arrowIcon) { } else if($arrowIcon.hasClass("open") == true) { $arrowIcon.removeClass("open").addClass("close"); - $instanceGroupContainer.empty(); + $("#leftmenu_instance_group_container").empty(); } //***** VM Detail (end) ******************************************************************************** $("#right_panel").load("jsp/instance.jsp", function() { @@ -1203,11 +1197,11 @@ function clickInstanceGroupHeader($arrowIcon) { //***** Volume tab (begin) ***************************************************************************** $("#volume_action_link").bind("mouseover", function(event) { - $("#volume_action_menu").show(); + $(this).find("#volume_action_menu").show(); return false; }); $("#volume_action_link").bind("mouseout", function(event) { - $("#volume_action_menu").hide(); + $(this).find("#volume_action_menu").hide(); return false; }); //***** Volume tab (end) ******************************************************************************* diff --git a/ui/new/scripts/cloud.core2.js b/ui/new/scripts/cloud.core2.js index 75a548c1519..2ef6d2858f8 100644 --- a/ui/new/scripts/cloud.core2.js +++ b/ui/new/scripts/cloud.core2.js @@ -20,7 +20,7 @@ // Version: @VERSION@ -var selectedItemIds = {}; +var selectedItemsInMidMenu = {}; function buildActionLink(label, actionMap, $actionMenu, listAPIMap) { var apiInfo = actionMap[label]; @@ -38,21 +38,21 @@ function buildActionLink(label, actionMap, $actionMenu, listAPIMap) { var $actionLink = $(this); var dialogBeforeActionFn = $actionLink.data("dialogBeforeActionFn"); if(dialogBeforeActionFn == null) { - for(var id in selectedItemIds) { + for(var id in selectedItemsInMidMenu) { var apiCommand = "command="+$actionLink.data("api")+"&id="+id; - doAction(id, $actionLink, apiCommand, listAPIMap); + doActionForMidMenu(id, $actionLink, apiCommand, listAPIMap); } } else { - dialogBeforeActionFn($actionLink, selectedItemIds, listAPIMap); + dialogBeforeActionFn($actionLink, selectedItemsInMidMenu, listAPIMap); } - selectedItemIds = {}; //clear selected items for action + selectedItemsInMidMenu = {}; //clear selected items for action return false; }); } -function doAction(id, $actionLink, apiCommand, listAPIMap) { +function doActionForMidMenu(id, $actionLink, apiCommand, listAPIMap) { var label = $actionLink.data("label"); var isAsyncJob = $actionLink.data("isAsyncJob"); var asyncJobResponse = $actionLink.data("asyncJobResponse"); @@ -113,45 +113,16 @@ function doAction(id, $actionLink, apiCommand, listAPIMap) { } }, error: function(XMLHttpResponse) { - $("body").stopTime(timerKey); - $midmenuItem.find("#content").removeClass("inaction"); - $midmenuItem.find("#spinning_wheel").hide(); - $midmenuItem.find("#info_icon").addClass("error").show(); - - var errorMsg = ""; - if(XMLHttpResponse.responseText != null & XMLHttpResponse.responseText.length > 0) { - var start = XMLHttpResponse.responseText.indexOf("h1") + 3; - var end = XMLHttpResponse.responseText.indexOf(" 0) - $midmenuItem.data("afterActionInfo", ((label + " action failed. Reason: " + sanitizeXSS(unescape(errorMsg))))); - else - $midmenuItem.data("afterActionInfo", (label + " action failed.")); - //handleError(XMLHttpResponse); + $("body").stopTime(timerKey); + handleErrorInMidMenu(XMLHttpResponse, $midmenuItem); } }); }, 0 ); }, - error: function(XMLHttpResponse) { - $midmenuItem.find("#content").removeClass("inaction"); - $midmenuItem.find("#spinning_wheel").hide(); - $midmenuItem.find("#info_icon").addClass("error").show(); - $midmenuItem.data("afterActionInfo", (label + " action failed.")); - - var errorMsg = ""; - if(XMLHttpResponse.responseText != null & XMLHttpResponse.responseText.length > 0) { - var start = XMLHttpResponse.responseText.indexOf("h1") + 3; - var end = XMLHttpResponse.responseText.indexOf(" 0) - $midmenuItem.data("afterActionInfo", ((label + " action failed. Reason: " + sanitizeXSS(unescape(errorMsg))))); - else - $midmenuItem.data("afterActionInfo", (label + " action failed.")); - //handleError(XMLHttpResponse); + error: function(XMLHttpResponse) { + handleErrorInMidMenu(XMLHttpResponse, $midmenuItem); } }); } @@ -178,20 +149,37 @@ function doAction(id, $actionLink, apiCommand, listAPIMap) { $midmenuItem.find("#info_icon").removeClass("error").show(); $midmenuItem.data("afterActionInfo", (label + " action succeeded.")); afterActionSeccessFn(json[listAPIResponse][listAPIResponseObj][0], $midmenuItem); - }, - error: function(XMLHttpResponse) { - $midmenuItem.find("#info_icon").addClass("error").show(); - $midmenuItem.data("afterActionInfo", (label + " action failed. Reason: " + sanitizeXSS(result.jobresult))); } }); //After Bug 6037 is fixed, remove temporary solution above and uncomment the line below //afterActionSeccessFn(json[listAPIResponse][listAPIResponseObj][0], $midmenuItem); - } + }, + error: function(XMLHttpResponse) { + handleErrorInMidMenu(XMLHttpResponse, $midmenuItem); + } }); } //Sync job (end) ***** } +function handleErrorInMidMenu(XMLHttpResponse, $midmenuItem) { + $midmenuItem.find("#content").removeClass("inaction"); + $midmenuItem.find("#spinning_wheel").hide(); + $midmenuItem.find("#info_icon").addClass("error").show(); + + var errorMsg = ""; + if(XMLHttpResponse.responseText != null & XMLHttpResponse.responseText.length > 0) { + var start = XMLHttpResponse.responseText.indexOf("h1") + 3; + var end = XMLHttpResponse.responseText.indexOf(" 0) + $midmenuItem.data("afterActionInfo", ((label + " action failed. Reason: " + sanitizeXSS(unescape(errorMsg))))); + else + $midmenuItem.data("afterActionInfo", (label + " action failed.")); +} + + function createURL(url) { return url +"&response=json&sessionkey=" + g_sessionKey; } diff --git a/ui/new/scripts/cloud.core2.volume.js b/ui/new/scripts/cloud.core2.volume.js index 5c85fa1fd2f..b2eb6e4c559 100644 --- a/ui/new/scripts/cloud.core2.volume.js +++ b/ui/new/scripts/cloud.core2.volume.js @@ -67,8 +67,8 @@ function doCreateTemplate($t, selectedItemIds, listAPIMap) { var password = thisDialog.find("#create_template_password").val(); for(var id in selectedItemIds) { - var apiCommand = "command=createTemplate&volumeId="+id+"&name="+encodeURIComponent(name)+"&displayText="+encodeURIComponent(desc)+"&osTypeId="+osType+"&isPublic="+isPublic+"&passwordEnabled="+password; - doAction(id, $t, apiCommand, listAPIMap); + var apiCommand = "command=createTemplate&volumeId="+id+"&name="+encodeURIComponent(name)+"&displayText="+encodeURIComponent(desc)+"&osTypeId="+osType+"&isPublic="+isPublic+"&passwordEnabled="+password; + doAction(id, $t, apiCommand, listAPIMap); } }, "Cancel": function() { diff --git a/ui/scripts/cloud.core.storage.js b/ui/scripts/cloud.core.storage.js index 028c541535c..68e03e0cfff 100644 --- a/ui/scripts/cloud.core.storage.js +++ b/ui/scripts/cloud.core.storage.js @@ -274,8 +274,10 @@ function showStorageTab(domainId, targetTab) { setDateField(json.created, template.find("#volume_created")); if(json.type=="ROOT") { - } else { - // DataDisk + if (json.vmstate == "Stopped") + template.find("#volume_action_create_template_span").show(); + } + else { //json.type=="DATADISK": "detach disk" is allowed, "create template" is disallowed. if (json.virtualmachineid != undefined) { if (json.storagetype == "shared" && (json.vmstate == "Running" || json.vmstate == "Stopped")) { template.find("#volume_action_detach_span").show();