Intial code changes and schema changes for adding/updating hostTags. Also some code for serviceOffering.

This commit is contained in:
prachi 2010-12-20 11:30:30 -08:00
parent d2e7e28d2a
commit dcf335de6c
28 changed files with 510 additions and 39 deletions

View File

@ -95,6 +95,7 @@
<dao name="NetfsStoragePoolDao" class="com.cloud.storage.dao.NetfsStoragePoolDaoImpl"/>
<dao name="StoragePoolDao" class="com.cloud.storage.dao.StoragePoolDaoImpl"/>
<dao name="StoragePoolHostDao" class="com.cloud.storage.dao.StoragePoolHostDaoImpl"/>
<dao name="HostTagsDao" class="com.cloud.host.dao.HostTagsDaoImpl"/>
<adapters key="com.cloud.agent.manager.allocator.HostAllocator">
<adapter name="FirstFitRouting" class="com.cloud.agent.manager.allocator.impl.FirstFitRoutingAllocator"/>

View File

@ -114,7 +114,7 @@
<adapter name="FirstFit" class="com.cloud.agent.manager.allocator.impl.FirstFitAllocator"/>
</adapters>
<adapters key="com.cloud.storage.allocator.StoragePoolAllocator">
<adapter name="LocalStorage" class="com.cloud.storage.allocator.LocalStoragePoolAllocator"/>
<adapter name="LocalStorage" class="com.cloud.storage.allocator.HostTagBasedLocalStoragePoolAllocator"/>
<adapter name="Storage" class="com.cloud.storage.allocator.FirstFitStoragePoolAllocator"/>
<adapter name="Storage" class="com.cloud.storage.allocator.RandomStoragePoolAllocator"/>
<adapter name="GarbageCollecting" class="com.cloud.storage.allocator.GarbageCollectingStoragePoolAllocator"/>

View File

@ -29,6 +29,7 @@ import com.cloud.dc.PodCluster;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.DiscoveryException;
import com.cloud.exception.InternalErrorException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.host.Host;
import com.cloud.host.HostStats;
@ -158,8 +159,9 @@ public interface AgentManager extends Manager {
* Updates a host
* @param hostId
* @param guestOSCategoryId
* @param hostTags
*/
void updateHost(long hostId, long guestOSCategoryId);
void updateHost(long hostId, long guestOSCategoryId, String hostTags) throws UnsupportedOperationException;
/**
* Deletes a host
@ -209,7 +211,14 @@ public interface AgentManager extends Manager {
public boolean executeUserRequest(long hostId, Event event) throws AgentUnavailableException;
public boolean reconnect(final long hostId) throws AgentUnavailableException;
public List<HostVO> discoverHosts(long dcId, Long podId, Long clusterId, URI url, String username, String password) throws DiscoveryException;
public List<HostVO> discoverHosts(long dcId, Long podId, Long clusterId, URI url, String username, String password, String hostTags) throws DiscoveryException;
Answer easySend(Long hostId, Command cmd, int timeout);
/**
* Returns a comma separated list of tags for the specified host
* @param hostId
* @return comma separated list of tags
*/
String getHostTags(long hostId);
}

View File

