From 0633608f8035f8f409c271fc6e7548699a63d366 Mon Sep 17 00:00:00 2001 From: frank Date: Fri, 19 Jul 2013 16:15:17 -0700 Subject: [PATCH] CLOUDSTACK-3453 UCS:API: List Blades after decommissioning a blade, listUcsBlades API returns wrong number of total blades fixed resolved --- .../com/cloud/ucs/manager/UcsManagerImpl.java | 86 ++++++++++++++++++- .../src/com/cloud/configuration/Config.java | 4 +- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java b/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java index ee75f1b1a39..f9e2c5a039b 100755 --- a/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java +++ b/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java @@ -22,14 +22,14 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.log4j.Logger; - import org.apache.cloudstack.api.AddUcsManagerCmd; import org.apache.cloudstack.api.AssociateUcsProfileToBladeCmd; import org.apache.cloudstack.api.ListUcsBladeCmd; @@ -39,7 +39,10 @@ import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.UcsBladeResponse; import org.apache.cloudstack.api.response.UcsManagerResponse; import org.apache.cloudstack.api.response.UcsProfileResponse; +import org.apache.log4j.Logger; +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.ClusterDao; @@ -54,6 +57,7 @@ import com.cloud.ucs.database.UcsManagerVO; import com.cloud.ucs.structure.ComputeBlade; import com.cloud.ucs.structure.UcsCookie; import com.cloud.ucs.structure.UcsProfile; +import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.SearchCriteria2; @@ -83,11 +87,86 @@ public class UcsManagerImpl implements UcsManager { private HostDao hostDao; @Inject private DataCenterDao dcDao; + @Inject + private ConfigurationDao configDao; private final Map cookies = new HashMap(); private String name; private int runLevel; private Map params; + private ScheduledExecutorService syncBladesExecutor; + private int syncBladeInterval; + + private class SyncBladesThread implements Runnable { + + private void discoverNewBlades(Map previous, + Map now, UcsManagerVO mgr) { + for (Map.Entry e : now.entrySet()) { + String dn = e.getKey(); + if (previous.keySet().contains(dn)) { + continue; + } + + ComputeBlade nc = e.getValue(); + UcsBladeVO vo = new UcsBladeVO(); + vo.setDn(nc.getDn()); + vo.setUcsManagerId(mgr.getId()); + vo.setUuid(UUID.randomUUID().toString()); + bladeDao.persist(vo); + s_logger.debug(String.format("discovered a new UCS blade[dn:%s] during sync", nc.getDn())); + } + } + + private void decommissionFadedBlade(Map previous, Map now) { + for (Map.Entry e : previous.entrySet()) { + String dn = e.getKey(); + if (now.keySet().contains(dn)) { + continue; + } + + UcsBladeVO vo = e.getValue(); + bladeDao.remove(vo.getId()); + s_logger.debug(String.format("decommission faded blade[dn:%s] during sync", vo.getDn())); + } + } + + private void syncBlades(UcsManagerVO mgr) { + SearchCriteriaService q = SearchCriteria2.create(UcsBladeVO.class); + q.addAnd(q.getEntity().getUcsManagerId(), Op.EQ, mgr.getId()); + List pblades = q.list(); + if (pblades.isEmpty()) { + return; + } + + + Map previousBlades = new HashMap(pblades.size()); + for (UcsBladeVO b : pblades) { + previousBlades.put(b.getDn(), b); + } + + List cblades = listBlades(mgr.getId()); + Map currentBlades = new HashMap(cblades.size()); + for (ComputeBlade c : cblades) { + currentBlades.put(c.getDn(), c); + } + + discoverNewBlades(previousBlades, currentBlades, mgr); + decommissionFadedBlade(previousBlades, currentBlades); + } + + @Override + public void run() { + try { + List mgrs = ucsDao.listAll(); + for (UcsManagerVO mgr : mgrs) { + syncBlades(mgr); + } + } catch (Throwable t) { + s_logger.warn(t.getMessage(), t); + } + } + + } @Override public boolean configure(String name, Map params) throws ConfigurationException { @@ -96,6 +175,9 @@ public class UcsManagerImpl implements UcsManager { @Override public boolean start() { + syncBladeInterval = Integer.valueOf(configDao.getValue(Config.UCSSyncBladeInterval.key())); + syncBladesExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("UCS-SyncBlades")); + syncBladesExecutor.scheduleAtFixedRate(new SyncBladesThread(), syncBladeInterval, syncBladeInterval, TimeUnit.SECONDS); return true; } diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index 8153dd6daa6..c815c771290 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -437,7 +437,9 @@ public enum Config { ExecuteInSequence("Advanced", ManagementServer.class, Boolean.class, "execute.in.sequence.hypervisor.commands", "false", "If set to true, StartCommand, StopCommand, CopyCommand will be synchronized on the agent side." + " If set to false, these commands become asynchronous. Default value is false.", null), ExecuteInSequenceNetworkElementCommands("Advanced", NetworkManager.class, Boolean.class, "execute.in.sequence.network.element.commands", "false", "If set to true, DhcpEntryCommand, SavePasswordCommand, UserDataCommand, VmDataCommand will be synchronized on the agent side." + - " If set to false, these commands become asynchronous. Default value is false.", null); + " If set to false, these commands become asynchronous. Default value is false.", null), + + UCSSyncBladeInterval("Advanced", ManagementServer.class, Integer.class, "ucs.sync.blade.interval", "3600", "the interval cloudstack sync with UCS manager for available blades in case user remove blades from chassis without notifying CloudStack", null); private final String _category; private final Class _componentClass;