From e8a587265532b1540a94cbac1edec72c1445034b Mon Sep 17 00:00:00 2001 From: anthony Date: Thu, 30 Sep 2010 19:02:17 -0700 Subject: [PATCH] bug 6363: 1. delete local storage when delete host 2. delete host detail when delete host 3. allow one host in maintance mode in a cluster instead of in a pod status 6363: resolved fixed --- core/src/com/cloud/host/dao/DetailsDao.java | 2 + .../com/cloud/host/dao/DetailsDaoImpl.java | 11 ++++ core/src/com/cloud/host/dao/HostDao.java | 2 +- core/src/com/cloud/host/dao/HostDaoImpl.java | 15 ++---- .../xen/resource/CitrixResourceBase.java | 46 +++++++++++----- core/src/com/cloud/storage/StoragePoolVO.java | 2 +- .../cloud/storage/dao/StoragePoolDaoImpl.java | 2 +- .../cloud/agent/manager/AgentManagerImpl.java | 40 ++++++++------ .../xen/discoverer/XcpServerDiscoverer.java | 54 ++++++++++++------- .../cloud/server/ManagementServerImpl.java | 2 +- setup/db/create-schema.sql | 2 +- 11 files changed, 115 insertions(+), 63 deletions(-) diff --git a/core/src/com/cloud/host/dao/DetailsDao.java b/core/src/com/cloud/host/dao/DetailsDao.java index 26e17d50902..e398f353887 100644 --- a/core/src/com/cloud/host/dao/DetailsDao.java +++ b/core/src/com/cloud/host/dao/DetailsDao.java @@ -28,4 +28,6 @@ public interface DetailsDao extends GenericDao { void persist(long hostId, Map details); DetailVO findDetail(long hostId, String name); + + void deleteDetails(long hostId); } diff --git a/core/src/com/cloud/host/dao/DetailsDaoImpl.java b/core/src/com/cloud/host/dao/DetailsDaoImpl.java index d624d1d9d3d..b10bd048fc6 100644 --- a/core/src/com/cloud/host/dao/DetailsDaoImpl.java +++ b/core/src/com/cloud/host/dao/DetailsDaoImpl.java @@ -66,6 +66,17 @@ public class DetailsDaoImpl extends GenericDaoBase implements De } return details; } + + @Override + public void deleteDetails(long hostId) { + SearchCriteria sc = HostSearch.create(); + sc.setParameters("hostId", hostId); + + List results = search(sc, null); + for (DetailVO result : results) { + delete(result.getId()); + } + } @Override public void persist(long hostId, Map details) { diff --git a/core/src/com/cloud/host/dao/HostDao.java b/core/src/com/cloud/host/dao/HostDao.java index 6bccaa4a4ea..78eeea89bfb 100644 --- a/core/src/com/cloud/host/dao/HostDao.java +++ b/core/src/com/cloud/host/dao/HostDao.java @@ -35,7 +35,7 @@ import com.cloud.utils.db.GenericDao; public interface HostDao extends GenericDao { List listBy(Host.Type type, Long clusterId, Long podId, long dcId); - long countBy(long podId, Status... statuses); + long countBy(long clusterId, Status... statuses); List listByDataCenter(long dcId); List listByHostPod(long podId); diff --git a/core/src/com/cloud/host/dao/HostDaoImpl.java b/core/src/com/cloud/host/dao/HostDaoImpl.java index 9368812718f..21f6512940f 100644 --- a/core/src/com/cloud/host/dao/HostDaoImpl.java +++ b/core/src/com/cloud/host/dao/HostDaoImpl.java @@ -91,8 +91,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao _vmHostDao = ComponentLocator.inject(VmHostDaoImpl.class); MaintenanceCountSearch = createSearchBuilder(); - MaintenanceCountSearch.and("pod", MaintenanceCountSearch.entity().getPodId(), SearchCriteria.Op.EQ); - MaintenanceCountSearch.select(Func.COUNT); + MaintenanceCountSearch.and("cluster", MaintenanceCountSearch.entity().getClusterId(), SearchCriteria.Op.EQ); MaintenanceCountSearch.and("status", MaintenanceCountSearch.entity().getStatus(), SearchCriteria.Op.IN); MaintenanceCountSearch.done(); @@ -203,18 +202,14 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao } @Override - public long countBy(long podId, Status... statuses) { + public long countBy(long clusterId, Status... statuses) { SearchCriteria sc = MaintenanceCountSearch.create(); sc.setParameters("status", (Object[])statuses); - sc.setParameters("pod", podId); + sc.setParameters("cluster", clusterId); - List rs = searchAll(sc, null); - if (rs.size() == 0) { - return 0; - } - - return (Long)(rs.get(0)[0]); + List hosts = listActiveBy(sc); + return hosts.size(); } @Override diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 11bc37a1d2e..b37bfc9f36b 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -2210,15 +2210,19 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR } public boolean joinPool(String masterIp, String username, String password) { - Connection slaveConn = null; + Connection hostConn = null; Connection poolConn = null; - Session slaveSession = null; - URL slaveUrl = null; + Session hostSession = null; + URL hostUrl = null; try { // Connect and find out about the new connection to the new pool. poolConn = _connPool.masterConnect(masterIp, username, password); + Set pools = Pool.getAll(poolConn); + Pool pool = pools.iterator().next(); + String poolUUID = pool.getUuid(poolConn); + //check if this host is already in pool Set hosts = Host.getAll(poolConn); for( Host host : hosts ) { @@ -2227,13 +2231,13 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR } } - slaveUrl = new URL("http://" + _host.ip); - slaveConn = new Connection(slaveUrl, 100); - slaveSession = Session.slaveLocalLoginWithPassword(slaveConn, _username, _password); + hostUrl = new URL("http://" + _host.ip); + hostConn = new Connection(hostUrl, 100); + hostSession = Session.loginWithPassword(hostConn, _username, _password, APIVersion.latest().toString()); // Now join it. - Pool.join(slaveConn, masterIp, username, password); + Pool.join(hostConn, masterIp, username, password); if (s_logger.isDebugEnabled()) { s_logger.debug("Joined the pool at " + masterIp); } @@ -2245,12 +2249,13 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR } // check if the master of this host is set correctly. - Connection c = new Connection(slaveUrl, 100); - for (int i = 0; i < 15; i++) { + Connection c = new Connection(hostUrl, 100); + int i; + for (i = 0 ; i < 15; i++) { try { Session.loginWithPassword(c, _username, _password, APIVersion.latest().toString()); - s_logger.debug("Still waiting for the conversion to the master"); + s_logger.debug(_host.ip + " is still master, waiting for the conversion to the slave"); Session.logout(c); c.dispose(); } catch (Types.HostIsSlave e) { @@ -2273,7 +2278,10 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR } catch (InterruptedException e) { } } - + if( i >= 15 ) { + throw new CloudRuntimeException(_host.ip + " didn't change to slave after waiting 30 secondary"); + } + _host.pool = poolUUID; return true; } catch (MalformedURLException e) { throw new CloudRuntimeException("Problem with url " + _host.ip); @@ -2295,9 +2303,9 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR } poolConn.dispose(); } - if(slaveSession != null) { + if(hostSession != null) { try { - Session.localLogout(slaveConn); + Session.logout(hostConn); } catch (Exception e) { } } @@ -6052,7 +6060,19 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR private Answer execute(PoolEjectCommand cmd) { Connection conn = getConnection(); String hostuuid = cmd.getHostuuid(); + try { + Map hostrs = Host.getAllRecords(conn); + boolean found = false; + for( Host.Record hr : hostrs.values() ) { + if( hr.uuid.equals(hostuuid)) { + found = true; + } + } + if( ! found) { + s_logger.debug("host " + hostuuid + " has already been ejected from pool " + _host.pool); + return new Answer(cmd); + } Host host = Host.getByUuid(conn, hostuuid); Pool.eject(conn, host); return new Answer(cmd); diff --git a/core/src/com/cloud/storage/StoragePoolVO.java b/core/src/com/cloud/storage/StoragePoolVO.java index 3aa9fcb4c5e..52087df43fe 100644 --- a/core/src/com/cloud/storage/StoragePoolVO.java +++ b/core/src/com/cloud/storage/StoragePoolVO.java @@ -48,7 +48,7 @@ public class StoragePoolVO implements StoragePool { @Column(name="name", updatable=false, nullable=false, length=255) private String name = null; - @Column(name="uuid", updatable=false, nullable=false, length=255) + @Column(name="uuid", length=255) private String uuid = null; @Column(name="pool_type", updatable=false, nullable=false, length=32) diff --git a/core/src/com/cloud/storage/dao/StoragePoolDaoImpl.java b/core/src/com/cloud/storage/dao/StoragePoolDaoImpl.java index 9a334d74f57..f8a3dafb121 100644 --- a/core/src/com/cloud/storage/dao/StoragePoolDaoImpl.java +++ b/core/src/com/cloud/storage/dao/StoragePoolDaoImpl.java @@ -173,7 +173,7 @@ public class StoragePoolDaoImpl extends GenericDaoBase imp sc.setParameters("datacenterId", datacenterId); sc.setParameters("podId", podId); - return findOneBy(sc); + return findOneActiveBy(sc); } @Override diff --git a/server/src/com/cloud/agent/manager/AgentManagerImpl.java b/server/src/com/cloud/agent/manager/AgentManagerImpl.java index aa9de6f4164..682353c455e 100755 --- a/server/src/com/cloud/agent/manager/AgentManagerImpl.java +++ b/server/src/com/cloud/agent/manager/AgentManagerImpl.java @@ -517,39 +517,43 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory { if (host.getType() == Type.Routing && host.getHypervisorType() == Hypervisor.Type.XenServer ) { if (host.getClusterId() != null) { List hosts = _hostDao.listBy(Type.Routing, host.getClusterId(), host.getPodId(), host.getDataCenterId()); + boolean success = false; for( HostVO thost: hosts ) { long thostId = thost.getId(); if( thostId == hostId ) continue; PoolEjectCommand eject = new PoolEjectCommand(host.getGuid()); Answer answer = easySend(thostId, eject); - if( answer == null || !answer.getResult()) { + if( answer != null && answer.getResult()) { + s_logger.debug("Eject Host: " + hostId + " from " + thostId + " Succeed"); + success = true; + break; + + } else { s_logger.debug("Eject Host: " + hostId + " from " + thostId + " failed due to " + (answer != null ? answer.getDetails() : "no answer")); - continue; } - break; + } + if( !success ){ + throw new CloudRuntimeException("Unable to delete host " + hostId + " due to unable to eject it from pool"); + } } } txn.start(); - + _dcDao.releasePrivateIpAddress(host.getPrivateIpAddress(), host.getDataCenterId(), null); AgentAttache attache = _agents.get(hostId); handleDisconnect(attache, Status.Event.Remove, false); /*Disconnected agent needs special handling here*/ - host.setGuid(null); - host.setClusterId(null); - _hostDao.update(host.getId(), host); + //delete host details + _hostDetailsDao.deleteDetails(hostId); + host.setGuid(null); + host.setClusterId(null); + _hostDao.update(host.getId(), host); _hostDao.remove(hostId); - //delete the associated primary storage from db - ComponentLocator locator = ComponentLocator.getLocator("management-server"); - _storagePoolHostDao = locator.getDao(StoragePoolHostDao.class); - if (_storagePoolHostDao == null) { - throw new ConfigurationException("Unable to get storage pool host dao: " + StoragePoolHostDao.class); - } //1. Get the pool_ids from the host ref table ArrayList pool_ids = _storagePoolHostDao.getPoolIds(hostId); @@ -557,8 +561,14 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory { _storagePoolHostDao.deletePrimaryRecordsForHost(hostId); //3.For pool ids you got, delete entries in pool table where type='FileSystem' || 'LVM' - if(!pool_ids.isEmpty()) { - _storagePoolDao.deleteStoragePoolRecords(pool_ids); + for( Long poolId : pool_ids) { + StoragePoolVO storagePool = _storagePoolDao.findById(poolId); + if( storagePool.isLocal()) { + storagePool.setUuid(null); + storagePool.setClusterId(null); + _storagePoolDao.update(poolId, storagePool); + _storagePoolDao.remove(poolId); + } } txn.commit(); return true; diff --git a/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java b/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java index 504dce37f6d..f5813d3a5a3 100644 --- a/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java +++ b/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java @@ -102,14 +102,38 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L public Map> find(long dcId, Long podId, Long clusterId, URI url, String username, String password) throws DiscoveryException { Map> resources = new HashMap>(); Connection conn = null; - Connection slaveConn = null; if (!url.getScheme().equals("http")) { String msg = "urlString is not http so we're not taking care of the discovery for this: " + url; s_logger.debug(msg); return null; } - try { + String cluster = null; + if (clusterId == null) { + String msg = "must specify cluster Id when add host"; + s_logger.debug(msg); + throw new RuntimeException(msg); + } else { + cluster = Long.toString(clusterId); + } + + String pod; + if (podId == null) { + String msg = "must specify pod Id when add host"; + s_logger.debug(msg); + throw new RuntimeException(msg); + } else { + pod = Long.toString(podId); + } + try { + String poolUuid = null; + List eHosts = _hostDao.listByCluster(clusterId); + if( eHosts.size() > 0 ) { + HostVO eHost = eHosts.get(0); + _hostDao.loadDetails(eHost); + poolUuid = eHost.getDetail("pool"); + } + String hostname = url.getHost(); InetAddress ia = InetAddress.getByName(hostname); String addr = ia.getHostAddress(); @@ -121,26 +145,14 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L s_logger.debug(msg); throw new RuntimeException(msg); } - - String pod; - if (podId == null) { - Map pools = Pool.getAllRecords(conn); - assert pools.size() == 1 : "Pools are not one....where on earth have i been? " + pools.size(); - - pod = pools.values().iterator().next().uuid; - } else { - pod = Long.toString(podId); + if( poolUuid == null ) { + Set pools = Pool.getAll(conn); + Pool pool = pools.iterator().next(); + Pool.Record pr = pool.getRecord(conn); + poolUuid = pr.uuid; } - String cluster = null; - if (clusterId != null) { - cluster = Long.toString(clusterId); - } - Set pools = Pool.getAll(conn); - Pool pool = pools.iterator().next(); - Pool.Record pr = pool.getRecord(conn); - String poolUuid = pr.uuid; + Map hosts = Host.getAllRecords(conn); - Host master = pr.master; if (_checkHvm) { for (Map.Entry entry : hosts.entrySet()) { @@ -192,6 +204,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L params.put("zone", Long.toString(dcId)); params.put("guid", record.uuid); params.put("pod", pod); + params.put("cluster", cluster); if (_increase != null) { params.put(Config.XenPreallocatedLunSizeRange.name(), _increase); @@ -393,6 +406,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L throw new DiscoveryException("Unable to join the pool"); } + return true; } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 9fa2762d1ac..e6b4584b8ff 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -671,7 +671,7 @@ public class ManagementServerImpl implements ManagementServer { throw new InvalidParameterValueException("Unable to find host with ID: " + hostId + ". Please specify a valid host ID."); } - if (_hostDao.countBy(host.getPodId(), Status.PrepareForMaintenance, Status.ErrorInMaintenance, Status.Maintenance) > 0) { + if (_hostDao.countBy(host.getClusterId(), Status.PrepareForMaintenance, Status.ErrorInMaintenance, Status.Maintenance) > 0) { throw new InvalidParameterValueException("There are other servers in maintenance mode."); } diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index ddc98126274..a533ab41bc7 100644 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -834,7 +834,7 @@ CREATE TABLE `cloud`.`load_balancer` ( CREATE TABLE `cloud`.`storage_pool` ( `id` bigint unsigned UNIQUE NOT NULL, `name` varchar(255) COMMENT 'should be NOT NULL', - `uuid` varchar(255) UNIQUE NOT NULL, + `uuid` varchar(255) UNIQUE, `pool_type` varchar(32) NOT NULL, `port` int unsigned NOT NULL, `data_center_id` bigint unsigned NOT NULL,