bug 8713 : finalize the implementation of supporting system vm pooling

This commit is contained in:
Kelven Yang 2011-03-31 17:13:26 -07:00
parent 5f4054325a
commit ea95ac1808
19 changed files with 244 additions and 95 deletions

View File

@ -63,6 +63,10 @@ public class StartupCommand extends Command {
return type;
}
public void setHostType(Host.Type type) {
this.type = type;
}
public String getIqn() {
return iqn;
}

View File

@ -30,6 +30,7 @@ public interface Host {
Storage(false),
Routing(false),
SecondaryStorage(false),
SecondaryStorageCmdExecutor(false),
ConsoleProxy(true),
ExternalFirewall(false),
ExternalLoadBalancer(false),

View File

@ -69,6 +69,7 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
import com.cloud.utils.net.NfsUtils;
import com.cloud.utils.script.Script;
import com.cloud.vm.SecondaryStorageVm;
public class NfsSecondaryStorageResource extends ServerResourceBase implements ServerResource {
private static final Logger s_logger = Logger.getLogger(NfsSecondaryStorageResource.class);
@ -82,6 +83,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
String _guid;
String _nfsPath;
String _mountParent;
String _role;
Map<String, Object> _params;
StorageLayer _storage;
boolean _inSystemVM = false;
@ -183,8 +185,6 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
return null;
}
private Answer execute(SecStorageFirewallCfgCommand cmd) {
if (!_inSystemVM){
return new Answer(cmd, true, null);
@ -294,7 +294,10 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
@Override
public Type getType() {
return Host.Type.SecondaryStorage;
if(SecondaryStorageVm.Role.templateProcessor.toString().equals(_role))
return Host.Type.SecondaryStorage;
return Host.Type.SecondaryStorageCmdExecutor;
}
@Override
@ -353,6 +356,11 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
s_logger.info("_configIpFirewallScr found in " + _configIpFirewallScr);
}
_role = (String)params.get("role");
if(_role == null)
_role = SecondaryStorageVm.Role.templateProcessor.toString();
s_logger.info("Secondary storage runs in role " + _role);
_guid = (String)params.get("guid");
if (_guid == null) {
throw new ConfigurationException("Unable to find the guid");
@ -636,6 +644,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
final StartupStorageCommand cmd = new StartupStorageCommand(_parent, StoragePoolType.NetworkFilesystem, getTotalSize(), new HashMap<String, TemplateInfo>());
cmd.setHostType(getType());
cmd.setResourceType(Storage.StorageResourceType.SECONDARY_STORAGE);
cmd.setIqn(null);
@ -646,7 +655,10 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
cmd.setName(_guid);
cmd.setVersion(NfsSecondaryStorageResource.class.getPackage().getImplementationVersion());
/* gather TemplateInfo in second storage */
final Map<String, TemplateInfo> tInfo = _dlMgr.gatherTemplateInfo();
Map<String, TemplateInfo> tInfo = new HashMap<String, TemplateInfo>();
if(SecondaryStorageVm.Role.templateProcessor.toString().equals(_role))
tInfo = _dlMgr.gatherTemplateInfo();
cmd.setTemplateInfo(tInfo);
cmd.getHostDetails().put("mount.parent", _mountParent);
cmd.getHostDetails().put("mount.path", _nfsPath);

View File

@ -21,6 +21,7 @@ package com.cloud.vm;
* Secondary Storage VM is a system VM instance that is used
* to interface the management server to secondary storage
*/
public interface SecondaryStorageVm extends SystemVm {
public interface SecondaryStorageVm extends SystemVm {
enum Role { templateProcessor, commandExecutor }
}

View File

@ -22,6 +22,8 @@ import java.util.Date;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import javax.persistence.Temporal;
@ -52,17 +54,20 @@ public class SecondaryStorageVmVO extends VMInstanceVO implements SecondaryStora
private String guid;
@Column(name="nfs_share", nullable=false)
private String nfsShare;
private String nfsShare;
@Column(name="role", nullable=false)
@Enumerated(value=EnumType.STRING)
private Role role;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="last_update", updatable=true, nullable=true)
private Date lastUpdateTime;
public SecondaryStorageVmVO(long id, long serviceOfferingId, String name, long templateId, HypervisorType hypervisorType, long guestOSId, long dataCenterId,
long domainId, long accountId) {
long domainId, long accountId, Role role) {
super(id, serviceOfferingId, name, name, Type.SecondaryStorageVm, templateId, hypervisorType, guestOSId, domainId, accountId, true);
this.role = role;
}
protected SecondaryStorageVmVO() {
@ -119,5 +124,13 @@ public class SecondaryStorageVmVO extends VMInstanceVO implements SecondaryStora
public String getNfsShare() {
return nfsShare;
}
}
public Role getRole() {
return this.role;
}
public void setRole(Role role) {
this.role = role;
}
}

View File

@ -2488,23 +2488,26 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory,
Host.Type type = null;
if (startup instanceof StartupStorageCommand) {
StartupStorageCommand ssCmd = ((StartupStorageCommand) startup);
if (ssCmd.getResourceType() == Storage.StorageResourceType.SECONDARY_STORAGE) {
type = Host.Type.SecondaryStorage;
if (resource != null
&& resource instanceof DummySecondaryStorageResource) {
resource = null;
}
if(ssCmd.getHostType() == Host.Type.SecondaryStorageCmdExecutor) {
type = ssCmd.getHostType();
} else {
type = Host.Type.Storage;
}
final Map<String, String> hostDetails = ssCmd.getHostDetails();
if (hostDetails != null) {
if (details != null) {
details.putAll(hostDetails);
if (ssCmd.getResourceType() == Storage.StorageResourceType.SECONDARY_STORAGE) {
type = Host.Type.SecondaryStorage;
if (resource != null
&& resource instanceof DummySecondaryStorageResource) {
resource = null;
}
} else {
details = hostDetails;
type = Host.Type.Storage;
}
final Map<String, String> hostDetails = ssCmd.getHostDetails();
if (hostDetails != null) {
if (details != null) {
details.putAll(hostDetails);
} else {
details = hostDetails;
}
}
}
} else if (startup instanceof StartupRoutingCommand) {
@ -2530,7 +2533,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory,
type = Host.Type.PxeServer;
} else if (startup instanceof StartupExternalDhcpCommand) {
type = Host.Type.ExternalDhcp;
}else {
} else {
assert false : "Did someone add a new Startup command?";
}

View File

@ -152,7 +152,11 @@ public enum Config {
MaxTemplateAndIsoSize("Advanced", ManagementServer.class, Long.class, "max.template.iso.size", "50", "The maximum size for a downloaded template or ISO (in GB).", null),
SecStorageAllowedInternalDownloadSites("Advanced", ManagementServer.class, String.class, "secstorage.allowed.internal.sites", null, "Comma separated list of cidrs internal to the datacenter that can host template download servers", null),
SecStorageEncryptCopy("Advanced", ManagementServer.class, Boolean.class, "secstorage.encrypt.copy", "false", "Use SSL method used to encrypt copy traffic between zones", "true,false"),
SecStorageSecureCopyCert("Advanced", ManagementServer.class, String.class, "secstorage.ssl.cert.domain", "realhostip.com", "SSL certificate used to encrypt copy traffic between zones", null),
SecStorageSecureCopyCert("Advanced", ManagementServer.class, String.class, "secstorage.ssl.cert.domain", "realhostip.com", "SSL certificate used to encrypt copy traffic between zones", null),
SecStorageCapacityStandby("Advanced", AgentManager.class, Integer.class, "secstorage.capacity.standby", "10", "The minimal number of command execution sessions that system is able to serve immediately(standby capacity)", null),
SecStorageSessionMax("Advanced", AgentManager.class, Integer.class, "secstorage.session.max", "50", "The max number of command execution sessions that a SSVM can handle", null),
SecStorageCmdExecutionTimeMax("Advanced", AgentManager.class, Integer.class, "secstorage.cmd.execution.time.max", "30", "The max command execution time in minute", null),
DirectAttachNetworkEnabled("Advanced", ManagementServer.class, Boolean.class, "direct.attach.network.externalIpAllocator.enabled", "false", "Direct-attach VMs using external DHCP server", "true,false"),
DirectAttachNetworkExternalAPIURL("Advanced", ManagementServer.class, String.class, "direct.attach.network.externalIpAllocator.url", null, "Direct-attach VMs using external DHCP server (API url)", null),
CheckPodCIDRs("Advanced", ManagementServer.class, String.class, "check.pod.cidrs", "true", "If true, different pods must belong to different CIDR subnets.", "true,false"),

View File

@ -1478,12 +1478,12 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
}
@Override
public AfterScanAction scanPool(Long pool) {
public Pair<AfterScanAction, Object> scanPool(Long pool) {
long dataCenterId = pool.longValue();
ConsoleProxyLoadInfo proxyInfo = this._zoneProxyCountMap.get(dataCenterId);
if(proxyInfo == null)
return AfterScanAction.nop;
return new Pair<AfterScanAction, Object>(AfterScanAction.nop, null);
ConsoleProxyLoadInfo vmInfo = this._zoneVmCountMap.get(dataCenterId);
if(vmInfo == null)
@ -1493,20 +1493,20 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
if(s_logger.isDebugEnabled())
s_logger.debug("Expand console proxy standby capacity for zone " + proxyInfo.getName());
return AfterScanAction.expand;
return new Pair<AfterScanAction, Object>(AfterScanAction.expand, null);
}
return AfterScanAction.nop;
return new Pair<AfterScanAction, Object>(AfterScanAction.nop, null);
}
@Override
public void expandPool(Long pool) {
public void expandPool(Long pool, Object actionArgs) {
long dataCenterId = pool.longValue();
allocCapacity(dataCenterId);
}
@Override
public void shrinkPool(Long pool) {
public void shrinkPool(Long pool, Object actionArgs) {
}
@Override

View File

@ -95,7 +95,9 @@ public interface HostDao extends GenericDao<HostVO, Long> {
* @param macAddress
* @return HostVO or null if not found.
*/
public HostVO findByGuid(String macAddress);
public HostVO findByGuid(String macAddress);
public HostVO findByName(String name);
/**

View File

@ -75,7 +75,8 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
protected final SearchBuilder<HostVO> PodSearch;
protected final SearchBuilder<HostVO> TypeSearch;
protected final SearchBuilder<HostVO> StatusSearch;
protected final SearchBuilder<HostVO> NameLikeSearch;
protected final SearchBuilder<HostVO> NameLikeSearch;
protected final SearchBuilder<HostVO> NameSearch;
protected final SearchBuilder<HostVO> SequenceSearch;
protected final SearchBuilder<HostVO> DirectlyConnectedSearch;
protected final SearchBuilder<HostVO> UnmanagedDirectConnectSearch;
@ -183,6 +184,10 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
NameLikeSearch = createSearchBuilder();
NameLikeSearch.and("name", NameLikeSearch.entity().getName(), SearchCriteria.Op.LIKE);
NameLikeSearch.done();
NameSearch = createSearchBuilder();
NameSearch.and("name", NameSearch.entity().getName(), SearchCriteria.Op.EQ);
NameSearch.done();
SequenceSearch = createSearchBuilder();
SequenceSearch.and("id", SequenceSearch.entity().getId(), SearchCriteria.Op.EQ);
@ -513,6 +518,12 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
public HostVO findByGuid(String guid) {
SearchCriteria<HostVO> sc = GuidSearch.create("guid", guid);
return findOneBy(sc);
}
@Override
public HostVO findByName(String name) {
SearchCriteria<HostVO> sc = NameSearch.create("name", name);
return findOneBy(sc);
}
@Override

View File

@ -44,7 +44,6 @@ import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.event.EventTypes;
import com.cloud.event.UsageEventVO;
import com.cloud.event.dao.EventDao;
import com.cloud.event.dao.UsageEventDao;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.StorageUnavailableException;
@ -68,6 +67,7 @@ import com.cloud.storage.template.TemplateInfo;
import com.cloud.user.Account;
import com.cloud.utils.component.Inject;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.SecondaryStorageVm;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.SecondaryStorageVmDao;
@ -238,7 +238,7 @@ public class DownloadMonitorImpl implements DownloadMonitor {
}
private String generateCopyUrl(HostVO sourceServer, VMTemplateHostVO srcTmpltHost) {
List<SecondaryStorageVmVO> ssVms = _secStorageVmDao.getSecStorageVmListInStates(sourceServer.getDataCenterId(), State.Running);
List<SecondaryStorageVmVO> ssVms = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, sourceServer.getDataCenterId(), State.Running);
if (ssVms.size() > 0) {
SecondaryStorageVmVO ssVm = ssVms.get(0);
if (ssVm.getPublicIpAddress() == null) {

View File

@ -31,6 +31,7 @@ import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.RebootCommand;
import com.cloud.agent.api.SecStorageFirewallCfgCommand;
import com.cloud.agent.api.SecStorageSetupCommand;
@ -89,6 +90,7 @@ import com.cloud.utils.net.NfsUtils;
import com.cloud.vm.Nic;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.SecondaryStorageVm;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.SystemVmLoadScanHandler;
import com.cloud.vm.SystemVmLoadScanner;
@ -138,7 +140,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
private Adapters<SecondaryStorageVmAllocator> _ssVmAllocators;
@Inject
private SecondaryStorageVmDao _secStorageVmDao;
protected SecondaryStorageVmDao _secStorageVmDao;
@Inject
private DataCenterDao _dcDao;
@Inject
@ -164,7 +166,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
private ServiceOfferingVO _serviceOffering;
@Inject
private ConfigurationDao _configDao;
protected ConfigurationDao _configDao;
@Inject
private ServiceOfferingDao _offeringDao;
@Inject
@ -225,7 +227,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
@Override
public boolean generateSetupCommand(Long zoneId) {
List<SecondaryStorageVmVO> zoneSsvms = _secStorageVmDao.listByZoneId(zoneId);
List<SecondaryStorageVmVO> zoneSsvms = _secStorageVmDao.listByZoneId(SecondaryStorageVm.Role.templateProcessor, zoneId);
if (zoneSsvms.size() == 0) {
return true;
}
@ -275,8 +277,13 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
}
}
@Override
public Pair<HostVO, SecondaryStorageVmVO> assignSecStorageVm(long zoneId, Command cmd) {
return null;
}
private boolean generateFirewallConfigurationForZone(Long zoneId) {
List<SecondaryStorageVmVO> zoneSsvms = _secStorageVmDao.listByZoneId(zoneId);
List<SecondaryStorageVmVO> zoneSsvms = _secStorageVmDao.listByZoneId(SecondaryStorageVm.Role.templateProcessor, zoneId);
if (zoneSsvms.size() == 0) {
return true;
}
@ -291,7 +298,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
s_logger.warn("No storage hosts found in zone " + zoneId + " , skip programming firewall rules");
return true;
}
List<SecondaryStorageVmVO> alreadyRunning = _secStorageVmDao.getSecStorageVmListInStates(State.Running, State.Migrating, State.Starting);
List<SecondaryStorageVmVO> alreadyRunning = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, State.Running, State.Migrating, State.Starting);
String copyPort = Integer.toString(TemplateConstants.DEFAULT_TMPLT_COPY_PORT);
SecStorageFirewallCfgCommand cpc = new SecStorageFirewallCfgCommand();
@ -321,13 +328,13 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
}
public SecondaryStorageVmVO startNew(long dataCenterId) {
public SecondaryStorageVmVO startNew(long dataCenterId, SecondaryStorageVm.Role role) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Assign secondary storage vm from a newly started instance for request from data center : " + dataCenterId);
}
Map<String, Object> context = createSecStorageVmInstance(dataCenterId);
Map<String, Object> context = createSecStorageVmInstance(dataCenterId, role);
long secStorageVmId = (Long) context.get("secStorageVmId");
if (secStorageVmId == 0) {
@ -360,7 +367,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
return null;
}
protected Map<String, Object> createSecStorageVmInstance(long dataCenterId) {
protected Map<String, Object> createSecStorageVmInstance(long dataCenterId, SecondaryStorageVm.Role role) {
HostVO secHost = _hostDao.findSecondaryStorageHost(dataCenterId);
if (secHost == null) {
String msg = "No secondary storage available in zone " + dataCenterId + ", cannot create secondary storage vm";
@ -406,7 +413,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
}
SecondaryStorageVmVO secStorageVm = new SecondaryStorageVmVO(id, _serviceOffering.getId(), name, template.getId(),
template.getHypervisorType(), template.getGuestOSId(), dataCenterId, systemAcct.getDomainId(), systemAcct.getId());
template.getHypervisorType(), template.getGuestOSId(), dataCenterId, systemAcct.getDomainId(), systemAcct.getId(), role);
try {
secStorageVm = _itMgr.allocate(secStorageVm, template, _serviceOffering, networks, plan, null, systemAcct);
} catch (InsufficientCapacityException e) {
@ -434,7 +441,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
return null;
}
public SecondaryStorageVmVO assignSecStorageVmFromRunningPool(long dataCenterId) {
public SecondaryStorageVmVO assignSecStorageVmFromRunningPool(long dataCenterId, SecondaryStorageVm.Role role) {
if (s_logger.isTraceEnabled()) {
s_logger.trace("Assign secondary storage vm from running pool for request from data center : " + dataCenterId);
@ -442,7 +449,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
SecondaryStorageVmAllocator allocator = getCurrentAllocator();
assert (allocator != null);
List<SecondaryStorageVmVO> runningList = _secStorageVmDao.getSecStorageVmListInStates(dataCenterId, State.Running);
List<SecondaryStorageVmVO> runningList = _secStorageVmDao.getSecStorageVmListInStates(role, dataCenterId, State.Running);
if (runningList != null && runningList.size() > 0) {
if (s_logger.isTraceEnabled()) {
s_logger.trace("Running secondary storage vm pool size : " + runningList.size());
@ -462,8 +469,8 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
return null;
}
public SecondaryStorageVmVO assignSecStorageVmFromStoppedPool(long dataCenterId) {
List<SecondaryStorageVmVO> l = _secStorageVmDao.getSecStorageVmListInStates(dataCenterId, State.Starting, State.Stopped, State.Migrating);
public SecondaryStorageVmVO assignSecStorageVmFromStoppedPool(long dataCenterId, SecondaryStorageVm.Role role) {
List<SecondaryStorageVmVO> l = _secStorageVmDao.getSecStorageVmListInStates(role, dataCenterId, State.Starting, State.Stopped, State.Migrating);
if (l != null && l.size() > 0) {
return l.get(0);
}
@ -471,13 +478,13 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
return null;
}
private void allocCapacity(long dataCenterId) {
private void allocCapacity(long dataCenterId, SecondaryStorageVm.Role role) {
if (s_logger.isTraceEnabled()) {
s_logger.trace("Allocate secondary storage vm standby capacity for data center : " + dataCenterId);
}
boolean secStorageVmFromStoppedPool = false;
SecondaryStorageVmVO secStorageVm = assignSecStorageVmFromStoppedPool(dataCenterId);
SecondaryStorageVmVO secStorageVm = assignSecStorageVmFromStoppedPool(dataCenterId, role);
if (secStorageVm == null) {
if (s_logger.isInfoEnabled()) {
s_logger.info("No stopped secondary storage vm is available, need to allocate a new secondary storage vm");
@ -485,7 +492,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
if (_allocLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
try {
secStorageVm = startNew(dataCenterId);
secStorageVm = startNew(dataCenterId, role);
} finally {
_allocLock.unlock();
}
@ -853,7 +860,12 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
buf.append(" zone=").append(dest.getDataCenter().getId());
buf.append(" pod=").append(dest.getPod().getId());
buf.append(" guid=").append(secHost.getGuid());
if(profile.getVirtualMachine().getRole() == SecondaryStorageVm.Role.templateProcessor)
buf.append(" guid=").append(secHost.getGuid());
else
buf.append(" guid=").append(profile.getVirtualMachine().getName());
String nfsMountPoint = null;
try {
nfsMountPoint = NfsUtils.url2Mount(secHost.getStorageUrl());
@ -870,6 +882,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
buf.append(" resource=com.cloud.storage.resource.NfsSecondaryStorageResource");
buf.append(" instance=SecStorage");
buf.append(" sslcopy=").append(Boolean.toString(_useSSlCopy));
buf.append(" role=").append(profile.getVirtualMachine().getRole().toString());
boolean externalDhcp = false;
String externalDhcpStr = _configDao.getValue("direct.attach.network.externalIpAllocator.enabled");
@ -1030,34 +1043,34 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
}
@Override
public AfterScanAction scanPool(Long pool) {
public Pair<AfterScanAction, Object> scanPool(Long pool) {
long dataCenterId = pool.longValue();
List<SecondaryStorageVmVO> alreadyRunning = _secStorageVmDao.getSecStorageVmListInStates(dataCenterId, State.Running,
List<SecondaryStorageVmVO> alreadyRunning = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, dataCenterId, State.Running,
State.Migrating, State.Starting);
List<SecondaryStorageVmVO> stopped = _secStorageVmDao.getSecStorageVmListInStates(dataCenterId, State.Stopped,
List<SecondaryStorageVmVO> stopped = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, dataCenterId, State.Stopped,
State.Stopping);
if (alreadyRunning.size() == 0) {
if (stopped.size() == 0) {
s_logger.info("No secondary storage vms found in datacenter id=" + dataCenterId + ", starting a new one");
return AfterScanAction.expand;
return new Pair<AfterScanAction, Object>(AfterScanAction.expand, SecondaryStorageVm.Role.templateProcessor);
} else {
s_logger.warn("Stopped secondary storage vms found in datacenter id=" + dataCenterId
+ ", not restarting them automatically");
}
}
return AfterScanAction.nop;
return new Pair<AfterScanAction, Object>(AfterScanAction.nop, SecondaryStorageVm.Role.templateProcessor);
}
@Override
public void expandPool(Long pool) {
public void expandPool(Long pool, Object actionArgs) {
long dataCenterId = pool.longValue();
allocCapacity(dataCenterId);
allocCapacity(dataCenterId, (SecondaryStorageVm.Role)actionArgs);
}
@Override
public void shrinkPool(Long pool) {
public void shrinkPool(Long pool, Object actionArgs) {
}
@Override

View File

@ -17,7 +17,10 @@
*/
package com.cloud.storage.secondary;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.StartupCommand;
import com.cloud.host.HostVO;
import com.cloud.utils.Pair;
import com.cloud.utils.component.Manager;
import com.cloud.vm.SecondaryStorageVmVO;
@ -25,6 +28,9 @@ public interface SecondaryStorageVmManager extends Manager {
public static final int DEFAULT_SS_VM_RAMSIZE = 256; // 256M
public static final int DEFAULT_SS_VM_CPUMHZ = 500; // 500 MHz
public static final int DEFAULT_SS_VM_CAPACITY = 50; // max command execution session per SSVM
public static final int DEFAULT_STANDBY_CAPACITY = 10; // standy capacity to reserve per zone
public static final String ALERT_SUBJECT = "secondarystoragevm-alert";
@ -34,6 +40,7 @@ public interface SecondaryStorageVmManager extends Manager {
public boolean destroySecStorageVm(long ssVmVmId);
public void onAgentConnect(Long dcId, StartupCommand cmd);
public boolean generateFirewallConfiguration(Long agentId);
public boolean generateSetupCommand(Long zoneId);
public boolean generateSetupCommand(Long zoneId);
public Pair<HostVO, SecondaryStorageVmVO> assignSecStorageVm(long zoneId, Command cmd);
}

View File

@ -47,6 +47,7 @@ import com.cloud.utils.component.Inject;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.SecondaryStorageVm;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.SecondaryStorageVmDao;
@ -210,7 +211,7 @@ public class UploadMonitorImpl implements UploadMonitor {
}
//Construct actual URL locally now that the symlink exists at SSVM
List<SecondaryStorageVmVO> ssVms = _secStorageVmDao.getSecStorageVmListInStates(dataCenterId, State.Running);
List<SecondaryStorageVmVO> ssVms = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, dataCenterId, State.Running);
if (ssVms.size() > 0) {
SecondaryStorageVmVO ssVm = ssVms.get(0);
if (ssVm.getPublicIpAddress() == null) {
@ -259,7 +260,7 @@ public class UploadMonitorImpl implements UploadMonitor {
uploadJob.setLastUpdated(new Date());
_uploadDao.update(uploadJob.getId(), uploadJob);
List<SecondaryStorageVmVO> ssVms = _secStorageVmDao.getSecStorageVmListInStates(dataCenterId, State.Running);
List<SecondaryStorageVmVO> ssVms = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, dataCenterId, State.Running);
if (ssVms.size() == 0){
errorString = "Couldnt find a running SSVM in the zone" + dataCenterId+ ". Couldnt create the extraction URL.";
throw new CloudRuntimeException(errorString);

View File

@ -1,5 +1,6 @@
package com.cloud.vm;
import com.cloud.utils.Pair;
import com.cloud.vm.SystemVmLoadScanner.AfterScanAction;
public interface SystemVmLoadScanHandler<T> {
@ -9,9 +10,9 @@ public interface SystemVmLoadScanHandler<T> {
T[] getScannablePools();
boolean isPoolReadyForScan(T pool);
AfterScanAction scanPool(T pool);
void expandPool(T pool);
void shrinkPool(T pool);
Pair<AfterScanAction, Object> scanPool(T pool);
void expandPool(T pool, Object actionArgs);
void shrinkPool(T pool, Object actionArgs);
void onScanEnd();
}

View File

@ -7,6 +7,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
import com.cloud.maid.StackMaid;
import com.cloud.utils.Pair;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.db.Transaction;
@ -86,16 +87,18 @@ public class SystemVmLoadScanner<T> {
T[] pools = _scanHandler.getScannablePools();
for(T p : pools) {
if(_scanHandler.isPoolReadyForScan(p)) {
switch(_scanHandler.scanPool(p)) {
Pair<AfterScanAction, Object> actionInfo = _scanHandler.scanPool(p);
switch(actionInfo.first()) {
case nop:
break;
case expand:
_scanHandler.expandPool(p);
_scanHandler.expandPool(p, actionInfo.second());
break;
case shrink:
_scanHandler.shrinkPool(p);
_scanHandler.shrinkPool(p, actionInfo.second());
break;
}
}

View File

@ -20,21 +20,23 @@ package com.cloud.vm.dao;
import java.util.List;
import com.cloud.utils.db.GenericDao;
import com.cloud.vm.SecondaryStorageVm;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.VirtualMachine.State;
public interface SecondaryStorageVmDao extends GenericDao<SecondaryStorageVmVO, Long> {
public List<SecondaryStorageVmVO> getSecStorageVmListInStates(long dataCenterId, State... states);
public List<SecondaryStorageVmVO> getSecStorageVmListInStates(State... states);
public List<SecondaryStorageVmVO> getSecStorageVmListInStates(SecondaryStorageVm.Role role, long dataCenterId, State... states);
public List<SecondaryStorageVmVO> getSecStorageVmListInStates(SecondaryStorageVm.Role role, State... states);
public List<SecondaryStorageVmVO> listByHostId(long hostId);
public List<SecondaryStorageVmVO> listByLastHostId(long hostId);
public List<SecondaryStorageVmVO> listByHostId(SecondaryStorageVm.Role role, long hostId);
public List<SecondaryStorageVmVO> listByLastHostId(SecondaryStorageVm.Role role, long hostId);
public List<SecondaryStorageVmVO> listUpByHostId(long hostId);
public List<SecondaryStorageVmVO> listUpByHostId(SecondaryStorageVm.Role role, long hostId);
public List<SecondaryStorageVmVO> listByZoneId(long zoneId);
public List<SecondaryStorageVmVO> listByZoneId(SecondaryStorageVm.Role role, long zoneId);
public List<Long> getRunningSecStorageVmListByMsid(long msid);
public List<Long> getRunningSecStorageVmListByMsid(SecondaryStorageVm.Role role, long msid);
public List<Long> listRunningSecStorageOrderByLoad(SecondaryStorageVm.Role role, long zoneId);
}

View File

@ -33,6 +33,7 @@ import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.UpdateBuilder;
import com.cloud.vm.SecondaryStorageVm;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.VirtualMachine.State;
@ -54,28 +55,34 @@ public class SecondaryStorageVmDaoImpl extends GenericDaoBase<SecondaryStorageVm
DataCenterStatusSearch = createSearchBuilder();
DataCenterStatusSearch.and("dc", DataCenterStatusSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
DataCenterStatusSearch.and("states", DataCenterStatusSearch.entity().getState(), SearchCriteria.Op.IN);
DataCenterStatusSearch.and("role", DataCenterStatusSearch.entity().getRole(), SearchCriteria.Op.EQ);
DataCenterStatusSearch.done();
StateSearch = createSearchBuilder();
StateSearch.and("states", StateSearch.entity().getState(), SearchCriteria.Op.IN);
StateSearch.and("role", StateSearch.entity().getRole(), SearchCriteria.Op.EQ);
StateSearch.done();
HostSearch = createSearchBuilder();
HostSearch.and("host", HostSearch.entity().getHostId(), SearchCriteria.Op.EQ);
HostSearch.and("role", HostSearch.entity().getRole(), SearchCriteria.Op.EQ);
HostSearch.done();
LastHostSearch = createSearchBuilder();
LastHostSearch.and("lastHost", LastHostSearch.entity().getLastHostId(), SearchCriteria.Op.EQ);
LastHostSearch.and("state", LastHostSearch.entity().getState(), SearchCriteria.Op.EQ);
LastHostSearch.and("role", LastHostSearch.entity().getRole(), SearchCriteria.Op.EQ);
LastHostSearch.done();
HostUpSearch = createSearchBuilder();
HostUpSearch.and("host", HostUpSearch.entity().getHostId(), SearchCriteria.Op.EQ);
HostUpSearch.and("states", HostUpSearch.entity().getState(), SearchCriteria.Op.NIN);
HostUpSearch.and("role", HostUpSearch.entity().getRole(), SearchCriteria.Op.EQ);
HostUpSearch.done();
ZoneSearch = createSearchBuilder();
ZoneSearch.and("zone", ZoneSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
ZoneSearch.and("role", ZoneSearch.entity().getRole(), SearchCriteria.Op.EQ);
ZoneSearch.done();
StateChangeSearch = createSearchBuilder();
@ -83,6 +90,7 @@ public class SecondaryStorageVmDaoImpl extends GenericDaoBase<SecondaryStorageVm
StateChangeSearch.and("states", StateChangeSearch.entity().getState(), SearchCriteria.Op.EQ);
StateChangeSearch.and("host", StateChangeSearch.entity().getHostId(), SearchCriteria.Op.EQ);
StateChangeSearch.and("update", StateChangeSearch.entity().getUpdated(), SearchCriteria.Op.EQ);
StateChangeSearch.and("role", StateChangeSearch.entity().getUpdated(), SearchCriteria.Op.EQ);
StateChangeSearch.done();
_updateTimeAttr = _allAttributes.get("updateTime");
@ -108,46 +116,67 @@ public class SecondaryStorageVmDaoImpl extends GenericDaoBase<SecondaryStorageVm
}
@Override
public List<SecondaryStorageVmVO> getSecStorageVmListInStates(long dataCenterId, State... states) {
public List<SecondaryStorageVmVO> getSecStorageVmListInStates(SecondaryStorageVm.Role role, long dataCenterId, State... states) {
SearchCriteria<SecondaryStorageVmVO> sc = DataCenterStatusSearch.create();
sc.setParameters("states", (Object[])states);
sc.setParameters("dc", dataCenterId);
sc.setParameters("dc", dataCenterId);
if(role != null)
sc.setParameters("role", role);
return listBy(sc);
}
@Override
public List<SecondaryStorageVmVO> getSecStorageVmListInStates(State... states) {
public List<SecondaryStorageVmVO> getSecStorageVmListInStates(SecondaryStorageVm.Role role, State... states) {
SearchCriteria<SecondaryStorageVmVO> sc = StateSearch.create();
sc.setParameters("states", (Object[])states);
sc.setParameters("states", (Object[])states);
if(role != null)
sc.setParameters("role", role);
return listBy(sc);
}
@Override
public List<SecondaryStorageVmVO> listByHostId(long hostId) {
public List<SecondaryStorageVmVO> listByHostId(SecondaryStorageVm.Role role, long hostId) {
SearchCriteria<SecondaryStorageVmVO> sc = HostSearch.create();
sc.setParameters("host", hostId);
if(role != null)
sc.setParameters("role", role);
return listBy(sc);
}
@Override
public List<SecondaryStorageVmVO> listUpByHostId(long hostId) {
public List<SecondaryStorageVmVO> listUpByHostId(SecondaryStorageVm.Role role, long hostId) {
SearchCriteria<SecondaryStorageVmVO> sc = HostUpSearch.create();
sc.setParameters("host", hostId);
sc.setParameters("states", new Object[] {State.Destroyed, State.Stopped, State.Expunging});
if(role != null)
sc.setParameters("role", role);
return listBy(sc);
}
@Override
public List<Long> getRunningSecStorageVmListByMsid(long msid) {
public List<Long> getRunningSecStorageVmListByMsid(SecondaryStorageVm.Role role, long msid) {
List<Long> l = new ArrayList<Long>();
Transaction txn = Transaction.currentTxn();;
PreparedStatement pstmt = null;
try {
pstmt = txn.prepareAutoCloseStatement(
"SELECT s.id FROM secondary_storage_vm s, vm_instance v, host h " +
"WHERE s.id=v.id AND v.state='Running' AND v.host_id=h.id AND h.mgmt_server_id=?");
try {
String sql;
if(role == null)
sql = "SELECT s.id FROM secondary_storage_vm s, vm_instance v, host h " +
"WHERE s.id=v.id AND v.state='Running' AND v.host_id=h.id AND h.mgmt_server_id=?";
else
sql = "SELECT s.id FROM secondary_storage_vm s, vm_instance v, host h " +
"WHERE s.id=v.id AND v.state='Running' AND s.role=? AND v.host_id=h.id AND h.mgmt_server_id=?";
pstmt = txn.prepareAutoCloseStatement(sql);
if(role == null) {
pstmt.setLong(1, msid);
} else {
pstmt.setString(1, role.toString());
pstmt.setLong(2, msid);
}
pstmt.setLong(1, msid);
ResultSet rs = pstmt.executeQuery();
while(rs.next()) {
l.add(rs.getLong(1));
@ -159,17 +188,57 @@ public class SecondaryStorageVmDaoImpl extends GenericDaoBase<SecondaryStorageVm
}
@Override
public List<SecondaryStorageVmVO> listByZoneId(long zoneId) {
public List<SecondaryStorageVmVO> listByZoneId(SecondaryStorageVm.Role role, long zoneId) {
SearchCriteria<SecondaryStorageVmVO> sc = ZoneSearch.create();
sc.setParameters("zone", zoneId);
if(role != null)
sc.setParameters("role", role);
return listBy(sc);
}
@Override
public List<SecondaryStorageVmVO> listByLastHostId(long hostId) {
public List<SecondaryStorageVmVO> listByLastHostId(SecondaryStorageVm.Role role, long hostId) {
SearchCriteria<SecondaryStorageVmVO> sc = LastHostSearch.create();
sc.setParameters("lastHost", hostId);
sc.setParameters("state", State.Stopped);
if(role != null)
sc.setParameters("role", role);
return listBy(sc);
}
}
@Override
public List<Long> listRunningSecStorageOrderByLoad(SecondaryStorageVm.Role role, long zoneId) {
List<Long> l = new ArrayList<Long>();
Transaction txn = Transaction.currentTxn();;
PreparedStatement pstmt = null;
try {
String sql;
if(role == null)
sql = "SELECT s.id, count(l.id) as count FROM secondary_storage_vm s, vm_instance v, cmd_exec_log l " +
"WHERE s.id=v.id AND v.state='Running' AND v.data_center_id=? AND v.id=l.instance_id GROUP BY s.id ORDER BY count";
else
sql = "SELECT s.id, count(l.id) as count FROM secondary_storage_vm s, vm_instance v, cmd_exec_log l " +
"WHERE s.id=v.id AND v.state='Running' AND v.data_center_id=? AND s.role=? AND v.id=l.instance_id GROUP BY s.id ORDER BY count";
pstmt = txn.prepareAutoCloseStatement(sql);
if(role == null) {
pstmt.setLong(1, zoneId);
} else {
pstmt.setLong(1, zoneId);
pstmt.setString(2, role.toString());
}
ResultSet rs = pstmt.executeQuery();
while(rs.next()) {
l.add(rs.getLong(1));
}
} catch (SQLException e) {
s_logger.error("Unexpected exception ", e);
}
return l;
}
}

View File

@ -951,6 +951,7 @@ CREATE TABLE `cloud`.`secondary_storage_vm` (
`guid` varchar(255) COMMENT 'copied from guid of secondary storage host',
`nfs_share` varchar(255) COMMENT 'server and path exported by the nfs server ',
`last_update` DATETIME NULL COMMENT 'Last session update time',
`role` varchar(64) NOT NULL DEFAULT 'templateProcessor' COMMENT 'work role of secondary storage host(templateProcessor | commandExecutor)',
PRIMARY KEY (`id`),
CONSTRAINT `fk_secondary_storage_vm__id` FOREIGN KEY `fk_secondary_storage_vm__id`(`id`) REFERENCES `vm_instance`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
@ -1483,8 +1484,9 @@ CREATE TABLE `cloud`.`domain_network_ref` (
CREATE TABLE `cloud`.`cmd_exec_log` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`host_id` bigint unsigned NOT NULL COMMENT 'host id of the system VM agent that command is sent to',
`instance_id` bigint unsigned NOT NULL COMMENT 'instance id of the system VM that command is executed on',
`command_name` bigint unsigned NOT NULL COMMENT 'command name',
`command_name` varchar(255) NOT NULL COMMENT 'command name',
`created` datetime NOT NULL COMMENT 'date created',
PRIMARY KEY (`id`),
CONSTRAINT `fk_cmd_exec_log_ref__inst_id` FOREIGN KEY (`instance_id`) REFERENCES `vm_instance`(`id`) ON DELETE CASCADE