From d6cbd2b6bca090434d239d745c1cb2c55662215a 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 361a2138123..9be47884691 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -4551,7 +4551,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; @@ -4584,7 +4583,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); @@ -4595,27 +4594,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 351d22ee110..fa5733e8897 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; @@ -177,9 +177,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 bf0341100b0..cd2054bda95 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -2066,10 +2066,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 @@ -2278,6 +2299,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);