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);