From 37d82c8aa7fbad8f3808829e2366a4f732bac3ff Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Fri, 10 Sep 2010 11:39:33 -0700 Subject: [PATCH 1/8] new UI - instance page - volume tab - show different action link for each volume depending on volume type and vm state. --- ui/new/scripts/cloud.core2.init.js | 4 ++-- ui/new/scripts/cloud.core2.instance.js | 10 +++++----- ui/new/scripts/cloud.core2.volume.js | 4 ++-- ui/scripts/cloud.core.storage.js | 6 ++++-- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/ui/new/scripts/cloud.core2.init.js b/ui/new/scripts/cloud.core2.init.js index 828380aa88e..c31824a41c6 100644 --- a/ui/new/scripts/cloud.core2.init.js +++ b/ui/new/scripts/cloud.core2.init.js @@ -100,11 +100,11 @@ $(document).ready(function() { $("#action_link").bind("mouseover", function(event) { - $("#action_menu").show(); + $(this).find("#action_menu").show(); return false; }); $("#action_link").bind("mouseout", function(event) { - $("#action_menu").hide(); + $(this).find("#action_menu").hide(); return false; }); diff --git a/ui/new/scripts/cloud.core2.instance.js b/ui/new/scripts/cloud.core2.instance.js index a4edcda1fb7..f85aadcf76a 100644 --- a/ui/new/scripts/cloud.core2.instance.js +++ b/ui/new/scripts/cloud.core2.instance.js @@ -445,11 +445,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); } } @@ -1203,11 +1203,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.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(); From e741b7272fbbd704919777cc62e055ccfe095286 Mon Sep 17 00:00:00 2001 From: NIKITA Date: Fri, 10 Sep 2010 12:09:11 -0700 Subject: [PATCH 2/8] Loading for grid header --- ui/new/css/main.css | 35 +++++++++++++++++++++++++ ui/new/images/grid_actionloader.gif | Bin 0 -> 847 bytes ui/new/images/gridheader_loadingbg.gif | Bin 0 -> 130 bytes ui/new/jsp/instance.jsp | 17 ++++++++---- 4 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 ui/new/images/grid_actionloader.gif create mode 100644 ui/new/images/gridheader_loadingbg.gif 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 0000000000000000000000000000000000000000..6b096585f807e8f55f1b02191a757ae40e24067b GIT binary patch literal 847 zcmZ?wbhEHb6krfw_`<+2bJOAf|Nqb4eB}At4=1nP|NZCByH8(N>^-yl^tG?wf1JPd z=<5Avi+7$pc;VLiLl+*tczgTFD+W@4;(u;G*N|Xm#{gF&Jp*P&pkBp)QqD!Gi6yBi z3gww4848J6i4{5di79%Sd1?6!ia%L6xqzy4K(>G!$-o+*pwO3+Id7?fNRFabOTwzP zGenL}lrnAjz;?5vA-b2vhAFc(V4^@PV`uB4zBQUU4W3ay7O5nC*yS;4fdgv-pu5*<>|Hn(-{gjt4u>v0=H?uP};XReTu;fv2}|U_B&<^oL6>a z;I;`cH(Wp`0?>!bpC@SC67kUDIuanlsk@}z@V#*(mzDEr zL+>pfElm&EJoIL$+}v2nz#*{j;u+Q(S=@S!;Vuq$_#zn=8F+Atwdxr3IbGrE%NFo@ z_Le8q-n5*VrA8&2H%616ryHxKL6Bf=P?*AGD00+cMYFRU+Zyp>+1*WZ7!{qKB-k@F zZfDvzLD{v*qRJ^Sq9J*A?xHeoA*F>1FAptFXiRA14Ru>4S#(E|Z)w46&ChB78?agf z@*6PrRygpu8VVdbDUlm1aeSwQN6&?}8yf5aT`VR{3ePokB$l};CVDVL1kd1T%r#xI zl`+Z1V+$L@s-1~RI$V9K4F$$x$w!nosQ=)7qr`4vW*(rX6`|jt(bKDf)zWyVr5-?! zaV&E%VK}tun4^;CM2-!!7AA1m<+ZYU8mM$g^vZdgZ{qdPVL#ZZThgr6)a)uHBCzDJ t?!|-^9SH}RehL_Na!72L?$FQYY@WfPZ^)9y8l&0Wqo&AU4N9J1000Q&6mS3l literal 0 HcmV?d00001 diff --git a/ui/new/images/gridheader_loadingbg.gif b/ui/new/images/gridheader_loadingbg.gif new file mode 100644 index 0000000000000000000000000000000000000000..6cb13eabcf234a2057d45fa813794c95543bfed0 GIT binary patch literal 130 zcmV-|0Db>QNk%w1VF&;b0J8u9nX<#V&D*ug*s;ddp0>uJxyilI-J7(UjO3V{ kr*kq2tGrCJ$n&xkc#ac%&mX`b5I`&%kI1BQS&RSxJ3^2@ZvX%Q literal 0 HcmV?d00001 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 @@
- + + +
From 93261c4eb8d075d7b80df74256771ed9e2254944 Mon Sep 17 00:00:00 2001 From: abhishek Date: Fri, 10 Sep 2010 13:43:37 -0700 Subject: [PATCH 3/8] bug 5147: Improvements after testing the storage maintenance across multiple sp's, with sys vms scattered across multiple sps --- core/src/com/cloud/storage/dao/StoragePoolDao.java | 2 ++ .../com/cloud/storage/dao/StoragePoolDaoImpl.java | 12 ++++++++++++ .../src/com/cloud/api/commands/CreateVolumeCmd.java | 3 ++- .../src/com/cloud/server/ManagementServerImpl.java | 7 ++++++- server/src/com/cloud/storage/StorageManagerImpl.java | 10 ++++++---- 5 files changed, 28 insertions(+), 6 deletions(-) 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/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index e826a2edc9d..c12c146badf 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -8722,7 +8722,12 @@ public class ManagementServerImpl implements ManagementServer { @Override public long getPsMaintenanceCount(long podId){ - return _poolDao.countBy(podId, Status.Maintenance); + List poolsInMaintenance = _poolDao.listPoolsByStatus(Status.Maintenance); + + if(poolsInMaintenance==null) + return 0; + else + return poolsInMaintenance.size(); } } 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 From f74d4f89df4139d6039f7c511ef89a3f52f3b76e Mon Sep 17 00:00:00 2001 From: NIKITA Date: Fri, 10 Sep 2010 14:32:58 -0700 Subject: [PATCH 4/8] Icons for Midmenu Account, Event and Network --- ...menuicon.png => midmenuicon_account_admin.png} | Bin ...enuicon.png => midmenuicon_account_domain.png} | Bin ...dmenuicon.png => midmenuicon_account_user.png} | Bin ...dmenuicon.png => midmenuicon_events_error.png} | Bin ...idmenuicon.png => midmenuicon_events_info.png} | Bin ...enuicon.png => midmenuicon_events_warning.png} | Bin .../images/midmenuicon_network_networkgroup.png | Bin 0 -> 542 bytes 7 files changed, 0 insertions(+), 0 deletions(-) rename ui/new/images/{account_admin_midmenuicon.png => midmenuicon_account_admin.png} (100%) rename ui/new/images/{account_domain_midmenuicon.png => midmenuicon_account_domain.png} (100%) rename ui/new/images/{account_user_midmenuicon.png => midmenuicon_account_user.png} (100%) rename ui/new/images/{events_error_midmenuicon.png => midmenuicon_events_error.png} (100%) rename ui/new/images/{events_info_midmenuicon.png => midmenuicon_events_info.png} (100%) rename ui/new/images/{events_warning_midmenuicon.png => midmenuicon_events_warning.png} (100%) create mode 100644 ui/new/images/midmenuicon_network_networkgroup.png 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 0000000000000000000000000000000000000000..2107efa20380c0cc573dadb5c3e6ff83b3d9c84e GIT binary patch literal 542 zcmV+(0^$9MP)&-eTU z1M2JM>pLnbL&ewM*6!`+Bo-AB^8t8;isZ%C*&FKU>HyfhvH=MpE&n(?IspIp_5cC^ zeE@?00m;hC|J>W$0532v;{gBw9lX7}03jeE00i>?3D*P>6eR2R_6r*p7SKRTRRikl z=Ia3lLRkML6b%3t2?+o$Bq0FJ;pqV3 Date: Fri, 10 Sep 2010 14:39:39 -0700 Subject: [PATCH 5/8] bug 5147: implemented the logic to ensure that the volume creation is blocked when all sp's are in maintenance (or any of the status != UP) --- .../com/cloud/server/ManagementServer.java | 1 + .../com/cloud/api/commands/StartVMCmd.java | 5 +++- .../cloud/server/ManagementServerImpl.java | 27 +++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) 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/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 c12c146badf..66b5518dfa6 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 @@ -8729,5 +8740,21 @@ public class ManagementServerImpl implements ManagementServer { else return poolsInMaintenance.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; + } } From c88962627809a3e356262c2e00b705f55f6828c5 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Fri, 10 Sep 2010 14:45:04 -0700 Subject: [PATCH 6/8] new UI - handle error in a central place for actions on midmenu items. --- ui/new/scripts/cloud.core2.init.js | 24 ++++---- ui/new/scripts/cloud.core2.instance.js | 58 +++++++++---------- ui/new/scripts/cloud.core2.js | 77 +++++++++++--------------- 3 files changed, 74 insertions(+), 85 deletions(-) diff --git a/ui/new/scripts/cloud.core2.init.js b/ui/new/scripts/cloud.core2.init.js index c31824a41c6..138a31d9e97 100644 --- a/ui/new/scripts/cloud.core2.init.js +++ b/ui/new/scripts/cloud.core2.init.js @@ -19,23 +19,23 @@ $(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"); } } } diff --git a/ui/new/scripts/cloud.core2.instance.js b/ui/new/scripts/cloud.core2.instance.js index f85aadcf76a..673abffdbf5 100644 --- a/ui/new/scripts/cloud.core2.instance.js +++ b/ui/new/scripts/cloud.core2.instance.js @@ -98,7 +98,7 @@ function clickInstanceGroupHeader($arrowIcon) { } } - function doAttachISO($t, selectedItemIds, vmListAPIMap) { + function doAttachISO($t, selectedItemsInMidMenu, vmListAPIMap) { $.ajax({ data: createURL("command=listIsos&isReady=true"), dataType: "json", @@ -125,9 +125,9 @@ function clickInstanceGroupHeader($arrowIcon) { $("#dialog_alert").dialog("open"); return false; } - for(var id in selectedItemIds) { + for(var id in selectedItemsInMidMenu) { var apiCommand = "command=attachIso&virtualmachineid="+id+"&id="+isoId; - doAction(id, $t, apiCommand, vmListAPIMap); + doActionForMidMenu(id, $t, apiCommand, vmListAPIMap); } }, "Cancel": function() { @@ -136,15 +136,15 @@ function clickInstanceGroupHeader($arrowIcon) { }).dialog("open"); } - function doDetachISO($t, selectedItemIds, vmListAPIMap) { + function doDetachISO($t, selectedItemsInMidMenu, vmListAPIMap) { $("#dialog_confirmation") .html("

Please 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 +153,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 +173,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 +182,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 +196,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 +207,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 +231,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 +240,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 +249,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 +261,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 +275,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 +283,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 +296,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 +304,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() { diff --git a/ui/new/scripts/cloud.core2.js b/ui/new/scripts/cloud.core2.js index 75a548c1519..0354df139d4 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,38 @@ 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) { + debugger; + $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; } From ec01e0b42306d7099ad9db8ab5f7eb6b48ac858f Mon Sep 17 00:00:00 2001 From: abhishek Date: Fri, 10 Sep 2010 14:50:47 -0700 Subject: [PATCH 7/8] bug 5147: this checkin ensures that we cover some more corner cases, in particular, to not allow an execution when we have pools in inconsistent states (maintenance, prepareformaintenance or errorinmaintenance) --- .../commands/PreparePrimaryStorageForMaintenanceCmd.java | 2 +- server/src/com/cloud/server/ManagementServerImpl.java | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) 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/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 66b5518dfa6..4ecb921ebc9 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -8733,12 +8733,15 @@ public class ManagementServerImpl implements ManagementServer { @Override public long getPsMaintenanceCount(long podId){ - List poolsInMaintenance = _poolDao.listPoolsByStatus(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(poolsInMaintenance==null) + if(poolsInTransition==null) return 0; else - return poolsInMaintenance.size(); + return poolsInTransition.size(); } @Override From d341d1ab64d4d7a8a01ac4f7933914b11da6c008 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Fri, 10 Sep 2010 15:10:39 -0700 Subject: [PATCH 8/8] new UI - clear selected items when switching to different page or sub-page. --- ui/new/scripts/cloud.core2.init.js | 16 +++++----------- ui/new/scripts/cloud.core2.instance.js | 20 +++++++------------- ui/new/scripts/cloud.core2.js | 1 - 3 files changed, 12 insertions(+), 25 deletions(-) diff --git a/ui/new/scripts/cloud.core2.init.js b/ui/new/scripts/cloud.core2.init.js index 138a31d9e97..e2d12c5e167 100644 --- a/ui/new/scripts/cloud.core2.init.js +++ b/ui/new/scripts/cloud.core2.init.js @@ -40,15 +40,7 @@ $(document).ready(function() { } } }); - - 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; i0) { - 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() { diff --git a/ui/new/scripts/cloud.core2.js b/ui/new/scripts/cloud.core2.js index 0354df139d4..2ef6d2858f8 100644 --- a/ui/new/scripts/cloud.core2.js +++ b/ui/new/scripts/cloud.core2.js @@ -163,7 +163,6 @@ function doActionForMidMenu(id, $actionLink, apiCommand, listAPIMap) { } function handleErrorInMidMenu(XMLHttpResponse, $midmenuItem) { - debugger; $midmenuItem.find("#content").removeClass("inaction"); $midmenuItem.find("#spinning_wheel").hide(); $midmenuItem.find("#info_icon").addClass("error").show();