diff --git a/api/src/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java index c9da0c28cd6..f93c9f4254c 100644 --- a/api/src/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java @@ -110,11 +110,7 @@ public class RegisterTemplateCmd extends BaseCmd { @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.UUID, entityType = ProjectResponse.class, description="Register template for the project") private Long projectId; - - @Parameter(name=ApiConstants.IMAGE_STORE_UUID, type=CommandType.STRING, - description="Image store uuid") - private String imageStoreUuid; - + @Parameter(name=ApiConstants.DETAILS, type=CommandType.MAP, description="Template details in key/value pairs.") protected Map details; @@ -193,10 +189,7 @@ public class RegisterTemplateCmd extends BaseCmd { public String getTemplateTag() { return templateTag; } - - public String getImageStoreUuid() { - return this.imageStoreUuid; - } + public Map getDetails() { if (details == null || details.isEmpty()) { diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStore.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStore.java index f101f243047..10f869c39fe 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStore.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStore.java @@ -23,6 +23,7 @@ public interface DataStore { String getUuid(); String getUri(); Scope getScope(); + String getName(); DataObject create(DataObject obj); boolean delete(DataObject obj); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreManager.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreManager.java index f940e8e9803..def3b96d331 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreManager.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreManager.java @@ -26,7 +26,7 @@ public interface DataStoreManager { public DataStore getDataStore(long storeId, DataStoreRole role); public DataStore getPrimaryDataStore(long storeId); public DataStore getDataStore(String uuid, DataStoreRole role); - public List getImageStoresByScope(Scope scope); + public List getImageStoresByScope(ZoneScope scope); public List getImageStoresByProvider(String provider); public DataStore registerDataStore(Map params, String providerUuid); } diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDao.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDao.java index fbd09884d1f..8d6acbdf011 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDao.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDao.java @@ -21,12 +21,14 @@ package org.apache.cloudstack.storage.datastore.db; import java.util.List; -import com.cloud.storage.ScopeType; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; + + import com.cloud.utils.db.GenericDao; public interface ImageStoreDao extends GenericDao { public ImageStoreVO findByName(String name); public List findByProvider(String provider); - public List findByScope(ScopeType scope); + public List findByScope(ZoneScope scope); } diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java index 4d92fd3311d..91ffdaa01c2 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java @@ -19,13 +19,14 @@ package org.apache.cloudstack.storage.datastore.db; import java.util.List; +import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; import com.cloud.utils.db.GenericDao; import com.cloud.utils.fsm.StateDao; -public interface SnapshotDataStoreDao extends GenericDao, StateDao { +public interface SnapshotDataStoreDao extends GenericDao, StateDao { public List listByStoreId(long id); diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreVO.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreVO.java index 0f9c95ad8cf..c257fb5c39c 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreVO.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreVO.java @@ -99,8 +99,8 @@ public class SnapshotDataStoreVO implements StateObject, StateDao { +public interface TemplateDataStoreDao extends GenericDao, StateDao { public List listByStoreId(long id); public List listLiveByStoreId(long id); public void deletePrimaryRecordsForStore(long id); + + List listByTemplateStoreStatus(long templateId, long storeId, State... states); + + TemplateDataStoreVO findByStoreTemplate(long storeId, long templateId); } diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreVO.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreVO.java index 4e48437ec2a..312fd119adc 100755 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreVO.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreVO.java @@ -32,7 +32,6 @@ import javax.persistence.TemporalType; import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; -import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.utils.db.GenericDaoBase; @@ -118,8 +117,8 @@ public class TemplateDataStoreVO implements StateObject, StateDao { +public interface VolumeDataStoreDao extends GenericDao, StateDao { public List listByStoreId(long id); diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreVO.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreVO.java index 1fb61845fcc..185b12b52f1 100755 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreVO.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreVO.java @@ -121,8 +121,8 @@ public class VolumeDataStoreVO implements StateObject extends AsyncRpcConext { final TemplateInfo srcTemplate; final DataStore store; @@ -68,39 +68,30 @@ public class ImageServiceImpl implements ImageService { this.templateOnStore = templateOnStore; } } - + @Override public AsyncCallFuture createTemplateAsync( TemplateInfo template, DataStore store) { TemplateObject to = (TemplateObject) template; AsyncCallFuture future = new AsyncCallFuture(); - try { - to.stateTransit(TemplateEvent.CreateRequested); - } catch (NoTransitionException e) { - s_logger.debug("Failed to transit state:", e); - CommandResult result = new CommandResult(); - result.setResult(e.toString()); - future.complete(result); - return future; - } - + // persist template_store_ref entry DataObject templateOnStore = store.create(template); + // update template_store_ref state templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.CreateOnlyRequested); - - CreateTemplateContext context = new CreateTemplateContext(null, + + CreateTemplateContext context = new CreateTemplateContext(null, template, future, store, templateOnStore ); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); - caller.setCallback(caller.getTarget().createTemplateCallback(null, null)) - .setContext(context); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().createTemplateCallback(null, null)).setContext(context); store.getDriver().createAsync(templateOnStore, caller); return future; } - - protected Void createTemplateCallback(AsyncCallbackDispatcher callback, + + protected Void createTemplateCallback(AsyncCallbackDispatcher callback, CreateTemplateContext context) { TemplateObject template = (TemplateObject)context.srcTemplate; AsyncCallFuture future = context.future; @@ -118,7 +109,7 @@ public class ImageServiceImpl implements ImageService { future.complete(result); return null; } - + try { templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed); template.stateTransit(TemplateEvent.OperationSucceeded); @@ -128,7 +119,7 @@ public class ImageServiceImpl implements ImageService { future.complete(result); return null; } - + future.complete(result); return null; } diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageStoreProviderManagerImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageStoreProviderManagerImpl.java index 642821f77b5..dbcfb765e1d 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageStoreProviderManagerImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageStoreProviderManagerImpl.java @@ -30,6 +30,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager; import org.apache.cloudstack.engine.subsystem.api.storage.ImageStoreProvider; import org.apache.cloudstack.engine.subsystem.api.storage.Scope; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; import org.apache.cloudstack.storage.image.ImageStoreDriver; @@ -93,8 +94,8 @@ public class ImageStoreProviderManagerImpl implements ImageStoreProviderManager } @Override - public List listImageStoresByScope(Scope scope) { - List stores = dataStoreDao.findByScope(scope.getScopeType()); + public List listImageStoresByScope(ZoneScope scope) { + List stores = dataStoreDao.findByScope(scope); List imageStores = new ArrayList(); for (ImageStoreVO store : stores) { imageStores.add(getImageStore(store.getId())); diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java index 90290d865f7..7e143cb6f06 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java @@ -94,7 +94,7 @@ public class ImageStoreImpl implements ImageStoreEntity { @Override public String getUri() { - return this.imageDataStoreVO.getProtocol() + "://" + "?" + EncodingType.ROLE + "=" + this.getRole(); + return this.imageDataStoreVO.getUrl(); } @Override diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java index fa7772a979d..0bd40d35122 100644 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java @@ -51,7 +51,7 @@ public class SnapshotDataFactoryImpl implements SnapshotDataFactory { @Override public SnapshotInfo getSnapshot(long snapshotId, DataStore store) { SnapshotVO snapshot = snapshotDao.findByIdIncludingRemoved(snapshotId); - DataObjectInStore obj = objMap.findObject(snapshot.getUuid(), DataObjectType.SNAPSHOT, store.getUuid(), store.getRole()); + DataObjectInStore obj = objMap.findObject(snapshot.getId(), DataObjectType.SNAPSHOT, store.getId(), store.getRole()); if (obj == null) { return null; } @@ -71,7 +71,7 @@ public class SnapshotDataFactoryImpl implements SnapshotDataFactory { } return so; } - + @Override public SnapshotInfo getSnapshot(DataObject obj, DataStore store) { SnapshotVO snapshot = snapshotDao.findByIdIncludingRemoved(obj.getId()); diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/DataStoreManagerImpl.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/DataStoreManagerImpl.java index 8f8d3c92c52..eb233aa3f8b 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/DataStoreManagerImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/DataStoreManagerImpl.java @@ -27,6 +27,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole; import org.apache.cloudstack.engine.subsystem.api.storage.Scope; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager; import org.springframework.stereotype.Component; @@ -63,8 +64,10 @@ public class DataStoreManagerImpl implements DataStoreManager { throw new CloudRuntimeException("un recognized type" + role); } + + @Override - public List getImageStoresByScope(Scope scope) { + public List getImageStoresByScope(ZoneScope scope) { return imageDataStoreMgr.listImageStoresByScope(scope); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManager.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManager.java index d170f5c707a..17b782ab6a0 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManager.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManager.java @@ -29,8 +29,8 @@ public interface ObjectInDataStoreManager { public DataObject create(DataObject template, DataStore dataStore); public DataObject get(DataObject dataObj, DataStore store); public boolean update(DataObject vo, Event event) throws NoTransitionException; - DataObjectInStore findObject(String uuid, DataObjectType type, - String dataStoreUuid, DataStoreRole role); + DataObjectInStore findObject(long objId, DataObjectType type, + long dataStoreId, DataStoreRole role); DataObjectInStore findObject(DataObject obj, DataStore store); DataStore findStore(String objUuid, DataObjectType type, DataStoreRole role); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java index 87ba1d216c5..80badc54d30 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java @@ -29,15 +29,19 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreState import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; -import org.apache.cloudstack.storage.db.ObjectInDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; +import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO; import org.apache.cloudstack.storage.db.ObjectInDataStoreVO; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import com.cloud.storage.VMTemplateStoragePoolVO; -import com.cloud.storage.dao.VMTemplateHostDao; import com.cloud.storage.dao.VMTemplatePoolDao; -import com.cloud.storage.dao.VolumeHostDao; +import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.SearchCriteria2; import com.cloud.utils.db.SearchCriteriaService; @@ -56,11 +60,11 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager { @Inject VolumeDataFactory volumeFactory; @Inject - ObjectInDataStoreDao objectDataStoreDao; + TemplateDataStoreDao templateDataStoreDao; @Inject - VolumeHostDao volumeHostDao; + SnapshotDataStoreDao snapshotDataStoreDao; @Inject - VMTemplateHostDao templateHostDao; + VolumeDataStoreDao volumeDataStoreDao; @Inject VMTemplatePoolDao templatePoolDao; @Inject @@ -101,28 +105,38 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager { @Override public DataObject create(DataObject obj, DataStore dataStore) { - if (obj.getType() == DataObjectType.TEMPLATE && dataStore.getRole() == DataStoreRole.Primary) { - VMTemplateStoragePoolVO vo = new VMTemplateStoragePoolVO(dataStore.getId(), obj.getId()); - vo = templatePoolDao.persist(vo); + if (dataStore.getRole() == DataStoreRole.Primary) { + if ( obj.getType() == DataObjectType.TEMPLATE){ + VMTemplateStoragePoolVO vo = new VMTemplateStoragePoolVO(dataStore.getId(), obj.getId()); + vo = templatePoolDao.persist(vo); + } } else { - ObjectInDataStoreVO vo = new ObjectInDataStoreVO(); - vo.setDataStoreRole(dataStore.getRole()); - vo.setDataStoreUuid(dataStore.getUuid()); - vo.setObjectType(obj.getType()); - vo.setObjectUuid(obj.getUuid()); - vo = objectDataStoreDao.persist(vo); + // Image store + switch ( obj.getType()){ + case TEMPLATE: + TemplateDataStoreVO ts = new TemplateDataStoreVO(); + ts.setTemplateId(obj.getId()); + ts.setDataStoreId(dataStore.getId()); + ts = templateDataStoreDao.persist(ts); + break; + case SNAPSHOT: + SnapshotDataStoreVO ss = new SnapshotDataStoreVO(); + ss.setSnapshotId(obj.getId()); + ss.setDataStoreId(dataStore.getId()); + ss = snapshotDataStoreDao.persist(ss); + break; + case VOLUME: + VolumeDataStoreVO vs = new VolumeDataStoreVO(); + vs.setVolumeId(obj.getId()); + vs.setDataStoreId(dataStore.getId()); + vs = volumeDataStoreDao.persist(vs); + break; + } } - if (obj.getType() == DataObjectType.TEMPLATE) { - return imageFactory.getTemplate(obj, dataStore); - } else if (obj.getType() == DataObjectType.VOLUME) { - return volumeFactory.getVolume(obj, dataStore); - } else if (obj.getType() == DataObjectType.SNAPSHOT) { - return snapshotFactory.getSnapshot(obj, dataStore); - } - throw new CloudRuntimeException("unknown type"); + return this.get(obj, dataStore); } - + @Override public boolean update(DataObject data, Event event) throws NoTransitionException { @@ -132,8 +146,17 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager { "can't find mapping in ObjectInDataStore table for: " + data); } - - if (data.getType() == DataObjectType.TEMPLATE && data.getDataStore().getRole() == DataStoreRole.Primary) { + + if ( data.getDataStore().getRole() == DataStoreRole.Image){ + switch (data.getType()){ + case TEMPLATE: + this.stateMachines.transitTo(obj, event, null, templateDataStoreDao); + case SNAPSHOT: + this.stateMachines.transitTo(obj, event, null, snapshotDataStoreDao); + case VOLUME: + this.stateMachines.transitTo(obj, event, null, volumeDataStoreDao); + } + } else if (data.getType() == DataObjectType.TEMPLATE && data.getDataStore().getRole() == DataStoreRole.Primary) { try { this.stateMachines.transitTo(obj, event, null, templatePoolDao); @@ -145,7 +168,7 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager { } } } else { - this.stateMachines.transitTo(obj, event, null, objectDataStoreDao); + throw new CloudRuntimeException("Invalid data or store type: " + data.getType() + " " + data.getDataStore().getRole()); } return true; } @@ -155,47 +178,53 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager { if (dataObj.getType() == DataObjectType.TEMPLATE) { return imageFactory.getTemplate(dataObj, store); } else if (dataObj.getType() == DataObjectType.VOLUME) { - return volumeFactory.getVolume(dataObj, store); + return volumeFactory.getVolume(dataObj, store); + } else if (dataObj.getType() == DataObjectType.SNAPSHOT) { + return snapshotFactory.getSnapshot(dataObj, store); } + throw new CloudRuntimeException("unknown type"); } @Override public DataObjectInStore findObject(DataObject obj, DataStore store) { - DataObjectInStore vo = null; - SearchCriteriaService sc = SearchCriteria2.create(ObjectInDataStoreVO.class); - - if (store.getRole() == DataStoreRole.Image) { - sc.addAnd(sc.getEntity().getDataStoreUuid(), Op.EQ, store.getUuid()); - sc.addAnd(sc.getEntity().getDataStoreRole(), Op.EQ, store.getRole()); - sc.addAnd(sc.getEntity().getObjectUuid(), Op.EQ, obj.getUuid()); - sc.addAnd(sc.getEntity().getObjectType(), Op.EQ, obj.getType()); - vo = sc.find(); - } else if (obj.getType() == DataObjectType.TEMPLATE && store.getRole() == DataStoreRole.Primary) { - vo = templatePoolDao.findByPoolTemplate(store.getId(), obj.getId()); - } else { - s_logger.debug("unknown type: " + obj.getType() + " " + store.getRole()); - throw new CloudRuntimeException("unknown type"); - } - return vo; + return findObject(obj.getId(), obj.getType(), store.getId(), store.getRole()); } + @Override - public DataObjectInStore findObject(String uuid, DataObjectType type, - String dataStoreUuid, DataStoreRole role) { + public DataObjectInStore findObject(long objId, DataObjectType type, + long dataStoreId, DataStoreRole role) { DataObjectInStore vo = null; - SearchCriteriaService sc = SearchCriteria2.create(ObjectInDataStoreVO.class); - if (role == DataStoreRole.Image) { - sc.addAnd(sc.getEntity().getDataStoreUuid(), Op.EQ, dataStoreUuid); - sc.addAnd(sc.getEntity().getDataStoreRole(), Op.EQ, role); - sc.addAnd(sc.getEntity().getObjectUuid(), Op.EQ, uuid); - sc.addAnd(sc.getEntity().getObjectType(), Op.EQ, type); - vo = sc.find(); + switch (type){ + case TEMPLATE: + SearchCriteria ts = templateDataStoreDao.createSearchCriteria(); + ts.addAnd("templateId", SearchCriteria.Op.EQ, objId); + ts.addAnd("dataStoreId", SearchCriteria.Op.EQ, dataStoreId); + vo = templateDataStoreDao.findOneBy(ts); + case SNAPSHOT: + SearchCriteria ss = snapshotDataStoreDao.createSearchCriteria(); + ss.addAnd("snapshotId", SearchCriteria.Op.EQ, objId); + ss.addAnd("dataStoreId", SearchCriteria.Op.EQ, objId); + vo = snapshotDataStoreDao.findOneBy(ss); + case VOLUME: + SearchCriteria vs = volumeDataStoreDao.createSearchCriteria(); + vs.addAnd("volumeId", SearchCriteria.Op.EQ, objId); + vs.addAnd("dataStoreId", SearchCriteria.Op.EQ, objId); + vo = volumeDataStoreDao.findOneBy(vs); + } + } else if (type == DataObjectType.TEMPLATE && role == DataStoreRole.Primary) { + vo = templatePoolDao.findByPoolTemplate(dataStoreId, objId); + } else { + s_logger.debug("Invalid data or store type: " + type + " " + role); + throw new CloudRuntimeException("Invalid data or store type: " + type + " " + role); } + return vo; + } - + @Override public DataStore findStore(String objUuid, DataObjectType type, DataStoreRole role) { DataStore store = null; diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreProviderManager.java b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreProviderManager.java index bb5e20fdea0..2026346ccdc 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreProviderManager.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreProviderManager.java @@ -22,13 +22,14 @@ import java.util.List; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.Scope; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.storage.image.ImageStoreDriver; public interface ImageStoreProviderManager { ImageStoreEntity getImageStore(long dataStoreId); ImageStoreEntity getImageStore(String uuid); List listImageStores(); - List listImageStoresByScope(Scope scope); + List listImageStoresByScope(ZoneScope scope); List listImageStoreByProvider(String provider); boolean registerDriver(String uuid, ImageStoreDriver driver); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDaoImpl.java index ab41a4b0deb..5bcf2f32691 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDaoImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDaoImpl.java @@ -24,6 +24,8 @@ import java.util.Map; import javax.naming.ConfigurationException; +import org.apache.cloudstack.engine.subsystem.api.storage.Scope; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; import org.apache.log4j.Logger; @@ -40,7 +42,6 @@ public class ImageStoreDaoImpl extends GenericDaoBase implem private static final Logger s_logger = Logger.getLogger(ImageStoreDaoImpl.class); private SearchBuilder nameSearch; private SearchBuilder providerSearch; - private SearchBuilder scopeSearch; @Override @@ -55,10 +56,6 @@ public class ImageStoreDaoImpl extends GenericDaoBase implem providerSearch.and("providerName", providerSearch.entity().getProviderName(), SearchCriteria.Op.EQ); providerSearch.done(); - scopeSearch = createSearchBuilder(); - scopeSearch.and("scope", scopeSearch.entity().getScope(), SearchCriteria.Op.EQ); - scopeSearch.done(); - return true; } @@ -77,9 +74,10 @@ public class ImageStoreDaoImpl extends GenericDaoBase implem } @Override - public List findByScope(ScopeType scope) { - SearchCriteria sc = scopeSearch.create(); - sc.setParameters("scope", scope); + public List findByScope(ZoneScope scope) { + SearchCriteria sc = createSearchCriteria(); + sc.addOr("scope", SearchCriteria.Op.EQ, ScopeType.REGION); + sc.addOr("dcId", SearchCriteria.Op.EQ, scope.getScopeId()); return listBy(sc); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java index a1c4871caa3..6a6e04a52b3 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java @@ -21,6 +21,7 @@ import java.util.Map; import javax.naming.ConfigurationException; +import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State; import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; @@ -66,7 +67,8 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase updateStateSearch; private SearchBuilder storeSearch; private SearchBuilder liveStoreSearch; + private SearchBuilder storeTemplateStateSearch; + private SearchBuilder storeTemplateSearch; @Override public boolean configure(String name, Map params) throws ConfigurationException { @@ -62,12 +64,27 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase listByTemplateStoreStatus(long templateId, long storeId, State... states) { + SearchCriteria sc = storeTemplateStateSearch.create(); + sc.setParameters("template_id", templateId); + sc.setParameters("store_id", storeId); + sc.setParameters("states", (Object[])states); + return search(sc, null); + } + + @Override + public TemplateDataStoreVO findByStoreTemplate(long storeId, long templateId) { + SearchCriteria sc = storeTemplateSearch.create(); + sc.setParameters("store_id", storeId); + sc.setParameters("template_id", templateId); + sc.setParameters("destroyed", false); + return findOneIncludingRemovedBy(sc); + } + + + } diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/VolumeDataStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/VolumeDataStoreDaoImpl.java index b8127ee3361..9a93f980b27 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/db/VolumeDataStoreDaoImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/VolumeDataStoreDaoImpl.java @@ -67,7 +67,8 @@ public class VolumeDataStoreDaoImpl extends GenericDaoBase callback) { + this.ssAgent = ssAgent; + this.sstore = store; + this.template = template; + this._vmTemplateStoreDao = dao; + this.downloadMonitor = downloadMonitor; + this.cmd = cmd; + this.templateStoreId = templStoreId; + initStateMachine(); + this.currState=getState(Status.NOT_DOWNLOADED.toString()); + this.timer = _timer; + this.timeoutTask = new TimeoutTask(this); + this.timer.schedule(timeoutTask, 3*STATUS_POLL_INTERVAL); + this._vmTemplateDao = templateDao; + this._resourceLimitMgr = _resourceLimitMgr; + this._accountMgr = _accountMgr; + this._alertMgr = _alertMgr; + this.callback = callback; + updateDatabase(Status.NOT_DOWNLOADED, ""); + } + + public DownloadListener(HostVO ssAgent, HostVO host, VolumeVO volume, Timer _timer, VolumeHostDao dao, Long volHostId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VolumeDao volumeDao, StorageManager storageMgr, ResourceLimitService _resourceLimitMgr, AlertManager _alertMgr, AccountManager _accountMgr) { this.ssAgent = ssAgent; this.sserver = host; @@ -185,8 +218,8 @@ public class DownloadListener implements Listener { this._alertMgr = _alertMgr; updateDatabase(Status.NOT_DOWNLOADED, ""); } - - + + public void setCurrState(VMTemplateHostVO.Status currState) { this.currState = getState(currState.toString()); } @@ -198,7 +231,7 @@ public class DownloadListener implements Listener { stateMap.put(Status.DOWNLOAD_IN_PROGRESS.toString(), new DownloadInProgressState(this)); stateMap.put(Status.ABANDONED.toString(), new DownloadAbandonedState(this)); } - + private DownloadState getState(String stateName) { return stateMap.get(stateName); } @@ -217,7 +250,7 @@ public class DownloadListener implements Listener { } catch (AgentUnavailableException e) { s_logger.debug("Send command failed", e); setDisconnected(); - } + } } } @@ -253,7 +286,7 @@ public class DownloadListener implements Listener { volumeHostDao.update(getVolumeHostId(), vo); } } - + public void log(String message, Level level) { if (template != null){ s_logger.log(level, message + ", template=" + template.getName() + " at host " + sserver.getName()); @@ -269,7 +302,15 @@ public class DownloadListener implements Listener { } return templateHostId; } - + + private Long getTemplateStoreId() { + if (templateStoreId == null){ + TemplateDataStoreVO templStore = _vmTemplateStoreDao.findByStoreTemplate(sstore.getId(), template.getId()); + templateStoreId = templStore.getId(); + } + return templateStoreId; + } + private Long getVolumeHostId() { if (volumeHostId == null){ VolumeHostVO volHost = volumeHostDao.findByHostVolume(sserver.getId(), volume.getId()); @@ -282,14 +323,14 @@ public class DownloadListener implements Listener { downloadMonitor = monitor; } - + @Override public boolean isRecurring() { return false; } - + @Override public boolean processAnswers(long agentId, long seq, Answer[] answers) { boolean processed = false; @@ -307,7 +348,7 @@ public class DownloadListener implements Listener { } return processed; } - + private synchronized void transition(DownloadEvent event, Object evtObj) { if (currState == null) { return; @@ -328,7 +369,7 @@ public class DownloadListener implements Listener { public synchronized void updateDatabase(DownloadAnswer answer) { if (template != null){ - VMTemplateHostVO updateBuilder = vmTemplateHostDao.createForUpdate(); + TemplateDataStoreVO updateBuilder = _vmTemplateStoreDao.createForUpdate(); updateBuilder.setDownloadPercent(answer.getDownloadPct()); updateBuilder.setDownloadState(answer.getDownloadStatus()); updateBuilder.setLastUpdated(new Date()); @@ -338,9 +379,9 @@ public class DownloadListener implements Listener { updateBuilder.setInstallPath(answer.getInstallPath()); updateBuilder.setSize(answer.getTemplateSize()); updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize()); - - vmTemplateHostDao.update(getTemplateHostId(), updateBuilder); - + + _vmTemplateStoreDao.update(getTemplateStoreId(), updateBuilder); + if (answer.getCheckSum() != null) { VMTemplateVO templateDaoBuilder = _vmTemplateDao.createForUpdate(); templateDaoBuilder.setChecksum(answer.getCheckSum()); @@ -363,7 +404,14 @@ public class DownloadListener implements Listener { com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal()); } } - + // only invoke callback when Download is completed or errored so that callback will update template_store_ref state column + Status dndStatus = answer.getDownloadStatus(); + if (dndStatus == Status.DOWNLOAD_ERROR || dndStatus == Status.DOWNLOADED ){ + if ( callback != null ){ + CreateCmdResult result = new CreateCmdResult(null, null); + callback.complete(result); + } + } } else { VolumeHostVO updateBuilder = volumeHostDao.createForUpdate(); updateBuilder.setDownloadPercent(answer.getDownloadPct()); @@ -422,20 +470,21 @@ public class DownloadListener implements Listener { setDisconnected(); return true; } - + @Override public void processConnect(HostVO agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException { if (cmd instanceof StartupRoutingCommand) { downloadMonitor.handleSysTemplateDownload(agent); } else if ( cmd instanceof StartupStorageCommand) { StartupStorageCommand storage = (StartupStorageCommand)cmd; - if( storage.getResourceType() == Storage.StorageResourceType.SECONDARY_STORAGE || + if( storage.getResourceType() == Storage.StorageResourceType.SECONDARY_STORAGE || storage.getResourceType() == Storage.StorageResourceType.LOCAL_SECONDARY_STORAGE ) { downloadMonitor.addSystemVMTemplatesToHost(agent, storage.getTemplateInfo()); - downloadMonitor.handleTemplateSync(agent); + // DO we need to do sync here since we have been doing sync in StartupSecondaryStorageCommand? + // downloadMonitor.handleTemplateSync(agent); downloadMonitor.handleVolumeSync(agent); } - } else if ( cmd instanceof StartupSecondaryStorageCommand ) { + } else if ( cmd instanceof StartupSecondaryStorageCommand ) { downloadMonitor.handleSync(agent.getDataCenterId()); } } @@ -448,7 +497,7 @@ public class DownloadListener implements Listener { return cmd; } - + public void abandon() { transition(DownloadEvent.ABANDON_DOWNLOAD, null); } @@ -467,7 +516,7 @@ public class DownloadListener implements Listener { statusTask = new StatusTask(this, request); timer.schedule(statusTask, STATUS_POLL_INTERVAL); } - + public void scheduleTimeoutTask(long delay) { if (timeoutTask != null) timeoutTask.cancel(); @@ -477,7 +526,7 @@ public class DownloadListener implements Listener { log("Scheduling timeout at " + delay + " ms", Level.DEBUG); } } - + public void scheduleImmediateStatusCheck(RequestType request) { if (statusTask != null) statusTask.cancel(); statusTask = new StatusTask(this, request); @@ -495,7 +544,7 @@ public class DownloadListener implements Listener { public Date getLastUpdated() { return lastUpdated; } - + public void setLastUpdated() { lastUpdated = new Date(); } @@ -515,12 +564,12 @@ public class DownloadListener implements Listener { public void logDownloadStart() { } - + @Override public boolean processTimeout(long agentId, long seq) { return true; } - + @Override public int getTimeout() { return -1; diff --git a/server/src/com/cloud/storage/download/DownloadMonitor.java b/server/src/com/cloud/storage/download/DownloadMonitor.java index 897befa250b..b20973352d5 100644 --- a/server/src/com/cloud/storage/download/DownloadMonitor.java +++ b/server/src/com/cloud/storage/download/DownloadMonitor.java @@ -18,6 +18,10 @@ package com.cloud.storage.download; import java.util.Map; +import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; + import com.cloud.exception.StorageUnavailableException; import com.cloud.host.HostVO; @@ -32,12 +36,12 @@ import com.cloud.utils.component.Manager; * */ public interface DownloadMonitor extends Manager{ - - public boolean downloadTemplateToStorage(VMTemplateVO template, Long zoneId); - + + public boolean downloadTemplateToStorage(VMTemplateVO template, DataStore store, AsyncCompletionCallback callback); + public void cancelAllDownloads(Long templateId); - public void handleTemplateSync(HostVO host); + public void handleTemplateSync(DataStore store); public boolean copyTemplate(VMTemplateVO template, HostVO sourceServer, HostVO destServer) throws StorageUnavailableException; @@ -50,6 +54,6 @@ public interface DownloadMonitor extends Manager{ boolean downloadVolumeToStorage(VolumeVO volume, Long zoneId, String url, String checkSum, ImageFormat format); - void handleVolumeSync(HostVO ssHost); + void handleVolumeSync(HostVO ssHost); } \ No newline at end of file diff --git a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java index 7ed6f3f27d6..70254def3f9 100755 --- a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java +++ b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java @@ -30,6 +30,12 @@ import java.util.concurrent.ConcurrentHashMap; import javax.ejb.Local; import javax.inject.Inject; +import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -118,15 +124,20 @@ import com.cloud.vm.dao.UserVmDao; import edu.emory.mathcs.backport.java.util.Collections; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; + @Component @Local(value={DownloadMonitor.class}) public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor { static final Logger s_logger = Logger.getLogger(DownloadMonitorImpl.class); - - @Inject + + @Inject VMTemplateHostDao _vmTemplateHostDao; - @Inject + @Inject + TemplateDataStoreDao _vmTemplateStoreDao; + @Inject VMTemplateZoneDao _vmTemplateZoneDao; @Inject VMTemplatePoolDao _vmTemplatePoolDao; @@ -148,7 +159,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor SecondaryStorageVmManager _ssvmMgr; @Inject StorageManager _storageMgr ; - + @Inject private final DataCenterDao _dcDao = null; @Inject @@ -163,10 +174,10 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor @Inject TemplateManager templateMgr; - - @Inject + + @Inject private UsageEventDao _usageEventDao; - + @Inject private ClusterDao _clusterDao; @@ -186,10 +197,13 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor private Boolean _sslCopy = new Boolean(false); private String _copyAuthPasswd; private String _proxy = null; - protected SearchBuilder ReadyTemplateStatesSearch; + protected SearchBuilder ReadyTemplateStatesSearch; Timer _timer; + @Inject DataStoreManager storeMgr; + + final Map _listenerTemplateMap = new ConcurrentHashMap(); final Map _listenerMap = new ConcurrentHashMap(); final Map _listenerVolumeMap = new ConcurrentHashMap(); @@ -203,20 +217,20 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor final Map configs = _configDao.getConfiguration("ManagementServer", params); _sslCopy = Boolean.parseBoolean(configs.get("secstorage.encrypt.copy")); _proxy = configs.get(Config.SecStorageProxy.key()); - + String cert = configs.get("secstorage.ssl.cert.domain"); if (!"realhostip.com".equalsIgnoreCase(cert)) { s_logger.warn("Only realhostip.com ssl cert is supported, ignoring self-signed and other certs"); } - + _copyAuthPasswd = configs.get("secstorage.copy.password"); - + _agentMgr.registerForHostEvents(new DownloadListener(this), true, false, false); - - ReadyTemplateStatesSearch = _vmTemplateHostDao.createSearchBuilder(); - ReadyTemplateStatesSearch.and("download_state", ReadyTemplateStatesSearch.entity().getDownloadState(), SearchCriteria.Op.EQ); + + ReadyTemplateStatesSearch = _vmTemplateStoreDao.createSearchBuilder(); + ReadyTemplateStatesSearch.and("state", ReadyTemplateStatesSearch.entity().getState(), SearchCriteria.Op.EQ); ReadyTemplateStatesSearch.and("destroyed", ReadyTemplateStatesSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); - ReadyTemplateStatesSearch.and("host_id", ReadyTemplateStatesSearch.entity().getHostId(), SearchCriteria.Op.EQ); + ReadyTemplateStatesSearch.and("store_id", ReadyTemplateStatesSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ); SearchBuilder TemplatesWithNoChecksumSearch = _templateDao.createSearchBuilder(); TemplatesWithNoChecksumSearch.and("checksum", TemplatesWithNoChecksumSearch.entity().getChecksum(), SearchCriteria.Op.NULL); @@ -225,7 +239,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor ReadyTemplateStatesSearch.entity().getTemplateId(), JoinBuilder.JoinType.INNER); TemplatesWithNoChecksumSearch.done(); ReadyTemplateStatesSearch.done(); - + return true; } @@ -239,13 +253,13 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor public boolean stop() { return true; } - - public boolean isTemplateUpdateable(Long templateId, Long hostId) { - List downloadsInProgress = - _vmTemplateHostDao.listByTemplateHostStatus(templateId.longValue(), hostId.longValue(), VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS, VMTemplateHostVO.Status.DOWNLOADED); + + public boolean isTemplateUpdateable(Long templateId, Long storeId) { + List downloadsInProgress = + _vmTemplateStoreDao.listByTemplateStoreStatus(templateId, storeId, ObjectInDataStoreStateMachine.State.Creating, ObjectInDataStoreStateMachine.State.Creating2, ObjectInDataStoreStateMachine.State.Ready); return (downloadsInProgress.size() == 0); } - + @Override public boolean copyTemplate(VMTemplateVO template, HostVO sourceServer, HostVO destServer) throws StorageUnavailableException{ @@ -278,12 +292,12 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor throw new CloudRuntimeException("Cant copy the template as the template's size " +srcTmpltHost.getSize()+ " is greater than max.template.iso.size " + maxTemplateSizeInBytes); } - + if(destTmpltHost != null) { start(); String sourceChecksum = this.templateMgr.getChecksum(srcTmpltHost.getHostId(), srcTmpltHost.getInstallPath()); - DownloadCommand dcmd = - new DownloadCommand(destServer.getStorageUrl(), url, template, TemplateConstants.DEFAULT_HTTP_AUTH_USER, _copyAuthPasswd, maxTemplateSizeInBytes); + DownloadCommand dcmd = + new DownloadCommand(destServer.getStorageUrl(), url, template, TemplateConstants.DEFAULT_HTTP_AUTH_USER, _copyAuthPasswd, maxTemplateSizeInBytes); dcmd.setProxy(getHttpProxy()); if (downloadJobExists) { dcmd = new DownloadProgressCommand(dcmd, destTmpltHost.getJobId(), RequestType.GET_OR_RESTART); @@ -305,7 +319,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor if( old != null ) { old.abandon(); } - + try { send(ssAhost.getId(), dcmd, dl); return true; @@ -316,10 +330,10 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor e.printStackTrace(); } } - + return false; } - + private String generateCopyUrl(String ipAddress, String dir, String path){ String hostname = ipAddress; String scheme = "http"; @@ -328,9 +342,9 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor hostname = hostname + ".realhostip.com"; scheme = "https"; } - return scheme + "://" + hostname + "/copy/SecStorage/" + dir + "/" + path; + return scheme + "://" + hostname + "/copy/SecStorage/" + dir + "/" + path; } - + private String generateCopyUrl(HostVO sourceServer, VMTemplateHostVO srcTmpltHost) { List ssVms = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, sourceServer.getDataCenterId(), State.Running); if (ssVms.size() > 0) { @@ -341,7 +355,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor } return generateCopyUrl(ssVm.getPublicIpAddress(), sourceServer.getParent(), srcTmpltHost.getInstallPath()); } - + VMTemplateVO tmplt = _templateDao.findById(srcTmpltHost.getTemplateId()); HypervisorType hyperType = tmplt.getHypervisorType(); /*No secondary storage vm yet*/ @@ -351,43 +365,43 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor return null; } - private void downloadTemplateToStorage(VMTemplateVO template, HostVO sserver) { + private void initiateTemplateDownload(VMTemplateVO template, DataStore store, AsyncCompletionCallback callback) { boolean downloadJobExists = false; - VMTemplateHostVO vmTemplateHost = null; + TemplateDataStoreVO vmTemplateStore = null; - vmTemplateHost = _vmTemplateHostDao.findByHostTemplate(sserver.getId(), template.getId()); - if (vmTemplateHost == null) { - vmTemplateHost = new VMTemplateHostVO(sserver.getId(), template.getId(), new Date(), 0, VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED, null, null, "jobid0000", null, template.getUrl()); - _vmTemplateHostDao.persist(vmTemplateHost); - } else if ((vmTemplateHost.getJobId() != null) && (vmTemplateHost.getJobId().length() > 2)) { + vmTemplateStore = _vmTemplateStoreDao.findByStoreTemplate(store.getId(), template.getId()); + // we should already persist one entry in template_store_ref table, so vmTemplateStore should not be null + if ((vmTemplateStore.getJobId() != null) && (vmTemplateStore.getJobId().length() > 2)) { downloadJobExists = true; } - + Long maxTemplateSizeInBytes = getMaxTemplateSizeInBytes(); - String secUrl = sserver.getStorageUrl(); - if(vmTemplateHost != null) { + String secUrl = store.getUri(); + if(vmTemplateStore != null) { start(); DownloadCommand dcmd = new DownloadCommand(secUrl, template, maxTemplateSizeInBytes); dcmd.setProxy(getHttpProxy()); if (downloadJobExists) { - dcmd = new DownloadProgressCommand(dcmd, vmTemplateHost.getJobId(), RequestType.GET_OR_RESTART); + dcmd = new DownloadProgressCommand(dcmd, vmTemplateStore.getJobId(), RequestType.GET_OR_RESTART); } - if (vmTemplateHost.isCopy()) { + if (vmTemplateStore.isCopy()) { dcmd.setCreds(TemplateConstants.DEFAULT_HTTP_AUTH_USER, _copyAuthPasswd); } - HostVO ssAhost = _ssvmMgr.pickSsvmHost(sserver); + HostVO ssAhost = _ssvmMgr.pickSsvmHost(store); if( ssAhost == null ) { - s_logger.warn("There is no secondary storage VM for secondary storage host " + sserver.getName()); + s_logger.warn("There is no secondary storage VM for downloading template to image store " + store.getName()); return; } - DownloadListener dl = new DownloadListener(ssAhost, sserver, template, _timer, _vmTemplateHostDao, vmTemplateHost.getId(), this, dcmd, _templateDao, _resourceLimitMgr, _alertMgr, _accountMgr); + DownloadListener dl = new DownloadListener(ssAhost, store, template, _timer, _vmTemplateStoreDao, vmTemplateStore.getId(), this, dcmd, _templateDao, _resourceLimitMgr, _alertMgr, _accountMgr, callback); if (downloadJobExists) { - dl.setCurrState(vmTemplateHost.getDownloadState()); + // due to handling existing download job issues, we still keep downloadState in template_store_ref to avoid big change in DownloadListener to use + // new ObjectInDataStore.State transition. TODO: fix this later to be able to remove downloadState from template_store_ref. + dl.setCurrState(vmTemplateStore.getDownloadState()); } DownloadListener old = null; - synchronized (_listenerMap) { - old = _listenerMap.put(vmTemplateHost, dl); + synchronized (_listenerTemplateMap) { + old = _listenerTemplateMap.put(vmTemplateStore, dl); } if( old != null ) { old.abandon(); @@ -396,7 +410,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor try { send(ssAhost.getId(), dcmd, dl); } catch (AgentUnavailableException e) { - s_logger.warn("Unable to start /resume download of template " + template.getUniqueName() + " to " + sserver.getName(), e); + s_logger.warn("Unable to start /resume download of template " + template.getUniqueName() + " to " + store.getName(), e); dl.setDisconnected(); dl.scheduleStatusCheck(RequestType.GET_OR_RESTART); } @@ -406,39 +420,26 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor @Override - public boolean downloadTemplateToStorage(VMTemplateVO template, Long zoneId) { - List dcs = new ArrayList(); - if (zoneId == null) { - dcs.addAll(_dcDao.listAll()); - } else { - dcs.add(_dcDao.findById(zoneId)); - } + public boolean downloadTemplateToStorage(VMTemplateVO template, DataStore store, AsyncCompletionCallback callback) { long templateId = template.getId(); - boolean isPublic = template.isFeatured() || template.isPublicTemplate(); - for ( DataCenterVO dc : dcs ) { - List ssHosts = _ssvmMgr.listAllTypesSecondaryStorageHostsInOneZone(dc.getId()); - for ( HostVO ssHost : ssHosts ) { - if (isTemplateUpdateable(templateId, ssHost.getId())) { - initiateTemplateDownload(templateId, ssHost); - if (! isPublic ) { - break; - } - } - } - } + if (isTemplateUpdateable(templateId, store.getId())) { + if ( template != null && template.getUrl() != null ){ + initiateTemplateDownload(template, store, callback); + } + } return true; } - + @Override public boolean downloadVolumeToStorage(VolumeVO volume, Long zoneId, String url, String checkSum, ImageFormat format) { - + List ssHosts = _ssvmMgr.listAllTypesSecondaryStorageHostsInOneZone(zoneId); Collections.shuffle(ssHosts); HostVO ssHost = ssHosts.get(0); downloadVolumeToStorage(volume, ssHost, url, checkSum, format); return true; } - + private void downloadVolumeToStorage(VolumeVO volume, HostVO sserver, String url, String checkSum, ImageFormat format) { boolean downloadJobExists = false; VolumeHostVO volumeHost = null; @@ -451,7 +452,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor } else if ((volumeHost.getJobId() != null) && (volumeHost.getJobId().length() > 2)) { downloadJobExists = true; } - + Long maxVolumeSizeInBytes = getMaxVolumeSizeInBytes(); String secUrl = sserver.getStorageUrl(); @@ -463,7 +464,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor dcmd = new DownloadProgressCommand(dcmd, volumeHost.getJobId(), RequestType.GET_OR_RESTART); dcmd.setResourceType(ResourceType.VOLUME); } - + HostVO ssvm = _ssvmMgr.pickSsvmHost(sserver); if( ssvm == null ) { s_logger.warn("There is no secondary storage VM for secondary storage host " + sserver.getName()); @@ -471,7 +472,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor } DownloadListener dl = new DownloadListener(ssvm, sserver, volume, _timer, _volumeHostDao, volumeHost.getId(), this, dcmd, _volumeDao, _storageMgr, _resourceLimitMgr, _alertMgr, _accountMgr); - + if (downloadJobExists) { dl.setCurrState(volumeHost.getDownloadState()); } @@ -493,15 +494,16 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor } } - - private void initiateTemplateDownload(Long templateId, HostVO ssHost) { +/* + private void initiateTemplateDownload(Long templateId, DataStore store) { VMTemplateVO template = _templateDao.findById(templateId); if (template != null && (template.getUrl() != null)) { //find all storage hosts and tell them to initiate download - downloadTemplateToStorage(template, ssHost); + downloadTemplateToStorage(template, store); } - + } + */ @DB public void handleDownloadEvent(HostVO host, VMTemplateVO template, Status dnldStatus) { @@ -511,11 +513,11 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor _listenerMap.remove(vmTemplateHost); } } - + VMTemplateHostVO vmTemplateHost = _vmTemplateHostDao.findByHostTemplate(host.getId(), template.getId()); - + Transaction txn = Transaction.currentTxn(); - txn.start(); + txn.start(); if (dnldStatus == Status.DOWNLOADED) { long size = -1; @@ -548,14 +550,14 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor _listenerVolumeMap.remove(volumeHost); } } - + VolumeHostVO volumeHost = _volumeHostDao.findByHostVolume(host.getId(), volume.getId()); - + Transaction txn = Transaction.currentTxn(); - txn.start(); + txn.start(); if (dnldStatus == Status.DOWNLOADED) { - + //Create usage event long size = -1; if(volumeHost!=null){ @@ -590,38 +592,45 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor } Set toBeDownloaded = new HashSet(); + List ssHosts = this.storeMgr.getImageStoresByScope(new ZoneScope(host.getDataCenterId())); + if (ssHosts == null || ssHosts.isEmpty()){ + return; + } + /* List ssHosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByType(Host.Type.SecondaryStorage, host.getDataCenterId()); if (ssHosts == null || ssHosts.isEmpty()) { return; } + */ /*Download all the templates in zone with the same hypervisortype*/ - for ( HostVO ssHost : ssHosts) { + for ( DataStore ssHost : ssHosts) { List rtngTmplts = _templateDao.listAllSystemVMTemplates(); List defaultBuiltin = _templateDao.listDefaultBuiltinTemplates(); - - + + for (VMTemplateVO rtngTmplt : rtngTmplts) { if (rtngTmplt.getHypervisorType() == hostHyper) { toBeDownloaded.add(rtngTmplt); } } - + for (VMTemplateVO builtinTmplt : defaultBuiltin) { if (builtinTmplt.getHypervisorType() == hostHyper) { toBeDownloaded.add(builtinTmplt); } } - + for (VMTemplateVO template: toBeDownloaded) { VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(ssHost.getId(), template.getId()); if (tmpltHost == null || tmpltHost.getDownloadState() != Status.DOWNLOADED) { - downloadTemplateToStorage(template, ssHost); + //TODO: pass callback here + initiateTemplateDownload(template, ssHost, null); } } } } - - @Override + + @Override public void addSystemVMTemplatesToHost(HostVO host, Map templateInfos){ if ( templateInfos == null ) { return; @@ -642,21 +651,26 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor } } } - + @Override public void handleSync(Long dcId) { if (dcId != null) { List ssHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(dcId); for (HostVO ssHost : ssHosts) { - handleTemplateSync(ssHost); + //handleTemplateSync(ssHost); handleVolumeSync(ssHost); } } + List imageStores = this.storeMgr.getImageStoresByScope(new ZoneScope(dcId)); + for (DataStore store : imageStores){ + handleTemplateSync(store); + } } - - private Map listTemplate(HostVO ssHost) { - ListTemplateCommand cmd = new ListTemplateCommand(ssHost.getStorageUrl()); - Answer answer = _agentMgr.sendToSecStorage(ssHost, cmd); + + private Map listTemplate(DataStore ssHost) { + ListTemplateCommand cmd = new ListTemplateCommand(ssHost.getUri()); + HostVO ssAhost = _ssvmMgr.pickSsvmHost(ssHost); + Answer answer = _agentMgr.sendToSecStorage(ssAhost, cmd); if (answer != null && answer.getResult()) { ListTemplateAnswer tanswer = (ListTemplateAnswer)answer; return tanswer.getTemplateInfo(); @@ -664,11 +678,11 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor if (s_logger.isDebugEnabled()) { s_logger.debug("can not list template for secondary storage host " + ssHost.getId()); } - } - + } + return null; } - + private Map listVolume(HostVO ssHost) { ListVolumeCommand cmd = new ListVolumeCommand(ssHost.getStorageUrl()); Answer answer = _agentMgr.sendToSecStorage(ssHost, cmd); @@ -679,11 +693,11 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor if (s_logger.isDebugEnabled()) { s_logger.debug("Can not list volumes for secondary storage host " + ssHost.getId()); } - } - + } + return null; } - + private Map listTemplate(SwiftVO swift) { if (swift == null) { return null; @@ -700,14 +714,14 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor } return null; } - + @Override public void handleVolumeSync(HostVO ssHost) { if (ssHost == null) { s_logger.warn("Huh? ssHost is null"); return; } - long sserverId = ssHost.getId(); + long sserverId = ssHost.getId(); if (!(ssHost.getType() == Host.Type.SecondaryStorage || ssHost.getType() == Host.Type.LocalSecondaryStorage)) { s_logger.warn("Huh? Agent id " + sserverId + " is not secondary storage host"); return; @@ -717,7 +731,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor if (volumeInfos == null) { return; } - + List dbVolumes = _volumeHostDao.listBySecStorage(sserverId); List toBeDownloaded = new ArrayList(dbVolumes); for (VolumeHostVO volumeHost : dbVolumes){ @@ -779,17 +793,17 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor if (volumeHost.getDownloadState() != Status.DOWNLOADED) { s_logger.info("Volume Sync did not find " + volume.getName() + " ready on server " + sserverId + ", will request download to start/resume shortly"); toBeDownloaded.add(volumeHost); - } + } } - + //Download volumes which haven't been downloaded yet. if (toBeDownloaded.size() > 0) { for (VolumeHostVO volumeHost : toBeDownloaded) { if (volumeHost.getDownloadUrl() == null) { // If url is null we can't initiate the download continue; - } + } s_logger.debug("Volume " + volumeHost.getVolumeId() + " needs to be downloaded to " + ssHost.getName()); - downloadVolumeToStorage(_volumeDao.findById(volumeHost.getVolumeId()), ssHost, volumeHost.getDownloadUrl(), volumeHost.getChecksum(), volumeHost.getFormat()); + downloadVolumeToStorage(_volumeDao.findById(volumeHost.getVolumeId()), ssHost, volumeHost.getDownloadUrl(), volumeHost.getChecksum(), volumeHost.getFormat()); } } @@ -804,32 +818,36 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor s_logger.error(err); return; } - + String description = "Deleted volume " + vInfo.getTemplateName() + " on secondary storage " + sserverId + " since it isn't in the database"; s_logger.info(description); } } - - @Override - public void handleTemplateSync(HostVO ssHost) { - if (ssHost == null) { - s_logger.warn("Huh? ssHost is null"); - return; - } - long sserverId = ssHost.getId(); - long zoneId = ssHost.getDataCenterId(); - if (!(ssHost.getType() == Host.Type.SecondaryStorage || ssHost.getType() == Host.Type.LocalSecondaryStorage)) { - s_logger.warn("Huh? Agent id " + sserverId + " is not secondary storage host"); - return; - } - Map templateInfos = listTemplate(ssHost); + @Override + public void handleTemplateSync(DataStore ssStore) { + if (ssStore == null) { + s_logger.warn("Huh? image store is null"); + return; + } + long storeId = ssStore.getId(); + Long zoneId = ssStore.getScope().getScopeId(); + + Map templateInfos = listTemplate(ssStore); if (templateInfos == null) { return; } Set toBeDownloaded = new HashSet(); - List allTemplates = _templateDao.listAllInZone(zoneId); + List allTemplates = null; + if (zoneId == null){ + // region wide store + allTemplates = _templateDao.listAll(); + } + else{ + // zone wide store + allTemplates = _templateDao.listAllInZone(zoneId); + } List rtngTmplts = _templateDao.listAllSystemVMTemplates(); List defaultBuiltin = _templateDao.listDefaultBuiltinTemplates(); @@ -853,34 +871,34 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor for (VMTemplateVO tmplt : allTemplates) { String uniqueName = tmplt.getUniqueName(); - VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(sserverId, tmplt.getId()); + TemplateDataStoreVO tmpltStore = _vmTemplateStoreDao.findByStoreTemplate(storeId, tmplt.getId()); if (templateInfos.containsKey(uniqueName)) { TemplateInfo tmpltInfo = templateInfos.remove(uniqueName); toBeDownloaded.remove(tmplt); - if (tmpltHost != null) { + if (tmpltStore != null) { s_logger.info("Template Sync found " + uniqueName + " already in the template host table"); - if (tmpltHost.getDownloadState() != Status.DOWNLOADED) { - tmpltHost.setErrorString(""); + if (tmpltStore.getDownloadState() != Status.DOWNLOADED) { + tmpltStore.setErrorString(""); } if (tmpltInfo.isCorrupted()) { - tmpltHost.setDownloadState(Status.DOWNLOAD_ERROR); - String msg = "Template " + tmplt.getName() + ":" + tmplt.getId() + " is corrupted on secondary storage " + tmpltHost.getId(); - tmpltHost.setErrorString(msg); + tmpltStore.setDownloadState(Status.DOWNLOAD_ERROR); + String msg = "Template " + tmplt.getName() + ":" + tmplt.getId() + " is corrupted on secondary storage " + tmpltStore.getId(); + tmpltStore.setErrorString(msg); s_logger.info("msg"); if (tmplt.getUrl() == null) { - msg = "Private Template (" + tmplt + ") with install path " + tmpltInfo.getInstallPath() + "is corrupted, please check in secondary storage: " + tmpltHost.getHostId(); + msg = "Private Template (" + tmplt + ") with install path " + tmpltInfo.getInstallPath() + "is corrupted, please check in image store: " + tmpltStore.getDataStoreId(); s_logger.warn(msg); } else { toBeDownloaded.add(tmplt); } } else { - tmpltHost.setDownloadPercent(100); - tmpltHost.setDownloadState(Status.DOWNLOADED); - tmpltHost.setInstallPath(tmpltInfo.getInstallPath()); - tmpltHost.setSize(tmpltInfo.getSize()); - tmpltHost.setPhysicalSize(tmpltInfo.getPhysicalSize()); - tmpltHost.setLastUpdated(new Date()); + tmpltStore.setDownloadPercent(100); + tmpltStore.setDownloadState(Status.DOWNLOADED); + tmpltStore.setInstallPath(tmpltInfo.getInstallPath()); + tmpltStore.setSize(tmpltInfo.getSize()); + tmpltStore.setPhysicalSize(tmpltInfo.getPhysicalSize()); + tmpltStore.setLastUpdated(new Date()); if (tmpltInfo.getSize() > 0) { long accountId = tmplt.getAccountId(); @@ -890,7 +908,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor tmpltInfo.getSize() - UriUtils.getRemoteSize(tmplt.getUrl())); } catch (ResourceAllocationException e) { s_logger.warn(e.getMessage()); - _alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, ssHost.getDataCenterId(), + _alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, zoneId, null, e.getMessage(), e.getMessage()); } finally { _resourceLimitMgr.recalculateResourceCount(accountId, _accountMgr.getAccount(accountId).getDomainId(), @@ -898,39 +916,62 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor } } } - _vmTemplateHostDao.update(tmpltHost.getId(), tmpltHost); + _vmTemplateStoreDao.update(tmpltStore.getId(), tmpltStore); } else { - tmpltHost = new VMTemplateHostVO(sserverId, tmplt.getId(), new Date(), 100, Status.DOWNLOADED, null, null, null, tmpltInfo.getInstallPath(), tmplt.getUrl()); - tmpltHost.setSize(tmpltInfo.getSize()); - tmpltHost.setPhysicalSize(tmpltInfo.getPhysicalSize()); - _vmTemplateHostDao.persist(tmpltHost); - VMTemplateZoneVO tmpltZoneVO = _vmTemplateZoneDao.findByZoneTemplate(zoneId, tmplt.getId()); + tmpltStore = new TemplateDataStoreVO(storeId, tmplt.getId(), new Date(), 100, Status.DOWNLOADED, null, null, null, tmpltInfo.getInstallPath(), tmplt.getUrl()); + tmpltStore.setSize(tmpltInfo.getSize()); + tmpltStore.setPhysicalSize(tmpltInfo.getPhysicalSize()); + _vmTemplateStoreDao.persist(tmpltStore); + List dcs = new ArrayList(); + if (zoneId != null ){ + dcs.add(zoneId); + } + else{ + List zones = _dcDao.listAll(); + for (DataCenterVO zone : zones){ + dcs.add(zone.getId()); + } + } + for (Long id : dcs) { + VMTemplateZoneVO tmpltZoneVO = _vmTemplateZoneDao.findByZoneTemplate(id, tmplt.getId()); + if (tmpltZoneVO == null) { + tmpltZoneVO = new VMTemplateZoneVO(id, tmplt.getId(), new Date()); + _vmTemplateZoneDao.persist(tmpltZoneVO); + } else { + tmpltZoneVO.setLastUpdated(new Date()); + _vmTemplateZoneDao.update(tmpltZoneVO.getId(), tmpltZoneVO); + } + } + } + + continue; + } + if (tmpltStore != null && tmpltStore.getDownloadState() != Status.DOWNLOADED) { + s_logger.info("Template Sync did not find " + uniqueName + " ready on server " + storeId + ", will request download to start/resume shortly"); + + } else if (tmpltStore == null) { + s_logger.info("Template Sync did not find " + uniqueName + " on the server " + storeId + ", will request download shortly"); + TemplateDataStoreVO templtStore = new TemplateDataStoreVO(storeId, tmplt.getId(), new Date(), 0, Status.NOT_DOWNLOADED, null, null, null, null, tmplt.getUrl()); + _vmTemplateStoreDao.persist(templtStore); + List dcs = new ArrayList(); + if (zoneId != null ){ + dcs.add(zoneId); + } + else{ + List zones = _dcDao.listAll(); + for (DataCenterVO zone : zones){ + dcs.add(zone.getId()); + } + } + for (Long id : dcs) { + VMTemplateZoneVO tmpltZoneVO = _vmTemplateZoneDao.findByZoneTemplate(id, tmplt.getId()); if (tmpltZoneVO == null) { - tmpltZoneVO = new VMTemplateZoneVO(zoneId, tmplt.getId(), new Date()); + tmpltZoneVO = new VMTemplateZoneVO(id, tmplt.getId(), new Date()); _vmTemplateZoneDao.persist(tmpltZoneVO); } else { tmpltZoneVO.setLastUpdated(new Date()); _vmTemplateZoneDao.update(tmpltZoneVO.getId(), tmpltZoneVO); } - - } - - continue; - } - if (tmpltHost != null && tmpltHost.getDownloadState() != Status.DOWNLOADED) { - s_logger.info("Template Sync did not find " + uniqueName + " ready on server " + sserverId + ", will request download to start/resume shortly"); - - } else if (tmpltHost == null) { - s_logger.info("Template Sync did not find " + uniqueName + " on the server " + sserverId + ", will request download shortly"); - VMTemplateHostVO templtHost = new VMTemplateHostVO(sserverId, tmplt.getId(), new Date(), 0, Status.NOT_DOWNLOADED, null, null, null, null, tmplt.getUrl()); - _vmTemplateHostDao.persist(templtHost); - VMTemplateZoneVO tmpltZoneVO = _vmTemplateZoneDao.findByZoneTemplate(zoneId, tmplt.getId()); - if (tmpltZoneVO == null) { - tmpltZoneVO = new VMTemplateZoneVO(zoneId, tmplt.getId(), new Date()); - _vmTemplateZoneDao.persist(tmpltZoneVO); - } else { - tmpltZoneVO.setLastUpdated(new Date()); - _vmTemplateZoneDao.update(tmpltZoneVO.getId(), tmpltZoneVO); } } @@ -958,7 +999,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor // if this is private template, and there is no record for this // template in this sHost, skip if (!tmplt.isPublicTemplate() && !tmplt.isFeatured()) { - VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(sserverId, tmplt.getId()); + VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(storeId, tmplt.getId()); if (tmpltHost == null) { continue; } @@ -969,8 +1010,9 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor continue; } } - s_logger.debug("Template " + tmplt.getName() + " needs to be downloaded to " + ssHost.getName()); - downloadTemplateToStorage(tmplt, ssHost); + s_logger.debug("Template " + tmplt.getName() + " needs to be downloaded to " + ssStore.getName()); + //TODO: we should pass a callback here + initiateTemplateDownload(tmplt, ssStore, null); } } } @@ -980,16 +1022,17 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor List userVmUsingIso = _userVmDao.listByIsoId(tInfo.getId()); //check if there is any Vm using this ISO. if (userVmUsingIso == null || userVmUsingIso.isEmpty()) { - DeleteTemplateCommand dtCommand = new DeleteTemplateCommand(ssHost.getStorageUrl(), tInfo.getInstallPath()); + DeleteTemplateCommand dtCommand = new DeleteTemplateCommand(ssStore.getUri(), tInfo.getInstallPath()); try { - _agentMgr.sendToSecStorage(ssHost, dtCommand, null); + HostVO ssAhost = _ssvmMgr.pickSsvmHost(ssStore); + _agentMgr.sendToSecStorage(ssAhost, dtCommand, null); } catch (AgentUnavailableException e) { - String err = "Failed to delete " + tInfo.getTemplateName() + " on secondary storage " + sserverId + " which isn't in the database"; + String err = "Failed to delete " + tInfo.getTemplateName() + " on secondary storage " + storeId + " which isn't in the database"; s_logger.error(err); return; } - String description = "Deleted template " + tInfo.getTemplateName() + " on secondary storage " + sserverId + " since it isn't in the database"; + String description = "Deleted template " + tInfo.getTemplateName() + " on secondary storage " + storeId + " since it isn't in the database"; s_logger.info(description); } } @@ -1012,10 +1055,11 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor } } } - + + /* private void checksumSync(long hostId){ - SearchCriteria sc = ReadyTemplateStatesSearch.create(); - sc.setParameters("download_state", com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED); + SearchCriteria sc = ReadyTemplateStatesSearch.create(); + sc.setParameters("state", ObjectInDataStoreStateMachine.State.Ready); sc.setParameters("host_id", hostId); List templateHostRefList = _vmTemplateHostDao.search(sc, null); @@ -1030,7 +1074,8 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor } } - + */ + private Long getMaxTemplateSizeInBytes() { try { return Long.parseLong(_configDao.getValue("max.template.iso.size")) * 1024L * 1024L * 1024L; @@ -1038,7 +1083,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor return null; } } - + private Long getMaxVolumeSizeInBytes() { try { return Long.parseLong(_configDao.getValue("storage.max.volume.upload.size")) * 1024L * 1024L * 1024L; @@ -1046,7 +1091,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor return null; } } - + private Proxy getHttpProxy() { if (_proxy == null) { return null; @@ -1058,7 +1103,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor } catch (URISyntaxException e) { return null; } - } - + } + } - + diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java index c94224b264c..bdac44d9a0d 100755 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java @@ -5,7 +5,7 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, @@ -29,6 +29,9 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole; +import org.apache.cloudstack.engine.subsystem.api.storage.Scope; import org.apache.log4j.Logger; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; @@ -95,6 +98,7 @@ import com.cloud.resource.ServerResource; import com.cloud.resource.UnableDeleteHostException; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.storage.ScopeType; import com.cloud.storage.SnapshotVO; import com.cloud.storage.Storage; import com.cloud.storage.VMTemplateHostVO; @@ -199,7 +203,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar protected NetworkModel _networkModel; @Inject protected SnapshotDao _snapshotDao; - + @Inject private ClusterManager _clusterMgr; @@ -221,7 +225,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar protected CapacityDao _capacityDao; @Inject UserVmDetailsDao _vmDetailsDao; - @Inject + @Inject protected ResourceManager _resourceMgr; //@Inject // TODO this is a very strange usage, a singleton class need to inject itself? protected SecondaryStorageVmManager _ssvmMgr; @@ -233,7 +237,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar protected IPAddressDao _ipAddressDao = null; @Inject protected RulesManager _rulesMgr; - + @Inject KeystoreManager _keystoreMgr; private long _capacityScanInterval = DEFAULT_CAPACITY_SCAN_INTERVAL; @@ -254,7 +258,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar public SecondaryStorageManagerImpl() { _ssvmMgr = this; } - + @Override public SecondaryStorageVmVO startSecStorageVm(long secStorageVmId) { try { @@ -283,13 +287,13 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } return null; } - + @Override public boolean generateSetupCommand(Long ssHostId) { HostVO cssHost = _hostDao.findById(ssHostId); Long zoneId = cssHost.getDataCenterId(); if( cssHost.getType() == Host.Type.SecondaryStorageVM ) { - + SecondaryStorageVmVO secStorageVm = _secStorageVmDao.findByInstanceName(cssHost.getName()); if (secStorageVm == null) { s_logger.warn("secondary storage VM " + cssHost.getName() + " doesn't exist"); @@ -306,7 +310,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar Certificates certs = _keystoreMgr.getCertificates(ConsoleProxyManager.CERTIFICATE_NAME); setupCmd = new SecStorageSetupCommand(secUrl, certs); } - + Answer answer = _agentMgr.easySend(ssHostId, setupCmd); if (answer != null && answer.getResult()) { SecStorageSetupAnswer an = (SecStorageSetupAnswer) answer; @@ -338,14 +342,14 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar s_logger.debug("Successfully programmed secondary storage " + host.getName() + " in secondary storage VM " + ssVm.getInstanceName()); } return false; - } + } } } return true; } - - - @Override + + + @Override public boolean deleteHost(Long hostId) { List snapshots = _snapshotDao.listByHostId(hostId); if( snapshots != null && !snapshots.isEmpty()) { @@ -362,10 +366,10 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar host.setGuid(null); _hostDao.update(hostId, host); _hostDao.remove(hostId); - + return true; } - + @Override public boolean generateVMSetupCommand(Long ssAHostId) { HostVO ssAHost = _hostDao.findById(ssAHostId); @@ -377,7 +381,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar s_logger.warn("secondary storage VM " + ssAHost.getName() + " doesn't exist"); return false; } - + SecStorageVMSetupCommand setupCmd = new SecStorageVMSetupCommand(); if (_allowedInternalSites != null) { List allowedCidrs = new ArrayList(); @@ -419,7 +423,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } HostVO ssAHost = _hostDao.findById(ssAHostId); SecondaryStorageVmVO thisSecStorageVm = _secStorageVmDao.findByInstanceName(ssAHost.getName()); - + if (thisSecStorageVm == null) { s_logger.warn("secondary storage VM " + ssAHost.getName() + " doesn't exist"); return false; @@ -428,7 +432,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar String copyPort = _useSSlCopy? "443" : Integer.toString(TemplateConstants.DEFAULT_TMPLT_COPY_PORT); SecStorageFirewallCfgCommand thiscpc = new SecStorageFirewallCfgCommand(true); thiscpc.addPortConfig(thisSecStorageVm.getPublicIpAddress(), copyPort, true, TemplateConstants.DEFAULT_TMPLT_COPY_INTF); - + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.SecondaryStorageVM); sc.addAnd(sc.getEntity().getStatus(), Op.IN, com.cloud.host.Status.Up, com.cloud.host.Status.Connecting); @@ -449,7 +453,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar return false; } } - + SecStorageFirewallCfgCommand allSSVMIpList = new SecStorageFirewallCfgCommand(false); for (HostVO ssvm : ssvms) { if (ssvm.getId() == ssAHostId) { @@ -457,7 +461,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } allSSVMIpList.addPortConfig(ssvm.getPublicIpAddress(), copyPort, true, TemplateConstants.DEFAULT_TMPLT_COPY_INTF); } - + Answer answer = _agentMgr.easySend(ssAHostId, allSSVMIpList); if (answer != null && answer.getResult()) { if (s_logger.isDebugEnabled()) { @@ -469,7 +473,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } return false; } - + return true; } @@ -539,19 +543,19 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar DataCenterDeployment plan = new DataCenterDeployment(dataCenterId); DataCenter dc = _dcDao.findById(plan.getDataCenterId()); - + TrafficType defaultTrafficType = TrafficType.Public; if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) { defaultTrafficType = TrafficType.Guest; } - + List defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType); - + //api should never allow this situation to happen if (defaultNetworks.size() != 1) { throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + defaultTrafficType + " when expect to find 1"); } - + NetworkVO defaultNetwork = defaultNetworks.get(0); List offerings = _networkModel.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemControlNetwork, NetworkOfferingVO.SystemManagementNetwork, NetworkOfferingVO.SystemStorageNetwork); @@ -570,7 +574,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } HypervisorType hypeType = _resourceMgr.getAvailableHypervisor(dataCenterId); - + VMTemplateVO template = _templateDao.findSystemVMTemplate(dataCenterId, hypeType); if (template == null) { s_logger.debug("Can't find a template to start"); @@ -596,7 +600,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar // for now, only one adapter is supported if(_ssVmAllocators.size() > 0) return _ssVmAllocators.get(0); - + return null; } @@ -652,8 +656,8 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } return; } - - + + boolean secStorageVmFromStoppedPool = false; SecondaryStorageVmVO secStorageVm = assignSecStorageVmFromStoppedPool(dataCenterId, role); if (secStorageVm == null) { @@ -798,7 +802,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } Map configs = _configDao.getConfiguration("management-server", params); - + _secStorageVmMtuSize = NumbersUtil.parseInt(configs.get("secstorage.vm.mtu.size"), DEFAULT_SS_VM_MTUSIZE); String useServiceVM = _configDao.getValue("secondary.storage.vm"); boolean _useServiceVM = false; @@ -834,7 +838,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar _agentMgr.registerForHostEvents(_listener, true, false, true); _itMgr.registerGuru(VirtualMachine.Type.SecondaryStorageVm, this); - + //check if there is a default service offering configured String ssvmSrvcOffIdStr = configs.get(Config.SecondaryStorageServiceOffering.key()); if (ssvmSrvcOffIdStr != null) { @@ -852,7 +856,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar _serviceOffering = new ServiceOfferingVO("System Offering For Secondary Storage VM", 1, ramSize, cpuFreq, null, null, false, null, _useLocalStorage, true, null, true, VirtualMachine.Type.SecondaryStorageVm, true); _serviceOffering.setUniqueName(ServiceOffering.ssvmDefaultOffUniqueName); _serviceOffering = _offeringDao.persistSystemServiceOffering(_serviceOffering); - + // this can sometimes happen, if DB is manually or programmatically manipulated if(_serviceOffering == null) { String msg = "Data integrity problem : System Offering For Secondary Storage VM has been removed?"; @@ -865,7 +869,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar _loadScanner = new SystemVmLoadScanner(this); _loadScanner.initScan(STARTUP_DELAY, _capacityScanInterval); } - + _httpProxy = configs.get(Config.SecStorageProxy.key()); if (_httpProxy != null) { boolean valid = true; @@ -989,14 +993,14 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar try { boolean result = _itMgr.expunge(ssvm, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); if (result) { - HostVO host = _hostDao.findByTypeNameAndZoneId(ssvm.getDataCenterId(), ssvm.getHostName(), + HostVO host = _hostDao.findByTypeNameAndZoneId(ssvm.getDataCenterId(), ssvm.getHostName(), Host.Type.SecondaryStorageVM); if (host != null) { s_logger.debug("Removing host entry for ssvm id=" + vmId); result = result && _hostDao.remove(host.getId()); } } - + return result; } catch (ResourceUnavailableException e) { s_logger.warn("Unable to expunge " + ssvm, e); @@ -1042,7 +1046,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar SecondaryStorageVmVO vm = profile.getVirtualMachine(); Map details = _vmDetailsDao.findDetails(vm.getId()); vm.setDetails(details); - + HostVO secHost = _ssvmMgr.findSecondaryStorageHost(dest.getDataCenter().getId()); assert (secHost != null); @@ -1081,7 +1085,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar if (externalDhcpStr != null && externalDhcpStr.equalsIgnoreCase("true")) { externalDhcp = true; } - + if (Boolean.valueOf(_configDao.getValue("system.vm.random.password"))) { buf.append(" vmpassword=").append(_configDao.getValue("system.vm.password")); } @@ -1289,7 +1293,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar List ssVms = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, dataCenterId, State.Running, State.Migrating, State.Starting, State.Stopped, State.Stopping ); int vmSize = (ssVms == null)? 0 : ssVms.size(); - List ssHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(dataCenterId); + List ssHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(dataCenterId); int hostSize = (ssHosts == null)? 0 : ssHosts.size(); if ( hostSize > vmSize ) { s_logger.info("No secondary storage vms found in datacenter id=" + dataCenterId + ", starting a new one"); @@ -1320,9 +1324,9 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar if (!(firstCmd instanceof StartupSecondaryStorageCommand)) { return null; } - + host.setType( com.cloud.host.Host.Type.SecondaryStorageVM); - return host; + return host; } @Override @@ -1368,7 +1372,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar host.setStorageUrl(ssCmd.getNfsShare()); } } - + return host; } @@ -1452,7 +1456,28 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } return null; } - + + + @Override + public HostVO pickSsvmHost(DataStore store) { + if ( store.getRole() == DataStoreRole.Image){ + Long dcId = null; + Scope storeScope = store.getScope(); + if ( storeScope.getScopeType() == ScopeType.ZONE ){ + dcId = storeScope.getScopeId(); + } + // find ssvm that can be used to download data to store. For zone-wide image store, use SSVM for that zone. For region-wide store, + // we can arbitrarily pick one ssvm to do that task + List ssAHosts = listUpAndConnectingSecondaryStorageVmHost(dcId); + if (ssAHosts == null || ssAHosts.isEmpty() ) { + return null; + } + Collections.shuffle(ssAHosts); + return ssAHosts.get(0); + } + return null; + } + @Override public boolean plugNic(Network network, NicTO nic, VirtualMachineTO vm, ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException, @@ -1471,6 +1496,6 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar @Override public void prepareStop(VirtualMachineProfile profile) { - + } } diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageVmManager.java b/server/src/com/cloud/storage/secondary/SecondaryStorageVmManager.java index d315d22cdd6..8565c38cc08 100755 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageVmManager.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageVmManager.java @@ -18,6 +18,8 @@ package com.cloud.storage.secondary; import java.util.List; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; + import com.cloud.agent.api.Command; import com.cloud.agent.api.StartupCommand; import com.cloud.host.HostVO; @@ -29,12 +31,12 @@ 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_MTUSIZE = 1500; + public static final int DEFAULT_SS_VM_MTUSIZE = 1500; 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"; - + public SecondaryStorageVmVO startSecStorageVm(long ssVmVmId); public boolean stopSecStorageVm(long ssVmVmId); public boolean rebootSecStorageVm(long ssVmVmId); @@ -42,7 +44,7 @@ public interface SecondaryStorageVmManager extends Manager { public void onAgentConnect(Long dcId, StartupCommand cmd); public boolean generateFirewallConfiguration(Long agentId); public boolean generateVMSetupCommand(Long hostId); - + public Pair assignSecStorageVm(long zoneId, Command cmd); boolean generateSetupCommand(Long hostId); boolean deleteHost(Long hostId); @@ -53,4 +55,5 @@ public interface SecondaryStorageVmManager extends Manager { public List listAllTypesSecondaryStorageHostsInOneZone(long dataCenterId); public List listUpAndConnectingSecondaryStorageVmHost(Long dcId); public HostVO pickSsvmHost(HostVO ssHost); + public HostVO pickSsvmHost(DataStore store); } diff --git a/server/src/com/cloud/template/HypervisorTemplateAdapter.java b/server/src/com/cloud/template/HypervisorTemplateAdapter.java index 491900b44e6..709288eca00 100755 --- a/server/src/com/cloud/template/HypervisorTemplateAdapter.java +++ b/server/src/com/cloud/template/HypervisorTemplateAdapter.java @@ -37,6 +37,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole; import org.apache.cloudstack.engine.subsystem.api.storage.ImageDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.ImageService; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.framework.async.AsyncCallFuture; import org.apache.log4j.Logger; @@ -50,6 +51,7 @@ import com.cloud.event.UsageEventUtils; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.ResourceAllocationException; import com.cloud.host.HostVO; +import com.cloud.storage.ScopeType; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.TemplateProfile; @@ -81,7 +83,7 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase implements Te public String getName() { return TemplateAdapterType.Hypervisor.getName(); } - + private String validateUrl(String url) { try { URI uri = new URI(url); @@ -164,23 +166,30 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase implements Te @Override public VMTemplateVO create(TemplateProfile profile) { + // persist entry in vm_template, vm_template_details and template_zone_ref tables VMTemplateVO template = persistTemplate(profile); if (template == null) { throw new CloudRuntimeException("Unable to persist the template " + profile.getTemplate()); } - DataStore imageStore = this.storeMgr.getDataStore(profile.getImageStoreId(), DataStoreRole.Image); - - AsyncCallFuture future = this.imageService.createTemplateAsync(this.imageFactory.getTemplate(template.getId()), imageStore); - try { - future.get(); - } catch (InterruptedException e) { - s_logger.debug("create template Failed", e); - throw new CloudRuntimeException("create template Failed", e); - } catch (ExecutionException e) { - s_logger.debug("create template Failed", e); - throw new CloudRuntimeException("create template Failed", e); + // find all eligible image stores for this zone scope + List imageStores = this.storeMgr.getImageStoresByScope(new ZoneScope(profile.getZoneId())); + if ( imageStores == null || imageStores.size() == 0 ){ + throw new CloudRuntimeException("Unable to find image store to download template "+ profile.getTemplate()); + } + for (DataStore imageStore : imageStores) { + AsyncCallFuture future = this.imageService + .createTemplateAsync(this.imageFactory.getTemplate(template.getId()), imageStore); + try { + future.get(); + } catch (InterruptedException e) { + s_logger.debug("create template Failed", e); + throw new CloudRuntimeException("create template Failed", e); + } catch (ExecutionException e) { + s_logger.debug("create template Failed", e); + throw new CloudRuntimeException("create template Failed", e); + } } _resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template); _resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.secondary_storage, diff --git a/server/src/com/cloud/template/TemplateAdapter.java b/server/src/com/cloud/template/TemplateAdapter.java index 1f8f491cb25..766afa85c7d 100755 --- a/server/src/com/cloud/template/TemplateAdapter.java +++ b/server/src/com/cloud/template/TemplateAdapter.java @@ -33,19 +33,19 @@ import com.cloud.utils.component.Adapter; public interface TemplateAdapter extends Adapter { public static class TemplateAdapterType { String _name; - + public static final TemplateAdapterType Hypervisor = new TemplateAdapterType("HypervisorAdapter"); public static final TemplateAdapterType BareMetal = new TemplateAdapterType("BareMetalAdapter"); - + public TemplateAdapterType(String name) { _name = name; } - + public String getName() { return _name; } } - + public TemplateProfile prepare(RegisterTemplateCmd cmd) throws ResourceAllocationException; public TemplateProfile prepare(RegisterIsoCmd cmd) throws ResourceAllocationException; @@ -57,14 +57,14 @@ public interface TemplateAdapter extends Adapter { public TemplateProfile prepareDelete(DeleteIsoCmd cmd); public boolean delete(TemplateProfile profile); - + public TemplateProfile prepare(boolean isIso, Long userId, String name, String displayText, Integer bits, Boolean passwordEnabled, Boolean requiresHVM, String url, Boolean isPublic, Boolean featured, Boolean isExtractable, String format, Long guestOSId, Long zoneId, HypervisorType hypervisorType, String accountName, Long domainId, String chksum, Boolean bootable, Map details) throws ResourceAllocationException; - + public TemplateProfile prepare(boolean isIso, long userId, String name, String displayText, Integer bits, Boolean passwordEnabled, Boolean requiresHVM, String url, Boolean isPublic, Boolean featured, Boolean isExtractable, String format, Long guestOSId, Long zoneId, HypervisorType hypervisorType, - String chksum, Boolean bootable, String templateTag, Account templateOwner, Map details, Boolean sshKeyEnabled, String imageStoreUuid) throws ResourceAllocationException; + String chksum, Boolean bootable, String templateTag, Account templateOwner, Map details, Boolean sshKeyEnabled) throws ResourceAllocationException; } diff --git a/server/src/com/cloud/template/TemplateAdapterBase.java b/server/src/com/cloud/template/TemplateAdapterBase.java index 1b114250621..1e79b60f150 100755 --- a/server/src/com/cloud/template/TemplateAdapterBase.java +++ b/server/src/com/cloud/template/TemplateAdapterBase.java @@ -82,12 +82,12 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat protected @Inject ResourceLimitService _resourceLimitMgr; protected @Inject DataStoreManager storeMgr; @Inject TemplateManager templateMgr; - + @Override public boolean stop() { return true; } - + private static boolean isAdmin(short accountType) { return ((accountType == Account.ACCOUNT_TYPE_ADMIN) || (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) || @@ -100,34 +100,24 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat Boolean isExtractable, String format, Long guestOSId, Long zoneId, HypervisorType hypervisorType, String accountName, Long domainId, String chksum, Boolean bootable, Map details) throws ResourceAllocationException { return prepare(isIso, userId, name, displayText, bits, passwordEnabled, requiresHVM, url, isPublic, featured, isExtractable, format, guestOSId, zoneId, hypervisorType, - chksum, bootable, null, null, details, false, null); + chksum, bootable, null, null, details, false); } - + public TemplateProfile prepare(boolean isIso, long userId, String name, String displayText, Integer bits, Boolean passwordEnabled, Boolean requiresHVM, String url, Boolean isPublic, Boolean featured, Boolean isExtractable, String format, Long guestOSId, Long zoneId, HypervisorType hypervisorType, - String chksum, Boolean bootable, String templateTag, Account templateOwner, Map details, Boolean sshkeyEnabled, - String imageStoreUuid) throws ResourceAllocationException { - //Long accountId = null; + String chksum, Boolean bootable, String templateTag, Account templateOwner, Map details, Boolean sshkeyEnabled) throws ResourceAllocationException { + // parameters verification - - String storeUuid = imageStoreUuid; - if (storeUuid != null) { - DataStore store = this.storeMgr.getDataStore(storeUuid, DataStoreRole.Image); - if (store == null) { - throw new InvalidParameterValueException("invalide image store uuid" + storeUuid); - } - - } - + if (isPublic == null) { isPublic = Boolean.FALSE; } - + if (zoneId.longValue() == -1) { zoneId = null; } - + if (isIso) { if (bootable == null) { bootable = Boolean.TRUE; @@ -148,9 +138,9 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat } if (requiresHVM == null) { requiresHVM = true; - } + } } - + if (isExtractable == null) { isExtractable = Boolean.FALSE; } @@ -167,7 +157,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat if (url.toLowerCase().contains("file://")) { throw new InvalidParameterValueException("File:// type urls are currently unsupported"); } - + boolean allowPublicUserTemplates = Boolean.parseBoolean(_configDao.getValue("allow.public.user.templates")); if (!isAdmin && !allowPublicUserTemplates && isPublic) { throw new InvalidParameterValueException("Only private templates/ISO can be created."); @@ -176,24 +166,24 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat if (!isAdmin || featured == null) { featured = Boolean.FALSE; } - + ImageFormat imgfmt = ImageFormat.valueOf(format.toUpperCase()); if (imgfmt == null) { throw new IllegalArgumentException("Image format is incorrect " + format + ". Supported formats are " + EnumUtils.listValues(ImageFormat.values())); } - + // Check that the resource limit for templates/ISOs won't be exceeded UserVO user = _userDao.findById(userId); if (user == null) { throw new IllegalArgumentException("Unable to find user with id " + userId); } - + _resourceLimitMgr.checkResourceLimit(templateOwner, ResourceType.template); - + if (templateOwner.getType() != Account.ACCOUNT_TYPE_ADMIN && zoneId == null) { throw new IllegalArgumentException("Only admins can create templates in all zones"); } - + // If a zoneId is specified, make sure it is valid if (zoneId != null) { DataCenterVO zone = _dcDao.findById(zoneId); @@ -205,39 +195,33 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: "+ zoneId ); } } - + List systemvmTmplts = _tmpltDao.listAllSystemVMTemplates(); for (VMTemplateVO template : systemvmTmplts) { if (template.getName().equalsIgnoreCase(name) || template.getDisplayText().equalsIgnoreCase(displayText)) { throw new IllegalArgumentException("Cannot use reserved names for templates"); } } - - DataStore imageStore = this.templateMgr.getImageStore(imageStoreUuid, zoneId); - if (imageStore == null) { - throw new IllegalArgumentException("Cann't find an image store"); - } - Long imageStoreId = imageStore.getId(); - + Long id = _tmpltDao.getNextInSequence(Long.class, "id"); UserContext.current().setEventDetails("Id: " +id+ " name: " + name); return new TemplateProfile(id, userId, name, displayText, bits, passwordEnabled, requiresHVM, url, isPublic, - featured, isExtractable, imgfmt, guestOSId, zoneId, hypervisorType, templateOwner.getAccountName(), templateOwner.getDomainId(), templateOwner.getAccountId(), chksum, bootable, templateTag, details, sshkeyEnabled, imageStoreId); + featured, isExtractable, imgfmt, guestOSId, zoneId, hypervisorType, templateOwner.getAccountName(), templateOwner.getDomainId(), templateOwner.getAccountId(), chksum, bootable, templateTag, details, sshkeyEnabled); } - + @Override public TemplateProfile prepare(RegisterTemplateCmd cmd) throws ResourceAllocationException { //check if the caller can operate with the template owner Account caller = UserContext.current().getCaller(); Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId()); _accountMgr.checkAccess(caller, null, true, owner); - - + + return prepare(false, UserContext.current().getCallerUserId(), cmd.getTemplateName(), cmd.getDisplayText(), cmd.getBits(), cmd.isPasswordEnabled(), cmd.getRequiresHvm(), cmd.getUrl(), cmd.isPublic(), cmd.isFeatured(), cmd.isExtractable(), cmd.getFormat(), cmd.getOsTypeId(), cmd.getZoneId(), HypervisorType.getType(cmd.getHypervisor()), - cmd.getChecksum(), true, cmd.getTemplateTag(), owner, cmd.getDetails(), cmd.isSshKeyEnabled(), cmd.getImageStoreUuid()); + cmd.getChecksum(), true, cmd.getTemplateTag(), owner, cmd.getDetails(), cmd.isSshKeyEnabled()); } public TemplateProfile prepare(RegisterIsoCmd cmd) throws ResourceAllocationException { @@ -245,24 +229,23 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat Account caller = UserContext.current().getCaller(); Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId()); _accountMgr.checkAccess(caller, null, true, owner); - + return prepare(true, UserContext.current().getCallerUserId(), cmd.getIsoName(), cmd.getDisplayText(), 64, false, true, cmd.getUrl(), cmd.isPublic(), cmd.isFeatured(), cmd.isExtractable(), ImageFormat.ISO.toString(), cmd.getOsTypeId(), - cmd.getZoneId(), HypervisorType.None, cmd.getChecksum(), cmd.isBootable(), null, owner, null, false, cmd.getImageStoreUuid()); + cmd.getZoneId(), HypervisorType.None, cmd.getChecksum(), cmd.isBootable(), null, owner, null, false); } - + protected VMTemplateVO persistTemplate(TemplateProfile profile) { Long zoneId = profile.getZoneId(); VMTemplateVO template = new VMTemplateVO(profile.getTemplateId(), profile.getName(), profile.getFormat(), profile.getIsPublic(), profile.getFeatured(), profile.getIsExtractable(), TemplateType.USER, profile.getUrl(), profile.getRequiresHVM(), profile.getBits(), profile.getAccountId(), profile.getCheckSum(), profile.getDisplayText(), - profile.getPasswordEnabled(), profile.getGuestOsId(), profile.getBootable(), profile.getHypervisorType(), profile.getTemplateTag(), + profile.getPasswordEnabled(), profile.getGuestOsId(), profile.getBootable(), profile.getHypervisorType(), profile.getTemplateTag(), profile.getDetails(), profile.getSshKeyEnabled()); - template.setImageDataStoreId(profile.getImageStoreId()); if (zoneId == null || zoneId.longValue() == -1) { List dcs = _dcDao.listAll(); - + if (dcs.isEmpty()) { throw new CloudRuntimeException("No zones are present in the system, can't add template"); } @@ -271,13 +254,13 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat for (DataCenterVO dc: dcs) { _tmpltDao.addTemplateToZone(template, dc.getId()); } - + } else { _tmpltDao.addTemplateToZone(template, zoneId); } return _tmpltDao.findById(template.getId()); } - + private Long accountAndUserValidation(Account account, long userId, UserVmVO vmInstanceCheck, VMTemplateVO template, String msg) throws PermissionDeniedException { @@ -311,7 +294,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat return userId; } - + public TemplateProfile prepareDelete(DeleteTemplateCmd cmd) { Long templateId = cmd.getId(); Long userId = UserContext.current().getCallerUserId(); @@ -342,23 +325,23 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat Long userId = UserContext.current().getCallerUserId(); Account account = UserContext.current().getCaller(); Long zoneId = cmd.getZoneId(); - + VMTemplateVO template = _tmpltDao.findById(templateId.longValue()); if (template == null) { throw new InvalidParameterValueException("unable to find iso with id " + templateId); } - + userId = accountAndUserValidation(account, userId, null, template, "Unable to delete iso " ); - + UserVO user = _userDao.findById(userId); if (user == null) { throw new InvalidParameterValueException("Please specify a valid user."); } - + if (template.getFormat() != ImageFormat.ISO) { throw new InvalidParameterValueException("Please specify a valid iso."); } - + return new TemplateProfile(userId, template, zoneId); }