@ -0,0 +1,51 @@
package com.cloud.host;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
@Entity
@Table(name="host_tags")
public class HostTagVO {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private long id;
@Column(name="host_id")
private long hostId;
@Column(name="tag")
private String tag;
protected HostTagVO() {
}
public HostTagVO(long hostId, String tag) {
this.hostId = hostId;
this.tag = tag;
}
public long getHostId() {
return hostId;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public long getId() {
return id;
}
}

View File

@ -19,7 +19,7 @@ package com.cloud.host;
import java.util.Date;
import java.util.Map;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
@ -129,7 +129,13 @@ public class HostVO implements Host {
// then this field has not been loaded yet.
// Call host dao to load it.
@Transient
Map<String, String> details;
Map<String, String> details;
// This is a delayed load value. If the value is null,
// then this field has not been loaded yet.
// Call host dao to load it.
@Transient
List<String> hostTags;
@Override
public String getStorageIpAddressDeux() {
@ -271,6 +277,14 @@ public class HostVO implements Host {
public void setDetails(Map<String, String> details) {
this.details = details;
}
public List<String> getHostTags() {
return hostTags;
}
public void setHostTags(List<String> hostTags) {
this.hostTags = hostTags;
}
@Column(name="data_center_id", nullable=false)

View File

@ -17,6 +17,7 @@
*/
package com.cloud.host.dao;
import java.util.List;
import java.util.Map;
import com.cloud.host.DetailVO;
@ -30,4 +31,6 @@ public interface DetailsDao extends GenericDao<DetailVO, Long> {
DetailVO findDetail(long hostId, String name);
void deleteDetails(long hostId);
List<String> findHostDetailsbyValue(long hostId, String value);
}

View File

@ -17,6 +17,10 @@
*/
package com.cloud.host.dao;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -28,12 +32,15 @@ import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
@Local(value=DetailsDao.class)
public class DetailsDaoImpl extends GenericDaoBase<DetailVO, Long> implements DetailsDao {
protected final SearchBuilder<DetailVO> HostSearch;
protected final SearchBuilder<DetailVO> DetailSearch;
private final String FindHostDetailsByValue = "SELECT host_details.name FROM host_details WHERE host_id = ? and value = ?";
protected DetailsDaoImpl() {
HostSearch = createSearchBuilder();
HostSearch.and("hostId", HostSearch.entity().getHostId(), SearchCriteria.Op.EQ);
@ -77,6 +84,31 @@ public class DetailsDaoImpl extends GenericDaoBase<DetailVO, Long> implements De
delete(result.getId());
}
}
public List<String> findHostDetailsbyValue(long hostId, String value){
StringBuilder sql = new StringBuilder(FindHostDetailsByValue);
Transaction txn = Transaction.currentTxn();
PreparedStatement pstmt = null;
try {
pstmt = txn.prepareAutoCloseStatement(sql.toString());
pstmt.setLong(1, hostId);
pstmt.setString(2, value);
ResultSet rs = pstmt.executeQuery();
List<String> detailNames = new ArrayList<String>();
while (rs.next()) {
detailNames.add(rs.getString("name"));
}
return detailNames;
} catch (SQLException e) {
throw new CloudRuntimeException("DB Exception on: " + pstmt.toString(), e);
}
}
@Override
public void persist(long hostId, Map<String, String> details) {

View File

@ -135,7 +135,7 @@ public interface HostDao extends GenericDao<HostVO, Long> {
long getNextSequence(long hostId);
void loadDetails(HostVO host);
void loadDetails(HostVO host);
void loadHostTags(HostVO host);
}

View File

@ -87,6 +87,8 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
protected final DetailsDaoImpl _detailsDao = ComponentLocator.inject(DetailsDaoImpl.class);
protected final HostTagsDaoImpl _hostTagsDao = ComponentLocator.inject(HostTagsDaoImpl.class);
public HostDaoImpl() {
_vmHostDao = ComponentLocator.inject(VmHostDaoImpl.class);
@ -326,6 +328,12 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
host.setDetails(details);
}
@Override
public void loadHostTags(HostVO host){
List<String> hostTags = _hostTagsDao.gethostTags(host.getId());
host.setHostTags(hostTags);
}
@Override
public boolean updateStatus(HostVO host, Event event, long msId) {
Status oldStatus = host.getStatus();
@ -488,6 +496,14 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
_detailsDao.persist(host.getId(), details);
}
protected void saveHostTags(HostVO host) {
List<String> hostTags = host.getHostTags();
if (hostTags == null || (hostTags != null && hostTags.isEmpty())) {
return;
}
_hostTagsDao.persist(host.getId(), hostTags);
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
if (!super.configure(name, params)) {
@ -509,6 +525,8 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
HostVO dbHost = super.persist(host);
saveDetails(host);
loadDetails(dbHost);
saveHostTags(host);
loadHostTags(dbHost);
txn.commit();
@ -526,6 +544,7 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
}
saveDetails(host);
saveHostTags(host);
txn.commit();

View File

@ -0,0 +1,31 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.host.dao;
import java.util.List;
import com.cloud.host.HostTagVO;
import com.cloud.utils.db.GenericDao;
public interface HostTagsDao extends GenericDao<HostTagVO, Long> {
void persist(long hostId, List<String> hostTags);
List<String> gethostTags(long hostId);
}

View File

@ -0,0 +1,65 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.host.dao;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Local;
import com.cloud.host.HostTagVO;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
@Local(value=HostTagsDao.class)
public class HostTagsDaoImpl extends GenericDaoBase<HostTagVO, Long> implements HostTagsDao {
protected final SearchBuilder<HostTagVO> HostSearch;
protected HostTagsDaoImpl() {
HostSearch = createSearchBuilder();
HostSearch.and("hostId", HostSearch.entity().getHostId(), SearchCriteria.Op.EQ);
HostSearch.done();
}
@Override
public List<String> gethostTags(long hostId) {
SearchCriteria sc = HostSearch.create();
sc.setParameters("hostId", hostId);
List<HostTagVO> results = search(sc, null);
List<String> hostTags = new ArrayList<String>(results.size());
for (HostTagVO result : results) {
hostTags.add(result.getTag());
}
return hostTags;
}
@Override
public void persist(long hostId, List<String> hostTags) {
Transaction txn = Transaction.currentTxn();
txn.start();
for (String tag : hostTags) {
HostTagVO vo = new HostTagVO(hostId, tag);
persist(vo);
}
txn.commit();
}
}

View File

@ -281,7 +281,7 @@ public interface ManagementServer {
* @return true if hosts were found; false if not.
* @throws IllegalArgumentException
*/
List<? extends Host> discoverHosts(long dcId, Long podId, Long clusterId, String url, String username, String password) throws IllegalArgumentException, DiscoveryException;
List<? extends Host> discoverHosts(long dcId, Long podId, Long clusterId, String url, String username, String password, String hostTags) throws IllegalArgumentException, DiscoveryException;
String updateAdminPassword(long userId, String oldPassword, String newPassword);
@ -826,7 +826,7 @@ public interface ManagementServer {
* @param hostId
* @param guestOSCategoryId
*/
void updateHost(long hostId, long guestOSCategoryId) throws InvalidParameterValueException;
void updateHost(long hostId, long guestOSCategoryId, String hostTags) throws InvalidParameterValueException, UnsupportedOperationException;
/**
* Deletes a host
@ -2182,4 +2182,12 @@ public interface ManagementServer {
String getHyperType();
String getHashKey();
/**
* Returns a comma separated list of tags for the specified host
* @param hostId
* @return comma separated list of tags
*/
String getHostTags(long hostId);
}

View File

@ -72,5 +72,10 @@ public interface ServiceOffering {
* @return whether or not the service offering requires local storage
*/
boolean getUseLocalStorage();
/*
* @return tag that should be present on the host needed ; optional parameter
*/
public String getHostTag();
}

View File

@ -54,7 +54,10 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering
@Column(name="guest_ip_type")
@Enumerated(EnumType.STRING)
private GuestIpType guestIpType;
private GuestIpType guestIpType;
@Column(name="host_tag")
private String hostTag;
protected ServiceOfferingVO() {
super();
@ -140,5 +143,9 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering
public GuestIpType getGuestIpType() {
return guestIpType;
}
public String getHostTag() {
return hostTag;
}
}

View File

@ -77,6 +77,8 @@ public interface StoragePoolDao extends GenericDao<StoragePoolVO, Long> {
List<StoragePoolVO> findPoolsByTags(long dcId, long podId, Long clusterId, String[] tags, Boolean shared);
List<StoragePoolVO> findPoolsByHostTags(long dcId, long podId, Long clusterId, String[] hostTags, Boolean shared);
/**
* Find pool by UUID.
*

View File

@ -303,6 +303,30 @@ public class StoragePoolDaoImpl extends GenericDaoBase<StoragePoolVO, Long> imp
}
}
@Override
public List<StoragePoolVO> findPoolsByHostTags(long dcId, long podId, Long clusterId, String[] tags, Boolean shared) {
List<StoragePoolVO> storagePools = null;
if (tags == null || tags.length == 0) {
storagePools = listBy(dcId, podId, clusterId);
} else {
Map<String, String> details = tagsToDetails(tags);
storagePools = findPoolsByDetails(dcId, podId, clusterId, details);
}
if (shared == null) {
return storagePools;
} else {
List<StoragePoolVO> filteredStoragePools = new ArrayList<StoragePoolVO>(storagePools);
for (StoragePoolVO pool : storagePools) {
if (shared != pool.isShared()) {
filteredStoragePools.remove(pool);
}
}
return filteredStoragePools;
}
}
@Override
@DB
public List<String> searchForStoragePoolDetails(long poolId, String value){

View File

@ -73,6 +73,7 @@ import com.cloud.alert.AlertManager;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterIpAddressVO;
@ -88,6 +89,7 @@ import com.cloud.event.dao.EventDao;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.DiscoveryException;
import com.cloud.exception.InternalErrorException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.UnsupportedVersionException;
import com.cloud.ha.HighAvailabilityManager;
@ -145,6 +147,7 @@ import com.cloud.vm.UserVm;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VmCharacteristics;
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.host.dao.HostTagsDao;
/**
* Implementation of the Agent Manager. This class controls the connection to
@ -197,6 +200,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory {
@Inject protected GuestOSCategoryDao _guestOSCategoryDao = null;
@Inject protected DetailsDao _hostDetailsDao = null;
@Inject protected ClusterDao _clusterDao;
@Inject protected HostTagsDao _hostTagsDao = null;
private String _publicNic;
private String _privateNic;
@ -219,6 +223,9 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory {
@Inject
protected UpgradeManager _upgradeMgr = null;
@Inject
protected ConfigurationManager _configMgr;
protected int _retry = 2;
protected String _name;
@ -465,11 +472,11 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory {
protected AgentAttache handleDirectConnect(ServerResource resource, StartupCommand[] startup, Map<String, String> details, boolean old) {
protected AgentAttache handleDirectConnect(ServerResource resource, StartupCommand[] startup, Map<String, String> details, boolean old, List<String> hostTags) {
if (startup == null) {
return null;
}
HostVO server = createHost(startup, resource, details, old);
HostVO server = createHost(startup, resource, details, old, hostTags);
if (server == null) {
return null;
}
@ -482,9 +489,12 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory {
}
@Override
public List<HostVO> discoverHosts(long dcId, Long podId, Long clusterId, URI url, String username, String password) throws IllegalArgumentException, DiscoveryException {
public List<HostVO> discoverHosts(long dcId, Long podId, Long clusterId, URI url, String username, String password, String hostTags) throws IllegalArgumentException, DiscoveryException {
List<HostVO> hosts = new ArrayList<HostVO>();
s_logger.info("Trying to add a new host at " + url + " in data center " + dcId);
List<String> hostTagList = _configMgr.csvTagsToList(hostTags);
Enumeration<Discoverer> en = _discoverers.enumeration();
while (en.hasMoreElements()) {
Discoverer discoverer = en.nextElement();
@ -493,7 +503,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory {
for (Map.Entry<? extends ServerResource, Map<String, String>> entry : resources.entrySet()) {
ServerResource resource = entry.getKey();
AgentAttache attache = simulateStart(resource, entry.getValue(), true);
AgentAttache attache = simulateStart(resource, entry.getValue(), true, hostTagList);
if (attache != null) {
hosts.add(_hostDao.findById(attache.getId()));
}
@ -1042,7 +1052,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory {
_executor.execute(new SimulateStartTask(host.getId(), resource, host.getDetails(), actionDelegate));
}
protected AgentAttache simulateStart(ServerResource resource, Map<String, String> details, boolean old) throws IllegalArgumentException{
protected AgentAttache simulateStart(ServerResource resource, Map<String, String> details, boolean old, List<String> hostTags) throws IllegalArgumentException{
StartupCommand[] cmds = resource.initialize();
if (cmds == null )
return null;
@ -1052,7 +1062,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory {
s_logger.debug("Startup request from directly connected host: " + new Request(0, -1, -1, cmds, false).toString());
}
try {
attache = handleDirectConnect(resource, cmds, details, old);
attache = handleDirectConnect(resource, cmds, details, old, hostTags);
}catch (IllegalArgumentException ex)
{
s_logger.warn("Unable to connect due to ", ex);
@ -1155,6 +1165,16 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory {
}
}
}
@Override
public String getHostTags(long hostId){
List<String> hostTags = _hostTagsDao.gethostTags(hostId);
if (hostTags == null) {
return null;
} else {
return _configMgr.listToCsvTags(hostTags);
}
}
@Override
public String getName() {
@ -1462,7 +1482,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory {
}
}
public HostVO createHost(final StartupCommand startup, ServerResource resource, Map<String, String> details, boolean directFirst) throws IllegalArgumentException {
public HostVO createHost(final StartupCommand startup, ServerResource resource, Map<String, String> details, boolean directFirst, List<String> hostTags) throws IllegalArgumentException {
Host.Type type = null;
if (startup instanceof StartupStorageCommand) {
@ -1522,6 +1542,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory {
}
server.setDetails(details);
server.setHostTags(hostTags);
updateHost(server, startup, type, _nodeId);
if (resource != null) {
@ -1570,9 +1591,9 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory {
return server;
}
public HostVO createHost(final StartupCommand[] startup, ServerResource resource, Map<String, String> details, boolean directFirst) throws IllegalArgumentException {
public HostVO createHost(final StartupCommand[] startup, ServerResource resource, Map<String, String> details, boolean directFirst, List<String> hostTags) throws IllegalArgumentException {
StartupCommand firstCmd = startup[0];
HostVO result = createHost(firstCmd, resource, details, directFirst);
HostVO result = createHost(firstCmd, resource, details, directFirst, hostTags);
if( result == null ) {
return null;
}
@ -1580,7 +1601,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory {
}
public AgentAttache handleConnect(final Link link, final StartupCommand[] startup) throws IllegalArgumentException {
HostVO server = createHost(startup, null, null, false);
HostVO server = createHost(startup, null, null, false, null);
if ( server == null ) {
return null;
}
@ -1647,20 +1668,56 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory {
}
@Override
public void updateHost(long hostId, long guestOSCategoryId) {
public void updateHost(long hostId, long guestOSCategoryId, String hostTags) throws UnsupportedOperationException{
GuestOSCategoryVO guestOSCategory = _guestOSCategoryDao.findById(guestOSCategoryId);
Map<String, String> hostDetails = _hostDetailsDao.findDetails(hostId);
boolean persistDetails = false;
String currentOSCategory = hostDetails.get("guest.os.category.id");
if (guestOSCategory != null) {
// Save a new entry for guest.os.category.id
hostDetails.put("guest.os.category.id", String.valueOf(guestOSCategory.getId()));
if(!String.valueOf(guestOSCategory.getId()).equals(currentOSCategory)){
// Save a new entry for guest.os.category.id
hostDetails.put("guest.os.category.id", String.valueOf(guestOSCategory.getId()));
persistDetails = true;
}
} else {
// Delete any existing entry for guest.os.category.id
hostDetails.remove("guest.os.category.id");
if(currentOSCategory != null){
hostDetails.remove("guest.os.category.id");
persistDetails = true;
}
}
_hostDetailsDao.persist(hostId, hostDetails);
if(persistDetails){
_hostDetailsDao.persist(hostId, hostDetails);
}
//update tags
List<String> newHostTags = _configMgr.csvTagsToList(hostTags);
List<String> oldHostTags = _hostTagsDao.gethostTags(hostId);
if(areExistingHostTagsRemoved(hostId, newHostTags, oldHostTags)){
//throw error - removing the existing host tags is not allowed
throw new UnsupportedOperationException("Invalid Operation: Cannot remove existing host tags");
}
//add the new tags to the host
newHostTags.removeAll(oldHostTags);
_hostTagsDao.persist(hostId, newHostTags);
}
private boolean areExistingHostTagsRemoved(long hostId, List<String> newHostTags, List<String> oldHostTags){
boolean tagsRemoved = false;
if(newHostTags.isEmpty() && !oldHostTags.isEmpty()){
tagsRemoved = true;
}else if(!newHostTags.isEmpty() && !oldHostTags.isEmpty()){
if(!newHostTags.containsAll(oldHostTags)){
tagsRemoved = true;
}
}
return tagsRemoved;
}
protected void updateHost(final HostVO host, final StartupCommand startup, final Host.Type type, final long msId) throws IllegalArgumentException {
s_logger.debug("updateHost() called");
@ -1890,7 +1947,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Simulating start for resource " + resource.getName() + " id " + id);
}
simulateStart(resource, details, false);
simulateStart(resource, details, false, null);
} catch (Exception e) {
s_logger.warn("Unable to simulate start on resource " + id + " name " + resource.getName(), e);
} finally {

View File

@ -397,7 +397,8 @@ public abstract class BaseCmd {
CLUSTER_NAME("clustername", BaseCmd.TYPE_STRING, "clustername"),
SCOPE("scope", BaseCmd.TYPE_STRING, "scope"),
SUM_ACROSS_ZONE("sumacrosszone", BaseCmd.TYPE_BOOLEAN, "sumAcrossZone"),
EXCEPTION("exception", BaseCmd.TYPE_STRING, "excetpion");
EXCEPTION("exception", BaseCmd.TYPE_STRING, "excetpion"),
HOST_TAGS("hosttags", BaseCmd.TYPE_STRING, "hostTags");
private final String _name;
private final short _dataType;

View File

@ -48,7 +48,9 @@ public class AddHostCmd extends BaseCmd {
s_properties.add(new Pair<Enum, Boolean>(BaseCmd.Properties.CLUSTER_NAME, Boolean.FALSE));
s_properties.add(new Pair<Enum, Boolean>(BaseCmd.Properties.URL, Boolean.TRUE));
s_properties.add(new Pair<Enum, Boolean>(BaseCmd.Properties.USERNAME, Boolean.TRUE));
s_properties.add(new Pair<Enum, Boolean>(BaseCmd.Properties.PASSWORD, Boolean.TRUE));
s_properties.add(new Pair<Enum, Boolean>(BaseCmd.Properties.PASSWORD, Boolean.TRUE));
//host_tags
s_properties.add(new Pair<Enum, Boolean>(BaseCmd.Properties.HOST_TAGS, Boolean.FALSE));
}
@Override
@ -70,6 +72,8 @@ public class AddHostCmd extends BaseCmd {
String password = (String)params.get(BaseCmd.Properties.PASSWORD.getName());
Long clusterId = (Long)params.get(BaseCmd.Properties.CLUSTER_ID.getName());
String clusterName = (String)params.get(BaseCmd.Properties.CLUSTER_NAME.getName());
//host_tags
String hostTags = (String)params.get(BaseCmd.Properties.HOST_TAGS.getName());
if (clusterName != null && clusterId != null) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Can't specify cluster by both id and name");
@ -120,7 +124,7 @@ public class AddHostCmd extends BaseCmd {
clusterId = cluster.getId();
}
List<? extends Host> h = getManagementServer().discoverHosts(zoneId, podId, clusterId, url, username, password);
List<? extends Host> h = getManagementServer().discoverHosts(zoneId, podId, clusterId, url, username, password, hostTags);
success = !h.isEmpty();
if(success)
@ -203,6 +207,9 @@ public class AddHostCmd extends BaseCmd {
// calculate memory utilized, we don't provide memory over commit
serverData.add(new Pair<String, Object>(BaseCmd.Properties.MEMORY_USED.getName(), mem));
//host_tags
serverData.add(new Pair<String, Object>(BaseCmd.Properties.HOST_TAGS.getName(), getManagementServer().getHostTags(host.getId())));
}
if (host.getType().toString().equals("Storage")) {

View File

@ -86,7 +86,7 @@ public class AddSecondaryStorageCmd extends BaseCmd {
List<? extends Host> h = null;
try {
h = getManagementServer().discoverHosts(zoneId, null, null, url, null, null);
h = getManagementServer().discoverHosts(zoneId, null, null, url, null, null, null);
} catch (Exception ex) {
s_logger.error("Failed to add secondary storage: ", ex);
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Can't add secondary storage with url " + url);

View File

@ -50,6 +50,8 @@ public class UpdateHostCmd extends BaseCmd {
static {
s_properties.add(new Pair<Enum, Boolean>(BaseCmd.Properties.ID, Boolean.TRUE));
s_properties.add(new Pair<Enum, Boolean>(BaseCmd.Properties.OS_CATEGORY_ID, Boolean.FALSE));
//host_tags
s_properties.add(new Pair<Enum, Boolean>(BaseCmd.Properties.HOST_TAGS, Boolean.FALSE));
}
@Override
@ -69,6 +71,8 @@ public class UpdateHostCmd extends BaseCmd {
public List<Pair<String, Object>> execute(Map<String, Object> params) {
Long id = (Long)params.get(BaseCmd.Properties.ID.getName());
Long guestOSCategoryId = (Long)params.get(BaseCmd.Properties.OS_CATEGORY_ID.getName());
//host_tags
String hostTags = (String)params.get(BaseCmd.Properties.HOST_TAGS.getName());
if (guestOSCategoryId == null) {
guestOSCategoryId = new Long(-1);
@ -79,10 +83,15 @@ public class UpdateHostCmd extends BaseCmd {
if (host == null) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Host with id " + id.toString() + " doesn't exist");
}
List<Pair<String, Object>> returnValues = new ArrayList<Pair<String, Object>>();
try {
getManagementServer().updateHost(id, guestOSCategoryId);
getManagementServer().updateHost(id, guestOSCategoryId, hostTags);
} catch(UnsupportedOperationException uex){
s_logger.error("Failed to update host: ", uex);
throw new ServerApiException(BaseCmd.UNSUPPORTED_ACTION_ERROR, "Failed to update host: " + uex.getMessage());
} catch (Exception ex) {
s_logger.error("Failed to update host: ", ex);
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update host: " + ex.getMessage());
@ -176,6 +185,8 @@ public class UpdateHostCmd extends BaseCmd {
// calculate memory utilized, we don't provide memory over commit
hostRO.setMemoryUsed(mem);
//host_tags
hostRO.setHostTags(getManagementServer().getHostTags(hostVO.getId()));
}
if (hostVO.getType().toString().equals("Storage")) {
hostRO.setDiskSizeTotal(hostVO.getTotalSize());

View File

@ -134,6 +134,9 @@ public class HostResultObject {
@Param(name="networkkbswrite")
private Long networkKbsWrite;
@Param(name="hostTags")
private String hostTags;
public long getId(){
return this.id;
@ -439,4 +442,12 @@ public class HostResultObject {
public void setNetworkKbsWrite(long networkKbsWrite){
this.networkKbsWrite = networkKbsWrite;
}
public String getHostTags() {
return hostTags;
}
public void setHostTags(String hostTags) {
this.hostTags = hostTags;
}
}

View File

@ -509,7 +509,7 @@ public class ManagementServerImpl implements ManagementServer {
}
@Override
public List<? extends Host> discoverHosts(long dcId, Long podId, Long clusterId, String url, String username, String password) throws IllegalArgumentException, DiscoveryException {
public List<? extends Host> discoverHosts(long dcId, Long podId, Long clusterId, String url, String username, String password, String hostTags) throws IllegalArgumentException, DiscoveryException {
URI uri;
try {
uri = new URI(url);
@ -517,7 +517,7 @@ public class ManagementServerImpl implements ManagementServer {
throw new IllegalArgumentException("Unable to convert the url" + url, e);
}
// TODO: parameter checks.
return _agentMgr.discoverHosts(dcId, podId, clusterId, uri, username, password);
return _agentMgr.discoverHosts(dcId, podId, clusterId, uri, username, password, hostTags);
}
@Override
@ -536,6 +536,11 @@ public class ManagementServerImpl implements ManagementServer {
}
}
@Override
public String getHostTags(long hostId) {
return _agentMgr.getHostTags(hostId);
}
@Override
public PreallocatedLunVO registerPreallocatedLun(String targetIqn, String portal, int lun, long size, long dcId, String t) {
String[] tags = null;
@ -2886,17 +2891,17 @@ public class ManagementServerImpl implements ManagementServer {
return _hostDao.findById(hostId);
}
public void updateHost(long hostId, long guestOSCategoryId) throws InvalidParameterValueException {
public void updateHost(long hostId, long guestOSCategoryId, String hostTags) throws InvalidParameterValueException, UnsupportedOperationException {
// Verify that the guest OS Category exists
if (guestOSCategoryId > 0) {
if (_guestOSCategoryDao.findById(guestOSCategoryId) == null) {
throw new InvalidParameterValueException("Please specify a valid guest OS category.");
}
}
}
_agentMgr.updateHost(hostId, guestOSCategoryId);
_agentMgr.updateHost(hostId, guestOSCategoryId, hostTags);
}
public boolean deleteHost(long hostId) {
return _agentMgr.deleteHost(hostId);
}

View File

@ -52,7 +52,7 @@ public class FirstFitStoragePoolAllocator extends AbstractStoragePoolAllocator {
return null;
}
List<StoragePoolVO> pools = _storagePoolDao.findPoolsByTags(dc.getId(), pod.getId(), clusterId, dskCh.getTags(), null);
List<StoragePoolVO> pools = findPools(dskCh, offering, dc, pod, clusterId);
if (pools.size() == 0) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("No storage pools available for pod id : " + pod.getId());
@ -80,4 +80,10 @@ public class FirstFitStoragePoolAllocator extends AbstractStoragePoolAllocator {
return null;
}
}
protected List<StoragePoolVO> findPools(DiskCharacteristicsTO dskCh, ServiceOffering offering, DataCenterVO dc, HostPodVO pod, Long clusterId){
List<StoragePoolVO> pools = _storagePoolDao.findPoolsByTags(dc.getId(), pod.getId(), clusterId, dskCh.getTags(), null);
return pools;
}
}

View File

@ -0,0 +1,82 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.storage.allocator;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.manager.allocator.HostAllocator;
import com.cloud.agent.manager.allocator.impl.FirstFitAllocator;
import com.cloud.agent.api.to.DiskCharacteristicsTO;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.host.Host;
import com.cloud.service.ServiceOffering;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.ServiceOffering.GuestIpType;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.utils.DateUtil;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Func;
import com.cloud.vm.State;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VmCharacteristics;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.storage.StoragePoolVO;
//
// TODO
// Rush to make LocalStoragePoolAllocator use static allocation status, we should revisit the overall
// allocation process to make it more reliable in next release. The code put in here is pretty ugly
//
@Local(value=StoragePoolAllocator.class)
public class HostTagBasedLocalStoragePoolAllocator extends LocalStoragePoolAllocator {
private static final Logger s_logger = Logger.getLogger(HostTagBasedLocalStoragePoolAllocator.class);
public HostTagBasedLocalStoragePoolAllocator() {
}
@Override
protected List<StoragePoolVO> findPools(DiskCharacteristicsTO dskCh, ServiceOffering offering, DataCenterVO dc, HostPodVO pod, Long clusterId){
List<StoragePoolVO> pools = _storagePoolDao.findPoolsByHostTags(dc.getId(), pod.getId(), clusterId, dskCh.getTags(), null);
return pools;
}
}

View File

@ -46,6 +46,7 @@ ALTER TABLE `cloud`.`host` ADD INDEX `i_host__pod_id`(`pod_id`);
ALTER TABLE `cloud`.`host` ADD CONSTRAINT `fk_host__cluster_id` FOREIGN KEY `fk_host__cluster_id`(`cluster_id`) REFERENCES `cloud`.`cluster`(`id`);
ALTER TABLE `cloud`.`host_details` ADD CONSTRAINT `fk_host_details__host_id` FOREIGN KEY `fk_host_details__host_id`(`host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE;
ALTER TABLE `cloud`.`host_tags` ADD CONSTRAINT `fk_host_tags__host_id` FOREIGN KEY `fk_host_tags__host_id`(`host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE;
ALTER TABLE `cloud`.`storage_pool` ADD CONSTRAINT `fk_storage_pool__pod_id` FOREIGN KEY `fk_storage_pool__pod_id` (`pod_id`) REFERENCES `host_pod_ref` (`id`) ON DELETE CASCADE;
ALTER TABLE `cloud`.`storage_pool` ADD INDEX `i_storage_pool__pod_id`(`pod_id`);

View File

@ -76,6 +76,7 @@ DROP TABLE IF EXISTS `cloud`.`cluster`;
DROP TABLE IF EXISTS `cloud`.`netapp_volume`;
DROP TABLE IF EXISTS `cloud`.`pool`;
DROP TABLE IF EXISTS `cloud`.`lun`;
DROP TABLE IF EXISTS `cloud`.`host_tags`;
CREATE TABLE `cloud`.`cluster` (
`id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT COMMENT 'id',
@ -391,6 +392,13 @@ CREATE TABLE `cloud`.`op_vm_host` (
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`host_tags` (
`id` bigint unsigned NOT NULL auto_increment,
`host_id` bigint unsigned NOT NULL COMMENT 'host id',
`tag` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`user` (
`id` bigint unsigned NOT NULL auto_increment,
`username` varchar(255) NOT NULL,
@ -784,6 +792,7 @@ CREATE TABLE `cloud`.`service_offering` (
`mc_rate` smallint unsigned default 10 COMMENT 'mcast rate throttle mbits/s',
`ha_enabled` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT 'Enable HA',
`guest_ip_type` varchar(255) NOT NULL DEFAULT 'Virtualized' COMMENT 'Type of guest network -- direct or virtualized',
`host_tag` varchar(255) COMMENT 'host tag specified by the service_offering',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View File

@ -0,0 +1,10 @@
CREATE TABLE `cloud`.`host_tags` (
`id` bigint unsigned NOT NULL auto_increment,
`host_id` bigint unsigned NOT NULL COMMENT 'host id',
`tag` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `cloud`.`host_tags` ADD CONSTRAINT `fk_host_tags__host_id` FOREIGN KEY `fk_host_tags__host_id`(`host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE;
ALTER TABLE `cloud`.`service_offering` ADD COLUMN `host_tag` varchar(255);