From bb44208ae3c2b536a516519da51e30bb2a752df2 Mon Sep 17 00:00:00 2001 From: anthony Date: Tue, 13 Sep 2011 22:07:54 -0700 Subject: [PATCH] bug 11275: remove heartbeat entry for this Primary Storage, when put this Primary Storage into maintenance mode create heartbeat entry for this Primary Storage, when cancal maintenance for this Primary Storage status 11275: resolved fixed --- .../xen/resource/CitrixResourceBase.java | 63 ++++++++++------ .../xenserver/setup_heartbeat_file.sh | 72 +++++++++++-------- scripts/vm/hypervisor/xenserver/vmopspremium | 3 +- server/src/com/cloud/host/dao/HostDao.java | 4 +- .../src/com/cloud/host/dao/HostDaoImpl.java | 23 ++++-- .../com/cloud/storage/StorageManagerImpl.java | 47 ++++++++++-- 6 files changed, 152 insertions(+), 60 deletions(-) diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 85f0eb5527e..e5805d689c6 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -4484,7 +4484,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return callHostPlugin(conn, "vmopspremium", cmd, params); } - protected String setupHeartbeatSr(Connection conn, SR sr, boolean force) throws XenAPIException, XmlRpcException { SR.Record srRec = sr.getRecord(conn); String srUuid = srRec.uuid; @@ -4517,7 +4516,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe host.setTags(conn, tags); } } - result = callHostPluginPremium(conn, "setup_heartbeat_file", "host", _host.uuid, "sr", srUuid); + result = callHostPluginPremium(conn, "setup_heartbeat_file", "host", _host.uuid, "sr", srUuid, "add", "true"); if (result == null || !result.split("#")[1].equals("0")) { throw new CloudRuntimeException("Unable to setup heartbeat file entry on SR " + srUuid + " due to " + result); @@ -4528,27 +4527,49 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected Answer execute(ModifyStoragePoolCommand cmd) { Connection conn = getConnection(); StorageFilerTO pool = cmd.getPool(); - try { - SR sr = getStorageRepository(conn, pool); - setupHeartbeatSr(conn, sr, false); - long capacity = sr.getPhysicalSize(conn); - long available = capacity - sr.getPhysicalUtilisation(conn); - if (capacity == -1) { - String msg = "Pool capacity is -1! pool: " + pool.getHost() + pool.getPath(); - s_logger.warn(msg); + boolean add = cmd.getAdd(); + if( add ) { + try { + SR sr = getStorageRepository(conn, pool); + setupHeartbeatSr(conn, sr, false); + long capacity = sr.getPhysicalSize(conn); + long available = capacity - sr.getPhysicalUtilisation(conn); + if (capacity == -1) { + String msg = "Pool capacity is -1! pool: " + pool.getHost() + pool.getPath(); + s_logger.warn(msg); + return new Answer(cmd, false, msg); + } + Map tInfo = new HashMap(); + ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, capacity, available, tInfo); + return answer; + } catch (XenAPIException e) { + String msg = "ModifyStoragePoolCommand add XenAPIException:" + e.toString() + " host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } catch (Exception e) { + String msg = "ModifyStoragePoolCommand add XenAPIException:" + e.getMessage() + " host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } + } else { + try { + SR sr = getStorageRepository(conn, pool); + String srUuid = sr.getUuid(conn); + String result = callHostPluginPremium(conn, "setup_heartbeat_file", "host", _host.uuid, "sr", srUuid, "add", "false"); + if (result == null || !result.split("#")[1].equals("0")) { + throw new CloudRuntimeException("Unable to remove heartbeat file entry for SR " + srUuid + " due to " + + result); + } + return new Answer(cmd, true , "seccuss"); + } catch (XenAPIException e) { + String msg = "ModifyStoragePoolCommand remove XenAPIException:" + e.toString() + " host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } catch (Exception e) { + String msg = "ModifyStoragePoolCommand remove XenAPIException:" + e.getMessage() + " host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath(); + s_logger.warn(msg, e); return new Answer(cmd, false, msg); } - Map tInfo = new HashMap(); - ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, capacity, available, tInfo); - return answer; - } catch (XenAPIException e) { - String msg = "ModifyStoragePoolCommand XenAPIException:" + e.toString() + " host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath(); - s_logger.warn(msg, e); - return new Answer(cmd, false, msg); - } catch (Exception e) { - String msg = "ModifyStoragePoolCommand XenAPIException:" + e.getMessage() + " host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath(); - s_logger.warn(msg, e); - return new Answer(cmd, false, msg); } } diff --git a/scripts/vm/hypervisor/xenserver/setup_heartbeat_file.sh b/scripts/vm/hypervisor/xenserver/setup_heartbeat_file.sh index b606d7efe6d..adc4bc13f2f 100755 --- a/scripts/vm/hypervisor/xenserver/setup_heartbeat_file.sh +++ b/scripts/vm/hypervisor/xenserver/setup_heartbeat_file.sh @@ -4,7 +4,7 @@ #set -x usage() { - printf "Usage: %s [uuid of this host] [uuid of the sr to place the heartbeat]\n" $(basename $0) + printf "Usage: %s [uuid of this host] [uuid of the sr to place the heartbeat] [ add , true/false]\n" $(basename $0) } @@ -21,6 +21,13 @@ if [ -z $2 ]; then exit 0 fi +if [ -z $3 ]; then + usage + echo "#21# no add parameter" + exit 0 +fi + + if [ `xe host-list | grep $1 | wc -l` -ne 1 ]; then echo "#3# Unable to find the host uuid: $1" exit 0 @@ -36,38 +43,47 @@ if [ `xe pbd-list sr-uuid=$2 | grep -B 1 $1 | wc -l` -eq 0 ]; then exit 0 fi -srtype=`xe sr-param-get param-name=type uuid=$2` - - -if [ "$srtype" = "nfs" ];then - dir=/var/run/sr-mount/$2 - filename=$dir/hb-$1 - if [ ! -f "$filename" ]; then - echo "#6# heartbeat file $filename doesn't exist" - exit 0 - fi -else - dir=/dev/VG_XenStorage-$2 - link=$dir/hb-$1 - lvchange -ay $link - if [ $? -ne 0 ]; then - echo "#7# Unable to make the heartbeat $link active" - exit 0 - fi -fi - hbfile=/opt/xensource/bin/heartbeat -if [ -f $hbfile ]; then - grep $dir $hbfile >/dev/null - if [ $? -gt 0 ] - then +if [ "$3" = "true" ]; then + + srtype=`xe sr-param-get param-name=type uuid=$2` + + + if [ "$srtype" = "nfs" ];then + dir=/var/run/sr-mount/$2 + filename=$dir/hb-$1 + if [ ! -f "$filename" ]; then + echo "#6# heartbeat file $filename doesn't exist" + exit 0 + fi + else + dir=/dev/VG_XenStorage-$2 + link=$dir/hb-$1 + lvchange -ay $link + if [ $? -ne 0 ]; then + echo "#7# Unable to make the heartbeat $link active" + exit 0 + fi + fi + + + if [ -f $hbfile ]; then + grep $dir $hbfile >/dev/null + if [ $? -gt 0 ] + then + echo $dir >> $hbfile + fi + else echo $dir >> $hbfile fi -else - echo $dir >> $hbfile + +else + if [ -f $hbfile ]; then + sed -i /$2/d $hbfile + fi fi - + echo "#0#DONE" exit 0 diff --git a/scripts/vm/hypervisor/xenserver/vmopspremium b/scripts/vm/hypervisor/xenserver/vmopspremium index d2f100e3fc7..07f2a6007ee 100755 --- a/scripts/vm/hypervisor/xenserver/vmopspremium +++ b/scripts/vm/hypervisor/xenserver/vmopspremium @@ -89,8 +89,9 @@ def setup_heartbeat_sr(session, args): def setup_heartbeat_file(session, args): host = args['host'] sr = args['sr'] + add = args['add'] try: - cmd = ["bash", "/opt/xensource/bin/setup_heartbeat_file.sh", host, sr] + cmd = ["bash", "/opt/xensource/bin/setup_heartbeat_file.sh", host, sr, add] txt = util.pread2(cmd) except: txt = '' diff --git a/server/src/com/cloud/host/dao/HostDao.java b/server/src/com/cloud/host/dao/HostDao.java index 3551735aa6e..6dba59a2904 100755 --- a/server/src/com/cloud/host/dao/HostDao.java +++ b/server/src/com/cloud/host/dao/HostDao.java @@ -176,5 +176,7 @@ public interface HostDao extends GenericDao { List findAndUpdateApplianceToLoad(long lastPingSecondsAfter, long managementServerId); - List listByInAllStatus(Type type, Long clusterId, Long podId, long dcId); + List listByInAllStatus(Type type, Long clusterId, Long podId, long dcId); + + List listByClusterStatus(long clusterId, Status status); } diff --git a/server/src/com/cloud/host/dao/HostDaoImpl.java b/server/src/com/cloud/host/dao/HostDaoImpl.java index c18331e6881..e4e9ab3f540 100755 --- a/server/src/com/cloud/host/dao/HostDaoImpl.java +++ b/server/src/com/cloud/host/dao/HostDaoImpl.java @@ -89,7 +89,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao protected final SearchBuilder UnmanagedDirectConnectSearch; protected final SearchBuilder UnmanagedApplianceSearch; protected final SearchBuilder MaintenanceCountSearch; - protected final SearchBuilder ClusterSearch; + protected final SearchBuilder ClusterStatusSearch; protected final SearchBuilder ConsoleProxyHostSearch; protected final SearchBuilder AvailHypevisorInZone; @@ -178,9 +178,10 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao DcSearch.and("dc", DcSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); DcSearch.done(); - ClusterSearch = createSearchBuilder(); - ClusterSearch.and("cluster", ClusterSearch.entity().getClusterId(), SearchCriteria.Op.EQ); - ClusterSearch.done(); + ClusterStatusSearch = createSearchBuilder(); + ClusterStatusSearch.and("cluster", ClusterStatusSearch.entity().getClusterId(), SearchCriteria.Op.EQ); + ClusterStatusSearch.and("status", ClusterStatusSearch.entity().getStatus(), SearchCriteria.Op.EQ); + ClusterStatusSearch.done(); ConsoleProxyHostSearch = createSearchBuilder(); ConsoleProxyHostSearch.and("name", ConsoleProxyHostSearch.entity().getName(), SearchCriteria.Op.EQ); @@ -515,12 +516,24 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao @Override public List listByCluster(long clusterId) { - SearchCriteria sc = ClusterSearch.create(); + SearchCriteria sc = ClusterStatusSearch.create(); sc.setParameters("cluster", clusterId); return listBy(sc); } + + + @Override + public List listByClusterStatus(long clusterId, Status status) { + SearchCriteria sc = ClusterStatusSearch.create(); + + sc.setParameters("cluster", clusterId); + sc.setParameters("status", status.toString()); + + return listBy(sc); + } + @Override public List listBy(Host.Type type, long dcId) { diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 339cfffcff4..f25196d9821 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -2067,10 +2067,31 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag throw new InvalidParameterValueException("Primary storage with id " + primaryStorageId + " is not ready for migration, as the status is:" + primaryStorage.getStatus().toString()); } - // set the pool state to prepare for maintenance - primaryStorage.setStatus(StoragePoolStatus.PrepareForMaintenance); - _storagePoolDao.update(primaryStorageId, primaryStorage); - + + List hosts = _hostDao.listByClusterStatus(primaryStorage.getClusterId(), Status.Up); + if( hosts == null || hosts.size() == 0 ) { + primaryStorage.setStatus(StoragePoolStatus.Maintenance); + _storagePoolDao.update(primaryStorageId, primaryStorage); + return _storagePoolDao.findById(primaryStorageId); + } else { + // set the pool state to prepare for maintenance + primaryStorage.setStatus(StoragePoolStatus.PrepareForMaintenance); + _storagePoolDao.update(primaryStorageId, primaryStorage); + } + // remove heartbeat + for ( HostVO host : hosts ) { + ModifyStoragePoolCommand cmd = new ModifyStoragePoolCommand(false, primaryStorage); + final Answer answer = _agentMgr.easySend(host.getId(), cmd); + if (answer == null || !answer.getResult()) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("ModifyStoragePool false failed due to " + ((answer == null) ? "answer null" : answer.getDetails())); + } + } else { + if (s_logger.isDebugEnabled()) { + s_logger.debug("ModifyStoragePool false secceeded"); + } + } + } // 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 @@ -2279,6 +2300,24 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag primaryStorage.setStatus(StoragePoolStatus.Up); _storagePoolDao.update(primaryStorageId, primaryStorage); txn.commit(); + List hosts = _hostDao.listByClusterStatus(primaryStorage.getClusterId(), Status.Up); + if( hosts == null || hosts.size() == 0 ) { + return _storagePoolDao.findById(primaryStorageId); + } + // add heartbeat + for ( HostVO host : hosts ) { + ModifyStoragePoolCommand msPoolCmd = new ModifyStoragePoolCommand(true, primaryStorage); + final Answer answer = _agentMgr.easySend(host.getId(), msPoolCmd); + if (answer == null || !answer.getResult()) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("ModifyStoragePool add failed due to " + ((answer == null) ? "answer null" : answer.getDetails())); + } + } else { + if (s_logger.isDebugEnabled()) { + s_logger.debug("ModifyStoragePool add secceeded"); + } + } + } // 2. Get a list of pending work for this queue List pendingWork = _storagePoolWorkDao.listPendingWorkForCancelMaintenanceByPoolId(primaryStorageId);