diff --git a/agent/src/com/cloud/agent/AgentShell.java b/agent/src/com/cloud/agent/AgentShell.java index cf454b8c89c..e7f114bc412 100644 --- a/agent/src/com/cloud/agent/AgentShell.java +++ b/agent/src/com/cloud/agent/AgentShell.java @@ -82,6 +82,7 @@ public class AgentShell implements IAgentShell, Daemon { private int _pingRetries; private final List _agents = new ArrayList(); + public AgentShell() { } diff --git a/api/src/com/cloud/agent/api/Answer.java b/api/src/com/cloud/agent/api/Answer.java index 655f4470097..9d106115d91 100755 --- a/api/src/com/cloud/agent/api/Answer.java +++ b/api/src/com/cloud/agent/api/Answer.java @@ -23,6 +23,7 @@ public class Answer extends Command { protected String details; protected Answer() { + this(null); } public Answer(Command command) { diff --git a/engine/storage/src/org/apache/cloudstack/storage/command/CopyTemplateToPrimaryStorageAnswer.java b/api/src/com/cloud/agent/api/storage/CopyTemplateToPrimaryStorageAnswer.java similarity index 95% rename from engine/storage/src/org/apache/cloudstack/storage/command/CopyTemplateToPrimaryStorageAnswer.java rename to api/src/com/cloud/agent/api/storage/CopyTemplateToPrimaryStorageAnswer.java index b248758bc12..ecc8e576681 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/command/CopyTemplateToPrimaryStorageAnswer.java +++ b/api/src/com/cloud/agent/api/storage/CopyTemplateToPrimaryStorageAnswer.java @@ -1,3 +1,4 @@ +package com.cloud.agent.api.storage; // Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information diff --git a/core/src/com/cloud/agent/api/storage/DeleteVolumeCommand.java b/api/src/com/cloud/agent/api/storage/PasswordAuth.java old mode 100755 new mode 100644 similarity index 69% rename from core/src/com/cloud/agent/api/storage/DeleteVolumeCommand.java rename to api/src/com/cloud/agent/api/storage/PasswordAuth.java index 949af010423..f03c584c660 --- a/core/src/com/cloud/agent/api/storage/DeleteVolumeCommand.java +++ b/api/src/com/cloud/agent/api/storage/PasswordAuth.java @@ -16,23 +16,24 @@ // under the License. package com.cloud.agent.api.storage; -public class DeleteVolumeCommand extends ssCommand { - private String volumePath; +/** + * Password authentication + */ +public class PasswordAuth { - public DeleteVolumeCommand() { - } + String userName; + String password; + public PasswordAuth() { - public DeleteVolumeCommand(String secUrl, String volumePath) { - this.setSecUrl(secUrl); - this.volumePath = volumePath; } - - @Override - public boolean executeInSequence() { - return true; + public PasswordAuth(String user, String password) { + this.userName = user; + this.password = password; + } + public String getUserName() { + return userName; + } + public String getPassword() { + return password; } - - public String getVolumePath() { - return volumePath; - } } diff --git a/api/src/com/cloud/agent/api/storage/Proxy.java b/api/src/com/cloud/agent/api/storage/Proxy.java new file mode 100644 index 00000000000..5adc1146bed --- /dev/null +++ b/api/src/com/cloud/agent/api/storage/Proxy.java @@ -0,0 +1,72 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.agent.api.storage; + +import java.net.URI; + +/** + * Download Proxy + */ +public class Proxy { + private String _host; + private int _port; + private String _userName; + private String _password; + + public Proxy() { + + } + + public Proxy(String host, int port, String userName, String password) { + this._host = host; + this._port = port; + this._userName = userName; + this._password = password; + } + + public Proxy(URI uri) { + this._host = uri.getHost(); + this._port = uri.getPort() == -1 ? 3128 : uri.getPort(); + String userInfo = uri.getUserInfo(); + if (userInfo != null) { + String[] tokens = userInfo.split(":"); + if (tokens.length == 1) { + this._userName = userInfo; + this._password = ""; + } else if (tokens.length == 2) { + this._userName = tokens[0]; + this._password = tokens[1]; + } + } + } + + public String getHost() { + return _host; + } + + public int getPort() { + return _port; + } + + public String getUserName() { + return _userName; + } + + public String getPassword() { + return _password; + } +} diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectType.java b/api/src/com/cloud/agent/api/to/DataObjectType.java similarity index 93% rename from engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectType.java rename to api/src/com/cloud/agent/api/to/DataObjectType.java index b4d1a57c88c..6f7a007e787 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectType.java +++ b/api/src/com/cloud/agent/api/to/DataObjectType.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.engine.subsystem.api.storage; +package com.cloud.agent.api.to; public enum DataObjectType { VOLUME, diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ImageDataStoreProvider.java b/api/src/com/cloud/agent/api/to/DataStoreTO.java similarity index 85% rename from engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ImageDataStoreProvider.java rename to api/src/com/cloud/agent/api/to/DataStoreTO.java index 1fb987e81cd..9014f8e2b81 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ImageDataStoreProvider.java +++ b/api/src/com/cloud/agent/api/to/DataStoreTO.java @@ -16,9 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.engine.subsystem.api.storage; +package com.cloud.agent.api.to; + +import com.cloud.storage.DataStoreRole; -public interface ImageDataStoreProvider extends DataStoreProvider { - +public interface DataStoreTO { + public DataStoreRole getRole(); } diff --git a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/ImageMotionStrategy.java b/api/src/com/cloud/agent/api/to/DataTO.java similarity index 79% rename from engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/ImageMotionStrategy.java rename to api/src/com/cloud/agent/api/to/DataTO.java index 7a476367d37..21e802fde1f 100644 --- a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/ImageMotionStrategy.java +++ b/api/src/com/cloud/agent/api/to/DataTO.java @@ -16,9 +16,15 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.storage.image.motion; +package com.cloud.agent.api.to; -import org.apache.cloudstack.storage.motion.DataMotionStrategy; +public interface DataTO { + public DataObjectType getObjectType(); + public DataStoreTO getDataStore(); + /** + * @return + */ + String getPath(); -public interface ImageMotionStrategy extends DataMotionStrategy { + long getId(); } diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/DataStoreProviderDaoImpl.java b/api/src/com/cloud/agent/api/to/DiskTO.java similarity index 51% rename from engine/api/src/org/apache/cloudstack/storage/datastore/db/DataStoreProviderDaoImpl.java rename to api/src/com/cloud/agent/api/to/DiskTO.java index ccb6b483253..7b32f006606 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/DataStoreProviderDaoImpl.java +++ b/api/src/com/cloud/agent/api/to/DiskTO.java @@ -16,23 +16,45 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.storage.datastore.db; +package com.cloud.agent.api.to; -import org.springframework.stereotype.Component; +import com.cloud.storage.Volume; -import com.cloud.utils.db.GenericDaoBase; -import com.cloud.utils.db.SearchCriteria2; -import com.cloud.utils.db.SearchCriteriaService; -import com.cloud.utils.db.SearchCriteria.Op; - -@Component -class DataStoreProviderDaoImpl extends GenericDaoBase implements DataStoreProviderDao { - - @Override - public DataStoreProviderVO findByName(String name) { - SearchCriteriaService sc = SearchCriteria2.create(DataStoreProviderVO.class); - sc.addAnd(sc.getEntity().getName(), Op.EQ, name); - return sc.find(); +public class DiskTO { + private DataTO data; + private Long diskSeq; + private Volume.Type type; + public DiskTO() { + + } + + public DiskTO(DataTO data, Long diskSeq, Volume.Type type) { + this.data = data; + this.diskSeq = diskSeq; + this.type = type; } -} \ No newline at end of file + public DataTO getData() { + return data; + } + + public void setData(DataTO data) { + this.data = data; + } + + public Long getDiskSeq() { + return diskSeq; + } + + public void setDiskSeq(Long diskSeq) { + this.diskSeq = diskSeq; + } + + public Volume.Type getType() { + return type; + } + + public void setType(Volume.Type type) { + this.type = type; + } +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/to/NfsPrimaryDataStoreTO.java b/api/src/com/cloud/agent/api/to/NfsTO.java similarity index 57% rename from engine/storage/src/org/apache/cloudstack/storage/to/NfsPrimaryDataStoreTO.java rename to api/src/com/cloud/agent/api/to/NfsTO.java index 96fb6bb2401..5490fd1e588 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/to/NfsPrimaryDataStoreTO.java +++ b/api/src/com/cloud/agent/api/to/NfsTO.java @@ -14,31 +14,47 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package org.apache.cloudstack.storage.to; +package com.cloud.agent.api.to; -import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; +import com.cloud.storage.DataStoreRole; + +public final class NfsTO implements DataStoreTO { + + private String _url; + private DataStoreRole _role; + + public NfsTO() { + + super(); -public class NfsPrimaryDataStoreTO extends PrimaryDataStoreTO { - private String server; - private String path; - - public NfsPrimaryDataStoreTO(PrimaryDataStoreInfo dataStore) { - super(dataStore); } - - public void setServer(String server) { - this.server = server; + + public NfsTO(String url, DataStoreRole role) { + + super(); + + this._url = url; + this._role = role; + } - - public String getServer() { - return this.server; + + public String getUrl() { + return _url; } - - public void setPath(String path) { - this.path = path; + + public void setUrl(String _url) { + this._url = _url; } - - public String getPath() { - return this.path; + + @Override + public DataStoreRole getRole() { + return _role; } + + public void setRole(DataStoreRole _role) { + this._role = _role; + } + + + } diff --git a/api/src/com/cloud/agent/api/to/S3TO.java b/api/src/com/cloud/agent/api/to/S3TO.java index d556cb6d05d..8a2f09dc5ab 100644 --- a/api/src/com/cloud/agent/api/to/S3TO.java +++ b/api/src/com/cloud/agent/api/to/S3TO.java @@ -18,9 +18,10 @@ package com.cloud.agent.api.to; import java.util.Date; +import com.cloud.storage.DataStoreRole; import com.cloud.utils.S3Utils; -public final class S3TO implements S3Utils.ClientOptions { +public final class S3TO implements S3Utils.ClientOptions, DataStoreTO { private Long id; private String uuid; @@ -33,6 +34,7 @@ public final class S3TO implements S3Utils.ClientOptions { private Integer maxErrorRetry; private Integer socketTimeout; private Date created; + private boolean enableRRS; public S3TO() { @@ -44,7 +46,7 @@ public final class S3TO implements S3Utils.ClientOptions { final String secretKey, final String endPoint, final String bucketName, final Boolean httpsFlag, final Integer connectionTimeout, final Integer maxErrorRetry, - final Integer socketTimeout, final Date created) { + final Integer socketTimeout, final Date created, final boolean enableRRS) { super(); @@ -59,6 +61,7 @@ public final class S3TO implements S3Utils.ClientOptions { this.maxErrorRetry = maxErrorRetry; this.socketTimeout = socketTimeout; this.created = created; + this.enableRRS = enableRRS; } @@ -128,6 +131,10 @@ public final class S3TO implements S3Utils.ClientOptions { return false; } + if (enableRRS != thatS3TO.enableRRS) { + return false; + } + return true; } @@ -249,4 +256,20 @@ public final class S3TO implements S3Utils.ClientOptions { this.created = created; } + @Override + public DataStoreRole getRole() { + return DataStoreRole.Image; + } + + + + public boolean getEnableRRS() { + return enableRRS; + } + + public void setEnableRRS(boolean enableRRS) { + this.enableRRS = enableRRS; + } + + } diff --git a/api/src/com/cloud/agent/api/to/SwiftTO.java b/api/src/com/cloud/agent/api/to/SwiftTO.java index 32742c7d0e3..e1697f91041 100644 --- a/api/src/com/cloud/agent/api/to/SwiftTO.java +++ b/api/src/com/cloud/agent/api/to/SwiftTO.java @@ -16,7 +16,9 @@ // under the License. package com.cloud.agent.api.to; -public class SwiftTO { +import com.cloud.storage.DataStoreRole; + +public class SwiftTO implements DataStoreTO { Long id; String url; String account; @@ -54,5 +56,11 @@ public class SwiftTO { return key; } + @Override + public DataStoreRole getRole() { + return DataStoreRole.Image; + } + + } diff --git a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java index 46ee01bc8a3..e6240ffda10 100644 --- a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java +++ b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java @@ -58,7 +58,7 @@ public class VirtualMachineTO { Map params; String uuid; - VolumeTO[] disks; + DiskTO[] disks; NicTO[] nics; public VirtualMachineTO(long id, String instanceName, VirtualMachine.Type type, int cpus, Integer speed, long minRam, long maxRam, BootloaderType bootloader, String os, boolean enableHA, boolean limitCpuUse, String vncPassword) { @@ -215,11 +215,11 @@ public class VirtualMachineTO { this.bootupScripts = bootupScripts; } - public VolumeTO[] getDisks() { + public DiskTO[] getDisks() { return disks; } - public void setDisks(VolumeTO[] disks) { + public void setDisks(DiskTO[] disks) { this.disks = disks; } diff --git a/api/src/com/cloud/server/ManagementService.java b/api/src/com/cloud/server/ManagementService.java index 24d33d5a3f8..8d00ef202fd 100755 --- a/api/src/com/cloud/server/ManagementService.java +++ b/api/src/com/cloud/server/ManagementService.java @@ -124,15 +124,6 @@ public interface ManagementService { */ Pair, Integer> searchForServers(ListHostsCmd cmd); - /** - * Creates a new template - * - * @param cmd - * @return updated template - */ - VirtualMachineTemplate updateTemplate(UpdateIsoCmd cmd); - - VirtualMachineTemplate updateTemplate(UpdateTemplateCmd cmd); @@ -223,28 +214,6 @@ public interface ManagementService { */ List listCapacities(ListCapacityCmd cmd); - /** - * List ISOs that match the specified criteria. - * - * @param cmd - * The command that wraps the (optional) templateId, name, keyword, templateFilter, bootable, account, - * and zoneId - * parameters. - * @return list of ISOs - */ - Set> listIsos(ListIsosCmd cmd); - - /** - * List templates that match the specified criteria. - * - * @param cmd - * The command that wraps the (optional) templateId, name, keyword, templateFilter, bootable, account, - * and zoneId - * parameters. - * @return list of ISOs - */ - Set> listTemplates(ListTemplatesCmd cmd); - /** * List system VMs by the given search criteria @@ -271,20 +240,6 @@ public interface ManagementService { Map listCapabilities(ListCapabilitiesCmd cmd); - /** - * Extracts the volume to a particular location. - * - * @param cmd - * the command specifying url (where the volume needs to be extracted to), zoneId (zone where the volume - * exists), - * id (the id of the volume) - * @throws URISyntaxException - * @throws InternalErrorException - * @throws PermissionDeniedException - * - */ - Long extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException; - /** * return an array of available hypervisors * @@ -412,7 +367,7 @@ public interface ManagementService { * @return List of capacities */ List listTopConsumedResources(ListCapacityCmd cmd); - + List listDeploymentPlanners(); VirtualMachine upgradeSystemVM(ScaleSystemVMCmd cmd) throws ResourceUnavailableException, ManagementServerException, VirtualMachineMigrationException, ConcurrentOperationException; diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreRole.java b/api/src/com/cloud/storage/DataStoreRole.java similarity index 96% rename from engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreRole.java rename to api/src/com/cloud/storage/DataStoreRole.java index a45ca7a6c8e..0448d29e75e 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreRole.java +++ b/api/src/com/cloud/storage/DataStoreRole.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.engine.subsystem.api.storage; +package com.cloud.storage; import com.cloud.utils.exception.CloudRuntimeException; diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/PrimaryDataStoreDriver.java b/api/src/com/cloud/storage/GuestOSHypervisor.java similarity index 77% rename from engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/PrimaryDataStoreDriver.java rename to api/src/com/cloud/storage/GuestOSHypervisor.java index b248758bc12..f022722af04 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/PrimaryDataStoreDriver.java +++ b/api/src/com/cloud/storage/GuestOSHypervisor.java @@ -14,3 +14,15 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. +package com.cloud.storage; + +import org.apache.cloudstack.api.InternalIdentity; + +public interface GuestOSHypervisor extends InternalIdentity { + + String getHypervisorType(); + + String getGuestOsName(); + + long getGuestOsId(); +} diff --git a/core/src/com/cloud/agent/api/storage/DeleteTemplateCommand.java b/api/src/com/cloud/storage/ImageStore.java similarity index 62% rename from core/src/com/cloud/agent/api/storage/DeleteTemplateCommand.java rename to api/src/com/cloud/storage/ImageStore.java index 69f465c6b16..d2a72a21fa6 100644 --- a/core/src/com/cloud/agent/api/storage/DeleteTemplateCommand.java +++ b/api/src/com/cloud/storage/ImageStore.java @@ -14,27 +14,34 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.agent.api.storage; +package com.cloud.storage; + +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +public interface ImageStore extends Identity, InternalIdentity { -public class DeleteTemplateCommand extends ssCommand { - private String templatePath; + /** + * @return name of the object store. + */ + String getName(); + + /** + * @return availability zone. + */ + Long getDataCenterId(); - public DeleteTemplateCommand() { - } + /** + * @return object store provider name + */ + String getProviderName(); - public DeleteTemplateCommand(String secUrl, String templatePath) { - this.setSecUrl(secUrl); - this.templatePath = templatePath; - } - @Override - public boolean executeInSequence() { - return true; - } - - public String getTemplatePath() { - return templatePath; - } + /** + * + * @return data store protocol + */ + String getProtocol(); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ScopeType.java b/api/src/com/cloud/storage/ScopeType.java similarity index 93% rename from engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ScopeType.java rename to api/src/com/cloud/storage/ScopeType.java index a3d21ce9bef..c9786d8d353 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ScopeType.java +++ b/api/src/com/cloud/storage/ScopeType.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.engine.subsystem.api.storage; +package com.cloud.storage; public enum ScopeType { HOST, diff --git a/api/src/com/cloud/storage/Snapshot.java b/api/src/com/cloud/storage/Snapshot.java index f71265cd230..27a2fe43f9f 100644 --- a/api/src/com/cloud/storage/Snapshot.java +++ b/api/src/com/cloud/storage/Snapshot.java @@ -18,12 +18,13 @@ package com.cloud.storage; import java.util.Date; -import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.utils.fsm.StateObject; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.utils.fsm.StateObject; + public interface Snapshot extends ControlledEntity, Identity, InternalIdentity, StateObject { public enum Type { MANUAL, @@ -59,6 +60,9 @@ public interface Snapshot extends ControlledEntity, Identity, InternalIdentity, CreatedOnPrimary, BackingUp, BackedUp, + Copying, + Destroying, + Destroyed,//it's a state, user can't see the snapshot from ui, while the snapshot may still exist on the storage Error; public String toString() { @@ -75,6 +79,8 @@ public interface Snapshot extends ControlledEntity, Identity, InternalIdentity, OperationNotPerformed, BackupToSecondary, BackedupToSecondary, + DestroyRequested, + CopyingRequested, OperationSucceeded, OperationFailed } @@ -85,8 +91,6 @@ public interface Snapshot extends ControlledEntity, Identity, InternalIdentity, long getVolumeId(); - String getPath(); - String getName(); Date getCreated(); diff --git a/api/src/com/cloud/storage/Storage.java b/api/src/com/cloud/storage/Storage.java index 0c3bb8bc2e5..16ef0192e32 100755 --- a/api/src/com/cloud/storage/Storage.java +++ b/api/src/com/cloud/storage/Storage.java @@ -21,13 +21,13 @@ import java.util.List; public class Storage { public static enum ImageFormat { - QCOW2(true, true, false), - RAW(false, false, false), - VHD(true, true, true), - ISO(false, false, false), + QCOW2(true, true, false, "qcow2"), + RAW(false, false, false, "raw"), + VHD(true, true, true, "vhd"), + ISO(false, false, false, "iso"), OVA(true, true, true, "ova"), - BAREMETAL(false, false, false), - TAR(false, false, false); + BAREMETAL(false, false, false, "BAREMETAL"), + TAR(false, false, false, "tar"); private final boolean thinProvisioned; private final boolean supportSparse; @@ -66,6 +66,7 @@ public class Storage { return fileExtension; } + } public static enum FileSystem { diff --git a/api/src/com/cloud/storage/StoragePool.java b/api/src/com/cloud/storage/StoragePool.java index 8b95383c537..8f8b8644ddc 100644 --- a/api/src/com/cloud/storage/StoragePool.java +++ b/api/src/com/cloud/storage/StoragePool.java @@ -58,7 +58,7 @@ public interface StoragePool extends Identity, InternalIdentity { /** * @return available storage in bytes */ - long getAvailableBytes(); + long getUsedBytes(); Long getClusterId(); diff --git a/api/src/com/cloud/storage/StorageService.java b/api/src/com/cloud/storage/StorageService.java index 63c5023ee91..869b2960e1c 100644 --- a/api/src/com/cloud/storage/StorageService.java +++ b/api/src/com/cloud/storage/StorageService.java @@ -18,12 +18,17 @@ package com.cloud.storage; import java.net.UnknownHostException; +import org.apache.cloudstack.api.command.admin.storage.AddImageStoreCmd; import org.apache.cloudstack.api.command.admin.storage.CancelPrimaryStorageMaintenanceCmd; +import org.apache.cloudstack.api.command.admin.storage.CreateCacheStoreCmd; import org.apache.cloudstack.api.command.admin.storage.CreateStoragePoolCmd; +import org.apache.cloudstack.api.command.admin.storage.DeleteImageStoreCmd; import org.apache.cloudstack.api.command.admin.storage.DeletePoolCmd; import org.apache.cloudstack.api.command.admin.storage.UpdateStoragePoolCmd; +import com.cloud.exception.DiscoveryException; import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.ResourceInUseException; import com.cloud.exception.ResourceUnavailableException; @@ -43,6 +48,8 @@ public interface StorageService{ */ StoragePool createPool(CreateStoragePoolCmd cmd) throws ResourceInUseException, IllegalArgumentException, UnknownHostException, ResourceUnavailableException; + + ImageStore createCacheStore(CreateCacheStoreCmd cmd); /** * Delete the storage pool @@ -82,4 +89,9 @@ public interface StorageService{ public StoragePool updateStoragePool(UpdateStoragePoolCmd cmd) throws IllegalArgumentException; public StoragePool getStoragePool(long id); + + boolean deleteImageStore(DeleteImageStoreCmd cmd); + + ImageStore discoverImageStore(AddImageStoreCmd cmd) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException; + } diff --git a/api/src/com/cloud/storage/Upload.java b/api/src/com/cloud/storage/Upload.java index ac3836caf55..69e10418a27 100755 --- a/api/src/com/cloud/storage/Upload.java +++ b/api/src/com/cloud/storage/Upload.java @@ -35,7 +35,7 @@ public interface Upload extends InternalIdentity, Identity { FTP_UPLOAD, HTTP_DOWNLOAD } - long getHostId(); + long getDataStoreId(); Date getCreated(); diff --git a/api/src/com/cloud/storage/Volume.java b/api/src/com/cloud/storage/Volume.java index 4903594f0af..f5ed4e267b6 100755 --- a/api/src/com/cloud/storage/Volume.java +++ b/api/src/com/cloud/storage/Volume.java @@ -44,6 +44,7 @@ public interface Volume extends ControlledEntity, Identity, InternalIdentity, Ba Destroying("The volume is destroying, and can't be recovered."), UploadOp ("The volume upload operation is in progress or in short the volume is on secondary storage"), Uploading("volume is uploading"), + Copying("volume is copying from image store to primary, in case it's an uploaded volume"), Uploaded("volume is uploaded"); String _description; @@ -73,9 +74,9 @@ public interface Volume extends ControlledEntity, Identity, InternalIdentity, Ba s_fsm.addTransition(Resizing, Event.OperationSucceeded, Ready); s_fsm.addTransition(Resizing, Event.OperationFailed, Ready); s_fsm.addTransition(Allocated, Event.UploadRequested, UploadOp); - s_fsm.addTransition(Uploaded, Event.CopyRequested, Creating);// CopyRequested for volume from sec to primary storage - s_fsm.addTransition(Creating, Event.CopySucceeded, Ready); - s_fsm.addTransition(Creating, Event.CopyFailed, Uploaded);// Copying volume from sec to primary failed. + s_fsm.addTransition(Uploaded, Event.CopyRequested, Copying); + s_fsm.addTransition(Copying, Event.OperationSucceeded, Ready); + s_fsm.addTransition(Copying, Event.OperationFailed, Uploaded); s_fsm.addTransition(UploadOp, Event.DestroyRequested, Destroy); s_fsm.addTransition(Ready, Event.DestroyRequested, Destroy); s_fsm.addTransition(Destroy, Event.ExpungingRequested, Expunging); @@ -152,7 +153,7 @@ public interface Volume extends ControlledEntity, Identity, InternalIdentity, Ba Date getCreated(); - long getDiskOfferingId(); + Long getDiskOfferingId(); String getChainInfo(); @@ -173,4 +174,5 @@ public interface Volume extends ControlledEntity, Identity, InternalIdentity, Ba * @param reserv */ void setReservationId(String reserv); + Storage.ImageFormat getFormat(); } diff --git a/api/src/com/cloud/storage/VolumeApiService.java b/api/src/com/cloud/storage/VolumeApiService.java index 7e5ebe21200..95f962df374 100644 --- a/api/src/com/cloud/storage/VolumeApiService.java +++ b/api/src/com/cloud/storage/VolumeApiService.java @@ -18,9 +18,12 @@ */ package com.cloud.storage; +import java.net.URISyntaxException; + import org.apache.cloudstack.api.command.user.volume.*; import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InternalErrorException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; import com.cloud.user.Account; @@ -36,7 +39,7 @@ public interface VolumeApiService { * @throws PermissionDeniedException */ Volume allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationException; - + /** * Creates the volume based on the given criteria * @@ -50,7 +53,7 @@ public interface VolumeApiService { /** * Resizes the volume based on the given criteria - * + * * @param cmd * the API command wrapping the criteria * @return the volume object @@ -58,7 +61,7 @@ public interface VolumeApiService { */ Volume resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationException; - Volume migrateVolume(MigrateVolumeCmd cmd) throws ConcurrentOperationException; + Volume migrateVolume(MigrateVolumeCmd cmd); /** * Uploads the volume to secondary storage @@ -75,5 +78,24 @@ public interface VolumeApiService { Volume detachVolumeFromVM(DetachVolumeCmd cmmd); + Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account) + throws ResourceAllocationException; + + Snapshot allocSnapshot(Long volumeId, Long policyId) + throws ResourceAllocationException; Volume updateVolume(UpdateVolumeCmd updateVolumeCmd); + + /** + * Extracts the volume to a particular location. + * + * @param cmd + * the command specifying url (where the volume needs to be extracted to), zoneId (zone where the volume + * exists), + * id (the id of the volume) + * @throws URISyntaxException + * @throws InternalErrorException + * @throws PermissionDeniedException + * + */ + String extractVolume(ExtractVolumeCmd cmd); } diff --git a/api/src/com/cloud/storage/snapshot/SnapshotService.java b/api/src/com/cloud/storage/snapshot/SnapshotApiService.java similarity index 99% rename from api/src/com/cloud/storage/snapshot/SnapshotService.java rename to api/src/com/cloud/storage/snapshot/SnapshotApiService.java index b5325f52080..23e65220ff9 100644 --- a/api/src/com/cloud/storage/snapshot/SnapshotService.java +++ b/api/src/com/cloud/storage/snapshot/SnapshotApiService.java @@ -31,7 +31,7 @@ import com.cloud.storage.Volume; import com.cloud.user.Account; import com.cloud.utils.Pair; -public interface SnapshotService { +public interface SnapshotApiService { /** * List all snapshots of a disk volume. Optionally lists snapshots created by specified interval diff --git a/api/src/com/cloud/storage/template/TemplateInfo.java b/api/src/com/cloud/storage/template/TemplateProp.java similarity index 91% rename from api/src/com/cloud/storage/template/TemplateInfo.java rename to api/src/com/cloud/storage/template/TemplateProp.java index 6559d73b18d..0a2efc12e67 100644 --- a/api/src/com/cloud/storage/template/TemplateInfo.java +++ b/api/src/com/cloud/storage/template/TemplateProp.java @@ -16,7 +16,7 @@ // under the License. package com.cloud.storage.template; -public class TemplateInfo { +public class TemplateProp { String templateName; String installPath; long size; @@ -25,11 +25,11 @@ public class TemplateInfo { boolean isPublic; boolean isCorrupted; - protected TemplateInfo() { + protected TemplateProp() { } - public TemplateInfo(String templateName, String installPath, long size, long physicalSize, boolean isPublic, boolean isCorrupted) { + public TemplateProp(String templateName, String installPath, long size, long physicalSize, boolean isPublic, boolean isCorrupted) { this.templateName = templateName; this.installPath = installPath; this.size = size; @@ -38,7 +38,7 @@ public class TemplateInfo { this.isCorrupted = isCorrupted; } - public TemplateInfo(String templateName, String installPath, boolean isPublic, boolean isCorrupted) { + public TemplateProp(String templateName, String installPath, boolean isPublic, boolean isCorrupted) { this(templateName, installPath, 0, 0, isPublic, isCorrupted); } diff --git a/api/src/com/cloud/template/TemplateService.java b/api/src/com/cloud/template/TemplateApiService.java similarity index 86% rename from api/src/com/cloud/template/TemplateService.java rename to api/src/com/cloud/template/TemplateApiService.java index 7e831fb0055..26f381914c9 100755 --- a/api/src/com/cloud/template/TemplateService.java +++ b/api/src/com/cloud/template/TemplateApiService.java @@ -24,19 +24,22 @@ import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoPermissionsCmd; import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd; import org.apache.cloudstack.api.command.user.iso.ExtractIsoCmd; import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd; +import org.apache.cloudstack.api.command.user.iso.UpdateIsoCmd; import org.apache.cloudstack.api.command.user.template.CopyTemplateCmd; import org.apache.cloudstack.api.command.user.template.CreateTemplateCmd; import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd; import org.apache.cloudstack.api.command.user.template.ExtractTemplateCmd; import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd; +import org.apache.cloudstack.api.command.user.template.UpdateTemplateCmd; import com.cloud.exception.InternalErrorException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.StorageUnavailableException; import com.cloud.user.Account; +import com.cloud.utils.Pair; import com.cloud.utils.exception.CloudRuntimeException; -public interface TemplateService { +public interface TemplateApiService { VirtualMachineTemplate registerTemplate(RegisterTemplateCmd cmd) throws URISyntaxException, ResourceAllocationException; @@ -72,29 +75,32 @@ public interface TemplateService { * * @param cmd * - the command specifying the mode and id of the ISO - * @return extractId. + * @return extractUrl extract url. */ - Long extract(ExtractIsoCmd cmd) throws InternalErrorException; + String extract(ExtractIsoCmd cmd) throws InternalErrorException; /** * Extracts a Template * * @param cmd * - the command specifying the mode and id of the template - * @return extractId + * @return extractUrl extract url */ - Long extract(ExtractTemplateCmd cmd) throws InternalErrorException; + String extract(ExtractTemplateCmd cmd) throws InternalErrorException; VirtualMachineTemplate getTemplate(long templateId); List listTemplatePermissions(BaseListTemplateOrIsoPermissionsCmd cmd); boolean updateTemplateOrIsoPermissions(BaseUpdateTemplateOrIsoPermissionsCmd cmd); - + VirtualMachineTemplate createPrivateTemplateRecord(CreateTemplateCmd cmd, Account templateOwner) throws ResourceAllocationException; VirtualMachineTemplate createPrivateTemplate(CreateTemplateCmd command) throws CloudRuntimeException; + VirtualMachineTemplate updateTemplate(UpdateIsoCmd cmd); + + VirtualMachineTemplate updateTemplate(UpdateTemplateCmd cmd); } diff --git a/api/src/com/cloud/vm/VirtualMachineProfile.java b/api/src/com/cloud/vm/VirtualMachineProfile.java index 33a9171e732..6861372d08d 100644 --- a/api/src/com/cloud/vm/VirtualMachineProfile.java +++ b/api/src/com/cloud/vm/VirtualMachineProfile.java @@ -19,6 +19,8 @@ package com.cloud.vm; import java.util.List; import java.util.Map; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.DiskTO; import com.cloud.agent.api.to.VolumeTO; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.offering.ServiceOffering; @@ -111,11 +113,11 @@ public interface VirtualMachineProfile { List getNics(); - List getDisks(); + List getDisks(); void addNic(int index, NicProfile nic); - void addDisk(int index, VolumeTO disk); + void addDisk(int index, DiskTO disk); StringBuilder getBootArgsBuilder(); @@ -125,7 +127,7 @@ public interface VirtualMachineProfile { void addNic(NicProfile nic); - void addDisk(VolumeTO disk); + void addDisk(DiskTO disk); VirtualMachine.Type getType(); diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java index 219e7c79e6f..1a8fdc79fb7 100644 --- a/api/src/org/apache/cloudstack/api/BaseCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseCmd.java @@ -69,8 +69,8 @@ import com.cloud.server.TaggedResourceService; import com.cloud.storage.DataStoreProviderApiService; import com.cloud.storage.StorageService; import com.cloud.storage.VolumeApiService; -import com.cloud.storage.snapshot.SnapshotService; -import com.cloud.template.TemplateService; +import com.cloud.storage.snapshot.SnapshotApiService; +import com.cloud.template.TemplateApiService; import com.cloud.user.Account; import com.cloud.user.AccountService; import com.cloud.user.DomainService; @@ -116,9 +116,9 @@ public abstract class BaseCmd { @Inject public VolumeApiService _volumeService; @Inject public ResourceService _resourceService; @Inject public NetworkService _networkService; - @Inject public TemplateService _templateService; + @Inject public TemplateApiService _templateService; @Inject public SecurityGroupService _securityGroupService; - @Inject public SnapshotService _snapshotService; + @Inject public SnapshotApiService _snapshotService; @Inject public VpcVirtualNetworkApplianceService _routerService; @Inject public ResponseGenerator _responseGenerator; @Inject public EntityManager _entityMgr; diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java index 096bf26c196..d8d07cb56fb 100644 --- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java @@ -122,6 +122,7 @@ import org.apache.cloudstack.api.response.HostForMigrationResponse; import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.HypervisorCapabilitiesResponse; import org.apache.cloudstack.api.response.IPAddressResponse; +import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.cloudstack.api.response.InstanceGroupResponse; import org.apache.cloudstack.api.response.InternalLoadBalancerElementResponse; import org.apache.cloudstack.api.response.IpForwardingRuleResponse; @@ -187,6 +188,7 @@ import org.apache.cloudstack.region.PortableIpRange; import org.apache.cloudstack.region.Region; import org.apache.cloudstack.usage.Usage; +import com.cloud.storage.ImageStore; import java.text.DecimalFormat; import java.util.EnumSet; import java.util.List; @@ -278,7 +280,7 @@ public interface ResponseGenerator { Host findHostById(Long hostId); - List createTemplateResponses(long templateId, long zoneId, boolean readyOnly); + //List createTemplateResponses(long templateId, long zoneId, boolean readyOnly); VpnUsersResponse createVpnUserResponse(VpnUser user); @@ -294,7 +296,9 @@ public interface ResponseGenerator { SecurityGroupResponse createSecurityGroupResponse(SecurityGroup group); - ExtractResponse createExtractResponse(Long uploadId, Long id, Long zoneId, Long accountId, String mode); + ExtractResponse createExtractResponse(Long uploadId, Long id, Long zoneId, Long accountId, String mode, String url); + + ExtractResponse createExtractResponse(Long id, Long zoneId, Long accountId, String mode, String url); String toSerializedString(CreateCmdResponse response, String responseType); @@ -304,7 +308,9 @@ public interface ResponseGenerator { //List createEventResponse(EventJoinVO... events); - TemplateResponse createIsoResponse(VirtualMachineTemplate result); + TemplateResponse createTemplateUpdateResponse(VirtualMachineTemplate result); + + List createTemplateResponses(VirtualMachineTemplate result, Long zoneId, boolean readyOnly); List createCapacityResponse(List result, DecimalFormat format); @@ -324,13 +330,13 @@ public interface ResponseGenerator { Long getSecurityGroupId(String groupName, long accountId); - List createIsoResponses(long isoId, Long zoneId, boolean readyOnly); + List createIsoResponses(VirtualMachineTemplate iso, Long zoneId, boolean readyOnly); + + // List createIsoResponses(long isoId, Long zoneId, boolean readyOnly); + //List createIsoResponses(VirtualMachineTemplate iso, long zoneId, boolean readyOnly); ProjectResponse createProjectResponse(Project project); - - List createIsoResponses(VirtualMachineTemplate iso, long zoneId, boolean readyOnly); - List createTemplateResponses(long templateId, Long vmId); FirewallResponse createFirewallResponse(FirewallRule fwRule); @@ -363,6 +369,8 @@ public interface ResponseGenerator { RegionResponse createRegionResponse(Region region); + ImageStoreResponse createImageStoreResponse(ImageStore os); + /** * @param resourceTag * @param keyValueOnly TODO @@ -437,7 +445,7 @@ public interface ResponseGenerator { public NicResponse createNicResponse(Nic result); ApplicationLoadBalancerResponse createLoadBalancerContainerReponse(ApplicationLoadBalancerRule lb, Map lbInstances); - + AffinityGroupResponse createAffinityGroupResponse(AffinityGroup group); Long getAffinityGroupId(String name, long entityOwnerId); diff --git a/api/src/org/apache/cloudstack/api/command/admin/host/AddSecondaryStorageCmd.java b/api/src/org/apache/cloudstack/api/command/admin/host/AddSecondaryStorageCmd.java index f1d12b3b07b..14725d3499b 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/host/AddSecondaryStorageCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/host/AddSecondaryStorageCmd.java @@ -16,23 +16,22 @@ // under the License. package org.apache.cloudstack.api.command.admin.host; -import java.util.List; - import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.response.HostResponse; +import org.apache.cloudstack.api.command.admin.storage.AddImageStoreCmd; +import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.log4j.Logger; import com.cloud.exception.DiscoveryException; -import com.cloud.host.Host; +import com.cloud.storage.ImageStore; import com.cloud.user.Account; -@APICommand(name = "addSecondaryStorage", description="Adds secondary storage.", responseObject=HostResponse.class) +@APICommand(name = "addSecondaryStorage", description="Adds secondary storage.", responseObject=ImageStoreResponse.class) public class AddSecondaryStorageCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(AddSecondaryStorageCmd.class.getName()); private static final String s_name = "addsecondarystorageresponse"; @@ -48,6 +47,8 @@ public class AddSecondaryStorageCmd extends BaseCmd { description="the Zone ID for the secondary storage") private Long zoneId; + + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -60,6 +61,7 @@ public class AddSecondaryStorageCmd extends BaseCmd { return zoneId; } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -76,17 +78,19 @@ public class AddSecondaryStorageCmd extends BaseCmd { @Override public void execute(){ - try { - List result = _resourceService.discoverHosts(this); - HostResponse hostResponse = null; - if (result != null && result.size() > 0) { - for (Host host : result) { - // There should only be one secondary storage host per add - hostResponse = _responseGenerator.createHostResponse(host); - hostResponse.setResponseName(getCommandName()); - hostResponse.setObjectName("secondarystorage"); - this.setResponseObject(hostResponse); - } + AddImageStoreCmd cmd = new AddImageStoreCmd(); + cmd.setUrl(this.getUrl()); + cmd.setZoneId(this.getZoneId()); + cmd.setProviderName("NFS"); + + try{ + ImageStore result = _storageService.discoverImageStore(cmd); + ImageStoreResponse storeResponse = null; + if (result != null ) { + storeResponse = _responseGenerator.createImageStoreResponse(result); + storeResponse.setResponseName(getCommandName()); + storeResponse.setObjectName("secondarystorage"); + this.setResponseObject(storeResponse); } else { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add secondary storage"); } diff --git a/api/src/org/apache/cloudstack/api/command/admin/storage/AddImageStoreCmd.java b/api/src/org/apache/cloudstack/api/command/admin/storage/AddImageStoreCmd.java new file mode 100644 index 00000000000..1e383c9647b --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/storage/AddImageStoreCmd.java @@ -0,0 +1,154 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.admin.storage; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.ImageStoreResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.log4j.Logger; + +import com.cloud.exception.DiscoveryException; +import com.cloud.storage.ImageStore; +import com.cloud.user.Account; + +@APICommand(name = "addImageStore", description="Adds backup image store.", responseObject=ImageStoreResponse.class, since = "4.2.0") +public class AddImageStoreCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(AddImageStoreCmd.class.getName()); + private static final String s_name = "addimagestoreresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="the name for the image store") + private String name; + + @Parameter(name=ApiConstants.URL, type=CommandType.STRING, description="the URL for the image store") + private String url; + + @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class, + description="the Zone ID for the image store") + private Long zoneId; + + @Parameter(name=ApiConstants.PROVIDER, type=CommandType.STRING, + required=true, description="the image store provider name") + private String providerName; + + + @Parameter(name=ApiConstants.DETAILS, type=CommandType.MAP, description="the details for the image store. Example: details[0].key=accesskey&details[0].value=s389ddssaa&details[1].key=secretkey&details[1].value=8dshfsss") + private Map details; + + + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + + public String getUrl() { + return url; + } + + public String getName() { + return name; + } + + public Long getZoneId() { + return zoneId; + } + + public Map getDetails() { + Map detailsMap = null; + if (details != null && !details.isEmpty()) { + detailsMap = new HashMap(); + Collection props = details.values(); + Iterator iter = props.iterator(); + while (iter.hasNext()) { + HashMap detail = (HashMap) iter.next(); + String key = detail.get("key"); + String value = detail.get("value"); + detailsMap.put(key, value); + } + } + return detailsMap; + } + + public String getProviderName() { + return this.providerName; + } + + public void setUrl(String url) { + this.url = url; + } + + public void setZoneId(Long zoneId) { + this.zoneId = zoneId; + } + + public void setProviderName(String providerName) { + this.providerName = providerName; + } + + public void setDetails(Map details) { + this.details = details; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute(){ + try{ + ImageStore result = _storageService.discoverImageStore(this); + ImageStoreResponse storeResponse = null; + if (result != null ) { + storeResponse = _responseGenerator.createImageStoreResponse(result); + storeResponse.setResponseName(getCommandName()); + storeResponse.setObjectName("secondarystorage"); + this.setResponseObject(storeResponse); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add secondary storage"); + } + } catch (DiscoveryException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); + } + } +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/storage/AddS3Cmd.java b/api/src/org/apache/cloudstack/api/command/admin/storage/AddS3Cmd.java index dbd9bff632b..3ad84fd5a51 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/storage/AddS3Cmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/storage/AddS3Cmd.java @@ -31,12 +31,17 @@ import static org.apache.cloudstack.api.BaseCmd.CommandType.BOOLEAN; import static org.apache.cloudstack.api.BaseCmd.CommandType.INTEGER; import static org.apache.cloudstack.api.BaseCmd.CommandType.STRING; +import java.util.HashMap; +import java.util.Map; + import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.response.S3Response; +import org.apache.cloudstack.api.response.ImageStoreResponse; +import org.apache.log4j.Logger; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.DiscoveryException; @@ -44,10 +49,11 @@ import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; -import com.cloud.storage.S3; +import com.cloud.storage.ImageStore; -@APICommand(name = "addS3", description = "Adds S3", responseObject = S3Response.class, since = "4.0.0") +@APICommand(name = "addS3", description = "Adds S3", responseObject = ImageStoreResponse.class, since = "4.0.0") public final class AddS3Cmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(AddS3Cmd.class.getName()); private static String COMMAND_NAME = "adds3response"; @@ -88,26 +94,33 @@ public final class AddS3Cmd extends BaseCmd { ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { - final S3 result; + AddImageStoreCmd cmd = new AddImageStoreCmd(); + cmd.setProviderName("S3"); + Map details = new HashMap(); + details.put(ApiConstants.S3_ACCESS_KEY, this.getAccessKey()); + details.put(ApiConstants.S3_SECRET_KEY, this.getSecretKey()); + details.put(ApiConstants.S3_END_POINT, this.getEndPoint()); + details.put(ApiConstants.S3_BUCKET_NAME, this.getBucketName()); + details.put(ApiConstants.S3_HTTPS_FLAG, this.getHttpsFlag().toString()); + details.put(ApiConstants.S3_CONNECTION_TIMEOUT, this.getConnectionTimeout().toString()); + details.put(ApiConstants.S3_MAX_ERROR_RETRY, this.getMaxErrorRetry().toString()); + details.put(ApiConstants.S3_SOCKET_TIMEOUT, this.getSocketTimeout().toString()); - try { - - result = _resourceService.discoverS3(this); - - if (result == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add S3."); + try{ + ImageStore result = _storageService.discoverImageStore(cmd); + ImageStoreResponse storeResponse = null; + if (result != null ) { + storeResponse = _responseGenerator.createImageStoreResponse(result); + storeResponse.setResponseName(getCommandName()); + storeResponse.setObjectName("secondarystorage"); + this.setResponseObject(storeResponse); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add secondary storage"); } - - } catch (DiscoveryException e) { - - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add S3 due to " + e.getMessage()); - + } catch (DiscoveryException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } - - final S3Response response = _responseGenerator.createS3Response(result); - response.setResponseName(this.getCommandName()); - this.setResponseObject(response); - } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/storage/CreateCacheStoreCmd.java b/api/src/org/apache/cloudstack/api/command/admin/storage/CreateCacheStoreCmd.java new file mode 100644 index 00000000000..ff01a40c1fa --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/storage/CreateCacheStoreCmd.java @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.api.command.admin.storage; + +import java.util.Map; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.BaseCmd.CommandType; +import org.apache.cloudstack.api.response.ImageStoreResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.log4j.Logger; + +import com.cloud.exception.DiscoveryException; +import com.cloud.storage.ImageStore; +import com.cloud.user.Account; + +@APICommand(name = "createCacheStore", description="create cache store.", responseObject=ImageStoreResponse.class) +public class CreateCacheStoreCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(AddImageStoreCmd.class.getName()); + private static final String s_name = "createcachestoreresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.URL, type=CommandType.STRING, required=true, description="the URL for the cache store") + private String url; + + @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class, + description="the Zone ID for the image store") + private Long zoneId; + + + @Parameter(name=ApiConstants.DETAILS, type=CommandType.MAP, description="the details for the image store") + private Map details; + + @Parameter(name=ApiConstants.SCOPE, type=CommandType.STRING, + required=false, description="the scope of the image store: zone only for now") + private String scope; + + @Parameter(name=ApiConstants.PROVIDER, type=CommandType.STRING, + required=false, description="the cache store provider name") + private String providerName; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public String getUrl() { + return url; + } + + public Long getZoneId() { + return zoneId; + } + + public Map getDetails() { + return details; + } + + public String getScope() { + return this.scope; + } + + public String getProviderName() { + return this.providerName; + } + + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute(){ + try{ + ImageStore result = _storageService.createCacheStore(this); + ImageStoreResponse storeResponse = null; + if (result != null ) { + storeResponse = _responseGenerator.createImageStoreResponse(result); + storeResponse.setResponseName(getCommandName()); + storeResponse.setObjectName("secondarystorage"); + this.setResponseObject(storeResponse); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add secondary storage"); + } + } catch (Exception ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); + } + } +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/storage/DeleteImageStoreCmd.java b/api/src/org/apache/cloudstack/api/command/admin/storage/DeleteImageStoreCmd.java new file mode 100644 index 00000000000..20ddc8b6fec --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/storage/DeleteImageStoreCmd.java @@ -0,0 +1,80 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.admin.storage; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.HostResponse; +import org.apache.cloudstack.api.response.ImageStoreResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.log4j.Logger; + +import com.cloud.user.Account; + +@APICommand(name = "deleteImageStore", description = "Deletes an image store .", responseObject = SuccessResponse.class, since = "4.2.0") +public class DeleteImageStoreCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(DeleteImageStoreCmd.class.getName()); + + private static final String s_name = "deleteimagestoreresponse"; + + // /////////////////////////////////////////////////// + // ////////////// API parameters ///////////////////// + // /////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ImageStoreResponse.class, + required = true, description = "the image store ID") + private Long id; + + + // /////////////////////////////////////////////////// + // ///////////////// Accessors /////////////////////// + // /////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + + // /////////////////////////////////////////////////// + // ///////////// API Implementation/////////////////// + // /////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute() { + boolean result = _storageService.deleteImageStore(this); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete image store"); + } + } +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/storage/ListImageStoresCmd.java b/api/src/org/apache/cloudstack/api/command/admin/storage/ListImageStoresCmd.java new file mode 100644 index 00000000000..57259b558a4 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/storage/ListImageStoresCmd.java @@ -0,0 +1,109 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.admin.storage; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.ClusterResponse; +import org.apache.cloudstack.api.response.ImageStoreResponse; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.PodResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.log4j.Logger; + +import com.cloud.async.AsyncJob; + +@APICommand(name = "listImageStores", description="Lists image stores.", responseObject=ImageStoreResponse.class, since = "4.2.0") +public class ListImageStoresCmd extends BaseListCmd { + public static final Logger s_logger = Logger.getLogger(ListImageStoresCmd.class.getName()); + + private static final String s_name = "listimagestoreresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="the name of the image store") + private String storeName; + + @Parameter(name=ApiConstants.PROTOCOL, type=CommandType.STRING, description="the image store protocol") + private String protocol; + + @Parameter(name=ApiConstants.PROVIDER, type=CommandType.STRING, description="the image store provider") + private String provider; + + @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType = ZoneResponse.class, + description="the Zone ID for the image store") + private Long zoneId; + + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = ImageStoreResponse.class, + description="the ID of the storage pool") + private Long id; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + + + public Long getZoneId() { + return zoneId; + } + + public String getStoreName() { + return storeName; + } + + public String getProtocol() { + return protocol; + } + + public Long getId() { + return id; + } + + public String getProvider() { + return provider; + } + + public void setProvider(String provider) { + this.provider = provider; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + + + + @Override + public String getCommandName() { + return s_name; + } + + + @Override + public void execute(){ + ListResponse response = _queryService.searchForImageStores(this); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/storage/ListS3sCmd.java b/api/src/org/apache/cloudstack/api/command/admin/storage/ListS3sCmd.java index 4ab71de24d0..409f1607ce7 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/storage/ListS3sCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/storage/ListS3sCmd.java @@ -18,23 +18,18 @@ */ package org.apache.cloudstack.api.command.admin.storage; -import java.util.ArrayList; -import java.util.List; - import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseListCmd; import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.cloudstack.api.response.ListResponse; -import org.apache.cloudstack.api.response.S3Response; - import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; -import com.cloud.storage.S3; -@APICommand(name = "listS3s", description = "Lists S3s", responseObject = S3Response.class, since = "4.0.0") +@APICommand(name = "listS3s", description = "Lists S3s", responseObject = ImageStoreResponse.class, since = "4.0.0") public class ListS3sCmd extends BaseListCmd { private static final String COMMAND_NAME = "lists3sresponse"; @@ -44,28 +39,11 @@ public class ListS3sCmd extends BaseListCmd { ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { - final List result = _resourceService.listS3s(this); - final ListResponse response = new ListResponse(); - final List s3Responses = new ArrayList(); - - if (result != null) { - - for (S3 s3 : result) { - - S3Response s3Response = _responseGenerator.createS3Response(s3); - s3Response.setResponseName(this.getCommandName()); - s3Response.setObjectName("s3"); - s3Responses.add(s3Response); - - } - - } - - response.setResponses(s3Responses); - response.setResponseName(this.getCommandName()); - + ListImageStoresCmd cmd = new ListImageStoresCmd(); + cmd.setProvider("S3"); + ListResponse response = _queryService.searchForImageStores(cmd); + response.setResponseName(getCommandName()); this.setResponseObject(response); - } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/swift/AddSwiftCmd.java b/api/src/org/apache/cloudstack/api/command/admin/swift/AddSwiftCmd.java index 364d916add6..462b5297ce5 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/swift/AddSwiftCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/swift/AddSwiftCmd.java @@ -16,21 +16,24 @@ // under the License. package org.apache.cloudstack.api.command.admin.swift; +import java.util.HashMap; +import java.util.Map; + import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.response.HostResponse; -import org.apache.cloudstack.api.response.SwiftResponse; +import org.apache.cloudstack.api.command.admin.storage.AddImageStoreCmd; +import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.log4j.Logger; import com.cloud.exception.DiscoveryException; -import com.cloud.storage.Swift; +import com.cloud.storage.ImageStore; import com.cloud.user.Account; -@APICommand(name = "addSwift", description = "Adds Swift.", responseObject = HostResponse.class, since="3.0.0") +@APICommand(name = "addSwift", description = "Adds Swift.", responseObject = ImageStoreResponse.class, since="3.0.0") public class AddSwiftCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(AddSwiftCmd.class.getName()); private static final String s_name = "addswiftresponse"; @@ -87,21 +90,29 @@ public class AddSwiftCmd extends BaseCmd { @Override public void execute(){ - try { - Swift result = _resourceService.discoverSwift(this); - SwiftResponse swiftResponse = null; - if (result != null) { - swiftResponse = _responseGenerator.createSwiftResponse(result); - swiftResponse.setResponseName(getCommandName()); - swiftResponse.setObjectName("swift"); - this.setResponseObject(swiftResponse); + AddImageStoreCmd cmd = new AddImageStoreCmd(); + cmd.setProviderName("Swift"); + cmd.setUrl(this.getUrl()); + Map details = new HashMap(); + details.put(ApiConstants.ACCOUNT, this.getAccount()); + details.put(ApiConstants.USERNAME, this.getUsername()); + details.put(ApiConstants.KEY, this.getKey()); + + + try{ + ImageStore result = _storageService.discoverImageStore(cmd); + ImageStoreResponse storeResponse = null; + if (result != null ) { + storeResponse = _responseGenerator.createImageStoreResponse(result); + storeResponse.setResponseName(getCommandName()); + storeResponse.setObjectName("secondarystorage"); + this.setResponseObject(storeResponse); } else { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add Swift"); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add secondary storage"); } } catch (DiscoveryException ex) { - String errMsg = "Failed to add Swift due to " + ex.toString(); - s_logger.warn(errMsg, ex); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errMsg); + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } } } diff --git a/api/src/org/apache/cloudstack/api/command/admin/swift/ListSwiftsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/swift/ListSwiftsCmd.java index 7cfe6e1ab7f..b0408f43792 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/swift/ListSwiftsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/swift/ListSwiftsCmd.java @@ -16,23 +16,18 @@ // under the License. package org.apache.cloudstack.api.command.admin.swift; -import java.util.ArrayList; -import java.util.List; - import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListCmd; import org.apache.cloudstack.api.Parameter; -import org.apache.cloudstack.api.response.HostResponse; +import org.apache.cloudstack.api.command.admin.storage.ListImageStoresCmd; +import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.cloudstack.api.response.ListResponse; -import org.apache.cloudstack.api.response.SwiftResponse; import org.apache.log4j.Logger; -import com.cloud.storage.Swift; import com.cloud.user.Account; -import com.cloud.utils.Pair; -@APICommand(name = "listSwifts", description = "List Swift.", responseObject = HostResponse.class, since="3.0.0") +@APICommand(name = "listSwifts", description = "List Swift.", responseObject = ImageStoreResponse.class, since="3.0.0") public class ListSwiftsCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListSwiftsCmd.class.getName()); private static final String s_name = "listswiftsresponse"; @@ -65,19 +60,10 @@ public class ListSwiftsCmd extends BaseListCmd { @Override public void execute(){ - Pair, Integer> result = _resourceService.listSwifts(this); - ListResponse response = new ListResponse(); - List swiftResponses = new ArrayList(); - if (result != null) { - for (Swift swift : result.first()) { - SwiftResponse swiftResponse = _responseGenerator.createSwiftResponse(swift); - swiftResponse.setResponseName(getCommandName()); - swiftResponse.setObjectName("swift"); - swiftResponses.add(swiftResponse); - } - } - response.setResponses(swiftResponses, result.second()); + ListImageStoresCmd cmd = new ListImageStoresCmd(); + cmd.setProvider("Swift"); + ListResponse response = _queryService.searchForImageStores(cmd); response.setResponseName(getCommandName()); this.setResponseObject(response); } diff --git a/api/src/org/apache/cloudstack/api/command/admin/template/PrepareTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/admin/template/PrepareTemplateCmd.java index 7d41d10ae08..aee35ade978 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/template/PrepareTemplateCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/template/PrepareTemplateCmd.java @@ -80,7 +80,7 @@ public class PrepareTemplateCmd extends BaseCmd { ListResponse response = new ListResponse(); VirtualMachineTemplate vmTemplate = _templateService.prepareTemplate(templateId, zoneId); - List templateResponses = _responseGenerator.createTemplateResponses(vmTemplate.getId(), zoneId, true); + List templateResponses = _responseGenerator.createTemplateResponses(vmTemplate, zoneId, true); response.setResponses(templateResponses); response.setResponseName(getCommandName()); this.setResponseObject(response); diff --git a/api/src/org/apache/cloudstack/api/command/user/iso/ExtractIsoCmd.java b/api/src/org/apache/cloudstack/api/command/user/iso/ExtractIsoCmd.java index 08a15eece73..dd0fc360e45 100644 --- a/api/src/org/apache/cloudstack/api/command/user/iso/ExtractIsoCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/iso/ExtractIsoCmd.java @@ -33,6 +33,7 @@ import com.cloud.exception.InternalErrorException; import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; import com.cloud.user.UserContext; +import com.cloud.utils.Pair; @APICommand(name = "extractIso", description="Extracts an ISO", responseObject=ExtractResponse.class) public class ExtractIsoCmd extends BaseAsyncCmd { @@ -123,9 +124,9 @@ public class ExtractIsoCmd extends BaseAsyncCmd { public void execute(){ try { UserContext.current().setEventDetails(getEventDescription()); - Long uploadId = _templateService.extract(this); - if (uploadId != null){ - ExtractResponse response = _responseGenerator.createExtractResponse(uploadId, id, zoneId, getEntityOwnerId(), mode); + String uploadUrl = _templateService.extract(this); + if (uploadUrl != null) { + ExtractResponse response = _responseGenerator.createExtractResponse(id, zoneId, getEntityOwnerId(), mode, uploadUrl); response.setResponseName(getCommandName()); response.setObjectName("iso"); this.setResponseObject(response); diff --git a/api/src/org/apache/cloudstack/api/command/user/iso/ListIsosCmd.java b/api/src/org/apache/cloudstack/api/command/user/iso/ListIsosCmd.java index 9e6abec74e2..b490ca9966a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/iso/ListIsosCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/iso/ListIsosCmd.java @@ -148,15 +148,7 @@ public class ListIsosCmd extends BaseListTaggedResourcesCmd { @Override public void execute(){ - Set> isoZonePairSet = _mgr.listIsos(this); - ListResponse response = new ListResponse(); - List templateResponses = new ArrayList(); - - for (Pair iso : isoZonePairSet) { - List responses = _responseGenerator.createIsoResponses(iso.first(), iso.second(), listInReadyState()); - templateResponses.addAll(responses); - } - response.setResponses(templateResponses); + ListResponse response = _queryService.listIsos(this); response.setResponseName(getCommandName()); this.setResponseObject(response); } diff --git a/api/src/org/apache/cloudstack/api/command/user/iso/RegisterIsoCmd.java b/api/src/org/apache/cloudstack/api/command/user/iso/RegisterIsoCmd.java index 1e7e3dae329..943cbe9674b 100644 --- a/api/src/org/apache/cloudstack/api/command/user/iso/RegisterIsoCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/iso/RegisterIsoCmd.java @@ -88,7 +88,7 @@ public class RegisterIsoCmd extends BaseCmd { @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.UUID, entityType = ProjectResponse.class, description="Register iso for the project") private Long projectId; - + @Parameter(name=ApiConstants.IMAGE_STORE_UUID, type=CommandType.STRING, description="Image store uuid") private String imageStoreUuid; @@ -147,7 +147,7 @@ public class RegisterIsoCmd extends BaseCmd { public String getChecksum() { return checksum; } - + public String getImageStoreUuid() { return this.imageStoreUuid; } @@ -180,7 +180,7 @@ public class RegisterIsoCmd extends BaseCmd { VirtualMachineTemplate template = _templateService.registerIso(this); if (template != null) { ListResponse response = new ListResponse(); - List templateResponses = _responseGenerator.createIsoResponses(template.getId(), zoneId, false); + List templateResponses = _responseGenerator.createIsoResponses(template, zoneId, false); response.setResponses(templateResponses); response.setResponseName(getCommandName()); this.setResponseObject(response); diff --git a/api/src/org/apache/cloudstack/api/command/user/iso/UpdateIsoCmd.java b/api/src/org/apache/cloudstack/api/command/user/iso/UpdateIsoCmd.java index 37294e3563a..1d848472fad 100644 --- a/api/src/org/apache/cloudstack/api/command/user/iso/UpdateIsoCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/iso/UpdateIsoCmd.java @@ -66,9 +66,9 @@ public class UpdateIsoCmd extends BaseUpdateTemplateOrIsoCmd { @Override public void execute(){ - VirtualMachineTemplate result = _mgr.updateTemplate(this); + VirtualMachineTemplate result = _templateService.updateTemplate(this); if (result != null) { - TemplateResponse response = _responseGenerator.createIsoResponse(result); + TemplateResponse response = _responseGenerator.createTemplateUpdateResponse(result); response.setResponseName(getCommandName()); this.setResponseObject(response); } else { diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java index 0b33f568d8a..73a7fc47d1f 100644 --- a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java @@ -152,7 +152,7 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd { @Override public void create() throws ResourceAllocationException { - Snapshot snapshot = _snapshotService.allocSnapshot(getVolumeId(), getPolicyId()); + Snapshot snapshot = this._volumeService.allocSnapshot(getVolumeId(), getPolicyId()); if (snapshot != null) { this.setEntityId(snapshot.getId()); this.setEntityUuid(snapshot.getUuid()); @@ -165,15 +165,19 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd { public void execute() { s_logger.info("VOLSS: createSnapshotCmd starts:" + System.currentTimeMillis()); UserContext.current().setEventDetails("Volume Id: "+getVolumeId()); - Snapshot snapshot = _snapshotService.createSnapshot(getVolumeId(), getPolicyId(), getEntityId(), _accountService.getAccount(getEntityOwnerId())); - if (snapshot != null) { - SnapshotResponse response = _responseGenerator.createSnapshotResponse(snapshot); - response.setResponseName(getCommandName()); - this.setResponseObject(response); - } else { + Snapshot snapshot; + try { + snapshot = _volumeService.takeSnapshot(this.getVolumeId(), this.getPolicyId(), this.getEntityId(), _accountService.getAccount(getEntityOwnerId())); + if (snapshot != null) { + SnapshotResponse response = _responseGenerator.createSnapshotResponse(snapshot); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create snapshot due to an internal error creating snapshot for volume " + volumeId); + } + } catch (Exception e) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create snapshot due to an internal error creating snapshot for volume " + volumeId); } - s_logger.info("VOLSS: backupSnapshotCmd finishes:" + System.currentTimeMillis()); } diff --git a/api/src/org/apache/cloudstack/api/command/user/template/CopyTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/CopyTemplateCmd.java index a4f05821244..34ee4bdc786 100644 --- a/api/src/org/apache/cloudstack/api/command/user/template/CopyTemplateCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/template/CopyTemplateCmd.java @@ -124,7 +124,7 @@ public class CopyTemplateCmd extends BaseAsyncCmd { VirtualMachineTemplate template = _templateService.copyTemplate(this); if (template != null){ - List listResponse = _responseGenerator.createTemplateResponses(template.getId(), getDestinationZoneId(), false); + List listResponse = _responseGenerator.createTemplateResponses(template, getDestinationZoneId(), false); TemplateResponse response = new TemplateResponse(); if (listResponse != null && !listResponse.isEmpty()) { response = listResponse.get(0); diff --git a/api/src/org/apache/cloudstack/api/command/user/template/ExtractTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/ExtractTemplateCmd.java index 9a2dee30bcb..f2dc5952386 100644 --- a/api/src/org/apache/cloudstack/api/command/user/template/ExtractTemplateCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/template/ExtractTemplateCmd.java @@ -34,6 +34,7 @@ import com.cloud.exception.InternalErrorException; import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; import com.cloud.user.UserContext; +import com.cloud.utils.Pair; @APICommand(name = "extractTemplate", description="Extracts a template", responseObject=ExtractResponse.class) public class ExtractTemplateCmd extends BaseAsyncCmd { @@ -125,9 +126,9 @@ public class ExtractTemplateCmd extends BaseAsyncCmd { public void execute(){ try { UserContext.current().setEventDetails(getEventDescription()); - Long uploadId = _templateService.extract(this); - if (uploadId != null){ - ExtractResponse response = _responseGenerator.createExtractResponse(uploadId, id, zoneId, getEntityOwnerId(), mode); + String uploadUrl = _templateService.extract(this); + if (uploadUrl != null) { + ExtractResponse response = _responseGenerator.createExtractResponse(id, zoneId, getEntityOwnerId(), mode, uploadUrl); response.setResponseName(getCommandName()); this.setResponseObject(response); } else { diff --git a/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java index dc94d676661..0b937be6d59 100644 --- a/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java @@ -26,6 +26,7 @@ import org.apache.cloudstack.api.BaseListTaggedResourcesCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.TemplateResponse; +import org.apache.cloudstack.api.response.VolumeResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.log4j.Logger; @@ -55,7 +56,7 @@ public class ListTemplatesCmd extends BaseListTaggedResourcesCmd { @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="the template name") private String templateName; - @Parameter(name=ApiConstants.TEMPLATE_FILTER, type=CommandType.STRING, required=true, description="possible values are \"featured\", \"self\", \"selfexecutable\",\"sharedexecutable\",\"executable\", and \"community\". " + + @Parameter(name=ApiConstants.TEMPLATE_FILTER, type=CommandType.STRING, required=true, description="possible values are \"featured\", \"self\", \"selfexecutable\",\"sharedexecutable\",\"executable\", and \"community\". " + "* featured : templates that have been marked as featured and public. " + "* self : templates that have been registered or created by the calling user. " + "* selfexecutable : same as self, but only returns templates that can be used to deploy a new VM. " + @@ -119,17 +120,7 @@ public class ListTemplatesCmd extends BaseListTaggedResourcesCmd { @Override public void execute(){ - Set> templateZonePairSet = _mgr.listTemplates(this); - - ListResponse response = new ListResponse(); - List templateResponses = new ArrayList(); - - for (Pair template : templateZonePairSet) { - List responses = _responseGenerator.createTemplateResponses(template.first().longValue(), template.second(), listInReadyState()); - templateResponses.addAll(responses); - } - - response.setResponses(templateResponses); + ListResponse response = _queryService.listTemplates(this); response.setResponseName(getCommandName()); this.setResponseObject(response); } 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 837faf69d29..6a8e5559284 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; @@ -196,10 +192,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()) { @@ -244,7 +237,7 @@ public class RegisterTemplateCmd extends BaseCmd { VirtualMachineTemplate template = _templateService.registerTemplate(this); if (template != null){ ListResponse response = new ListResponse(); - List templateResponses = _responseGenerator.createTemplateResponses(template.getId(), zoneId, false); + List templateResponses = _responseGenerator.createTemplateResponses(template, zoneId, false); response.setResponses(templateResponses); response.setResponseName(getCommandName()); this.setResponseObject(response); diff --git a/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmd.java index 3987dbedc3e..9f55f9df6c7 100644 --- a/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmd.java @@ -66,9 +66,9 @@ public class UpdateTemplateCmd extends BaseUpdateTemplateOrIsoCmd { @Override public void execute(){ - VirtualMachineTemplate result = _mgr.updateTemplate(this); + VirtualMachineTemplate result = _templateService.updateTemplate(this); if (result != null) { - TemplateResponse response = _responseGenerator.createIsoResponse(result); + TemplateResponse response = _responseGenerator.createTemplateUpdateResponse(result); response.setObjectName("template"); response.setResponseName(getCommandName()); this.setResponseObject(response); diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java index 86a494b8848..107af1195a9 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java @@ -117,7 +117,7 @@ public class CreateVolumeCmd extends BaseAsyncCreateCmd { } public Boolean getDisplayVolume() { - return displayVolume; + return displayVolume != null ? displayVolume : Boolean.TRUE; } ///////////////////////////////////////////////////// diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java index b86155b2a6c..5fbe106b334 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java @@ -126,33 +126,26 @@ public class ExtractVolumeCmd extends BaseAsyncCmd { @Override public void execute(){ - try { - UserContext.current().setEventDetails("Volume Id: "+getId()); - Long uploadId = _mgr.extractVolume(this); - if (uploadId != null){ - Upload uploadInfo = _entityMgr.findById(Upload.class, uploadId); - ExtractResponse response = new ExtractResponse(); - response.setResponseName(getCommandName()); - response.setObjectName("volume"); - Volume vol = _entityMgr.findById(Volume.class, id); - response.setId(vol.getUuid()); - response.setName(vol.getName()); - DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId); - response.setZoneId(zone.getUuid()); - response.setZoneName(zone.getName()); - response.setMode(mode); - response.setUploadId(uploadInfo.getUuid()); - response.setState(uploadInfo.getUploadState().toString()); - Account account = _entityMgr.findById(Account.class, getEntityOwnerId()); - response.setAccountId(account.getUuid()); - response.setUrl(uploadInfo.getUploadUrl()); - this.setResponseObject(response); - } else { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to extract volume"); - } - } catch (URISyntaxException ex) { - s_logger.info(ex); - throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ex.getMessage()); + UserContext.current().setEventDetails("Volume Id: " + getId()); + String uploadUrl = _volumeService.extractVolume(this); + if (uploadUrl != null) { + ExtractResponse response = new ExtractResponse(); + response.setResponseName(getCommandName()); + response.setObjectName("volume"); + Volume vol = _entityMgr.findById(Volume.class, id); + response.setId(vol.getUuid()); + response.setName(vol.getName()); + DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId); + response.setZoneId(zone.getUuid()); + response.setZoneName(zone.getName()); + response.setMode(mode); + response.setState(Upload.Status.DOWNLOAD_URL_CREATED.toString()); + Account account = _entityMgr.findById(Account.class, getEntityOwnerId()); + response.setAccountId(account.getUuid()); + response.setUrl(uploadUrl); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to extract volume"); } } } diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java index ce40f0d2979..40e6123d0ec 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java @@ -98,18 +98,15 @@ public class MigrateVolumeCmd extends BaseAsyncCmd { @Override public void execute(){ - Volume result; - try { - result = _volumeService.migrateVolume(this); - if (result != null) { - VolumeResponse response = _responseGenerator.createVolumeResponse(result); - response.setResponseName(getCommandName()); - this.setResponseObject(response); - } - } catch (ConcurrentOperationException e) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to migrate volume: "); - } - + Volume result; + result = _volumeService.migrateVolume(this); + if (result != null) { + VolumeResponse response = _responseGenerator.createVolumeResponse(result); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to migrate volume"); + } } } diff --git a/api/src/org/apache/cloudstack/api/response/ImageStoreDetailResponse.java b/api/src/org/apache/cloudstack/api/response/ImageStoreDetailResponse.java new file mode 100644 index 00000000000..6f90f0ff8f7 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/ImageStoreDetailResponse.java @@ -0,0 +1,86 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.response; + +import org.apache.cloudstack.api.BaseResponse; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +public class ImageStoreDetailResponse extends BaseResponse { + @SerializedName("name") @Param(description="detail property name of the image store") + private String name; + + @SerializedName("value") @Param(description="detail property value of the image store") + private String value; + + public ImageStoreDetailResponse(){ + super(); + } + + public ImageStoreDetailResponse(String name, String val){ + super(); + this.name = name; + this.value = val; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + String oid = this.getName(); + result = prime * result + ((oid== null) ? 0 : oid.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ImageStoreDetailResponse other = (ImageStoreDetailResponse) obj; + String oid = this.getName(); + if (oid == null) { + if (other.getName() != null) + return false; + } else if (!oid.equals(other.getName())) + return false; + else if ( this.getValue().equals(other.getValue())) + return false; + return true; + } + +} diff --git a/api/src/org/apache/cloudstack/api/response/ImageStoreResponse.java b/api/src/org/apache/cloudstack/api/response/ImageStoreResponse.java new file mode 100644 index 00000000000..04a375f467c --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/ImageStoreResponse.java @@ -0,0 +1,149 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.response; + +import java.util.LinkedHashSet; +import java.util.Set; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +import com.cloud.serializer.Param; +import com.cloud.storage.ImageStore; +import com.cloud.storage.ScopeType; +import com.google.gson.annotations.SerializedName; + +@EntityReference(value=ImageStore.class) +public class ImageStoreResponse extends BaseResponse { + @SerializedName("id") @Param(description="the ID of the image store") + private String id; + + @SerializedName("zoneid") @Param(description="the Zone ID of the image store") + private String zoneId; + + @SerializedName(ApiConstants.ZONE_NAME) @Param(description="the Zone name of the image store") + private String zoneName; + + @SerializedName("name") @Param(description="the name of the image store") + private String name; + + @SerializedName("url") @Param(description="the url of the image store") + private String url; + + @SerializedName("protocol") @Param(description="the protocol of the image store") + private String protocol; + + @SerializedName("providername") @Param(description="the provider name of the image store") + private String providerName; + + @SerializedName("scope") @Param(description="the scope of the image store") + private ScopeType scope; + + @SerializedName("details") @Param(description="the details of the image store") + private Set details; + + + public ImageStoreResponse(){ + this.details = new LinkedHashSet(); + } + + @Override + public String getObjectId() { + return this.getId(); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getZoneId() { + return zoneId; + } + + public void setZoneId(String zoneId) { + this.zoneId = zoneId; + } + + public String getZoneName() { + return zoneName; + } + + public void setZoneName(String zoneName) { + this.zoneName = zoneName; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getProviderName() { + return providerName; + } + + public void setProviderName(String providerName) { + this.providerName = providerName; + } + + public ScopeType getScope() { + return scope; + } + + public void setScope(ScopeType type) { + this.scope = type; + } + + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public Set getDetails() { + return details; + } + + public void setDetails(Set details) { + this.details = details; + } + + public void addDetail(ImageStoreDetailResponse detail){ + this.details.add(detail); + } + + + +} diff --git a/api/src/org/apache/cloudstack/api/response/TemplateResponse.java b/api/src/org/apache/cloudstack/api/response/TemplateResponse.java index 2089c4b3660..e6221f7b565 100644 --- a/api/src/org/apache/cloudstack/api/response/TemplateResponse.java +++ b/api/src/org/apache/cloudstack/api/response/TemplateResponse.java @@ -17,8 +17,10 @@ package org.apache.cloudstack.api.response; import java.util.Date; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; @@ -31,7 +33,7 @@ import com.google.gson.annotations.SerializedName; @EntityReference(value=VirtualMachineTemplate.class) @SuppressWarnings("unused") -public class TemplateResponse extends BaseResponse implements ControlledEntityResponse { +public class TemplateResponse extends BaseResponse implements ControlledViewEntityResponse { @SerializedName(ApiConstants.ID) @Param(description="the template ID") private String id; @@ -82,6 +84,8 @@ public class TemplateResponse extends BaseResponse implements ControlledEntityRe @SerializedName(ApiConstants.ACCOUNT) @Param(description="the account name to which the template belongs") private String account; + //TODO: since a template can be associated to more than one zones, this model is not accurate. For backward-compatibility, keep these fields + // here, but add a zones field to capture multiple zones. @SerializedName(ApiConstants.ZONE_ID) @Param(description="the ID of the zone for this template") private String zoneId; @@ -133,8 +137,11 @@ public class TemplateResponse extends BaseResponse implements ControlledEntityRe @SerializedName(ApiConstants.DETAILS) @Param(description="additional key/value details tied with template") private Map details; + @SerializedName("zones") @Param(description="list of zones associated with tempate", responseObject = TemplateZoneResponse.class) + private Set zones; + @SerializedName(ApiConstants.TAGS) @Param(description="the list of resource tags associated with tempate", responseObject = ResourceTagResponse.class) - private List tags; + private Set tags; @SerializedName(ApiConstants.SSHKEY_ENABLED) @Param(description="true if template is sshkey enabled, false otherwise") private Boolean sshKeyEnabled; @@ -142,6 +149,12 @@ public class TemplateResponse extends BaseResponse implements ControlledEntityRe @SerializedName(ApiConstants.IS_DYNAMICALLY_SCALABLE) @Param(description="true if template contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory") private Boolean isDynamicallyScalable; + public TemplateResponse(){ + zones = new LinkedHashSet(); + tags = new LinkedHashSet(); + } + + @Override public String getObjectId() { return this.getId(); @@ -291,10 +304,22 @@ public class TemplateResponse extends BaseResponse implements ControlledEntityRe this.details = details; } - public void setTags(List tags) { + public void setTags(Set tags) { this.tags = tags; } + public void addTag(ResourceTagResponse tag){ + this.tags.add(tag); + } + + public void setZones(Set zones){ + this.zones = zones; + } + + public void addZone(TemplateZoneResponse zone){ + this.zones.add(zone); + } + public void setSshKeyEnabled(boolean sshKeyEnabled) { this.sshKeyEnabled = sshKeyEnabled; } @@ -303,4 +328,7 @@ public class TemplateResponse extends BaseResponse implements ControlledEntityRe this.isDynamicallyScalable = isDynamicallyScalable; } + public String getZoneId() { + return zoneId; + } } diff --git a/api/src/org/apache/cloudstack/api/response/TemplateZoneResponse.java b/api/src/org/apache/cloudstack/api/response/TemplateZoneResponse.java new file mode 100644 index 00000000000..9d26ad9fc10 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/TemplateZoneResponse.java @@ -0,0 +1,90 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.response; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +public class TemplateZoneResponse extends BaseResponse { + @SerializedName(ApiConstants.ZONE_ID) @Param(description="the ID of the zone for the template") + private String zoneId; + + @SerializedName(ApiConstants.ZONE_NAME) @Param(description="the name of the zone for the template") + private String zoneName; + + + public TemplateZoneResponse(){ + super(); + } + + public TemplateZoneResponse(String zoneId, String zoneName){ + super(); + this.zoneId = zoneId; + this.zoneName = zoneName; + } + + + + public String getZoneId() { + return zoneId; + } + + public void setZoneId(String zoneId) { + this.zoneId = zoneId; + } + + public String getZoneName() { + return zoneName; + } + + public void setZoneName(String zoneName) { + this.zoneName = zoneName; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + String oid = this.getZoneId(); + result = prime * result + ((oid== null) ? 0 : oid.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + TemplateZoneResponse other = (TemplateZoneResponse) obj; + String oid = this.getZoneId(); + if (oid == null) { + if (other.getZoneId() != null) + return false; + } else if (!oid.equals(other.getZoneId())) + return false; + else if ( this.getZoneName().equals(other.getZoneName())) + return false; + return true; + } + +} diff --git a/api/src/org/apache/cloudstack/query/QueryService.java b/api/src/org/apache/cloudstack/query/QueryService.java index 73e393b069f..28dba3db5e1 100644 --- a/api/src/org/apache/cloudstack/query/QueryService.java +++ b/api/src/org/apache/cloudstack/query/QueryService.java @@ -20,11 +20,13 @@ import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.command.admin.host.ListHostsCmd; import org.apache.cloudstack.api.command.admin.internallb.ListInternalLBVMsCmd; import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd; +import org.apache.cloudstack.api.command.admin.storage.ListImageStoresCmd; import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd; import org.apache.cloudstack.api.command.admin.user.ListUsersCmd; import org.apache.cloudstack.api.command.user.account.ListAccountsCmd; import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd; import org.apache.cloudstack.api.command.user.event.ListEventsCmd; +import org.apache.cloudstack.api.command.user.iso.ListIsosCmd; import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd; import org.apache.cloudstack.api.command.user.offering.ListDiskOfferingsCmd; import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd; @@ -32,11 +34,33 @@ import org.apache.cloudstack.api.command.user.project.ListProjectInvitationsCmd; import org.apache.cloudstack.api.command.user.project.ListProjectsCmd; import org.apache.cloudstack.api.command.user.securitygroup.ListSecurityGroupsCmd; import org.apache.cloudstack.api.command.user.tag.ListTagsCmd; +import org.apache.cloudstack.api.command.user.template.ListTemplatesCmd; import org.apache.cloudstack.api.command.user.vm.ListVMsCmd; import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd; import org.apache.cloudstack.api.command.user.volume.ListResourceDetailsCmd; import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd; import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd; +import org.apache.cloudstack.api.response.AccountResponse; +import org.apache.cloudstack.api.response.AsyncJobResponse; +import org.apache.cloudstack.api.response.DiskOfferingResponse; +import org.apache.cloudstack.api.response.DomainRouterResponse; +import org.apache.cloudstack.api.response.EventResponse; +import org.apache.cloudstack.api.response.HostResponse; +import org.apache.cloudstack.api.response.ImageStoreResponse; +import org.apache.cloudstack.api.response.InstanceGroupResponse; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.ProjectAccountResponse; +import org.apache.cloudstack.api.response.ProjectInvitationResponse; +import org.apache.cloudstack.api.response.ProjectResponse; +import org.apache.cloudstack.api.response.ResourceTagResponse; +import org.apache.cloudstack.api.response.SecurityGroupResponse; +import org.apache.cloudstack.api.response.ServiceOfferingResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; +import org.apache.cloudstack.api.response.TemplateResponse; +import org.apache.cloudstack.api.response.UserResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.api.response.VolumeResponse; +import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.api.response.*; import com.cloud.exception.PermissionDeniedException; @@ -75,6 +99,8 @@ public interface QueryService { public ListResponse searchForStoragePools(ListStoragePoolsCmd cmd); + public ListResponse searchForImageStores(ListImageStoresCmd cmd); + public ListResponse searchForAccounts(ListAccountsCmd cmd); public ListResponse searchForAsyncJobs(ListAsyncJobsCmd cmd); @@ -85,6 +111,9 @@ public interface QueryService { public ListResponse listDataCenters(ListZonesByCmd cmd); + public ListResponse listTemplates(ListTemplatesCmd cmd); + + public ListResponse listIsos(ListIsosCmd cmd); public ListResponse listAffinityGroups(Long affinityGroupId, String affinityGroupName, String affinityGroupType, Long vmId, String accountName, Long domainId, boolean isRecursive, boolean listAll, Long startIndex, Long pageSize); diff --git a/api/test/org/apache/cloudstack/api/command/test/AddSecondaryStorageCmdTest.java b/api/test/org/apache/cloudstack/api/command/test/AddSecondaryStorageCmdTest.java index d6de94dd033..c221ace62cc 100644 --- a/api/test/org/apache/cloudstack/api/command/test/AddSecondaryStorageCmdTest.java +++ b/api/test/org/apache/cloudstack/api/command/test/AddSecondaryStorageCmdTest.java @@ -21,29 +21,29 @@ import junit.framework.TestCase; import org.apache.cloudstack.api.ResponseGenerator; import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.command.admin.host.AddSecondaryStorageCmd; +import org.apache.cloudstack.api.command.admin.storage.AddImageStoreCmd; import org.apache.cloudstack.api.response.HostResponse; +import org.apache.cloudstack.api.response.ImageStoreResponse; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.Mockito; -import com.cloud.host.Host; -import com.cloud.resource.ResourceService; - -import edu.emory.mathcs.backport.java.util.Arrays; +import com.cloud.storage.ImageStore; +import com.cloud.storage.StorageService; public class AddSecondaryStorageCmdTest extends TestCase { - private AddSecondaryStorageCmd addSecondaryStorageCmd; + private AddImageStoreCmd addImageStoreCmd; @Rule public ExpectedException expectedException = ExpectedException.none(); + @Override @Before public void setUp() { - addSecondaryStorageCmd = new AddSecondaryStorageCmd() { + addImageStoreCmd = new AddImageStoreCmd() { }; } @@ -51,69 +51,48 @@ public class AddSecondaryStorageCmdTest extends TestCase { @Test public void testExecuteForResult() throws Exception { - ResourceService resourceService = Mockito.mock(ResourceService.class); - addSecondaryStorageCmd._resourceService = resourceService; + StorageService resourceService = Mockito.mock(StorageService.class); + addImageStoreCmd._storageService = resourceService; - Host host = Mockito.mock(Host.class); - Host[] mockHosts = new Host[] { host }; + ImageStore store = Mockito.mock(ImageStore.class); - Mockito.when(resourceService.discoverHosts(addSecondaryStorageCmd)) - .thenReturn(Arrays.asList(mockHosts)); + Mockito.when(resourceService.discoverImageStore(addImageStoreCmd)) + .thenReturn(store); ResponseGenerator responseGenerator = Mockito .mock(ResponseGenerator.class); - addSecondaryStorageCmd._responseGenerator = responseGenerator; + addImageStoreCmd._responseGenerator = responseGenerator; - HostResponse responseHost = new HostResponse(); + ImageStoreResponse responseHost = new ImageStoreResponse(); responseHost.setName("Test"); - Mockito.when(responseGenerator.createHostResponse(host)).thenReturn( + Mockito.when(responseGenerator.createImageStoreResponse(store)).thenReturn( responseHost); - addSecondaryStorageCmd.execute(); + addImageStoreCmd.execute(); - Mockito.verify(responseGenerator).createHostResponse(host); + Mockito.verify(responseGenerator).createImageStoreResponse(store); - HostResponse actualResponse = (HostResponse) addSecondaryStorageCmd + ImageStoreResponse actualResponse = (ImageStoreResponse) addImageStoreCmd .getResponseObject(); Assert.assertEquals(responseHost, actualResponse); - Assert.assertEquals("addsecondarystorageresponse", + Assert.assertEquals("addimagestoreresponse", actualResponse.getResponseName()); } - @Test - public void testExecuteForEmptyResult() throws Exception { - - ResourceService resourceService = Mockito.mock(ResourceService.class); - addSecondaryStorageCmd._resourceService = resourceService; - - Host[] mockHosts = new Host[] {}; - - Mockito.when(resourceService.discoverHosts(addSecondaryStorageCmd)) - .thenReturn(Arrays.asList(mockHosts)); - - try { - addSecondaryStorageCmd.execute(); - } catch (ServerApiException exception) { - Assert.assertEquals("Failed to add secondary storage", - exception.getDescription()); - } - - } - @Test public void testExecuteForNullResult() throws Exception { - ResourceService resourceService = Mockito.mock(ResourceService.class); - addSecondaryStorageCmd._resourceService = resourceService; + StorageService resourceService = Mockito.mock(StorageService.class); + addImageStoreCmd._storageService = resourceService; - Mockito.when(resourceService.discoverHosts(addSecondaryStorageCmd)) + Mockito.when(resourceService.discoverImageStore(addImageStoreCmd)) .thenReturn(null); try { - addSecondaryStorageCmd.execute(); + addImageStoreCmd.execute(); } catch (ServerApiException exception) { Assert.assertEquals("Failed to add secondary storage", exception.getDescription()); diff --git a/api/test/org/apache/cloudstack/api/command/test/AddSwiftCmdTest.java b/api/test/org/apache/cloudstack/api/command/test/AddSwiftCmdTest.java deleted file mode 100644 index 141a2368d78..00000000000 --- a/api/test/org/apache/cloudstack/api/command/test/AddSwiftCmdTest.java +++ /dev/null @@ -1,97 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// 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, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package org.apache.cloudstack.api.command.test; - -import junit.framework.Assert; -import junit.framework.TestCase; - -import org.apache.cloudstack.api.ResponseGenerator; -import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.command.admin.swift.AddSwiftCmd; -import org.apache.cloudstack.api.response.SwiftResponse; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; - -import com.cloud.exception.DiscoveryException; -import com.cloud.resource.ResourceService; -import com.cloud.storage.Swift; - -public class AddSwiftCmdTest extends TestCase { - - private AddSwiftCmd addSwiftCmd; - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Before - public void setUp() { - addSwiftCmd = new AddSwiftCmd(); - } - - @Test - public void testExecuteSuccess() { - - ResourceService resourceService = Mockito.mock(ResourceService.class); - addSwiftCmd._resourceService = resourceService; - - Swift swift = Mockito.mock(Swift.class); - - try { - Mockito.when(resourceService.discoverSwift(addSwiftCmd)) - .thenReturn(swift); - } catch (DiscoveryException e) { - e.printStackTrace(); - } - - ResponseGenerator responseGenerator = Mockito - .mock(ResponseGenerator.class); - addSwiftCmd._responseGenerator = responseGenerator; - - SwiftResponse swiftResponse = Mockito.mock(SwiftResponse.class); - - Mockito.when(responseGenerator.createSwiftResponse(swift)).thenReturn( - swiftResponse); - - addSwiftCmd.execute(); - - } - - @Test - public void testExecuteFailure() { - - ResourceService resourceService = Mockito.mock(ResourceService.class); - addSwiftCmd._resourceService = resourceService; - try { - Mockito.when(resourceService.discoverSwift(addSwiftCmd)) - .thenReturn(null); - } catch (DiscoveryException e) { - e.printStackTrace(); - } - - try { - addSwiftCmd.execute(); - } catch (ServerApiException exception) { - Assert.assertEquals("Failed to add Swift", - exception.getDescription()); - } - - } - -} diff --git a/client/pom.xml b/client/pom.xml index ab758eb2a67..672f4ebfa85 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -30,7 +30,7 @@ cloud-plugin-acl-static-role-based ${project.version} - + org.apache.cloudstack cloud-plugin-dedicated-resources ${project.version} @@ -211,7 +211,7 @@ org.apache.cloudstack - cloud-engine-storage-backup + cloud-engine-storage-cache ${project.version} @@ -221,7 +221,7 @@ org.apache.cloudstack - cloud-engine-storage-imagemotion + cloud-engine-storage-datamotion ${project.version} @@ -244,6 +244,21 @@ cloud-plugin-storage-volume-default ${project.version} + + org.apache.cloudstack + cloud-plugin-storage-image-default + ${project.version} + + + org.apache.cloudstack + cloud-plugin-storage-image-s3 + ${project.version} + + + org.apache.cloudstack + cloud-plugin-storage-image-swift + ${project.version} + org.apache.cloudstack cloud-plugin-syslog-alerts diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in index 049e483bf5e..2a746a9cd05 100644 --- a/client/tomcatconf/applicationContext.xml.in +++ b/client/tomcatconf/applicationContext.xml.in @@ -93,7 +93,7 @@ - + @@ -156,7 +156,7 @@ - + @@ -166,7 +166,7 @@ - + @@ -198,7 +198,6 @@ - @@ -221,6 +220,7 @@ + @@ -231,8 +231,13 @@ - - + + + + + + + @@ -284,7 +289,7 @@ - + @@ -312,7 +317,6 @@ - @@ -368,7 +372,6 @@ - @@ -734,9 +737,10 @@ + + + - - @@ -753,17 +757,15 @@ - + + - - - - - + + - + @@ -780,7 +782,6 @@ - @@ -808,8 +809,12 @@ + + + + diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 5eccf366c66..6ee1e6405dd 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -249,6 +249,12 @@ listSwifts=1 addS3=1 listS3s=1 +#### image store commands +addImageStore=1 +listImageStores=1 +deleteImageStore=1 +createCacheStore=1 + #### host commands addHost=3 addCluster=1 diff --git a/client/tomcatconf/log4j-cloud.xml.in b/client/tomcatconf/log4j-cloud.xml.in index 0e7f004eb80..fc1c29ef5e1 100755 --- a/client/tomcatconf/log4j-cloud.xml.in +++ b/client/tomcatconf/log4j-cloud.xml.in @@ -132,6 +132,10 @@ under the License. + + + + diff --git a/core/src/com/cloud/agent/Listener.java b/core/src/com/cloud/agent/Listener.java index 47b9bc3011d..242f90cfeed 100755 --- a/core/src/com/cloud/agent/Listener.java +++ b/core/src/com/cloud/agent/Listener.java @@ -22,39 +22,39 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.StartupCommand; import com.cloud.exception.ConnectionException; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.host.Status; /** * There are several types of events that the AgentManager forwards - * + * * 1. Agent Connect & Disconnect * 2. Commands sent by the agent. * 3. Answers sent by the agent. */ public interface Listener { - /** - * - * @param agentId id of the agent - * @param seq sequence number return by the send() method. - * @param answers answers to the commands. - * @return true if processed. false if not. - */ + /** + * + * @param agentId id of the agent + * @param seq sequence number return by the send() method. + * @param answers answers to the commands. + * @return true if processed. false if not. + */ boolean processAnswers(long agentId, long seq, Answer[] answers); /** * This method is called by the AgentManager when an agent sent * a command to the server. In order to process these commands, * the Listener must be registered for host commands. - * + * * @param agentId id of the agent. * @param seq sequence number of the command sent. * @param commands commands that were sent. * @return true if you processed the commands. false if not. */ boolean processCommands(long agentId, long seq, Command[] commands); - + /** * process control command sent from agent under its management * @param agentId @@ -72,26 +72,26 @@ public interface Listener { * @param agentId id of the agent * @throws ConnectionException if host has problems and needs to put into maintenance state. */ - void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) throws ConnectionException; - + void processConnect(Host host, StartupCommand cmd, boolean forRebalance) throws ConnectionException; + /** * This method is called by AgentManager when an agent disconnects * from this server if the listener has been registered for host events. - * + * * If the Listener is passed to the send() method, this method is * also called by AgentManager if the agent disconnected. - * + * * @param agentId id of the agent * @param state the current state of the agent. */ boolean processDisconnect(long agentId, Status state); - + /** * If this Listener is passed to the send() method, this method * is called by AgentManager after processing an answer * from the agent. Returning true means you're expecting more * answers from the agent using the same sequence number. - * + * * @return true if expecting more answers using the same sequence number. */ boolean isRecurring(); @@ -102,7 +102,7 @@ public interface Listener { * is in seconds. -1 indicates to wait forever. 0 indicates to * use the default timeout. If the timeout is * reached, processTimeout on this same Listener is called. - * + * * @return timeout in seconds before processTimeout is called. */ int getTimeout(); @@ -115,5 +115,5 @@ public interface Listener { * @return true if processed; false if not. */ boolean processTimeout(long agentId, long seq); - + } diff --git a/core/src/com/cloud/agent/api/CleanupSnapshotBackupCommand.java b/core/src/com/cloud/agent/api/CleanupSnapshotBackupCommand.java deleted file mode 100644 index ae65a529c52..00000000000 --- a/core/src/com/cloud/agent/api/CleanupSnapshotBackupCommand.java +++ /dev/null @@ -1,75 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// 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, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package com.cloud.agent.api; - -import java.util.List; - -public class CleanupSnapshotBackupCommand extends Command { - private String secondaryStoragePoolURL; - private Long dcId; - private Long accountId; - private Long volumeId; - private List validBackupUUIDs; - - protected CleanupSnapshotBackupCommand() { - - } - - /* - * @param secondaryStoragePoolURL This is what shows up in the UI when you click on Secondary storage. - * In the code, it is present as: In the vmops.host_details table, there is a field mount.parent. This is the value of that field - * If you have better ideas on how to get it, you are welcome. - * @param validBackupUUID The VHD which are valid - */ - public CleanupSnapshotBackupCommand(String secondaryStoragePoolURL, - Long dcId, - Long accountId, - Long volumeId, - List validBackupUUIDs) - { - this.secondaryStoragePoolURL = secondaryStoragePoolURL; - this.dcId = dcId; - this.accountId = accountId; - this.volumeId = volumeId; - this.validBackupUUIDs = validBackupUUIDs; - } - - public String getSecondaryStoragePoolURL() { - return secondaryStoragePoolURL; - } - - public Long getDcId() { - return dcId; - } - - public Long getAccountId() { - return accountId; - } - - public Long getVolumeId() { - return volumeId; - } - - public List getValidBackupUUIDs() { - return validBackupUUIDs; - } - - @Override - public boolean executeInSequence() { - return false; - } -} diff --git a/core/src/com/cloud/agent/api/ComputeChecksumCommand.java b/core/src/com/cloud/agent/api/ComputeChecksumCommand.java index a2c88c440a8..95c67bf218c 100755 --- a/core/src/com/cloud/agent/api/ComputeChecksumCommand.java +++ b/core/src/com/cloud/agent/api/ComputeChecksumCommand.java @@ -17,24 +17,32 @@ package com.cloud.agent.api; import com.cloud.agent.api.storage.ssCommand; +import com.cloud.agent.api.to.DataStoreTO; public class ComputeChecksumCommand extends ssCommand { - - + private DataStoreTO store; private String templatePath; public ComputeChecksumCommand() { super(); } - public ComputeChecksumCommand(String secUrl, String templatePath) { - super(secUrl); + public ComputeChecksumCommand(DataStoreTO store, String templatePath) { this.templatePath = templatePath; + this.setStore(store); } public String getTemplatePath() { return templatePath; } + public DataStoreTO getStore() { + return store; + } + + public void setStore(DataStoreTO store) { + this.store = store; + } + } diff --git a/core/src/com/cloud/agent/api/DeleteObjectFromSwiftCommand.java b/core/src/com/cloud/agent/api/DeleteObjectFromSwiftCommand.java deleted file mode 100644 index 3d62c507b89..00000000000 --- a/core/src/com/cloud/agent/api/DeleteObjectFromSwiftCommand.java +++ /dev/null @@ -1,61 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// 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, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package com.cloud.agent.api; - -import com.cloud.agent.api.LogLevel.Log4jLevel; -import com.cloud.agent.api.to.SwiftTO; - -/** - * - * - */ - -public class DeleteObjectFromSwiftCommand extends Command { - @LogLevel(Log4jLevel.Off) - private SwiftTO swift; - private String container; - private String object; - - protected DeleteObjectFromSwiftCommand() { - - } - - public DeleteObjectFromSwiftCommand(SwiftTO swift, String container, String object) { - this.swift = swift; - this.container = container; - this.object = object; - } - - public SwiftTO getSwift() { - return this.swift; - } - - public String getContainer() { - return container; - } - - public String getObject() { - return object; - } - - @Override - public boolean executeInSequence() { - // TODO Auto-generated method stub - return true; - } - -} diff --git a/core/src/com/cloud/agent/api/DeleteSnapshotBackupCommand.java b/core/src/com/cloud/agent/api/DeleteSnapshotBackupCommand.java deleted file mode 100644 index 128df84c729..00000000000 --- a/core/src/com/cloud/agent/api/DeleteSnapshotBackupCommand.java +++ /dev/null @@ -1,96 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// 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, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package com.cloud.agent.api; - -import com.cloud.agent.api.LogLevel.Log4jLevel; -import com.cloud.agent.api.to.S3TO; -import com.cloud.agent.api.to.SwiftTO; -import com.cloud.storage.StoragePool; - -/** - * This command encapsulates a primitive operation which enables coalescing the backed up VHD snapshots on the secondary server - * This currently assumes that the secondary storage are mounted on the XenServer. - */ -public class DeleteSnapshotBackupCommand extends SnapshotCommand { - @LogLevel(Log4jLevel.Off) - private SwiftTO swift; - private S3TO s3; - private Boolean all; - - public SwiftTO getSwift() { - return swift; - } - - public Boolean isAll() { - return all; - } - - public void setAll(Boolean all) { - this.all = all; - } - - public void setSwift(SwiftTO swift) { - this.swift = swift; - } - - public S3TO getS3() { - return s3; - } - - protected DeleteSnapshotBackupCommand() { - } - - /** - * Given 2 VHD files on the secondary storage which are linked in a parent chain as follows: - * backupUUID = parent(childUUID) - * It gets another VHD - * previousBackupVHD = parent(backupUUID) - * - * And - * 1) it coalesces backupUuid into its parent. - * 2) It deletes the VHD file corresponding to backupUuid - * 3) It sets the parent VHD of childUUID to that of previousBackupUuid - * - * It takes care of the cases when - * 1) childUUID is null. - Step 3 is not done. - * 2) previousBackupUUID is null - * - Merge childUUID into its parent backupUUID - * - Set the UUID of the resultant VHD to childUUID - * - Essentially we are deleting the oldest VHD file and setting the current oldest VHD to childUUID - * - * @param volumeName The name of the volume whose snapshot was taken (something like i-3-SV-ROOT) - * @param secondaryStoragePoolURL This is what shows up in the UI when you click on Secondary storage. - * In the code, it is present as: In the vmops.host_details table, there is a field mount.parent. This is the value of that field - * If you have better ideas on how to get it, you are welcome. - * @param backupUUID The VHD which has to be deleted - * @param childUUID The child VHD file of the backup whose parent is reset to its grandparent. - */ - public DeleteSnapshotBackupCommand(StoragePool pool, - SwiftTO swift, - S3TO s3, - String secondaryStoragePoolURL, - Long dcId, - Long accountId, - Long volumeId, - String backupUUID, Boolean all) - { - super(pool, secondaryStoragePoolURL, backupUUID, null, dcId, accountId, volumeId); - setSwift(swift); - this.s3 = s3; - setAll(all); - } -} diff --git a/core/src/com/cloud/agent/api/DeleteSnapshotsDirCommand.java b/core/src/com/cloud/agent/api/DeleteSnapshotsDirCommand.java index e2071d7f746..26d75867851 100644 --- a/core/src/com/cloud/agent/api/DeleteSnapshotsDirCommand.java +++ b/core/src/com/cloud/agent/api/DeleteSnapshotsDirCommand.java @@ -16,27 +16,23 @@ // under the License. package com.cloud.agent.api; +import com.cloud.agent.api.to.DataStoreTO; + /** * This command encapsulates a primitive operation which enables coalescing the backed up VHD snapshots on the secondary server * This currently assumes that the secondary storage are mounted on the XenServer. */ public class DeleteSnapshotsDirCommand extends Command { - String secondaryStorageUrl; - Long dcId; - Long accountId; - Long volumeId; + DataStoreTO store; + String directory; protected DeleteSnapshotsDirCommand() { } - public DeleteSnapshotsDirCommand(String secondaryStorageUrl, - Long dcId, Long accountId, Long volumeId) - { - this.secondaryStorageUrl = secondaryStorageUrl; - this.dcId = dcId; - this.accountId = accountId; - this.volumeId = volumeId; + public DeleteSnapshotsDirCommand(DataStoreTO store, String dir) { + this.store = store; + this.directory = dir; } @Override @@ -44,20 +40,12 @@ public class DeleteSnapshotsDirCommand extends Command { return true; } - public String getSecondaryStorageUrl() { - return secondaryStorageUrl; + public DataStoreTO getDataStore() { + return store; } - public Long getDcId() { - return dcId; - } - public Long getAccountId() { - return accountId; + public String getDirectory() { + return directory; } - - public Long getVolumeId() { - return volumeId; - } - } diff --git a/core/src/com/cloud/agent/api/DeleteTemplateFromS3Command.java b/core/src/com/cloud/agent/api/DeleteTemplateFromS3Command.java deleted file mode 100644 index 278669b2c97..00000000000 --- a/core/src/com/cloud/agent/api/DeleteTemplateFromS3Command.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package com.cloud.agent.api; - -import com.cloud.agent.api.to.S3TO; - -public class DeleteTemplateFromS3Command extends Command { - - private S3TO s3; - private Long templateId; - private Long accountId; - - protected DeleteTemplateFromS3Command() { - super(); - } - - public DeleteTemplateFromS3Command(final S3TO s3, final Long accountId, - final Long templateId) { - - super(); - - this.s3 = s3; - this.accountId = accountId; - this.templateId = templateId; - - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + ((accountId == null) ? 0 : accountId.hashCode()); - result = prime * result + ((s3 == null) ? 0 : s3.hashCode()); - result = prime * result - + ((templateId == null) ? 0 : templateId.hashCode()); - return result; - } - - @Override - public boolean equals(Object thatObject) { - - if (this == thatObject) { - return true; - } - - if (thatObject == null) { - return false; - } - - if (getClass() != thatObject.getClass()) { - return false; - } - - final DeleteTemplateFromS3Command thatCommand = (DeleteTemplateFromS3Command) thatObject; - - if (!(accountId == thatCommand.accountId) - || (this.accountId != null && this.accountId - .equals(thatCommand.accountId))) { - return false; - } - - if (!(templateId == thatCommand.templateId) - || (this.templateId != null && this.templateId - .equals(thatCommand.templateId))) { - return false; - } - - return true; - - } - - public S3TO getS3() { - return s3; - } - - public Long getTemplateId() { - return templateId; - } - - public Long getAccountId() { - return accountId; - } - - @Override - public boolean executeInSequence() { - return true; - } - -} diff --git a/core/src/com/cloud/agent/api/MigrateWithStorageAnswer.java b/core/src/com/cloud/agent/api/MigrateWithStorageAnswer.java index 06aff323bdc..d87a5f184c8 100644 --- a/core/src/com/cloud/agent/api/MigrateWithStorageAnswer.java +++ b/core/src/com/cloud/agent/api/MigrateWithStorageAnswer.java @@ -17,23 +17,27 @@ package com.cloud.agent.api; import java.util.List; + +import org.apache.cloudstack.storage.to.VolumeObjectTO; + +import com.cloud.agent.api.to.DiskTO; import com.cloud.agent.api.to.VolumeTO; public class MigrateWithStorageAnswer extends Answer { - List volumeTos; + List volumeTos; public MigrateWithStorageAnswer(MigrateWithStorageCommand cmd, Exception ex) { super(cmd, ex); volumeTos = null; } - public MigrateWithStorageAnswer(MigrateWithStorageCommand cmd, List volumeTos) { + public MigrateWithStorageAnswer(MigrateWithStorageCommand cmd, List volumeTos) { super(cmd, true, null); this.volumeTos = volumeTos; } - public List getVolumeTos() { + public List getVolumeTos() { return volumeTos; } } diff --git a/core/src/com/cloud/agent/api/MigrateWithStorageCompleteAnswer.java b/core/src/com/cloud/agent/api/MigrateWithStorageCompleteAnswer.java index 920cf48ca49..fd8f22f3579 100644 --- a/core/src/com/cloud/agent/api/MigrateWithStorageCompleteAnswer.java +++ b/core/src/com/cloud/agent/api/MigrateWithStorageCompleteAnswer.java @@ -17,22 +17,25 @@ package com.cloud.agent.api; import java.util.List; + +import org.apache.cloudstack.storage.to.VolumeObjectTO; + import com.cloud.agent.api.to.VolumeTO; public class MigrateWithStorageCompleteAnswer extends Answer { - List volumeTos; + List volumeTos; public MigrateWithStorageCompleteAnswer(MigrateWithStorageCompleteCommand cmd, Exception ex) { super(cmd, ex); volumeTos = null; } - public MigrateWithStorageCompleteAnswer(MigrateWithStorageCompleteCommand cmd, List volumeTos) { + public MigrateWithStorageCompleteAnswer(MigrateWithStorageCompleteCommand cmd, List volumeTos) { super(cmd, true, null); this.volumeTos = volumeTos; } - public List getVolumeTos() { + public List getVolumeTos() { return volumeTos; } } diff --git a/core/src/com/cloud/agent/api/ModifyStoragePoolAnswer.java b/core/src/com/cloud/agent/api/ModifyStoragePoolAnswer.java index df77985248f..ed7043a8ec4 100644 --- a/core/src/com/cloud/agent/api/ModifyStoragePoolAnswer.java +++ b/core/src/com/cloud/agent/api/ModifyStoragePoolAnswer.java @@ -18,16 +18,16 @@ package com.cloud.agent.api; import java.util.Map; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; public class ModifyStoragePoolAnswer extends Answer { StoragePoolInfo poolInfo; - Map templateInfo; + Map templateInfo; protected ModifyStoragePoolAnswer() { } - public ModifyStoragePoolAnswer(ModifyStoragePoolCommand cmd, long capacityBytes, long availableBytes, Map tInfo) { + public ModifyStoragePoolAnswer(ModifyStoragePoolCommand cmd, long capacityBytes, long availableBytes, Map tInfo) { super(cmd); this.result = true; this.poolInfo = new StoragePoolInfo(null, @@ -46,11 +46,11 @@ public class ModifyStoragePoolAnswer extends Answer { } - public Map getTemplateInfo() { + public Map getTemplateInfo() { return templateInfo; } - public void setTemplateInfo(Map templateInfo) { + public void setTemplateInfo(Map templateInfo) { this.templateInfo = templateInfo; } diff --git a/core/src/com/cloud/agent/api/SecStorageSetupCommand.java b/core/src/com/cloud/agent/api/SecStorageSetupCommand.java index 50c06cffa43..b1f32348baa 100644 --- a/core/src/com/cloud/agent/api/SecStorageSetupCommand.java +++ b/core/src/com/cloud/agent/api/SecStorageSetupCommand.java @@ -17,8 +17,10 @@ package com.cloud.agent.api; import com.cloud.agent.api.LogLevel.Log4jLevel; +import com.cloud.agent.api.to.DataStoreTO; public class SecStorageSetupCommand extends Command { + private DataStoreTO store; private String secUrl; private Certificates certs; @@ -57,10 +59,11 @@ public class SecStorageSetupCommand extends Command { super(); } - public SecStorageSetupCommand(String secUrl, Certificates certs) { + public SecStorageSetupCommand(DataStoreTO store, String secUrl, Certificates certs) { super(); this.secUrl = secUrl; this.certs = certs; + this.store = store; } @Override @@ -80,4 +83,14 @@ public class SecStorageSetupCommand extends Command { this.secUrl = secUrl; } + + public DataStoreTO getDataStore() { + return store; + } + + public void setDataStore(DataStoreTO store) { + this.store = store; + } + + } diff --git a/core/src/com/cloud/agent/api/SnapshotCommand.java b/core/src/com/cloud/agent/api/SnapshotCommand.java index d8abeb62371..ccf9613d5e8 100644 --- a/core/src/com/cloud/agent/api/SnapshotCommand.java +++ b/core/src/com/cloud/agent/api/SnapshotCommand.java @@ -53,8 +53,8 @@ public class SnapshotCommand extends Command { public SnapshotCommand(StoragePool pool, String secondaryStorageUrl, String snapshotUuid, String snapshotName, Long dcId, Long accountId, Long volumeId) { - this.primaryStoragePoolNameLabel = pool.getUuid(); - this.primaryPool = new StorageFilerTO(pool); + // this.primaryStoragePoolNameLabel = pool.getUuid(); + //this.primaryPool = new StorageFilerTO(pool); this.snapshotUuid = snapshotUuid; this.secondaryStorageUrl = secondaryStorageUrl; this.dcId = dcId; diff --git a/core/src/com/cloud/agent/api/StartupStorageCommand.java b/core/src/com/cloud/agent/api/StartupStorageCommand.java index 3c3b058ce39..52ed3ffdff3 100755 --- a/core/src/com/cloud/agent/api/StartupStorageCommand.java +++ b/core/src/com/cloud/agent/api/StartupStorageCommand.java @@ -22,13 +22,13 @@ import java.util.Map; import com.cloud.host.Host; import com.cloud.storage.Storage; import com.cloud.storage.Storage.StoragePoolType; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; public class StartupStorageCommand extends StartupCommand { String parent; - Map templateInfo; + Map templateInfo; long totalSize; StoragePoolInfo poolInfo; Storage.StorageResourceType resourceType; @@ -40,7 +40,7 @@ public class StartupStorageCommand extends StartupCommand { super(Host.Type.Storage); } - public StartupStorageCommand(String parent, StoragePoolType fsType, long totalSize, Map info) { + public StartupStorageCommand(String parent, StoragePoolType fsType, long totalSize, Map info) { super(Host.Type.Storage); this.parent = parent; this.totalSize = totalSize; @@ -50,7 +50,7 @@ public class StartupStorageCommand extends StartupCommand { } - public StartupStorageCommand(String parent, StoragePoolType fsType, Map templateInfo, StoragePoolInfo poolInfo) { + public StartupStorageCommand(String parent, StoragePoolType fsType, Map templateInfo, StoragePoolInfo poolInfo) { super(Host.Type.Storage); this.parent = parent; this.templateInfo = templateInfo; @@ -79,11 +79,11 @@ public class StartupStorageCommand extends StartupCommand { return totalSize; } - public Map getTemplateInfo() { + public Map getTemplateInfo() { return templateInfo; } - public void setTemplateInfo(Map templateInfo) { + public void setTemplateInfo(Map templateInfo) { this.templateInfo = templateInfo; } diff --git a/core/src/com/cloud/agent/api/storage/AbstractDownloadCommand.java b/core/src/com/cloud/agent/api/storage/AbstractDownloadCommand.java index 04b3d4360d5..248a41902ac 100644 --- a/core/src/com/cloud/agent/api/storage/AbstractDownloadCommand.java +++ b/core/src/com/cloud/agent/api/storage/AbstractDownloadCommand.java @@ -28,7 +28,7 @@ public abstract class AbstractDownloadCommand extends ssCommand { protected AbstractDownloadCommand() { } - protected AbstractDownloadCommand(String name, String url, ImageFormat format, long accountId) { + protected AbstractDownloadCommand(String name, String url, ImageFormat format, Long accountId) { assert(url != null); url = url.replace('\\', '/'); diff --git a/core/src/com/cloud/agent/api/storage/CopyVolumeAnswer.java b/core/src/com/cloud/agent/api/storage/CopyVolumeAnswer.java index 8c55ac3eecc..b9942b0c4b3 100644 --- a/core/src/com/cloud/agent/api/storage/CopyVolumeAnswer.java +++ b/core/src/com/cloud/agent/api/storage/CopyVolumeAnswer.java @@ -24,6 +24,7 @@ public class CopyVolumeAnswer extends Answer { private String volumePath; protected CopyVolumeAnswer() { + super(); } public CopyVolumeAnswer(Command command, boolean success, String details, String volumeFolder, String volumePath) { diff --git a/core/src/com/cloud/agent/api/storage/CreateAnswer.java b/core/src/com/cloud/agent/api/storage/CreateAnswer.java index ab6cc038604..cd2a7c8f00b 100644 --- a/core/src/com/cloud/agent/api/storage/CreateAnswer.java +++ b/core/src/com/cloud/agent/api/storage/CreateAnswer.java @@ -23,6 +23,7 @@ public class CreateAnswer extends Answer { VolumeTO volume; boolean requestTemplateReload = false; protected CreateAnswer() { + super(); } public CreateAnswer(CreateCommand cmd, VolumeTO volume) { diff --git a/core/src/com/cloud/agent/api/storage/CreatePrivateTemplateAnswer.java b/core/src/com/cloud/agent/api/storage/CreatePrivateTemplateAnswer.java index 83db84d8b87..37ebbfe4082 100644 --- a/core/src/com/cloud/agent/api/storage/CreatePrivateTemplateAnswer.java +++ b/core/src/com/cloud/agent/api/storage/CreatePrivateTemplateAnswer.java @@ -27,7 +27,9 @@ public class CreatePrivateTemplateAnswer extends Answer { private String _uniqueName; private ImageFormat _format; - public CreatePrivateTemplateAnswer() {} + public CreatePrivateTemplateAnswer() { + super(); + } public CreatePrivateTemplateAnswer(Command cmd, boolean success, String result, String path, long virtualSize, long physicalSize, String uniqueName, ImageFormat format) { diff --git a/core/src/com/cloud/agent/api/storage/ListTemplateAnswer.java b/core/src/com/cloud/agent/api/storage/ListTemplateAnswer.java index a4e2e255001..a3542cf6083 100644 --- a/core/src/com/cloud/agent/api/storage/ListTemplateAnswer.java +++ b/core/src/com/cloud/agent/api/storage/ListTemplateAnswer.java @@ -19,27 +19,27 @@ package com.cloud.agent.api.storage; import java.util.Map; import com.cloud.agent.api.Answer; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; public class ListTemplateAnswer extends Answer { private String secUrl; - private Map templateInfos; + private Map templateInfos; public ListTemplateAnswer() { - + super(); } - public ListTemplateAnswer(String secUrl, Map templateInfos) { + public ListTemplateAnswer(String secUrl, Map templateInfos) { super(null, true, "success"); this.setSecUrl(secUrl); this.templateInfos = templateInfos; } - public Map getTemplateInfo() { + public Map getTemplateInfo() { return templateInfos; } - public void setTemplateInfo(Map templateInfos) { + public void setTemplateInfo(Map templateInfos) { this.templateInfos = templateInfos; } diff --git a/core/src/com/cloud/agent/api/storage/ListTemplateCommand.java b/core/src/com/cloud/agent/api/storage/ListTemplateCommand.java index da25ed56bf3..e5339f2982d 100644 --- a/core/src/com/cloud/agent/api/storage/ListTemplateCommand.java +++ b/core/src/com/cloud/agent/api/storage/ListTemplateCommand.java @@ -16,39 +16,32 @@ // under the License. package com.cloud.agent.api.storage; -import com.cloud.agent.api.LogLevel; -import com.cloud.agent.api.LogLevel.Log4jLevel; -import com.cloud.agent.api.to.SwiftTO; +import com.cloud.agent.api.to.DataStoreTO; public class ListTemplateCommand extends StorageCommand { - private String secUrl; - @LogLevel(Log4jLevel.Off) - private SwiftTO swift; + private DataStoreTO store; + //private String secUrl; public ListTemplateCommand() { } - public ListTemplateCommand(String secUrl) { - this.secUrl = secUrl; - this.swift = null; + public ListTemplateCommand(DataStoreTO store) { + this.store = store; +// this.secUrl = url; } - public ListTemplateCommand(SwiftTO swift) { - this.secUrl = null; - this.swift = swift; - } - @Override public boolean executeInSequence() { return true; } - public String getSecUrl() { - return secUrl; + + public DataStoreTO getDataStore() { + return store; } - public SwiftTO getSwift() { - return swift; - } + // public String getSecUrl() { + // return secUrl; + // } } diff --git a/core/src/com/cloud/agent/api/storage/ListVolumeAnswer.java b/core/src/com/cloud/agent/api/storage/ListVolumeAnswer.java index 6bbb2e82c33..9995d4b715e 100755 --- a/core/src/com/cloud/agent/api/storage/ListVolumeAnswer.java +++ b/core/src/com/cloud/agent/api/storage/ListVolumeAnswer.java @@ -19,27 +19,27 @@ package com.cloud.agent.api.storage; import java.util.Map; import com.cloud.agent.api.Answer; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; public class ListVolumeAnswer extends Answer { private String secUrl; - private Map templateInfos; + private Map templateInfos; public ListVolumeAnswer() { - + super(); } - public ListVolumeAnswer(String secUrl, Map templateInfos) { + public ListVolumeAnswer(String secUrl, Map templateInfos) { super(null, true, "success"); this.setSecUrl(secUrl); this.templateInfos = templateInfos; } - public Map getTemplateInfo() { + public Map getTemplateInfo() { return templateInfos; } - public void setTemplateInfo(Map templateInfos) { + public void setTemplateInfo(Map templateInfos) { this.templateInfos = templateInfos; } diff --git a/core/src/com/cloud/agent/api/storage/ListVolumeCommand.java b/core/src/com/cloud/agent/api/storage/ListVolumeCommand.java index 63c5b621c6e..0de44defdb1 100755 --- a/core/src/com/cloud/agent/api/storage/ListVolumeCommand.java +++ b/core/src/com/cloud/agent/api/storage/ListVolumeCommand.java @@ -16,15 +16,19 @@ // under the License. package com.cloud.agent.api.storage; +import com.cloud.agent.api.to.DataStoreTO; + public class ListVolumeCommand extends StorageCommand { + private DataStoreTO store; private String secUrl; public ListVolumeCommand() { } - public ListVolumeCommand(String secUrl) { + public ListVolumeCommand(DataStoreTO store, String secUrl) { + this.store = store; this.secUrl = secUrl; } @@ -37,4 +41,7 @@ public class ListVolumeCommand extends StorageCommand { return secUrl; } + public DataStoreTO getDataStore() { + return store; + } } diff --git a/core/src/com/cloud/agent/api/storage/ManageVolumeAvailabilityAnswer.java b/core/src/com/cloud/agent/api/storage/ManageVolumeAvailabilityAnswer.java index edd283090b1..e8e0d20a074 100644 --- a/core/src/com/cloud/agent/api/storage/ManageVolumeAvailabilityAnswer.java +++ b/core/src/com/cloud/agent/api/storage/ManageVolumeAvailabilityAnswer.java @@ -22,6 +22,7 @@ import com.cloud.agent.api.Command; public class ManageVolumeAvailabilityAnswer extends Answer { protected ManageVolumeAvailabilityAnswer() { + super(); } public ManageVolumeAvailabilityAnswer(Command command, boolean success, String details) { diff --git a/core/src/com/cloud/agent/api/storage/PrimaryStorageDownloadAnswer.java b/core/src/com/cloud/agent/api/storage/PrimaryStorageDownloadAnswer.java index a5a6c49e9ab..6300fee84ec 100644 --- a/core/src/com/cloud/agent/api/storage/PrimaryStorageDownloadAnswer.java +++ b/core/src/com/cloud/agent/api/storage/PrimaryStorageDownloadAnswer.java @@ -23,6 +23,7 @@ public class PrimaryStorageDownloadAnswer extends Answer { private long templateSize = 0L; protected PrimaryStorageDownloadAnswer() { + super(); } public PrimaryStorageDownloadAnswer(String detail) { diff --git a/core/src/com/cloud/agent/api/storage/PrimaryStorageDownloadCommand.java b/core/src/com/cloud/agent/api/storage/PrimaryStorageDownloadCommand.java index 8d955bb1c63..b0d0fdf87eb 100644 --- a/core/src/com/cloud/agent/api/storage/PrimaryStorageDownloadCommand.java +++ b/core/src/com/cloud/agent/api/storage/PrimaryStorageDownloadCommand.java @@ -34,7 +34,16 @@ public class PrimaryStorageDownloadCommand extends AbstractDownloadCommand { String primaryStorageUrl; protected PrimaryStorageDownloadCommand() { + } + + public PrimaryStorageDownloadCommand(String url, StoragePool pool, int wait) { + super(null, url, null, null); + this.poolId = pool.getId(); + this.poolUuid = pool.getUuid(); + this.primaryPool = new StorageFilerTO(pool); + setWait(wait); + } public PrimaryStorageDownloadCommand(String name, String url, ImageFormat format, long accountId, StoragePool pool, int wait) { super(name, url, format, accountId); diff --git a/core/src/com/cloud/agent/api/storage/ResizeVolumeAnswer.java b/core/src/com/cloud/agent/api/storage/ResizeVolumeAnswer.java index 3434b985aaa..9d4c974e5a7 100644 --- a/core/src/com/cloud/agent/api/storage/ResizeVolumeAnswer.java +++ b/core/src/com/cloud/agent/api/storage/ResizeVolumeAnswer.java @@ -22,7 +22,7 @@ public class ResizeVolumeAnswer extends Answer { private long newSize; protected ResizeVolumeAnswer() { - + super(); } public ResizeVolumeAnswer(ResizeVolumeCommand cmd, boolean result, String details, long newSize) { diff --git a/core/src/com/cloud/agent/api/storage/UpgradeDiskAnswer.java b/core/src/com/cloud/agent/api/storage/UpgradeDiskAnswer.java index 9660136b9e0..b328c907553 100644 --- a/core/src/com/cloud/agent/api/storage/UpgradeDiskAnswer.java +++ b/core/src/com/cloud/agent/api/storage/UpgradeDiskAnswer.java @@ -21,7 +21,9 @@ import com.cloud.agent.api.Command; public class UpgradeDiskAnswer extends Answer { - public UpgradeDiskAnswer() {} + public UpgradeDiskAnswer() { + super(); + } public UpgradeDiskAnswer(Command cmd, boolean success, String details) { super(cmd, success, details); diff --git a/core/src/com/cloud/agent/api/storage/UploadCommand.java b/core/src/com/cloud/agent/api/storage/UploadCommand.java index 473bd5b75ac..9b893e2abd5 100644 --- a/core/src/com/cloud/agent/api/storage/UploadCommand.java +++ b/core/src/com/cloud/agent/api/storage/UploadCommand.java @@ -18,7 +18,6 @@ package com.cloud.agent.api.storage; import org.apache.cloudstack.api.InternalIdentity; -import com.cloud.agent.api.storage.DownloadCommand.PasswordAuth; import com.cloud.agent.api.to.TemplateTO; import com.cloud.storage.Upload.Type; import com.cloud.template.VirtualMachineTemplate; diff --git a/core/src/com/cloud/agent/transport/ArrayTypeAdaptor.java b/core/src/com/cloud/agent/transport/ArrayTypeAdaptor.java index 8eddc0328b7..ffb26b6dc84 100755 --- a/core/src/com/cloud/agent/transport/ArrayTypeAdaptor.java +++ b/core/src/com/cloud/agent/transport/ArrayTypeAdaptor.java @@ -39,8 +39,6 @@ public class ArrayTypeAdaptor implements JsonDeserializer, JsonSerialize protected Gson _gson = null; - private static final String s_pkg = Command.class.getPackage().getName() + "."; - public ArrayTypeAdaptor() { } @@ -53,7 +51,7 @@ public class ArrayTypeAdaptor implements JsonDeserializer, JsonSerialize JsonArray array = new JsonArray(); for (T cmd : src) { JsonObject obj = new JsonObject(); - obj.add(cmd.getClass().getName().substring(s_pkg.length()), _gson.toJsonTree(cmd)); + obj.add(cmd.getClass().getName(), _gson.toJsonTree(cmd)); array.add(obj); } @@ -71,7 +69,7 @@ public class ArrayTypeAdaptor implements JsonDeserializer, JsonSerialize JsonObject element = (JsonObject)it.next(); Map.Entry entry = element.entrySet().iterator().next(); - String name = s_pkg + entry.getKey(); + String name = entry.getKey(); Class clazz; try { clazz = Class.forName(name); diff --git a/core/src/com/cloud/agent/transport/InterfaceTypeAdaptor.java b/core/src/com/cloud/agent/transport/InterfaceTypeAdaptor.java new file mode 100644 index 00000000000..1ad4afc1948 --- /dev/null +++ b/core/src/com/cloud/agent/transport/InterfaceTypeAdaptor.java @@ -0,0 +1,66 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.agent.transport; + +import java.lang.reflect.Type; +import java.util.Map; + +import com.cloud.utils.exception.CloudRuntimeException; +import com.google.gson.Gson; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +public class InterfaceTypeAdaptor implements JsonDeserializer, JsonSerializer { + + protected Gson _gson = null; + + + public InterfaceTypeAdaptor() { + } + + public void initGson(Gson gson) { + _gson = gson; + } + + @Override + public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject obj = new JsonObject(); + obj.add(src.getClass().getName(), _gson.toJsonTree(src)); + return obj; + } + + @Override + @SuppressWarnings("unchecked") + public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + JsonObject element = (JsonObject) json; + Map.Entry entry = element.entrySet().iterator().next(); + String name = entry.getKey(); + Class clazz; + try { + clazz = Class.forName(name); + } catch (ClassNotFoundException e) { + throw new CloudRuntimeException("can't find " + name); + } + return (T) _gson.fromJson(entry.getValue(), clazz); + } +} \ No newline at end of file diff --git a/core/src/com/cloud/hypervisor/hyperv/resource/HypervResource.java b/core/src/com/cloud/hypervisor/hyperv/resource/HypervResource.java index 0f9b3dd9c6b..725f0cc1ae2 100755 --- a/core/src/com/cloud/hypervisor/hyperv/resource/HypervResource.java +++ b/core/src/com/cloud/hypervisor/hyperv/resource/HypervResource.java @@ -105,7 +105,7 @@ import com.cloud.resource.ServerResource; import com.cloud.resource.ServerResourceBase; import com.cloud.serializer.GsonHelper; import com.cloud.storage.Volume; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; import com.cloud.utils.Pair; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.DiskProfile; @@ -765,7 +765,7 @@ public class HypervResource extends ServerResourceBase implements ServerResource try { StorageFilerTO pool = cmd.getPool(); s_logger.info("Primary storage pool details: " + pool.getHost() + " " + pool.getPath()); - Map tInfo = new HashMap(); + Map tInfo = new HashMap(); // FIXME: get the actual storage capacity and storage stats of CSV volume // by running powershell cmdlet. This hardcoding just for prototype. ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, diff --git a/core/src/com/cloud/serializer/GsonHelper.java b/core/src/com/cloud/serializer/GsonHelper.java index 8b2dcb0e928..54b6b171712 100644 --- a/core/src/com/cloud/serializer/GsonHelper.java +++ b/core/src/com/cloud/serializer/GsonHelper.java @@ -25,7 +25,10 @@ import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.SecStorageFirewallCfgCommand.PortConfig; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; import com.cloud.agent.transport.ArrayTypeAdaptor; +import com.cloud.agent.transport.InterfaceTypeAdaptor; import com.cloud.agent.transport.LoggingExclusionStrategy; import com.cloud.agent.transport.Request.NwGroupsCommandTypeAdaptor; import com.cloud.agent.transport.Request.PortConfigListTypeAdaptor; @@ -52,6 +55,10 @@ public class GsonHelper { static Gson setDefaultGsonConfig(GsonBuilder builder) { builder.setVersion(1.5); + InterfaceTypeAdaptor dsAdaptor = new InterfaceTypeAdaptor(); + builder.registerTypeAdapter(DataStoreTO.class, dsAdaptor); + InterfaceTypeAdaptor dtAdaptor = new InterfaceTypeAdaptor(); + builder.registerTypeAdapter(DataTO.class, dtAdaptor); ArrayTypeAdaptor cmdAdaptor = new ArrayTypeAdaptor(); builder.registerTypeAdapter(Command[].class, cmdAdaptor); ArrayTypeAdaptor ansAdaptor = new ArrayTypeAdaptor(); @@ -61,6 +68,8 @@ public class GsonHelper { builder.registerTypeAdapter(new TypeToken>() { }.getType(), new NwGroupsCommandTypeAdaptor()); Gson gson = builder.create(); + dsAdaptor.initGson(gson); + dtAdaptor.initGson(gson); cmdAdaptor.initGson(gson); ansAdaptor.initGson(gson); return gson; diff --git a/core/src/com/cloud/storage/GuestOSHypervisorVO.java b/core/src/com/cloud/storage/GuestOSHypervisorVO.java new file mode 100644 index 00000000000..5ab34809280 --- /dev/null +++ b/core/src/com/cloud/storage/GuestOSHypervisorVO.java @@ -0,0 +1,73 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.storage; + +import java.util.UUID; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +@Entity +@Table(name="guest_os_hypervisor") +public class GuestOSHypervisorVO implements GuestOSHypervisor { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + long id; + + @Column(name="guest_os_id") + private long guestOsId; + + @Column(name="guest_os_name") + String guestOsName; + + @Column(name="hypervisor_type") + String hypervisorType; + + + @Override + public long getId() { + return id; + } + + + @Override + public String getHypervisorType() { + return hypervisorType; + } + + + @Override + public String getGuestOsName() { + return guestOsName; + } + + + @Override + public long getGuestOsId() { + return guestOsId; + } + + +} diff --git a/core/src/com/cloud/storage/resource/StorageProcessor.java b/core/src/com/cloud/storage/resource/StorageProcessor.java new file mode 100644 index 00000000000..ca441edcb79 --- /dev/null +++ b/core/src/com/cloud/storage/resource/StorageProcessor.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.cloud.storage.resource; + +import org.apache.cloudstack.storage.command.AttachCommand; +import org.apache.cloudstack.storage.command.CopyCommand; +import org.apache.cloudstack.storage.command.CreateObjectCommand; +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.command.DettachCommand; + +import com.cloud.agent.api.Answer; + +public interface StorageProcessor { + public Answer copyTemplateToPrimaryStorage(CopyCommand cmd); + public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd); + public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd); + public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd); + public Answer createTemplateFromVolume(CopyCommand cmd); + public Answer backupSnasphot(CopyCommand cmd); + public Answer attachIso(AttachCommand cmd); + public Answer attachVolume(AttachCommand cmd); + public Answer dettachIso(DettachCommand cmd); + public Answer dettachVolume(DettachCommand cmd); + public Answer createVolume(CreateObjectCommand cmd); + public Answer createSnapshot(CreateObjectCommand cmd); + public Answer deleteVolume(DeleteCommand cmd); + public Answer createVolumeFromSnapshot(CopyCommand cmd); + public Answer deleteSnapshot(DeleteCommand cmd); +} diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/ImageOrchestrator.java b/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandler.java similarity index 75% rename from engine/storage/image/src/org/apache/cloudstack/storage/image/ImageOrchestrator.java rename to core/src/com/cloud/storage/resource/StorageSubsystemCommandHandler.java index e4141f3fa00..5ac601e38a9 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/ImageOrchestrator.java +++ b/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandler.java @@ -16,14 +16,12 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.storage.image; +package com.cloud.storage.resource; -public interface ImageOrchestrator { - void registerTemplate(long templateId); +import org.apache.cloudstack.storage.command.StorageSubSystemCommand; - void registerSnapshot(long snapshotId); +import com.cloud.agent.api.Answer; - void registerVolume(long volumeId); - - void registerIso(long isoId); +public interface StorageSubsystemCommandHandler { + public Answer handleStorageCommands(StorageSubSystemCommand command); } diff --git a/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java b/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java new file mode 100644 index 00000000000..23ccd318253 --- /dev/null +++ b/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.cloud.storage.resource; + +import org.apache.cloudstack.storage.command.AttachCommand; +import org.apache.cloudstack.storage.command.CopyCommand; +import org.apache.cloudstack.storage.command.CreateObjectAnswer; +import org.apache.cloudstack.storage.command.CreateObjectCommand; +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.command.DettachCommand; +import org.apache.cloudstack.storage.command.StorageSubSystemCommand; +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.DiskTO; +import com.cloud.agent.api.to.NfsTO; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.Volume; + +public class StorageSubsystemCommandHandlerBase implements StorageSubsystemCommandHandler { + private static final Logger s_logger = Logger.getLogger(StorageSubsystemCommandHandlerBase.class); + private StorageProcessor processor; + public StorageSubsystemCommandHandlerBase(StorageProcessor processor) { + this.processor = processor; + } + @Override + public Answer handleStorageCommands(StorageSubSystemCommand command) { + if (command instanceof CopyCommand) { + return this.execute((CopyCommand)command); + } else if (command instanceof CreateObjectCommand) { + return execute((CreateObjectCommand) command); + } else if (command instanceof DeleteCommand) { + return execute((DeleteCommand)command); + } else if (command instanceof AttachCommand) { + return execute((AttachCommand)command); + } else if (command instanceof DettachCommand) { + return execute((DettachCommand)command); + } + return new Answer((Command)command, false, "not implemented yet"); + } + + protected Answer execute(CopyCommand cmd) { + DataTO srcData = cmd.getSrcTO(); + DataTO destData = cmd.getDestTO(); + DataStoreTO srcDataStore = srcData.getDataStore(); + DataStoreTO destDataStore = destData.getDataStore(); + + if ((srcData.getObjectType() == DataObjectType.TEMPLATE) && (srcDataStore instanceof NfsTO) && (destData.getDataStore().getRole() == DataStoreRole.Primary)) { + //copy template to primary storage + return processor.copyTemplateToPrimaryStorage(cmd); + } else if (srcData.getObjectType() == DataObjectType.TEMPLATE && srcDataStore.getRole() == DataStoreRole.Primary && destDataStore.getRole() == DataStoreRole.Primary) { + //clone template to a volume + return processor.cloneVolumeFromBaseTemplate(cmd); + } else if (srcData.getObjectType() == DataObjectType.VOLUME && (srcData.getDataStore().getRole() == DataStoreRole.ImageCache || srcDataStore.getRole() == DataStoreRole.Image)) { + //copy volume from image cache to primary + return processor.copyVolumeFromImageCacheToPrimary(cmd); + } else if (srcData.getObjectType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Primary) { + if (destData.getObjectType() == DataObjectType.VOLUME) { + return processor.copyVolumeFromPrimaryToSecondary(cmd); + } else if (destData.getObjectType() == DataObjectType.TEMPLATE) { + return processor.createTemplateFromVolume(cmd); + } + } else if (srcData.getObjectType() == DataObjectType.SNAPSHOT && srcData.getDataStore().getRole() == DataStoreRole.Primary) { + return processor.backupSnasphot(cmd); + } else if (srcData.getObjectType() == DataObjectType.SNAPSHOT && destData.getObjectType() == DataObjectType.VOLUME) { + return processor.createVolumeFromSnapshot(cmd); + } + + return new Answer(cmd, false, "not implemented yet"); + } + + + protected Answer execute(CreateObjectCommand cmd) { + DataTO data = cmd.getData(); + try { + if (data.getObjectType() == DataObjectType.VOLUME) { + return processor.createVolume(cmd); + } else if (data.getObjectType() == DataObjectType.SNAPSHOT) { + return processor.createSnapshot(cmd); + } + return new CreateObjectAnswer("not supported type"); + } catch (Exception e) { + s_logger.debug("Failed to create object: " + data.getObjectType() + ": " + e.toString()); + return new CreateObjectAnswer(e.toString()); + } + } + + protected Answer execute(DeleteCommand cmd) { + DataTO data = cmd.getData(); + Answer answer = null; + if (data.getObjectType() == DataObjectType.VOLUME) { + answer = processor.deleteVolume(cmd); + } else if (data.getObjectType() == DataObjectType.SNAPSHOT) { + answer = processor.deleteSnapshot(cmd); + } else { + answer = new Answer(cmd, false, "unsupported type"); + } + + return answer; + } + + protected Answer execute(AttachCommand cmd) { + DiskTO disk = cmd.getDisk(); + if (disk.getType() == Volume.Type.ISO) { + return processor.attachIso(cmd); + } else { + return processor.attachVolume(cmd); + } + } + + protected Answer execute(DettachCommand cmd) { + DiskTO disk = cmd.getDisk(); + if (disk.getType() == Volume.Type.ISO) { + return processor.dettachIso(cmd); + } else { + return processor.dettachVolume(cmd); + } + } +} diff --git a/core/src/com/cloud/storage/template/HttpTemplateDownloader.java b/core/src/com/cloud/storage/template/HttpTemplateDownloader.java index c8aac27da8c..d87dd68bb81 100644 --- a/core/src/com/cloud/storage/template/HttpTemplateDownloader.java +++ b/core/src/com/cloud/storage/template/HttpTemplateDownloader.java @@ -29,6 +29,7 @@ import java.net.URISyntaxException; import java.net.UnknownHostException; import java.util.Date; +import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType; import org.apache.commons.httpclient.ChunkedInputStream; import org.apache.commons.httpclient.Credentials; import org.apache.commons.httpclient.Header; @@ -45,11 +46,11 @@ import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.params.HttpMethodParams; import org.apache.log4j.Logger; -import com.cloud.agent.api.storage.DownloadCommand.Proxy; -import com.cloud.agent.api.storage.DownloadCommand.ResourceType; +import com.cloud.agent.api.storage.Proxy; import com.cloud.storage.StorageLayer; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.Pair; +import com.cloud.utils.UriUtils; /** * Download a template file using HTTP @@ -79,7 +80,7 @@ public class HttpTemplateDownloader implements TemplateDownloader { private ResourceType resourceType = ResourceType.TEMPLATE; private final HttpMethodRetryHandler myretryhandler; - + public HttpTemplateDownloader (StorageLayer storageLayer, String downloadUrl, String toDir, DownloadCompleteCallback callback, long maxTemplateSizeInBytes, String user, String password, Proxy proxy, ResourceType resourceType) { this._storage = storageLayer; @@ -88,7 +89,7 @@ public class HttpTemplateDownloader implements TemplateDownloader { this.status = TemplateDownloader.Status.NOT_STARTED; this.resourceType = resourceType; this.MAX_TEMPLATE_SIZE_IN_BYTES = maxTemplateSizeInBytes; - + this.totalBytes = 0; this.client = new HttpClient(s_httpClientManager); @@ -114,7 +115,7 @@ public class HttpTemplateDownloader implements TemplateDownloader { return false; } }; - + try { this.request = new GetMethod(downloadUrl); this.request.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, myretryhandler); @@ -122,14 +123,14 @@ public class HttpTemplateDownloader implements TemplateDownloader { //this.request.setFollowRedirects(false); File f = File.createTempFile("dnld", "tmp_", new File(toDir)); - + if (_storage != null) { _storage.setWorldReadableAndWriteable(f); } - + toFile = f.getAbsolutePath(); - Pair hostAndPort = validateUrl(downloadUrl); - + Pair hostAndPort = UriUtils.validateUrl(downloadUrl); + if (proxy != null) { client.getHostConfiguration().setProxy(proxy.getHost(), proxy.getPort()); if (proxy.getUserName() != null) { @@ -144,7 +145,7 @@ public class HttpTemplateDownloader implements TemplateDownloader { s_logger.info("Added username=" + user + ", password=" + password + "for host " + hostAndPort.first() + ":" + hostAndPort.second()); } else { s_logger.info("No credentials configured for host=" + hostAndPort.first() + ":" + hostAndPort.second()); - } + } } catch (IllegalArgumentException iae) { errorString = iae.getMessage(); status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; @@ -157,47 +158,8 @@ public class HttpTemplateDownloader implements TemplateDownloader { s_logger.warn("throwable caught ", th); } } - - private Pair validateUrl(String url) throws IllegalArgumentException { - try { - URI uri = new URI(url); - if (!uri.getScheme().equalsIgnoreCase("http") && !uri.getScheme().equalsIgnoreCase("https") ) { - throw new IllegalArgumentException("Unsupported scheme for url"); - } - int port = uri.getPort(); - if (!(port == 80 || port == 443 || port == -1)) { - throw new IllegalArgumentException("Only ports 80 and 443 are allowed"); - } - - if (port == -1 && uri.getScheme().equalsIgnoreCase("https")) { - port = 443; - } else if (port == -1 && uri.getScheme().equalsIgnoreCase("http")) { - port = 80; - } - - String host = uri.getHost(); - try { - InetAddress hostAddr = InetAddress.getByName(host); - if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress()) { - throw new IllegalArgumentException("Illegal host specified in url"); - } - if (hostAddr instanceof Inet6Address) { - throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")"); - } - return new Pair(host, port); - } catch (UnknownHostException uhe) { - throw new IllegalArgumentException("Unable to resolve " + host); - } - } catch (IllegalArgumentException iae) { - s_logger.warn("Failed uri validation check: " + iae.getMessage()); - throw iae; - } catch (URISyntaxException use) { - s_logger.warn("Failed uri syntax check: " + use.getMessage()); - throw new IllegalArgumentException(use.getMessage()); - } - } - + @Override public long download(boolean resume, DownloadCompleteCallback callback) { switch (status) { @@ -211,17 +173,17 @@ public class HttpTemplateDownloader implements TemplateDownloader { int bytes=0; File file = new File(toFile); try { - + long localFileSize = 0; if (file.exists() && resume) { localFileSize = file.length(); s_logger.info("Resuming download to file (current size)=" + localFileSize); } - + Date start = new Date(); int responseCode=0; - + if (localFileSize > 0 ) { // require partial content support for resume request.addRequestHeader("Range", "bytes=" + localFileSize + "-"); @@ -235,7 +197,7 @@ public class HttpTemplateDownloader implements TemplateDownloader { errorString = " HTTP Server returned " + responseCode + " (expected 200 OK) "; return 0; //FIXME: retry? } - + Header contentLengthHeader = request.getResponseHeader("Content-Length"); boolean chunked = false; long remoteSize2 = 0; @@ -262,26 +224,26 @@ public class HttpTemplateDownloader implements TemplateDownloader { if (remoteSize == 0) { remoteSize = remoteSize2; } - + if (remoteSize > MAX_TEMPLATE_SIZE_IN_BYTES) { s_logger.info("Remote size is too large: " + remoteSize + " , max=" + MAX_TEMPLATE_SIZE_IN_BYTES); status = Status.UNRECOVERABLE_ERROR; errorString = "Download file size is too large"; return 0; } - + if (remoteSize == 0) { remoteSize = MAX_TEMPLATE_SIZE_IN_BYTES; } - + InputStream in = !chunked?new BufferedInputStream(request.getResponseBodyAsStream()) : new ChunkedInputStream(request.getResponseBodyAsStream()); - + RandomAccessFile out = new RandomAccessFile(file, "rwd"); out.seek(localFileSize); s_logger.info("Starting download from " + getDownloadUrl() + " to " + toFile + " remoteSize=" + remoteSize + " , max size=" + MAX_TEMPLATE_SIZE_IN_BYTES); - + byte[] block = new byte[CHUNK_SIZE]; long offset=0; boolean done=false; @@ -305,7 +267,7 @@ public class HttpTemplateDownloader implements TemplateDownloader { errorString = "Downloaded " + totalBytes + " bytes " + downloaded; downloadTime += finish.getTime() - start.getTime(); out.close(); - + return totalBytes; }catch (HttpException hte) { status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; @@ -343,8 +305,8 @@ public class HttpTemplateDownloader implements TemplateDownloader { public long getDownloadTime() { return downloadTime; } - - + + public long getDownloadedBytes() { return totalBytes; } @@ -382,7 +344,7 @@ public class HttpTemplateDownloader implements TemplateDownloader { if (remoteSize == 0) { return 0; } - + return (int)(100.0*totalBytes/remoteSize); } @@ -395,7 +357,7 @@ public class HttpTemplateDownloader implements TemplateDownloader { errorString = "Failed to install: " + t.getMessage(); status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; } - + } @Override @@ -431,10 +393,10 @@ public class HttpTemplateDownloader implements TemplateDownloader { return toDir; } - public long getMaxTemplateSizeInBytes() { + public long getMaxTemplateSizeInBytes() { return this.MAX_TEMPLATE_SIZE_IN_BYTES; } - + public static void main(String[] args) { String url ="http:// dev.mysql.com/get/Downloads/MySQL-5.0/mysql-noinstall-5.0.77-win32.zip/from/http://mirror.services.wisc.edu/mysql/"; try { diff --git a/core/src/com/cloud/storage/template/S3TemplateDownloader.java b/core/src/com/cloud/storage/template/S3TemplateDownloader.java new file mode 100644 index 00000000000..340e0dba868 --- /dev/null +++ b/core/src/com/cloud/storage/template/S3TemplateDownloader.java @@ -0,0 +1,418 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.storage.template; + +import static com.cloud.utils.StringUtils.join; +import static java.util.Arrays.asList; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Date; + +import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType; +import org.apache.commons.httpclient.ChunkedInputStream; +import org.apache.commons.httpclient.Credentials; +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.HttpMethodRetryHandler; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; +import org.apache.commons.httpclient.NoHttpResponseException; +import org.apache.commons.httpclient.UsernamePasswordCredentials; +import org.apache.commons.httpclient.auth.AuthScope; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.params.HttpMethodParams; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + +import com.amazonaws.AmazonClientException; +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.ProgressEvent; +import com.amazonaws.services.s3.model.ProgressListener; +import com.amazonaws.services.s3.model.PutObjectRequest; +import com.amazonaws.services.s3.model.StorageClass; +import com.amazonaws.services.s3.transfer.TransferManager; +import com.amazonaws.services.s3.transfer.Upload; +import com.cloud.agent.api.storage.Proxy; +import com.cloud.agent.api.to.S3TO; +import com.cloud.utils.Pair; +import com.cloud.utils.S3Utils; +import com.cloud.utils.UriUtils; + +/** + * Download a template file using HTTP + * + */ +public class S3TemplateDownloader implements TemplateDownloader { + public static final Logger s_logger = Logger.getLogger(S3TemplateDownloader.class.getName()); + private static final MultiThreadedHttpConnectionManager s_httpClientManager = new MultiThreadedHttpConnectionManager(); + + private String downloadUrl; + private String installPath; + private String s3Key; + private String fileName; + public TemplateDownloader.Status status = TemplateDownloader.Status.NOT_STARTED; + public String errorString = " "; + private long remoteSize = 0; + public long downloadTime = 0; + public long totalBytes; + private final HttpClient client; + private GetMethod request; + private boolean resume = false; + private DownloadCompleteCallback completionCallback; + private S3TO s3; + private boolean inited = true; + + private long maxTemplateSizeInByte; + private ResourceType resourceType = ResourceType.TEMPLATE; + private final HttpMethodRetryHandler myretryhandler; + + public S3TemplateDownloader(S3TO storageLayer, String downloadUrl, String installPath, + DownloadCompleteCallback callback, long maxTemplateSizeInBytes, String user, String password, Proxy proxy, + ResourceType resourceType) { + this.s3 = storageLayer; + this.downloadUrl = downloadUrl; + this.installPath = installPath; + this.status = TemplateDownloader.Status.NOT_STARTED; + this.resourceType = resourceType; + this.maxTemplateSizeInByte = maxTemplateSizeInBytes; + + this.totalBytes = 0; + this.client = new HttpClient(s_httpClientManager); + + myretryhandler = new HttpMethodRetryHandler() { + @Override + public boolean retryMethod(final HttpMethod method, final IOException exception, int executionCount) { + if (executionCount >= 2) { + // Do not retry if over max retry count + return false; + } + if (exception instanceof NoHttpResponseException) { + // Retry if the server dropped connection on us + return true; + } + if (!method.isRequestSent()) { + // Retry if the request has not been sent fully or + // if it's OK to retry methods that have been sent + return true; + } + // otherwise do not retry + return false; + } + }; + + try { + this.request = new GetMethod(downloadUrl); + this.request.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, myretryhandler); + this.completionCallback = callback; + + Pair hostAndPort = UriUtils.validateUrl(downloadUrl); + this.fileName = StringUtils.substringAfterLast(downloadUrl, "/"); + + if (proxy != null) { + client.getHostConfiguration().setProxy(proxy.getHost(), proxy.getPort()); + if (proxy.getUserName() != null) { + Credentials proxyCreds = new UsernamePasswordCredentials(proxy.getUserName(), proxy.getPassword()); + client.getState().setProxyCredentials(AuthScope.ANY, proxyCreds); + } + } + if ((user != null) && (password != null)) { + client.getParams().setAuthenticationPreemptive(true); + Credentials defaultcreds = new UsernamePasswordCredentials(user, password); + client.getState().setCredentials( + new AuthScope(hostAndPort.first(), hostAndPort.second(), AuthScope.ANY_REALM), defaultcreds); + s_logger.info("Added username=" + user + ", password=" + password + "for host " + hostAndPort.first() + + ":" + hostAndPort.second()); + } else { + s_logger.info("No credentials configured for host=" + hostAndPort.first() + ":" + hostAndPort.second()); + } + } catch (IllegalArgumentException iae) { + errorString = iae.getMessage(); + status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; + inited = false; + } catch (Exception ex) { + errorString = "Unable to start download -- check url? "; + status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; + s_logger.warn("Exception in constructor -- " + ex.toString()); + } catch (Throwable th) { + s_logger.warn("throwable caught ", th); + } + } + + @Override + public long download(boolean resume, DownloadCompleteCallback callback) { + switch (status) { + case ABORTED: + case UNRECOVERABLE_ERROR: + case DOWNLOAD_FINISHED: + return 0; + default: + + } + + try { + // execute get method + int responseCode = HttpStatus.SC_OK; + if ((responseCode = client.executeMethod(request)) != HttpStatus.SC_OK) { + status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; + errorString = " HTTP Server returned " + responseCode + " (expected 200 OK) "; + return 0; // FIXME: retry? + } + // get the total size of file + Header contentLengthHeader = request.getResponseHeader("Content-Length"); + boolean chunked = false; + long remoteSize2 = 0; + if (contentLengthHeader == null) { + Header chunkedHeader = request.getResponseHeader("Transfer-Encoding"); + if (chunkedHeader == null || !"chunked".equalsIgnoreCase(chunkedHeader.getValue())) { + status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; + errorString = " Failed to receive length of download "; + return 0; // FIXME: what status do we put here? Do we retry? + } else if ("chunked".equalsIgnoreCase(chunkedHeader.getValue())) { + chunked = true; + } + } else { + remoteSize2 = Long.parseLong(contentLengthHeader.getValue()); + } + + if (remoteSize == 0) { + remoteSize = remoteSize2; + } + + if (remoteSize > maxTemplateSizeInByte) { + s_logger.info("Remote size is too large: " + remoteSize + " , max=" + maxTemplateSizeInByte); + status = Status.UNRECOVERABLE_ERROR; + errorString = "Download file size is too large"; + return 0; + } + + if (remoteSize == 0) { + remoteSize = maxTemplateSizeInByte; + } + + // get content type + String contentType = null; + Header contentTypeHeader = request.getResponseHeader("Content-Type"); + if ( contentTypeHeader != null ){ + contentType = contentTypeHeader.getValue(); + } + + InputStream in = !chunked ? new BufferedInputStream(request.getResponseBodyAsStream()) + : new ChunkedInputStream(request.getResponseBodyAsStream()); + + s_logger.info("Starting download from " + getDownloadUrl() + " to s3 bucket " + s3.getBucketName() + + " remoteSize=" + remoteSize + " , max size=" + maxTemplateSizeInByte); + + Date start = new Date(); + // compute s3 key + s3Key = join(asList(installPath, fileName), S3Utils.SEPARATOR); + + // multi-part upload using S3 api to handle > 5G input stream + TransferManager tm = new TransferManager(S3Utils.acquireClient(s3)); + + // download using S3 API + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentLength(remoteSize); + if ( contentType != null ){ + metadata.setContentType(contentType); + } + PutObjectRequest putObjectRequest = new PutObjectRequest(s3.getBucketName(), s3Key, in, metadata); + // check if RRS is enabled + if (s3.getEnableRRS()){ + putObjectRequest = putObjectRequest.withStorageClass(StorageClass.ReducedRedundancy); + } + // register progress listenser + putObjectRequest.setProgressListener(new ProgressListener() { + @Override + public void progressChanged(ProgressEvent progressEvent) { + // s_logger.debug(progressEvent.getBytesTransfered() + // + " number of byte transferd " + // + new Date()); + totalBytes += progressEvent.getBytesTransfered(); + if (progressEvent.getEventCode() == ProgressEvent.COMPLETED_EVENT_CODE) { + s_logger.info("download completed"); + status = TemplateDownloader.Status.DOWNLOAD_FINISHED; + } else if (progressEvent.getEventCode() == ProgressEvent.FAILED_EVENT_CODE) { + status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; + } else if (progressEvent.getEventCode() == ProgressEvent.CANCELED_EVENT_CODE) { + status = TemplateDownloader.Status.ABORTED; + } else { + status = TemplateDownloader.Status.IN_PROGRESS; + } + } + + }); + // TransferManager processes all transfers asynchronously, + // so this call will return immediately. + Upload upload = tm.upload(putObjectRequest); + + upload.waitForCompletion(); + + // finished or aborted + Date finish = new Date(); + String downloaded = "(incomplete download)"; + if (totalBytes >= remoteSize) { + status = TemplateDownloader.Status.DOWNLOAD_FINISHED; + downloaded = "(download complete remote=" + remoteSize + "bytes)"; + } else { + errorString = "Downloaded " + totalBytes + " bytes " + downloaded; + } + downloadTime += finish.getTime() - start.getTime(); + return totalBytes; + } catch (HttpException hte) { + status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; + errorString = hte.getMessage(); + } catch (IOException ioe) { + // probably a file write error + status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; + errorString = ioe.getMessage(); + } catch (AmazonClientException ex) { + // S3 api exception + status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; + errorString = ex.getMessage(); + } catch (InterruptedException e) { + // S3 upload api exception + status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; + errorString = e.getMessage(); + } finally { + // close input stream + request.releaseConnection(); + if (callback != null) { + callback.downloadComplete(status); + } + } + return 0; + } + + public String getDownloadUrl() { + return downloadUrl; + } + + @Override + public TemplateDownloader.Status getStatus() { + return status; + } + + @Override + public long getDownloadTime() { + return downloadTime; + } + + @Override + public long getDownloadedBytes() { + return totalBytes; + } + + @Override + @SuppressWarnings("fallthrough") + public boolean stopDownload() { + switch (getStatus()) { + case IN_PROGRESS: + if (request != null) { + request.abort(); + } + status = TemplateDownloader.Status.ABORTED; + return true; + case UNKNOWN: + case NOT_STARTED: + case RECOVERABLE_ERROR: + case UNRECOVERABLE_ERROR: + case ABORTED: + status = TemplateDownloader.Status.ABORTED; + case DOWNLOAD_FINISHED: + try { + S3Utils.deleteObject(s3, s3.getBucketName(), s3Key); + } catch (Exception ex) { + // ignore delete exception if it is not there + } + return true; + + default: + return true; + } + } + + @Override + public int getDownloadPercent() { + if (remoteSize == 0) { + return 0; + } + + return (int) (100.0 * totalBytes / remoteSize); + } + + @Override + public void run() { + try { + download(resume, completionCallback); + } catch (Throwable t) { + s_logger.warn("Caught exception during download " + t.getMessage(), t); + errorString = "Failed to install: " + t.getMessage(); + status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; + } + + } + + @Override + public void setStatus(TemplateDownloader.Status status) { + this.status = status; + } + + public boolean isResume() { + return resume; + } + + @Override + public String getDownloadError() { + return errorString; + } + + @Override + public String getDownloadLocalPath() { + return this.s3Key; + } + + @Override + public void setResume(boolean resume) { + this.resume = resume; + } + + @Override + public long getMaxTemplateSizeInBytes() { + return this.maxTemplateSizeInByte; + } + + @Override + public void setDownloadError(String error) { + errorString = error; + } + + @Override + public boolean isInited() { + return inited; + } + + public ResourceType getResourceType() { + return resourceType; + } + +} diff --git a/core/src/com/cloud/storage/template/TemplateConstants.java b/core/src/com/cloud/storage/template/TemplateConstants.java index 5c6de986c17..7b376648b7a 100644 --- a/core/src/com/cloud/storage/template/TemplateConstants.java +++ b/core/src/com/cloud/storage/template/TemplateConstants.java @@ -18,17 +18,18 @@ package com.cloud.storage.template; public final class TemplateConstants { public static final String DEFAULT_TMPLT_ROOT_DIR = "template"; + public static final String DEFAULT_SNAPSHOT_ROOT_DIR = "snapshots"; public static final String DEFAULT_VOLUME_ROOT_DIR = "volumes"; public static final String DEFAULT_TMPLT_FIRST_LEVEL_DIR = "tmpl/"; - + public static final String DEFAULT_SYSTEM_VM_TEMPLATE_PATH = "template/tmpl/1/"; - + public static final String DEFAULT_SYSTEM_VM_TMPLT_NAME = "routing"; - + public static final int DEFAULT_TMPLT_COPY_PORT = 80; public static final String DEFAULT_TMPLT_COPY_INTF = "eth2"; - + public static final String DEFAULT_SSL_CERT_DOMAIN = "realhostip.com"; public static final String DEFAULT_HTTP_AUTH_USER = "cloud"; - + } diff --git a/core/src/com/cloud/storage/template/TemplateLocation.java b/core/src/com/cloud/storage/template/TemplateLocation.java index 58d023a4907..161a663981d 100644 --- a/core/src/com/cloud/storage/template/TemplateLocation.java +++ b/core/src/com/cloud/storage/template/TemplateLocation.java @@ -24,9 +24,9 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.Properties; +import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType; import org.apache.log4j.Logger; -import com.cloud.agent.api.storage.DownloadCommand.ResourceType; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.StorageLayer; import com.cloud.storage.template.Processor.FormatInfo; @@ -35,17 +35,17 @@ import com.cloud.utils.NumbersUtil; public class TemplateLocation { private static final Logger s_logger = Logger.getLogger(TemplateLocation.class); public final static String Filename = "template.properties"; - + StorageLayer _storage; String _templatePath; boolean _isCorrupted; ResourceType _resourceType = ResourceType.TEMPLATE; - + File _file; Properties _props; - + ArrayList _formats; - + public TemplateLocation(StorageLayer storage, String templatePath) { _storage = storage; _templatePath = templatePath; @@ -63,16 +63,16 @@ public class TemplateLocation { } _isCorrupted = false; } - + public boolean create(long id, boolean isPublic, String uniqueName) throws IOException { boolean result = load(); _props.setProperty("id", Long.toString(id)); _props.setProperty("public", Boolean.toString(isPublic)); _props.setProperty("uniquename", uniqueName); - + return result; } - + public boolean purge() { boolean purged = true; String[] files = _storage.listFiles(_templatePath); @@ -85,10 +85,10 @@ public class TemplateLocation { s_logger.debug((r ? "R" : "Unable to r") + "emove " + file); } } - + return purged; } - + public boolean load() throws IOException { FileInputStream strm = null; try { @@ -102,7 +102,7 @@ public class TemplateLocation { } } } - + for (ImageFormat format : ImageFormat.values()) { String ext = _props.getProperty(format.getFileExtension()); if (ext != null) { @@ -115,22 +115,22 @@ public class TemplateLocation { info.size = NumbersUtil.parseLong(_props.getProperty(format.getFileExtension() + ".size"), -1); _props.setProperty("physicalSize", Long.toString(info.size)); info.virtualSize = NumbersUtil.parseLong(_props.getProperty(format.getFileExtension() + ".virtualsize"), -1); - _formats.add(info); - + _formats.add(info); + if (!checkFormatValidity(info)) { _isCorrupted = true; s_logger.warn("Cleaning up inconsistent information for " + format); - } + } } } - + if (_props.getProperty("uniquename") == null || _props.getProperty("virtualsize") == null) { return false; } - + return (_formats.size() > 0); } - + public boolean save() { for (FormatInfo info : _formats) { _props.setProperty(info.format.getFileExtension(), "true"); @@ -152,60 +152,64 @@ public class TemplateLocation { } catch (IOException e) { } } - } + } return true; } - - public TemplateInfo getTemplateInfo() { - TemplateInfo tmplInfo = new TemplateInfo(); + + public TemplateProp getTemplateInfo() { + TemplateProp tmplInfo = new TemplateProp(); tmplInfo.id = Long.parseLong(_props.getProperty("id")); - tmplInfo.installPath = _templatePath + File.separator + _props.getProperty("filename"); + tmplInfo.installPath = _templatePath + _props.getProperty("filename"); // _templatePath endsWith / if (_resourceType == ResourceType.VOLUME){ - tmplInfo.installPath = tmplInfo.installPath.substring(tmplInfo.installPath.indexOf("volumes")); + tmplInfo.installPath = tmplInfo.installPath.substring(tmplInfo.installPath.indexOf("volumes")); }else { tmplInfo.installPath = tmplInfo.installPath.substring(tmplInfo.installPath.indexOf("template")); } tmplInfo.isCorrupted = _isCorrupted; tmplInfo.isPublic = Boolean.parseBoolean(_props.getProperty("public")); tmplInfo.templateName = _props.getProperty("uniquename"); - tmplInfo.size = Long.parseLong(_props.getProperty("virtualsize")); - tmplInfo.physicalSize = Long.parseLong(_props.getProperty("physicalSize")); - + if (_props.getProperty("virtualsize") != null) { + tmplInfo.size = Long.parseLong(_props.getProperty("virtualsize")); + } + if (_props.getProperty("physicalSize") != null) { + tmplInfo.physicalSize = Long.parseLong(_props.getProperty("physicalSize")); + } + return tmplInfo; } - - + + public FormatInfo getFormat(ImageFormat format) { for (FormatInfo info : _formats) { if (info.format == format) { return info; } } - + return null; } - + public boolean addFormat(FormatInfo newInfo) { deleteFormat(newInfo.format); - + if (!checkFormatValidity(newInfo)) { s_logger.warn("Format is invalid "); return false; } - + _props.setProperty("virtualsize", Long.toString(newInfo.virtualSize)); _formats.add(newInfo); return true; } - + public void updateVirtualSize(long virtualSize) { _props.setProperty("virtualsize", Long.toString(virtualSize)); } - + protected boolean checkFormatValidity(FormatInfo info) { return (info.format != null && info.size > 0 && info.virtualSize > 0 && info.filename != null); } - + protected FormatInfo deleteFormat(ImageFormat format) { Iterator it = _formats.iterator(); while (it.hasNext()) { @@ -219,7 +223,7 @@ public class TemplateLocation { return info; } } - + return null; } } diff --git a/core/src/com/cloud/agent/api/storage/DownloadCommand.java b/core/src/org/apache/cloudstack/storage/command/DownloadCommand.java similarity index 53% rename from core/src/com/cloud/agent/api/storage/DownloadCommand.java rename to core/src/org/apache/cloudstack/storage/command/DownloadCommand.java index c6ffe45a9ef..7e3d65c7bde 100644 --- a/core/src/com/cloud/agent/api/storage/DownloadCommand.java +++ b/core/src/org/apache/cloudstack/storage/command/DownloadCommand.java @@ -14,89 +14,27 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.agent.api.storage; - -import java.net.URI; +package org.apache.cloudstack.storage.command; import org.apache.cloudstack.api.InternalIdentity; +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; +import com.cloud.agent.api.storage.AbstractDownloadCommand; +import com.cloud.agent.api.storage.PasswordAuth; +import com.cloud.agent.api.storage.Proxy; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.NfsTO; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Volume; -import com.cloud.template.VirtualMachineTemplate; public class DownloadCommand extends AbstractDownloadCommand implements InternalIdentity { - public static class PasswordAuth { - String userName; - String password; - public PasswordAuth() { - - } - public PasswordAuth(String user, String password) { - this.userName = user; - this.password = password; - } - public String getUserName() { - return userName; - } - public String getPassword() { - return password; - } - } public static enum ResourceType { VOLUME, TEMPLATE } - public static class Proxy { - private String _host; - private int _port; - private String _userName; - private String _password; - - public Proxy() { - - } - - public Proxy(String host, int port, String userName, String password) { - this._host = host; - this._port = port; - this._userName = userName; - this._password = password; - } - - public Proxy(URI uri) { - this._host = uri.getHost(); - this._port = uri.getPort() == -1 ? 3128 : uri.getPort(); - String userInfo = uri.getUserInfo(); - if (userInfo != null) { - String[] tokens = userInfo.split(":"); - if (tokens.length == 1) { - this._userName = userInfo; - this._password = ""; - } else if (tokens.length == 2) { - this._userName = tokens[0]; - this._password = tokens[1]; - } - } - } - - public String getHost() { - return _host; - } - - public int getPort() { - return _port; - } - - public String getUserName() { - return _userName; - } - - public String getPassword() { - return _password; - } - } private boolean hvm; private String description; private String checksum; @@ -105,6 +43,8 @@ public class DownloadCommand extends AbstractDownloadCommand implements Internal private Long maxDownloadSizeInBytes = null; private long id; private ResourceType resourceType = ResourceType.TEMPLATE; + private String installPath; + private DataStoreTO _store; protected DownloadCommand() { } @@ -120,40 +60,41 @@ public class DownloadCommand extends AbstractDownloadCommand implements Internal this.setSecUrl(that.getSecUrl()); this.maxDownloadSizeInBytes = that.getMaxDownloadSizeInBytes(); this.resourceType = that.resourceType; + this.installPath = that.installPath; + this._store = that._store; } - public DownloadCommand(String secUrl, VirtualMachineTemplate template, Long maxDownloadSizeInBytes) { - super(template.getUniqueName(), template.getUrl(), template.getFormat(), template.getAccountId()); + public DownloadCommand(TemplateObjectTO template, Long maxDownloadSizeInBytes) { + + super(template.getName(), template.getOrigUrl(), template.getFormat(), template.getAccountId()); + this._store = template.getDataStore(); + this.installPath = template.getPath(); this.hvm = template.isRequiresHvm(); this.checksum = template.getChecksum(); this.id = template.getId(); - this.description = template.getDisplayText(); - this.setSecUrl(secUrl); + this.description = template.getDescription(); + if (_store instanceof NfsTO) { + this.setSecUrl(((NfsTO) _store).getUrl()); + } this.maxDownloadSizeInBytes = maxDownloadSizeInBytes; } - public DownloadCommand(String secUrl, Volume volume, Long maxDownloadSizeInBytes, String checkSum, String url, ImageFormat format) { - super(volume.getName(), url, format, volume.getAccountId()); - //this.hvm = volume.isRequiresHvm(); - this.checksum = checkSum; - this.id = volume.getId(); - this.setSecUrl(secUrl); - this.maxDownloadSizeInBytes = maxDownloadSizeInBytes; - this.resourceType = ResourceType.VOLUME; - } - - public DownloadCommand(String secUrl, String url, VirtualMachineTemplate template, String user, String passwd, Long maxDownloadSizeInBytes) { - super(template.getUniqueName(), url, template.getFormat(), template.getAccountId()); - this.hvm = template.isRequiresHvm(); - this.checksum = template.getChecksum(); - this.id = template.getId(); - this.description = template.getDisplayText(); - this.setSecUrl(secUrl); - this.maxDownloadSizeInBytes = maxDownloadSizeInBytes; + public DownloadCommand(TemplateObjectTO template, String user, String passwd, Long maxDownloadSizeInBytes) { + this(template, maxDownloadSizeInBytes); auth = new PasswordAuth(user, passwd); } - public long getId() { + public DownloadCommand(VolumeObjectTO volume, Long maxDownloadSizeInBytes, String checkSum, String url, ImageFormat format) { + super(volume.getName(), url, format, volume.getAccountId()); + this.checksum = checkSum; + this.id = volume.getVolumeId(); + this.installPath = volume.getPath(); + this._store = volume.getDataStore(); + this.maxDownloadSizeInBytes = maxDownloadSizeInBytes; + this.resourceType = ResourceType.VOLUME; + } + @Override + public long getId() { return id; } @@ -216,4 +157,28 @@ public class DownloadCommand extends AbstractDownloadCommand implements Internal public void setResourceType(ResourceType resourceType) { this.resourceType = resourceType; } + + + public DataStoreTO getDataStore() { + return _store; + } + + + public void setDataStore(DataStoreTO _store) { + this._store = _store; + } + + + public String getInstallPath() { + return installPath; + } + + + public void setInstallPath(String installPath) { + this.installPath = installPath; + } + + + + } diff --git a/core/src/com/cloud/agent/api/storage/DownloadProgressCommand.java b/core/src/org/apache/cloudstack/storage/command/DownloadProgressCommand.java similarity index 96% rename from core/src/com/cloud/agent/api/storage/DownloadProgressCommand.java rename to core/src/org/apache/cloudstack/storage/command/DownloadProgressCommand.java index 835847bedeb..72ca90172b1 100644 --- a/core/src/com/cloud/agent/api/storage/DownloadProgressCommand.java +++ b/core/src/org/apache/cloudstack/storage/command/DownloadProgressCommand.java @@ -14,7 +14,8 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.agent.api.storage; +package org.apache.cloudstack.storage.command; + diff --git a/core/test/com/cloud/agent/transport/RequestTest.java b/core/test/com/cloud/agent/transport/RequestTest.java index 64c1e0bddef..510be91ae6e 100644 --- a/core/test/com/cloud/agent/transport/RequestTest.java +++ b/core/test/com/cloud/agent/transport/RequestTest.java @@ -20,6 +20,8 @@ import java.nio.ByteBuffer; import junit.framework.TestCase; +import org.apache.cloudstack.storage.command.DownloadCommand; +import org.apache.cloudstack.storage.to.TemplateObjectTO; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.junit.Assert; @@ -28,22 +30,25 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.SecStorageFirewallCfgCommand; +import com.cloud.agent.api.SecStorageSetupCommand; import com.cloud.agent.api.UpdateHostPasswordCommand; import com.cloud.agent.api.storage.DownloadAnswer; -import com.cloud.agent.api.storage.DownloadCommand; +import com.cloud.agent.api.storage.ListTemplateCommand; +import com.cloud.agent.api.to.NfsTO; import com.cloud.exception.UnsupportedVersionException; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.serializer.GsonHelper; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.VMTemplateVO; /** - * - * - * - * + * + * + * + * */ public class RequestTest extends TestCase { @@ -51,7 +56,7 @@ public class RequestTest extends TestCase { public void testSerDeser() { s_logger.info("Testing serializing and deserializing works as expected"); - + s_logger.info("UpdateHostPasswordCommand should have two parameters that doesn't show in logging"); UpdateHostPasswordCommand cmd1 = new UpdateHostPasswordCommand("abc", "def"); s_logger.info("SecStorageFirewallCfgCommand has a context map that shouldn't show up in debug level"); @@ -89,7 +94,7 @@ public class RequestTest extends TestCase { logger.setLevel(level); byte[] bytes = sreq.getBytes(); - + assert Request.getSequence(bytes) == 892403717; assert Request.getManagementServerId(bytes) == 3; assert Request.getAgentId(bytes) == 2; @@ -126,11 +131,46 @@ public class RequestTest extends TestCase { compareRequest(cresp, sresp); } + + public void testSerDeserTO() { + s_logger.info("Testing serializing and deserializing interface TO works as expected"); + + NfsTO nfs = new NfsTO("nfs://192.168.56.10/opt/storage/secondary", DataStoreRole.Image); + // SecStorageSetupCommand cmd = new SecStorageSetupCommand(nfs, "nfs://192.168.56.10/opt/storage/secondary", null); + ListTemplateCommand cmd = new ListTemplateCommand(nfs); + Request sreq = new Request(2, 3, cmd, true); + sreq.setSequence(892403718); + + + byte[] bytes = sreq.getBytes(); + + assert Request.getSequence(bytes) == 892403718; + assert Request.getManagementServerId(bytes) == 3; + assert Request.getAgentId(bytes) == 2; + assert Request.getViaAgentId(bytes) == 2; + Request creq = null; + try { + creq = Request.parse(bytes); + } catch (ClassNotFoundException e) { + s_logger.error("Unable to parse bytes: ", e); + } catch (UnsupportedVersionException e) { + s_logger.error("Unable to parse bytes: ", e); + } + + assert creq != null : "Couldn't get the request back"; + + compareRequest(creq, sreq); + assertEquals("nfs://192.168.56.10/opt/storage/secondary", ((NfsTO)((ListTemplateCommand)creq.getCommand()).getDataStore()).getUrl()); + } + public void testDownload() { s_logger.info("Testing Download answer"); VMTemplateVO template = new VMTemplateVO(1, "templatename", ImageFormat.QCOW2, true, true, true, TemplateType.USER, "url", true, 32, 1, "chksum", "displayText", true, 30, true, HypervisorType.KVM, null); - DownloadCommand cmd = new DownloadCommand("secUrl", template, 30000000l); + NfsTO nfs = new NfsTO("secUrl", DataStoreRole.Image); + TemplateObjectTO to = new TemplateObjectTO(template); + to.setImageDataStore(nfs); + DownloadCommand cmd = new DownloadCommand(to, 30000000l); Request req = new Request(1, 1, cmd, true); req.logD("Debug for Download"); @@ -161,7 +201,7 @@ public class RequestTest extends TestCase { } } } - + public void testLogging() { s_logger.info("Testing Logging"); GetHostStatsCommand cmd3 = new GetHostStatsCommand("hostguid", "hostname", 101); diff --git a/core/test/org/apache/cloudstack/api/agent/test/BackupSnapshotCommandTest.java b/core/test/org/apache/cloudstack/api/agent/test/BackupSnapshotCommandTest.java index 44d53aaa175..989059322a9 100644 --- a/core/test/org/apache/cloudstack/api/agent/test/BackupSnapshotCommandTest.java +++ b/core/test/org/apache/cloudstack/api/agent/test/BackupSnapshotCommandTest.java @@ -83,7 +83,7 @@ public class BackupSnapshotCommandTest { }; @Override - public long getAvailableBytes() { + public long getUsedBytes() { return 0L; }; @@ -159,11 +159,6 @@ public class BackupSnapshotCommandTest { "9012793e-0657-11e2-bebc-0050568b0057", "7167e0b2-f5b0-11e1-8414-0050568b0057", false, "vmName", 5); - @Test - public void testGetPrimaryStoragePoolNameLabel() { - String label = bsc.getPrimaryStoragePoolNameLabel(); - assertTrue(label.equals("bed9f83e-cac3-11e1-ac8a-0050568b007e")); - } @Test public void testGetSecondaryStorageUrl() { @@ -199,37 +194,6 @@ public class BackupSnapshotCommandTest { assertEquals(expected, ssId); } - @Test - public void testGetPool() { - StorageFilerTO pool = bsc.getPool(); - - Long id = pool.getId(); - Long expectedL = 1L; - assertEquals(expectedL, id); - - String uuid = pool.getUuid(); - assertTrue(uuid.equals("bed9f83e-cac3-11e1-ac8a-0050568b007e")); - - String host = pool.getHost(); - assertTrue(host.equals("hostAddress")); - - String path = pool.getPath(); - assertTrue(path.equals("path")); - - String userInfo = pool.getUserInfo(); - assertTrue(userInfo.equals("userInfo")); - - Integer port = pool.getPort(); - Integer expectedI = 25; - assertEquals(expectedI, port); - - StoragePoolType type = pool.getType(); - assertEquals(StoragePoolType.Filesystem, type); - - String str = pool.toString(); - assertTrue(str.equals("Pool[" + id.toString() + "|" + host + ":" - + port.toString() + "|" + path + "]")); - } @Test public void testGetCreated() { diff --git a/core/test/org/apache/cloudstack/api/agent/test/CheckNetworkAnswerTest.java b/core/test/org/apache/cloudstack/api/agent/test/CheckNetworkAnswerTest.java index 1853d3967c9..4db65570f1b 100644 --- a/core/test/org/apache/cloudstack/api/agent/test/CheckNetworkAnswerTest.java +++ b/core/test/org/apache/cloudstack/api/agent/test/CheckNetworkAnswerTest.java @@ -16,9 +16,15 @@ // under the License. package org.apache.cloudstack.api.agent.test; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import com.cloud.agent.api.storage.ResizeVolumeCommand; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.storage.Storage; +import com.cloud.storage.StoragePool; +import com.cloud.storage.StoragePoolStatus; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; @@ -26,6 +32,10 @@ import org.mockito.Mockito; import com.cloud.agent.api.CheckNetworkAnswer; import com.cloud.agent.api.CheckNetworkCommand; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + public class CheckNetworkAnswerTest { CheckNetworkCommand cnc; CheckNetworkAnswer cna; @@ -59,4 +69,199 @@ public class CheckNetworkAnswerTest { boolean b = cna.executeInSequence(); assertFalse(b); } + + public static class ResizeVolumeCommandTest { + + public StoragePool dummypool = new StoragePool() { + @Override + public long getId() { + return 1L; + }; + + @Override + public String getName() { + return "name"; + }; + + @Override + public String getUuid() { + return "bed9f83e-cac3-11e1-ac8a-0050568b007e"; + }; + + @Override + public Storage.StoragePoolType getPoolType() { + return Storage.StoragePoolType.Filesystem; + }; + + @Override + public Date getCreated() { + Date date = null; + try { + date = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss") + .parse("01/01/1970 12:12:12"); + } catch (ParseException e) { + e.printStackTrace(); + } + return date; + } + + @Override + public Date getUpdateTime() { + return new Date(); + }; + + @Override + public long getDataCenterId() { + return 0L; + }; + + @Override + public long getCapacityBytes() { + return 0L; + }; + + @Override + public long getUsedBytes() { + return 0L; + }; + + @Override + public Long getClusterId() { + return 0L; + }; + + @Override + public String getHostAddress() { + return "hostAddress"; + }; + + @Override + public String getPath() { + return "path"; + }; + + @Override + public String getUserInfo() { + return "userInfo"; + }; + + @Override + public boolean isShared() { + return false; + }; + + @Override + public boolean isLocal() { + return false; + }; + + @Override + public StoragePoolStatus getStatus() { + return StoragePoolStatus.Up; + }; + + @Override + public int getPort() { + return 25; + }; + + @Override + public Long getPodId() { + return 0L; + } + + @Override + public String getStorageProviderName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isInMaintenance() { + // TODO Auto-generated method stub + return false; + }; + }; + + Long newSize = 4194304L; + Long currentSize = 1048576L; + + ResizeVolumeCommand rv = new ResizeVolumeCommand("dummydiskpath", + new StorageFilerTO(dummypool), currentSize, newSize, false, + "vmName"); + + @Test + public void testExecuteInSequence() { + boolean b = rv.executeInSequence(); + assertFalse(b); + } + + @Test + public void testGetPath() { + String path = rv.getPath(); + assertTrue(path.equals("dummydiskpath")); + } + + @Test + public void testGetPoolUuid() { + String poolUuid = rv.getPoolUuid(); + assertTrue(poolUuid.equals("bed9f83e-cac3-11e1-ac8a-0050568b007e")); + } + + @Test + public void testGetPool() { + StorageFilerTO pool = rv.getPool(); + + Long id = pool.getId(); + Long expectedL = 1L; + assertEquals(expectedL, id); + + String uuid = pool.getUuid(); + assertTrue(uuid.equals("bed9f83e-cac3-11e1-ac8a-0050568b007e")); + + String host = pool.getHost(); + assertTrue(host.equals("hostAddress")); + + String path = pool.getPath(); + assertTrue(path.equals("path")); + + String userInfo = pool.getUserInfo(); + assertTrue(userInfo.equals("userInfo")); + + Integer port = pool.getPort(); + Integer expectedI = 25; + assertEquals(expectedI, port); + + Storage.StoragePoolType type = pool.getType(); + assertEquals(Storage.StoragePoolType.Filesystem, type); + + String str = pool.toString(); + assertTrue(str.equals("Pool[" + id.toString() + "|" + host + ":" + + port.toString() + "|" + path + "]")); + } + + @Test + public void testGetNewSize() { + long newSize = rv.getNewSize(); + assertTrue(newSize == 4194304L); + } + + @Test + public void testGetCurrentSize() { + long currentSize = rv.getCurrentSize(); + assertTrue(currentSize == 1048576L); + } + + @Test + public void testGetShrinkOk() { + assertFalse(rv.getShrinkOk()); + } + + @Test + public void testGetInstanceName() { + String vmName = rv.getInstanceName(); + assertTrue(vmName.equals("vmName")); + } + + } } diff --git a/core/test/org/apache/cloudstack/api/agent/test/SnapshotCommandTest.java b/core/test/org/apache/cloudstack/api/agent/test/SnapshotCommandTest.java index c2d69c0b0fd..3076d453434 100644 --- a/core/test/org/apache/cloudstack/api/agent/test/SnapshotCommandTest.java +++ b/core/test/org/apache/cloudstack/api/agent/test/SnapshotCommandTest.java @@ -74,7 +74,7 @@ public class SnapshotCommandTest { return 0L; }; - public long getAvailableBytes() { + public long getUsedBytes() { return 0L; }; @@ -142,12 +142,6 @@ public class SnapshotCommandTest { 102L, 103L); } - @Test - public void testGetPrimaryStoragePoolNameLabel() { - String label = ssc.getPrimaryStoragePoolNameLabel(); - assertTrue(label.equals("bed9f83e-cac3-11e1-ac8a-0050568b007e")); - } - @Test public void testGetSecondaryStorageUrl() { String url = ssc.getSecondaryStorageUrl(); diff --git a/core/test/src/com/cloud/agent/api/test/ResizeVolumeCommandTest.java b/core/test/src/com/cloud/agent/api/test/ResizeVolumeCommandTest.java deleted file mode 100644 index 02085f577b6..00000000000 --- a/core/test/src/com/cloud/agent/api/test/ResizeVolumeCommandTest.java +++ /dev/null @@ -1,229 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// 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, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package src.com.cloud.agent.api.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.junit.Test; - -import com.cloud.agent.api.storage.ResizeVolumeCommand; -import com.cloud.agent.api.to.StorageFilerTO; -import com.cloud.storage.Storage.StoragePoolType; -import com.cloud.storage.StoragePool; -import com.cloud.storage.StoragePoolStatus; - - -public class ResizeVolumeCommandTest { - - public StoragePool dummypool = new StoragePool() { - @Override - public long getId() { - return 1L; - }; - - @Override - public String getName() { - return "name"; - }; - - @Override - public String getUuid() { - return "bed9f83e-cac3-11e1-ac8a-0050568b007e"; - }; - - @Override - public StoragePoolType getPoolType() { - return StoragePoolType.Filesystem; - }; - - @Override - public Date getCreated() { - Date date = null; - try { - date = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss") - .parse("01/01/1970 12:12:12"); - } catch (ParseException e) { - e.printStackTrace(); - } - return date; - } - - @Override - public Date getUpdateTime() { - return new Date(); - }; - - @Override - public long getDataCenterId() { - return 0L; - }; - - @Override - public long getCapacityBytes() { - return 0L; - }; - - @Override - public long getAvailableBytes() { - return 0L; - }; - - @Override - public Long getClusterId() { - return 0L; - }; - - @Override - public String getHostAddress() { - return "hostAddress"; - }; - - @Override - public String getPath() { - return "path"; - }; - - @Override - public String getUserInfo() { - return "userInfo"; - }; - - @Override - public boolean isShared() { - return false; - }; - - @Override - public boolean isLocal() { - return false; - }; - - @Override - public StoragePoolStatus getStatus() { - return StoragePoolStatus.Up; - }; - - @Override - public int getPort() { - return 25; - }; - - @Override - public Long getPodId() { - return 0L; - } - - @Override - public String getStorageProviderName() { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean isInMaintenance() { - // TODO Auto-generated method stub - return false; - }; - }; - - Long newSize = 4194304L; - Long currentSize = 1048576L; - - ResizeVolumeCommand rv = new ResizeVolumeCommand("dummydiskpath", - new StorageFilerTO(dummypool), currentSize, newSize, false, - "vmName"); - - @Test - public void testExecuteInSequence() { - boolean b = rv.executeInSequence(); - assertFalse(b); - } - - @Test - public void testGetPath() { - String path = rv.getPath(); - assertTrue(path.equals("dummydiskpath")); - } - - @Test - public void testGetPoolUuid() { - String poolUuid = rv.getPoolUuid(); - assertTrue(poolUuid.equals("bed9f83e-cac3-11e1-ac8a-0050568b007e")); - } - - @Test - public void testGetPool() { - StorageFilerTO pool = rv.getPool(); - - Long id = pool.getId(); - Long expectedL = 1L; - assertEquals(expectedL, id); - - String uuid = pool.getUuid(); - assertTrue(uuid.equals("bed9f83e-cac3-11e1-ac8a-0050568b007e")); - - String host = pool.getHost(); - assertTrue(host.equals("hostAddress")); - - String path = pool.getPath(); - assertTrue(path.equals("path")); - - String userInfo = pool.getUserInfo(); - assertTrue(userInfo.equals("userInfo")); - - Integer port = pool.getPort(); - Integer expectedI = 25; - assertEquals(expectedI, port); - - StoragePoolType type = pool.getType(); - assertEquals(StoragePoolType.Filesystem, type); - - String str = pool.toString(); - assertTrue(str.equals("Pool[" + id.toString() + "|" + host + ":" - + port.toString() + "|" + path + "]")); - } - - @Test - public void testGetNewSize() { - long newSize = rv.getNewSize(); - assertTrue(newSize == 4194304L); - } - - @Test - public void testGetCurrentSize() { - long currentSize = rv.getCurrentSize(); - assertTrue(currentSize == 1048576L); - } - - @Test - public void testGetShrinkOk() { - assertFalse(rv.getShrinkOk()); - } - - @Test - public void testGetInstanceName() { - String vmName = rv.getInstanceName(); - assertTrue(vmName.equals("vmName")); - } - -} diff --git a/developer/pom.xml b/developer/pom.xml index 9bfb79294fd..a680b8aa98e 100644 --- a/developer/pom.xml +++ b/developer/pom.xml @@ -156,6 +156,7 @@ ${basedir}/target/db/cloudbridge_offering_alter.sql ${basedir}/developer-prefill.sql + ${basedir}/developer-prefill.sql.override com.cloud.upgrade.DatabaseUpgradeChecker --database=cloud,usage,awsapi @@ -232,4 +233,4 @@ - \ No newline at end of file + diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ClusterScope.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ClusterScope.java index 0f0e9581523..b0ed7d7d52b 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ClusterScope.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ClusterScope.java @@ -18,19 +18,21 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; +import com.cloud.storage.ScopeType; public class ClusterScope extends AbstractScope { private ScopeType type = ScopeType.CLUSTER; private Long clusterId; private Long podId; private Long zoneId; - + public ClusterScope(Long clusterId, Long podId, Long zoneId) { + super(); this.clusterId = clusterId; this.podId = podId; this.zoneId = zoneId; } - + @Override public ScopeType getScopeType() { return this.type; @@ -40,11 +42,11 @@ public class ClusterScope extends AbstractScope { public Long getScopeId() { return this.clusterId; } - + public Long getPodId() { return this.podId; } - + public Long getZoneId() { return this.zoneId; } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CopyCommandResult.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CopyCommandResult.java index 571a77c3786..bb5ba14d25d 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CopyCommandResult.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CopyCommandResult.java @@ -18,22 +18,25 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; +import org.apache.cloudstack.storage.command.CommandResult; + import com.cloud.agent.api.Answer; public class CopyCommandResult extends CommandResult { private final String path; private final Answer answer; + public CopyCommandResult(String path, Answer answer) { super(); this.path = path; this.answer = answer; } - + public String getPath() { return this.path; } - + public Answer getAnswer() { - return this.answer; + return this.answer; } } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CreateCmdResult.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CreateCmdResult.java index b6d5b689951..d05653cafb1 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CreateCmdResult.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CreateCmdResult.java @@ -18,20 +18,30 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; +import org.apache.cloudstack.storage.command.CommandResult; + +import com.cloud.agent.api.Answer; + public class CreateCmdResult extends CommandResult { private String path; - private Long size; - public CreateCmdResult(String path, Long size) { + private Answer answer; + + public CreateCmdResult(String path, Answer answer) { super(); this.path = path; - this.size = size; + this.answer = answer; } - + public String getPath() { return this.path; } - - public Long getSize() { - return this.size; + + public Answer getAnswer() { + return answer; } + + public void setAnswer(Answer answer) { + this.answer = answer; + } + } diff --git a/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionService.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataMotionService.java similarity index 65% rename from engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionService.java rename to engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataMotionService.java index 5ecbcb37afb..5e10a0ba7e7 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionService.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataMotionService.java @@ -16,22 +16,19 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.storage.motion; +package org.apache.cloudstack.engine.subsystem.api.storage; import java.util.Map; -import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.host.Host; public interface DataMotionService { - public void copyAsync(DataObject srcData, DataObject destData, + void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback callback); + + void copyAsync(Map volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, AsyncCompletionCallback callback); - public void copyAsync(Map volumeMap, VirtualMachineTO vmTo, - Host srcHost, Host destHost, AsyncCompletionCallback callback); + } diff --git a/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionStrategy.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataMotionStrategy.java similarity index 59% rename from engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionStrategy.java rename to engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataMotionStrategy.java index e3859b4e131..6deb6c1afc0 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionStrategy.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataMotionStrategy.java @@ -16,25 +16,23 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.storage.motion; +package org.apache.cloudstack.engine.subsystem.api.storage; import java.util.Map; -import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.host.Host; public interface DataMotionStrategy { - public boolean canHandle(DataObject srcData, DataObject destData); - public boolean canHandle(Map volumeMap, Host srcHost, Host destHost); + boolean canHandle(DataObject srcData, DataObject destData); - public Void copyAsync(DataObject srcData, DataObject destData, - AsyncCompletionCallback callback); - public Void copyAsync(Map volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, + boolean canHandle(Map volumeMap, Host srcHost, Host destHost); + + Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback callback); + + Void copyAsync(Map volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, AsyncCompletionCallback callback); + } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java index 0827cf6b674..c57b01ce8b0 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java @@ -18,15 +18,34 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; -import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataTO; public interface DataObject { - public long getId(); - public String getUri(); - public DataStore getDataStore(); - public Long getSize(); - public DataObjectType getType(); - public DiskFormat getFormat(); - public String getUuid(); - public void processEvent(ObjectInDataStoreStateMachine.Event event); + long getId(); + + String getUri(); + + DataTO getTO(); + + DataStore getDataStore(); + + Long getSize(); + + DataObjectType getType(); + + String getUuid(); + + boolean delete(); + + void processEvent(ObjectInDataStoreStateMachine.Event event); + + void processEvent(ObjectInDataStoreStateMachine.Event event, Answer answer); + + void incRefCount(); + + void decRefCount(); + + Long getRefCount(); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectInStore.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectInStore.java index 32ea996e638..95bb9b98c44 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectInStore.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectInStore.java @@ -20,8 +20,14 @@ package org.apache.cloudstack.engine.subsystem.api.storage; import com.cloud.utils.fsm.StateObject; - public interface DataObjectInStore extends StateObject { - public String getInstallPath(); - public void setInstallPath(String path); + String getInstallPath(); + + void setInstallPath(String path); + + long getObjectId(); + + long getDataStoreId(); + + ObjectInDataStoreStateMachine.State getObjectInStoreState(); } 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..e9a8f50e105 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 @@ -16,13 +16,27 @@ // under the License. package org.apache.cloudstack.engine.subsystem.api.storage; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.storage.DataStoreRole; + public interface DataStore { DataStoreDriver getDriver(); + DataStoreRole getRole(); + long getId(); + String getUuid(); + String getUri(); + Scope getScope(); + + String getName(); + DataObject create(DataObject obj); + boolean delete(DataObject obj); + + DataStoreTO getTO(); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java index cf5759b2924..1cb6e158489 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java @@ -18,17 +18,23 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; -import java.util.Set; - +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.storage.command.CommandResult; public interface DataStoreDriver { - public String grantAccess(DataObject data, EndPoint ep); - public boolean revokeAccess(DataObject data, EndPoint ep); - public Set listObjects(DataStore store); - public void createAsync(DataObject data, AsyncCompletionCallback callback); - public void deleteAsync(DataObject data, AsyncCompletionCallback callback); - public void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback callback); - public boolean canCopy(DataObject srcData, DataObject destData); - public void resize(DataObject data, AsyncCompletionCallback callback); + void createAsync(DataObject data, AsyncCompletionCallback callback); + + void deleteAsync(DataObject data, AsyncCompletionCallback callback); + + void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback callback); + + boolean canCopy(DataObject srcData, DataObject destData); + + void resize(DataObject data, AsyncCompletionCallback callback); + + DataTO getTO(DataObject data); + + DataStoreTO getStoreTO(DataStore store); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreLifeCycle.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreLifeCycle.java index cb467093955..1e893db6bb5 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreLifeCycle.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreLifeCycle.java @@ -23,21 +23,18 @@ import java.util.Map; import com.cloud.agent.api.StoragePoolInfo; import com.cloud.hypervisor.Hypervisor.HypervisorType; - public interface DataStoreLifeCycle { - public DataStore initialize(Map dsInfos); + DataStore initialize(Map dsInfos); + + boolean attachCluster(DataStore store, ClusterScope scope); + + boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo); - public boolean attachCluster(DataStore store, ClusterScope scope); - public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo); boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisorType); - public boolean dettach(); + boolean maintain(DataStore store); - public boolean unmanaged(); + boolean cancelMaintain(DataStore store); - public boolean maintain(DataStore store); - - public boolean cancelMaintain(DataStore store); - - public boolean deleteDataStore(DataStore store); + boolean deleteDataStore(DataStore store); } 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 15e49e133fb..949b037c1bd 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 @@ -21,11 +21,20 @@ package org.apache.cloudstack.engine.subsystem.api.storage; import java.util.List; import java.util.Map; +import com.cloud.storage.DataStoreRole; public interface DataStoreManager { - public DataStore getDataStore(long storeId, DataStoreRole role); - public DataStore getPrimaryDataStore(long storeId); - public DataStore getDataStore(String uuid, DataStoreRole role); - public List getImageStores(Scope scope); - public DataStore registerDataStore(Map params, String providerUuid); + DataStore getDataStore(long storeId, DataStoreRole role); + + DataStore getPrimaryDataStore(long storeId); + + DataStore getDataStore(String uuid, DataStoreRole role); + + List getImageStoresByScope(ZoneScope scope); + + DataStore getImageStore(long zoneId); + + List getImageCacheStores(Scope scope); + + List listImageStores(); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreProvider.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreProvider.java index 115a52f92ac..855f0854103 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreProvider.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreProvider.java @@ -21,17 +21,28 @@ package org.apache.cloudstack.engine.subsystem.api.storage; import java.util.Map; import java.util.Set; - public interface DataStoreProvider { - public static enum DataStoreProviderType { - PRIMARY, - IMAGE + // constants for provider names + static final String NFS_IMAGE = "NFS"; + static final String S3_IMAGE = "S3"; + static final String SWIFT_IMAGE = "Swift"; + static final String SAMPLE_IMAGE = "Sample"; + + static final String DEFAULT_PRIMARY = "DefaultPrimary"; + + static enum DataStoreProviderType { + PRIMARY, IMAGE, ImageCache } - public DataStoreLifeCycle getDataStoreLifeCycle(); - public DataStoreDriver getDataStoreDriver(); - public HypervisorHostListener getHostListener(); - public String getName(); - public boolean configure(Map params); - public Set getTypes(); - + + DataStoreLifeCycle getDataStoreLifeCycle(); + + DataStoreDriver getDataStoreDriver(); + + HypervisorHostListener getHostListener(); + + String getName(); + + boolean configure(Map params); + + Set getTypes(); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreProviderManager.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreProviderManager.java index 906720a1f41..d25e10ed34a 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreProviderManager.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreProviderManager.java @@ -24,8 +24,11 @@ import com.cloud.storage.DataStoreProviderApiService; import com.cloud.utils.component.Manager; public interface DataStoreProviderManager extends Manager, DataStoreProviderApiService { - public DataStoreProvider getDataStoreProvider(String name); - public DataStoreProvider getDefaultPrimaryDataStoreProvider(); - public List getDataStoreProviders(); + DataStoreProvider getDataStoreProvider(String name); + DataStoreProvider getDefaultPrimaryDataStoreProvider(); + + DataStoreProvider getDefaultImageDataStoreProvider(); + + DataStoreProvider getDefaultCacheDataStoreProvider(); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPoint.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPoint.java index 2ff45b1bf56..254c91d3544 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPoint.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPoint.java @@ -22,7 +22,13 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; public interface EndPoint { - public long getId(); - public Answer sendMessage(Command cmd); - public void sendMessageAsync(Command cmd, AsyncCompletionCallback callback); + long getId(); + + String getHostAddr(); + + String getPublicAddr(); + + Answer sendMessage(Command cmd); + + void sendMessageAsync(Command cmd, AsyncCompletionCallback callback); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataMigrationSubSystem.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java old mode 100755 new mode 100644 similarity index 77% rename from engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataMigrationSubSystem.java rename to engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java index 65928bd5537..ca0cc2c970a --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataMigrationSubSystem.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java @@ -18,12 +18,14 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; -import java.net.URI; +import java.util.List; -import com.cloud.org.Grouping; +public interface EndPointSelector { + EndPoint select(DataObject srcData, DataObject destData); -public interface DataMigrationSubSystem { + EndPoint select(DataObject object); - Class getScopeCoverage(); - void migrate(URI source, URI dest, String reservationId); + EndPoint select(DataStore store); + + List selectAll(DataStore store); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/HostScope.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/HostScope.java index c5e90ac894c..1ff381872e6 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/HostScope.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/HostScope.java @@ -18,20 +18,30 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; +import com.cloud.storage.ScopeType; public class HostScope extends AbstractScope { - private ScopeType type = ScopeType.HOST; private Long hostId; - public HostScope(Long hostId) { + private Long zoneId; + + public HostScope(Long hostId, Long zoneId) { + super(); this.hostId = hostId; + this.zoneId = zoneId; } + @Override public ScopeType getScopeType() { - return this.type; + return ScopeType.HOST; } @Override public Long getScopeId() { return this.hostId; } + + public Long getZoneId() { + return zoneId; + } + } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/HypervisorHostListener.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/HypervisorHostListener.java index 3ac17598bb0..8db4101ffc0 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/HypervisorHostListener.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/HypervisorHostListener.java @@ -20,5 +20,6 @@ package org.apache.cloudstack.engine.subsystem.api.storage; public interface HypervisorHostListener { boolean hostConnect(long hostId, long poolId); + boolean hostDisconnected(long hostId, long poolId); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ImageService.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ImageService.java deleted file mode 100644 index 119f3b1d32f..00000000000 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ImageService.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.engine.subsystem.api.storage; - -import org.apache.cloudstack.framework.async.AsyncCallFuture; - -public interface ImageService { - AsyncCallFuture createTemplateAsync(TemplateInfo template, DataStore store); - AsyncCallFuture createTemplateFromSnapshotAsync(SnapshotInfo snapshot, TemplateInfo template, DataStore store); - AsyncCallFuture createTemplateFromVolumeAsync(VolumeInfo volume, TemplateInfo template, DataStore store); - AsyncCallFuture deleteTemplateAsync(TemplateInfo template); - -} diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeProfile.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ImageStoreProvider.java similarity index 82% rename from engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeProfile.java rename to engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ImageStoreProvider.java index ed4d42187be..0025ae1cde6 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeProfile.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ImageStoreProvider.java @@ -18,17 +18,11 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; -public class VolumeProfile { - private String _uri; - public String getURI() { - return _uri; - } - - public String getPath() { - return null; - } - - public long getSize() { - return 0; - } +import com.cloud.storage.ScopeType; + +public interface ImageStoreProvider extends DataStoreProvider { + + boolean isScopeSupported(ScopeType scope); + + boolean needDownloadSysTemplate(); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java index 94ae800ab8e..04522f628d5 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java @@ -22,16 +22,11 @@ import com.cloud.utils.fsm.StateObject; public interface ObjectInDataStoreStateMachine extends StateObject { enum State { - Allocated("The initial state"), - Creating2("This is only used with createOnlyRequested event"), - Creating("The object is being creating on data store"), - Created("The object is created"), - Ready("Template downloading is accomplished"), - Copying("The object is being coping"), - Migrating("The object is being migrated"), - Destroying("Template is destroying"), - Destroyed("Template is destroyed"), - Failed("Failed to download template"); + Allocated("The initial state"), Creating2("This is only used with createOnlyRequested event"), Creating( + "The object is being creating on data store"), Created("The object is created"), Ready( + "Template downloading is accomplished"), Copying("The object is being coping"), Migrating( + "The object is being migrated"), Destroying("Template is destroying"), Destroyed( + "Template is destroyed"), Failed("Failed to download template"); String _description; private State(String description) { @@ -42,17 +37,9 @@ public interface ObjectInDataStoreStateMachine extends StateObject callback); - public void revertSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback); + void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback); + + void revertSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreInfo.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreInfo.java index 3497f7a894f..95a5cc9778b 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreInfo.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreInfo.java @@ -18,7 +18,6 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; - import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat; import com.cloud.hypervisor.Hypervisor.HypervisorType; @@ -26,12 +25,15 @@ import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.StoragePool; public interface PrimaryDataStoreInfo extends StoragePool { - public boolean isHypervisorSupported(HypervisorType hypervisor); - public boolean isLocalStorageSupported(); - public boolean isVolumeDiskTypeSupported(DiskFormat diskType); + boolean isHypervisorSupported(HypervisorType hypervisor); - public String getUuid(); + boolean isLocalStorageSupported(); - public StoragePoolType getPoolType(); - public PrimaryDataStoreLifeCycle getLifeCycle(); + boolean isVolumeDiskTypeSupported(DiskFormat diskType); + + String getUuid(); + + StoragePoolType getPoolType(); + + PrimaryDataStoreLifeCycle getLifeCycle(); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreLifeCycle.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreLifeCycle.java index cf29d9fea09..28b06f5234c 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreLifeCycle.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreLifeCycle.java @@ -18,6 +18,5 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; - public interface PrimaryDataStoreLifeCycle extends DataStoreLifeCycle { } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreParameters.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreParameters.java index b2b787cc133..3b5362a2d06 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreParameters.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreParameters.java @@ -36,6 +36,7 @@ public class PrimaryDataStoreParameters { private String uuid; private String name; private String userInfo; + /** * @return the userInfo */ @@ -44,7 +45,8 @@ public class PrimaryDataStoreParameters { } /** - * @param userInfo the userInfo to set + * @param userInfo + * the userInfo to set */ public void setUserInfo(String userInfo) { this.userInfo = userInfo; @@ -58,7 +60,8 @@ public class PrimaryDataStoreParameters { } /** - * @param name the name to set + * @param name + * the name to set */ public void setName(String name) { this.name = name; @@ -72,7 +75,8 @@ public class PrimaryDataStoreParameters { } /** - * @param uuid the uuid to set + * @param uuid + * the uuid to set */ public void setUuid(String uuid) { this.uuid = uuid; @@ -86,7 +90,8 @@ public class PrimaryDataStoreParameters { } /** - * @param port the port to set + * @param port + * the port to set */ public void setPort(int port) { this.port = port; @@ -100,7 +105,8 @@ public class PrimaryDataStoreParameters { } /** - * @param path the path to set + * @param path + * the path to set */ public void setPath(String path) { this.path = path; @@ -114,7 +120,8 @@ public class PrimaryDataStoreParameters { } /** - * @param host the host to set + * @param host + * the host to set */ public void setHost(String host) { this.host = host; @@ -128,7 +135,8 @@ public class PrimaryDataStoreParameters { } /** - * @param type the type to set + * @param type + * the type to set */ public void setType(StoragePoolType type) { this.type = type; @@ -142,7 +150,8 @@ public class PrimaryDataStoreParameters { } /** - * @param tags the tags to set + * @param tags + * the tags to set */ public void setTags(String tags) { this.tags = tags; @@ -156,7 +165,8 @@ public class PrimaryDataStoreParameters { } /** - * @param details the details to set + * @param details + * the details to set */ public void setDetails(Map details) { this.details = details; @@ -170,7 +180,8 @@ public class PrimaryDataStoreParameters { } /** - * @param providerName the providerName to set + * @param providerName + * the providerName to set */ public void setProviderName(String providerName) { this.providerName = providerName; @@ -184,7 +195,8 @@ public class PrimaryDataStoreParameters { } /** - * @param clusterId the clusterId to set + * @param clusterId + * the clusterId to set */ public void setClusterId(Long clusterId) { this.clusterId = clusterId; @@ -198,7 +210,8 @@ public class PrimaryDataStoreParameters { } /** - * @param podId the podId to set + * @param podId + * the podId to set */ public void setPodId(Long podId) { this.podId = podId; @@ -212,7 +225,8 @@ public class PrimaryDataStoreParameters { } /** - * @param zoneId the zoneId to set + * @param zoneId + * the zoneId to set */ public void setZoneId(Long zoneId) { this.zoneId = zoneId; diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/Scope.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/Scope.java index 91d4734ef15..8e43fa07fd8 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/Scope.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/Scope.java @@ -18,8 +18,12 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; +import com.cloud.storage.ScopeType; + public interface Scope { - public ScopeType getScopeType(); - public boolean isSameScope(Scope scope); - public Long getScopeId(); + ScopeType getScopeType(); + + boolean isSameScope(Scope scope); + + Long getScopeId(); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotDataFactory.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotDataFactory.java index 1ff3ff25065..0b8d1f104e1 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotDataFactory.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotDataFactory.java @@ -18,9 +18,12 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; +import com.cloud.storage.DataStoreRole; public interface SnapshotDataFactory { - public SnapshotInfo getSnapshot(long snapshotId, DataStore store); - public SnapshotInfo getSnapshot(DataObject obj, DataStore store); - public SnapshotInfo getSnapshot(long snapshotId); + SnapshotInfo getSnapshot(long snapshotId, DataStore store); + + SnapshotInfo getSnapshot(DataObject obj, DataStore store); + + SnapshotInfo getSnapshot(long snapshotId, DataStoreRole role); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotInfo.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotInfo.java index b90404c5667..8d6b76010fe 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotInfo.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotInfo.java @@ -18,11 +18,18 @@ package org.apache.cloudstack.engine.subsystem.api.storage; import com.cloud.storage.Snapshot; - public interface SnapshotInfo extends DataObject, Snapshot { - public SnapshotInfo getParent(); - public SnapshotInfo getChild(); - public VolumeInfo getBaseVolume(); + SnapshotInfo getParent(); + + String getPath(); + + SnapshotInfo getChild(); + + VolumeInfo getBaseVolume(); + + void addPayload(Object data); + Long getDataCenterId(); - public Long getPrevSnapshotId(); + + ObjectInDataStoreStateMachine.State getStatus(); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotProfile.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotProfile.java index 50a12002cf2..a51a51dedf8 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotProfile.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotProfile.java @@ -19,8 +19,9 @@ package org.apache.cloudstack.engine.subsystem.api.storage; public class SnapshotProfile { - private String _uri; - public String getURI() { - return _uri; - } + private String _uri; + + public String getURI() { + return _uri; + } } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotResult.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotResult.java new file mode 100644 index 00000000000..80dbbf83590 --- /dev/null +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotResult.java @@ -0,0 +1,48 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.engine.subsystem.api.storage; + +import org.apache.cloudstack.storage.command.CommandResult; + +import com.cloud.agent.api.Answer; + +public class SnapshotResult extends CommandResult { + private SnapshotInfo snashot; + private Answer answer; + + public SnapshotResult(SnapshotInfo snapshot, Answer answer) { + super(); + this.setSnashot(snapshot); + this.setAnswer(answer); + } + + public SnapshotInfo getSnashot() { + return snashot; + } + + public void setSnashot(SnapshotInfo snashot) { + this.snashot = snashot; + } + + public Answer getAnswer() { + return answer; + } + + public void setAnswer(Answer answer) { + this.answer = answer; + } +} diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StorageSubSystem.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotService.java similarity index 76% rename from engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StorageSubSystem.java rename to engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotService.java index 8043487d46b..d594a0728cb 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StorageSubSystem.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotService.java @@ -14,16 +14,15 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + package org.apache.cloudstack.engine.subsystem.api.storage; -import java.net.URI; +public interface SnapshotService { + SnapshotResult takeSnapshot(SnapshotInfo snapshot); -import com.cloud.org.Grouping; + SnapshotInfo backupSnapshot(SnapshotInfo snapshot); -public interface StorageSubSystem { - String getType(); - Class getScope(); + boolean deleteSnapshot(SnapshotInfo snapshot); - URI grantAccess(String vol, String reservationId); - URI RemoveAccess(String vol, String reservationId); + boolean revertSnapshot(SnapshotInfo snapshot); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotStrategy.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotStrategy.java index e9492c4afc6..86ae532e2dc 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotStrategy.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotStrategy.java @@ -11,17 +11,19 @@ // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the +// KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. - package org.apache.cloudstack.engine.subsystem.api.storage; +import com.cloud.storage.Snapshot; public interface SnapshotStrategy { - public boolean canHandle(SnapshotInfo snapshot); - public SnapshotInfo takeSnapshot(VolumeInfo volume, Long snapshotId); - public SnapshotInfo backupSnapshot(SnapshotInfo snapshot); - public boolean deleteSnapshot(SnapshotInfo snapshot); - public boolean revertSnapshot(SnapshotInfo snapshot); + SnapshotInfo takeSnapshot(SnapshotInfo snapshot); + + SnapshotInfo backupSnapshot(SnapshotInfo snapshot); + + boolean deleteSnapshot(Long snapshotId); + + boolean canHandle(Snapshot snapshot); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StorageCacheManager.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StorageCacheManager.java new file mode 100644 index 00000000000..92724c91889 --- /dev/null +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StorageCacheManager.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.engine.subsystem.api.storage; + +public interface StorageCacheManager { + DataStore getCacheStorage(Scope scope); + + DataObject createCacheObject(DataObject data, Scope scope); + + /** + * only create cache object in db + * + * @param data + * @param scope + * @return + */ + DataObject getCacheObject(DataObject data, Scope scope); + + boolean deleteCacheObject(DataObject data); + + boolean releaseCacheObject(DataObject data); + + DataObject createCacheObject(DataObject data, DataStore store); +} diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StorageEvent.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StorageEvent.java index 3f64002ed9e..6147b6ab6cc 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StorageEvent.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StorageEvent.java @@ -19,7 +19,5 @@ package org.apache.cloudstack.engine.subsystem.api.storage; public enum StorageEvent { - DownloadTemplateToPrimary, - RegisterTemplate, - CreateVolumeFromTemplate; + DownloadTemplateToPrimary, RegisterTemplate, CreateVolumeFromTemplate; } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StorageOrchestrator.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StorageOrchestrator.java deleted file mode 100755 index fdb15c7331c..00000000000 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StorageOrchestrator.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.engine.subsystem.api.storage; - -import java.util.List; - -import org.apache.cloudstack.engine.cloud.entity.api.TemplateEntity; -import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity; -import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat; -import org.apache.cloudstack.engine.subsystem.api.storage.type.VolumeType; - -import com.cloud.deploy.DeploymentPlan; - -public interface StorageOrchestrator { - - /** - * Prepares all storage ready for a VM to start - * @param vm - * @param reservationId - */ - void prepare(long vmId, DeploymentPlan plan, String reservationId); - - /** - * Releases all storage that were used for a VM shutdown - * @param vm - * @param disks - * @param reservationId - */ - void release(long vmId, String reservationId); - - /** - * Destroy all disks - * @param disks - * @param reservationId - */ - void destroy(List disks, String reservationId); - - /** - * Cancel a reservation - * @param reservationId reservation to - */ - void cancel(String reservationId); - - /** - * If attaching a volume in allocated state to a running vm, need to create this volume - */ - void prepareAttachDiskToVM(long diskId, long vmId, String reservationId); - - boolean createVolume(VolumeEntity volume, long dataStoreId, DiskFormat diskType); - boolean createVolumeFromTemplate(VolumeEntity volume, long dataStoreId, DiskFormat dis, TemplateEntity template); - VolumeEntity allocateVolumeInDb(long size, VolumeType type,String volName, Long templateId); -} diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StoragePoolAllocator.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StoragePoolAllocator.java index ffced54c28c..eccf0f4f6e1 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StoragePoolAllocator.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StoragePoolAllocator.java @@ -29,17 +29,23 @@ import com.cloud.vm.VirtualMachineProfile; /** */ public interface StoragePoolAllocator extends Adapter { - /** - * Determines which storage pools are suitable for the guest virtual machine - * - * @param DiskProfile dskCh - * @param VirtualMachineProfile vmProfile - * @param DeploymentPlan plan - * @param ExcludeList avoid - * @param int returnUpTo (use -1 to return all possible pools) - * @return List List of storage pools that are suitable for the VM - **/ - List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo); - - public static int RETURN_UPTO_ALL = -1; + /** + * Determines which storage pools are suitable for the guest virtual machine + * + * @param DiskProfile + * dskCh + * @param VirtualMachineProfile + * vmProfile + * @param DeploymentPlan + * plan + * @param ExcludeList + * avoid + * @param int returnUpTo (use -1 to return all possible pools) + * @return List List of storage pools that are suitable for the + * VM + **/ + List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, + DeploymentPlan plan, ExcludeList avoid, int returnUpTo); + + static int RETURN_UPTO_ALL = -1; } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ImageDataFactory.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateDataFactory.java similarity index 80% rename from engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ImageDataFactory.java rename to engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateDataFactory.java index f0d69887c7d..0b78da058ed 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ImageDataFactory.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateDataFactory.java @@ -18,9 +18,14 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; +import com.cloud.storage.DataStoreRole; -public interface ImageDataFactory { +public interface TemplateDataFactory { TemplateInfo getTemplate(long templateId, DataStore store); + TemplateInfo getTemplate(DataObject obj, DataStore store); - TemplateInfo getTemplate(long templateId); + + TemplateInfo getTemplate(long templateId, DataStoreRole storeRole); + + TemplateInfo getTemplate(long templateId, DataStoreRole storeRole, Long zoneId); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateEvent.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateEvent.java index c677166b39a..be74c7a9d8a 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateEvent.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateEvent.java @@ -19,8 +19,5 @@ package org.apache.cloudstack.engine.subsystem.api.storage; public enum TemplateEvent { - CreateRequested, - OperationFailed, - OperationSucceeded, - DestroyRequested; + CreateRequested, OperationFailed, OperationSucceeded, DestroyRequested; } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateInfo.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateInfo.java index 8e03503911e..ceb5fc0f55b 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateInfo.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateInfo.java @@ -18,5 +18,10 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; -public interface TemplateInfo extends DataObject { +import com.cloud.template.VirtualMachineTemplate; + +public interface TemplateInfo extends DataObject, VirtualMachineTemplate { + String getUniqueName(); + + String getInstallPath(); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateProfile.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateProfile.java deleted file mode 100755 index e05e7db67fa..00000000000 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateProfile.java +++ /dev/null @@ -1,287 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// 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, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package org.apache.cloudstack.engine.subsystem.api.storage; - -import java.util.Map; - -import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.storage.Storage.ImageFormat; -import com.cloud.template.VirtualMachineTemplate; - -public class TemplateProfile { - Long userId; - String name; - String displayText; - Integer bits; - Boolean passwordEnabled; - Boolean sshKeyEnbaled; - Boolean requiresHvm; - String url; - Boolean isPublic; - Boolean featured; - Boolean isExtractable; - ImageFormat format; - Long guestOsId; - Long zoneId; - HypervisorType hypervisorType; - String accountName; - Long domainId; - Long accountId; - String chksum; - Boolean bootable; - Long templateId; - VirtualMachineTemplate template; - String templateTag; - Map details; - - public TemplateProfile(Long templateId, Long userId, String name, String displayText, Integer bits, Boolean passwordEnabled, Boolean requiresHvm, - String url, Boolean isPublic, Boolean featured, Boolean isExtractable, ImageFormat format, Long guestOsId, Long zoneId, - HypervisorType hypervisorType, String accountName, Long domainId, Long accountId, String chksum, Boolean bootable, Map details, Boolean sshKeyEnabled) { - this.templateId = templateId; - this.userId = userId; - this.name = name; - this.displayText = displayText; - this.bits = bits; - this.passwordEnabled = passwordEnabled; - this.requiresHvm = requiresHvm; - this.url = url; - this.isPublic = isPublic; - this.featured = featured; - this.isExtractable = isExtractable; - this.format = format; - this.guestOsId = guestOsId; - this.zoneId = zoneId; - this.hypervisorType = hypervisorType; - this.accountName = accountName; - this.domainId = domainId; - this.accountId = accountId; - this.chksum = chksum; - this.bootable = bootable; - this.details = details; - this.sshKeyEnbaled = sshKeyEnabled; - } - - public TemplateProfile(Long userId, VirtualMachineTemplate template, Long zoneId) { - this.userId = userId; - this.template = template; - this.zoneId = zoneId; - } - - public TemplateProfile(Long templateId, Long userId, String name, String displayText, Integer bits, Boolean passwordEnabled, Boolean requiresHvm, - String url, Boolean isPublic, Boolean featured, Boolean isExtractable, ImageFormat format, Long guestOsId, Long zoneId, - HypervisorType hypervisorType, String accountName, Long domainId, Long accountId, String chksum, Boolean bootable, String templateTag, Map details, Boolean sshKeyEnabled) { - this(templateId, userId, name, displayText, bits, passwordEnabled, requiresHvm, url, isPublic, featured, isExtractable, format, guestOsId, zoneId, - hypervisorType, accountName, domainId, accountId, chksum, bootable, details, sshKeyEnabled); - this.templateTag = templateTag; - } - - public Long getTemplateId() { - return templateId; - } - public void setTemplateId(Long id) { - this.templateId = id; - } - - public Long getUserId() { - return userId; - } - public void setUserId(Long userId) { - this.userId = userId; - } - - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - - public String getDisplayText() { - return displayText; - } - public void setDisplayText(String text) { - this.displayText = text; - } - - public Integer getBits() { - return bits; - } - public void setBits(Integer bits) { - this.bits = bits; - } - - public Boolean getPasswordEnabled() { - return passwordEnabled; - } - public void setPasswordEnabled(Boolean enabled) { - this.passwordEnabled = enabled; - } - - public Boolean getRequiresHVM() { - return requiresHvm; - } - public void setRequiresHVM(Boolean hvm) { - this.requiresHvm = hvm; - } - - public String getUrl() { - return url; - } - public void setUrl(String url) { - this.url = url; - } - - public Boolean getIsPublic() { - return isPublic; - } - public void setIsPublic(Boolean is) { - this.isPublic = is; - } - - public Boolean getFeatured() { - return featured; - } - public void setFeatured(Boolean featured) { - this.featured = featured; - } - - public Boolean getIsExtractable() { - return isExtractable; - } - public void setIsExtractable(Boolean is) { - this.isExtractable = is; - } - - public ImageFormat getFormat() { - return format; - } - public void setFormat(ImageFormat format) { - this.format = format; - } - - public Long getGuestOsId() { - return guestOsId; - } - public void setGuestOsId(Long id) { - this.guestOsId = id; - } - - public Long getZoneId() { - return zoneId; - } - public void setZoneId(Long id) { - this.zoneId = id; - } - - public HypervisorType getHypervisorType() { - return hypervisorType; - } - public void setHypervisorType(HypervisorType type) { - this.hypervisorType = type; - } - - public Long getDomainId() { - return domainId; - } - public void setDomainId(Long id) { - this.domainId = id; - } - - public Long getAccountId() { - return accountId; - } - public void setAccountId(Long id) { - this.accountId = id; - } - - public String getCheckSum() { - return chksum; - } - public void setCheckSum(String chksum) { - this.chksum = chksum; - } - - public Boolean getBootable() { - return this.bootable; - } - public void setBootable(Boolean bootable) { - this.bootable = bootable; - } - - public VirtualMachineTemplate getTemplate() { - return template; - } - public void setTemplate(VirtualMachineTemplate template) { - this.template = template; - } - - public String getTemplateTag() { - return templateTag; - } - - public void setTemplateTag(String templateTag) { - this.templateTag = templateTag; - } - - public Map getDetails() { - return this.details; - } - - public void setDetails(Map details) { - this.details = details; - } - - public void setSshKeyEnabled(Boolean enabled) { - this.sshKeyEnbaled = enabled; - } - - public Boolean getSshKeyEnabled() { - return this.sshKeyEnbaled; - } - - public String getImageStorageUri() { - return null; - } - - public void setLocalPath(String path) { - - } - - public String getLocalPath() { - return null; - } - - public String getJobId() { - return null; - } - - public void setTemplatePoolRefId(long id) { - - } - - public long getId() { - return 0; - } - - public long getTemplatePoolRefId() { - return 0; - } - - public long getSize() { - return 0; - } -} diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java new file mode 100644 index 00000000000..085fbbdb232 --- /dev/null +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.engine.subsystem.api.storage; + +import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.storage.command.CommandResult; + +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.StoragePool; + +public interface TemplateService { + + class TemplateApiResult extends CommandResult { + private final TemplateInfo template; + + public TemplateApiResult(TemplateInfo template) { + super(); + this.template = template; + } + + public TemplateInfo getTemplate() { + return this.template; + } + } + + void createTemplateAsync(TemplateInfo template, DataStore store, AsyncCompletionCallback callback); + + AsyncCallFuture createTemplateFromSnapshotAsync(SnapshotInfo snapshot, TemplateInfo template, + DataStore store); + + AsyncCallFuture createTemplateFromVolumeAsync(VolumeInfo volume, TemplateInfo template, + DataStore store); + + AsyncCallFuture deleteTemplateAsync(TemplateInfo template); + + AsyncCallFuture copyTemplate(TemplateInfo srcTemplate, DataStore destStore); + + AsyncCallFuture prepareTemplateOnPrimary(TemplateInfo srcTemplate, StoragePool pool); + + void handleSysTemplateDownload(HypervisorType hostHyper, Long dcId); + + void handleTemplateSync(DataStore store); + + void downloadBootstrapSysTemplate(DataStore store); + + void addSystemVMTemplatesToSecondary(DataStore store); +} diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateState.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateState.java index ef2488080f8..43ea82a2688 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateState.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateState.java @@ -19,9 +19,5 @@ package org.apache.cloudstack.engine.subsystem.api.storage; public enum TemplateState { - Allocated, - Creating, - Destroying, - Destroyed, - Ready; + Allocated, Creating, Destroying, Destroyed, Ready; } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeDataFactory.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeDataFactory.java index 1518fd2eb43..fc65a32c33e 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeDataFactory.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeDataFactory.java @@ -18,9 +18,10 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; - public interface VolumeDataFactory { VolumeInfo getVolume(long volumeId, DataStore store); + VolumeInfo getVolume(DataObject volume, DataStore store); + VolumeInfo getVolume(long volumeId); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java index 349325af45d..3b4aba970ba 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java @@ -18,13 +18,31 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; +import com.cloud.agent.api.Answer; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.Volume; public interface VolumeInfo extends DataObject, Volume { - public boolean isAttachedVM(); - public void addPayload(Object data); - public Object getpayload(); - public HypervisorType getHypervisorType(); - public Long getLastPoolId(); + boolean isAttachedVM(); + + void addPayload(Object data); + + Object getpayload(); + + HypervisorType getHypervisorType(); + + Long getLastPoolId(); + + String getAttachedVmName(); + + void processEventOnly(ObjectInDataStoreStateMachine.Event event); + + void processEventOnly(ObjectInDataStoreStateMachine.Event event, Answer answer); + + boolean stateTransit(Volume.Event event); + + Long getBytesReadRate(); + Long getBytesWriteRate(); + Long getIopsReadRate(); + Long getIopsWriteRate(); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java index 3a1fe6ac226..f96ea4032d1 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java @@ -19,20 +19,24 @@ package org.apache.cloudstack.engine.subsystem.api.storage; import java.util.Map; + import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity; import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.storage.command.CommandResult; + import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.exception.ConcurrentOperationException; import com.cloud.host.Host; public interface VolumeService { - - public class VolumeApiResult extends CommandResult { + class VolumeApiResult extends CommandResult { private final VolumeInfo volume; + public VolumeApiResult(VolumeInfo volume) { + super(); this.volume = volume; } - + public VolumeInfo getVolume() { return this.volume; } @@ -57,27 +61,35 @@ public interface VolumeService { AsyncCallFuture expungeVolumeAsync(VolumeInfo volume); /** - * + * */ boolean cloneVolume(long volumeId, long baseVolId); /** - * + * */ - AsyncCallFuture createVolumeFromSnapshot(VolumeInfo volume, DataStore store, SnapshotInfo snapshot); - + AsyncCallFuture createVolumeFromSnapshot(VolumeInfo volume, DataStore store, SnapshotInfo snapshot); VolumeEntity getVolumeEntity(long volumeId); - AsyncCallFuture createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId, TemplateInfo template); + AsyncCallFuture createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId, + TemplateInfo template); + AsyncCallFuture copyVolume(VolumeInfo srcVolume, DataStore destStore); + AsyncCallFuture migrateVolume(VolumeInfo srcVolume, DataStore destStore); - AsyncCallFuture migrateVolumes(Map volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost); + + AsyncCallFuture migrateVolumes(Map volumeMap, VirtualMachineTO vmTo, + Host srcHost, Host destHost); boolean destroyVolume(long volumeId) throws ConcurrentOperationException; AsyncCallFuture registerVolume(VolumeInfo volume, DataStore store); - + AsyncCallFuture resize(VolumeInfo volume); + void handleVolumeSync(DataStore store); + + SnapshotInfo takeSnapshot(VolumeInfo volume); + } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ZoneScope.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ZoneScope.java index 2d3d41f22b5..a0d75b5cc7c 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ZoneScope.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ZoneScope.java @@ -18,15 +18,17 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; +import com.cloud.storage.ScopeType; public class ZoneScope extends AbstractScope { private ScopeType type = ScopeType.ZONE; private Long zoneId; - + public ZoneScope(Long zoneId) { + super(); this.zoneId = zoneId; } - + @Override public ScopeType getScopeType() { return this.type; diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/disktype/DiskFormat.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/disktype/DiskFormat.java index e059fa90320..6be7a6bb49e 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/disktype/DiskFormat.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/disktype/DiskFormat.java @@ -19,10 +19,7 @@ package org.apache.cloudstack.engine.subsystem.api.storage.disktype; import com.cloud.utils.exception.CloudRuntimeException; public enum DiskFormat { - VMDK, - VHD, - ISO, - QCOW2; + VMDK, VHD, ISO, QCOW2; public static DiskFormat getFormat(String format) { if (VMDK.toString().equalsIgnoreCase(format)) { return VMDK; diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/BaseImage.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/BaseImage.java index 9991cedfa27..495d45c183c 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/BaseImage.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/BaseImage.java @@ -17,7 +17,7 @@ package org.apache.cloudstack.engine.subsystem.api.storage.type; public class BaseImage extends VolumeTypeBase { - public BaseImage() { - this.type = "BaseImage"; - } + public BaseImage() { + this.type = "BaseImage"; + } } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/DataDisk.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/DataDisk.java index 762233e940f..a533f55d31c 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/DataDisk.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/DataDisk.java @@ -20,7 +20,7 @@ import org.springframework.stereotype.Component; @Component public class DataDisk extends VolumeTypeBase { - public DataDisk() { - this.type = "DataDisk"; - } + public DataDisk() { + this.type = "DataDisk"; + } } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/Iso.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/Iso.java index 43611b461b1..85c62725597 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/Iso.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/Iso.java @@ -20,7 +20,7 @@ import org.springframework.stereotype.Component; @Component public class Iso extends VolumeTypeBase { - public Iso() { - this.type = "iso"; - } + public Iso() { + this.type = "iso"; + } } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/RootDisk.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/RootDisk.java index 723d59c66cf..e8f4ce5c128 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/RootDisk.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/RootDisk.java @@ -20,7 +20,7 @@ import org.springframework.stereotype.Component; @Component public class RootDisk extends VolumeTypeBase { - public RootDisk() { - this.type = "Root"; - } + public RootDisk() { + this.type = "Root"; + } } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/Unknown.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/Unknown.java index 6f8904a5af2..f264d21757f 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/Unknown.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/Unknown.java @@ -17,8 +17,8 @@ package org.apache.cloudstack.engine.subsystem.api.storage.type; public class Unknown extends VolumeTypeBase { - public Unknown() { - this.type = "Unknown"; - } + public Unknown() { + this.type = "Unknown"; + } } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/VolumeTypeBase.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/VolumeTypeBase.java index 6ffd9d7c9c8..cf466ea8144 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/VolumeTypeBase.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/VolumeTypeBase.java @@ -17,31 +17,31 @@ package org.apache.cloudstack.engine.subsystem.api.storage.type; public class VolumeTypeBase implements VolumeType { - protected String type = "Unknown"; - - @Override - public boolean equals(Object that) { - if (this == that) { - return true; - } - if (that instanceof String) { - if (this.toString().equalsIgnoreCase((String)that)) { - return true; - } - } else if (that instanceof VolumeTypeBase) { - VolumeTypeBase th = (VolumeTypeBase)that; - if (this.toString().equalsIgnoreCase(th.toString())) { - return true; - } - } else { - return false; - } - return false; - } - - @Override - public String toString() { - return type; - } - + protected String type = "Unknown"; + + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } + if (that instanceof String) { + if (this.toString().equalsIgnoreCase((String) that)) { + return true; + } + } else if (that instanceof VolumeTypeBase) { + VolumeTypeBase th = (VolumeTypeBase) that; + if (this.toString().equalsIgnoreCase(th.toString())) { + return true; + } + } else { + return false; + } + return false; + } + + @Override + public String toString() { + return type; + } + } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/VolumeTypeHelper.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/VolumeTypeHelper.java index f29dd08721f..6dc2cd48c3d 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/VolumeTypeHelper.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/type/VolumeTypeHelper.java @@ -24,21 +24,21 @@ import org.springframework.stereotype.Component; @Component public class VolumeTypeHelper { - static private List types; - private static VolumeType defaultType = new Unknown(); - - @Inject - public void setTypes(List types) { - VolumeTypeHelper.types = types; - } - - public static VolumeType getType(String type) { - for (VolumeType ty : types) { - if (ty.equals(type)) { - return ty; - } - } - return VolumeTypeHelper.defaultType; - } - + static private List types; + private static VolumeType defaultType = new Unknown(); + + @Inject + public void setTypes(List types) { + VolumeTypeHelper.types = types; + } + + public static VolumeType getType(String type) { + for (VolumeType ty : types) { + if (ty.equals(type)) { + return ty; + } + } + return VolumeTypeHelper.defaultType; + } + } diff --git a/engine/storage/src/org/apache/cloudstack/storage/HostEndpointRpcServer.java b/engine/api/src/org/apache/cloudstack/storage/command/AttachAnswer.java similarity index 62% rename from engine/storage/src/org/apache/cloudstack/storage/HostEndpointRpcServer.java rename to engine/api/src/org/apache/cloudstack/storage/command/AttachAnswer.java index a316223b24d..5a26d4a3f13 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/HostEndpointRpcServer.java +++ b/engine/api/src/org/apache/cloudstack/storage/command/AttachAnswer.java @@ -16,14 +16,32 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.storage; - -import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +package org.apache.cloudstack.storage.command; import com.cloud.agent.api.Answer; -import com.cloud.agent.api.Command; +import com.cloud.agent.api.to.DiskTO; -public interface HostEndpointRpcServer { - void sendCommandAsync(HypervisorHostEndPoint ep, final Command command, final AsyncCompletionCallback callback); - Answer sendCommand(HypervisorHostEndPoint ep, final Command command); +public class AttachAnswer extends Answer { + private DiskTO disk; + + public AttachAnswer() { + super(null); + } + + public AttachAnswer(DiskTO disk) { + super(null); + this.setDisk(disk); + } + + public AttachAnswer(String errMsg) { + super(null, false, errMsg); + } + + public DiskTO getDisk() { + return disk; + } + + public void setDisk(DiskTO disk) { + this.disk = disk; + } } diff --git a/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeFromBaseImageCommand.java b/engine/api/src/org/apache/cloudstack/storage/command/AttachCommand.java similarity index 61% rename from engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeFromBaseImageCommand.java rename to engine/api/src/org/apache/cloudstack/storage/command/AttachCommand.java index 1734bc409cc..6b4e9f7ed00 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeFromBaseImageCommand.java +++ b/engine/api/src/org/apache/cloudstack/storage/command/AttachCommand.java @@ -18,32 +18,38 @@ */ package org.apache.cloudstack.storage.command; -import org.apache.cloudstack.storage.to.ImageOnPrimaryDataStoreTO; -import org.apache.cloudstack.storage.to.VolumeTO; - import com.cloud.agent.api.Command; +import com.cloud.agent.api.to.DiskTO; -public class CreateVolumeFromBaseImageCommand extends Command implements StorageSubSystemCommand { - private final VolumeTO volume; - private final ImageOnPrimaryDataStoreTO image; +public final class AttachCommand extends Command implements StorageSubSystemCommand { + private DiskTO disk; + private String vmName; - public CreateVolumeFromBaseImageCommand(VolumeTO volume, String image) { - this.volume = volume; - this.image = null; - } - - public VolumeTO getVolume() { - return this.volume; - } - - public ImageOnPrimaryDataStoreTO getImage() { - return this.image; + public AttachCommand(DiskTO disk, String vmName) { + super(); + this.disk = disk; + this.vmName = vmName; } @Override public boolean executeInSequence() { - // TODO Auto-generated method stub return false; } + public DiskTO getDisk() { + return disk; + } + + public void setDisk(DiskTO disk) { + this.disk = disk; + } + + public String getVmName() { + return vmName; + } + + public void setVmName(String vmName) { + this.vmName = vmName; + } + } diff --git a/engine/storage/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreAnswer.java b/engine/api/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreAnswer.java similarity index 98% rename from engine/storage/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreAnswer.java rename to engine/api/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreAnswer.java index cd15030084d..6d5bbaf6a68 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreAnswer.java +++ b/engine/api/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreAnswer.java @@ -25,30 +25,31 @@ public class AttachPrimaryDataStoreAnswer extends Answer { private String uuid; private long capacity; private long avail; + public AttachPrimaryDataStoreAnswer(Command cmd) { super(cmd); } - + public void setUuid(String uuid) { this.uuid = uuid; } - + public String getUuid() { return this.uuid; } - + public void setCapacity(long capacity) { this.capacity = capacity; } - + public long getCapacity() { return this.capacity; } - + public void setAvailable(long avail) { this.avail = avail; } - + public long getAvailable() { return this.avail; } diff --git a/engine/storage/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreCmd.java b/engine/api/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreCmd.java similarity index 89% rename from engine/storage/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreCmd.java rename to engine/api/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreCmd.java index 8aaca94aee0..2083876b567 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreCmd.java +++ b/engine/api/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreCmd.java @@ -20,19 +20,20 @@ package org.apache.cloudstack.storage.command; import com.cloud.agent.api.Command; -public class AttachPrimaryDataStoreCmd extends Command implements StorageSubSystemCommand { +public final class AttachPrimaryDataStoreCmd extends Command implements StorageSubSystemCommand { private final String dataStore; + public AttachPrimaryDataStoreCmd(String uri) { + super(); this.dataStore = uri; } - + public String getDataStore() { return this.dataStore; } @Override public boolean executeInSequence() { - // TODO Auto-generated method stub return false; } } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CommandResult.java b/engine/api/src/org/apache/cloudstack/storage/command/CommandResult.java similarity index 94% rename from engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CommandResult.java rename to engine/api/src/org/apache/cloudstack/storage/command/CommandResult.java index cc45914dc41..0a33c519f01 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CommandResult.java +++ b/engine/api/src/org/apache/cloudstack/storage/command/CommandResult.java @@ -16,32 +16,33 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.engine.subsystem.api.storage; +package org.apache.cloudstack.storage.command; public class CommandResult { private boolean success; private String result; + public CommandResult() { this.success = true; this.result = ""; } - + public boolean isSuccess() { return this.success; } - + public boolean isFailed() { return !this.success; } - + public void setSuccess(boolean success) { this.success = success; } - + public String getResult() { return this.result; } - + public void setResult(String result) { this.result = result; if (result != null) { @@ -49,4 +50,3 @@ public class CommandResult { } } } - \ No newline at end of file diff --git a/engine/storage/src/org/apache/cloudstack/storage/command/CopyCmdAnswer.java b/engine/api/src/org/apache/cloudstack/storage/command/CopyCmdAnswer.java similarity index 75% rename from engine/storage/src/org/apache/cloudstack/storage/command/CopyCmdAnswer.java rename to engine/api/src/org/apache/cloudstack/storage/command/CopyCmdAnswer.java index 53e082e6950..95c0e8990f8 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/command/CopyCmdAnswer.java +++ b/engine/api/src/org/apache/cloudstack/storage/command/CopyCmdAnswer.java @@ -17,17 +17,21 @@ package org.apache.cloudstack.storage.command; import com.cloud.agent.api.Answer; -import com.cloud.agent.api.Command; +import com.cloud.agent.api.to.DataTO; public class CopyCmdAnswer extends Answer { - private final String path; - - public CopyCmdAnswer(Command cmd, String path) { - super(cmd); - this.path = path; + private DataTO newData; + + public CopyCmdAnswer(DataTO newData) { + super(null); + this.newData = newData; } - - public String getPath() { - return this.path; + + public DataTO getNewData() { + return this.newData; + } + + public CopyCmdAnswer(String errMsg) { + super(null, false, errMsg); } } diff --git a/engine/storage/src/org/apache/cloudstack/storage/command/CopyCmd.java b/engine/api/src/org/apache/cloudstack/storage/command/CopyCommand.java similarity index 60% rename from engine/storage/src/org/apache/cloudstack/storage/command/CopyCmd.java rename to engine/api/src/org/apache/cloudstack/storage/command/CopyCommand.java index 10478ef24c7..852d8013c93 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/command/CopyCmd.java +++ b/engine/api/src/org/apache/cloudstack/storage/command/CopyCommand.java @@ -17,29 +17,39 @@ package org.apache.cloudstack.storage.command; import com.cloud.agent.api.Command; +import com.cloud.agent.api.to.DataTO; -public class CopyCmd extends Command implements StorageSubSystemCommand { - private String srcUri; - private String destUri; +public final class CopyCommand extends Command implements StorageSubSystemCommand { + private DataTO srcTO; + private DataTO destTO; + private DataTO cacheTO; - public CopyCmd(String srcUri, String destUri) { + public CopyCommand(DataTO srcData, DataTO destData, int timeout) { super(); - this.srcUri = srcUri; - this.destUri = destUri; + this.srcTO = srcData; + this.destTO = destData; + this.setWait(timeout); } - - public String getDestUri() { - return this.destUri; + + public DataTO getDestTO() { + return this.destTO; } - - public String getSrcUri() { - return this.srcUri; + + public DataTO getSrcTO() { + return this.srcTO; } @Override public boolean executeInSequence() { - // TODO Auto-generated method stub - return false; + return true; + } + + public DataTO getCacheTO() { + return cacheTO; + } + + public void setCacheTO(DataTO cacheTO) { + this.cacheTO = cacheTO; } } diff --git a/engine/storage/src/org/apache/cloudstack/storage/command/CreateObjectAnswer.java b/engine/api/src/org/apache/cloudstack/storage/command/CreateObjectAnswer.java similarity index 65% rename from engine/storage/src/org/apache/cloudstack/storage/command/CreateObjectAnswer.java rename to engine/api/src/org/apache/cloudstack/storage/command/CreateObjectAnswer.java index 43540de2bd3..b0c47447f6f 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/command/CreateObjectAnswer.java +++ b/engine/api/src/org/apache/cloudstack/storage/command/CreateObjectAnswer.java @@ -19,30 +19,25 @@ package org.apache.cloudstack.storage.command; import com.cloud.agent.api.Answer; -import com.cloud.agent.api.Command; +import com.cloud.agent.api.to.DataTO; + +public final class CreateObjectAnswer extends Answer { + private DataTO data; -public class CreateObjectAnswer extends Answer { - private String path; - private Long size; protected CreateObjectAnswer() { super(); } - public CreateObjectAnswer(Command cmd, String path, Long size) { - super(cmd); - this.path = path; - this.size = size; - } - - public CreateObjectAnswer(Command cmd, boolean status, String result) { - super(cmd, status, result); + public CreateObjectAnswer(DataTO data) { + super(); + this.data = data; } - public String getPath() { - return this.path; + public DataTO getData() { + return this.data; } - - public Long getSize() { - return this.size; + + public CreateObjectAnswer(String errMsg) { + super(null, false, errMsg); } } diff --git a/engine/storage/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java b/engine/api/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java similarity index 77% rename from engine/storage/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java rename to engine/api/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java index 86d3bd42410..121a7ee449c 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java +++ b/engine/api/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java @@ -19,13 +19,14 @@ package org.apache.cloudstack.storage.command; import com.cloud.agent.api.Command; +import com.cloud.agent.api.to.DataTO; -public class CreateObjectCommand extends Command implements StorageSubSystemCommand { - protected String objectUri; +public final class CreateObjectCommand extends Command implements StorageSubSystemCommand { + private DataTO data; - public CreateObjectCommand(String objectUri) { + public CreateObjectCommand(DataTO obj) { super(); - this.objectUri = objectUri; + this.data = obj; } protected CreateObjectCommand() { @@ -34,12 +35,11 @@ public class CreateObjectCommand extends Command implements StorageSubSystemComm @Override public boolean executeInSequence() { - // TODO Auto-generated method stub return false; } - - public String getObjectUri() { - return this.objectUri; + + public DataTO getData() { + return this.data; } } diff --git a/engine/storage/src/org/apache/cloudstack/storage/command/CreatePrimaryDataStoreCmd.java b/engine/api/src/org/apache/cloudstack/storage/command/CreatePrimaryDataStoreCmd.java similarity index 88% rename from engine/storage/src/org/apache/cloudstack/storage/command/CreatePrimaryDataStoreCmd.java rename to engine/api/src/org/apache/cloudstack/storage/command/CreatePrimaryDataStoreCmd.java index 0e50950843e..b536028927f 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/command/CreatePrimaryDataStoreCmd.java +++ b/engine/api/src/org/apache/cloudstack/storage/command/CreatePrimaryDataStoreCmd.java @@ -18,19 +18,20 @@ package org.apache.cloudstack.storage.command; import com.cloud.agent.api.Command; -public class CreatePrimaryDataStoreCmd extends Command implements StorageSubSystemCommand { +public final class CreatePrimaryDataStoreCmd extends Command implements StorageSubSystemCommand { private final String dataStore; + public CreatePrimaryDataStoreCmd(String uri) { + super(); this.dataStore = uri; } - + public String getDataStore() { return this.dataStore; } - + @Override public boolean executeInSequence() { - // TODO Auto-generated method stub return false; } diff --git a/engine/storage/src/org/apache/cloudstack/storage/command/DeleteCommand.java b/engine/api/src/org/apache/cloudstack/storage/command/DeleteCommand.java similarity index 75% rename from engine/storage/src/org/apache/cloudstack/storage/command/DeleteCommand.java rename to engine/api/src/org/apache/cloudstack/storage/command/DeleteCommand.java index 5d948d19356..76696da30ae 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/command/DeleteCommand.java +++ b/engine/api/src/org/apache/cloudstack/storage/command/DeleteCommand.java @@ -18,27 +18,28 @@ */ package org.apache.cloudstack.storage.command; -import org.apache.cloudstack.storage.to.VolumeTO; - import com.cloud.agent.api.Command; +import com.cloud.agent.api.to.DataTO; -public class DeleteCommand extends Command implements StorageSubSystemCommand { - private String uri; - public DeleteCommand(String uri) { - this.uri = uri; +public final class DeleteCommand extends Command implements StorageSubSystemCommand { + private DataTO data; + + public DeleteCommand(DataTO data) { + super(); + this.data = data; } - + protected DeleteCommand() { - + super(); } + @Override public boolean executeInSequence() { - // TODO Auto-generated method stub return false; } - - public String getUri() { - return this.uri; + + public DataTO getData() { + return this.data; } } diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageDataManager.java b/engine/api/src/org/apache/cloudstack/storage/command/DettachAnswer.java similarity index 59% rename from engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageDataManager.java rename to engine/api/src/org/apache/cloudstack/storage/command/DettachAnswer.java index e1fd46b76df..62ce2465ab5 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageDataManager.java +++ b/engine/api/src/org/apache/cloudstack/storage/command/DettachAnswer.java @@ -16,15 +16,32 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.storage.image.manager; +package org.apache.cloudstack.storage.command; -import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent; -import org.apache.cloudstack.engine.subsystem.api.storage.TemplateState; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.to.DiskTO; -import com.cloud.storage.VMTemplateVO; -import com.cloud.utils.fsm.StateMachine2; +public final class DettachAnswer extends Answer { + private DiskTO disk; -public interface ImageDataManager { - StateMachine2 getStateMachine(); + public DettachAnswer() { + super(null); + } + public DettachAnswer(DiskTO disk) { + super(null); + this.setDisk(disk); + } + + public DettachAnswer(String errMsg) { + super(null, false, errMsg); + } + + public DiskTO getDisk() { + return disk; + } + + public void setDisk(DiskTO disk) { + this.disk = disk; + } } diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDaoStoreDaoImpl.java b/engine/api/src/org/apache/cloudstack/storage/command/DettachCommand.java similarity index 53% rename from engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDaoStoreDaoImpl.java rename to engine/api/src/org/apache/cloudstack/storage/command/DettachCommand.java index 3f3e9ca95fb..a0ab4b2e6f4 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDaoStoreDaoImpl.java +++ b/engine/api/src/org/apache/cloudstack/storage/command/DettachCommand.java @@ -16,23 +16,40 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.storage.image.db; +package org.apache.cloudstack.storage.command; -import org.springframework.stereotype.Component; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.to.DiskTO; -import com.cloud.utils.db.GenericDaoBase; -import com.cloud.utils.db.SearchCriteria2; -import com.cloud.utils.db.SearchCriteriaService; -import com.cloud.utils.db.SearchCriteria.Op; +public class DettachCommand extends Command implements StorageSubSystemCommand { + private DiskTO disk; + private String vmName; -@Component -public class ImageDaoStoreDaoImpl extends GenericDaoBase implements ImageDataStoreDao { + public DettachCommand(DiskTO disk, String vmName) { + super(); + this.disk = disk; + this.vmName = vmName; + } @Override - public ImageDataStoreVO findByName(String name) { - SearchCriteriaService sc = SearchCriteria2.create(ImageDataStoreVO.class); - sc.addAnd(sc.getEntity().getName(), Op.EQ, name); - return sc.find(); + public boolean executeInSequence() { + return false; + } + + public DiskTO getDisk() { + return disk; + } + + public void setDisk(DiskTO disk) { + this.disk = disk; + } + + public String getVmName() { + return vmName; + } + + public void setVmName(String vmName) { + this.vmName = vmName; } } diff --git a/engine/api/src/org/apache/cloudstack/storage/command/DownloadSystemTemplateCommand.java b/engine/api/src/org/apache/cloudstack/storage/command/DownloadSystemTemplateCommand.java new file mode 100644 index 00000000000..9528ff788d8 --- /dev/null +++ b/engine/api/src/org/apache/cloudstack/storage/command/DownloadSystemTemplateCommand.java @@ -0,0 +1,129 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.command; + +import com.cloud.agent.api.Command; +import com.cloud.agent.api.storage.PasswordAuth; +import com.cloud.agent.api.storage.Proxy; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.template.VirtualMachineTemplate; + +public class DownloadSystemTemplateCommand extends Command { + + private PasswordAuth auth; + private Proxy _proxy; + private DataStoreTO _store; + private Long resourceId; + private Long accountId; + private String url; + private Long maxDownloadSizeInBytes; + private String name; + + protected DownloadSystemTemplateCommand() { + super(); + } + + public DownloadSystemTemplateCommand(DataStoreTO store, String secUrl, VirtualMachineTemplate template, + Long maxDownloadSizeInBytes) { + super(); + this._store = store; + this.accountId = template.getAccountId(); + this.url = secUrl; + this.maxDownloadSizeInBytes = maxDownloadSizeInBytes; + this.resourceId = template.getId(); + this.name = template.getUniqueName(); + } + + public DownloadSystemTemplateCommand(DataStoreTO store, String secUrl, String url, VirtualMachineTemplate template, + String user, String passwd, Long maxDownloadSizeInBytes) { + super(); + this._store = store; + this.accountId = template.getAccountId(); + this.url = secUrl; + this.maxDownloadSizeInBytes = maxDownloadSizeInBytes; + this.resourceId = template.getId(); + auth = new PasswordAuth(user, passwd); + this.name = template.getUniqueName(); + } + + public PasswordAuth getAuth() { + return auth; + } + + public void setCreds(String userName, String passwd) { + auth = new PasswordAuth(userName, passwd); + } + + public Proxy getProxy() { + return _proxy; + } + + public void setProxy(Proxy proxy) { + _proxy = proxy; + } + + public Long getMaxDownloadSizeInBytes() { + return maxDownloadSizeInBytes; + } + + public DataStoreTO getDataStore() { + return _store; + } + + public void setDataStore(DataStoreTO _store) { + this._store = _store; + } + + public Long getResourceId() { + return resourceId; + } + + public void setResourceId(Long resourceId) { + this.resourceId = resourceId; + } + + public Long getAccountId() { + return accountId; + } + + public void setAccountId(Long accountId) { + this.accountId = accountId; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public boolean executeInSequence() { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/command/StorageSubSystemCommand.java b/engine/api/src/org/apache/cloudstack/storage/command/StorageSubSystemCommand.java similarity index 100% rename from engine/storage/src/org/apache/cloudstack/storage/command/StorageSubSystemCommand.java rename to engine/api/src/org/apache/cloudstack/storage/command/StorageSubSystemCommand.java diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/DataStoreProviderVO.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/DataStoreProviderVO.java deleted file mode 100644 index dcdafddb175..00000000000 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/DataStoreProviderVO.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.datastore.db; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Table; -import javax.persistence.TableGenerator; - -@Entity -@Table(name = "data_store_provider") -public class DataStoreProviderVO { - @Id - @TableGenerator(name = "data_store_provider_sq", table = "sequence", pkColumnName = "name", valueColumnName = "value", pkColumnValue = "data_store_provider_seq", allocationSize = 1) - @Column(name = "id", updatable = false, nullable = false) - private long id; - - @Column(name = "name", nullable = false) - private String name; - - @Column(name = "uuid", nullable = false) - private String uuid; - - public long getId() { - return id; - } - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - public void setUuid(String uuid) { - this.uuid = uuid; - } - - public String getUuid() { - return this.uuid; - } -} diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/DataStoreProviderDao.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDao.java similarity index 67% rename from engine/api/src/org/apache/cloudstack/storage/datastore/db/DataStoreProviderDao.java rename to engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDao.java index dca83ce0b8a..70e9bb386e0 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/DataStoreProviderDao.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDao.java @@ -18,8 +18,20 @@ */ package org.apache.cloudstack.storage.datastore.db; +import java.util.List; + +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; + import com.cloud.utils.db.GenericDao; -public interface DataStoreProviderDao extends GenericDao { - public DataStoreProviderVO findByName(String name); +public interface ImageStoreDao extends GenericDao { + ImageStoreVO findByName(String name); + + List findByProvider(String provider); + + List findByScope(ZoneScope scope); + + List findImageCacheByScope(ZoneScope scope); + + List listImageStores(); } diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailVO.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailVO.java new file mode 100644 index 00000000000..b9221489e05 --- /dev/null +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailVO.java @@ -0,0 +1,82 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.datastore.db; + +import org.apache.cloudstack.api.InternalIdentity; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "image_store_details") +public class ImageStoreDetailVO implements InternalIdentity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + long id; + + @Column(name = "store_id") + long storeId; + + @Column(name = "name") + String name; + + @Column(name = "value") + String value; + + public ImageStoreDetailVO() { + } + + public ImageStoreDetailVO(long storeId, String name, String value) { + this.storeId = storeId; + this.name = name; + this.value = value; + } + + public long getId() { + return id; + } + + public long getStoreId() { + return storeId; + } + + public void setStoreId(long storeId) { + this.storeId = storeId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/provider/PrimaryDataStoreProviderManager.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailsDao.java similarity index 69% rename from engine/storage/volume/src/org/apache/cloudstack/storage/datastore/provider/PrimaryDataStoreProviderManager.java rename to engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailsDao.java index b248758bc12..91fff280d91 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/provider/PrimaryDataStoreProviderManager.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDetailsDao.java @@ -14,3 +14,17 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. +package org.apache.cloudstack.storage.datastore.db; + +import java.util.Map; + +import com.cloud.utils.db.GenericDao; + +public interface ImageStoreDetailsDao extends GenericDao { + + void update(long storeId, Map details); + + Map getDetails(long storeId); + + void deleteDetails(long storeId); +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDataStoreVO.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreVO.java similarity index 53% rename from engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDataStoreVO.java rename to engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreVO.java index 4cb402a1271..5ed48a3781c 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDataStoreVO.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreVO.java @@ -16,7 +16,9 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.storage.image.db; +package org.apache.cloudstack.storage.datastore.db; + +import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; @@ -26,36 +28,69 @@ import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.TableGenerator; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ImageStore; +import com.cloud.storage.ScopeType; +import com.cloud.utils.db.GenericDao; @Entity -@Table(name = "image_data_store") -public class ImageDataStoreVO { +@Table(name = "image_store") +public class ImageStoreVO implements ImageStore { @Id - @TableGenerator(name = "image_data_store_sq", table = "sequence", pkColumnName = "name", valueColumnName = "value", pkColumnValue = "image_data_store_seq", allocationSize = 1) + @TableGenerator(name = "image_store_sq", table = "sequence", pkColumnName = "name", valueColumnName = "value", + pkColumnValue = "image_store_seq", allocationSize = 1) @Column(name = "id", nullable = false) private long id; @Column(name = "name", nullable = false) private String name; - + @Column(name = "uuid", nullable = false) private String uuid; - + @Column(name = "protocol", nullable = false) private String protocol; + @Column(name = "url", nullable = false) + private String url; + @Column(name = "image_provider_name", nullable = false) private String providerName; - + @Column(name = "data_center_id") - private long dcId; - + private Long dcId; + @Column(name = "scope") @Enumerated(value = EnumType.STRING) private ScopeType scope; - - + + @Column(name = GenericDao.CREATED_COLUMN) + private Date created; + + @Column(name = GenericDao.REMOVED_COLUMN) + private Date removed; + + @Column(name = "role") + @Enumerated(value = EnumType.STRING) + private DataStoreRole role; + + @Column(name = "parent") + private String parent; + + @Column(name = "total_size") + private Long totalSize; + + @Column(name = "used_bytes") + private Long usedBytes; + + public DataStoreRole getRole() { + return role; + } + + public void setRole(DataStoreRole role) { + this.role = role; + } + public long getId() { return this.id; } @@ -75,36 +110,84 @@ public class ImageDataStoreVO { public void setProviderName(String provider) { this.providerName = provider; } - + public void setProtocol(String protocol) { this.protocol = protocol; } - + public String getProtocol() { return this.protocol; } - - public void setDcId(long dcId) { + + public void setDataCenterId(Long dcId) { this.dcId = dcId; } - - public long getDcId() { + + public Long getDataCenterId() { return this.dcId; } - + public ScopeType getScope() { return this.scope; } - + public void setScope(ScopeType scope) { this.scope = scope; } - + public void setUuid(String uuid) { this.uuid = uuid; } - + public String getUuid() { return this.uuid; } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public Date getCreated() { + return created; + } + + public void setCreated(Date created) { + this.created = created; + } + + public Date getRemoved() { + return removed; + } + + public void setRemoved(Date removed) { + this.removed = removed; + } + + public String getParent() { + return parent; + } + + public void setParent(String parent) { + this.parent = parent; + } + + public Long getTotalSize() { + return totalSize; + } + + public void setTotalSize(Long totalSize) { + this.totalSize = totalSize; + } + + public Long getUsedBytes() { + return usedBytes; + } + + public void setUsedBytes(Long usedBytes) { + this.usedBytes = usedBytes; + } } diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java index d436762c25a..99b7b9c92b4 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java @@ -16,100 +16,110 @@ // under the License. package org.apache.cloudstack.storage.datastore.db; -import java.util.ArrayList; import java.util.List; import java.util.Map; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; - import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.ScopeType; import com.cloud.storage.StoragePoolStatus; import com.cloud.utils.db.GenericDao; + /** * Data Access Object for storage_pool table */ public interface PrimaryDataStoreDao extends GenericDao { - /** - * @param datacenterId -- the id of the datacenter (availability zone) - */ - List listByDataCenterId(long datacenterId); - - /** - * @param datacenterId -- the id of the datacenter (availability zone) - */ - List listBy(long datacenterId, long podId, Long clusterId, ScopeType scope); - - /** - * Set capacity of storage pool in bytes - * @param id pool id. - * @param capacity capacity in bytes - */ + /** + * @param datacenterId + * -- the id of the datacenter (availability zone) + */ + List listByDataCenterId(long datacenterId); + + /** + * @param datacenterId + * -- the id of the datacenter (availability zone) + */ + List listBy(long datacenterId, long podId, Long clusterId, ScopeType scope); + + /** + * Set capacity of storage pool in bytes + * + * @param id + * pool id. + * @param capacity + * capacity in bytes + */ void updateCapacity(long id, long capacity); - - /** - * Set available bytes of storage pool in bytes - * @param id pool id. - * @param available available capacity in bytes - */ + + /** + * Set available bytes of storage pool in bytes + * + * @param id + * pool id. + * @param available + * available capacity in bytes + */ void updateAvailable(long id, long available); - - + StoragePoolVO persist(StoragePoolVO pool, Map details); - + /** * Find pool by name. - * - * @param name name of pool. - * @return the single StoragePoolVO + * + * @param name + * name of pool. + * @return the single StoragePoolVO */ List findPoolByName(String name); - + /** * Find pools by the pod that matches the details. - * - * @param podId pod id to find the pools in. - * @param details details to match. All must match for the pool to be returned. + * + * @param podId + * pod id to find the pools in. + * @param details + * details to match. All must match for the pool to be returned. * @return List of StoragePoolVO */ - List findPoolsByDetails(long dcId, long podId, Long clusterId, Map details, ScopeType scope); - + List findPoolsByDetails(long dcId, long podId, Long clusterId, Map details, + ScopeType scope); + List findPoolsByTags(long dcId, long podId, Long clusterId, String[] tags); - + /** * Find pool by UUID. - * - * @param uuid uuid of pool. - * @return the single StoragePoolVO + * + * @param uuid + * uuid of pool. + * @return the single StoragePoolVO */ StoragePoolVO findPoolByUUID(String uuid); List listByStorageHost(String hostFqdnOrIp); StoragePoolVO findPoolByHostPath(long dcId, Long podId, String host, String path, String uuid); - + List listPoolByHostPath(String host, String path); - + void updateDetails(long poolId, Map details); - + Map getDetails(long poolId); - List searchForStoragePoolDetails(long poolId, String value); - - List findIfDuplicatePoolsExistByUUID(String uuid); + List searchForStoragePoolDetails(long poolId, String value); + + List findIfDuplicatePoolsExistByUUID(String uuid); List listByStatus(StoragePoolStatus status); long countPoolsByStatus(StoragePoolStatus... statuses); - List listByStatusInZone(long dcId, StoragePoolStatus status); - + List listByStatusInZone(long dcId, StoragePoolStatus status); + List listPoolsByCluster(long clusterId); - List findLocalStoragePoolsByTags(long dcId, long podId, - Long clusterId, String[] tags); + List findLocalStoragePoolsByTags(long dcId, long podId, Long clusterId, String[] tags); - List findZoneWideStoragePoolsByTags(long dcId, String[] tags); + List findZoneWideStoragePoolsByTags(long dcId, String[] tags); List findZoneWideStoragePoolsByHypervisor(long dataCenterId, HypervisorType hypervisorType); } diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java index d461d58ddfc..8f7826f4006 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java @@ -28,12 +28,12 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; import org.springframework.stereotype.Component; import com.cloud.host.Status; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.ScopeType; import com.cloud.storage.StoragePoolStatus; import com.cloud.utils.db.DB; @@ -49,141 +49,136 @@ import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; @Component -@Local(value={PrimaryDataStoreDao.class}) @DB(txn=false) -public class PrimaryDataStoreDaoImpl extends GenericDaoBase implements PrimaryDataStoreDao { +@Local(value = { PrimaryDataStoreDao.class }) +@DB(txn = false) +public class PrimaryDataStoreDaoImpl extends GenericDaoBase implements PrimaryDataStoreDao { protected final SearchBuilder AllFieldSearch; - protected final SearchBuilder DcPodSearch; + protected final SearchBuilder DcPodSearch; protected final SearchBuilder DcPodAnyClusterSearch; protected final SearchBuilder DeleteLvmSearch; protected final GenericSearchBuilder StatusCountSearch; - - @Inject protected StoragePoolDetailsDao _detailsDao; - + + @Inject + protected StoragePoolDetailsDao _detailsDao; + private final String DetailsSqlPrefix = "SELECT storage_pool.* from storage_pool LEFT JOIN storage_pool_details ON storage_pool.id = storage_pool_details.pool_id WHERE storage_pool.removed is null and storage_pool.status = 'Up' and storage_pool.data_center_id = ? and (storage_pool.pod_id = ? or storage_pool.pod_id is null) and storage_pool.scope = ? and ("; - private final String DetailsSqlSuffix = ") GROUP BY storage_pool_details.pool_id HAVING COUNT(storage_pool_details.name) >= ?"; - private final String ZoneWideDetailsSqlPrefix = "SELECT storage_pool.* from storage_pool LEFT JOIN storage_pool_details ON storage_pool.id = storage_pool_details.pool_id WHERE storage_pool.removed is null and storage_pool.status = 'Up' and storage_pool.data_center_id = ? and storage_pool.scope = ? and ("; - private final String ZoneWideDetailsSqlSuffix = ") GROUP BY storage_pool_details.pool_id HAVING COUNT(storage_pool_details.name) >= ?"; - - private final String FindPoolTagDetails = "SELECT storage_pool_details.name FROM storage_pool_details WHERE pool_id = ? and value = ?"; - + private final String DetailsSqlSuffix = ") GROUP BY storage_pool_details.pool_id HAVING COUNT(storage_pool_details.name) >= ?"; + private final String ZoneWideDetailsSqlPrefix = "SELECT storage_pool.* from storage_pool LEFT JOIN storage_pool_details ON storage_pool.id = storage_pool_details.pool_id WHERE storage_pool.removed is null and storage_pool.status = 'Up' and storage_pool.data_center_id = ? and storage_pool.scope = ? and ("; + private final String ZoneWideDetailsSqlSuffix = ") GROUP BY storage_pool_details.pool_id HAVING COUNT(storage_pool_details.name) >= ?"; + + private final String FindPoolTagDetails = "SELECT storage_pool_details.name FROM storage_pool_details WHERE pool_id = ? and value = ?"; + public PrimaryDataStoreDaoImpl() { AllFieldSearch = createSearchBuilder(); AllFieldSearch.and("name", AllFieldSearch.entity().getName(), SearchCriteria.Op.EQ); AllFieldSearch.and("uuid", AllFieldSearch.entity().getUuid(), SearchCriteria.Op.EQ); AllFieldSearch.and("datacenterId", AllFieldSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); AllFieldSearch.and("hostAddress", AllFieldSearch.entity().getHostAddress(), SearchCriteria.Op.EQ); - AllFieldSearch.and("status",AllFieldSearch.entity().getStatus(),SearchCriteria.Op.EQ); + AllFieldSearch.and("status", AllFieldSearch.entity().getStatus(), SearchCriteria.Op.EQ); AllFieldSearch.and("path", AllFieldSearch.entity().getPath(), SearchCriteria.Op.EQ); AllFieldSearch.and("podId", AllFieldSearch.entity().getPodId(), Op.EQ); AllFieldSearch.and("clusterId", AllFieldSearch.entity().getClusterId(), Op.EQ); - AllFieldSearch.done(); - - DcPodSearch = createSearchBuilder(); - DcPodSearch.and("datacenterId", DcPodSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); - DcPodSearch.and("status", DcPodSearch.entity().getStatus(), SearchCriteria.Op.EQ); - DcPodSearch.and("scope", DcPodSearch.entity().getScope(), SearchCriteria.Op.EQ); - DcPodSearch.and().op("nullpod", DcPodSearch.entity().getPodId(), SearchCriteria.Op.NULL); - DcPodSearch.or("podId", DcPodSearch.entity().getPodId(), SearchCriteria.Op.EQ); - DcPodSearch.cp(); - DcPodSearch.and().op("nullcluster", DcPodSearch.entity().getClusterId(), SearchCriteria.Op.NULL); - DcPodSearch.or("cluster", DcPodSearch.entity().getClusterId(), SearchCriteria.Op.EQ); - DcPodSearch.cp(); - DcPodSearch.done(); - - DcPodAnyClusterSearch = createSearchBuilder(); - DcPodAnyClusterSearch.and("datacenterId", DcPodAnyClusterSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); + AllFieldSearch.done(); + + DcPodSearch = createSearchBuilder(); + DcPodSearch.and("datacenterId", DcPodSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); + DcPodSearch.and("status", DcPodSearch.entity().getStatus(), SearchCriteria.Op.EQ); + DcPodSearch.and("scope", DcPodSearch.entity().getScope(), SearchCriteria.Op.EQ); + DcPodSearch.and().op("nullpod", DcPodSearch.entity().getPodId(), SearchCriteria.Op.NULL); + DcPodSearch.or("podId", DcPodSearch.entity().getPodId(), SearchCriteria.Op.EQ); + DcPodSearch.cp(); + DcPodSearch.and().op("nullcluster", DcPodSearch.entity().getClusterId(), SearchCriteria.Op.NULL); + DcPodSearch.or("cluster", DcPodSearch.entity().getClusterId(), SearchCriteria.Op.EQ); + DcPodSearch.cp(); + DcPodSearch.done(); + + DcPodAnyClusterSearch = createSearchBuilder(); + DcPodAnyClusterSearch.and("datacenterId", DcPodAnyClusterSearch.entity().getDataCenterId(), + SearchCriteria.Op.EQ); DcPodAnyClusterSearch.and("status", DcPodAnyClusterSearch.entity().getStatus(), SearchCriteria.Op.EQ); DcPodAnyClusterSearch.and("scope", DcPodAnyClusterSearch.entity().getScope(), SearchCriteria.Op.EQ); DcPodAnyClusterSearch.and().op("nullpod", DcPodAnyClusterSearch.entity().getPodId(), SearchCriteria.Op.NULL); DcPodAnyClusterSearch.or("podId", DcPodAnyClusterSearch.entity().getPodId(), SearchCriteria.Op.EQ); DcPodAnyClusterSearch.cp(); DcPodAnyClusterSearch.done(); - + DeleteLvmSearch = createSearchBuilder(); DeleteLvmSearch.and("ids", DeleteLvmSearch.entity().getId(), SearchCriteria.Op.IN); DeleteLvmSearch.and().op("LVM", DeleteLvmSearch.entity().getPoolType(), SearchCriteria.Op.EQ); DeleteLvmSearch.or("Filesystem", DeleteLvmSearch.entity().getPoolType(), SearchCriteria.Op.EQ); DeleteLvmSearch.cp(); - DeleteLvmSearch.done(); + DeleteLvmSearch.done(); - - StatusCountSearch = createSearchBuilder(Long.class); StatusCountSearch.and("status", StatusCountSearch.entity().getStatus(), SearchCriteria.Op.IN); StatusCountSearch.select(null, Func.COUNT, null); StatusCountSearch.done(); } - - @Override - public List findPoolByName(String name) { - SearchCriteria sc = AllFieldSearch.create(); + + @Override + public List findPoolByName(String name) { + SearchCriteria sc = AllFieldSearch.create(); sc.setParameters("name", name); return listIncludingRemovedBy(sc); - } + } - - @Override - public StoragePoolVO findPoolByUUID(String uuid) { - SearchCriteria sc = AllFieldSearch.create(); + @Override + public StoragePoolVO findPoolByUUID(String uuid) { + SearchCriteria sc = AllFieldSearch.create(); sc.setParameters("uuid", uuid); return findOneIncludingRemovedBy(sc); - } - - + } - @Override - public List findIfDuplicatePoolsExistByUUID(String uuid) { - SearchCriteria sc = AllFieldSearch.create(); + @Override + public List findIfDuplicatePoolsExistByUUID(String uuid) { + SearchCriteria sc = AllFieldSearch.create(); sc.setParameters("uuid", uuid); return listBy(sc); - } + } - - @Override - public List listByDataCenterId(long datacenterId) { - SearchCriteria sc = AllFieldSearch.create(); + @Override + public List listByDataCenterId(long datacenterId) { + SearchCriteria sc = AllFieldSearch.create(); sc.setParameters("datacenterId", datacenterId); return listBy(sc); - } + } + @Override + public void updateAvailable(long id, long available) { + StoragePoolVO pool = createForUpdate(id); + pool.setUsedBytes(available); + update(id, pool); + } - @Override - public void updateAvailable(long id, long available) { - StoragePoolVO pool = createForUpdate(id); - pool.setAvailableBytes(available); - update(id, pool); - } + @Override + public void updateCapacity(long id, long capacity) { + StoragePoolVO pool = createForUpdate(id); + pool.setCapacityBytes(capacity); + update(id, pool); + } - @Override - public void updateCapacity(long id, long capacity) { - StoragePoolVO pool = createForUpdate(id); - pool.setCapacityBytes(capacity); - update(id, pool); - - } - @Override public List listByStorageHost(String hostFqdnOrIp) { SearchCriteria sc = AllFieldSearch.create(); sc.setParameters("hostAddress", hostFqdnOrIp); return listIncludingRemovedBy(sc); } - + @Override - public List listByStatus(StoragePoolStatus status){ + public List listByStatus(StoragePoolStatus status) { SearchCriteria sc = AllFieldSearch.create(); - sc.setParameters("status", status); - return listBy(sc); + sc.setParameters("status", status); + return listBy(sc); } - + @Override - public List listByStatusInZone(long dcId, StoragePoolStatus status){ + public List listByStatusInZone(long dcId, StoragePoolStatus status) { SearchCriteria sc = AllFieldSearch.create(); - sc.setParameters("status", status); - sc.setParameters("datacenterId", dcId); - return listBy(sc); + sc.setParameters("status", status); + sc.setParameters("datacenterId", dcId); + return listBy(sc); } @Override @@ -194,238 +189,239 @@ public class PrimaryDataStoreDaoImpl extends GenericDaoBase sc.setParameters("datacenterId", datacenterId); sc.setParameters("podId", podId); sc.setParameters("uuid", uuid); - + return findOneBy(sc); } - @Override - public List listBy(long datacenterId, long podId, Long clusterId, ScopeType scope) { - if (clusterId != null) { - SearchCriteria sc = DcPodSearch.create(); + @Override + public List listBy(long datacenterId, long podId, Long clusterId, ScopeType scope) { + if (clusterId != null) { + SearchCriteria sc = DcPodSearch.create(); sc.setParameters("datacenterId", datacenterId); sc.setParameters("podId", podId); sc.setParameters("status", Status.Up); sc.setParameters("scope", scope); - + sc.setParameters("cluster", clusterId); return listBy(sc); - } else { - SearchCriteria sc = DcPodAnyClusterSearch.create(); - sc.setParameters("datacenterId", datacenterId); - sc.setParameters("podId", podId); - sc.setParameters("status", Status.Up); - sc.setParameters("scope", scope); - return listBy(sc); - } - } + } else { + SearchCriteria sc = DcPodAnyClusterSearch.create(); + sc.setParameters("datacenterId", datacenterId); + sc.setParameters("podId", podId); + sc.setParameters("status", Status.Up); + sc.setParameters("scope", scope); + return listBy(sc); + } + } - @Override - public List listPoolByHostPath(String host, String path) { + @Override + public List listPoolByHostPath(String host, String path) { SearchCriteria sc = AllFieldSearch.create(); sc.setParameters("hostAddress", host); sc.setParameters("path", path); - + return listBy(sc); - } - - public StoragePoolVO listById(Integer id) - { + } + + public StoragePoolVO listById(Integer id) { SearchCriteria sc = AllFieldSearch.create(); sc.setParameters("id", id); - + return findOneIncludingRemovedBy(sc); - } - - @Override @DB - public StoragePoolVO persist(StoragePoolVO pool, Map details) { - Transaction txn = Transaction.currentTxn(); - txn.start(); - pool = super.persist(pool); - if (details != null) { - for (Map.Entry detail : details.entrySet()) { - StoragePoolDetailVO vo = new StoragePoolDetailVO(pool.getId(), detail.getKey(), detail.getValue()); - _detailsDao.persist(vo); - } - } - txn.commit(); - return pool; - } - - @DB - @Override - public List findPoolsByDetails(long dcId, long podId, Long clusterId, Map details, ScopeType scope) { - StringBuilder sql = new StringBuilder(DetailsSqlPrefix); - if (clusterId != null) { - sql.append("storage_pool.cluster_id = ? OR storage_pool.cluster_id IS NULL) AND ("); - } - - for (Map.Entry detail : details.entrySet()) { - sql.append("((storage_pool_details.name='").append(detail.getKey()).append("') AND (storage_pool_details.value='").append(detail.getValue()).append("')) OR "); - } - sql.delete(sql.length() - 4, sql.length()); - sql.append(DetailsSqlSuffix); - Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = null; - try { - pstmt = txn.prepareAutoCloseStatement(sql.toString()); - int i = 1; - pstmt.setLong(i++, dcId); - pstmt.setLong(i++, podId); - pstmt.setString(i++, scope.toString()); - if (clusterId != null) { - pstmt.setLong(i++, clusterId); - } - pstmt.setInt(i++, details.size()); - ResultSet rs = pstmt.executeQuery(); - List pools = new ArrayList(); - while (rs.next()) { - pools.add(toEntityBean(rs, false)); - } - return pools; - } catch (SQLException e) { - throw new CloudRuntimeException("Unable to execute " + pstmt, e); - } - } - - protected Map tagsToDetails(String[] tags) { - Map details = new HashMap(tags.length); - for (String tag: tags) { - details.put(tag, "true"); - } - return details; - } - - @Override - public List findPoolsByTags(long dcId, long podId, Long clusterId, String[] tags) { - List storagePools = null; - if (tags == null || tags.length == 0) { - storagePools = listBy(dcId, podId, clusterId, ScopeType.CLUSTER); - } else { - Map details = tagsToDetails(tags); - storagePools = findPoolsByDetails(dcId, podId, clusterId, details, ScopeType.CLUSTER); - } - - return storagePools; - } - - @Override - public List findLocalStoragePoolsByTags(long dcId, long podId, Long clusterId, String[] tags) { - List storagePools = null; - if (tags == null || tags.length == 0) { - storagePools = listBy(dcId, podId, clusterId, ScopeType.HOST); - } else { - Map details = tagsToDetails(tags); - storagePools = findPoolsByDetails(dcId, podId, clusterId, details, ScopeType.HOST); - } - - return storagePools; - } - - @Override - public List findZoneWideStoragePoolsByTags(long dcId, String[] tags) { - List storagePools = null; - if (tags == null || tags.length == 0) { - SearchCriteriaService sc = SearchCriteria2.create(StoragePoolVO.class); - sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId); - sc.addAnd(sc.getEntity().getStatus(), Op.EQ, Status.Up); - sc.addAnd(sc.getEntity().getScope(), Op.EQ, ScopeType.ZONE); - return sc.list(); - } else { - Map details = tagsToDetails(tags); - - StringBuilder sql = new StringBuilder(ZoneWideDetailsSqlPrefix); - - for (Map.Entry detail : details.entrySet()) { - sql.append("((storage_pool_details.name='").append(detail.getKey()).append("') AND (storage_pool_details.value='").append(detail.getValue()).append("')) OR "); - } - sql.delete(sql.length() - 4, sql.length()); - sql.append(ZoneWideDetailsSqlSuffix); - Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = null; - try { - pstmt = txn.prepareAutoCloseStatement(sql.toString()); - int i = 1; - pstmt.setLong(i++, dcId); - pstmt.setString(i++, ScopeType.ZONE.toString()); - pstmt.setInt(i++, details.size()); - ResultSet rs = pstmt.executeQuery(); - List pools = new ArrayList(); - while (rs.next()) { - pools.add(toEntityBean(rs, false)); - } - return pools; - } catch (SQLException e) { - throw new CloudRuntimeException("Unable to execute " + pstmt, e); - } - } - } - - @Override - @DB - public List searchForStoragePoolDetails(long poolId, String value){ - - StringBuilder sql = new StringBuilder(FindPoolTagDetails); - - Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = null; - try { - pstmt = txn.prepareAutoCloseStatement(sql.toString()); - pstmt.setLong(1, poolId); - pstmt.setString(2, value); - - ResultSet rs = pstmt.executeQuery(); - List tags = new ArrayList(); - - while (rs.next()) { - tags.add(rs.getString("name")); - } - return tags; - } catch (SQLException e) { - throw new CloudRuntimeException("Unable to execute " + pstmt.toString(), e); - } - - } - - @Override - public void updateDetails(long poolId, Map details) { - if (details != null) { - _detailsDao.update(poolId, details); - } } - - @Override - public Map getDetails(long poolId) { - return _detailsDao.getDetails(poolId); - } - - @Override - public boolean configure(String name, Map params) throws ConfigurationException { - super.configure(name, params); - _detailsDao.configure("DetailsDao", params); - return true; - } - - - + @Override - public long countPoolsByStatus( StoragePoolStatus... statuses) { + @DB + public StoragePoolVO persist(StoragePoolVO pool, Map details) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + pool = super.persist(pool); + if (details != null) { + for (Map.Entry detail : details.entrySet()) { + StoragePoolDetailVO vo = new StoragePoolDetailVO(pool.getId(), detail.getKey(), detail.getValue()); + _detailsDao.persist(vo); + } + } + txn.commit(); + return pool; + } + + @DB + @Override + public List findPoolsByDetails(long dcId, long podId, Long clusterId, Map details, + ScopeType scope) { + StringBuilder sql = new StringBuilder(DetailsSqlPrefix); + if (clusterId != null) { + sql.append("storage_pool.cluster_id = ? OR storage_pool.cluster_id IS NULL) AND ("); + } + + for (Map.Entry detail : details.entrySet()) { + sql.append("((storage_pool_details.name='").append(detail.getKey()) + .append("') AND (storage_pool_details.value='").append(detail.getValue()).append("')) OR "); + } + sql.delete(sql.length() - 4, sql.length()); + sql.append(DetailsSqlSuffix); + Transaction txn = Transaction.currentTxn(); + PreparedStatement pstmt = null; + try { + pstmt = txn.prepareAutoCloseStatement(sql.toString()); + int i = 1; + pstmt.setLong(i++, dcId); + pstmt.setLong(i++, podId); + pstmt.setString(i++, scope.toString()); + if (clusterId != null) { + pstmt.setLong(i++, clusterId); + } + pstmt.setInt(i++, details.size()); + ResultSet rs = pstmt.executeQuery(); + List pools = new ArrayList(); + while (rs.next()) { + pools.add(toEntityBean(rs, false)); + } + return pools; + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to execute " + pstmt, e); + } + } + + protected Map tagsToDetails(String[] tags) { + Map details = new HashMap(tags.length); + for (String tag : tags) { + details.put(tag, "true"); + } + return details; + } + + @Override + public List findPoolsByTags(long dcId, long podId, Long clusterId, String[] tags) { + List storagePools = null; + if (tags == null || tags.length == 0) { + storagePools = listBy(dcId, podId, clusterId, ScopeType.CLUSTER); + } else { + Map details = tagsToDetails(tags); + storagePools = findPoolsByDetails(dcId, podId, clusterId, details, ScopeType.CLUSTER); + } + + return storagePools; + } + + @Override + public List findLocalStoragePoolsByTags(long dcId, long podId, Long clusterId, String[] tags) { + List storagePools = null; + if (tags == null || tags.length == 0) { + storagePools = listBy(dcId, podId, clusterId, ScopeType.HOST); + } else { + Map details = tagsToDetails(tags); + storagePools = findPoolsByDetails(dcId, podId, clusterId, details, ScopeType.HOST); + } + + return storagePools; + } + + @Override + public List findZoneWideStoragePoolsByTags(long dcId, String[] tags) { + List storagePools = null; + if (tags == null || tags.length == 0) { + SearchCriteriaService sc = SearchCriteria2.create(StoragePoolVO.class); + sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId); + sc.addAnd(sc.getEntity().getStatus(), Op.EQ, Status.Up); + sc.addAnd(sc.getEntity().getScope(), Op.EQ, ScopeType.ZONE); + return sc.list(); + } else { + Map details = tagsToDetails(tags); + + StringBuilder sql = new StringBuilder(ZoneWideDetailsSqlPrefix); + + for (Map.Entry detail : details.entrySet()) { + sql.append("((storage_pool_details.name='").append(detail.getKey()) + .append("') AND (storage_pool_details.value='").append(detail.getValue()).append("')) OR "); + } + sql.delete(sql.length() - 4, sql.length()); + sql.append(ZoneWideDetailsSqlSuffix); + Transaction txn = Transaction.currentTxn(); + PreparedStatement pstmt = null; + try { + pstmt = txn.prepareAutoCloseStatement(sql.toString()); + int i = 1; + pstmt.setLong(i++, dcId); + pstmt.setString(i++, ScopeType.ZONE.toString()); + pstmt.setInt(i++, details.size()); + ResultSet rs = pstmt.executeQuery(); + List pools = new ArrayList(); + while (rs.next()) { + pools.add(toEntityBean(rs, false)); + } + return pools; + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to execute " + pstmt, e); + } + } + } + + @Override + @DB + public List searchForStoragePoolDetails(long poolId, String value) { + + StringBuilder sql = new StringBuilder(FindPoolTagDetails); + + Transaction txn = Transaction.currentTxn(); + PreparedStatement pstmt = null; + try { + pstmt = txn.prepareAutoCloseStatement(sql.toString()); + pstmt.setLong(1, poolId); + pstmt.setString(2, value); + + ResultSet rs = pstmt.executeQuery(); + List tags = new ArrayList(); + + while (rs.next()) { + tags.add(rs.getString("name")); + } + return tags; + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to execute " + pstmt.toString(), e); + } + + } + + @Override + public void updateDetails(long poolId, Map details) { + if (details != null) { + _detailsDao.update(poolId, details); + } + } + + @Override + public Map getDetails(long poolId) { + return _detailsDao.getDetails(poolId); + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + super.configure(name, params); + _detailsDao.configure("DetailsDao", params); + return true; + } + + @Override + public long countPoolsByStatus(StoragePoolStatus... statuses) { SearchCriteria sc = StatusCountSearch.create(); - - sc.setParameters("status", (Object[])statuses); - + + sc.setParameters("status", (Object[]) statuses); + List rs = customSearchIncludingRemoved(sc, null); if (rs.size() == 0) { return 0; } - + return rs.get(0); } - + @Override public List listPoolsByCluster(long clusterId) { SearchCriteria sc = AllFieldSearch.create(); sc.setParameters("clusterId", clusterId); - + return listBy(sc); } diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDetailVO.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDetailVO.java index d1f802de949..0d9af4b5fb3 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDetailVO.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDetailVO.java @@ -24,28 +24,28 @@ import javax.persistence.Id; import javax.persistence.Table; @Entity -@Table(name="storage_pool_details") +@Table(name = "storage_pool_details") public class PrimaryDataStoreDetailVO { @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - @Column(name="id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") long id; - - @Column(name="pool_id") + + @Column(name = "pool_id") long poolId; - - @Column(name="name") + + @Column(name = "name") String name; - - @Column(name="value") + + @Column(name = "value") String value; - + public PrimaryDataStoreDetailVO(long poolId, String name, String value) { this.poolId = poolId; this.name = name; this.value = value; } - + public long getId() { return id; } diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDetailsDao.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDetailsDao.java index c2b109a959e..18e2f1c7018 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDetailsDao.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDetailsDao.java @@ -21,7 +21,8 @@ import java.util.Map; import com.cloud.utils.db.GenericDao; public interface PrimaryDataStoreDetailsDao extends GenericDao { - + void update(long poolId, Map details); + Map getDetails(long poolId); } \ No newline at end of file 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 new file mode 100644 index 00000000000..01f02208307 --- /dev/null +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java @@ -0,0 +1,40 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +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.storage.DataStoreRole; +import com.cloud.utils.db.GenericDao; +import com.cloud.utils.fsm.StateDao; + +public interface SnapshotDataStoreDao extends GenericDao, + StateDao { + + List listByStoreId(long id, DataStoreRole role); + + void deletePrimaryRecordsForStore(long id); + + SnapshotDataStoreVO findByStoreSnapshot(DataStoreRole role, long storeId, long snapshotId); + + SnapshotDataStoreVO findBySnapshot(long snapshotId, DataStoreRole role); + + List listDestroyed(long storeId); +} 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 new file mode 100644 index 00000000000..2ae3e8cdbda --- /dev/null +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreVO.java @@ -0,0 +1,260 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.datastore.db; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State; + +import com.cloud.storage.DataStoreRole; +import com.cloud.utils.db.GenericDao; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.fsm.StateObject; + +/** + * Join table for image_data_store and snapshots + * + */ +@Entity +@Table(name = "snapshot_store_ref") +public class SnapshotDataStoreVO implements StateObject, DataObjectInStore { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + Long id; + + @Column(name = "store_id") + private long dataStoreId; + + @Column(name = "store_role") + @Enumerated(EnumType.STRING) + private DataStoreRole role; + + @Column(name = "snapshot_id") + private long snapshotId; + + @Column(name = GenericDaoBase.CREATED_COLUMN) + private Date created = null; + + @Column(name = "last_updated") + @Temporal(value = TemporalType.TIMESTAMP) + private Date lastUpdated = null; + + @Column(name = "size") + private long size; + + @Column(name = "physical_size") + private long physicalSize; + + @Column(name = "parent_snapshot_id") + private long parentSnapshotId; + + @Column(name = "job_id") + private String jobId; + + @Column(name = "install_path") + private String installPath; + + @Column(name = "update_count", updatable = true, nullable = false) + protected long updatedCount; + + @Column(name = "updated") + @Temporal(value = TemporalType.TIMESTAMP) + Date updated; + + @Column(name = "state") + @Enumerated(EnumType.STRING) + ObjectInDataStoreStateMachine.State state; + + @Column(name = "ref_cnt") + Long refCnt; + + public String getInstallPath() { + return installPath; + } + + @Override + public long getDataStoreId() { + return dataStoreId; + } + + public void setDataStoreId(long storeId) { + this.dataStoreId = storeId; + } + + public long getSnapshotId() { + return snapshotId; + } + + public void setSnapshotId(long snapshotId) { + this.snapshotId = snapshotId; + } + + public long getId() { + return id; + } + + public Date getCreated() { + return created; + } + + public Date getLastUpdated() { + return lastUpdated; + } + + public void setLastUpdated(Date date) { + lastUpdated = date; + } + + public void setInstallPath(String installPath) { + this.installPath = installPath; + } + + public SnapshotDataStoreVO(long hostId, long snapshotId) { + super(); + this.dataStoreId = hostId; + this.snapshotId = snapshotId; + this.state = ObjectInDataStoreStateMachine.State.Allocated; + } + + public SnapshotDataStoreVO() { + + } + + public void setJobId(String jobId) { + this.jobId = jobId; + } + + public String getJobId() { + return jobId; + } + + public boolean equals(Object obj) { + if (obj instanceof SnapshotDataStoreVO) { + SnapshotDataStoreVO other = (SnapshotDataStoreVO) obj; + return (this.snapshotId == other.getSnapshotId() && this.dataStoreId == other.getDataStoreId()); + } + return false; + } + + public int hashCode() { + Long tid = new Long(snapshotId); + Long hid = new Long(dataStoreId); + return tid.hashCode() + hid.hashCode(); + } + + public void setSize(long size) { + this.size = size; + } + + public long getSize() { + return size; + } + + public void setPhysicalSize(long physicalSize) { + this.physicalSize = physicalSize; + } + + public long getPhysicalSize() { + return physicalSize; + } + + public long getVolumeSize() { + return -1; + } + + public String toString() { + return new StringBuilder("VolumeHost[").append(id).append("-").append(snapshotId).append("-") + .append(dataStoreId).append(installPath).append("]").toString(); + } + + public long getUpdatedCount() { + return this.updatedCount; + } + + public void incrUpdatedCount() { + this.updatedCount++; + } + + public void decrUpdatedCount() { + this.updatedCount--; + } + + public Date getUpdated() { + return updated; + } + + @Override + public ObjectInDataStoreStateMachine.State getState() { + // TODO Auto-generated method stub + return this.state; + } + + public void setState(ObjectInDataStoreStateMachine.State state) { + this.state = state; + } + + @Override + public long getObjectId() { + return this.getSnapshotId(); + } + + public DataStoreRole getRole() { + return role; + } + + public void setRole(DataStoreRole role) { + this.role = role; + } + + @Override + public State getObjectInStoreState() { + return this.state; + } + + public long getParentSnapshotId() { + return parentSnapshotId; + } + + public void setParentSnapshotId(long parentSnapshotId) { + this.parentSnapshotId = parentSnapshotId; + } + + public Long getRefCnt() { + return refCnt; + } + + public void incrRefCnt() { + this.refCnt++; + } + + public void decrRefCnt() { + this.refCnt--; + } +} diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolDetailVO.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolDetailVO.java index 699beef90c2..e51f3a38996 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolDetailVO.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolDetailVO.java @@ -26,28 +26,28 @@ import javax.persistence.Id; import javax.persistence.Table; @Entity -@Table(name="storage_pool_details") +@Table(name = "storage_pool_details") public class StoragePoolDetailVO implements InternalIdentity { @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - @Column(name="id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") long id; - - @Column(name="pool_id") + + @Column(name = "pool_id") long poolId; - - @Column(name="name") + + @Column(name = "name") String name; - - @Column(name="value") + + @Column(name = "value") String value; - + public StoragePoolDetailVO(long poolId, String name, String value) { this.poolId = poolId; this.name = name; this.value = value; } - + public long getId() { return id; } diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolDetailsDao.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolDetailsDao.java index 237f235704d..49f4f196245 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolDetailsDao.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolDetailsDao.java @@ -18,12 +18,13 @@ package org.apache.cloudstack.storage.datastore.db; import java.util.Map; - import com.cloud.utils.db.GenericDao; public interface StoragePoolDetailsDao extends GenericDao { - + void update(long poolId, Map details); + Map getDetails(long poolId); + StoragePoolDetailVO findDetail(long poolId, String name); } diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java index 0262f65af0a..9b8de679b08 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java @@ -29,19 +29,19 @@ import javax.persistence.TableGenerator; import javax.persistence.Temporal; import javax.persistence.TemporalType; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; - import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.storage.ScopeType; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolStatus; import com.cloud.utils.db.GenericDao; @Entity -@Table(name="storage_pool") -public class StoragePoolVO implements StoragePool{ +@Table(name = "storage_pool") +public class StoragePoolVO implements StoragePool { @Id - @TableGenerator(name = "storage_pool_sq", table = "sequence", pkColumnName = "name", valueColumnName = "value", pkColumnValue = "storage_pool_seq", allocationSize = 1) + @TableGenerator(name = "storage_pool_sq", table = "sequence", pkColumnName = "name", valueColumnName = "value", + pkColumnValue = "storage_pool_seq", allocationSize = 1) @Column(name = "id", updatable = false, nullable = false) private long id; @@ -71,8 +71,8 @@ public class StoragePoolVO implements StoragePool{ @Column(name = "pod_id", updatable = true) private Long podId; - @Column(name = "available_bytes", updatable = true, nullable = true) - private long availableBytes; + @Column(name = "used_bytes", updatable = true, nullable = true) + private long usedBytes; @Column(name = "capacity_bytes", updatable = true, nullable = true) private long capacityBytes; @@ -118,15 +118,15 @@ public class StoragePoolVO implements StoragePool{ public StoragePoolVO() { this.status = StoragePoolStatus.Initial; } - - public StoragePoolVO(long poolId, String name, String uuid, StoragePoolType type, - long dataCenterId, Long podId, long availableBytes, long capacityBytes, String hostAddress, int port, String hostPath) { - this.name = name; + + public StoragePoolVO(long poolId, String name, String uuid, StoragePoolType type, long dataCenterId, Long podId, + long availableBytes, long capacityBytes, String hostAddress, int port, String hostPath) { + this.name = name; this.id = poolId; this.uuid = uuid; this.poolType = type; this.dataCenterId = dataCenterId; - this.availableBytes = availableBytes; + this.usedBytes = availableBytes; this.capacityBytes = capacityBytes; this.hostAddress = hostAddress; this.path = hostPath; @@ -136,7 +136,8 @@ public class StoragePoolVO implements StoragePool{ } public StoragePoolVO(StoragePoolVO that) { - this(that.id, that.name, that.uuid, that.poolType, that.dataCenterId, that.podId, that.availableBytes, that.capacityBytes, that.hostAddress, that.port, that.path); + this(that.id, that.name, that.uuid, that.poolType, that.dataCenterId, that.podId, that.usedBytes, + that.capacityBytes, that.hostAddress, that.port, that.path); } public StoragePoolVO(StoragePoolType type, String hostAddress, int port, String path) { @@ -148,7 +149,6 @@ public class StoragePoolVO implements StoragePool{ this.uuid = UUID.randomUUID().toString(); } - public String getName() { return name; } @@ -181,8 +181,8 @@ public class StoragePoolVO implements StoragePool{ return dataCenterId; } - public long getAvailableBytes() { - return availableBytes; + public long getUsedBytes() { + return usedBytes; } public String getStorageProviderName() { @@ -197,8 +197,8 @@ public class StoragePoolVO implements StoragePool{ return capacityBytes; } - public void setAvailableBytes(long available) { - availableBytes = available; + public void setUsedBytes(long available) { + usedBytes = available; } public void setCapacityBytes(long capacity) { @@ -307,11 +307,11 @@ public class StoragePoolVO implements StoragePool{ public String toString() { return new StringBuilder("Pool[").append(id).append("|").append(poolType).append("]").toString(); } - + public boolean isShared() { return this.scope == ScopeType.HOST ? false : true; } - + public boolean isLocal() { return !isShared(); } diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java new file mode 100644 index 00000000000..13b84ff3dba --- /dev/null +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java @@ -0,0 +1,63 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.datastore.db; + +import java.util.List; + +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State; +import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; + +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.VMTemplateStorageResourceAssoc; +import com.cloud.utils.db.GenericDao; +import com.cloud.utils.fsm.StateDao; + +public interface TemplateDataStoreDao extends GenericDao, + StateDao { + + List listByStoreId(long id); + + List listDestroyed(long storeId); + + void deletePrimaryRecordsForStore(long id); + + void deletePrimaryRecordsForTemplate(long templateId); + + List listByTemplateStore(long templateId, long storeId); + + List listByTemplateStoreStatus(long templateId, long storeId, State... states); + + List listByTemplateStoreDownloadStatus(long templateId, long storeId, + VMTemplateStorageResourceAssoc.Status... status); + + List listByTemplateZoneDownloadStatus(long templateId, Long zoneId, + VMTemplateStorageResourceAssoc.Status... status); + + TemplateDataStoreVO findByTemplateZoneDownloadStatus(long templateId, Long zoneId, + VMTemplateStorageResourceAssoc.Status... status); + + TemplateDataStoreVO findByStoreTemplate(long storeId, long templateId); + + TemplateDataStoreVO findByStoreTemplate(long storeId, long templateId, boolean lock); + + TemplateDataStoreVO findByTemplate(long templateId, DataStoreRole role); + + TemplateDataStoreVO findByTemplateZone(long templateId, Long zoneId, DataStoreRole role); + + List listByTemplate(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 new file mode 100755 index 00000000000..c6b434dbc1a --- /dev/null +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreVO.java @@ -0,0 +1,372 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.datastore.db; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State; + +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; + +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.fsm.StateObject; + +/** + * Join table for image_data_store and templates + * + */ +@Entity +@Table(name = "template_store_ref") +public class TemplateDataStoreVO implements StateObject, DataObjectInStore { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + Long id; + + @Column(name = "store_id") + private Long dataStoreId; // this can be null for baremetal templates + + @Column(name = "template_id") + private long templateId; + + @Column(name = "store_role") + @Enumerated(EnumType.STRING) + private DataStoreRole dataStoreRole; + + @Column(name = GenericDaoBase.CREATED_COLUMN) + private Date created = null; + + @Column(name = "last_updated") + @Temporal(value = TemporalType.TIMESTAMP) + private Date lastUpdated = null; + + @Column(name = "download_pct") + private int downloadPercent; + + @Column(name = "size") + private Long size; + + @Column(name = "physical_size") + private long physicalSize; + + @Column(name = "download_state") + @Enumerated(EnumType.STRING) + private Status downloadState; + + @Column(name = "local_path") + private String localDownloadPath; + + @Column(name = "error_str") + private String errorString; + + @Column(name = "job_id") + private String jobId; + + @Column(name = "install_path") + private String installPath; + + @Column(name = "url") + private String downloadUrl; + + @Column(name = "is_copy") + private boolean isCopy = false; + + @Column(name = "destroyed") + boolean destroyed = false; + + @Column(name = "update_count", updatable = true, nullable = false) + protected long updatedCount; + + @Column(name = "updated") + @Temporal(value = TemporalType.TIMESTAMP) + Date updated; + + @Column(name = "state") + @Enumerated(EnumType.STRING) + ObjectInDataStoreStateMachine.State state; + + @Column(name = "ref_cnt") + Long refCnt; + + public TemplateDataStoreVO(Long hostId, long templateId) { + super(); + this.dataStoreId = hostId; + this.templateId = templateId; + this.state = ObjectInDataStoreStateMachine.State.Allocated; + this.refCnt = 0L; + } + + public TemplateDataStoreVO(Long hostId, long templateId, Date lastUpdated, int downloadPercent, + Status downloadState, String localDownloadPath, String errorString, String jobId, String installPath, + String downloadUrl) { + super(); + this.dataStoreId = hostId; + this.templateId = templateId; + this.lastUpdated = lastUpdated; + this.downloadPercent = downloadPercent; + this.downloadState = downloadState; + this.localDownloadPath = localDownloadPath; + this.errorString = errorString; + this.jobId = jobId; + this.refCnt = 0L; + this.installPath = installPath; + this.setDownloadUrl(downloadUrl); + switch (downloadState) { + case DOWNLOADED: + this.state = ObjectInDataStoreStateMachine.State.Ready; + break; + case CREATING: + case DOWNLOAD_IN_PROGRESS: + case UPLOAD_IN_PROGRESS: + this.state = ObjectInDataStoreStateMachine.State.Creating2; + break; + case DOWNLOAD_ERROR: + case UPLOAD_ERROR: + this.state = ObjectInDataStoreStateMachine.State.Failed; + break; + case ABANDONED: + this.state = ObjectInDataStoreStateMachine.State.Destroyed; + break; + default: + this.state = ObjectInDataStoreStateMachine.State.Allocated; + break; + } + } + + public TemplateDataStoreVO() { + this.refCnt = 0L; + } + + @Override + public String getInstallPath() { + return installPath; + } + + @Override + public long getDataStoreId() { + return dataStoreId; + } + + public void setDataStoreId(long storeId) { + this.dataStoreId = storeId; + } + + public long getTemplateId() { + return templateId; + } + + public void setTemplateId(long templateId) { + this.templateId = templateId; + } + + public int getDownloadPercent() { + return downloadPercent; + } + + public void setDownloadPercent(int downloadPercent) { + this.downloadPercent = downloadPercent; + } + + public void setDownloadState(Status downloadState) { + this.downloadState = downloadState; + } + + public long getId() { + return id; + } + + public Date getCreated() { + return created; + } + + public Date getLastUpdated() { + return lastUpdated; + } + + public void setLastUpdated(Date date) { + lastUpdated = date; + } + + @Override + public void setInstallPath(String installPath) { + this.installPath = installPath; + } + + public Status getDownloadState() { + return downloadState; + } + + public void setLocalDownloadPath(String localPath) { + this.localDownloadPath = localPath; + } + + public String getLocalDownloadPath() { + return localDownloadPath; + } + + public void setErrorString(String errorString) { + this.errorString = errorString; + } + + public String getErrorString() { + return errorString; + } + + public void setJobId(String jobId) { + this.jobId = jobId; + } + + public String getJobId() { + return jobId; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof TemplateDataStoreVO) { + TemplateDataStoreVO other = (TemplateDataStoreVO) obj; + return (this.templateId == other.getTemplateId() && this.dataStoreId == other.getDataStoreId()); + } + return false; + } + + @Override + public int hashCode() { + Long tid = new Long(templateId); + Long hid = new Long(dataStoreId); + return tid.hashCode() + hid.hashCode(); + } + + public void setSize(Long size) { + this.size = size; + } + + public long getSize() { + return size; + } + + public void setPhysicalSize(long physicalSize) { + this.physicalSize = physicalSize; + } + + public long getPhysicalSize() { + return physicalSize; + } + + public void setDestroyed(boolean destroyed) { + this.destroyed = destroyed; + } + + public boolean getDestroyed() { + return destroyed; + } + + public void setDownloadUrl(String downloadUrl) { + this.downloadUrl = downloadUrl; + } + + public String getDownloadUrl() { + return downloadUrl; + } + + public void setCopy(boolean isCopy) { + this.isCopy = isCopy; + } + + public boolean isCopy() { + return isCopy; + } + + public long getTemplateSize() { + return -1; + } + + @Override + public String toString() { + return new StringBuilder("TmplHost[").append(id).append("-").append(templateId).append("-").append(dataStoreId) + .append(installPath).append("]").toString(); + } + + @Override + public ObjectInDataStoreStateMachine.State getState() { + // TODO Auto-generated method stub + return this.state; + } + + public void setState(ObjectInDataStoreStateMachine.State state) { + this.state = state; + } + + public long getUpdatedCount() { + return this.updatedCount; + } + + public void incrUpdatedCount() { + this.updatedCount++; + } + + public void decrUpdatedCount() { + this.updatedCount--; + } + + public Date getUpdated() { + return updated; + } + + @Override + public long getObjectId() { + return this.getTemplateId(); + } + + @Override + public State getObjectInStoreState() { + return this.state; + } + + public DataStoreRole getDataStoreRole() { + return dataStoreRole; + } + + public void setDataStoreRole(DataStoreRole dataStoreRole) { + this.dataStoreRole = dataStoreRole; + } + + public Long getRefCnt() { + return refCnt; + } + + public void incrRefCnt() { + this.refCnt++; + } + + public void decrRefCnt() { + this.refCnt--; + } + +} diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreDao.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreDao.java new file mode 100644 index 00000000000..4152516bcf0 --- /dev/null +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreDao.java @@ -0,0 +1,41 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +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 VolumeDataStoreDao extends GenericDao, + StateDao { + + List listByStoreId(long id); + + void deletePrimaryRecordsForStore(long id); + + VolumeDataStoreVO findByVolume(long volumeId); + + VolumeDataStoreVO findByStoreVolume(long storeId, long volumeId); + + VolumeDataStoreVO findByStoreVolume(long storeId, long volumeId, boolean lock); + + List listDestroyed(long storeId); +} 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 new file mode 100755 index 00000000000..222447fa4a5 --- /dev/null +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreVO.java @@ -0,0 +1,348 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.datastore.db; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State; + +import com.cloud.storage.Storage; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.fsm.StateObject; + +/** + * Join table for image_data_store and volumes + * + */ +@Entity +@Table(name = "volume_store_ref") +public class VolumeDataStoreVO implements StateObject, DataObjectInStore { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + Long id; + + @Column(name = "store_id") + private long dataStoreId; + + @Column(name = "volume_id") + private long volumeId; + + @Column(name = "zone_id") + private long zoneId; + + @Column(name = GenericDaoBase.CREATED_COLUMN) + private Date created = null; + + @Column(name = "last_updated") + @Temporal(value = TemporalType.TIMESTAMP) + private Date lastUpdated = null; + + @Column(name = "download_pct") + private int downloadPercent; + + @Column(name = "size") + private long size; + + @Column(name = "physical_size") + private long physicalSize; + + @Column(name = "download_state") + @Enumerated(EnumType.STRING) + private Status downloadState; + + @Column(name = "checksum") + private String checksum; + + @Column(name = "local_path") + private String localDownloadPath; + + @Column(name = "error_str") + private String errorString; + + @Column(name = "job_id") + private String jobId; + + @Column(name = "install_path") + private String installPath; + + @Column(name = "url") + private String downloadUrl; + + @Column(name = "destroyed") + boolean destroyed = false; + + @Column(name = "update_count", updatable = true, nullable = false) + protected long updatedCount; + + @Column(name = "updated") + @Temporal(value = TemporalType.TIMESTAMP) + Date updated; + + @Column(name = "state") + @Enumerated(EnumType.STRING) + ObjectInDataStoreStateMachine.State state; + + @Column(name = "ref_cnt") + Long refCnt; + + public String getInstallPath() { + return installPath; + } + + @Override + public long getDataStoreId() { + return dataStoreId; + } + + public void setDataStoreId(long storeId) { + this.dataStoreId = storeId; + } + + public long getVolumeId() { + return volumeId; + } + + public void setVolumeId(long volumeId) { + this.volumeId = volumeId; + } + + public long getZoneId() { + return zoneId; + } + + public void setZoneId(long zoneId) { + this.zoneId = zoneId; + } + + public int getDownloadPercent() { + return downloadPercent; + } + + public void setDownloadPercent(int downloadPercent) { + this.downloadPercent = downloadPercent; + } + + public void setDownloadState(Status downloadState) { + this.downloadState = downloadState; + } + + public long getId() { + return id; + } + + public Date getCreated() { + return created; + } + + public Date getLastUpdated() { + return lastUpdated; + } + + public void setLastUpdated(Date date) { + lastUpdated = date; + } + + public void setInstallPath(String installPath) { + this.installPath = installPath; + } + + public Status getDownloadState() { + return downloadState; + } + + public String getChecksum() { + return checksum; + } + + public void setChecksum(String checksum) { + this.checksum = checksum; + } + + public VolumeDataStoreVO(long hostId, long volumeId) { + super(); + this.dataStoreId = hostId; + this.volumeId = volumeId; + this.state = ObjectInDataStoreStateMachine.State.Allocated; + this.refCnt = 0L; + } + + public VolumeDataStoreVO(long hostId, long volumeId, Date lastUpdated, int downloadPercent, Status downloadState, + String localDownloadPath, String errorString, String jobId, String installPath, String downloadUrl, + String checksum) { + // super(); + this.dataStoreId = hostId; + this.volumeId = volumeId; + // this.zoneId = zoneId; + this.lastUpdated = lastUpdated; + this.downloadPercent = downloadPercent; + this.downloadState = downloadState; + this.localDownloadPath = localDownloadPath; + this.errorString = errorString; + this.jobId = jobId; + this.installPath = installPath; + this.setDownloadUrl(downloadUrl); + this.checksum = checksum; + this.refCnt = 0L; + } + + public VolumeDataStoreVO() { + this.refCnt = 0L; + } + + public void setLocalDownloadPath(String localPath) { + this.localDownloadPath = localPath; + } + + public String getLocalDownloadPath() { + return localDownloadPath; + } + + public void setErrorString(String errorString) { + this.errorString = errorString; + } + + public String getErrorString() { + return errorString; + } + + public void setJobId(String jobId) { + this.jobId = jobId; + } + + public String getJobId() { + return jobId; + } + + public boolean equals(Object obj) { + if (obj instanceof VolumeDataStoreVO) { + VolumeDataStoreVO other = (VolumeDataStoreVO) obj; + return (this.volumeId == other.getVolumeId() && this.dataStoreId == other.getDataStoreId()); + } + return false; + } + + public int hashCode() { + Long tid = new Long(volumeId); + Long hid = new Long(dataStoreId); + return tid.hashCode() + hid.hashCode(); + } + + public void setSize(long size) { + this.size = size; + } + + public long getSize() { + return size; + } + + public void setPhysicalSize(long physicalSize) { + this.physicalSize = physicalSize; + } + + public long getPhysicalSize() { + return physicalSize; + } + + public void setDestroyed(boolean destroyed) { + this.destroyed = destroyed; + } + + public boolean getDestroyed() { + return destroyed; + } + + public void setDownloadUrl(String downloadUrl) { + this.downloadUrl = downloadUrl; + } + + public String getDownloadUrl() { + return downloadUrl; + } + + public long getVolumeSize() { + return -1; + } + + public String toString() { + return new StringBuilder("VolumeHost[").append(id).append("-").append(volumeId).append("-").append(dataStoreId) + .append(installPath).append("]").toString(); + } + + public long getUpdatedCount() { + return this.updatedCount; + } + + public void incrUpdatedCount() { + this.updatedCount++; + } + + public void decrUpdatedCount() { + this.updatedCount--; + } + + public Date getUpdated() { + return updated; + } + + @Override + public ObjectInDataStoreStateMachine.State getState() { + // TODO Auto-generated method stub + return this.state; + } + + public void setState(ObjectInDataStoreStateMachine.State state) { + this.state = state; + } + + @Override + public long getObjectId() { + return this.getVolumeId(); + } + + @Override + public State getObjectInStoreState() { + return this.state; + } + + public Long getRefCnt() { + return refCnt; + } + + public void incrRefCnt() { + this.refCnt++; + } + + public void decrRefCnt() { + this.refCnt--; + } + +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageDataStore.java b/engine/api/src/org/apache/cloudstack/storage/image/datastore/ImageStoreEntity.java similarity index 81% rename from engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageDataStore.java rename to engine/api/src/org/apache/cloudstack/storage/image/datastore/ImageStoreEntity.java index ed2274e3d40..90deff96c92 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageDataStore.java +++ b/engine/api/src/org/apache/cloudstack/storage/image/datastore/ImageStoreEntity.java @@ -26,10 +26,21 @@ import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; -public interface ImageDataStore extends DataStore { +import com.cloud.storage.ImageStore; +import com.cloud.storage.Storage.ImageFormat; + +public interface ImageStoreEntity extends DataStore, ImageStore { TemplateInfo getTemplate(long templateId); + VolumeInfo getVolume(long volumeId); + SnapshotInfo getSnapshot(long snapshotId); + boolean exists(DataObject object); + Set listTemplates(); + + String getMountPoint(); // get the mount point on ssvm. + + String createEntityExtractUrl(String installPath, ImageFormat format); // get the entity download URL } diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageDataStoreInfo.java b/engine/api/src/org/apache/cloudstack/storage/image/datastore/ImageStoreInfo.java similarity index 88% rename from engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageDataStoreInfo.java rename to engine/api/src/org/apache/cloudstack/storage/image/datastore/ImageStoreInfo.java index b6b9a2a55d7..7261a15a486 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageDataStoreInfo.java +++ b/engine/api/src/org/apache/cloudstack/storage/image/datastore/ImageStoreInfo.java @@ -20,7 +20,8 @@ package org.apache.cloudstack.storage.image.datastore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -public interface ImageDataStoreInfo extends DataStore { - public long getImageDataStoreId(); - public String getType(); +public interface ImageStoreInfo extends DataStore { + long getImageStoreId(); + + String getType(); } diff --git a/engine/api/src/org/apache/cloudstack/storage/to/ImageStoreTO.java b/engine/api/src/org/apache/cloudstack/storage/to/ImageStoreTO.java new file mode 100644 index 00000000000..0037ea57242 --- /dev/null +++ b/engine/api/src/org/apache/cloudstack/storage/to/ImageStoreTO.java @@ -0,0 +1,79 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.to; + +import org.apache.cloudstack.storage.image.datastore.ImageStoreInfo; + +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.storage.DataStoreRole; + +public class ImageStoreTO implements DataStoreTO { + private String type; + private String uri; + private String providerName; + private DataStoreRole role; + + public ImageStoreTO() { + + } + + public ImageStoreTO(ImageStoreInfo dataStore) { + this.type = dataStore.getType(); + this.uri = dataStore.getUri(); + this.providerName = null; + this.role = dataStore.getRole(); + } + + public String getProtocol() { + return this.type; + } + + public String getUri() { + return this.uri; + } + + public String getProviderName() { + return providerName; + } + + public void setType(String type) { + this.type = type; + } + + public void setUri(String uri) { + this.uri = uri; + } + + public void setProviderName(String providerName) { + this.providerName = providerName; + } + + public void setRole(DataStoreRole role) { + this.role = role; + } + + @Override + public DataStoreRole getRole() { + return this.role; + } + + @Override + public String toString() { + return new StringBuilder("ImageStoreTO[type=").append(type).append("|provider=").append(providerName) + .append("|role=").append(role).append("|uri=").append(uri).append("]").toString(); + } +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java b/engine/api/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java similarity index 50% rename from engine/storage/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java rename to engine/api/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java index aa47e8f4977..5e870df3716 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java +++ b/engine/api/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java @@ -18,31 +18,86 @@ package org.apache.cloudstack.storage.to; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; -public class PrimaryDataStoreTO { +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.Storage.StoragePoolType; + +public class PrimaryDataStoreTO implements DataStoreTO { private final String uuid; private final String name; - private String type; + private String type; private final long id; + private StoragePoolType poolType; + private String host; + private String path; + private int port; + public PrimaryDataStoreTO(PrimaryDataStoreInfo dataStore) { this.uuid = dataStore.getUuid(); this.name = dataStore.getName(); - // this.type = dataStore.getType(); this.id = dataStore.getId(); + this.setPoolType(dataStore.getPoolType()); + this.setHost(dataStore.getHostAddress()); + this.setPath(dataStore.getPath()); + this.setPort(dataStore.getPort()); } - + public long getId() { return this.id; } - + public String getUuid() { return this.uuid; } - + public String getName() { return this.name; } - + public String getType() { return this.type; } + + @Override + public DataStoreRole getRole() { + return DataStoreRole.Primary; + } + + public StoragePoolType getPoolType() { + return poolType; + } + + public void setPoolType(StoragePoolType poolType) { + this.poolType = poolType; + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + @Override + public String toString() { + return new StringBuilder("PrimaryDataStoreTO[uuid=").append(uuid).append("|name=").append(name) + .append("|id=").append(id).append("|pooltype=").append(poolType).append("]").toString(); + } } diff --git a/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java b/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java new file mode 100644 index 00000000000..1115aece6ff --- /dev/null +++ b/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java @@ -0,0 +1,126 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.to; + +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; + +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.hypervisor.Hypervisor.HypervisorType; + +public class SnapshotObjectTO implements DataTO { + private String path; + private VolumeObjectTO volume; + private String parentSnapshotPath; + private DataStoreTO dataStore; + private String vmName; + private String name; + private HypervisorType hypervisorType; + private long id; + + public SnapshotObjectTO() { + + } + + public SnapshotObjectTO(SnapshotInfo snapshot) { + this.path = snapshot.getPath(); + this.setId(snapshot.getId()); + this.volume = (VolumeObjectTO) snapshot.getBaseVolume().getTO(); + this.setVmName(snapshot.getBaseVolume().getAttachedVmName()); + if (snapshot.getParent() != null) { + this.parentSnapshotPath = snapshot.getParent().getPath(); + } + this.dataStore = snapshot.getDataStore().getTO(); + this.setName(snapshot.getName()); + this.hypervisorType = snapshot.getHypervisorType(); + } + + @Override + public DataObjectType getObjectType() { + return DataObjectType.SNAPSHOT; + } + + @Override + public DataStoreTO getDataStore() { + return this.dataStore; + } + + @Override + public String getPath() { + return this.path; + } + + public void setPath(String path) { + this.path = path; + } + + public VolumeObjectTO getVolume() { + return volume; + } + + public void setVolume(VolumeObjectTO volume) { + this.volume = volume; + } + + public String getParentSnapshotPath() { + return parentSnapshotPath; + } + + public void setParentSnapshotPath(String parentSnapshotPath) { + this.parentSnapshotPath = parentSnapshotPath; + } + + public String getVmName() { + return vmName; + } + + public void setVmName(String vmName) { + this.vmName = vmName; + } + + @Override + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public HypervisorType getHypervisorType() { + return hypervisorType; + } + + public void setHypervisorType(HypervisorType hypervisorType) { + this.hypervisorType = hypervisorType; + } + + @Override + public String toString() { + return new StringBuilder("SnapshotTO[datastore=").append(dataStore).append("|volume=").append(volume).append("|path") + .append(path).append("]").toString(); + } +} diff --git a/engine/api/src/org/apache/cloudstack/storage/to/TemplateObjectTO.java b/engine/api/src/org/apache/cloudstack/storage/to/TemplateObjectTO.java new file mode 100644 index 00000000000..abe59eb2b4d --- /dev/null +++ b/engine/api/src/org/apache/cloudstack/storage/to/TemplateObjectTO.java @@ -0,0 +1,199 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.to; + +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; + +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.template.VirtualMachineTemplate; + +public class TemplateObjectTO implements DataTO { + private String path; + private String origUrl; + private String uuid; + private long id; + private ImageFormat format; + private long accountId; + private String checksum; + private boolean hvm; + private String displayText; + private DataStoreTO imageDataStore; + private String name; + private String guestOsType; + private Long size; + + public TemplateObjectTO() { + + } + + public TemplateObjectTO(VirtualMachineTemplate template) { + this.uuid = template.getUuid(); + this.id = template.getId(); + this.origUrl = template.getUrl(); + this.displayText = template.getDisplayText(); + this.checksum = template.getChecksum(); + this.hvm = template.isRequiresHvm(); + this.accountId = template.getAccountId(); + this.name = template.getUniqueName(); + this.format = template.getFormat(); + } + + public TemplateObjectTO(TemplateInfo template) { + this.path = template.getInstallPath(); + this.uuid = template.getUuid(); + this.id = template.getId(); + this.origUrl = template.getUrl(); + this.displayText = template.getDisplayText(); + this.checksum = template.getChecksum(); + this.hvm = template.isRequiresHvm(); + this.accountId = template.getAccountId(); + this.name = template.getUniqueName(); + this.format = template.getFormat(); + if (template.getDataStore() != null) { + this.imageDataStore = template.getDataStore().getTO(); + } + } + + @Override + public String getPath() { + return this.path; + } + + public String getUuid() { + return this.uuid; + } + + @Override + public long getId() { + return id; + } + + public void setId(long id){ + this.id = id; + } + + public ImageFormat getFormat() { + return format; + } + + public long getAccountId() { + return accountId; + } + + public String getChecksum() { + return checksum; + } + + public boolean isRequiresHvm() { + return hvm; + } + + public void setRequiresHvm(boolean hvm) { + this.hvm = hvm; + } + + public String getDescription() { + return displayText; + } + + public void setDescription(String desc) { + this.displayText = desc; + } + + + @Override + public DataObjectType getObjectType() { + return DataObjectType.TEMPLATE; + } + + @Override + public DataStoreTO getDataStore() { + return this.imageDataStore; + } + + public void setDataStore(DataStoreTO store){ + this.imageDataStore = store; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + public void setPath(String path) { + this.path = path; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public void setName(String name) { + this.name = name; + } + + public String getOrigUrl() { + return origUrl; + } + + public void setOrigUrl(String origUrl) { + this.origUrl = origUrl; + } + + public void setFormat(ImageFormat format) { + this.format = format; + } + + public void setAccountId(long accountId) { + this.accountId = accountId; + } + + public void setChecksum(String checksum) { + this.checksum = checksum; + } + + public void setImageDataStore(DataStoreTO imageDataStore) { + this.imageDataStore = imageDataStore; + } + + public String getGuestOsType() { + return guestOsType; + } + + public void setGuestOsType(String guestOsType) { + this.guestOsType = guestOsType; + } + + public Long getSize() { + return size; + } + + public void setSize(Long size) { + this.size = size; + } + + @Override + public String toString() { + return new StringBuilder("TemplateTO[id=").append(id).append("|origUrl=").append(origUrl) + .append("|name").append(name).append("]").toString(); + } +} diff --git a/engine/api/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java b/engine/api/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java new file mode 100644 index 00000000000..ab3d5ea14d3 --- /dev/null +++ b/engine/api/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java @@ -0,0 +1,215 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.to; + +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; + +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.storage.Storage; +import com.cloud.storage.Volume; + +public class VolumeObjectTO implements DataTO { + private String uuid; + private Volume.Type volumeType; + private DataStoreTO dataStore; + private String name; + private long size; + private String path; + private Long volumeId; + private String vmName; + private long accountId; + private String chainInfo; + private Storage.ImageFormat format; + private long id; + private Long bytesReadRate; + private Long bytesWriteRate; + private Long iopsReadRate; + private Long iopsWriteRate; + + public VolumeObjectTO() { + + } + + public VolumeObjectTO(VolumeInfo volume) { + this.uuid = volume.getUuid(); + this.path = volume.getPath(); + this.accountId = volume.getAccountId(); + if (volume.getDataStore() != null) { + this.dataStore = volume.getDataStore().getTO(); + } else { + this.dataStore = null; + } + this.vmName = volume.getAttachedVmName(); + this.size = volume.getSize(); + this.setVolumeId(volume.getId()); + this.chainInfo = volume.getChainInfo(); + this.volumeType = volume.getVolumeType(); + this.name = volume.getName(); + this.setId(volume.getId()); + this.format = volume.getFormat(); + this.bytesReadRate = volume.getBytesReadRate(); + this.bytesWriteRate = volume.getBytesWriteRate(); + this.iopsReadRate = volume.getIopsReadRate(); + this.iopsWriteRate = volume.getIopsWriteRate(); + } + + public String getUuid() { + return this.uuid; + } + + @Override + public String getPath() { + return this.path; + } + + public Volume.Type getVolumeType() { + return this.volumeType; + } + + @Override + public DataStoreTO getDataStore() { + return this.dataStore; + } + + + public void setDataStore(DataStoreTO store){ + this.dataStore = store; + } + + public void setDataStore(PrimaryDataStoreTO dataStore) { + this.dataStore = dataStore; + } + + public String getName() { + return this.name; + } + + public long getSize() { + return this.size; + } + + @Override + public DataObjectType getObjectType() { + return DataObjectType.VOLUME; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public void setName(String name) { + this.name = name; + } + + public void setSize(long size) { + this.size = size; + } + + public void setPath(String path) { + this.path = path; + } + + public Long getVolumeId() { + return volumeId; + } + + public void setVolumeId(Long volumeId) { + this.volumeId = volumeId; + } + + public long getAccountId() { + return accountId; + } + + public void setAccountId(long accountId) { + this.accountId = accountId; + } + + public String getVmName() { + return vmName; + } + + public void setVmName(String vmName) { + this.vmName = vmName; + } + + public String getChainInfo() { + return chainInfo; + } + + public void setChainInfo(String chainInfo) { + this.chainInfo = chainInfo; + } + + @Override + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public Storage.ImageFormat getFormat() { + return format; + } + + public void setFormat(Storage.ImageFormat format) { + this.format = format; + } + + @Override + public String toString() { + return new StringBuilder("volumeTO[uuid=").append(uuid).append("|path=").append(path) + .append("|datastore=").append(dataStore).append("]").toString(); + } + + public void setBytesReadRate(Long bytesReadRate) { + this.bytesReadRate = bytesReadRate; + } + + public Long getBytesReadRate() { + return bytesReadRate; + } + + public void setBytesWriteRate(Long bytesWriteRate) { + this.bytesWriteRate = bytesWriteRate; + } + + public Long getBytesWriteRate() { + return bytesWriteRate; + } + + public void setIopsReadRate(Long iopsReadRate) { + this.iopsReadRate = iopsReadRate; + } + + public Long getIopsReadRate() { + return iopsReadRate; + } + + public void setIopsWriteRate(Long iopsWriteRate) { + this.iopsWriteRate = iopsWriteRate; + } + + public Long getIopsWriteRate() { + return iopsWriteRate; + } + +} diff --git a/engine/api/test/org/apache/cloudstack/engine/subsystem/api/storage/ScopeTest.java b/engine/api/test/org/apache/cloudstack/engine/subsystem/api/storage/ScopeTest.java index e3ec48c74f0..4b6b361ba07 100644 --- a/engine/api/test/org/apache/cloudstack/engine/subsystem/api/storage/ScopeTest.java +++ b/engine/api/test/org/apache/cloudstack/engine/subsystem/api/storage/ScopeTest.java @@ -30,28 +30,28 @@ public class ScopeTest { ZoneScope zoneScope = new ZoneScope(1L); ZoneScope zoneScope2 = new ZoneScope(1L); Assert.assertTrue(zoneScope.isSameScope(zoneScope2)); - + ZoneScope zoneScope3 = new ZoneScope(2L); Assert.assertFalse(zoneScope.isSameScope(zoneScope3)); } - + @Test public void testClusterScope() { ClusterScope clusterScope = new ClusterScope(1L, 1L, 1L); ClusterScope clusterScope2 = new ClusterScope(1L, 1L, 1L); - + Assert.assertTrue(clusterScope.isSameScope(clusterScope2)); - + ClusterScope clusterScope3 = new ClusterScope(2L, 2L, 1L); Assert.assertFalse(clusterScope.isSameScope(clusterScope3)); } - + @Test public void testHostScope() { - HostScope hostScope = new HostScope(1L); - HostScope hostScope2 = new HostScope(1L); - HostScope hostScope3 = new HostScope(2L); - + HostScope hostScope = new HostScope(1L, 1L); + HostScope hostScope2 = new HostScope(1L, 1L); + HostScope hostScope3 = new HostScope(2L, 1L); + Assert.assertTrue(hostScope.isSameScope(hostScope2)); Assert.assertFalse(hostScope.isSameScope(hostScope3)); } diff --git a/engine/pom.xml b/engine/pom.xml index 169425ae14e..3d305bc5c40 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -37,13 +37,25 @@ storage storage/volume storage/image - storage/imagemotion - storage/backup + storage/datamotion + storage/cache storage/snapshot - storage/integration-test components-api schema network service + + + integration-test + + + nonoss + + + + storage/integration-test + + + diff --git a/engine/schema/src/com/cloud/storage/DiskOfferingVO.java b/engine/schema/src/com/cloud/storage/DiskOfferingVO.java index 44f9e8f7b1c..b7363e7208a 100755 --- a/engine/schema/src/com/cloud/storage/DiskOfferingVO.java +++ b/engine/schema/src/com/cloud/storage/DiskOfferingVO.java @@ -34,70 +34,67 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; import javax.persistence.Transient; -import org.apache.cloudstack.api.Identity; import com.cloud.offering.DiskOffering; import com.cloud.utils.db.GenericDao; -import org.apache.cloudstack.api.InternalIdentity; @Entity -@Table(name="disk_offering") -@Inheritance(strategy=InheritanceType.JOINED) -@DiscriminatorColumn(name="type", discriminatorType=DiscriminatorType.STRING, length=32) +@Table(name = "disk_offering") +@Inheritance(strategy = InheritanceType.JOINED) +@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING, length = 32) public class DiskOfferingVO implements DiskOffering { public enum Type { - Disk, - Service + Disk, Service }; @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - @Column(name="id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") long id; - @Column(name="domain_id") + @Column(name = "domain_id") Long domainId; - @Column(name="unique_name") + @Column(name = "unique_name") private String uniqueName; - @Column(name="name") + @Column(name = "name") private String name = null; - @Column(name="display_text", length=4096) + @Column(name = "display_text", length = 4096) private String displayText = null; - @Column(name="disk_size") + @Column(name = "disk_size") long diskSize; - @Column(name="tags", length=4096) + @Column(name = "tags", length = 4096) String tags; - @Column(name="type") + @Column(name = "type") Type type; - @Column(name=GenericDao.REMOVED) + @Column(name = GenericDao.REMOVED) @Temporal(TemporalType.TIMESTAMP) private Date removed; - @Column(name=GenericDao.CREATED_COLUMN) + @Column(name = GenericDao.CREATED_COLUMN) private Date created; - @Column(name="recreatable") + @Column(name = "recreatable") private boolean recreatable; - @Column(name="use_local_storage") + @Column(name = "use_local_storage") private boolean useLocalStorage; - @Column(name="system_use") + @Column(name = "system_use") private boolean systemUse; - @Column(name="customized") + @Column(name = "customized") private boolean customized; - @Column(name="uuid") + @Column(name = "uuid") private String uuid; - @Column(name="sort_key") + @Column(name = "sort_key") int sortKey; @Column(name="bytes_read_rate") @@ -116,10 +113,11 @@ public class DiskOfferingVO implements DiskOffering { boolean displayOffering; public DiskOfferingVO() { - this.uuid = UUID.randomUUID().toString(); + this.uuid = UUID.randomUUID().toString(); } - public DiskOfferingVO(Long domainId, String name, String displayText, long diskSize, String tags, boolean isCustomized) { + public DiskOfferingVO(Long domainId, String name, String displayText, long diskSize, String tags, + boolean isCustomized) { this.domainId = domainId; this.name = name; this.displayText = displayText; @@ -129,10 +127,11 @@ public class DiskOfferingVO implements DiskOffering { this.type = Type.Disk; this.useLocalStorage = false; this.customized = isCustomized; - this.uuid = UUID.randomUUID().toString(); + this.uuid = UUID.randomUUID().toString(); } - public DiskOfferingVO(String name, String displayText, boolean mirrored, String tags, boolean recreatable, boolean useLocalStorage, boolean systemUse, boolean customized) { + public DiskOfferingVO(String name, String displayText, boolean mirrored, String tags, boolean recreatable, + boolean useLocalStorage, boolean systemUse, boolean customized) { this.domainId = null; this.type = Type.Service; this.name = name; @@ -142,11 +141,13 @@ public class DiskOfferingVO implements DiskOffering { this.useLocalStorage = useLocalStorage; this.systemUse = systemUse; this.customized = customized; - this.uuid = UUID.randomUUID().toString(); + this.uuid = UUID.randomUUID().toString(); } - //domain specific offerings constructor (null domainId implies public offering) - public DiskOfferingVO(String name, String displayText, boolean mirrored, String tags, boolean recreatable, boolean useLocalStorage, boolean systemUse, boolean customized, Long domainId) { + // domain specific offerings constructor (null domainId implies public + // offering) + public DiskOfferingVO(String name, String displayText, boolean mirrored, String tags, boolean recreatable, + boolean useLocalStorage, boolean systemUse, boolean customized, Long domainId) { this.type = Type.Service; this.name = name; this.displayText = displayText; @@ -156,7 +157,7 @@ public class DiskOfferingVO implements DiskOffering { this.systemUse = systemUse; this.customized = customized; this.domainId = domainId; - this.uuid = UUID.randomUUID().toString(); + this.uuid = UUID.randomUUID().toString(); } @Override @@ -166,14 +167,14 @@ public class DiskOfferingVO implements DiskOffering { @Override public boolean isCustomized() { - return customized; - } + return customized; + } - public void setCustomized(boolean customized) { - this.customized = customized; - } + public void setCustomized(boolean customized) { + this.customized = customized; + } - @Override + @Override public String getUniqueName() { return uniqueName; } @@ -209,7 +210,6 @@ public class DiskOfferingVO implements DiskOffering { this.name = name; } - @Override public boolean getSystemUse() { return systemUse; @@ -223,13 +223,14 @@ public class DiskOfferingVO implements DiskOffering { public String getDisplayText() { return displayText; } + public void setDisplayText(String displayText) { this.displayText = displayText; } @Override - public long getDiskSize(){ - return diskSize; + public long getDiskSize() { + return diskSize; } @Override @@ -241,10 +242,10 @@ public class DiskOfferingVO implements DiskOffering { return removed; } - @Override + @Override public Date getCreated() { - return created; - } + return created; + } protected void setTags(String tags) { this.tags = tags; @@ -302,9 +303,9 @@ public class DiskOfferingVO implements DiskOffering { setTags(buf.toString()); } - public void setUseLocalStorage(boolean useLocalStorage) { - this.useLocalStorage = useLocalStorage; - } + public void setUseLocalStorage(boolean useLocalStorage) { + this.useLocalStorage = useLocalStorage; + } public void setRemoved(Date removed) { this.removed = removed; @@ -312,25 +313,24 @@ public class DiskOfferingVO implements DiskOffering { @Override public String getUuid() { - return this.uuid; + return this.uuid; } public void setUuid(String uuid) { - this.uuid = uuid; + this.uuid = uuid; } public void setSortKey(int key) { - sortKey = key; + sortKey = key; } public int getSortKey() { - return sortKey; - } - - public void setRecreatable(boolean recreatable) { - this.recreatable = recreatable; + return sortKey; } + public void setRecreatable(boolean recreatable) { + this.recreatable = recreatable; + } public boolean getDisplayOffering() { return displayOffering; diff --git a/engine/schema/src/com/cloud/storage/GuestOSCategoryVO.java b/engine/schema/src/com/cloud/storage/GuestOSCategoryVO.java index 03a74793001..36773e351e3 100644 --- a/engine/schema/src/com/cloud/storage/GuestOSCategoryVO.java +++ b/engine/schema/src/com/cloud/storage/GuestOSCategoryVO.java @@ -25,44 +25,41 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.api.Identity; -import org.apache.cloudstack.api.InternalIdentity; - @Entity -@Table(name="guest_os_category") +@Table(name = "guest_os_category") public class GuestOSCategoryVO implements GuestOsCategory { @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - @Column(name="id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") long id; - @Column(name="name") + @Column(name = "name") String name; - @Column(name="uuid") + @Column(name = "uuid") String uuid = UUID.randomUUID().toString(); @Override public long getId() { - return id; + return id; } @Override public String getName() { - return name; + return name; } @Override public void setName(String name) { - this.name = name; + this.name = name; } @Override public String getUuid() { - return this.uuid; + return this.uuid; } public void setUuid(String uuid) { - this.uuid = uuid; + this.uuid = uuid; } } diff --git a/engine/schema/src/com/cloud/storage/GuestOSVO.java b/engine/schema/src/com/cloud/storage/GuestOSVO.java index 49e136d03c1..f34d831d7a5 100644 --- a/engine/schema/src/com/cloud/storage/GuestOSVO.java +++ b/engine/schema/src/com/cloud/storage/GuestOSVO.java @@ -25,66 +25,63 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.api.Identity; -import org.apache.cloudstack.api.InternalIdentity; - @Entity -@Table(name="guest_os") +@Table(name = "guest_os") public class GuestOSVO implements GuestOS { @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - @Column(name="id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") long id; - @Column(name="category_id") + @Column(name = "category_id") private long categoryId; - @Column(name="name") + @Column(name = "name") String name; - @Column(name="display_name") + @Column(name = "display_name") String displayName; - @Column(name="uuid") + @Column(name = "uuid") String uuid = UUID.randomUUID().toString(); @Override public long getId() { - return id; + return id; } public long getCategoryId() { - return categoryId; + return categoryId; } public void setCategoryId(long categoryId) { - this.categoryId = categoryId; + this.categoryId = categoryId; } @Override public String getName() { - return name; + return name; } public void setName(String name) { - this.name = name; + this.name = name; } @Override public String getDisplayName() { - return displayName; + return displayName; } public void setDisplayName(String displayName) { - this.displayName = displayName; + this.displayName = displayName; } @Override public String getUuid() { - return this.uuid; + return this.uuid; } public void setUuid(String uuid) { - this.uuid = uuid; + this.uuid = uuid; } } diff --git a/engine/schema/src/com/cloud/storage/LaunchPermissionVO.java b/engine/schema/src/com/cloud/storage/LaunchPermissionVO.java index 992bac2365e..9082debbd51 100644 --- a/engine/schema/src/com/cloud/storage/LaunchPermissionVO.java +++ b/engine/schema/src/com/cloud/storage/LaunchPermissionVO.java @@ -24,19 +24,20 @@ import javax.persistence.Id; import javax.persistence.Table; @Entity -@Table(name="launch_permission") +@Table(name = "launch_permission") public class LaunchPermissionVO implements InternalIdentity { @Id - @Column(name="id") + @Column(name = "id") private Long id; - @Column(name="template_id") + @Column(name = "template_id") private long templateId; - @Column(name="account_id") + @Column(name = "account_id") private long accountId; - public LaunchPermissionVO() { } + public LaunchPermissionVO() { + } public LaunchPermissionVO(long templateId, long accountId) { this.templateId = templateId; diff --git a/engine/schema/src/com/cloud/storage/S3VO.java b/engine/schema/src/com/cloud/storage/S3VO.java index ec49bc92d74..e30da0cbc2d 100644 --- a/engine/schema/src/com/cloud/storage/S3VO.java +++ b/engine/schema/src/com/cloud/storage/S3VO.java @@ -18,10 +18,7 @@ */ package com.cloud.storage; -import com.cloud.agent.api.to.S3TO; -import com.cloud.utils.db.GenericDao; -import org.apache.cloudstack.api.Identity; -import org.apache.cloudstack.api.InternalIdentity; +import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; @@ -29,8 +26,11 @@ import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; -import java.util.Date; +import com.cloud.agent.api.to.S3TO; +import com.cloud.utils.db.GenericDao; + +//TODO: this will be removed after object_store merge. @Entity @Table(name = "s3") public class S3VO implements S3 { @@ -76,11 +76,9 @@ public class S3VO implements S3 { super(); } - public S3VO(final String uuid, final String accessKey, - final String secretKey, final String endPoint, - final String bucketName, final Boolean httpsFlag, - final Integer connectionTimeout, final Integer maxErrorRetry, - final Integer socketTimeout, final Date created) { + public S3VO(final String uuid, final String accessKey, final String secretKey, final String endPoint, + final String bucketName, final Boolean httpsFlag, final Integer connectionTimeout, + final Integer maxErrorRetry, final Integer socketTimeout, final Date created) { super(); @@ -111,10 +109,8 @@ public class S3VO implements S3 { httpsFlag = this.httpsFlag == 0 ? false : true; } - return new S3TO(this.id, this.uuid, this.accessKey, this.secretKey, - this.endPoint, this.bucketName, httpsFlag, - this.connectionTimeout, this.maxErrorRetry, this.socketTimeout, - this.created); + return new S3TO(this.id, this.uuid, this.accessKey, this.secretKey, this.endPoint, this.bucketName, httpsFlag, + this.connectionTimeout, this.maxErrorRetry, this.socketTimeout, this.created, false); } diff --git a/engine/schema/src/com/cloud/storage/SnapshotPolicyVO.java b/engine/schema/src/com/cloud/storage/SnapshotPolicyVO.java index 4eb4916afd3..fc6283d177f 100644 --- a/engine/schema/src/com/cloud/storage/SnapshotPolicyVO.java +++ b/engine/schema/src/com/cloud/storage/SnapshotPolicyVO.java @@ -25,53 +25,51 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.api.Identity; import com.cloud.storage.snapshot.SnapshotPolicy; import com.cloud.utils.DateUtil.IntervalType; -import org.apache.cloudstack.api.InternalIdentity; @Entity -@Table(name="snapshot_policy") +@Table(name = "snapshot_policy") public class SnapshotPolicyVO implements SnapshotPolicy { @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - @Column(name="id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") long id; - @Column(name="volume_id") + @Column(name = "volume_id") long volumeId; - @Column(name="schedule") + @Column(name = "schedule") String schedule; - @Column(name="timezone") + @Column(name = "timezone") String timezone; - @Column(name="interval") + @Column(name = "interval") private short interval; - @Column(name="max_snaps") + @Column(name = "max_snaps") private int maxSnaps; - @Column(name="active") + @Column(name = "active") boolean active = false; - @Column(name="uuid") + @Column(name = "uuid") String uuid; public SnapshotPolicyVO() { - this.uuid = UUID.randomUUID().toString(); + this.uuid = UUID.randomUUID().toString(); } public SnapshotPolicyVO(long volumeId, String schedule, String timezone, IntervalType intvType, int maxSnaps) { - this.volumeId = volumeId; + this.volumeId = volumeId; this.schedule = schedule; this.timezone = timezone; - this.interval = (short)intvType.ordinal(); + this.interval = (short) intvType.ordinal(); this.maxSnaps = maxSnaps; this.active = true; - this.uuid = UUID.randomUUID().toString(); + this.uuid = UUID.randomUUID().toString(); } public long getId() { @@ -79,10 +77,10 @@ public class SnapshotPolicyVO implements SnapshotPolicy { } public long getVolumeId() { - return volumeId; - } + return volumeId; + } - public void setSchedule(String schedule) { + public void setSchedule(String schedule) { this.schedule = schedule; } @@ -124,10 +122,10 @@ public class SnapshotPolicyVO implements SnapshotPolicy { @Override public String getUuid() { - return this.uuid; + return this.uuid; } public void setUuid(String uuid) { - this.uuid = uuid; + this.uuid = uuid; } } diff --git a/engine/schema/src/com/cloud/storage/SnapshotScheduleVO.java b/engine/schema/src/com/cloud/storage/SnapshotScheduleVO.java index 75757c6b22b..7adc136066f 100644 --- a/engine/schema/src/com/cloud/storage/SnapshotScheduleVO.java +++ b/engine/schema/src/com/cloud/storage/SnapshotScheduleVO.java @@ -28,40 +28,40 @@ import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; -import org.apache.cloudstack.api.Identity; import com.cloud.storage.snapshot.SnapshotSchedule; -import org.apache.cloudstack.api.InternalIdentity; @Entity -@Table(name="snapshot_schedule") +@Table(name = "snapshot_schedule") public class SnapshotScheduleVO implements SnapshotSchedule { @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - @Column(name="id") - long id; + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + long id; - // DB constraint: For a given volume and policyId, there will only be one entry in this table. - @Column(name="volume_id") + // DB constraint: For a given volume and policyId, there will only be one + // entry in this table. + @Column(name = "volume_id") long volumeId; - @Column(name="policy_id") + @Column(name = "policy_id") long policyId; - @Column(name="scheduled_timestamp") - @Temporal(value=TemporalType.TIMESTAMP) + @Column(name = "scheduled_timestamp") + @Temporal(value = TemporalType.TIMESTAMP) Date scheduledTimestamp; - @Column(name="async_job_id") + @Column(name = "async_job_id") Long asyncJobId; - @Column(name="snapshot_id") + @Column(name = "snapshot_id") Long snapshotId; - @Column(name="uuid") + @Column(name = "uuid") String uuid = UUID.randomUUID().toString(); - public SnapshotScheduleVO() { } + public SnapshotScheduleVO() { + } public SnapshotScheduleVO(long volumeId, long policyId, Date scheduledTimestamp) { this.volumeId = volumeId; @@ -83,43 +83,43 @@ public class SnapshotScheduleVO implements SnapshotSchedule { return policyId; } - public void setPolicyId(long policyId) { + public void setPolicyId(long policyId) { this.policyId = policyId; } /** - * @return the scheduledTimestamp - */ - public Date getScheduledTimestamp() { - return scheduledTimestamp; - } + * @return the scheduledTimestamp + */ + public Date getScheduledTimestamp() { + return scheduledTimestamp; + } - public void setScheduledTimestamp(Date scheduledTimestamp) { + public void setScheduledTimestamp(Date scheduledTimestamp) { this.scheduledTimestamp = scheduledTimestamp; } public Long getAsyncJobId() { - return asyncJobId; - } + return asyncJobId; + } - public void setAsyncJobId(Long asyncJobId) { - this.asyncJobId = asyncJobId; - } + public void setAsyncJobId(Long asyncJobId) { + this.asyncJobId = asyncJobId; + } - public Long getSnapshotId() { - return snapshotId; - } + public Long getSnapshotId() { + return snapshotId; + } - public void setSnapshotId(Long snapshotId) { - this.snapshotId = snapshotId; - } + public void setSnapshotId(Long snapshotId) { + this.snapshotId = snapshotId; + } - @Override - public String getUuid() { - return this.uuid; - } + @Override + public String getUuid() { + return this.uuid; + } - public void setUuid(String uuid) { - this.uuid = uuid; - } + public void setUuid(String uuid) { + this.uuid = uuid; + } } diff --git a/engine/schema/src/com/cloud/storage/SnapshotVO.java b/engine/schema/src/com/cloud/storage/SnapshotVO.java index 78b96ec9779..e3912740a48 100644 --- a/engine/schema/src/com/cloud/storage/SnapshotVO.java +++ b/engine/schema/src/com/cloud/storage/SnapshotVO.java @@ -25,100 +25,80 @@ import java.util.Date; import java.util.UUID; @Entity -@Table(name="snapshots") +@Table(name = "snapshots") public class SnapshotVO implements Snapshot { @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - @Column(name="id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") private long id; - @Column(name="data_center_id") + @Column(name = "data_center_id") long dataCenterId; - @Column(name="account_id") + @Column(name = "account_id") long accountId; - @Column(name="domain_id") + @Column(name = "domain_id") long domainId; - @Column(name="volume_id") + @Column(name = "volume_id") Long volumeId; - @Column(name="disk_offering_id") + @Column(name = "disk_offering_id") Long diskOfferingId; @Expose - @Column(name="path") - String path; - - @Expose - @Column(name="name") + @Column(name = "name") String name; @Expose - @Column(name="status", updatable = true, nullable=false) - @Enumerated(value=EnumType.STRING) + @Column(name = "status", updatable = true, nullable = false) + @Enumerated(value = EnumType.STRING) private State state; - @Column(name="snapshot_type") + @Column(name = "snapshot_type") short snapshotType; - @Column(name="type_description") + @Column(name = "type_description") String typeDescription; - @Column(name="size") + @Column(name = "size") long size; - @Column(name=GenericDao.CREATED_COLUMN) + @Column(name = GenericDao.CREATED_COLUMN) Date created; - @Column(name=GenericDao.REMOVED_COLUMN) + @Column(name = GenericDao.REMOVED_COLUMN) Date removed; - @Column(name="backup_snap_id") - String backupSnapshotId; - - @Column(name="swift_id") - Long swiftId; - - @Column(name="s3_id") - Long s3Id; - - @Column(name="sechost_id") - Long secHostId; - - @Column(name="prev_snap_id") - long prevSnapshotId; - - @Column(name="hypervisor_type") - @Enumerated(value=EnumType.STRING) - HypervisorType hypervisorType; + @Column(name = "hypervisor_type") + @Enumerated(value = EnumType.STRING) + HypervisorType hypervisorType; @Expose - @Column(name="version") + @Column(name = "version") String version; - @Column(name="uuid") + @Column(name = "uuid") String uuid; public SnapshotVO() { this.uuid = UUID.randomUUID().toString(); } - public SnapshotVO(long dcId, long accountId, long domainId, Long volumeId, Long diskOfferingId, String path, String name, short snapshotType, String typeDescription, long size, HypervisorType hypervisorType ) { + public SnapshotVO(long dcId, long accountId, long domainId, Long volumeId, Long diskOfferingId, String name, + short snapshotType, String typeDescription, long size, HypervisorType hypervisorType) { this.dataCenterId = dcId; this.accountId = accountId; this.domainId = domainId; this.volumeId = volumeId; this.diskOfferingId = diskOfferingId; - this.path = path; this.name = name; this.snapshotType = snapshotType; this.typeDescription = typeDescription; this.size = size; this.state = State.Allocated; - this.prevSnapshotId = 0; this.hypervisorType = hypervisorType; this.version = "2.2"; this.uuid = UUID.randomUUID().toString(); @@ -156,19 +136,11 @@ public class SnapshotVO implements Snapshot { this.volumeId = volumeId; } - @Override - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - @Override public String getName() { return name; } + @Override public short getsnapshotType() { return snapshotType; @@ -182,22 +154,6 @@ public class SnapshotVO implements Snapshot { return Type.values()[snapshotType]; } - public Long getSwiftId() { - return swiftId; - } - - public void setSwiftId(Long swiftId) { - this.swiftId = swiftId; - } - - public Long getSecHostId() { - return secHostId; - } - - public void setSecHostId(Long secHostId) { - this.secHostId = secHostId; - } - @Override public HypervisorType getHypervisorType() { return hypervisorType; @@ -208,8 +164,8 @@ public class SnapshotVO implements Snapshot { } @Override - public boolean isRecursive(){ - if ( snapshotType >= Type.HOURLY.ordinal() && snapshotType <= Type.MONTHLY.ordinal() ) { + public boolean isRecursive() { + if (snapshotType >= Type.HOURLY.ordinal() && snapshotType <= Type.MONTHLY.ordinal()) { return true; } return false; @@ -222,6 +178,7 @@ public class SnapshotVO implements Snapshot { public String getTypeDescription() { return typeDescription; } + public void setTypeDescription(String typeDescription) { this.typeDescription = typeDescription; } @@ -248,30 +205,13 @@ public class SnapshotVO implements Snapshot { return state; } - - public void setState(State state) { + public void setState(State state) { this.state = state; } - public String getBackupSnapshotId(){ - return backupSnapshotId; - } - - public long getPrevSnapshotId(){ - return prevSnapshotId; - } - - public void setBackupSnapshotId(String backUpSnapshotId){ - this.backupSnapshotId = backUpSnapshotId; - } - - public void setPrevSnapshotId(long prevSnapshotId){ - this.prevSnapshotId = prevSnapshotId; - } - public static Type getSnapshotType(String snapshotType) { - for ( Type type : Type.values()) { - if ( type.equals(snapshotType)) { + for (Type type : Type.values()) { + if (type.equals(snapshotType)) { return type; } } @@ -286,13 +226,4 @@ public class SnapshotVO implements Snapshot { public void setUuid(String uuid) { this.uuid = uuid; } - - public Long getS3Id() { - return s3Id; - } - - public void setS3Id(Long s3Id) { - this.s3Id = s3Id; - } - } diff --git a/engine/schema/src/com/cloud/storage/StoragePoolHostAssoc.java b/engine/schema/src/com/cloud/storage/StoragePoolHostAssoc.java index 34326d963a6..1b20bf62c66 100644 --- a/engine/schema/src/com/cloud/storage/StoragePoolHostAssoc.java +++ b/engine/schema/src/com/cloud/storage/StoragePoolHostAssoc.java @@ -21,15 +21,15 @@ import org.apache.cloudstack.api.InternalIdentity; import java.util.Date; public interface StoragePoolHostAssoc extends InternalIdentity { - - long getHostId(); - - long getPoolId(); - - String getLocalPath(); - Date getCreated(); + long getHostId(); - Date getLastUpdated(); + long getPoolId(); + + String getLocalPath(); + + Date getCreated(); + + Date getLastUpdated(); } diff --git a/engine/schema/src/com/cloud/storage/StoragePoolHostVO.java b/engine/schema/src/com/cloud/storage/StoragePoolHostVO.java index 1b02f6d9754..3b70984e63c 100644 --- a/engine/schema/src/com/cloud/storage/StoragePoolHostVO.java +++ b/engine/schema/src/com/cloud/storage/StoragePoolHostVO.java @@ -31,79 +31,73 @@ import com.cloud.utils.db.GenericDaoBase; /** * Join table for storage pools and hosts - * + * */ @Entity -@Table(name="storage_pool_host_ref") +@Table(name = "storage_pool_host_ref") public class StoragePoolHostVO implements StoragePoolHostAssoc { - @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - private Long id; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; - @Column(name="pool_id") - private long poolId; + @Column(name = "pool_id") + private long poolId; - @Column(name="host_id") - private long hostId; + @Column(name = "host_id") + private long hostId; - @Column(name="local_path") - private String localPath; + @Column(name = "local_path") + private String localPath; - @Column(name=GenericDaoBase.CREATED_COLUMN) + @Column(name = GenericDaoBase.CREATED_COLUMN) private Date created = null; - @Column(name="last_updated") - @Temporal(value=TemporalType.TIMESTAMP) + @Column(name = "last_updated") + @Temporal(value = TemporalType.TIMESTAMP) private Date lastUpdated = null; + public StoragePoolHostVO() { + super(); + } - public StoragePoolHostVO() { - super(); - } - - - public StoragePoolHostVO(long poolId, long hostId, String localPath) { - this.poolId = poolId; - this.hostId = hostId; - this.localPath = localPath; - } - - - @Override - public long getHostId() { - return hostId; - } + public StoragePoolHostVO(long poolId, long hostId, String localPath) { + this.poolId = poolId; + this.hostId = hostId; + this.localPath = localPath; + } + @Override + public long getHostId() { + return hostId; + } @Override public long getId() { return id; } + @Override + public String getLocalPath() { + return localPath; + } @Override - public String getLocalPath() { - return localPath; - } + public long getPoolId() { + return poolId; + } - @Override - public long getPoolId() { - return poolId; - } + @Override + public Date getCreated() { + return created; + } - @Override - public Date getCreated() { - return created; - } + @Override + public Date getLastUpdated() { + return lastUpdated; + } - @Override - public Date getLastUpdated() { - return lastUpdated; - } - - - public void setLocalPath(String localPath) { - this.localPath = localPath; - } + public void setLocalPath(String localPath) { + this.localPath = localPath; + } } diff --git a/engine/schema/src/com/cloud/storage/StoragePoolWorkVO.java b/engine/schema/src/com/cloud/storage/StoragePoolWorkVO.java index 440065da66b..56d57ec1e33 100644 --- a/engine/schema/src/com/cloud/storage/StoragePoolWorkVO.java +++ b/engine/schema/src/com/cloud/storage/StoragePoolWorkVO.java @@ -27,9 +27,9 @@ import javax.persistence.Id; import javax.persistence.Table; @Entity -@Table(name="storage_pool_work") +@Table(name = "storage_pool_work") public class StoragePoolWorkVO implements InternalIdentity { - + public long getId() { return id; } @@ -42,22 +42,18 @@ public class StoragePoolWorkVO implements InternalIdentity { return poolId; } - public void setPoolId(Long poolId) { this.poolId = poolId; } - public boolean isStoppedForMaintenance() { return stoppedForMaintenance; } - public void setStoppedForMaintenance(boolean stoppedForMaintenance) { this.stoppedForMaintenance = stoppedForMaintenance; } - public boolean isStartedAfterMaintenance() { return startedAfterMaintenance; } @@ -73,7 +69,7 @@ public class StoragePoolWorkVO implements InternalIdentity { public void setVmId(Long vmId) { this.vmId = vmId; } - + public Long getManagementServerId() { return managementServerId; } @@ -83,27 +79,27 @@ public class StoragePoolWorkVO implements InternalIdentity { } @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - @Column(name="id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") private Long id; - - @Column(name="pool_id") + + @Column(name = "pool_id") private Long poolId; - @Column(name="vm_id") + @Column(name = "vm_id") private Long vmId; - - @Column(name="stopped_for_maintenance") + + @Column(name = "stopped_for_maintenance") private boolean stoppedForMaintenance; - - @Column(name="started_after_maintenance") + + @Column(name = "started_after_maintenance") private boolean startedAfterMaintenance; - @Column(name="mgmt_server_id") + @Column(name = "mgmt_server_id") private Long managementServerId; - - public StoragePoolWorkVO(long vmId, long poolId, boolean stoppedForMaintenance, boolean startedAfterMaintenance, long mgmtServerId) { + public StoragePoolWorkVO(long vmId, long poolId, boolean stoppedForMaintenance, boolean startedAfterMaintenance, + long mgmtServerId) { super(); this.vmId = vmId; this.poolId = poolId; @@ -111,8 +107,8 @@ public class StoragePoolWorkVO implements InternalIdentity { this.startedAfterMaintenance = startedAfterMaintenance; this.managementServerId = mgmtServerId; } - + public StoragePoolWorkVO() { - + } } diff --git a/engine/schema/src/com/cloud/storage/SwiftVO.java b/engine/schema/src/com/cloud/storage/SwiftVO.java index c99f0efc702..4136a224b3c 100644 --- a/engine/schema/src/com/cloud/storage/SwiftVO.java +++ b/engine/schema/src/com/cloud/storage/SwiftVO.java @@ -26,39 +26,40 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; -import com.cloud.agent.api.to.SwiftTO; -import org.apache.cloudstack.api.Identity; -import com.cloud.utils.db.GenericDao; import org.apache.cloudstack.api.InternalIdentity; +import com.cloud.agent.api.to.SwiftTO; +import com.cloud.utils.db.GenericDao; + @Entity -@Table(name="swift") +@Table(name = "swift") public class SwiftVO implements Swift, InternalIdentity { @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - @Column(name="id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") private long id; - @Column(name="url") + @Column(name = "url") String url; - @Column(name="account") + @Column(name = "account") String account; - @Column(name="username") + @Column(name = "username") String userName; - @Column(name="key") + @Column(name = "key") String key; - @Column(name="uuid") + @Column(name = "uuid") String uuid = UUID.randomUUID().toString(); @Column(name = GenericDao.CREATED_COLUMN) private Date created; - public SwiftVO() { } + public SwiftVO() { + } public SwiftVO(String url, String account, String userName, String key) { this.url = url; @@ -71,18 +72,22 @@ public class SwiftVO implements Swift, InternalIdentity { public long getId() { return id; } + @Override public String getUrl() { return url; } + @Override public String getAccount() { return account; } + @Override public String getUserName() { return userName; } + @Override public String getKey() { return key; @@ -99,10 +104,10 @@ public class SwiftVO implements Swift, InternalIdentity { @Override public String getUuid() { - return this.uuid; + return this.uuid; } public void setUuid(String uuid) { - this.uuid = uuid; + this.uuid = uuid; } } diff --git a/engine/schema/src/com/cloud/storage/UploadVO.java b/engine/schema/src/com/cloud/storage/UploadVO.java index d761bf17e3b..63fadfac3e8 100755 --- a/engine/schema/src/com/cloud/storage/UploadVO.java +++ b/engine/schema/src/com/cloud/storage/UploadVO.java @@ -32,117 +32,114 @@ import javax.persistence.TemporalType; import com.cloud.utils.NumbersUtil; import com.cloud.utils.db.GenericDaoBase; -import org.apache.cloudstack.api.InternalIdentity; @Entity -@Table(name="upload") +@Table(name = "upload") public class UploadVO implements Upload { - @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - long id; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + long id; - @Column(name="uuid") - private String uuid; + @Column(name = "uuid") + private String uuid; - @Column(name="host_id") - private long hostId; + @Column(name = "host_id") + private long storeId; - @Column(name="type_id") - private long typeId; + @Column(name = "type_id") + private long typeId; - @Column(name=GenericDaoBase.CREATED_COLUMN) - private Date created = null; + @Column(name = GenericDaoBase.CREATED_COLUMN) + private Date created = null; - @Column(name="last_updated") - @Temporal(value=TemporalType.TIMESTAMP) - private Date lastUpdated = null; + @Column(name = "last_updated") + @Temporal(value = TemporalType.TIMESTAMP) + private Date lastUpdated = null; - @Column (name="upload_pct") - private int uploadPercent; + @Column(name = "upload_pct") + private int uploadPercent; - @Column (name="type") - @Enumerated(EnumType.STRING) - private Type type; + @Column(name = "type") + @Enumerated(EnumType.STRING) + private Type type; - @Column (name="mode") + @Column(name = "mode") @Enumerated(EnumType.STRING) private Mode mode = Mode.FTP_UPLOAD; - @Column (name="upload_state") - @Enumerated(EnumType.STRING) - private Status uploadState; + @Column(name = "upload_state") + @Enumerated(EnumType.STRING) + private Status uploadState; - @Column (name="error_str") - private String errorString; + @Column(name = "error_str") + private String errorString; - @Column (name="job_id") - private String jobId; + @Column(name = "job_id") + private String jobId; - @Column (name="url") - private String uploadUrl; + @Column(name = "url") + private String uploadUrl; - @Column (name="install_path") - private String installPath; + @Column(name = "install_path") + private String installPath; - @Override - public long getHostId() { - return hostId; - } + @Override + public long getDataStoreId() { + return storeId; + } - public void setHostId(long hostId) { - this.hostId = hostId; - } + public void setDataStoreId(long hostId) { + this.storeId = hostId; + } - @Override + @Override public long getId() { - return id; - } + return id; + } - - public String getUuid() { + @Override + public String getUuid() { return uuid; } @Override public Date getCreated() { - return created; - } + return created; + } - @Override + @Override public Date getLastUpdated() { - return lastUpdated; - } + return lastUpdated; + } - public void setLastUpdated(Date date) { - lastUpdated = date; - } + public void setLastUpdated(Date date) { + lastUpdated = date; + } - public UploadVO(long hostId, long templateId) { - super(); - this.hostId = hostId; - this.typeId = templateId; - this.uuid = UUID.randomUUID().toString(); - } - - public UploadVO(long hostId, long typeId, Date lastUpdated, - Status uploadState, Type type, - String uploadUrl, Mode mode) { - super(); - this.hostId = hostId; - this.typeId = typeId; - this.lastUpdated = lastUpdated; - this.uploadState = uploadState; - this.mode = mode; - this.type = type; - this.uploadUrl = uploadUrl; + public UploadVO(long hostId, long templateId) { + super(); + this.storeId = hostId; + this.typeId = templateId; this.uuid = UUID.randomUUID().toString(); - } + } - public UploadVO(long hostId, long typeId, Date lastUpdated, - Status uploadState, int uploadPercent, Type type, + public UploadVO(long hostId, long typeId, Date lastUpdated, Status uploadState, Type type, String uploadUrl, Mode mode) { super(); - this.hostId = hostId; + this.storeId = hostId; + this.typeId = typeId; + this.lastUpdated = lastUpdated; + this.uploadState = uploadState; + this.mode = mode; + this.type = type; + this.uploadUrl = uploadUrl; + this.uuid = UUID.randomUUID().toString(); + } + + public UploadVO(long hostId, long typeId, Date lastUpdated, Status uploadState, int uploadPercent, Type type, + Mode mode) { + super(); + this.storeId = hostId; this.typeId = typeId; this.lastUpdated = lastUpdated; this.uploadState = uploadState; @@ -153,82 +150,83 @@ public class UploadVO implements Upload { } - protected UploadVO() { - } + protected UploadVO() { + } - public UploadVO(Long uploadId) { - this.id = uploadId; - } + public UploadVO(Long uploadId) { + this.id = uploadId; + } - public void setErrorString(String errorString) { - this.errorString = errorString; - } + public void setErrorString(String errorString) { + this.errorString = errorString; + } - @Override + @Override public String getErrorString() { - return errorString; - } + return errorString; + } - public void setJobId(String jobId) { - this.jobId = jobId; - } + public void setJobId(String jobId) { + this.jobId = jobId; + } - @Override + @Override public String getJobId() { - return jobId; - } + return jobId; + } - @Override - public boolean equals(Object obj) { - if (obj instanceof UploadVO) { - UploadVO other = (UploadVO)obj; - return (this.typeId==other.getTypeId() && this.hostId==other.getHostId() && this.type == other.getType()); - } - return false; - } + @Override + public boolean equals(Object obj) { + if (obj instanceof UploadVO) { + UploadVO other = (UploadVO) obj; + return (this.typeId == other.getTypeId() && this.storeId == other.getDataStoreId() && this.type == other + .getType()); + } + return false; + } - @Override - public int hashCode() { - return NumbersUtil.hash(id); - } + @Override + public int hashCode() { + return NumbersUtil.hash(id); + } - @Override + @Override public int getUploadPercent() { - return uploadPercent; - } + return uploadPercent; + } - public void setUploadPercent(int uploadPercent) { - this.uploadPercent = uploadPercent; - } + public void setUploadPercent(int uploadPercent) { + this.uploadPercent = uploadPercent; + } - @Override + @Override public Status getUploadState() { - return uploadState; - } + return uploadState; + } - public void setUploadState(Status uploadState) { - this.uploadState = uploadState; - } + public void setUploadState(Status uploadState) { + this.uploadState = uploadState; + } - @Override + @Override public long getTypeId() { - return typeId; - } + return typeId; + } - public void setTypeId(long typeId) { - this.typeId = typeId; - } + public void setTypeId(long typeId) { + this.typeId = typeId; + } - @Override + @Override public Type getType() { - return type; - } + return type; + } - public void setType(Type type) { - this.type = type; - } + public void setType(Type type) { + this.type = type; + } - @Override + @Override public Mode getMode() { return mode; } @@ -239,22 +237,22 @@ public class UploadVO implements Upload { @Override public String getUploadUrl() { - return uploadUrl; - } + return uploadUrl; + } - public void setUploadUrl(String uploadUrl) { - this.uploadUrl = uploadUrl; - } + public void setUploadUrl(String uploadUrl) { + this.uploadUrl = uploadUrl; + } - @Override + @Override public void setId(Long id) { - this.id = id; - } + this.id = id; + } - @Override + @Override public void setCreated(Date created) { - this.created = created; - } + this.created = created; + } @Override public String getInstallPath() { diff --git a/engine/schema/src/com/cloud/storage/VMTemplateDetailVO.java b/engine/schema/src/com/cloud/storage/VMTemplateDetailVO.java index c007802db3f..3d4c7ef30db 100644 --- a/engine/schema/src/com/cloud/storage/VMTemplateDetailVO.java +++ b/engine/schema/src/com/cloud/storage/VMTemplateDetailVO.java @@ -26,59 +26,60 @@ import javax.persistence.Id; import javax.persistence.Table; @Entity -@Table(name="vm_template_details") +@Table(name = "vm_template_details") public class VMTemplateDetailVO implements InternalIdentity { @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - @Column(name="id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") private long id; - - @Column(name="template_id") + + @Column(name = "template_id") private long templateId; - - @Column(name="name") + + @Column(name = "name") private String name; - - @Column(name="value", length=1024) + + @Column(name = "value", length = 1024) private String value; - - public VMTemplateDetailVO() {} - - public VMTemplateDetailVO(long templateId, String name, String value) { - this.templateId = templateId; - this.name = name; - this.value = value; + + public VMTemplateDetailVO() { } - public long getId() { - return id; - } + public VMTemplateDetailVO(long templateId, String name, String value) { + this.templateId = templateId; + this.name = name; + this.value = value; + } - public long getTemplateId() { - return templateId; - } + public long getId() { + return id; + } - public String getName() { - return name; - } + public long getTemplateId() { + return templateId; + } - public String getValue() { - return value; - } + public String getName() { + return name; + } - public void setId(long id) { - this.id = id; - } + public String getValue() { + return value; + } - public void setTemplateId(long templateId) { - this.templateId = templateId; - } + public void setId(long id) { + this.id = id; + } - public void setName(String name) { - this.name = name; - } + public void setTemplateId(long templateId) { + this.templateId = templateId; + } - public void setValue(String value) { - this.value = value; - } + public void setName(String name) { + this.name = name; + } + + public void setValue(String value) { + this.value = value; + } } diff --git a/engine/schema/src/com/cloud/storage/VMTemplateHostVO.java b/engine/schema/src/com/cloud/storage/VMTemplateHostVO.java index b8dfc41d51b..33732a419c9 100755 --- a/engine/schema/src/com/cloud/storage/VMTemplateHostVO.java +++ b/engine/schema/src/com/cloud/storage/VMTemplateHostVO.java @@ -31,220 +31,218 @@ import javax.persistence.TemporalType; import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State; import com.cloud.utils.db.GenericDaoBase; /** * Join table for storage hosts and templates - * + * */ @Entity -@Table(name="template_host_ref") +@Table(name = "template_host_ref") public class VMTemplateHostVO implements VMTemplateStorageResourceAssoc, DataObjectInStore { - @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - Long id; - - @Column(name="host_id") - private long hostId; - - @Column(name="template_id") - private long templateId; - - @Column(name=GenericDaoBase.CREATED_COLUMN) - private Date created = null; - - @Column(name="last_updated") - @Temporal(value=TemporalType.TIMESTAMP) - private Date lastUpdated = null; - - @Column (name="download_pct") - private int downloadPercent; - - @Column (name="size") - private long size; - - @Column (name="physical_size") - private long physicalSize; - - @Column (name="download_state") - @Enumerated(EnumType.STRING) - private Status downloadState; - - @Column (name="local_path") - private String localDownloadPath; - - @Column (name="error_str") - private String errorString; - - @Column (name="job_id") - private String jobId; - - @Column (name="install_path") - private String installPath; - - @Column (name="url") - private String downloadUrl; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + Long id; - @Column(name="is_copy") - private boolean isCopy = false; - - @Column(name="destroyed") + @Column(name = "host_id") + private long hostId; + + @Column(name = "template_id") + private long templateId; + + @Column(name = GenericDaoBase.CREATED_COLUMN) + private Date created = null; + + @Column(name = "last_updated") + @Temporal(value = TemporalType.TIMESTAMP) + private Date lastUpdated = null; + + @Column(name = "download_pct") + private int downloadPercent; + + @Column(name = "size") + private long size; + + @Column(name = "physical_size") + private long physicalSize; + + @Column(name = "download_state") + @Enumerated(EnumType.STRING) + private Status downloadState; + + @Column(name = "local_path") + private String localDownloadPath; + + @Column(name = "error_str") + private String errorString; + + @Column(name = "job_id") + private String jobId; + + @Column(name = "install_path") + private String installPath; + + @Column(name = "url") + private String downloadUrl; + + @Column(name = "is_copy") + private boolean isCopy = false; + + @Column(name = "destroyed") boolean destroyed = false; - - @Column(name="update_count", updatable = true, nullable=false) + + @Column(name = "update_count", updatable = true, nullable = false) protected long updatedCount; - + @Column(name = "updated") @Temporal(value = TemporalType.TIMESTAMP) Date updated; - + @Column(name = "state") @Enumerated(EnumType.STRING) ObjectInDataStoreStateMachine.State state; - - - @Override + + @Override public String getInstallPath() { - return installPath; - } + return installPath; + } - public long getHostId() { - return hostId; - } + public long getHostId() { + return hostId; + } - public void setHostId(long hostId) { - this.hostId = hostId; - } + public void setHostId(long hostId) { + this.hostId = hostId; + } - @Override + @Override public long getTemplateId() { - return templateId; - } + return templateId; + } - @Override + @Override public void setTemplateId(long templateId) { - this.templateId = templateId; - } + this.templateId = templateId; + } - @Override + @Override public int getDownloadPercent() { - return downloadPercent; - } + return downloadPercent; + } - @Override + @Override public void setDownloadPercent(int downloadPercent) { - this.downloadPercent = downloadPercent; - } + this.downloadPercent = downloadPercent; + } - @Override + @Override public void setDownloadState(Status downloadState) { - this.downloadState = downloadState; - } + this.downloadState = downloadState; + } - @Override + @Override public long getId() { - return id; - } + return id; + } - @Override + @Override public Date getCreated() { - return created; - } + return created; + } - @Override + @Override public Date getLastUpdated() { - return lastUpdated; - } - - @Override + return lastUpdated; + } + + @Override public void setLastUpdated(Date date) { - lastUpdated = date; - } - - @Override + lastUpdated = date; + } + + @Override public void setInstallPath(String installPath) { - this.installPath = installPath; - } + this.installPath = installPath; + } - @Override + @Override public Status getDownloadState() { - return downloadState; - } + return downloadState; + } - public VMTemplateHostVO(long hostId, long templateId) { - super(); - this.hostId = hostId; - this.templateId = templateId; - this.state = ObjectInDataStoreStateMachine.State.Allocated; - } + public VMTemplateHostVO(long hostId, long templateId) { + super(); + this.hostId = hostId; + this.templateId = templateId; + this.state = ObjectInDataStoreStateMachine.State.Allocated; + } - public VMTemplateHostVO(long hostId, long templateId, Date lastUpdated, - int downloadPercent, Status downloadState, - String localDownloadPath, String errorString, String jobId, - String installPath, String downloadUrl) { - super(); - this.hostId = hostId; - this.templateId = templateId; - this.lastUpdated = lastUpdated; - this.downloadPercent = downloadPercent; - this.downloadState = downloadState; - this.localDownloadPath = localDownloadPath; - this.errorString = errorString; - this.jobId = jobId; - this.installPath = installPath; - this.setDownloadUrl(downloadUrl); - } + public VMTemplateHostVO(long hostId, long templateId, Date lastUpdated, int downloadPercent, Status downloadState, + String localDownloadPath, String errorString, String jobId, String installPath, String downloadUrl) { + super(); + this.hostId = hostId; + this.templateId = templateId; + this.lastUpdated = lastUpdated; + this.downloadPercent = downloadPercent; + this.downloadState = downloadState; + this.localDownloadPath = localDownloadPath; + this.errorString = errorString; + this.jobId = jobId; + this.installPath = installPath; + this.setDownloadUrl(downloadUrl); + } - protected VMTemplateHostVO() { - - } + protected VMTemplateHostVO() { - @Override + } + + @Override public void setLocalDownloadPath(String localPath) { - this.localDownloadPath = localPath; - } + this.localDownloadPath = localPath; + } - @Override + @Override public String getLocalDownloadPath() { - return localDownloadPath; - } + return localDownloadPath; + } - @Override + @Override public void setErrorString(String errorString) { - this.errorString = errorString; - } + this.errorString = errorString; + } - @Override + @Override public String getErrorString() { - return errorString; - } + return errorString; + } - @Override + @Override public void setJobId(String jobId) { - this.jobId = jobId; - } + this.jobId = jobId; + } - @Override + @Override public String getJobId() { - return jobId; - } + return jobId; + } - @Override - public boolean equals(Object obj) { - if (obj instanceof VMTemplateHostVO) { - VMTemplateHostVO other = (VMTemplateHostVO)obj; - return (this.templateId==other.getTemplateId() && this.hostId==other.getHostId()); - } - return false; - } + @Override + public boolean equals(Object obj) { + if (obj instanceof VMTemplateHostVO) { + VMTemplateHostVO other = (VMTemplateHostVO) obj; + return (this.templateId == other.getTemplateId() && this.hostId == other.getHostId()); + } + return false; + } - @Override - public int hashCode() { - Long tid = new Long(templateId); - Long hid = new Long(hostId); - return tid.hashCode()+hid.hashCode(); - } + @Override + public int hashCode() { + Long tid = new Long(templateId); + Long hid = new Long(hostId); + return tid.hashCode() + hid.hashCode(); + } public void setSize(long size) { this.size = size; @@ -253,8 +251,7 @@ public class VMTemplateHostVO implements VMTemplateStorageResourceAssoc, DataObj public long getSize() { return size; } - - + public void setPhysicalSize(long physicalSize) { this.physicalSize = physicalSize; } @@ -264,49 +261,50 @@ public class VMTemplateHostVO implements VMTemplateStorageResourceAssoc, DataObj } public void setDestroyed(boolean destroyed) { - this.destroyed = destroyed; + this.destroyed = destroyed; } public boolean getDestroyed() { - return destroyed; + return destroyed; } - public void setDownloadUrl(String downloadUrl) { - this.downloadUrl = downloadUrl; - } + public void setDownloadUrl(String downloadUrl) { + this.downloadUrl = downloadUrl; + } - public String getDownloadUrl() { - return downloadUrl; - } + public String getDownloadUrl() { + return downloadUrl; + } - public void setCopy(boolean isCopy) { - this.isCopy = isCopy; - } + public void setCopy(boolean isCopy) { + this.isCopy = isCopy; + } - public boolean isCopy() { - return isCopy; - } - - @Override + public boolean isCopy() { + return isCopy; + } + + @Override public long getTemplateSize() { - return -1; - } - - @Override + return -1; + } + + @Override public String toString() { - return new StringBuilder("TmplHost[").append(id).append("-").append(templateId).append("-").append(hostId).append(installPath).append("]").toString(); - } + return new StringBuilder("TmplHost[").append(id).append("-").append(templateId).append("-").append(hostId) + .append(installPath).append("]").toString(); + } @Override public ObjectInDataStoreStateMachine.State getState() { // TODO Auto-generated method stub return this.state; } - + public long getUpdatedCount() { return this.updatedCount; } - + public void incrUpdatedCount() { this.updatedCount++; } @@ -314,9 +312,24 @@ public class VMTemplateHostVO implements VMTemplateStorageResourceAssoc, DataObj public void decrUpdatedCount() { this.updatedCount--; } - + public Date getUpdated() { return updated; } + @Override + public long getObjectId() { + return this.getTemplateId(); + } + + @Override + public long getDataStoreId() { + return this.getHostId(); + } + + @Override + public State getObjectInStoreState() { + return this.state; + } + } diff --git a/engine/schema/src/com/cloud/storage/VMTemplateS3VO.java b/engine/schema/src/com/cloud/storage/VMTemplateS3VO.java index 02f3ff5cf7f..e106bf7d1a5 100644 --- a/engine/schema/src/com/cloud/storage/VMTemplateS3VO.java +++ b/engine/schema/src/com/cloud/storage/VMTemplateS3VO.java @@ -62,8 +62,8 @@ public class VMTemplateS3VO implements InternalIdentity { super(); } - public VMTemplateS3VO(final long s3Id, final long templateId, - final Date created, final Long size, final Long physicalSize) { + public VMTemplateS3VO(final long s3Id, final long templateId, final Date created, final Long size, + final Long physicalSize) { super(); @@ -100,19 +100,16 @@ public class VMTemplateS3VO implements InternalIdentity { return false; } - if (this.created != null ? !created.equals(thatVMTemplateS3VO.created) - : thatVMTemplateS3VO.created != null) { + if (this.created != null ? !created.equals(thatVMTemplateS3VO.created) : thatVMTemplateS3VO.created != null) { return false; } - if (this.physicalSize != null ? !physicalSize - .equals(thatVMTemplateS3VO.physicalSize) + if (this.physicalSize != null ? !physicalSize.equals(thatVMTemplateS3VO.physicalSize) : thatVMTemplateS3VO.physicalSize != null) { return false; } - if (this.size != null ? !size.equals(thatVMTemplateS3VO.size) - : thatVMTemplateS3VO.size != null) { + if (this.size != null ? !size.equals(thatVMTemplateS3VO.size) : thatVMTemplateS3VO.size != null) { return false; } @@ -125,14 +122,10 @@ public class VMTemplateS3VO implements InternalIdentity { int result = (int) (this.id ^ (this.id >>> 32)); result = 31 * result + (int) (this.s3Id ^ (this.s3Id >>> 32)); - result = 31 * result - + (int) (this.templateId ^ (this.templateId >>> 32)); - result = 31 * result - + (this.created != null ? this.created.hashCode() : 0); + result = 31 * result + (int) (this.templateId ^ (this.templateId >>> 32)); + result = 31 * result + (this.created != null ? this.created.hashCode() : 0); result = 31 * result + (this.size != null ? this.size.hashCode() : 0); - result = 31 - * result - + (this.physicalSize != null ? this.physicalSize.hashCode() : 0); + result = 31 * result + (this.physicalSize != null ? this.physicalSize.hashCode() : 0); return result; @@ -189,13 +182,10 @@ public class VMTemplateS3VO implements InternalIdentity { @Override public String toString() { - final StringBuilder stringBuilder = new StringBuilder( - "VMTemplateS3VO [ id: ").append(id).append(", created: ") - .append(DateFormat.getDateTimeInstance().format(created)) - .append(", physicalSize: ").append(physicalSize) - .append(", size: ").append(size).append(", templateId: ") - .append(templateId).append(", s3Id: ").append(s3Id) - .append(" ]"); + final StringBuilder stringBuilder = new StringBuilder("VMTemplateS3VO [ id: ").append(id).append(", created: ") + .append(DateFormat.getDateTimeInstance().format(created)).append(", physicalSize: ") + .append(physicalSize).append(", size: ").append(size).append(", templateId: ").append(templateId) + .append(", s3Id: ").append(s3Id).append(" ]"); return stringBuilder.toString(); diff --git a/engine/schema/src/com/cloud/storage/VMTemplateStoragePoolVO.java b/engine/schema/src/com/cloud/storage/VMTemplateStoragePoolVO.java index 9b761764359..10ced67244f 100644 --- a/engine/schema/src/com/cloud/storage/VMTemplateStoragePoolVO.java +++ b/engine/schema/src/com/cloud/storage/VMTemplateStoragePoolVO.java @@ -37,228 +37,239 @@ import com.cloud.utils.db.GenericDaoBase; /** * Join table for storage pools and templates - * + * */ @Entity -@Table(name="template_spool_ref") +@Table(name = "template_spool_ref") public class VMTemplateStoragePoolVO implements VMTemplateStorageResourceAssoc, DataObjectInStore { - @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - long id; - - @Column(name="pool_id") - private long poolId; - - @Column(name="template_id") long templateId; - - @Column(name=GenericDaoBase.CREATED_COLUMN) Date created = null; - - @Column(name="last_updated") - @Temporal(value=TemporalType.TIMESTAMP) Date lastUpdated = null; - - @Column (name="download_pct") int downloadPercent; - - @Column (name="download_state") - @Enumerated(EnumType.STRING) Status downloadState; - - @Column (name="local_path") String localDownloadPath; - - @Column (name="error_str") String errorString; - - @Column (name="job_id") String jobId; - - @Column (name="install_path") String installPath; - - @Column (name="template_size") long templateSize; - - @Column (name="marked_for_gc") boolean markedForGC; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + long id; - @Column(name="update_count", updatable = true, nullable=false) - protected long updatedCount; + @Column(name = "pool_id") + private long poolId; - @Column(name = "updated") - @Temporal(value = TemporalType.TIMESTAMP) - Date updated; + @Column(name = "template_id") + long templateId; - @Column(name = "state") - @Enumerated(EnumType.STRING) - ObjectInDataStoreStateMachine.State state; + @Column(name = GenericDaoBase.CREATED_COLUMN) + Date created = null; - @Override + @Column(name = "last_updated") + @Temporal(value = TemporalType.TIMESTAMP) + Date lastUpdated = null; + + @Column(name = "download_pct") + int downloadPercent; + + @Column(name = "download_state") + @Enumerated(EnumType.STRING) + Status downloadState; + + @Column(name = "local_path") + String localDownloadPath; + + @Column(name = "error_str") + String errorString; + + @Column(name = "job_id") + String jobId; + + @Column(name = "install_path") + String installPath; + + @Column(name = "template_size") + long templateSize; + + @Column(name = "marked_for_gc") + boolean markedForGC; + + @Column(name = "update_count", updatable = true, nullable = false) + protected long updatedCount; + + @Column(name = "updated") + @Temporal(value = TemporalType.TIMESTAMP) + Date updated; + + @Column(name = "state") + @Enumerated(EnumType.STRING) + ObjectInDataStoreStateMachine.State state; + + @Override public String getInstallPath() { - return installPath; - } - - @Override + return installPath; + } + + @Override public long getTemplateSize() { - return templateSize; - } + return templateSize; + } - public long getPoolId() { - return poolId; - } + public long getPoolId() { + return poolId; + } - public void setpoolId(long poolId) { - this.poolId = poolId; - } + public void setpoolId(long poolId) { + this.poolId = poolId; + } - @Override + @Override public long getTemplateId() { - return templateId; - } + return templateId; + } - @Override + @Override public void setTemplateId(long templateId) { - this.templateId = templateId; - } + this.templateId = templateId; + } - @Override + @Override public int getDownloadPercent() { - return downloadPercent; - } + return downloadPercent; + } - @Override + @Override public void setDownloadPercent(int downloadPercent) { - this.downloadPercent = downloadPercent; - } + this.downloadPercent = downloadPercent; + } - @Override + @Override public void setDownloadState(Status downloadState) { - this.downloadState = downloadState; - } + this.downloadState = downloadState; + } - @Override + @Override public long getId() { - return id; - } + return id; + } - @Override + @Override public Date getCreated() { - return created; - } + return created; + } - @Override + @Override public Date getLastUpdated() { - return lastUpdated; - } - - @Override + return lastUpdated; + } + + @Override public void setLastUpdated(Date date) { - lastUpdated = date; - } - - @Override + lastUpdated = date; + } + + @Override public void setInstallPath(String installPath) { - this.installPath = installPath; - } + this.installPath = installPath; + } - @Override + @Override public Status getDownloadState() { - return downloadState; - } + return downloadState; + } - public VMTemplateStoragePoolVO(long poolId, long templateId) { - super(); - this.poolId = poolId; - this.templateId = templateId; - this.downloadState = Status.NOT_DOWNLOADED; - this.state = ObjectInDataStoreStateMachine.State.Allocated; - this.markedForGC = false; - } + public VMTemplateStoragePoolVO(long poolId, long templateId) { + super(); + this.poolId = poolId; + this.templateId = templateId; + this.downloadState = Status.NOT_DOWNLOADED; + this.state = ObjectInDataStoreStateMachine.State.Allocated; + this.markedForGC = false; + } - public VMTemplateStoragePoolVO(long poolId, long templateId, Date lastUpdated, - int downloadPercent, Status downloadState, - String localDownloadPath, String errorString, String jobId, - String installPath, long templateSize) { - super(); - this.poolId = poolId; - this.templateId = templateId; - this.lastUpdated = lastUpdated; - this.downloadPercent = downloadPercent; - this.downloadState = downloadState; - this.localDownloadPath = localDownloadPath; - this.errorString = errorString; - this.jobId = jobId; - this.installPath = installPath; - this.templateSize = templateSize; - } + public VMTemplateStoragePoolVO(long poolId, long templateId, Date lastUpdated, int downloadPercent, + Status downloadState, String localDownloadPath, String errorString, String jobId, String installPath, + long templateSize) { + super(); + this.poolId = poolId; + this.templateId = templateId; + this.lastUpdated = lastUpdated; + this.downloadPercent = downloadPercent; + this.downloadState = downloadState; + this.localDownloadPath = localDownloadPath; + this.errorString = errorString; + this.jobId = jobId; + this.installPath = installPath; + this.templateSize = templateSize; + } - protected VMTemplateStoragePoolVO() { - - } + protected VMTemplateStoragePoolVO() { - @Override + } + + @Override public void setLocalDownloadPath(String localPath) { - this.localDownloadPath = localPath; - } + this.localDownloadPath = localPath; + } - @Override + @Override public String getLocalDownloadPath() { - return localDownloadPath; - } + return localDownloadPath; + } - @Override + @Override public void setErrorString(String errorString) { - this.errorString = errorString; - } + this.errorString = errorString; + } - @Override + @Override public String getErrorString() { - return errorString; - } + return errorString; + } - @Override + @Override public void setJobId(String jobId) { - this.jobId = jobId; - } + this.jobId = jobId; + } - @Override + @Override public String getJobId() { - return jobId; - } - - public void setTemplateSize(long templateSize) { - this.templateSize = templateSize; - } - - public boolean getMarkedForGC() { - return markedForGC; - } - - public void setMarkedForGC(boolean markedForGC) { - this.markedForGC = markedForGC; - } + return jobId; + } - @Override - public boolean equals(Object obj) { - if (obj instanceof VMTemplateStoragePoolVO) { - VMTemplateStoragePoolVO other = (VMTemplateStoragePoolVO)obj; - return (this.templateId==other.getTemplateId() && this.poolId==other.getPoolId()); - } - return false; - } + public void setTemplateSize(long templateSize) { + this.templateSize = templateSize; + } - @Override - public int hashCode() { - Long tid = new Long(templateId); - Long hid = new Long(poolId); - return tid.hashCode()+hid.hashCode(); - } - - @Override + public boolean getMarkedForGC() { + return markedForGC; + } + + public void setMarkedForGC(boolean markedForGC) { + this.markedForGC = markedForGC; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof VMTemplateStoragePoolVO) { + VMTemplateStoragePoolVO other = (VMTemplateStoragePoolVO) obj; + return (this.templateId == other.getTemplateId() && this.poolId == other.getPoolId()); + } + return false; + } + + @Override + public int hashCode() { + Long tid = new Long(templateId); + Long hid = new Long(poolId); + return tid.hashCode() + hid.hashCode(); + } + + @Override public String toString() { - return new StringBuilder("TmplPool[").append(id).append("-").append(templateId).append("-").append("poolId").append("-").append(installPath).append("]").toString(); - } + return new StringBuilder("TmplPool[").append(id).append("-").append(templateId).append("-").append("poolId") + .append("-").append(installPath).append("]").toString(); + } @Override public State getState() { return this.state; } - + public long getUpdatedCount() { return this.updatedCount; } - + public void incrUpdatedCount() { this.updatedCount++; } @@ -266,10 +277,24 @@ public class VMTemplateStoragePoolVO implements VMTemplateStorageResourceAssoc, public void decrUpdatedCount() { this.updatedCount--; } - + public Date getUpdated() { return updated; } - + + @Override + public long getObjectId() { + return this.getTemplateId(); + } + + @Override + public long getDataStoreId() { + return this.getPoolId(); + } + + @Override + public State getObjectInStoreState() { + return this.state; + } } diff --git a/engine/schema/src/com/cloud/storage/VMTemplateSwiftVO.java b/engine/schema/src/com/cloud/storage/VMTemplateSwiftVO.java index 6c7a73d3c05..de55fb6622f 100755 --- a/engine/schema/src/com/cloud/storage/VMTemplateSwiftVO.java +++ b/engine/schema/src/com/cloud/storage/VMTemplateSwiftVO.java @@ -101,7 +101,8 @@ public class VMTemplateSwiftVO implements InternalIdentity { @Override public String toString() { - return new StringBuilder("TmplSwift[").append(id).append("-").append(templateId).append("-").append(swiftId).append("]").toString(); + return new StringBuilder("TmplSwift[").append(id).append("-").append(templateId).append("-").append(swiftId) + .append("]").toString(); } } diff --git a/engine/schema/src/com/cloud/storage/VMTemplateVO.java b/engine/schema/src/com/cloud/storage/VMTemplateVO.java index 3bf83c0e727..45eed231714 100755 --- a/engine/schema/src/com/cloud/storage/VMTemplateVO.java +++ b/engine/schema/src/com/cloud/storage/VMTemplateVO.java @@ -41,106 +41,101 @@ import com.cloud.utils.db.GenericDao; import com.cloud.utils.fsm.StateObject; @Entity -@Table(name="vm_template") -public class VMTemplateVO implements VirtualMachineTemplate, StateObject { +@Table(name = "vm_template") +public class VMTemplateVO implements VirtualMachineTemplate { @Id - @TableGenerator(name="vm_template_sq", table="sequence", pkColumnName="name", valueColumnName="value", pkColumnValue="vm_template_seq", allocationSize=1) - @Column(name="id", nullable = false) + @TableGenerator(name = "vm_template_sq", table = "sequence", pkColumnName = "name", valueColumnName = "value", + pkColumnValue = "vm_template_seq", allocationSize = 1) + @Column(name = "id", nullable = false) private long id; - @Column(name="format") + @Column(name = "format") private Storage.ImageFormat format; - @Column(name="unique_name") + @Column(name = "unique_name") private String uniqueName; - @Column(name="name") + @Column(name = "name") private String name = null; - @Column(name="public") + @Column(name = "public") private boolean publicTemplate = true; - @Column(name="featured") + @Column(name = "featured") private boolean featured; - @Column(name="type") + @Column(name = "type") private Storage.TemplateType templateType; - @Column(name="url") + @Column(name = "url") private String url = null; - @Column(name="hvm") + @Column(name = "hvm") private boolean requiresHvm; - @Column(name="bits") + @Column(name = "bits") private int bits; - @Temporal(value=TemporalType.TIMESTAMP) - @Column(name=GenericDao.CREATED_COLUMN) + @Temporal(value = TemporalType.TIMESTAMP) + @Column(name = GenericDao.CREATED_COLUMN) private Date created = null; - @Column(name=GenericDao.REMOVED) + @Column(name = GenericDao.REMOVED) @Temporal(TemporalType.TIMESTAMP) private Date removed; - @Column(name="account_id") + @Column(name = "account_id") private long accountId; - @Column(name="checksum") + @Column(name = "checksum") private String checksum; - @Column(name="display_text", length=4096) + @Column(name = "display_text", length = 4096) private String displayText; - @Column(name="enable_password") + @Column(name = "enable_password") private boolean enablePassword; - @Column(name="guest_os_id") + @Column(name = "guest_os_id") private long guestOSId; - @Column(name="bootable") + @Column(name = "bootable") private boolean bootable = true; - @Column(name="prepopulate") + @Column(name = "prepopulate") private boolean prepopulate = false; - @Column(name="cross_zones") + @Column(name = "cross_zones") private boolean crossZones = false; - @Column(name="hypervisor_type") - @Enumerated(value=EnumType.STRING) + @Column(name = "hypervisor_type") + @Enumerated(value = EnumType.STRING) private HypervisorType hypervisorType; - @Column(name="extractable") + @Column(name = "extractable") private boolean extractable = true; - @Column(name="source_template_id") + @Column(name = "source_template_id") private Long sourceTemplateId; - @Column(name="template_tag") + @Column(name = "template_tag") private String templateTag; - @Column(name="uuid") + @Column(name = "uuid") private String uuid; - @Column(name="sort_key") + @Column(name = "sort_key") private int sortKey; - @Column(name="enable_sshkey") + @Column(name = "enable_sshkey") private boolean enableSshKey; - - @Column(name = "image_data_store_id") - private long imageDataStoreId; - + @Column(name = "size") private Long size; - - @Column(name = "state") - private TemplateState state; - - @Column(name="update_count", updatable = true) + + @Column(name = "update_count", updatable = true) protected long updatedCount; - + @Column(name = "updated") @Temporal(value = TemporalType.TIMESTAMP) Date updated; @@ -161,29 +156,50 @@ public class VMTemplateVO implements VirtualMachineTemplate, StateObject { List listByDomainId(long domainId); + List findPrivateDiskOffering(); - List findPublicDiskOfferings(); + + List findPublicDiskOfferings(); + DiskOfferingVO findByUniqueName(String uniqueName); + DiskOfferingVO persistDeafultDiskOffering(DiskOfferingVO offering); - + } diff --git a/engine/schema/src/com/cloud/storage/dao/DiskOfferingDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/DiskOfferingDaoImpl.java index 1f68c5082ff..0c77a8a8600 100644 --- a/engine/schema/src/com/cloud/storage/dao/DiskOfferingDaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/DiskOfferingDaoImpl.java @@ -22,7 +22,6 @@ import java.util.List; import javax.ejb.Local; import javax.persistence.EntityExistsException; -import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import com.cloud.storage.DiskOfferingVO; @@ -35,10 +34,8 @@ import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria.Op; @Component -@Local(value={DiskOfferingDao.class}) +@Local(value = { DiskOfferingDao.class }) public class DiskOfferingDaoImpl extends GenericDaoBase implements DiskOfferingDao { - private static final Logger s_logger = Logger.getLogger(DiskOfferingDaoImpl.class); - private final SearchBuilder DomainIdSearch; private final SearchBuilder PrivateDiskOfferingSearch; private final SearchBuilder PublicDiskOfferingSearch; @@ -46,25 +43,27 @@ public class DiskOfferingDaoImpl extends GenericDaoBase im private final Attribute _typeAttr; protected DiskOfferingDaoImpl() { - DomainIdSearch = createSearchBuilder(); + DomainIdSearch = createSearchBuilder(); DomainIdSearch.and("domainId", DomainIdSearch.entity().getDomainId(), SearchCriteria.Op.EQ); DomainIdSearch.and("removed", DomainIdSearch.entity().getRemoved(), SearchCriteria.Op.NULL); DomainIdSearch.done(); - - PrivateDiskOfferingSearch = createSearchBuilder(); - PrivateDiskOfferingSearch.and("diskSize", PrivateDiskOfferingSearch.entity().getDiskSize(), SearchCriteria.Op.EQ); + + PrivateDiskOfferingSearch = createSearchBuilder(); + PrivateDiskOfferingSearch.and("diskSize", PrivateDiskOfferingSearch.entity().getDiskSize(), + SearchCriteria.Op.EQ); PrivateDiskOfferingSearch.done(); - + PublicDiskOfferingSearch = createSearchBuilder(); - PublicDiskOfferingSearch.and("domainId", PublicDiskOfferingSearch.entity().getDomainId(), SearchCriteria.Op.NULL); + PublicDiskOfferingSearch.and("domainId", PublicDiskOfferingSearch.entity().getDomainId(), + SearchCriteria.Op.NULL); PublicDiskOfferingSearch.and("system", PublicDiskOfferingSearch.entity().getSystemUse(), SearchCriteria.Op.EQ); PublicDiskOfferingSearch.and("removed", PublicDiskOfferingSearch.entity().getRemoved(), SearchCriteria.Op.NULL); PublicDiskOfferingSearch.done(); - + UniqueNameSearch = createSearchBuilder(); UniqueNameSearch.and("name", UniqueNameSearch.entity().getUniqueName(), SearchCriteria.Op.EQ); UniqueNameSearch.done(); - + _typeAttr = _allAttributes.get("type"); } @@ -72,29 +71,31 @@ public class DiskOfferingDaoImpl extends GenericDaoBase im public List listByDomainId(long domainId) { SearchCriteria sc = DomainIdSearch.create(); sc.setParameters("domainId", domainId); - // FIXME: this should not be exact match, but instead should find all available disk offerings from parent domains + // FIXME: this should not be exact match, but instead should find all + // available disk offerings from parent domains return listBy(sc); } - + @Override public List findPrivateDiskOffering() { SearchCriteria sc = PrivateDiskOfferingSearch.create(); sc.setParameters("diskSize", 0); return listBy(sc); } - + @Override - public List searchIncludingRemoved(SearchCriteria sc, final Filter filter, final Boolean lock, final boolean cache) { + public List searchIncludingRemoved(SearchCriteria sc, final Filter filter, + final Boolean lock, final boolean cache) { sc.addAnd(_typeAttr, Op.EQ, Type.Disk); return super.searchIncludingRemoved(sc, filter, lock, cache); } - + @Override public List customSearchIncludingRemoved(SearchCriteria sc, final Filter filter) { sc.addAnd(_typeAttr, Op.EQ, Type.Disk); return super.customSearchIncludingRemoved(sc, filter); } - + @Override protected List executeList(final String sql, final Object... params) { StringBuilder builder = new StringBuilder(sql); @@ -104,17 +105,17 @@ public class DiskOfferingDaoImpl extends GenericDaoBase im } else { builder.insert(index + 6, "type=? "); } - + return super.executeList(sql, Type.Disk, params); } - + @Override - public List findPublicDiskOfferings(){ - SearchCriteria sc = PublicDiskOfferingSearch.create(); - sc.setParameters("system", false); - return listBy(sc); + public List findPublicDiskOfferings() { + SearchCriteria sc = PublicDiskOfferingSearch.create(); + sc.setParameters("system", false); + return listBy(sc); } - + @Override public DiskOfferingVO findByUniqueName(String uniqueName) { SearchCriteria sc = UniqueNameSearch.create(); @@ -123,10 +124,10 @@ public class DiskOfferingDaoImpl extends GenericDaoBase im if (vos.size() == 0) { return null; } - + return vos.get(0); } - + @Override public DiskOfferingVO persistDeafultDiskOffering(DiskOfferingVO offering) { assert offering.getUniqueName() != null : "unique name shouldn't be null for the disk offering"; @@ -141,7 +142,7 @@ public class DiskOfferingDaoImpl extends GenericDaoBase im return findByUniqueName(offering.getUniqueName()); } } - + @Override public boolean remove(Long id) { DiskOfferingVO diskOffering = createForUpdate(); diff --git a/engine/schema/src/com/cloud/storage/dao/GuestOSCategoryDao.java b/engine/schema/src/com/cloud/storage/dao/GuestOSCategoryDao.java index 0f7ea327f15..61fec36d526 100644 --- a/engine/schema/src/com/cloud/storage/dao/GuestOSCategoryDao.java +++ b/engine/schema/src/com/cloud/storage/dao/GuestOSCategoryDao.java @@ -20,5 +20,5 @@ import com.cloud.storage.GuestOSCategoryVO; import com.cloud.utils.db.GenericDao; public interface GuestOSCategoryDao extends GenericDao { - + } diff --git a/engine/schema/src/com/cloud/storage/dao/GuestOSCategoryDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/GuestOSCategoryDaoImpl.java index d017b996d5d..0637ecbf4ff 100644 --- a/engine/schema/src/com/cloud/storage/dao/GuestOSCategoryDaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/GuestOSCategoryDaoImpl.java @@ -24,11 +24,11 @@ import com.cloud.storage.GuestOSCategoryVO; import com.cloud.utils.db.GenericDaoBase; @Component -@Local (value={GuestOSCategoryDao.class}) +@Local(value = { GuestOSCategoryDao.class }) public class GuestOSCategoryDaoImpl extends GenericDaoBase implements GuestOSCategoryDao { - - protected GuestOSCategoryDaoImpl() { - } - + protected GuestOSCategoryDaoImpl() { + + } + } diff --git a/engine/schema/src/com/cloud/storage/dao/GuestOSDao.java b/engine/schema/src/com/cloud/storage/dao/GuestOSDao.java index 19e423bfefd..a9d0cdb8279 100755 --- a/engine/schema/src/com/cloud/storage/dao/GuestOSDao.java +++ b/engine/schema/src/com/cloud/storage/dao/GuestOSDao.java @@ -22,5 +22,5 @@ import com.cloud.utils.db.GenericDao; public interface GuestOSDao extends GenericDao { GuestOSVO listByDisplayName(String displayName); - + } diff --git a/engine/schema/src/com/cloud/storage/dao/GuestOSDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/GuestOSDaoImpl.java index c39fae8ea8d..618578524c6 100755 --- a/engine/schema/src/com/cloud/storage/dao/GuestOSDaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/GuestOSDaoImpl.java @@ -16,32 +16,28 @@ // under the License. package com.cloud.storage.dao; -import java.util.List; - import javax.ejb.Local; import org.springframework.stereotype.Component; import com.cloud.storage.GuestOSVO; -import com.cloud.storage.VMTemplateHostVO; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; @Component -@Local (value={GuestOSDao.class}) +@Local(value = { GuestOSDao.class }) public class GuestOSDaoImpl extends GenericDaoBase implements GuestOSDao { - - + protected final SearchBuilder Search; - - protected GuestOSDaoImpl() { + + protected GuestOSDaoImpl() { Search = createSearchBuilder(); Search.and("display_name", Search.entity().getDisplayName(), SearchCriteria.Op.EQ); Search.done(); - } - - @Override + } + + @Override public GuestOSVO listByDisplayName(String displayName) { SearchCriteria sc = Search.create(); sc.setParameters("display_name", displayName); diff --git a/engine/schema/src/com/cloud/storage/dao/LaunchPermissionDao.java b/engine/schema/src/com/cloud/storage/dao/LaunchPermissionDao.java index 0ad60b50ee8..146e180fd07 100644 --- a/engine/schema/src/com/cloud/storage/dao/LaunchPermissionDao.java +++ b/engine/schema/src/com/cloud/storage/dao/LaunchPermissionDao.java @@ -18,42 +18,54 @@ package com.cloud.storage.dao; import java.util.List; - import com.cloud.storage.LaunchPermissionVO; import com.cloud.storage.VMTemplateVO; import com.cloud.utils.db.GenericDao; public interface LaunchPermissionDao extends GenericDao { /** - * remove the ability to launch vms from the given template for the given account names which are valid in the given domain - * @param templateId id of the template to modify launch permissions - * @param accountIds list of account ids + * remove the ability to launch vms from the given template for the given + * account names which are valid in the given domain + * + * @param templateId + * id of the template to modify launch permissions + * @param accountIds + * list of account ids */ void removePermissions(long templateId, List accountIds); /** * remove all launch permissions associated with a template + * * @param templateId */ void removeAllPermissions(long templateId); /** * Find a launch permission by templateId, accountName, and domainId - * @param templateId the id of the template to search for - * @param accountId the id of the account for which permission is being searched + * + * @param templateId + * the id of the template to search for + * @param accountId + * the id of the account for which permission is being searched * @return launch permission if found, null otherwise */ LaunchPermissionVO findByTemplateAndAccount(long templateId, long accountId); /** * List all launch permissions for the given template - * @param templateId id of the template for which launch permissions will be queried + * + * @param templateId + * id of the template for which launch permissions will be + * queried * @return list of launch permissions */ List findByTemplate(long templateId); /** - * List all templates for which permission to launch instances has been granted to the given account + * List all templates for which permission to launch instances has been + * granted to the given account + * * @param accountId * @return */ diff --git a/engine/schema/src/com/cloud/storage/dao/LaunchPermissionDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/LaunchPermissionDaoImpl.java index 286b1d9ce3f..3e32f1a9529 100644 --- a/engine/schema/src/com/cloud/storage/dao/LaunchPermissionDaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/LaunchPermissionDaoImpl.java @@ -39,26 +39,27 @@ import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; @Component -@Local(value={LaunchPermissionDao.class}) +@Local(value = { LaunchPermissionDao.class }) public class LaunchPermissionDaoImpl extends GenericDaoBase implements LaunchPermissionDao { private static final Logger s_logger = Logger.getLogger(LaunchPermissionDaoImpl.class); - private static final String REMOVE_LAUNCH_PERMISSION = "DELETE FROM `cloud`.`launch_permission`" + - " WHERE template_id = ? AND account_id = ?"; + private static final String REMOVE_LAUNCH_PERMISSION = "DELETE FROM `cloud`.`launch_permission`" + + " WHERE template_id = ? AND account_id = ?"; - private static final String LIST_PERMITTED_TEMPLATES = "SELECT t.id, t.unique_name, t.name, t.public, t.format, t.type, t.hvm, t.bits, t.url, t.created, t.account_id, t.checksum, t.display_text, t.enable_password, t.guest_os_id, t.featured" + - " FROM `cloud`.`vm_template` t INNER JOIN (SELECT lp.template_id as lptid" + - " FROM `cloud`.`launch_permission` lp" + - " WHERE lp.account_id = ?) joinlp" + - " WHERE t.id = joinlp.lptid" + - " ORDER BY t.created DESC"; + private static final String LIST_PERMITTED_TEMPLATES = "SELECT t.id, t.unique_name, t.name, t.public, t.format, t.type, t.hvm, t.bits, t.url, t.created, t.account_id, t.checksum, t.display_text, t.enable_password, t.guest_os_id, t.featured" + + " FROM `cloud`.`vm_template` t INNER JOIN (SELECT lp.template_id as lptid" + + " FROM `cloud`.`launch_permission` lp" + + " WHERE lp.account_id = ?) joinlp" + + " WHERE t.id = joinlp.lptid" + " ORDER BY t.created DESC"; private final SearchBuilder TemplateAndAccountSearch; private final SearchBuilder TemplateIdSearch; protected LaunchPermissionDaoImpl() { TemplateAndAccountSearch = createSearchBuilder(); - TemplateAndAccountSearch.and("templateId", TemplateAndAccountSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); - TemplateAndAccountSearch.and("accountId", TemplateAndAccountSearch.entity().getAccountId(), SearchCriteria.Op.EQ); + TemplateAndAccountSearch.and("templateId", TemplateAndAccountSearch.entity().getTemplateId(), + SearchCriteria.Op.EQ); + TemplateAndAccountSearch.and("accountId", TemplateAndAccountSearch.entity().getAccountId(), + SearchCriteria.Op.EQ); TemplateAndAccountSearch.done(); TemplateIdSearch = createSearchBuilder(); @@ -138,9 +139,13 @@ public class LaunchPermissionDaoImpl extends GenericDaoBase implements S3Dao { } - // NOTE: Excluded listAll / shuffle operation implemented in SwiftDaoImpl ... + // NOTE: Excluded listAll / shuffle operation implemented in + // SwiftDaoImpl ... return null; diff --git a/engine/schema/src/com/cloud/storage/dao/SnapshotDao.java b/engine/schema/src/com/cloud/storage/dao/SnapshotDao.java index 3ac9e77fb5d..a58902121cc 100644 --- a/engine/schema/src/com/cloud/storage/dao/SnapshotDao.java +++ b/engine/schema/src/com/cloud/storage/dao/SnapshotDao.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.storage.dao; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.Snapshot; import com.cloud.storage.Snapshot.Type; import com.cloud.storage.SnapshotVO; @@ -26,26 +27,40 @@ import com.cloud.utils.fsm.StateDao; import java.util.List; public interface SnapshotDao extends GenericDao, StateDao { - List listByVolumeId(long volumeId); - List listByVolumeId(Filter filter, long volumeId); - SnapshotVO findNextSnapshot(long parentSnapId); - long getLastSnapshot(long volumeId, long snapId); + List listByVolumeId(long volumeId); + + List listByVolumeId(Filter filter, long volumeId); + + SnapshotVO findNextSnapshot(long parentSnapId); + + long getLastSnapshot(long volumeId, DataStoreRole role); + List listByVolumeIdType(long volumeId, Type type); + List listByVolumeIdIncludingRemoved(long volumeId); + List listByBackupUuid(long volumeId, String backupUuid); + long updateSnapshotVersion(long volumeId, String from, String to); + List listByVolumeIdVersion(long volumeId, String version); + Long getSecHostId(long volumeId); + long updateSnapshotSecHost(long dcId, long secHostId); - List listByHostId(Filter filter, long hostId); - List listByHostId(long hostId); + public Long countSnapshotsForAccount(long accountId); + List listByInstanceId(long instanceId, Snapshot.State... status); + List listByStatus(long volumeId, Snapshot.State... status); + List listAllByStatus(Snapshot.State... status); + /** - * Gets the Total Secondary Storage space (in bytes) used by snapshots allocated for an account - * + * Gets the Total Secondary Storage space (in bytes) used by snapshots + * allocated for an account + * * @param account * @return total Secondary Storage space allocated */ diff --git a/engine/schema/src/com/cloud/storage/dao/SnapshotDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/SnapshotDaoImpl.java index f55663fe204..f5319ea120a 100644 --- a/engine/schema/src/com/cloud/storage/dao/SnapshotDaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/SnapshotDaoImpl.java @@ -28,6 +28,7 @@ import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import com.cloud.server.ResourceTag.TaggedResourceType; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.Snapshot; import com.cloud.storage.Snapshot.Event; import com.cloud.storage.Snapshot.State; @@ -51,12 +52,13 @@ import com.cloud.vm.VMInstanceVO; import com.cloud.vm.dao.VMInstanceDao; @Component -@Local (value={SnapshotDao.class}) +@Local(value = { SnapshotDao.class }) public class SnapshotDaoImpl extends GenericDaoBase implements SnapshotDao { public static final Logger s_logger = Logger.getLogger(SnapshotDaoImpl.class.getName()); - private static final String GET_LAST_SNAPSHOT = "SELECT id FROM snapshots where volume_id = ? AND id != ? AND path IS NOT NULL ORDER BY created DESC"; + // TODO: we should remove these direct sqls + private static final String GET_LAST_SNAPSHOT = "SELECT snapshots.id FROM snapshot_store_ref, snapshots where snapshots.id = snapshot_store_ref.snapshot_id AND snapshosts.volume_id = ? AND snapshot_store_ref.role = ? ORDER BY created DESC"; private static final String UPDATE_SNAPSHOT_VERSION = "UPDATE snapshots SET version = ? WHERE volume_id = ? AND version = ?"; - private static final String GET_SECHOST_ID = "SELECT sechost_id FROM snapshots where volume_id = ? AND backup_snap_id IS NOT NULL AND sechost_id IS NOT NULL LIMIT 1"; + private static final String GET_SECHOST_ID = "SELECT store_id FROM snapshots, snapshot_store_ref where snapshots.id = snapshot_store_ref.snapshot_id AND volume_id = ? AND backup_snap_id IS NOT NULL AND sechost_id IS NOT NULL LIMIT 1"; private static final String UPDATE_SECHOST_ID = "UPDATE snapshots SET sechost_id = ? WHERE data_center_id = ?"; private SearchBuilder VolumeIdSearch; @@ -64,15 +66,17 @@ public class SnapshotDaoImpl extends GenericDaoBase implements private SearchBuilder ParentIdSearch; private SearchBuilder backupUuidSearch; private SearchBuilder VolumeIdVersionSearch; - private SearchBuilder HostIdSearch; private SearchBuilder AccountIdSearch; private SearchBuilder InstanceIdSearch; private SearchBuilder StatusSearch; private GenericSearchBuilder CountSnapshotsByAccount; private GenericSearchBuilder secondaryStorageSearch; - @Inject ResourceTagDao _tagsDao; - @Inject protected VMInstanceDao _instanceDao; - @Inject protected VolumeDao _volumeDao; + @Inject + ResourceTagDao _tagsDao; + @Inject + protected VMInstanceDao _instanceDao; + @Inject + protected VolumeDao _volumeDao; @Override public SnapshotVO findNextSnapshot(long snapshotId) { @@ -80,22 +84,21 @@ public class SnapshotDaoImpl extends GenericDaoBase implements sc.setParameters("prevSnapshotId", snapshotId); return findOneIncludingRemovedBy(sc); } - + @Override - public List listByBackupUuid(long volumeId, String backupUuid) { + public List listByBackupUuid(long volumeId, String backupUuid) { SearchCriteria sc = backupUuidSearch.create(); sc.setParameters("backupUuid", backupUuid); return listBy(sc, null); } - + @Override - public List listByVolumeIdType(long volumeId, Type type ) { + public List listByVolumeIdType(long volumeId, Type type) { return listByVolumeIdType(null, volumeId, type); } - - + @Override - public List listByVolumeIdVersion(long volumeId, String version ) { + public List listByVolumeIdVersion(long volumeId, String version) { return listByVolumeIdVersion(null, volumeId, version); } @@ -103,42 +106,29 @@ public class SnapshotDaoImpl extends GenericDaoBase implements public List listByVolumeId(long volumeId) { return listByVolumeId(null, volumeId); } - + @Override - public List listByVolumeId(Filter filter, long volumeId ) { + public List listByVolumeId(Filter filter, long volumeId) { SearchCriteria sc = VolumeIdSearch.create(); sc.setParameters("volumeId", volumeId); return listBy(sc, filter); } - - @Override - public List listByHostId(long hostId) { - return listByHostId(null, hostId); - } - - @Override - public List listByHostId(Filter filter, long hostId ) { - SearchCriteria sc = HostIdSearch.create(); - sc.setParameters("hostId", hostId); - sc.setParameters("status", Snapshot.State.BackedUp); - return listBy(sc, filter); - } - + @Override public List listByVolumeIdIncludingRemoved(long volumeId) { SearchCriteria sc = VolumeIdSearch.create(); sc.setParameters("volumeId", volumeId); return listIncludingRemovedBy(sc, null); } - - public List listByVolumeIdType(Filter filter, long volumeId, Type type ) { + + public List listByVolumeIdType(Filter filter, long volumeId, Type type) { SearchCriteria sc = VolumeIdTypeSearch.create(); sc.setParameters("volumeId", volumeId); sc.setParameters("type", type.ordinal()); return listBy(sc, filter); } - - public List listByVolumeIdVersion(Filter filter, long volumeId, String version ) { + + public List listByVolumeIdVersion(Filter filter, long volumeId, String version) { SearchCriteria sc = VolumeIdVersionSearch.create(); sc.setParameters("volumeId", volumeId); sc.setParameters("version", version); @@ -147,51 +137,48 @@ public class SnapshotDaoImpl extends GenericDaoBase implements public SnapshotDaoImpl() { } - + @PostConstruct protected void init() { VolumeIdSearch = createSearchBuilder(); VolumeIdSearch.and("volumeId", VolumeIdSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); VolumeIdSearch.done(); - - HostIdSearch = createSearchBuilder(); - HostIdSearch.and("hostId", HostIdSearch.entity().getSecHostId(), SearchCriteria.Op.EQ); - HostIdSearch.and("status", HostIdSearch.entity().getState(), SearchCriteria.Op.EQ); - HostIdSearch.done(); - + VolumeIdTypeSearch = createSearchBuilder(); VolumeIdTypeSearch.and("volumeId", VolumeIdTypeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); VolumeIdTypeSearch.and("type", VolumeIdTypeSearch.entity().getsnapshotType(), SearchCriteria.Op.EQ); VolumeIdTypeSearch.done(); - + VolumeIdVersionSearch = createSearchBuilder(); VolumeIdVersionSearch.and("volumeId", VolumeIdVersionSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); VolumeIdVersionSearch.and("version", VolumeIdVersionSearch.entity().getVersion(), SearchCriteria.Op.EQ); VolumeIdVersionSearch.done(); - - ParentIdSearch = createSearchBuilder(); - ParentIdSearch.and("prevSnapshotId", ParentIdSearch.entity().getPrevSnapshotId(), SearchCriteria.Op.EQ); - ParentIdSearch.done(); - - backupUuidSearch = createSearchBuilder(); - backupUuidSearch.and("backupUuid", backupUuidSearch.entity().getBackupSnapshotId(), SearchCriteria.Op.EQ); - backupUuidSearch.done(); - + /* + * ParentIdSearch = createSearchBuilder(); + * ParentIdSearch.and("prevSnapshotId", + * ParentIdSearch.entity().getPrevSnapshotId(), SearchCriteria.Op.EQ); + * ParentIdSearch.done(); + * + * backupUuidSearch = createSearchBuilder(); + * backupUuidSearch.and("backupUuid", + * backupUuidSearch.entity().getBackupSnapshotId(), + * SearchCriteria.Op.EQ); backupUuidSearch.done(); + */ AccountIdSearch = createSearchBuilder(); AccountIdSearch.and("accountId", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ); AccountIdSearch.done(); - + StatusSearch = createSearchBuilder(); StatusSearch.and("volumeId", StatusSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); StatusSearch.and("status", StatusSearch.entity().getState(), SearchCriteria.Op.IN); StatusSearch.done(); - + CountSnapshotsByAccount = createSearchBuilder(Long.class); - CountSnapshotsByAccount.select(null, Func.COUNT, null); + CountSnapshotsByAccount.select(null, Func.COUNT, null); CountSnapshotsByAccount.and("account", CountSnapshotsByAccount.entity().getAccountId(), SearchCriteria.Op.EQ); CountSnapshotsByAccount.and("removed", CountSnapshotsByAccount.entity().getRemoved(), SearchCriteria.Op.NULL); CountSnapshotsByAccount.done(); - + InstanceIdSearch = createSearchBuilder(); InstanceIdSearch.and("status", InstanceIdSearch.entity().getState(), SearchCriteria.Op.IN); @@ -200,9 +187,11 @@ public class SnapshotDaoImpl extends GenericDaoBase implements SearchBuilder volumeSearch = _volumeDao.createSearchBuilder(); volumeSearch.and("state", volumeSearch.entity().getState(), SearchCriteria.Op.EQ); - volumeSearch.join("instanceVolumes", instanceSearch, instanceSearch.entity().getId(), volumeSearch.entity().getInstanceId(), JoinType.INNER); + volumeSearch.join("instanceVolumes", instanceSearch, instanceSearch.entity().getId(), volumeSearch.entity() + .getInstanceId(), JoinType.INNER); - InstanceIdSearch.join("instanceSnapshots", volumeSearch, volumeSearch.entity().getId(), InstanceIdSearch.entity().getVolumeId(), JoinType.INNER); + InstanceIdSearch.join("instanceSnapshots", volumeSearch, volumeSearch.entity().getId(), InstanceIdSearch + .entity().getVolumeId(), JoinType.INNER); InstanceIdSearch.done(); secondaryStorageSearch = createSearchBuilder(SumCount.class); @@ -227,17 +216,18 @@ public class SnapshotDaoImpl extends GenericDaoBase implements } } catch (Exception ex) { } - return null; + return null; } + @Override - public long getLastSnapshot(long volumeId, long snapId) { + public long getLastSnapshot(long volumeId, DataStoreRole role) { Transaction txn = Transaction.currentTxn(); PreparedStatement pstmt = null; String sql = GET_LAST_SNAPSHOT; try { pstmt = txn.prepareAutoCloseStatement(sql); pstmt.setLong(1, volumeId); - pstmt.setLong(2, snapId); + pstmt.setString(2, role.toString()); ResultSet rs = pstmt.executeQuery(); if (rs.next()) { return rs.getLong(1); @@ -265,7 +255,7 @@ public class SnapshotDaoImpl extends GenericDaoBase implements } return 0; } - + @Override public long updateSnapshotSecHost(long dcId, long secHostId) { Transaction txn = Transaction.currentTxn(); @@ -285,32 +275,32 @@ public class SnapshotDaoImpl extends GenericDaoBase implements @Override public Long countSnapshotsForAccount(long accountId) { - SearchCriteria sc = CountSnapshotsByAccount.create(); + SearchCriteria sc = CountSnapshotsByAccount.create(); sc.setParameters("account", accountId); return customSearch(sc, null).get(0); } - + @Override - public List listByInstanceId(long instanceId, Snapshot.State... status) { - SearchCriteria sc = this.InstanceIdSearch.create(); - - if (status != null && status.length != 0) { - sc.setParameters("status", (Object[])status); - } - - sc.setJoinParameters("instanceSnapshots", "state", Volume.State.Ready); - sc.setJoinParameters("instanceVolumes", "instanceId", instanceId); + public List listByInstanceId(long instanceId, Snapshot.State... status) { + SearchCriteria sc = this.InstanceIdSearch.create(); + + if (status != null && status.length != 0) { + sc.setParameters("status", (Object[]) status); + } + + sc.setJoinParameters("instanceSnapshots", "state", Volume.State.Ready); + sc.setJoinParameters("instanceVolumes", "instanceId", instanceId); return listBy(sc, null); } - + @Override public List listByStatus(long volumeId, Snapshot.State... status) { - SearchCriteria sc = this.StatusSearch.create(); - sc.setParameters("volumeId", volumeId); - sc.setParameters("status", (Object[])status); - return listBy(sc, null); + SearchCriteria sc = this.StatusSearch.create(); + sc.setParameters("volumeId", volumeId); + sc.setParameters("status", (Object[]) status); + return listBy(sc, null); } - + @Override @DB public boolean remove(Long id) { @@ -324,11 +314,11 @@ public class SnapshotDaoImpl extends GenericDaoBase implements txn.commit(); return result; } - + @Override public List listAllByStatus(Snapshot.State... status) { SearchCriteria sc = this.StatusSearch.create(); - sc.setParameters("status", (Object[])status); + sc.setParameters("status", (Object[]) status); return listBy(sc, null); } @@ -336,7 +326,7 @@ public class SnapshotDaoImpl extends GenericDaoBase implements public boolean updateState(State currentState, Event event, State nextState, SnapshotVO snapshot, Object data) { Transaction txn = Transaction.currentTxn(); txn.start(); - SnapshotVO snapshotVO = (SnapshotVO)snapshot; + SnapshotVO snapshotVO = (SnapshotVO) snapshot; snapshotVO.setState(nextState); super.update(snapshotVO.getId(), snapshotVO); txn.commit(); diff --git a/engine/schema/src/com/cloud/storage/dao/SnapshotPolicyDao.java b/engine/schema/src/com/cloud/storage/dao/SnapshotPolicyDao.java index 467d491d779..f65b5839f75 100644 --- a/engine/schema/src/com/cloud/storage/dao/SnapshotPolicyDao.java +++ b/engine/schema/src/com/cloud/storage/dao/SnapshotPolicyDao.java @@ -28,11 +28,17 @@ import com.cloud.utils.db.GenericDao; * Data Access Object for snapshot_policy table */ public interface SnapshotPolicyDao extends GenericDao { - List listByVolumeId(long volumeId); - List listByVolumeId(long volumeId, Filter filter); + List listByVolumeId(long volumeId); + + List listByVolumeId(long volumeId, Filter filter); + Pair, Integer> listAndCountByVolumeId(long volumeId); + Pair, Integer> listAndCountByVolumeId(long volumeId, Filter filter); - SnapshotPolicyVO findOneByVolumeInterval(long volumeId, IntervalType intvType); + + SnapshotPolicyVO findOneByVolumeInterval(long volumeId, IntervalType intvType); + List listActivePolicies(); + SnapshotPolicyVO findOneByVolume(long volumeId); } diff --git a/engine/schema/src/com/cloud/storage/dao/SnapshotPolicyDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/SnapshotPolicyDaoImpl.java index 5394a8fa103..76359223bb3 100644 --- a/engine/schema/src/com/cloud/storage/dao/SnapshotPolicyDaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/SnapshotPolicyDaoImpl.java @@ -16,7 +16,6 @@ // under the License. package com.cloud.storage.dao; - import java.util.List; import javax.ejb.Local; @@ -32,40 +31,40 @@ import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; @Component -@Local (value={SnapshotPolicyDao.class}) +@Local(value = { SnapshotPolicyDao.class }) public class SnapshotPolicyDaoImpl extends GenericDaoBase implements SnapshotPolicyDao { - private final SearchBuilder VolumeIdSearch; - private final SearchBuilder VolumeIdIntervalSearch; - private final SearchBuilder ActivePolicySearch; - - @Override - public SnapshotPolicyVO findOneByVolumeInterval(long volumeId, IntervalType intvType) { - SearchCriteria sc = VolumeIdIntervalSearch.create(); + private final SearchBuilder VolumeIdSearch; + private final SearchBuilder VolumeIdIntervalSearch; + private final SearchBuilder ActivePolicySearch; + + @Override + public SnapshotPolicyVO findOneByVolumeInterval(long volumeId, IntervalType intvType) { + SearchCriteria sc = VolumeIdIntervalSearch.create(); sc.setParameters("volumeId", volumeId); sc.setParameters("interval", intvType.ordinal()); - return findOneBy(sc); - } - - @Override + return findOneBy(sc); + } + + @Override public SnapshotPolicyVO findOneByVolume(long volumeId) { SearchCriteria sc = VolumeIdSearch.create(); sc.setParameters("volumeId", volumeId); sc.setParameters("active", true); return findOneBy(sc); } - - @Override - public List listByVolumeId(long volumeId) { - return listByVolumeId(volumeId, null); - } - + + @Override + public List listByVolumeId(long volumeId) { + return listByVolumeId(volumeId, null); + } + @Override public List listByVolumeId(long volumeId, Filter filter) { SearchCriteria sc = VolumeIdSearch.create(); sc.setParameters("volumeId", volumeId); return listBy(sc, filter); } - + @Override public Pair, Integer> listAndCountByVolumeId(long volumeId) { return listAndCountByVolumeId(volumeId, null); @@ -84,12 +83,12 @@ public class SnapshotPolicyDaoImpl extends GenericDaoBase sc = ActivePolicySearch.create(); sc.setParameters("active", true); return listIncludingRemovedBy(sc); - } + } } \ No newline at end of file diff --git a/engine/schema/src/com/cloud/storage/dao/SnapshotScheduleDao.java b/engine/schema/src/com/cloud/storage/dao/SnapshotScheduleDao.java index 0419e2836a0..7ca0a3915f5 100644 --- a/engine/schema/src/com/cloud/storage/dao/SnapshotScheduleDao.java +++ b/engine/schema/src/com/cloud/storage/dao/SnapshotScheduleDao.java @@ -16,10 +16,9 @@ // under the License. package com.cloud.storage.dao; - import java.util.Date; import java.util.List; -import com.cloud.storage.SnapshotPolicyVO; + import com.cloud.storage.SnapshotScheduleVO; import com.cloud.utils.db.GenericDao; @@ -28,7 +27,7 @@ import com.cloud.utils.db.GenericDao; */ public interface SnapshotScheduleDao extends GenericDao { - List getCoincidingSnapshotSchedules(long volumeId, Date date); + List getCoincidingSnapshotSchedules(long volumeId, Date date); List getSchedulesToExecute(Date currentTimestamp); diff --git a/engine/schema/src/com/cloud/storage/dao/SnapshotScheduleDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/SnapshotScheduleDaoImpl.java index c01644e0918..72d47fa4dcc 100644 --- a/engine/schema/src/com/cloud/storage/dao/SnapshotScheduleDaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/SnapshotScheduleDaoImpl.java @@ -30,60 +30,63 @@ import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; @Component -@Local (value={SnapshotScheduleDao.class}) +@Local(value = { SnapshotScheduleDao.class }) public class SnapshotScheduleDaoImpl extends GenericDaoBase implements SnapshotScheduleDao { - protected final SearchBuilder executableSchedulesSearch; - protected final SearchBuilder coincidingSchedulesSearch; + protected final SearchBuilder executableSchedulesSearch; + protected final SearchBuilder coincidingSchedulesSearch; private final SearchBuilder VolumeIdSearch; private final SearchBuilder VolumeIdPolicyIdSearch; - - - protected SnapshotScheduleDaoImpl() { - - executableSchedulesSearch = createSearchBuilder(); - executableSchedulesSearch.and("scheduledTimestamp", executableSchedulesSearch.entity().getScheduledTimestamp(), SearchCriteria.Op.LT); - executableSchedulesSearch.and("asyncJobId", executableSchedulesSearch.entity().getAsyncJobId(), SearchCriteria.Op.NULL); + + protected SnapshotScheduleDaoImpl() { + + executableSchedulesSearch = createSearchBuilder(); + executableSchedulesSearch.and("scheduledTimestamp", executableSchedulesSearch.entity().getScheduledTimestamp(), + SearchCriteria.Op.LT); + executableSchedulesSearch.and("asyncJobId", executableSchedulesSearch.entity().getAsyncJobId(), + SearchCriteria.Op.NULL); executableSchedulesSearch.done(); - + coincidingSchedulesSearch = createSearchBuilder(); - coincidingSchedulesSearch.and("volumeId", coincidingSchedulesSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); - coincidingSchedulesSearch.and("scheduledTimestamp", coincidingSchedulesSearch.entity().getScheduledTimestamp(), SearchCriteria.Op.LT); - coincidingSchedulesSearch.and("asyncJobId", coincidingSchedulesSearch.entity().getAsyncJobId(), SearchCriteria.Op.NULL); + coincidingSchedulesSearch.and("volumeId", coincidingSchedulesSearch.entity().getVolumeId(), + SearchCriteria.Op.EQ); + coincidingSchedulesSearch.and("scheduledTimestamp", coincidingSchedulesSearch.entity().getScheduledTimestamp(), + SearchCriteria.Op.LT); + coincidingSchedulesSearch.and("asyncJobId", coincidingSchedulesSearch.entity().getAsyncJobId(), + SearchCriteria.Op.NULL); coincidingSchedulesSearch.done(); - + VolumeIdSearch = createSearchBuilder(); VolumeIdSearch.and("volumeId", VolumeIdSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); VolumeIdSearch.done(); - + VolumeIdPolicyIdSearch = createSearchBuilder(); VolumeIdPolicyIdSearch.and("volumeId", VolumeIdPolicyIdSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); VolumeIdPolicyIdSearch.and("policyId", VolumeIdPolicyIdSearch.entity().getPolicyId(), SearchCriteria.Op.EQ); VolumeIdPolicyIdSearch.done(); - - } - - /** - * {@inheritDoc} - */ - @Override - public List getCoincidingSnapshotSchedules(long volumeId, Date date) { - SearchCriteria sc = coincidingSchedulesSearch.create(); - sc.setParameters("volumeId", volumeId); - sc.setParameters("scheduledTimestamp", date); - // Don't return manual snapshots. They will be executed through another code path. + + } + + /** + * {@inheritDoc} + */ + @Override + public List getCoincidingSnapshotSchedules(long volumeId, Date date) { + SearchCriteria sc = coincidingSchedulesSearch.create(); + sc.setParameters("volumeId", volumeId); + sc.setParameters("scheduledTimestamp", date); + // Don't return manual snapshots. They will be executed through another + // code path. sc.addAnd("policyId", SearchCriteria.Op.NEQ, 1L); return listBy(sc); - } + } - @Override public SnapshotScheduleVO findOneByVolume(long volumeId) { SearchCriteria sc = VolumeIdSearch.create(); sc.setParameters("volumeId", volumeId); return findOneBy(sc); } - - + @Override public SnapshotScheduleVO findOneByVolumePolicy(long volumeId, long policyId) { SearchCriteria sc = VolumeIdPolicyIdSearch.create(); @@ -91,8 +94,9 @@ public class SnapshotScheduleDaoImpl extends GenericDaoBase getSchedulesToExecute(Date currentTimestamp) { @@ -100,9 +104,9 @@ public class SnapshotScheduleDaoImpl extends GenericDaoBase snapshotSchedules = listBy(sc); - // This will return only one schedule because of a DB uniqueness constraint. + // This will return only one schedule because of a DB uniqueness + // constraint. assert (snapshotSchedules.size() <= 1); if (snapshotSchedules.isEmpty()) { return null; - } - else { + } else { return snapshotSchedules.get(0); } } - + } \ No newline at end of file diff --git a/engine/schema/src/com/cloud/storage/dao/StoragePoolDetailsDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/StoragePoolDetailsDaoImpl.java index 38b525330f2..8952e6cb154 100644 --- a/engine/schema/src/com/cloud/storage/dao/StoragePoolDetailsDaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/StoragePoolDetailsDaoImpl.java @@ -32,11 +32,12 @@ import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; @Component -@Local(value=StoragePoolDetailsDao.class) -public class StoragePoolDetailsDaoImpl extends GenericDaoBase implements StoragePoolDetailsDao { - +@Local(value = StoragePoolDetailsDao.class) +public class StoragePoolDetailsDaoImpl extends GenericDaoBase implements + StoragePoolDetailsDao { + protected final SearchBuilder PoolSearch; - + protected StoragePoolDetailsDaoImpl() { super(); PoolSearch = createSearchBuilder(); @@ -44,13 +45,13 @@ public class StoragePoolDetailsDaoImpl extends GenericDaoBase details) { Transaction txn = Transaction.currentTxn(); SearchCriteria sc = PoolSearch.create(); sc.setParameters("pool", poolId); - + txn.start(); expunge(sc); for (Map.Entry entry : details.entrySet()) { @@ -59,19 +60,19 @@ public class StoragePoolDetailsDaoImpl extends GenericDaoBase getDetails(long poolId) { - SearchCriteria sc = PoolSearch.create(); - sc.setParameters("pool", poolId); - - List details = listBy(sc); - Map detailsMap = new HashMap(); - for (StoragePoolDetailVO detail : details) { - detailsMap.put(detail.getName(), detail.getValue()); - } - - return detailsMap; + SearchCriteria sc = PoolSearch.create(); + sc.setParameters("pool", poolId); + + List details = listBy(sc); + Map detailsMap = new HashMap(); + for (StoragePoolDetailVO detail : details) { + detailsMap.put(detail.getName(), detail.getValue()); + } + + return detailsMap; } @Override diff --git a/engine/schema/src/com/cloud/storage/dao/StoragePoolHostDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/StoragePoolHostDaoImpl.java index 4f509d14041..730216b82b0 100644 --- a/engine/schema/src/com/cloud/storage/dao/StoragePoolHostDaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/StoragePoolHostDaoImpl.java @@ -46,13 +46,16 @@ public class StoragePoolHostDaoImpl extends GenericDaoBase listByHostId(long hostId) { SearchCriteria sc = HostSearch.create(); @@ -113,7 +116,8 @@ public class StoragePoolHostDaoImpl extends GenericDaoBase void removePendingJobsOnMsRestart(long msId, long poolId); List searchForPoolIdsForPendingWorkJobs(long msId); - + } diff --git a/engine/schema/src/com/cloud/storage/dao/StoragePoolWorkDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/StoragePoolWorkDaoImpl.java index 360a814f59a..052bae4fc78 100644 --- a/engine/schema/src/com/cloud/storage/dao/StoragePoolWorkDaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/StoragePoolWorkDaoImpl.java @@ -35,43 +35,53 @@ import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; @Component -@Local(value={StoragePoolWorkDao.class}) @DB(txn=false) -public class StoragePoolWorkDaoImpl extends GenericDaoBase implements StoragePoolWorkDao { +@Local(value = { StoragePoolWorkDao.class }) +@DB(txn = false) +public class StoragePoolWorkDaoImpl extends GenericDaoBase implements StoragePoolWorkDao { protected final SearchBuilder PendingWorkForPrepareForMaintenanceSearch; protected final SearchBuilder PendingWorkForCancelMaintenanceSearch; protected final SearchBuilder PoolAndVmIdSearch; protected final SearchBuilder PendingJobsForDeadMs; - + private final String FindPoolIds = "SELECT distinct storage_pool_work.pool_id FROM storage_pool_work WHERE mgmt_server_id = ?"; - + protected StoragePoolWorkDaoImpl() { PendingWorkForPrepareForMaintenanceSearch = createSearchBuilder(); - PendingWorkForPrepareForMaintenanceSearch.and("poolId", PendingWorkForPrepareForMaintenanceSearch.entity().getPoolId(), SearchCriteria.Op.EQ); - PendingWorkForPrepareForMaintenanceSearch.and("stoppedForMaintenance", PendingWorkForPrepareForMaintenanceSearch.entity().isStoppedForMaintenance(), SearchCriteria.Op.EQ); - PendingWorkForPrepareForMaintenanceSearch.and("startedAfterMaintenance", PendingWorkForPrepareForMaintenanceSearch.entity().isStartedAfterMaintenance(), SearchCriteria.Op.EQ); + PendingWorkForPrepareForMaintenanceSearch.and("poolId", PendingWorkForPrepareForMaintenanceSearch.entity() + .getPoolId(), SearchCriteria.Op.EQ); + PendingWorkForPrepareForMaintenanceSearch.and("stoppedForMaintenance", + PendingWorkForPrepareForMaintenanceSearch.entity().isStoppedForMaintenance(), SearchCriteria.Op.EQ); + PendingWorkForPrepareForMaintenanceSearch.and("startedAfterMaintenance", + PendingWorkForPrepareForMaintenanceSearch.entity().isStartedAfterMaintenance(), SearchCriteria.Op.EQ); PendingWorkForPrepareForMaintenanceSearch.done(); - + PendingWorkForCancelMaintenanceSearch = createSearchBuilder(); - PendingWorkForCancelMaintenanceSearch.and("poolId", PendingWorkForCancelMaintenanceSearch.entity().getPoolId(), SearchCriteria.Op.EQ); - PendingWorkForCancelMaintenanceSearch.and("stoppedForMaintenance", PendingWorkForCancelMaintenanceSearch.entity().isStoppedForMaintenance(), SearchCriteria.Op.EQ); - PendingWorkForCancelMaintenanceSearch.and("startedAfterMaintenance", PendingWorkForCancelMaintenanceSearch.entity().isStartedAfterMaintenance(), SearchCriteria.Op.EQ); + PendingWorkForCancelMaintenanceSearch.and("poolId", PendingWorkForCancelMaintenanceSearch.entity().getPoolId(), + SearchCriteria.Op.EQ); + PendingWorkForCancelMaintenanceSearch.and("stoppedForMaintenance", PendingWorkForCancelMaintenanceSearch + .entity().isStoppedForMaintenance(), SearchCriteria.Op.EQ); + PendingWorkForCancelMaintenanceSearch.and("startedAfterMaintenance", PendingWorkForCancelMaintenanceSearch + .entity().isStartedAfterMaintenance(), SearchCriteria.Op.EQ); PendingWorkForCancelMaintenanceSearch.done(); PoolAndVmIdSearch = createSearchBuilder(); PoolAndVmIdSearch.and("poolId", PoolAndVmIdSearch.entity().getPoolId(), SearchCriteria.Op.EQ); PoolAndVmIdSearch.and("vmId", PoolAndVmIdSearch.entity().getVmId(), SearchCriteria.Op.EQ); PoolAndVmIdSearch.done(); - + PendingJobsForDeadMs = createSearchBuilder(); - PendingJobsForDeadMs.and("managementServerId", PendingJobsForDeadMs.entity().getManagementServerId(), SearchCriteria.Op.EQ); + PendingJobsForDeadMs.and("managementServerId", PendingJobsForDeadMs.entity().getManagementServerId(), + SearchCriteria.Op.EQ); PendingJobsForDeadMs.and("poolId", PendingJobsForDeadMs.entity().getPoolId(), SearchCriteria.Op.EQ); - PendingJobsForDeadMs.and("stoppedForMaintenance", PendingJobsForDeadMs.entity().isStoppedForMaintenance(), SearchCriteria.Op.EQ); - PendingJobsForDeadMs.and("startedAfterMaintenance", PendingJobsForDeadMs.entity().isStartedAfterMaintenance(), SearchCriteria.Op.EQ); + PendingJobsForDeadMs.and("stoppedForMaintenance", PendingJobsForDeadMs.entity().isStoppedForMaintenance(), + SearchCriteria.Op.EQ); + PendingJobsForDeadMs.and("startedAfterMaintenance", PendingJobsForDeadMs.entity().isStartedAfterMaintenance(), + SearchCriteria.Op.EQ); PendingJobsForDeadMs.done(); - + } - + @Override public List listPendingWorkForPrepareForMaintenanceByPoolId(long poolId) { SearchCriteria sc = PendingWorkForPrepareForMaintenanceSearch.create(); @@ -80,7 +90,7 @@ public class StoragePoolWorkDaoImpl extends GenericDaoBase listPendingWorkForCancelMaintenanceByPoolId(long poolId) { SearchCriteria sc = PendingWorkForCancelMaintenanceSearch.create(); @@ -89,7 +99,7 @@ public class StoragePoolWorkDaoImpl extends GenericDaoBase sc = PoolAndVmIdSearch.create(); @@ -97,22 +107,22 @@ public class StoragePoolWorkDaoImpl extends GenericDaoBase sc = PendingJobsForDeadMs.create(); sc.setParameters("managementServerId", msId); sc.setParameters("poolId", poolId); sc.setParameters("stoppedForMaintenance", true); - sc.setParameters("startedAfterMaintenance", false); + sc.setParameters("startedAfterMaintenance", false); remove(sc); } - + @Override @DB - public List searchForPoolIdsForPendingWorkJobs(long msId){ - + public List searchForPoolIdsForPendingWorkJobs(long msId) { + StringBuilder sql = new StringBuilder(FindPoolIds); Transaction txn = Transaction.currentTxn(); @@ -126,7 +136,7 @@ public class StoragePoolWorkDaoImpl extends GenericDaoBase implements SwiftDao { public static final Logger s_logger = Logger.getLogger(SwiftDaoImpl.class.getName()); diff --git a/engine/schema/src/com/cloud/storage/dao/UploadDao.java b/engine/schema/src/com/cloud/storage/dao/UploadDao.java index 06336ae04cc..0defb36ebb5 100755 --- a/engine/schema/src/com/cloud/storage/dao/UploadDao.java +++ b/engine/schema/src/com/cloud/storage/dao/UploadDao.java @@ -24,13 +24,12 @@ import com.cloud.storage.Upload.Type; import com.cloud.storage.Upload.Mode; import com.cloud.utils.db.GenericDao; -public interface UploadDao extends GenericDao { +public interface UploadDao extends GenericDao { - List listByTypeUploadStatus(long typeId, Type type, - Status uploadState); + List listByTypeUploadStatus(long typeId, Type type, Status uploadState); - List listByHostAndUploadStatus(long sserverId, Status uploadInProgress); - - List listByModeAndStatus(Mode mode, Status uploadState); + List listByHostAndUploadStatus(long sserverId, Status uploadInProgress); + + List listByModeAndStatus(Mode mode, Status uploadState); } diff --git a/engine/schema/src/com/cloud/storage/dao/UploadDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/UploadDaoImpl.java index 31fad43e257..8e112bff17f 100755 --- a/engine/schema/src/com/cloud/storage/dao/UploadDaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/UploadDaoImpl.java @@ -15,6 +15,7 @@ // specific language governing permissions and limitations // under the License. package com.cloud.storage.dao; + import java.util.List; import javax.ejb.Local; @@ -29,64 +30,64 @@ import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; @Component -@Local(value={UploadDao.class}) +@Local(value = { UploadDao.class }) public class UploadDaoImpl extends GenericDaoBase implements UploadDao { - public static final Logger s_logger = Logger.getLogger(UploadDaoImpl.class.getName()); - protected final SearchBuilder typeUploadStatusSearch; - protected final SearchBuilder typeHostAndUploadStatusSearch; - protected final SearchBuilder typeModeAndStatusSearch; - - protected static final String UPDATE_UPLOAD_INFO = - "UPDATE upload SET upload_state = ?, upload_pct= ?, last_updated = ? " - + ", upload_error_str = ?, upload_job_id = ? " - + "WHERE host_id = ? and type_id = ? and type = ?"; - - protected static final String UPLOADS_STATE_DC= - "SELECT * FROM upload t, host h where t.host_id = h.id and h.data_center_id=? " - + " and t.type_id=? and t.upload_state = ?" ; - - - public UploadDaoImpl() { - typeUploadStatusSearch = createSearchBuilder(); - typeUploadStatusSearch.and("type_id", typeUploadStatusSearch.entity().getTypeId(), SearchCriteria.Op.EQ); - typeUploadStatusSearch.and("upload_state", typeUploadStatusSearch.entity().getUploadState(), SearchCriteria.Op.EQ); - typeUploadStatusSearch.and("type", typeUploadStatusSearch.entity().getType(), SearchCriteria.Op.EQ); - typeUploadStatusSearch.done(); - - typeHostAndUploadStatusSearch = createSearchBuilder(); - typeHostAndUploadStatusSearch.and("host_id", typeHostAndUploadStatusSearch.entity().getHostId(), SearchCriteria.Op.EQ); - typeHostAndUploadStatusSearch.and("upload_state", typeHostAndUploadStatusSearch.entity().getUploadState(), SearchCriteria.Op.EQ); - typeHostAndUploadStatusSearch.done(); - - typeModeAndStatusSearch = createSearchBuilder(); - typeModeAndStatusSearch.and("mode", typeModeAndStatusSearch.entity().getMode(), SearchCriteria.Op.EQ); - typeModeAndStatusSearch.and("upload_state", typeModeAndStatusSearch.entity().getUploadState(), SearchCriteria.Op.EQ); - typeModeAndStatusSearch.done(); - - } - - @Override - public List listByTypeUploadStatus(long typeId, UploadVO.Type type, UploadVO.Status uploadState) { - SearchCriteria sc = typeUploadStatusSearch.create(); - sc.setParameters("type_id", typeId); - sc.setParameters("type", type); - sc.setParameters("upload_state", uploadState.toString()); - return listBy(sc); - } - - @Override - public List listByHostAndUploadStatus(long sserverId, Status uploadState){ + public static final Logger s_logger = Logger.getLogger(UploadDaoImpl.class.getName()); + protected final SearchBuilder typeUploadStatusSearch; + protected final SearchBuilder typeHostAndUploadStatusSearch; + protected final SearchBuilder typeModeAndStatusSearch; + + protected static final String UPDATE_UPLOAD_INFO = "UPDATE upload SET upload_state = ?, upload_pct= ?, last_updated = ? " + + ", upload_error_str = ?, upload_job_id = ? " + "WHERE host_id = ? and type_id = ? and type = ?"; + + protected static final String UPLOADS_STATE_DC = "SELECT * FROM upload t, host h where t.host_id = h.id and h.data_center_id=? " + + " and t.type_id=? and t.upload_state = ?"; + + public UploadDaoImpl() { + typeUploadStatusSearch = createSearchBuilder(); + typeUploadStatusSearch.and("type_id", typeUploadStatusSearch.entity().getTypeId(), SearchCriteria.Op.EQ); + typeUploadStatusSearch.and("upload_state", typeUploadStatusSearch.entity().getUploadState(), + SearchCriteria.Op.EQ); + typeUploadStatusSearch.and("type", typeUploadStatusSearch.entity().getType(), SearchCriteria.Op.EQ); + typeUploadStatusSearch.done(); + + typeHostAndUploadStatusSearch = createSearchBuilder(); + typeHostAndUploadStatusSearch.and("host_id", typeHostAndUploadStatusSearch.entity().getDataStoreId(), + SearchCriteria.Op.EQ); + typeHostAndUploadStatusSearch.and("upload_state", typeHostAndUploadStatusSearch.entity().getUploadState(), + SearchCriteria.Op.EQ); + typeHostAndUploadStatusSearch.done(); + + typeModeAndStatusSearch = createSearchBuilder(); + typeModeAndStatusSearch.and("mode", typeModeAndStatusSearch.entity().getMode(), SearchCriteria.Op.EQ); + typeModeAndStatusSearch.and("upload_state", typeModeAndStatusSearch.entity().getUploadState(), + SearchCriteria.Op.EQ); + typeModeAndStatusSearch.done(); + + } + + @Override + public List listByTypeUploadStatus(long typeId, UploadVO.Type type, UploadVO.Status uploadState) { + SearchCriteria sc = typeUploadStatusSearch.create(); + sc.setParameters("type_id", typeId); + sc.setParameters("type", type); + sc.setParameters("upload_state", uploadState.toString()); + return listBy(sc); + } + + @Override + public List listByHostAndUploadStatus(long sserverId, Status uploadState) { SearchCriteria sc = typeHostAndUploadStatusSearch.create(); sc.setParameters("host_id", sserverId); sc.setParameters("upload_state", uploadState.toString()); return listBy(sc); - } - - @Override - public List listByModeAndStatus(Mode mode, Status uploadState){ - SearchCriteria sc = typeModeAndStatusSearch.create(); - sc.setParameters("mode", mode.toString()); - sc.setParameters("upload_state", uploadState.toString()); - return listBy(sc); - } + } + + @Override + public List listByModeAndStatus(Mode mode, Status uploadState) { + SearchCriteria sc = typeModeAndStatusSearch.create(); + sc.setParameters("mode", mode.toString()); + sc.setParameters("upload_state", uploadState.toString()); + return listBy(sc); + } } \ No newline at end of file diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateDao.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateDao.java index 7c66dd4b46b..c3d44bdb6aa 100755 --- a/engine/schema/src/com/cloud/storage/dao/VMTemplateDao.java +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateDao.java @@ -18,67 +18,62 @@ package com.cloud.storage.dao; import java.util.List; import java.util.Map; -import java.util.Set; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateState; -import com.cloud.domain.DomainVO; import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.projects.Project.ListProjectResourcesCriteria; import com.cloud.storage.VMTemplateVO; -import com.cloud.template.VirtualMachineTemplate.TemplateFilter; -import com.cloud.user.Account; -import com.cloud.utils.Pair; import com.cloud.utils.db.GenericDao; import com.cloud.utils.fsm.StateDao; /* * Data Access Object for vm_templates table */ -public interface VMTemplateDao extends GenericDao, StateDao { - - - public List listByPublic(); - public VMTemplateVO findByName(String templateName); - public VMTemplateVO findByTemplateName(String templateName); +public interface VMTemplateDao extends GenericDao { - //public void update(VMTemplateVO template); + public List listByPublic(); + public VMTemplateVO findByName(String templateName); - public List listAllSystemVMTemplates(); + public VMTemplateVO findByTemplateName(String templateName); - public List listDefaultBuiltinTemplates(); - public String getRoutingTemplateUniqueName(); - public List findIsosByIdAndPath(Long domainId, Long accountId, String path); - public List listReadyTemplates(); - public List listByAccountId(long accountId); - public Set> searchTemplates(String name, String keyword, TemplateFilter templateFilter, boolean isIso, - List hypers, Boolean bootable, DomainVO domain, Long pageSize, Long startIndex, Long zoneId, - HypervisorType hyperType, boolean onlyReady, boolean showDomr, List permittedAccounts, Account caller, - ListProjectResourcesCriteria listProjectResourcesCriteria, Map tags); - - public Set> searchSwiftTemplates(String name, String keyword, TemplateFilter templateFilter, - boolean isIso, List hypers, Boolean bootable, DomainVO domain, Long pageSize, Long startIndex, - Long zoneId, HypervisorType hyperType, boolean onlyReady, boolean showDomr, List permittedAccounts, Account caller, Map tags); + // public void update(VMTemplateVO template); - public Set> searchS3Templates(String name, String keyword, TemplateFilter templateFilter, - boolean isIso, List hypers, Boolean bootable, DomainVO domain, Long pageSize, Long startIndex, - Long zoneId, HypervisorType hyperType, boolean onlyReady, boolean showDomr, List permittedAccounts, Account caller, Map tags); + public List listAllSystemVMTemplates(); + + public List listDefaultBuiltinTemplates(); + + public String getRoutingTemplateUniqueName(); + + public List findIsosByIdAndPath(Long domainId, Long accountId, String path); + + public List listReadyTemplates(); + + public List listByAccountId(long accountId); + + public long addTemplateToZone(VMTemplateVO tmplt, long zoneId); + + public List listAllInZone(long dataCenterId); + + public List listAllActive(); - public long addTemplateToZone(VMTemplateVO tmplt, long zoneId); - public List listAllInZone(long dataCenterId); - public List listByHypervisorType(List hyperTypes); - public List publicIsoSearch(Boolean bootable, boolean listRemoved, Map tags); - public List userIsoSearch(boolean listRemoved); + + public List publicIsoSearch(Boolean bootable, boolean listRemoved, Map tags); + + public List userIsoSearch(boolean listRemoved); + VMTemplateVO findSystemVMTemplate(long zoneId); + VMTemplateVO findSystemVMTemplate(long zoneId, HypervisorType hType); VMTemplateVO findRoutingTemplate(HypervisorType type, String templateName); + List listPrivateTemplatesByHost(Long hostId); + public Long countTemplatesForAccount(long accountId); - + List findTemplatesToSyncToS3(); } diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java index d45ef73168b..e7b85f8a63f 100755 --- a/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java @@ -16,25 +16,18 @@ // under the License. package com.cloud.storage.dao; -import static com.cloud.utils.StringUtils.join; -import static com.cloud.utils.db.DbUtil.closeResources; - import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; -import java.util.HashSet; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Set; import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateState; import org.apache.log4j.Logger; @@ -42,25 +35,19 @@ import org.springframework.stereotype.Component; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.dao.DataCenterDao; -import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.projects.Project.ListProjectResourcesCriteria; import com.cloud.server.ResourceTag.TaggedResourceType; import com.cloud.storage.Storage; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; -import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateZoneVO; import com.cloud.tags.ResourceTagVO; import com.cloud.tags.dao.ResourceTagDao; -import com.cloud.template.VirtualMachineTemplate.TemplateFilter; -import com.cloud.user.Account; -import com.cloud.utils.Pair; import com.cloud.utils.db.DB; import com.cloud.utils.db.Filter; import com.cloud.utils.db.GenericDaoBase; @@ -75,7 +62,7 @@ import com.cloud.utils.db.UpdateBuilder; import com.cloud.utils.exception.CloudRuntimeException; @Component -@Local(value={VMTemplateDao.class}) +@Local(value = { VMTemplateDao.class }) public class VMTemplateDaoImpl extends GenericDaoBase implements VMTemplateDao { private static final Logger s_logger = Logger.getLogger(VMTemplateDaoImpl.class); @@ -85,31 +72,20 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem VMTemplateDetailsDao _templateDetailsDao; @Inject - ConfigurationDao _configDao; + ConfigurationDao _configDao; @Inject - HostDao _hostDao; + HostDao _hostDao; @Inject DomainDao _domainDao; @Inject DataCenterDao _dcDao; - private final String SELECT_TEMPLATE_HOST_REF = "SELECT t.id, h.data_center_id, t.unique_name, t.name, t.public, t.featured, t.type, t.hvm, t.bits, t.url, t.format, t.created, t.account_id, " + - "t.checksum, t.display_text, t.enable_password, t.guest_os_id, t.bootable, t.prepopulate, t.cross_zones, t.hypervisor_type FROM vm_template t"; - private final String SELECT_TEMPLATE_ZONE_REF = "SELECT t.id, tzr.zone_id, t.unique_name, t.name, t.public, t.featured, t.type, t.hvm, t.bits, t.url, t.format, t.created, t.account_id, " + - "t.checksum, t.display_text, t.enable_password, t.guest_os_id, t.bootable, t.prepopulate, t.cross_zones, t.hypervisor_type FROM vm_template t INNER JOIN template_zone_ref tzr on (t.id = tzr.template_id) "; - - private final String SELECT_TEMPLATE_SWIFT_REF = "SELECT t.id, t.unique_name, t.name, t.public, t.featured, t.type, t.hvm, t.bits, t.url, t.format, t.created, t.account_id, " - + "t.checksum, t.display_text, t.enable_password, t.guest_os_id, t.bootable, t.prepopulate, t.cross_zones, t.hypervisor_type FROM vm_template t"; - - private final String SELECT_TEMPLATE_S3_REF = "SELECT t.id, t.unique_name, t.name, t.public, t.featured, t.type, t.hvm, t.bits, t.url, t.format, t.created, t.account_id, " - + "t.checksum, t.display_text, t.enable_password, t.guest_os_id, t.bootable, t.prepopulate, t.cross_zones, t.hypervisor_type FROM vm_template t"; - - private static final String SELECT_S3_CANDIDATE_TEMPLATES = "SELECT t.id, t.unique_name, t.name, t.public, t.featured, " + - "t.type, t.hvm, t.bits, t.url, t.format, t.created, t.account_id, t.checksum, t.display_text, " + - "t.enable_password, t.guest_os_id, t.bootable, t.prepopulate, t.cross_zones, t.hypervisor_type " + - "FROM vm_template t JOIN template_host_ref r ON t.id=r.template_id JOIN host h ON h.id=r.host_id " + - "WHERE t.hypervisor_type IN (SELECT hypervisor_type FROM host) AND r.download_state = 'DOWNLOADED' AND " + - "r.template_id NOT IN (SELECT template_id FROM template_s3_ref) AND r.destroyed = 0 AND t.type <> 'PERHOST'"; + private static final String SELECT_S3_CANDIDATE_TEMPLATES = "SELECT t.id, t.unique_name, t.name, t.public, t.featured, " + + "t.type, t.hvm, t.bits, t.url, t.format, t.created, t.account_id, t.checksum, t.display_text, " + + "t.enable_password, t.guest_os_id, t.bootable, t.prepopulate, t.cross_zones, t.hypervisor_type " + + "FROM vm_template t JOIN template_host_ref r ON t.id=r.template_id JOIN host h ON h.id=r.host_id " + + "WHERE t.hypervisor_type IN (SELECT hypervisor_type FROM host) AND r.download_state = 'DOWNLOADED' AND " + + "r.template_id NOT IN (SELECT template_id FROM template_s3_ref) AND r.destroyed = 0 AND t.type <> 'PERHOST'"; protected SearchBuilder TemplateNameSearch; protected SearchBuilder UniqueNameSearch; @@ -120,15 +96,16 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem protected SearchBuilder AccountIdSearch; protected SearchBuilder NameSearch; protected SearchBuilder TmpltsInZoneSearch; + protected SearchBuilder ActiveTmpltSearch; private SearchBuilder PublicSearch; private SearchBuilder NameAccountIdSearch; private SearchBuilder PublicIsoSearch; private SearchBuilder UserIsoSearch; private GenericSearchBuilder CountTemplatesByAccount; - private SearchBuilder updateStateSearch; - - @Inject ResourceTagDao _tagsDao; + // private SearchBuilder updateStateSearch; + @Inject + ResourceTagDao _tagsDao; private String routerTmpltName; private String consoleProxyTmpltName; @@ -138,27 +115,27 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem @Override public List listByPublic() { - SearchCriteria sc = PublicSearch.create(); - sc.setParameters("public", 1); - return listBy(sc); - } - - @Override - public VMTemplateVO findByName(String templateName) { - SearchCriteria sc = UniqueNameSearch.create(); - sc.setParameters("uniqueName", templateName); - return findOneIncludingRemovedBy(sc); - } - - @Override - public VMTemplateVO findByTemplateName(String templateName) { - SearchCriteria sc = NameSearch.create(); - sc.setParameters("name", templateName); - return findOneIncludingRemovedBy(sc); - } + SearchCriteria sc = PublicSearch.create(); + sc.setParameters("public", 1); + return listBy(sc); + } @Override - public List publicIsoSearch(Boolean bootable, boolean listRemoved, Map tags){ + public VMTemplateVO findByName(String templateName) { + SearchCriteria sc = UniqueNameSearch.create(); + sc.setParameters("uniqueName", templateName); + return findOneIncludingRemovedBy(sc); + } + + @Override + public VMTemplateVO findByTemplateName(String templateName) { + SearchCriteria sc = NameSearch.create(); + sc.setParameters("name", templateName); + return findOneIncludingRemovedBy(sc); + } + + @Override + public List publicIsoSearch(Boolean bootable, boolean listRemoved, Map tags) { SearchBuilder sb = null; if (tags == null || tags.isEmpty()) { @@ -172,30 +149,31 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem sb.and("removed", sb.entity().getRemoved(), SearchCriteria.Op.EQ); SearchBuilder tagSearch = _tagsDao.createSearchBuilder(); - for (int count=0; count < tags.size(); count++) { + for (int count = 0; count < tags.size(); count++) { tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ); tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ); tagSearch.cp(); } tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ); sb.groupBy(sb.entity().getId()); - sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER); + sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), + JoinBuilder.JoinType.INNER); } SearchCriteria sc = sb.create(); - sc.setParameters("public", 1); - sc.setParameters("format", "ISO"); - sc.setParameters("type", TemplateType.PERHOST.toString()); - if (bootable != null) { - sc.setParameters("bootable", bootable); - } + sc.setParameters("public", 1); + sc.setParameters("format", "ISO"); + sc.setParameters("type", TemplateType.PERHOST.toString()); + if (bootable != null) { + sc.setParameters("bootable", bootable); + } - if (!listRemoved) { - sc.setParameters("removed", (Object)null); - } + if (!listRemoved) { + sc.setParameters("removed", (Object) null); + } - if (tags != null && !tags.isEmpty()) { + if (tags != null && !tags.isEmpty()) { int count = 0; sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.ISO.toString()); for (String key : tags.keySet()) { @@ -209,7 +187,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem } @Override - public List userIsoSearch(boolean listRemoved){ + public List userIsoSearch(boolean listRemoved) { SearchBuilder sb = null; sb = UserIsoSearch; @@ -219,25 +197,26 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem sc.setParameters("type", TemplateType.USER.toString()); if (!listRemoved) { - sc.setParameters("removed", (Object)null); + sc.setParameters("removed", (Object) null); } return listBy(sc); } - @Override - public List listAllSystemVMTemplates() { - SearchCriteria sc = tmpltTypeSearch.create(); - sc.setParameters("templateType", Storage.TemplateType.SYSTEM); - Filter filter = new Filter(VMTemplateVO.class, "id", false, null, null); - return listBy(sc, filter); - } + @Override + public List listAllSystemVMTemplates() { + SearchCriteria sc = tmpltTypeSearch.create(); + sc.setParameters("templateType", Storage.TemplateType.SYSTEM); + + Filter filter = new Filter(VMTemplateVO.class, "id", false, null, null); + return listBy(sc, filter); + } @Override public List listPrivateTemplatesByHost(Long hostId) { String sql = "select * from template_host_ref as thr INNER JOIN vm_template as t ON t.id=thr.template_id " - + "where thr.host_id=? and t.public=0 and t.featured=0 and t.type='USER' and t.removed is NULL"; + + "where thr.host_id=? and t.public=0 and t.featured=0 and t.type='USER' and t.removed is NULL"; List l = new ArrayList(); @@ -257,654 +236,527 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem return l; } - @Override - public List listReadyTemplates() { - SearchCriteria sc = createSearchCriteria(); - sc.addAnd("ready", SearchCriteria.Op.EQ, true); - sc.addAnd("format", SearchCriteria.Op.NEQ, Storage.ImageFormat.ISO); - return listIncludingRemovedBy(sc); - } + @Override + public List listReadyTemplates() { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("ready", SearchCriteria.Op.EQ, true); + sc.addAnd("format", SearchCriteria.Op.NEQ, Storage.ImageFormat.ISO); + return listIncludingRemovedBy(sc); + } - @Override - public List findIsosByIdAndPath(Long domainId, Long accountId, String path) { - SearchCriteria sc = createSearchCriteria(); - sc.addAnd("iso", SearchCriteria.Op.EQ, true); - if (domainId != null) { + @Override + public List findIsosByIdAndPath(Long domainId, Long accountId, String path) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("iso", SearchCriteria.Op.EQ, true); + if (domainId != null) { sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId); } - if (accountId != null) { + if (accountId != null) { sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId); } - if (path != null) { + if (path != null) { sc.addAnd("path", SearchCriteria.Op.EQ, path); } - return listIncludingRemovedBy(sc); - } + return listIncludingRemovedBy(sc); + } - @Override - public List listByAccountId(long accountId) { + @Override + public List listByAccountId(long accountId) { SearchCriteria sc = AccountIdSearch.create(); sc.setParameters("accountId", accountId); return listBy(sc); - } + } - @Override + @Override public List listByHypervisorType(List hyperTypes) { - SearchCriteria sc = createSearchCriteria(); + SearchCriteria sc = createSearchCriteria(); hyperTypes.add(HypervisorType.None); sc.addAnd("hypervisorType", SearchCriteria.Op.IN, hyperTypes.toArray()); - return listBy(sc); - } + return listBy(sc); + } - @Override - public boolean configure(String name, Map params) throws ConfigurationException { - boolean result = super.configure(name, params); + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + boolean result = super.configure(name, params); - PublicSearch = createSearchBuilder(); - PublicSearch.and("public", PublicSearch.entity().isPublicTemplate(), SearchCriteria.Op.EQ); + PublicSearch = createSearchBuilder(); + PublicSearch.and("public", PublicSearch.entity().isPublicTemplate(), SearchCriteria.Op.EQ); - routerTmpltName = (String)params.get("routing.uniquename"); + routerTmpltName = (String) params.get("routing.uniquename"); - s_logger.debug("Found parameter routing unique name " + routerTmpltName); - if (routerTmpltName==null) { - routerTmpltName="routing"; - } + s_logger.debug("Found parameter routing unique name " + routerTmpltName); + if (routerTmpltName == null) { + routerTmpltName = "routing"; + } - consoleProxyTmpltName = (String)params.get("consoleproxy.uniquename"); - if(consoleProxyTmpltName == null) { + consoleProxyTmpltName = (String) params.get("consoleproxy.uniquename"); + if (consoleProxyTmpltName == null) { consoleProxyTmpltName = "routing"; } - if(s_logger.isDebugEnabled()) { + if (s_logger.isDebugEnabled()) { s_logger.debug("Use console proxy template : " + consoleProxyTmpltName); } - UniqueNameSearch = createSearchBuilder(); - UniqueNameSearch.and("uniqueName", UniqueNameSearch.entity().getUniqueName(), SearchCriteria.Op.EQ); - NameSearch = createSearchBuilder(); - NameSearch.and("name", NameSearch.entity().getName(), SearchCriteria.Op.EQ); + UniqueNameSearch = createSearchBuilder(); + UniqueNameSearch.and("uniqueName", UniqueNameSearch.entity().getUniqueName(), SearchCriteria.Op.EQ); + NameSearch = createSearchBuilder(); + NameSearch.and("name", NameSearch.entity().getName(), SearchCriteria.Op.EQ); - NameAccountIdSearch = createSearchBuilder(); - NameAccountIdSearch.and("name", NameAccountIdSearch.entity().getName(), SearchCriteria.Op.EQ); - NameAccountIdSearch.and("accountId", NameAccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ); + NameAccountIdSearch = createSearchBuilder(); + NameAccountIdSearch.and("name", NameAccountIdSearch.entity().getName(), SearchCriteria.Op.EQ); + NameAccountIdSearch.and("accountId", NameAccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ); - PublicIsoSearch = createSearchBuilder(); - PublicIsoSearch.and("public", PublicIsoSearch.entity().isPublicTemplate(), SearchCriteria.Op.EQ); - PublicIsoSearch.and("format", PublicIsoSearch.entity().getFormat(), SearchCriteria.Op.EQ); - PublicIsoSearch.and("type", PublicIsoSearch.entity().getTemplateType(), SearchCriteria.Op.EQ); - PublicIsoSearch.and("bootable", PublicIsoSearch.entity().isBootable(), SearchCriteria.Op.EQ); - PublicIsoSearch.and("removed", PublicIsoSearch.entity().getRemoved(), SearchCriteria.Op.EQ); + PublicIsoSearch = createSearchBuilder(); + PublicIsoSearch.and("public", PublicIsoSearch.entity().isPublicTemplate(), SearchCriteria.Op.EQ); + PublicIsoSearch.and("format", PublicIsoSearch.entity().getFormat(), SearchCriteria.Op.EQ); + PublicIsoSearch.and("type", PublicIsoSearch.entity().getTemplateType(), SearchCriteria.Op.EQ); + PublicIsoSearch.and("bootable", PublicIsoSearch.entity().isBootable(), SearchCriteria.Op.EQ); + PublicIsoSearch.and("removed", PublicIsoSearch.entity().getRemoved(), SearchCriteria.Op.EQ); - UserIsoSearch = createSearchBuilder(); - UserIsoSearch.and("format", UserIsoSearch.entity().getFormat(), SearchCriteria.Op.EQ); - UserIsoSearch.and("type", UserIsoSearch.entity().getTemplateType(), SearchCriteria.Op.EQ); - UserIsoSearch.and("removed", UserIsoSearch.entity().getRemoved(), SearchCriteria.Op.EQ); + UserIsoSearch = createSearchBuilder(); + UserIsoSearch.and("format", UserIsoSearch.entity().getFormat(), SearchCriteria.Op.EQ); + UserIsoSearch.and("type", UserIsoSearch.entity().getTemplateType(), SearchCriteria.Op.EQ); + UserIsoSearch.and("removed", UserIsoSearch.entity().getRemoved(), SearchCriteria.Op.EQ); - tmpltTypeHyperSearch = createSearchBuilder(); - tmpltTypeHyperSearch.and("templateType", tmpltTypeHyperSearch.entity().getTemplateType(), SearchCriteria.Op.EQ); - SearchBuilder hostHyperSearch = _hostDao.createSearchBuilder(); - hostHyperSearch.and("type", hostHyperSearch.entity().getType(), SearchCriteria.Op.EQ); - hostHyperSearch.and("zoneId", hostHyperSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); - hostHyperSearch.groupBy(hostHyperSearch.entity().getHypervisorType()); + tmpltTypeHyperSearch = createSearchBuilder(); + tmpltTypeHyperSearch.and("templateType", tmpltTypeHyperSearch.entity().getTemplateType(), SearchCriteria.Op.EQ); + SearchBuilder hostHyperSearch = _hostDao.createSearchBuilder(); + hostHyperSearch.and("type", hostHyperSearch.entity().getType(), SearchCriteria.Op.EQ); + hostHyperSearch.and("zoneId", hostHyperSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); + hostHyperSearch.groupBy(hostHyperSearch.entity().getHypervisorType()); - tmpltTypeHyperSearch.join("tmplHyper", hostHyperSearch, hostHyperSearch.entity().getHypervisorType(), tmpltTypeHyperSearch.entity().getHypervisorType(), JoinBuilder.JoinType.INNER); - hostHyperSearch.done(); - tmpltTypeHyperSearch.done(); + tmpltTypeHyperSearch.join("tmplHyper", hostHyperSearch, hostHyperSearch.entity().getHypervisorType(), + tmpltTypeHyperSearch.entity().getHypervisorType(), JoinBuilder.JoinType.INNER); + hostHyperSearch.done(); + tmpltTypeHyperSearch.done(); - tmpltTypeHyperSearch2 = createSearchBuilder(); - tmpltTypeHyperSearch2.and("templateType", tmpltTypeHyperSearch2.entity().getTemplateType(), SearchCriteria.Op.EQ); - tmpltTypeHyperSearch2.and("hypervisorType", tmpltTypeHyperSearch2.entity().getHypervisorType(), SearchCriteria.Op.EQ); + tmpltTypeHyperSearch2 = createSearchBuilder(); + tmpltTypeHyperSearch2.and("templateType", tmpltTypeHyperSearch2.entity().getTemplateType(), + SearchCriteria.Op.EQ); + tmpltTypeHyperSearch2.and("hypervisorType", tmpltTypeHyperSearch2.entity().getHypervisorType(), + SearchCriteria.Op.EQ); tmpltTypeHyperSearch2.and("templateName", tmpltTypeHyperSearch2.entity().getName(), SearchCriteria.Op.EQ); - - tmpltTypeSearch = createSearchBuilder(); + tmpltTypeSearch = createSearchBuilder(); tmpltTypeSearch.and("removed", tmpltTypeSearch.entity().getRemoved(), SearchCriteria.Op.NULL); - tmpltTypeSearch.and("templateType", tmpltTypeSearch.entity().getTemplateType(), SearchCriteria.Op.EQ); + tmpltTypeSearch.and("templateType", tmpltTypeSearch.entity().getTemplateType(), SearchCriteria.Op.EQ); - AccountIdSearch = createSearchBuilder(); - AccountIdSearch.and("accountId", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ); + AccountIdSearch = createSearchBuilder(); + AccountIdSearch.and("accountId", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ); AccountIdSearch.and("publicTemplate", AccountIdSearch.entity().isPublicTemplate(), SearchCriteria.Op.EQ); - AccountIdSearch.done(); + AccountIdSearch.done(); - SearchBuilder tmpltZoneSearch = _templateZoneDao.createSearchBuilder(); - tmpltZoneSearch.and("removed", tmpltZoneSearch.entity().getRemoved(), SearchCriteria.Op.NULL); - tmpltZoneSearch.and("zoneId", tmpltZoneSearch.entity().getZoneId(), SearchCriteria.Op.EQ); + SearchBuilder tmpltZoneSearch = _templateZoneDao.createSearchBuilder(); + tmpltZoneSearch.and("removed", tmpltZoneSearch.entity().getRemoved(), SearchCriteria.Op.NULL); + tmpltZoneSearch.and("zoneId", tmpltZoneSearch.entity().getZoneId(), SearchCriteria.Op.EQ); - TmpltsInZoneSearch = createSearchBuilder(); - TmpltsInZoneSearch.and("removed", TmpltsInZoneSearch.entity().getRemoved(), SearchCriteria.Op.NULL); - TmpltsInZoneSearch.and().op("avoidtype", TmpltsInZoneSearch.entity().getTemplateType(), SearchCriteria.Op.NEQ); - TmpltsInZoneSearch.or("templateType", TmpltsInZoneSearch.entity().getTemplateType(), SearchCriteria.Op.NULL); - TmpltsInZoneSearch.cp(); - TmpltsInZoneSearch.join("tmpltzone", tmpltZoneSearch, tmpltZoneSearch.entity().getTemplateId(), TmpltsInZoneSearch.entity().getId(), JoinBuilder.JoinType.INNER); - tmpltZoneSearch.done(); - TmpltsInZoneSearch.done(); + TmpltsInZoneSearch = createSearchBuilder(); + TmpltsInZoneSearch.and("removed", TmpltsInZoneSearch.entity().getRemoved(), SearchCriteria.Op.NULL); + TmpltsInZoneSearch.and().op("avoidtype", TmpltsInZoneSearch.entity().getTemplateType(), SearchCriteria.Op.NEQ); + TmpltsInZoneSearch.or("templateType", TmpltsInZoneSearch.entity().getTemplateType(), SearchCriteria.Op.NULL); + TmpltsInZoneSearch.cp(); + TmpltsInZoneSearch.join("tmpltzone", tmpltZoneSearch, tmpltZoneSearch.entity().getTemplateId(), + TmpltsInZoneSearch.entity().getId(), JoinBuilder.JoinType.INNER); + tmpltZoneSearch.done(); + TmpltsInZoneSearch.done(); - CountTemplatesByAccount = createSearchBuilder(Long.class); - CountTemplatesByAccount.select(null, Func.COUNT, null); - CountTemplatesByAccount.and("account", CountTemplatesByAccount.entity().getAccountId(), SearchCriteria.Op.EQ); - CountTemplatesByAccount.and("removed", CountTemplatesByAccount.entity().getRemoved(), SearchCriteria.Op.NULL); - CountTemplatesByAccount.done(); + ActiveTmpltSearch = createSearchBuilder(); + ActiveTmpltSearch.and("removed", ActiveTmpltSearch.entity().getRemoved(), SearchCriteria.Op.NULL); - updateStateSearch = this.createSearchBuilder(); - updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ); - updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ); - updateStateSearch.and("updatedCount", updateStateSearch.entity().getUpdatedCount(), Op.EQ); - updateStateSearch.done(); + CountTemplatesByAccount = createSearchBuilder(Long.class); + CountTemplatesByAccount.select(null, Func.COUNT, null); + CountTemplatesByAccount.and("account", CountTemplatesByAccount.entity().getAccountId(), SearchCriteria.Op.EQ); + CountTemplatesByAccount.and("removed", CountTemplatesByAccount.entity().getRemoved(), SearchCriteria.Op.NULL); + CountTemplatesByAccount.done(); - return result; - } +// updateStateSearch = this.createSearchBuilder(); +// updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ); +// updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ); +// updateStateSearch.and("updatedCount", updateStateSearch.entity().getUpdatedCount(), Op.EQ); +// updateStateSearch.done(); - @Override - public String getRoutingTemplateUniqueName() { - return routerTmpltName; - } - - @Override - public Set> searchSwiftTemplates(String name, String keyword, TemplateFilter templateFilter, boolean isIso, List hypers, Boolean bootable, DomainVO domain, - Long pageSize, Long startIndex, Long zoneId, HypervisorType hyperType, boolean onlyReady, boolean showDomr, List permittedAccounts, Account caller, Map tags) { - - StringBuilder builder = new StringBuilder(); - if (!permittedAccounts.isEmpty()) { - for (Account permittedAccount : permittedAccounts) { - builder.append(permittedAccount.getAccountId() + ","); - } - } - - String permittedAccountsStr = builder.toString(); - - if (permittedAccountsStr.length() > 0) { - // chop the "," off - permittedAccountsStr = permittedAccountsStr.substring(0, permittedAccountsStr.length() - 1); - } - - Transaction txn = Transaction.currentTxn(); - txn.start(); - - Set> templateZonePairList = new HashSet>(); - PreparedStatement pstmt = null; - ResultSet rs = null; - String sql = SELECT_TEMPLATE_SWIFT_REF; - try { - String joinClause = ""; - String whereClause = " WHERE t.removed IS NULL"; - - if (isIso) { - whereClause += " AND t.format = 'ISO'"; - if (!hyperType.equals(HypervisorType.None)) { - joinClause = " INNER JOIN guest_os guestOS on (guestOS.id = t.guest_os_id) INNER JOIN guest_os_hypervisor goh on ( goh.guest_os_id = guestOS.id) "; - whereClause += " AND goh.hypervisor_type = '" + hyperType.toString() + "'"; - } - } else { - whereClause += " AND t.format <> 'ISO'"; - if (hypers.isEmpty()) { - return templateZonePairList; - } else { - StringBuilder relatedHypers = new StringBuilder(); - for (HypervisorType hyper : hypers) { - relatedHypers.append("'"); - relatedHypers.append(hyper.toString()); - relatedHypers.append("'"); - relatedHypers.append(","); - } - relatedHypers.setLength(relatedHypers.length() - 1); - whereClause += " AND t.hypervisor_type IN (" + relatedHypers + ")"; - } - } - joinClause += " INNER JOIN template_swift_ref tsr on (t.id = tsr.template_id)"; - if (keyword != null) { - whereClause += " AND t.name LIKE \"%" + keyword + "%\""; - } else if (name != null) { - whereClause += " AND t.name LIKE \"%" + name + "%\""; - } - - if (bootable != null) { - whereClause += " AND t.bootable = " + bootable; - } - - if (!showDomr) { - whereClause += " AND t.type != '" + Storage.TemplateType.SYSTEM.toString() + "'"; - } - - if (templateFilter == TemplateFilter.featured) { - whereClause += " AND t.public = 1 AND t.featured = 1"; - } else if ((templateFilter == TemplateFilter.self || templateFilter == TemplateFilter.selfexecutable) && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { - if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { - joinClause += " INNER JOIN account a on (t.account_id = a.id) INNER JOIN domain d on (a.domain_id = d.id)"; - whereClause += " AND d.path LIKE '" + domain.getPath() + "%'"; - } else { - whereClause += " AND t.account_id IN (" + permittedAccountsStr + ")"; - } - } else if ((templateFilter == TemplateFilter.shared || templateFilter == TemplateFilter.sharedexecutable) && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { - if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { - joinClause += " LEFT JOIN launch_permission lp ON t.id = lp.template_id WHERE" + " (t.account_id IN (" + permittedAccountsStr + ") OR" + " lp.account_id IN (" - + permittedAccountsStr + "))"; - } else { - joinClause += " INNER JOIN account a on (t.account_id = a.id) "; - } - } else if (templateFilter == TemplateFilter.executable && !permittedAccounts.isEmpty()) { - whereClause += " AND (t.public = 1 OR t.account_id IN (" + permittedAccountsStr + "))"; - } else if (templateFilter == TemplateFilter.community) { - whereClause += " AND t.public = 1 AND t.featured = 0"; - } else if (templateFilter == TemplateFilter.all && caller.getType() == Account.ACCOUNT_TYPE_ADMIN) { - } else if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { - return templateZonePairList; - } - - sql += joinClause + whereClause + getOrderByLimit(pageSize, startIndex); - pstmt = txn.prepareStatement(sql); - rs = pstmt.executeQuery(); - while (rs.next()) { - Pair templateZonePair = new Pair(rs.getLong(1), -1L); - templateZonePairList.add(templateZonePair); - } - - } catch (Exception e) { - s_logger.warn("Error listing templates", e); - } finally { - try { - if (rs != null) { - rs.close(); - } - if (pstmt != null) { - pstmt.close(); - } - txn.commit(); - } catch (SQLException sqle) { - s_logger.warn("Error in cleaning up", sqle); - } - } - - return templateZonePairList; + return result; } + @Override + public String getRoutingTemplateUniqueName() { + return routerTmpltName; + } - @Override - public Set> searchTemplates(String name, String keyword, TemplateFilter templateFilter, - boolean isIso, List hypers, Boolean bootable, DomainVO domain, Long pageSize, Long startIndex, - Long zoneId, HypervisorType hyperType, boolean onlyReady, boolean showDomr,List permittedAccounts, - Account caller, ListProjectResourcesCriteria listProjectResourcesCriteria, Map tags) { - StringBuilder builder = new StringBuilder(); - if (!permittedAccounts.isEmpty()) { - for (Account permittedAccount : permittedAccounts) { - builder.append(permittedAccount.getAccountId() + ","); - } - } + /* + * @Override public Set> searchSwiftTemplates(String name, + * String keyword, TemplateFilter templateFilter, boolean isIso, + * List hypers, Boolean bootable, DomainVO domain, Long + * pageSize, Long startIndex, Long zoneId, HypervisorType hyperType, boolean + * onlyReady, boolean showDomr, List permittedAccounts, Account + * caller, Map tags) { + * + * StringBuilder builder = new StringBuilder(); if + * (!permittedAccounts.isEmpty()) { for (Account permittedAccount : + * permittedAccounts) { builder.append(permittedAccount.getAccountId() + + * ","); } } + * + * String permittedAccountsStr = builder.toString(); + * + * if (permittedAccountsStr.length() > 0) { // chop the "," off + * permittedAccountsStr = permittedAccountsStr.substring(0, + * permittedAccountsStr.length() - 1); } + * + * Transaction txn = Transaction.currentTxn(); txn.start(); + * + * Set> templateZonePairList = new HashSet>(); PreparedStatement pstmt = null; ResultSet rs = null; String sql + * = SELECT_TEMPLATE_SWIFT_REF; try { String joinClause = ""; String + * whereClause = " WHERE t.removed IS NULL"; + * + * if (isIso) { whereClause += " AND t.format = 'ISO'"; if + * (!hyperType.equals(HypervisorType.None)) { joinClause = + * " INNER JOIN guest_os guestOS on (guestOS.id = t.guest_os_id) INNER JOIN guest_os_hypervisor goh on ( goh.guest_os_id = guestOS.id) " + * ; whereClause += " AND goh.hypervisor_type = '" + hyperType.toString() + + * "'"; } } else { whereClause += " AND t.format <> 'ISO'"; if + * (hypers.isEmpty()) { return templateZonePairList; } else { StringBuilder + * relatedHypers = new StringBuilder(); for (HypervisorType hyper : hypers) + * { relatedHypers.append("'"); relatedHypers.append(hyper.toString()); + * relatedHypers.append("'"); relatedHypers.append(","); } + * relatedHypers.setLength(relatedHypers.length() - 1); whereClause += + * " AND t.hypervisor_type IN (" + relatedHypers + ")"; } } joinClause += + * " INNER JOIN template_swift_ref tsr on (t.id = tsr.template_id)"; if + * (keyword != null) { whereClause += " AND t.name LIKE \"%" + keyword + + * "%\""; } else if (name != null) { whereClause += " AND t.name LIKE \"%" + + * name + "%\""; } + * + * if (bootable != null) { whereClause += " AND t.bootable = " + bootable; } + * + * if (!showDomr) { whereClause += " AND t.type != '" + + * Storage.TemplateType.SYSTEM.toString() + "'"; } + * + * if (templateFilter == TemplateFilter.featured) { whereClause += + * " AND t.public = 1 AND t.featured = 1"; } else if ((templateFilter == + * TemplateFilter.self || templateFilter == TemplateFilter.selfexecutable) + * && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { if (caller.getType() + * == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || caller.getType() == + * Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { joinClause += + * " INNER JOIN account a on (t.account_id = a.id) INNER JOIN domain d on (a.domain_id = d.id)" + * ; whereClause += " AND d.path LIKE '" + domain.getPath() + "%'"; } else + * { whereClause += " AND t.account_id IN (" + permittedAccountsStr + ")"; } + * } else if ((templateFilter == TemplateFilter.shared || templateFilter == + * TemplateFilter.sharedexecutable) && caller.getType() != + * Account.ACCOUNT_TYPE_ADMIN) { if (caller.getType() == + * Account.ACCOUNT_TYPE_NORMAL) { joinClause += + * " LEFT JOIN launch_permission lp ON t.id = lp.template_id WHERE" + + * " (t.account_id IN (" + permittedAccountsStr + ") OR" + + * " lp.account_id IN (" + permittedAccountsStr + "))"; } else { joinClause + * += " INNER JOIN account a on (t.account_id = a.id) "; } } else if + * (templateFilter == TemplateFilter.executable && + * !permittedAccounts.isEmpty()) { whereClause += + * " AND (t.public = 1 OR t.account_id IN (" + permittedAccountsStr + "))"; + * } else if (templateFilter == TemplateFilter.community) { whereClause += + * " AND t.public = 1 AND t.featured = 0"; } else if (templateFilter == + * TemplateFilter.all && caller.getType() == Account.ACCOUNT_TYPE_ADMIN) { } + * else if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { return + * templateZonePairList; } + * + * sql += joinClause + whereClause + getOrderByLimit(pageSize, startIndex); + * pstmt = txn.prepareStatement(sql); rs = pstmt.executeQuery(); while + * (rs.next()) { Pair templateZonePair = new Pair(rs.getLong(1), -1L); templateZonePairList.add(templateZonePair); } + * + * } catch (Exception e) { s_logger.warn("Error listing templates", e); } + * finally { try { if (rs != null) { rs.close(); } if (pstmt != null) { + * pstmt.close(); } txn.commit(); } catch (SQLException sqle) { + * s_logger.warn("Error in cleaning up", sqle); } } + * + * return templateZonePairList; } + * + * + * @Override public Set> searchTemplates(String name, + * String keyword, TemplateFilter templateFilter, boolean isIso, + * List hypers, Boolean bootable, DomainVO domain, Long + * pageSize, Long startIndex, Long zoneId, HypervisorType hyperType, boolean + * onlyReady, boolean showDomr,List permittedAccounts, Account + * caller, ListProjectResourcesCriteria listProjectResourcesCriteria, + * Map tags, String zoneType) { StringBuilder builder = new + * StringBuilder(); if (!permittedAccounts.isEmpty()) { for (Account + * permittedAccount : permittedAccounts) { + * builder.append(permittedAccount.getAccountId() + ","); } } + * + * String permittedAccountsStr = builder.toString(); + * + * if (permittedAccountsStr.length() > 0) { //chop the "," off + * permittedAccountsStr = permittedAccountsStr.substring(0, + * permittedAccountsStr.length()-1); } + * + * Transaction txn = Transaction.currentTxn(); txn.start(); + * + * // Use LinkedHashSet here to guarantee iteration order Set> templateZonePairList = new LinkedHashSet>(); + * PreparedStatement pstmt = null; ResultSet rs = null; StringBuilder + * relatedDomainIds = new StringBuilder(); String sql = + * SELECT_TEMPLATE_ZONE_REF; String groupByClause = ""; try { //short + * accountType; //String accountId = null; String guestOSJoin = ""; + * StringBuilder templateHostRefJoin = new StringBuilder(); String + * dataCenterJoin = "", lpjoin = ""; String tagsJoin = ""; + * + * if (isIso && !hyperType.equals(HypervisorType.None)) { guestOSJoin = + * " INNER JOIN guest_os guestOS on (guestOS.id = t.guest_os_id) INNER JOIN guest_os_hypervisor goh on ( goh.guest_os_id = guestOS.id) " + * ; } if (onlyReady){ templateHostRefJoin.append( + * " INNER JOIN template_host_ref thr on (t.id = thr.template_id) INNER JOIN host h on (thr.host_id = h.id)" + * ); sql = SELECT_TEMPLATE_HOST_REF; groupByClause = + * " GROUP BY t.id, h.data_center_id "; } if ((templateFilter == + * TemplateFilter.featured) || (templateFilter == TemplateFilter.community)) + * { dataCenterJoin = + * " INNER JOIN data_center dc on (h.data_center_id = dc.id)"; } + * + * if (zoneType != null) { dataCenterJoin = + * " INNER JOIN template_host_ref thr on (t.id = thr.template_id) INNER JOIN host h on (thr.host_id = h.id)" + * ; dataCenterJoin += + * " INNER JOIN data_center dc on (h.data_center_id = dc.id)"; } + * + * if (templateFilter == TemplateFilter.sharedexecutable || templateFilter + * == TemplateFilter.shared ){ lpjoin = + * " INNER JOIN launch_permission lp ON t.id = lp.template_id "; } + * + * if (tags != null && !tags.isEmpty()) { tagsJoin = + * " INNER JOIN resource_tags r ON t.id = r.resource_id "; } + * + * sql += guestOSJoin + templateHostRefJoin + dataCenterJoin + lpjoin + + * tagsJoin; String whereClause = ""; + * + * //All joins have to be made before we start setting the condition + * settings if ((listProjectResourcesCriteria == + * ListProjectResourcesCriteria.SkipProjectResources || + * (!permittedAccounts.isEmpty() && !(templateFilter == + * TemplateFilter.community || templateFilter == TemplateFilter.featured))) + * && !(caller.getType() != Account.ACCOUNT_TYPE_NORMAL && templateFilter == + * TemplateFilter.all)) { whereClause += + * " INNER JOIN account a on (t.account_id = a.id)"; if ((templateFilter == + * TemplateFilter.self || templateFilter == TemplateFilter.selfexecutable) + * && (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || + * caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN)) { + * whereClause += + * " INNER JOIN domain d on (a.domain_id = d.id) WHERE d.path LIKE '" + + * domain.getPath() + "%'"; if (listProjectResourcesCriteria == + * ListProjectResourcesCriteria.SkipProjectResources) { whereClause += + * " AND a.type != " + Account.ACCOUNT_TYPE_PROJECT; } } else if + * (listProjectResourcesCriteria == + * ListProjectResourcesCriteria.SkipProjectResources) { whereClause += + * " WHERE a.type != " + Account.ACCOUNT_TYPE_PROJECT; } } + * + * if (!permittedAccounts.isEmpty()) { for (Account account : + * permittedAccounts) { //accountType = account.getType(); //accountId = + * Long.toString(account.getId()); DomainVO accountDomain = + * _domainDao.findById(account.getDomainId()); + * + * // get all parent domain ID's all the way till root domain DomainVO + * domainTreeNode = accountDomain; while (true) { + * relatedDomainIds.append(domainTreeNode.getId()); + * relatedDomainIds.append(","); if (domainTreeNode.getParent() != null) { + * domainTreeNode = _domainDao.findById(domainTreeNode.getParent()); } else + * { break; } } + * + * // get all child domain ID's if (isAdmin(account.getType()) ) { + * List allChildDomains = + * _domainDao.findAllChildren(accountDomain.getPath(), + * accountDomain.getId()); for (DomainVO childDomain : allChildDomains) { + * relatedDomainIds.append(childDomain.getId()); + * relatedDomainIds.append(","); } } + * relatedDomainIds.setLength(relatedDomainIds.length()-1); } } + * + * String attr = " AND "; if (whereClause.endsWith(" WHERE ")) { attr += + * " WHERE "; } + * + * if (!isIso) { if ( hypers.isEmpty() ) { return templateZonePairList; } + * else { StringBuilder relatedHypers = new StringBuilder(); for + * (HypervisorType hyper : hypers ) { relatedHypers.append("'"); + * relatedHypers.append(hyper.toString()); relatedHypers.append("'"); + * relatedHypers.append(","); } + * relatedHypers.setLength(relatedHypers.length()-1); whereClause += attr + + * " t.hypervisor_type IN (" + relatedHypers + ")"; } } + * + * if (!permittedAccounts.isEmpty() && !(templateFilter == + * TemplateFilter.featured || templateFilter == TemplateFilter.community || + * templateFilter == TemplateFilter.executable || templateFilter == + * TemplateFilter.shared || templateFilter == + * TemplateFilter.sharedexecutable) && !isAdmin(caller.getType()) ) { + * whereClause += attr + "t.account_id IN (" + permittedAccountsStr + ")"; } + * + * if (templateFilter == TemplateFilter.featured) { whereClause += attr + + * "t.public = 1 AND t.featured = 1"; if (!permittedAccounts.isEmpty()) { + * whereClause += attr + "(dc.domain_id IN (" + relatedDomainIds + + * ") OR dc.domain_id is NULL)"; } } else if (templateFilter == + * TemplateFilter.self || templateFilter == TemplateFilter.selfexecutable) { + * whereClause += " AND t.account_id IN (" + permittedAccountsStr + ")"; } + * else if (templateFilter == TemplateFilter.sharedexecutable || + * templateFilter == TemplateFilter.shared ) { whereClause += " AND " + + * " (t.account_id IN (" + permittedAccountsStr + ") OR" + + * " lp.account_id IN (" + permittedAccountsStr + "))"; } else if + * (templateFilter == TemplateFilter.executable && + * !permittedAccounts.isEmpty()) { whereClause += attr + + * "(t.public = 1 OR t.account_id IN (" + permittedAccountsStr + "))"; } + * else if (templateFilter == TemplateFilter.community) { whereClause += + * attr + "t.public = 1 AND t.featured = 0"; if + * (!permittedAccounts.isEmpty()) { whereClause += attr + + * "(dc.domain_id IN (" + relatedDomainIds + ") OR dc.domain_id is NULL)"; } + * } else if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN && !isIso) { + * return templateZonePairList; } + * + * if (tags != null && !tags.isEmpty()) { whereClause += " AND ("; boolean + * first = true; for (String key : tags.keySet()) { if (!first) { + * whereClause += " OR "; } whereClause += "(r.key=\"" + key + + * "\" and r.value=\"" + tags.get(key) + "\")"; first = false; } whereClause + * += ")"; } + * + * if (whereClause.equals("")) { whereClause += " WHERE "; } else if + * (!whereClause.equals(" WHERE ")) { whereClause += " AND "; } + * + * sql += whereClause + getExtrasWhere(templateFilter, name, keyword, isIso, + * bootable, hyperType, zoneId, onlyReady, showDomr, zoneType) + + * groupByClause + getOrderByLimit(pageSize, startIndex); + * + * pstmt = txn.prepareStatement(sql); rs = pstmt.executeQuery(); + * + * while (rs.next()) { Pair templateZonePair = new Pair(rs.getLong(1), rs.getLong(2)); + * templateZonePairList.add(templateZonePair); } //for now, defaulting + * pageSize to a large val if null; may need to revisit post 2.2RC2 if(isIso + * && templateZonePairList.size() < (pageSize != null ? pageSize : 500) && + * templateFilter != TemplateFilter.community && !(templateFilter == + * TemplateFilter.self && !BaseCmd.isRootAdmin(caller.getType())) ){ + * //evaluates to true If root admin and filter=self + * + * List publicIsos = publicIsoSearch(bootable, false, tags); + * List userIsos = userIsoSearch(false); + * + * //Listing the ISOs according to the page size.Restricting the total no. + * of ISOs on a page //to be less than or equal to the pageSize parameter + * + * int i=0; + * + * if (startIndex > userIsos.size()) { i=(int) (startIndex - + * userIsos.size()); } + * + * for (; i < publicIsos.size(); i++) { if(templateZonePairList.size() >= + * pageSize){ break; } else { if (keyword != null && + * publicIsos.get(i).getName().contains(keyword)) { + * templateZonePairList.add(new Pair(publicIsos.get(i).getId(), + * null)); continue; } else if (name != null && + * publicIsos.get(i).getName().contains(name)) { + * templateZonePairList.add(new Pair(publicIsos.get(i).getId(), + * null)); continue; } else if (keyword == null && name == null){ + * templateZonePairList.add(new Pair(publicIsos.get(i).getId(), + * null)); } } } } } catch (Exception e) { + * s_logger.warn("Error listing templates", e); } finally { try { if (rs != + * null) { rs.close(); } if (pstmt != null) { pstmt.close(); } txn.commit(); + * } catch( SQLException sqle) { s_logger.warn("Error in cleaning up", + * sqle); } } + * + * return templateZonePairList; } + */ - String permittedAccountsStr = builder.toString(); + /* + * private String getExtrasWhere(TemplateFilter templateFilter, String name, + * String keyword, boolean isIso, Boolean bootable, HypervisorType + * hyperType, Long zoneId, boolean onlyReady, boolean showDomr, String + * zoneType) { String sql = ""; if (keyword != null) { sql += + * " t.name LIKE \"%" + keyword + "%\" AND"; } else if (name != null) { sql + * += " t.name LIKE \"%" + name + "%\" AND"; } + * + * if (isIso) { sql += " t.format = 'ISO'"; if + * (!hyperType.equals(HypervisorType.None)) { sql += + * " AND goh.hypervisor_type = '" + hyperType.toString() + "'"; } } else { + * sql += " t.format <> 'ISO'"; if (!hyperType.equals(HypervisorType.None)) + * { sql += " AND t.hypervisor_type = '" + hyperType.toString() + "'"; } } + * + * if (bootable != null) { sql += " AND t.bootable = " + bootable; } + * + * if (onlyReady){ sql += " AND thr.download_state = '" + * +Status.DOWNLOADED.toString() + "'" + " AND thr.destroyed=0 "; if (zoneId + * != null){ sql += " AND h.data_center_id = " +zoneId; } }else if (zoneId + * != null){ sql += " AND tzr.zone_id = " +zoneId+ + * " AND tzr.removed is null" ; }else{ sql += " AND tzr.removed is null "; } + * + * if (zoneType != null){ sql += " AND dc.networktype = '" + zoneType + "'"; + * } + * + * if (!showDomr){ sql += " AND t.type != '" + * +Storage.TemplateType.SYSTEM.toString() + "'"; } + * + * sql += " AND t.removed IS NULL"; + * + * return sql; } + * + * private String getOrderByLimit(Long pageSize, Long startIndex) { Boolean + * isAscending = + * Boolean.parseBoolean(_configDao.getValue("sortkey.algorithm")); + * isAscending = (isAscending == null ? true : isAscending); + * + * String sql; if (isAscending) { sql = " ORDER BY t.sort_key ASC"; } else { + * sql = " ORDER BY t.sort_key DESC"; } + * + * if ((pageSize != null) && (startIndex != null)) { sql += " LIMIT " + + * startIndex.toString() + "," + pageSize.toString(); } return sql; } + */ - if (permittedAccountsStr.length() > 0) { - //chop the "," off - permittedAccountsStr = permittedAccountsStr.substring(0, permittedAccountsStr.length()-1); - } - - Transaction txn = Transaction.currentTxn(); + @SuppressWarnings("unchecked") + @Override + @DB + public long addTemplateToZone(VMTemplateVO tmplt, long zoneId) { + Transaction txn = Transaction.currentTxn(); txn.start(); - - /* Use LinkedHashSet here to guarantee iteration order */ - Set> templateZonePairList = new LinkedHashSet>(); - PreparedStatement pstmt = null; - ResultSet rs = null; - StringBuilder relatedDomainIds = new StringBuilder(); - String sql = SELECT_TEMPLATE_ZONE_REF; - String groupByClause = ""; - try { - //short accountType; - //String accountId = null; - String guestOSJoin = ""; - StringBuilder templateHostRefJoin = new StringBuilder(); - String dataCenterJoin = "", lpjoin = ""; - String tagsJoin = ""; - - if (isIso && !hyperType.equals(HypervisorType.None)) { - guestOSJoin = " INNER JOIN guest_os guestOS on (guestOS.id = t.guest_os_id) INNER JOIN guest_os_hypervisor goh on ( goh.guest_os_id = guestOS.id) "; - } - if (onlyReady){ - templateHostRefJoin.append(" INNER JOIN template_host_ref thr on (t.id = thr.template_id) INNER JOIN host h on (thr.host_id = h.id)"); - sql = SELECT_TEMPLATE_HOST_REF; - groupByClause = " GROUP BY t.id, h.data_center_id "; - } - if ((templateFilter == TemplateFilter.featured) || (templateFilter == TemplateFilter.community)) { - dataCenterJoin = " INNER JOIN data_center dc on (h.data_center_id = dc.id)"; - } - - if (templateFilter == TemplateFilter.sharedexecutable || templateFilter == TemplateFilter.shared ){ - lpjoin = " INNER JOIN launch_permission lp ON t.id = lp.template_id "; - } - - if (tags != null && !tags.isEmpty()) { - tagsJoin = " INNER JOIN resource_tags r ON t.id = r.resource_id "; - } - - sql += guestOSJoin + templateHostRefJoin + dataCenterJoin + lpjoin + tagsJoin; - String whereClause = ""; - - //All joins have to be made before we start setting the condition settings - if ((listProjectResourcesCriteria == ListProjectResourcesCriteria.SkipProjectResources - || (!permittedAccounts.isEmpty() && !(templateFilter == TemplateFilter.community || templateFilter == TemplateFilter.featured))) && - !(caller.getType() != Account.ACCOUNT_TYPE_NORMAL && templateFilter == TemplateFilter.all)) { - whereClause += " INNER JOIN account a on (t.account_id = a.id)"; - if ((templateFilter == TemplateFilter.self || templateFilter == TemplateFilter.selfexecutable) && (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN)) { - whereClause += " INNER JOIN domain d on (a.domain_id = d.id) WHERE d.path LIKE '" + domain.getPath() + "%'"; - if (listProjectResourcesCriteria == ListProjectResourcesCriteria.SkipProjectResources) { - whereClause += " AND a.type != " + Account.ACCOUNT_TYPE_PROJECT; - } - } else - if (listProjectResourcesCriteria == ListProjectResourcesCriteria.SkipProjectResources) { - whereClause += " WHERE a.type != " + Account.ACCOUNT_TYPE_PROJECT; - } - } - - if (!permittedAccounts.isEmpty()) { - for (Account account : permittedAccounts) { - //accountType = account.getType(); - //accountId = Long.toString(account.getId()); - DomainVO accountDomain = _domainDao.findById(account.getDomainId()); - - // get all parent domain ID's all the way till root domain - DomainVO domainTreeNode = accountDomain; - while (true) { - relatedDomainIds.append(domainTreeNode.getId()); - relatedDomainIds.append(","); - if (domainTreeNode.getParent() != null) { - domainTreeNode = _domainDao.findById(domainTreeNode.getParent()); - } else { - break; - } - } - - // get all child domain ID's - if (isAdmin(account.getType()) ) { - List allChildDomains = _domainDao.findAllChildren(accountDomain.getPath(), accountDomain.getId()); - for (DomainVO childDomain : allChildDomains) { - relatedDomainIds.append(childDomain.getId()); - relatedDomainIds.append(","); - } - } - relatedDomainIds.setLength(relatedDomainIds.length()-1); - } + VMTemplateVO tmplt2 = findById(tmplt.getId()); + if (tmplt2 == null) { + if (persist(tmplt) == null) { + throw new CloudRuntimeException("Failed to persist the template " + tmplt); } - - String attr = " AND "; - if (whereClause.endsWith(" WHERE ")) { - attr += " WHERE "; + if (tmplt.getDetails() != null) { + _templateDetailsDao.persist(tmplt.getId(), tmplt.getDetails()); } - - if (!isIso) { - if ( hypers.isEmpty() ) { - return templateZonePairList; - } else { - StringBuilder relatedHypers = new StringBuilder(); - for (HypervisorType hyper : hypers ) { - relatedHypers.append("'"); - relatedHypers.append(hyper.toString()); - relatedHypers.append("'"); - relatedHypers.append(","); - } - relatedHypers.setLength(relatedHypers.length()-1); - whereClause += attr + " t.hypervisor_type IN (" + relatedHypers + ")"; - } - } - - if (!permittedAccounts.isEmpty() && !(templateFilter == TemplateFilter.featured || - templateFilter == TemplateFilter.community || templateFilter == TemplateFilter.executable - || templateFilter == TemplateFilter.shared || templateFilter == TemplateFilter.sharedexecutable) && !isAdmin(caller.getType()) ) { - whereClause += attr + "t.account_id IN (" + permittedAccountsStr + ")"; - } - - if (templateFilter == TemplateFilter.featured) { - whereClause += attr + "t.public = 1 AND t.featured = 1"; - if (!permittedAccounts.isEmpty()) { - whereClause += attr + "(dc.domain_id IN (" + relatedDomainIds + ") OR dc.domain_id is NULL)"; - } - } else if (templateFilter == TemplateFilter.self || templateFilter == TemplateFilter.selfexecutable) { - whereClause += " AND t.account_id IN (" + permittedAccountsStr + ")"; - } else if (templateFilter == TemplateFilter.sharedexecutable || templateFilter == TemplateFilter.shared ) { - whereClause += " AND " + - " (t.account_id IN (" + permittedAccountsStr + ") OR" + - " lp.account_id IN (" + permittedAccountsStr + "))"; - } else if (templateFilter == TemplateFilter.executable && !permittedAccounts.isEmpty()) { - whereClause += attr + "(t.public = 1 OR t.account_id IN (" + permittedAccountsStr + "))"; - } else if (templateFilter == TemplateFilter.community) { - whereClause += attr + "t.public = 1 AND t.featured = 0"; - if (!permittedAccounts.isEmpty()) { - whereClause += attr + "(dc.domain_id IN (" + relatedDomainIds + ") OR dc.domain_id is NULL)"; - } - } else if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN && !isIso) { - return templateZonePairList; - } - - if (tags != null && !tags.isEmpty()) { - whereClause += " AND ("; - boolean first = true; - for (String key : tags.keySet()) { - if (!first) { - whereClause += " OR "; - } - whereClause += "(r.key=\"" + key + "\" and r.value=\"" + tags.get(key) + "\")"; - first = false; - } - whereClause += ")"; - } - - if (whereClause.equals("")) { - whereClause += " WHERE "; - } else if (!whereClause.equals(" WHERE ")) { - whereClause += " AND "; - } - - sql += whereClause + getExtrasWhere(templateFilter, name, keyword, isIso, bootable, hyperType, zoneId, - onlyReady, showDomr) + groupByClause + getOrderByLimit(pageSize, startIndex); - - pstmt = txn.prepareStatement(sql); - rs = pstmt.executeQuery(); - - while (rs.next()) { - Pair templateZonePair = new Pair(rs.getLong(1), rs.getLong(2)); - templateZonePairList.add(templateZonePair); - } - //for now, defaulting pageSize to a large val if null; may need to revisit post 2.2RC2 - if(isIso && templateZonePairList.size() < (pageSize != null ? pageSize : 500) - && templateFilter != TemplateFilter.community - && !(templateFilter == TemplateFilter.self && !BaseCmd.isRootAdmin(caller.getType())) ){ //evaluates to true If root admin and filter=self - - List publicIsos = publicIsoSearch(bootable, false, tags); - List userIsos = userIsoSearch(false); - - //Listing the ISOs according to the page size.Restricting the total no. of ISOs on a page - //to be less than or equal to the pageSize parameter - - int i=0; - - if (startIndex > userIsos.size()) { - i=(int) (startIndex - userIsos.size()); - } - - for (; i < publicIsos.size(); i++) { - if(templateZonePairList.size() >= pageSize){ - break; - } else { - if (keyword != null && publicIsos.get(i).getName().contains(keyword)) { - templateZonePairList.add(new Pair(publicIsos.get(i).getId(), null)); - continue; - } else if (name != null && publicIsos.get(i).getName().contains(name)) { - templateZonePairList.add(new Pair(publicIsos.get(i).getId(), null)); - continue; - } else if (keyword == null && name == null){ - templateZonePairList.add(new Pair(publicIsos.get(i).getId(), null)); - } - } - } - } - } catch (Exception e) { - s_logger.warn("Error listing templates", e); - } finally { - try { - if (rs != null) { - rs.close(); - } - if (pstmt != null) { - pstmt.close(); - } - txn.commit(); - } catch( SQLException sqle) { - s_logger.warn("Error in cleaning up", sqle); - } } - - return templateZonePairList; - } - - private String getExtrasWhere(TemplateFilter templateFilter, String name, String keyword, boolean isIso, Boolean bootable, HypervisorType hyperType, Long zoneId, boolean onlyReady, boolean showDomr) { - String sql = ""; - if (keyword != null) { - sql += " t.name LIKE \"%" + keyword + "%\" AND"; - } else if (name != null) { - sql += " t.name LIKE \"%" + name + "%\" AND"; - } - - if (isIso) { - sql += " t.format = 'ISO'"; - if (!hyperType.equals(HypervisorType.None)) { - sql += " AND goh.hypervisor_type = '" + hyperType.toString() + "'"; - } + VMTemplateZoneVO tmpltZoneVO = _templateZoneDao.findByZoneTemplate(zoneId, tmplt.getId()); + if (tmpltZoneVO == null) { + tmpltZoneVO = new VMTemplateZoneVO(zoneId, tmplt.getId(), new Date()); + _templateZoneDao.persist(tmpltZoneVO); } else { - sql += " t.format <> 'ISO'"; - if (!hyperType.equals(HypervisorType.None)) { - sql += " AND t.hypervisor_type = '" + hyperType.toString() + "'"; - } + tmpltZoneVO.setRemoved(null); + tmpltZoneVO.setLastUpdated(new Date()); + _templateZoneDao.update(tmpltZoneVO.getId(), tmpltZoneVO); } + txn.commit(); - if (bootable != null) { - sql += " AND t.bootable = " + bootable; - } + return tmplt.getId(); + } - if (onlyReady){ - sql += " AND thr.download_state = '" +Status.DOWNLOADED.toString() + "'" + " AND thr.destroyed=0 "; - if (zoneId != null){ - sql += " AND h.data_center_id = " +zoneId; - } - }else if (zoneId != null){ - sql += " AND tzr.zone_id = " +zoneId+ " AND tzr.removed is null" ; - }else{ - sql += " AND tzr.removed is null "; - } - - if (!showDomr){ - sql += " AND t.type != '" +Storage.TemplateType.SYSTEM.toString() + "'"; - } + @Override + @DB + public List listAllInZone(long dataCenterId) { + SearchCriteria sc = TmpltsInZoneSearch.create(); + sc.setParameters("avoidtype", TemplateType.PERHOST.toString()); + sc.setJoinParameters("tmpltzone", "zoneId", dataCenterId); + return listBy(sc); + } - sql += " AND t.removed IS NULL"; + @Override + public List listAllActive() { + SearchCriteria sc = ActiveTmpltSearch.create(); + return listBy(sc); + } - return sql; - } + @Override + public List listDefaultBuiltinTemplates() { + SearchCriteria sc = tmpltTypeSearch.create(); + sc.setParameters("templateType", Storage.TemplateType.BUILTIN); + return listBy(sc); + } - private String getOrderByLimit(Long pageSize, Long startIndex) { - Boolean isAscending = Boolean.parseBoolean(_configDao.getValue("sortkey.algorithm")); - isAscending = (isAscending == null ? true : isAscending); - - String sql; - if (isAscending) { - sql = " ORDER BY t.sort_key ASC"; - } else { - sql = " ORDER BY t.sort_key DESC"; - } - - if ((pageSize != null) && (startIndex != null)) { - sql += " LIMIT " + startIndex.toString() + "," + pageSize.toString(); - } - return sql; - } - - @Override - @DB - public long addTemplateToZone(VMTemplateVO tmplt, long zoneId) { - Transaction txn = Transaction.currentTxn(); - txn.start(); - VMTemplateVO tmplt2 = findById(tmplt.getId()); - if (tmplt2 == null){ - if (persist(tmplt) == null) { - throw new CloudRuntimeException("Failed to persist the template " + tmplt); - } - if(tmplt.getDetails() != null) { - _templateDetailsDao.persist(tmplt.getId(), tmplt.getDetails()); - } - } - VMTemplateZoneVO tmpltZoneVO = _templateZoneDao.findByZoneTemplate(zoneId, tmplt.getId()); - if (tmpltZoneVO == null ) { - tmpltZoneVO = new VMTemplateZoneVO(zoneId, tmplt.getId(), new Date()); - _templateZoneDao.persist(tmpltZoneVO); - } else { - tmpltZoneVO.setRemoved(null); - tmpltZoneVO.setLastUpdated(new Date()); - _templateZoneDao.update(tmpltZoneVO.getId(), tmpltZoneVO); - } - txn.commit(); - - return tmplt.getId(); - } - - @Override - @DB - public List listAllInZone(long dataCenterId) { - SearchCriteria sc = TmpltsInZoneSearch.create(); - sc.setParameters("avoidtype", TemplateType.PERHOST.toString()); - sc.setJoinParameters("tmpltzone", "zoneId", dataCenterId); - return listBy(sc); - } - - @Override - public List listDefaultBuiltinTemplates() { - SearchCriteria sc = tmpltTypeSearch.create(); - sc.setParameters("templateType", Storage.TemplateType.BUILTIN); - return listBy(sc); - } - - @Override - public VMTemplateVO findSystemVMTemplate(long zoneId) { - SearchCriteria sc = tmpltTypeHyperSearch.create(); - sc.setParameters("templateType", Storage.TemplateType.SYSTEM); - sc.setJoinParameters("tmplHyper", "type", Host.Type.Routing); - sc.setJoinParameters("tmplHyper", "zoneId", zoneId); - - //order by descending order of id and select the first (this is going to be the latest) - List tmplts = listBy(sc, new Filter(VMTemplateVO.class, "id", false, null, 1l)); - - if (tmplts.size() > 0) { - return tmplts.get(0); - } else { - return null; - } - } - - public VMTemplateVO findSystemVMTemplate(long zoneId, HypervisorType hType) { - SearchCriteria sc = tmpltTypeHyperSearch.create(); - sc.setParameters("templateType", Storage.TemplateType.SYSTEM); - sc.setJoinParameters("tmplHyper", "type", Host.Type.Routing); - sc.setJoinParameters("tmplHyper", "zoneId", zoneId); - - //order by descending order of id - List tmplts = listBy(sc, new Filter(VMTemplateVO.class, "id", false, null, null)); - - for (VMTemplateVO tmplt: tmplts) { - if (tmplt.getHypervisorType() == hType) { - return tmplt; - } - } - if (tmplts.size() > 0 && hType == HypervisorType.Any) { - return tmplts.get(0); - } - return null; - } - - @Override - public VMTemplateVO findRoutingTemplate(HypervisorType hType, String templateName) { - SearchCriteria sc = tmpltTypeHyperSearch2.create(); + @Override + public VMTemplateVO findSystemVMTemplate(long zoneId) { + SearchCriteria sc = tmpltTypeHyperSearch.create(); sc.setParameters("templateType", Storage.TemplateType.SYSTEM); - sc.setParameters("hypervisorType", hType); - if (templateName != null) { - sc.setParameters("templateName", templateName); - } + sc.setJoinParameters("tmplHyper", "type", Host.Type.Routing); + sc.setJoinParameters("tmplHyper", "zoneId", zoneId); - //order by descending order of id and select the first (this is going to be the latest) + // order by descending order of id and select the first (this is going + // to be the latest) List tmplts = listBy(sc, new Filter(VMTemplateVO.class, "id", false, null, 1l)); if (tmplts.size() > 0) { @@ -912,11 +764,52 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem } else { return null; } - } + } + + @Override + public VMTemplateVO findSystemVMTemplate(long zoneId, HypervisorType hType) { + SearchCriteria sc = tmpltTypeHyperSearch.create(); + sc.setParameters("templateType", Storage.TemplateType.SYSTEM); + sc.setJoinParameters("tmplHyper", "type", Host.Type.Routing); + sc.setJoinParameters("tmplHyper", "zoneId", zoneId); + + // order by descending order of id + List tmplts = listBy(sc, new Filter(VMTemplateVO.class, "id", false, null, null)); + + for (VMTemplateVO tmplt : tmplts) { + if (tmplt.getHypervisorType() == hType) { + return tmplt; + } + } + if (tmplts.size() > 0 && hType == HypervisorType.Any) { + return tmplts.get(0); + } + return null; + } + + @Override + public VMTemplateVO findRoutingTemplate(HypervisorType hType, String templateName) { + SearchCriteria sc = tmpltTypeHyperSearch2.create(); + sc.setParameters("templateType", Storage.TemplateType.SYSTEM); + sc.setParameters("hypervisorType", hType); + if (templateName != null) { + sc.setParameters("templateName", templateName); + } + + // order by descending order of id and select the first (this is going + // to be the latest) + List tmplts = listBy(sc, new Filter(VMTemplateVO.class, "id", false, null, 1l)); + + if (tmplts.size() > 0) { + return tmplts.get(0); + } else { + return null; + } + } @Override public Long countTemplatesForAccount(long accountId) { - SearchCriteria sc = CountTemplatesByAccount.create(); + SearchCriteria sc = CountTemplatesByAccount.create(); sc.setParameters("account", accountId); return customSearch(sc, null).get(0); } @@ -943,185 +836,101 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem return result; } - private boolean isAdmin(short accountType) { - return ((accountType == Account.ACCOUNT_TYPE_ADMIN) || - (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) || - (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || - (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)); - } - @Override public List findTemplatesToSyncToS3() { return executeList(SELECT_S3_CANDIDATE_TEMPLATES, new Object[] {}); } - @Override - public Set> searchS3Templates(final String name, - final String keyword, final TemplateFilter templateFilter, - final boolean isIso, final List hypers, - final Boolean bootable, final DomainVO domain, final Long pageSize, - final Long startIndex, final Long zoneId, - final HypervisorType hyperType, final boolean onlyReady, - final boolean showDomr, final List permittedAccounts, - final Account caller, final Map tags) { - - final String permittedAccountsStr = join(",", permittedAccounts); - - final Transaction txn = Transaction.currentTxn(); - txn.start(); - - Set> templateZonePairList = new HashSet>(); - PreparedStatement pstmt = null; - ResultSet rs = null; - try { - - final StringBuilder joinClause = new StringBuilder(); - final StringBuilder whereClause = new StringBuilder(" WHERE t.removed IS NULL"); - - if (isIso) { - whereClause.append(" AND t.format = 'ISO'"); - if (!hyperType.equals(HypervisorType.None)) { - joinClause.append(" INNER JOIN guest_os guestOS on (guestOS.id = t.guest_os_id) INNER JOIN guest_os_hypervisor goh on ( goh.guest_os_id = guestOS.id) "); - whereClause.append(" AND goh.hypervisor_type = '"); - whereClause.append(hyperType); - whereClause.append("'"); - } - } else { - whereClause.append(" AND t.format <> 'ISO'"); - if (hypers.isEmpty()) { - return templateZonePairList; - } else { - final StringBuilder relatedHypers = new StringBuilder(); - for (HypervisorType hyper : hypers) { - relatedHypers.append("'"); - relatedHypers.append(hyper.toString()); - relatedHypers.append("'"); - relatedHypers.append(","); - } - relatedHypers.setLength(relatedHypers.length() - 1); - whereClause.append(" AND t.hypervisor_type IN ("); - whereClause.append(relatedHypers); - whereClause.append(")"); - } - } - - joinClause.append(" INNER JOIN template_s3_ref tsr on (t.id = tsr.template_id)"); - - whereClause.append("AND t.name LIKE \"%"); - whereClause.append(keyword == null ? keyword : name); - whereClause.append("%\""); - - if (bootable != null) { - whereClause.append(" AND t.bootable = "); - whereClause.append(bootable); - } - - if (!showDomr) { - whereClause.append(" AND t.type != '"); - whereClause.append(Storage.TemplateType.SYSTEM); - whereClause.append("'"); - } - - if (templateFilter == TemplateFilter.featured) { - whereClause.append(" AND t.public = 1 AND t.featured = 1"); - } else if ((templateFilter == TemplateFilter.self || templateFilter == TemplateFilter.selfexecutable) - && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { - if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN - || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { - joinClause.append(" INNER JOIN account a on (t.account_id = a.id) INNER JOIN domain d on (a.domain_id = d.id)"); - whereClause.append(" AND d.path LIKE '"); - whereClause.append(domain.getPath()); - whereClause.append("%'"); - } else { - whereClause.append(" AND t.account_id IN ("); - whereClause.append(permittedAccountsStr); - whereClause.append(")"); - } - } else if (templateFilter == TemplateFilter.sharedexecutable - && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { - if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { - joinClause.append(" LEFT JOIN launch_permission lp ON t.id = lp.template_id WHERE (t.account_id IN ("); - joinClause.append(permittedAccountsStr); - joinClause.append(") OR lp.account_id IN ("); - joinClause.append(permittedAccountsStr); - joinClause.append("))"); - } else { - joinClause.append(" INNER JOIN account a on (t.account_id = a.id) "); - } - } else if (templateFilter == TemplateFilter.executable - && !permittedAccounts.isEmpty()) { - whereClause.append(" AND (t.public = 1 OR t.account_id IN ("); - whereClause.append(permittedAccountsStr); - whereClause.append("))"); - } else if (templateFilter == TemplateFilter.community) { - whereClause.append(" AND t.public = 1 AND t.featured = 0"); - } else if (templateFilter == TemplateFilter.all - && caller.getType() == Account.ACCOUNT_TYPE_ADMIN) { - } else if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { - return templateZonePairList; - } - - final StringBuilder sql = new StringBuilder(SELECT_TEMPLATE_S3_REF); - sql.append(joinClause); - sql.append(whereClause); - sql.append(getOrderByLimit(pageSize, startIndex)); - - pstmt = txn.prepareStatement(sql.toString()); - rs = pstmt.executeQuery(); - while (rs.next()) { - final Pair templateZonePair = new Pair( - rs.getLong(1), -1L); - templateZonePairList.add(templateZonePair); - } - txn.commit(); - } catch (Exception e) { - s_logger.warn("Error listing S3 templates", e); - if (txn != null) { - txn.rollback(); - } - } finally { - closeResources(pstmt, rs); - if (txn != null) { - txn.close(); - } - } - - return templateZonePairList; - } - - @Override - public boolean updateState(TemplateState currentState, TemplateEvent event, - TemplateState nextState, VMTemplateVO vo, Object data) { - Long oldUpdated = vo.getUpdatedCount(); - Date oldUpdatedTime = vo.getUpdated(); + /* + * @Override public Set> searchS3Templates(final String + * name, final String keyword, final TemplateFilter templateFilter, final + * boolean isIso, final List hypers, final Boolean bootable, + * final DomainVO domain, final Long pageSize, final Long startIndex, final + * Long zoneId, final HypervisorType hyperType, final boolean onlyReady, + * final boolean showDomr, final List permittedAccounts, final + * Account caller, final Map tags) { + * + * final String permittedAccountsStr = join(",", permittedAccounts); + * + * final Transaction txn = Transaction.currentTxn(); txn.start(); + * + * Set> templateZonePairList = new HashSet>(); PreparedStatement pstmt = null; ResultSet rs = null; try { + * + * final StringBuilder joinClause = new StringBuilder(); final StringBuilder + * whereClause = new StringBuilder(" WHERE t.removed IS NULL"); + * + * if (isIso) { whereClause.append(" AND t.format = 'ISO'"); if + * (!hyperType.equals(HypervisorType.None)) { joinClause.append( + * " INNER JOIN guest_os guestOS on (guestOS.id = t.guest_os_id) INNER JOIN guest_os_hypervisor goh on ( goh.guest_os_id = guestOS.id) " + * ); whereClause.append(" AND goh.hypervisor_type = '"); + * whereClause.append(hyperType); whereClause.append("'"); } } else { + * whereClause.append(" AND t.format <> 'ISO'"); if (hypers.isEmpty()) { + * return templateZonePairList; } else { final StringBuilder relatedHypers = + * new StringBuilder(); for (HypervisorType hyper : hypers) { + * relatedHypers.append("'"); relatedHypers.append(hyper.toString()); + * relatedHypers.append("'"); relatedHypers.append(","); } + * relatedHypers.setLength(relatedHypers.length() - 1); + * whereClause.append(" AND t.hypervisor_type IN ("); + * whereClause.append(relatedHypers); whereClause.append(")"); } } + * + * joinClause.append( + * " INNER JOIN template_s3_ref tsr on (t.id = tsr.template_id)"); + * + * whereClause.append("AND t.name LIKE \"%"); whereClause.append(keyword == + * null ? keyword : name); whereClause.append("%\""); + * + * if (bootable != null) { whereClause.append(" AND t.bootable = "); + * whereClause.append(bootable); } + * + * if (!showDomr) { whereClause.append(" AND t.type != '"); + * whereClause.append(Storage.TemplateType.SYSTEM); whereClause.append("'"); + * } + * + * if (templateFilter == TemplateFilter.featured) { + * whereClause.append(" AND t.public = 1 AND t.featured = 1"); } else if + * ((templateFilter == TemplateFilter.self || templateFilter == + * TemplateFilter.selfexecutable) && caller.getType() != + * Account.ACCOUNT_TYPE_ADMIN) { if (caller.getType() == + * Account.ACCOUNT_TYPE_DOMAIN_ADMIN || caller.getType() == + * Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { joinClause.append( + * " INNER JOIN account a on (t.account_id = a.id) INNER JOIN domain d on (a.domain_id = d.id)" + * ); whereClause.append(" AND d.path LIKE '"); + * whereClause.append(domain.getPath()); whereClause.append("%'"); } else { + * whereClause.append(" AND t.account_id IN ("); + * whereClause.append(permittedAccountsStr); whereClause.append(")"); } } + * else if (templateFilter == TemplateFilter.sharedexecutable && + * caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { if (caller.getType() == + * Account.ACCOUNT_TYPE_NORMAL) { joinClause.append( + * " LEFT JOIN launch_permission lp ON t.id = lp.template_id WHERE (t.account_id IN (" + * ); joinClause.append(permittedAccountsStr); + * joinClause.append(") OR lp.account_id IN ("); + * joinClause.append(permittedAccountsStr); joinClause.append("))"); } else + * { joinClause.append(" INNER JOIN account a on (t.account_id = a.id) "); } + * } else if (templateFilter == TemplateFilter.executable && + * !permittedAccounts.isEmpty()) { + * whereClause.append(" AND (t.public = 1 OR t.account_id IN ("); + * whereClause.append(permittedAccountsStr); whereClause.append("))"); } + * else if (templateFilter == TemplateFilter.community) { + * whereClause.append(" AND t.public = 1 AND t.featured = 0"); } else if + * (templateFilter == TemplateFilter.all && caller.getType() == + * Account.ACCOUNT_TYPE_ADMIN) { } else if (caller.getType() != + * Account.ACCOUNT_TYPE_ADMIN) { return templateZonePairList; } + * + * final StringBuilder sql = new StringBuilder(SELECT_TEMPLATE_S3_REF); + * sql.append(joinClause); sql.append(whereClause); + * sql.append(getOrderByLimit(pageSize, startIndex)); + * + * pstmt = txn.prepareStatement(sql.toString()); rs = pstmt.executeQuery(); + * while (rs.next()) { final Pair templateZonePair = new + * Pair( rs.getLong(1), -1L); + * templateZonePairList.add(templateZonePair); } txn.commit(); } catch + * (Exception e) { s_logger.warn("Error listing S3 templates", e); if (txn + * != null) { txn.rollback(); } } finally { closeResources(pstmt, rs); if + * (txn != null) { txn.close(); } } + * + * return templateZonePairList; } + */ - SearchCriteria sc = updateStateSearch.create(); - sc.setParameters("id", vo.getId()); - sc.setParameters("state", currentState); - sc.setParameters("updatedCount", vo.getUpdatedCount()); - - vo.incrUpdatedCount(); - - UpdateBuilder builder = getUpdateBuilder(vo); - builder.set(vo, "state", nextState); - builder.set(vo, "updated", new Date()); - - int rows = update((VMTemplateVO) vo, sc); - if (rows == 0 && s_logger.isDebugEnabled()) { - VMTemplateVO dbVol = findByIdIncludingRemoved(vo.getId()); - if (dbVol != null) { - StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); - str.append(": DB Data={id=").append(dbVol.getId()).append("; state=").append(dbVol.getState()).append("; updatecount=").append(dbVol.getUpdatedCount()).append(";updatedTime=") - .append(dbVol.getUpdated()); - str.append(": New Data={id=").append(vo.getId()).append("; state=").append(nextState).append("; event=").append(event).append("; updatecount=").append(vo.getUpdatedCount()) - .append("; updatedTime=").append(vo.getUpdated()); - str.append(": stale Data={id=").append(vo.getId()).append("; state=").append(currentState).append("; event=").append(event).append("; updatecount=").append(oldUpdated) - .append("; updatedTime=").append(oldUpdatedTime); - } else { - s_logger.debug("Unable to update objectIndatastore: id=" + vo.getId() + ", as there is no such object exists in the database anymore"); - } - } - return rows > 0; - } } diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateDetailsDao.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateDetailsDao.java index 5edea8e5586..552f8f00a86 100644 --- a/engine/schema/src/com/cloud/storage/dao/VMTemplateDetailsDao.java +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateDetailsDao.java @@ -21,12 +21,12 @@ import java.util.Map; import com.cloud.storage.VMTemplateDetailVO; import com.cloud.utils.db.GenericDao; -public interface VMTemplateDetailsDao extends GenericDao { +public interface VMTemplateDetailsDao extends GenericDao { Map findDetails(long templateId); - + void persist(long templateId, Map details); - + VMTemplateDetailVO findDetail(long templateId, String name); - - void deleteDetails(long vmId); + + void deleteDetails(long vmId); } diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java index 04b553c2f8b..33b96c45bcc 100644 --- a/engine/schema/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java @@ -31,69 +31,69 @@ import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; @Component -@Local(value=VMTemplateDetailsDao.class) +@Local(value = VMTemplateDetailsDao.class) public class VMTemplateDetailsDaoImpl extends GenericDaoBase implements VMTemplateDetailsDao { protected final SearchBuilder TemplateSearch; protected final SearchBuilder DetailSearch; - - public VMTemplateDetailsDaoImpl() { - TemplateSearch = createSearchBuilder(); - TemplateSearch.and("templateId", TemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); - TemplateSearch.done(); - - DetailSearch = createSearchBuilder(); + + public VMTemplateDetailsDaoImpl() { + TemplateSearch = createSearchBuilder(); + TemplateSearch.and("templateId", TemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + TemplateSearch.done(); + + DetailSearch = createSearchBuilder(); DetailSearch.and("templateId", DetailSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); DetailSearch.and("name", DetailSearch.entity().getName(), SearchCriteria.Op.EQ); DetailSearch.done(); - } - - @Override - public void deleteDetails(long templateId) { + } + + @Override + public void deleteDetails(long templateId) { SearchCriteria sc = TemplateSearch.create(); sc.setParameters("templateId", templateId); - + List results = search(sc, null); for (VMTemplateDetailVO result : results) { - remove(result.getId()); - } - } + remove(result.getId()); + } + } - @Override - public VMTemplateDetailVO findDetail(long templateId, String name) { + @Override + public VMTemplateDetailVO findDetail(long templateId, String name) { SearchCriteria sc = DetailSearch.create(); sc.setParameters("templateId", templateId); sc.setParameters("name", name); - - return findOneBy(sc); - } - @Override - public Map findDetails(long templateId) { + return findOneBy(sc); + } + + @Override + public Map findDetails(long templateId) { SearchCriteria sc = TemplateSearch.create(); sc.setParameters("templateId", templateId); - + List results = search(sc, null); Map details = new HashMap(results.size()); for (VMTemplateDetailVO result : results) { details.put(result.getName(), result.getValue()); } - - return details; - } - @Override - public void persist(long templateId, Map details) { + return details; + } + + @Override + public void persist(long templateId, Map details) { Transaction txn = Transaction.currentTxn(); txn.start(); SearchCriteria sc = TemplateSearch.create(); sc.setParameters("templateId", templateId); expunge(sc); - + for (Map.Entry detail : details.entrySet()) { VMTemplateDetailVO vo = new VMTemplateDetailVO(templateId, detail.getKey(), detail.getValue()); persist(vo); } - txn.commit(); - } + txn.commit(); + } } diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateHostDao.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateHostDao.java index 23241cd17da..72072fa9325 100755 --- a/engine/schema/src/com/cloud/storage/dao/VMTemplateHostDao.java +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateHostDao.java @@ -26,28 +26,31 @@ import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.utils.db.GenericDao; import com.cloud.utils.fsm.StateDao; -public interface VMTemplateHostDao extends GenericDao, StateDao { +public interface VMTemplateHostDao extends GenericDao, + StateDao { List listByHostId(long id); List listByTemplateId(long templateId); - + List listByOnlyTemplateId(long templateId); VMTemplateHostVO findByHostTemplate(long hostId, long templateId); - + VMTemplateHostVO findByTemplateId(long templateId); VMTemplateHostVO findByHostTemplate(long hostId, long templateId, boolean lock); List listByHostTemplate(long hostId, long templateId); - void update(VMTemplateHostVO instance); + void update(VMTemplateHostVO instance); List listByTemplateStatus(long templateId, VMTemplateHostVO.Status downloadState); - List listByTemplateStatus(long templateId, long datacenterId, VMTemplateHostVO.Status downloadState); + List listByTemplateStatus(long templateId, long datacenterId, + VMTemplateHostVO.Status downloadState); - List listByTemplateStatus(long templateId, long datacenterId, long podId, VMTemplateHostVO.Status downloadState); + List listByTemplateStatus(long templateId, long datacenterId, long podId, + VMTemplateHostVO.Status downloadState); List listByTemplateStates(long templateId, VMTemplateHostVO.Status... states); diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateHostDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateHostDaoImpl.java index 7f35eabfaa7..85d8348e36e 100755 --- a/engine/schema/src/com/cloud/storage/dao/VMTemplateHostDaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateHostDaoImpl.java @@ -50,67 +50,61 @@ import com.cloud.utils.db.Transaction; import com.cloud.utils.db.UpdateBuilder; @Component -@Local(value={VMTemplateHostDao.class}) +@Local(value = { VMTemplateHostDao.class }) public class VMTemplateHostDaoImpl extends GenericDaoBase implements VMTemplateHostDao { - public static final Logger s_logger = Logger.getLogger(VMTemplateHostDaoImpl.class.getName()); + public static final Logger s_logger = Logger.getLogger(VMTemplateHostDaoImpl.class.getName()); @Inject - HostDao _hostDao; - protected final SearchBuilder HostSearch; - protected final SearchBuilder TemplateSearch; - protected final SearchBuilder HostTemplateSearch; - protected final SearchBuilder HostTemplateStateSearch; - protected final SearchBuilder HostDestroyedSearch; - protected final SearchBuilder TemplateStatusSearch; - protected final SearchBuilder TemplateStatesSearch; - protected final SearchBuilder updateStateSearch; - protected SearchBuilder ZONE_TEMPLATE_SEARCH; - protected SearchBuilder LOCAL_SECONDARY_STORAGE_SEARCH; + HostDao _hostDao; + protected final SearchBuilder HostSearch; + protected final SearchBuilder TemplateSearch; + protected final SearchBuilder HostTemplateSearch; + protected final SearchBuilder HostTemplateStateSearch; + protected final SearchBuilder HostDestroyedSearch; + protected final SearchBuilder TemplateStatusSearch; + protected final SearchBuilder TemplateStatesSearch; + protected final SearchBuilder updateStateSearch; + protected SearchBuilder ZONE_TEMPLATE_SEARCH; + protected SearchBuilder LOCAL_SECONDARY_STORAGE_SEARCH; - - protected static final String UPDATE_TEMPLATE_HOST_REF = - "UPDATE template_host_ref SET download_state = ?, download_pct= ?, last_updated = ? " - + ", error_str = ?, local_path = ?, job_id = ? " - + "WHERE host_id = ? and type_id = ?"; - - protected static final String DOWNLOADS_STATE_DC= - "SELECT t.id, t.host_id, t.template_id, t.created, t.last_updated, t.job_id, " - + "t.download_pct, t.size, t.physical_size, t.download_state, t.error_str, t.local_path, " - + "t.install_path, t.url, t.destroyed, t.is_copy FROM template_host_ref t, host h " - + "where t.host_id = h.id and h.data_center_id=? " - + " and t.template_id=? and t.download_state = ?" ; - - protected static final String DOWNLOADS_STATE_DC_POD= - "SELECT * FROM template_host_ref t, host h where t.host_id = h.id and h.data_center_id=? and h.pod_id=? " - + " and t.template_id=? and t.download_state=?" ; - - protected static final String DOWNLOADS_STATE= - "SELECT * FROM template_host_ref t " - + " where t.template_id=? and t.download_state=?"; - - public VMTemplateHostDaoImpl () { - HostSearch = createSearchBuilder(); - HostSearch.and("host_id", HostSearch.entity().getHostId(), SearchCriteria.Op.EQ); - HostSearch.done(); - - TemplateSearch = createSearchBuilder(); - TemplateSearch.and("template_id", TemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); - TemplateSearch.and("destroyed", TemplateSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); - TemplateSearch.done(); - - HostTemplateSearch = createSearchBuilder(); - HostTemplateSearch.and("host_id", HostTemplateSearch.entity().getHostId(), SearchCriteria.Op.EQ); - HostTemplateSearch.and("template_id", HostTemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + protected static final String UPDATE_TEMPLATE_HOST_REF = "UPDATE template_host_ref SET download_state = ?, download_pct= ?, last_updated = ? " + + ", error_str = ?, local_path = ?, job_id = ? " + "WHERE host_id = ? and type_id = ?"; + + protected static final String DOWNLOADS_STATE_DC = "SELECT t.id, t.host_id, t.template_id, t.created, t.last_updated, t.job_id, " + + "t.download_pct, t.size, t.physical_size, t.download_state, t.error_str, t.local_path, " + + "t.install_path, t.url, t.destroyed, t.is_copy FROM template_host_ref t, host h " + + "where t.host_id = h.id and h.data_center_id=? " + " and t.template_id=? and t.download_state = ?"; + + protected static final String DOWNLOADS_STATE_DC_POD = "SELECT * FROM template_host_ref t, host h where t.host_id = h.id and h.data_center_id=? and h.pod_id=? " + + " and t.template_id=? and t.download_state=?"; + + protected static final String DOWNLOADS_STATE = "SELECT * FROM template_host_ref t " + + " where t.template_id=? and t.download_state=?"; + + public VMTemplateHostDaoImpl() { + HostSearch = createSearchBuilder(); + HostSearch.and("host_id", HostSearch.entity().getHostId(), SearchCriteria.Op.EQ); + HostSearch.done(); + + TemplateSearch = createSearchBuilder(); + TemplateSearch.and("template_id", TemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + TemplateSearch.and("destroyed", TemplateSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + TemplateSearch.done(); + + HostTemplateSearch = createSearchBuilder(); + HostTemplateSearch.and("host_id", HostTemplateSearch.entity().getHostId(), SearchCriteria.Op.EQ); + HostTemplateSearch.and("template_id", HostTemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); HostTemplateSearch.and("destroyed", HostTemplateSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); HostTemplateSearch.done(); - - HostDestroyedSearch = createSearchBuilder(); - HostDestroyedSearch.and("host_id", HostDestroyedSearch.entity().getHostId(), SearchCriteria.Op.EQ); - HostDestroyedSearch.and("destroyed", HostDestroyedSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); - HostDestroyedSearch.done(); - - TemplateStatusSearch = createSearchBuilder(); - TemplateStatusSearch.and("template_id", TemplateStatusSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); - TemplateStatusSearch.and("download_state", TemplateStatusSearch.entity().getDownloadState(), SearchCriteria.Op.EQ); + + HostDestroyedSearch = createSearchBuilder(); + HostDestroyedSearch.and("host_id", HostDestroyedSearch.entity().getHostId(), SearchCriteria.Op.EQ); + HostDestroyedSearch.and("destroyed", HostDestroyedSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + HostDestroyedSearch.done(); + + TemplateStatusSearch = createSearchBuilder(); + TemplateStatusSearch.and("template_id", TemplateStatusSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + TemplateStatusSearch.and("download_state", TemplateStatusSearch.entity().getDownloadState(), + SearchCriteria.Op.EQ); TemplateStatusSearch.and("destroyed", TemplateStatusSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); TemplateStatusSearch.done(); @@ -121,12 +115,14 @@ public class VMTemplateHostDaoImpl extends GenericDaoBase params) throws ConfigurationException { - boolean result = super.configure(name, params); - ZONE_TEMPLATE_SEARCH = createSearchBuilder(); - ZONE_TEMPLATE_SEARCH.and("template_id", ZONE_TEMPLATE_SEARCH.entity().getTemplateId(), SearchCriteria.Op.EQ); - ZONE_TEMPLATE_SEARCH.and("state", ZONE_TEMPLATE_SEARCH.entity().getDownloadState(), SearchCriteria.Op.EQ); - SearchBuilder hostSearch = _hostDao.createSearchBuilder(); - hostSearch.and("zone_id", hostSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); - ZONE_TEMPLATE_SEARCH.join("tmplHost", hostSearch, hostSearch.entity().getId(), ZONE_TEMPLATE_SEARCH.entity().getHostId(), JoinBuilder.JoinType.INNER); - ZONE_TEMPLATE_SEARCH.done(); - - LOCAL_SECONDARY_STORAGE_SEARCH = createSearchBuilder(); - LOCAL_SECONDARY_STORAGE_SEARCH.and("template_id", LOCAL_SECONDARY_STORAGE_SEARCH.entity().getTemplateId(), SearchCriteria.Op.EQ); - LOCAL_SECONDARY_STORAGE_SEARCH.and("state", LOCAL_SECONDARY_STORAGE_SEARCH.entity().getDownloadState(), SearchCriteria.Op.EQ); - SearchBuilder localSecondaryHost = _hostDao.createSearchBuilder(); - localSecondaryHost.and("private_ip_address", localSecondaryHost.entity().getPrivateIpAddress(), SearchCriteria.Op.EQ); - localSecondaryHost.and("state", localSecondaryHost.entity().getStatus(), SearchCriteria.Op.EQ); - localSecondaryHost.and("data_center_id", localSecondaryHost.entity().getDataCenterId(), SearchCriteria.Op.EQ); - localSecondaryHost.and("type", localSecondaryHost.entity().getType(), SearchCriteria.Op.EQ); - LOCAL_SECONDARY_STORAGE_SEARCH.join("host", localSecondaryHost, localSecondaryHost.entity().getId(), LOCAL_SECONDARY_STORAGE_SEARCH.entity().getHostId(), JoinBuilder.JoinType.INNER); - LOCAL_SECONDARY_STORAGE_SEARCH.done(); - - return result; - } - @Override - public void update(VMTemplateHostVO instance) { - Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = null; - try { - Date now = new Date(); - String sql = UPDATE_TEMPLATE_HOST_REF; - pstmt = txn.prepareAutoCloseStatement(sql); - pstmt.setString(1, instance.getDownloadState().toString()); - pstmt.setInt(2, instance.getDownloadPercent()); - pstmt.setString(3, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), now)); - pstmt.setString(4, instance.getErrorString()); - pstmt.setString(5, instance.getLocalDownloadPath()); - pstmt.setString(6, instance.getJobId()); - pstmt.setLong(7, instance.getHostId()); - pstmt.setLong(8, instance.getTemplateId()); - pstmt.executeUpdate(); - } catch (Exception e) { - s_logger.warn("Exception: ", e); - } - } - - @Override - public List listByHostId(long id) { - SearchCriteria sc = HostSearch.create(); - sc.setParameters("host_id", id); - return listIncludingRemovedBy(sc); - } - - @Override - public List listByTemplateId(long templateId) { - SearchCriteria sc = TemplateSearch.create(); - sc.setParameters("template_id", templateId); - sc.setParameters("destroyed", false); - return listIncludingRemovedBy(sc); - } - - - @Override - public List listByOnlyTemplateId(long templateId) { - SearchCriteria sc = TemplateSearch.create(); - sc.setParameters("template_id", templateId); - sc.setParameters("destroyed", false); - return listIncludingRemovedBy(sc); - } - - @Override - public VMTemplateHostVO findByHostTemplate(long hostId, long templateId) { - SearchCriteria sc = HostTemplateSearch.create(); - sc.setParameters("host_id", hostId); - sc.setParameters("template_id", templateId); - sc.setParameters("destroyed", false); - return findOneIncludingRemovedBy(sc); - } - - @Override - public VMTemplateHostVO findByTemplateId(long templateId) { - SearchCriteria sc = HostTemplateSearch.create(); - sc.setParameters("template_id", templateId); - sc.setParameters("destroyed", false); - return findOneIncludingRemovedBy(sc); - } - - @Override - public List listByTemplateStatus(long templateId, VMTemplateHostVO.Status downloadState) { - SearchCriteria sc = TemplateStatusSearch.create(); - sc.setParameters("template_id", templateId); - sc.setParameters("download_state", downloadState.toString()); - sc.setParameters("destroyed", false); - return listIncludingRemovedBy(sc); - } - - @Override - public List listByTemplateStatus(long templateId, long datacenterId, VMTemplateHostVO.Status downloadState) { - Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = null; - List result = new ArrayList(); - try { - String sql = DOWNLOADS_STATE_DC; - pstmt = txn.prepareAutoCloseStatement(sql); - pstmt.setLong(1, datacenterId); - pstmt.setLong(2, templateId); - pstmt.setString(3, downloadState.toString()); - ResultSet rs = pstmt.executeQuery(); - while (rs.next()) { - result.add(toEntityBean(rs, false)); - } - } catch (Exception e) { - s_logger.warn("Exception: ", e); - } - return result; - } @Override - public List listByTemplateHostStatus(long templateId, long hostId, VMTemplateHostVO.Status... states) { + public boolean configure(String name, Map params) throws ConfigurationException { + boolean result = super.configure(name, params); + ZONE_TEMPLATE_SEARCH = createSearchBuilder(); + ZONE_TEMPLATE_SEARCH.and("template_id", ZONE_TEMPLATE_SEARCH.entity().getTemplateId(), SearchCriteria.Op.EQ); + ZONE_TEMPLATE_SEARCH.and("state", ZONE_TEMPLATE_SEARCH.entity().getDownloadState(), SearchCriteria.Op.EQ); + SearchBuilder hostSearch = _hostDao.createSearchBuilder(); + hostSearch.and("zone_id", hostSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); + ZONE_TEMPLATE_SEARCH.join("tmplHost", hostSearch, hostSearch.entity().getId(), ZONE_TEMPLATE_SEARCH.entity() + .getHostId(), JoinBuilder.JoinType.INNER); + ZONE_TEMPLATE_SEARCH.done(); + + LOCAL_SECONDARY_STORAGE_SEARCH = createSearchBuilder(); + LOCAL_SECONDARY_STORAGE_SEARCH.and("template_id", LOCAL_SECONDARY_STORAGE_SEARCH.entity().getTemplateId(), + SearchCriteria.Op.EQ); + LOCAL_SECONDARY_STORAGE_SEARCH.and("state", LOCAL_SECONDARY_STORAGE_SEARCH.entity().getDownloadState(), + SearchCriteria.Op.EQ); + SearchBuilder localSecondaryHost = _hostDao.createSearchBuilder(); + localSecondaryHost.and("private_ip_address", localSecondaryHost.entity().getPrivateIpAddress(), + SearchCriteria.Op.EQ); + localSecondaryHost.and("state", localSecondaryHost.entity().getStatus(), SearchCriteria.Op.EQ); + localSecondaryHost.and("data_center_id", localSecondaryHost.entity().getDataCenterId(), SearchCriteria.Op.EQ); + localSecondaryHost.and("type", localSecondaryHost.entity().getType(), SearchCriteria.Op.EQ); + LOCAL_SECONDARY_STORAGE_SEARCH.join("host", localSecondaryHost, localSecondaryHost.entity().getId(), + LOCAL_SECONDARY_STORAGE_SEARCH.entity().getHostId(), JoinBuilder.JoinType.INNER); + LOCAL_SECONDARY_STORAGE_SEARCH.done(); + + return result; + } + + @Override + public void update(VMTemplateHostVO instance) { + Transaction txn = Transaction.currentTxn(); + PreparedStatement pstmt = null; + try { + Date now = new Date(); + String sql = UPDATE_TEMPLATE_HOST_REF; + pstmt = txn.prepareAutoCloseStatement(sql); + pstmt.setString(1, instance.getDownloadState().toString()); + pstmt.setInt(2, instance.getDownloadPercent()); + pstmt.setString(3, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), now)); + pstmt.setString(4, instance.getErrorString()); + pstmt.setString(5, instance.getLocalDownloadPath()); + pstmt.setString(6, instance.getJobId()); + pstmt.setLong(7, instance.getHostId()); + pstmt.setLong(8, instance.getTemplateId()); + pstmt.executeUpdate(); + } catch (Exception e) { + s_logger.warn("Exception: ", e); + } + } + + @Override + public List listByHostId(long id) { + SearchCriteria sc = HostSearch.create(); + sc.setParameters("host_id", id); + return listIncludingRemovedBy(sc); + } + + @Override + public List listByTemplateId(long templateId) { + SearchCriteria sc = TemplateSearch.create(); + sc.setParameters("template_id", templateId); + sc.setParameters("destroyed", false); + return listIncludingRemovedBy(sc); + } + + @Override + public List listByOnlyTemplateId(long templateId) { + SearchCriteria sc = TemplateSearch.create(); + sc.setParameters("template_id", templateId); + sc.setParameters("destroyed", false); + return listIncludingRemovedBy(sc); + } + + @Override + public VMTemplateHostVO findByHostTemplate(long hostId, long templateId) { + SearchCriteria sc = HostTemplateSearch.create(); + sc.setParameters("host_id", hostId); + sc.setParameters("template_id", templateId); + sc.setParameters("destroyed", false); + return findOneIncludingRemovedBy(sc); + } + + @Override + public VMTemplateHostVO findByTemplateId(long templateId) { + SearchCriteria sc = HostTemplateSearch.create(); + sc.setParameters("template_id", templateId); + sc.setParameters("destroyed", false); + return findOneIncludingRemovedBy(sc); + } + + @Override + public List listByTemplateStatus(long templateId, VMTemplateHostVO.Status downloadState) { + SearchCriteria sc = TemplateStatusSearch.create(); + sc.setParameters("template_id", templateId); + sc.setParameters("download_state", downloadState.toString()); + sc.setParameters("destroyed", false); + return listIncludingRemovedBy(sc); + } + + @Override + public List listByTemplateStatus(long templateId, long datacenterId, + VMTemplateHostVO.Status downloadState) { + Transaction txn = Transaction.currentTxn(); + PreparedStatement pstmt = null; + List result = new ArrayList(); + try { + String sql = DOWNLOADS_STATE_DC; + pstmt = txn.prepareAutoCloseStatement(sql); + pstmt.setLong(1, datacenterId); + pstmt.setLong(2, templateId); + pstmt.setString(3, downloadState.toString()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + result.add(toEntityBean(rs, false)); + } + } catch (Exception e) { + s_logger.warn("Exception: ", e); + } + return result; + } + + @Override + public List listByTemplateHostStatus(long templateId, long hostId, + VMTemplateHostVO.Status... states) { SearchCriteria sc = HostTemplateStateSearch.create(); sc.setParameters("template_id", templateId); sc.setParameters("host_id", hostId); - sc.setParameters("states", (Object[])states); + sc.setParameters("states", (Object[]) states); return search(sc, null); } - - @Override - public List listByTemplateStatus(long templateId, long datacenterId, long podId, VMTemplateHostVO.Status downloadState) { + + @Override + public List listByTemplateStatus(long templateId, long datacenterId, long podId, + VMTemplateHostVO.Status downloadState) { Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = null; - List result = new ArrayList(); - ResultSet rs = null; - try { - String sql = DOWNLOADS_STATE_DC_POD; - pstmt = txn.prepareStatement(sql); - - pstmt.setLong(1, datacenterId); - pstmt.setLong(2, podId); - pstmt.setLong(3, templateId); - pstmt.setString(4, downloadState.toString()); - rs = pstmt.executeQuery(); - while (rs.next()) { - // result.add(toEntityBean(rs, false)); TODO: this is buggy in GenericDaoBase for hand constructed queries - long id = rs.getLong(1); //ID column - result.add(findById(id)); + PreparedStatement pstmt = null; + List result = new ArrayList(); + ResultSet rs = null; + try { + String sql = DOWNLOADS_STATE_DC_POD; + pstmt = txn.prepareStatement(sql); + + pstmt.setLong(1, datacenterId); + pstmt.setLong(2, podId); + pstmt.setLong(3, templateId); + pstmt.setString(4, downloadState.toString()); + rs = pstmt.executeQuery(); + while (rs.next()) { + // result.add(toEntityBean(rs, false)); TODO: this is buggy in + // GenericDaoBase for hand constructed queries + long id = rs.getLong(1); // ID column + result.add(findById(id)); } - } catch (Exception e) { - s_logger.warn("Exception: ", e); - } finally { - try { - if (rs != null) { - rs.close(); - } - if (pstmt != null) { - pstmt.close(); - } - } catch (SQLException e) { - } - } - return result; + } catch (Exception e) { + s_logger.warn("Exception: ", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + return result; - } + } - @Override - public boolean templateAvailable(long templateId, long hostId) { - VMTemplateHostVO tmpltHost = findByHostTemplate(hostId, templateId); - if (tmpltHost == null) - return false; - - return tmpltHost.getDownloadState()==Status.DOWNLOADED; - } + @Override + public boolean templateAvailable(long templateId, long hostId) { + VMTemplateHostVO tmpltHost = findByHostTemplate(hostId, templateId); + if (tmpltHost == null) + return false; - @Override - public List listByTemplateStates(long templateId, VMTemplateHostVO.Status... states) { - SearchCriteria sc = TemplateStatesSearch.create(); - sc.setParameters("states", (Object[])states); - sc.setParameters("template_id", templateId); + return tmpltHost.getDownloadState() == Status.DOWNLOADED; + } + + @Override + public List listByTemplateStates(long templateId, VMTemplateHostVO.Status... states) { + SearchCriteria sc = TemplateStatesSearch.create(); + sc.setParameters("states", (Object[]) states); + sc.setParameters("template_id", templateId); sc.setParameters("destroyed", false); return search(sc, null); - } + } @Override public List listByState(VMTemplateHostVO.Status state) { @@ -324,14 +329,14 @@ public class VMTemplateHostDaoImpl extends GenericDaoBase listByHostTemplate(long hostId, long templateId) { - SearchCriteria sc = HostTemplateSearch.create(); - sc.setParameters("host_id", hostId); + @Override + public List listByHostTemplate(long hostId, long templateId) { + SearchCriteria sc = HostTemplateSearch.create(); + sc.setParameters("host_id", hostId); sc.setParameters("template_id", templateId); sc.setParameters("destroyed", false); return listIncludingRemovedBy(sc); - } + } @Override public List listByZoneTemplate(long dcId, long templateId, boolean readyOnly) { @@ -340,61 +345,61 @@ public class VMTemplateHostDaoImpl extends GenericDaoBase listDestroyed(long hostId) { - SearchCriteria sc = HostDestroyedSearch.create(); - sc.setParameters("host_id", hostId); - sc.setParameters("destroyed", true); - return listIncludingRemovedBy(sc); - } - @Override - public VMTemplateHostVO findByHostTemplate(long hostId, long templateId, boolean lock) { - SearchCriteria sc = HostTemplateSearch.create(); - sc.setParameters("host_id", hostId); - sc.setParameters("template_id", templateId); + @Override + public List listDestroyed(long hostId) { + SearchCriteria sc = HostDestroyedSearch.create(); + sc.setParameters("host_id", hostId); + sc.setParameters("destroyed", true); + return listIncludingRemovedBy(sc); + } + + @Override + public VMTemplateHostVO findByHostTemplate(long hostId, long templateId, boolean lock) { + SearchCriteria sc = HostTemplateSearch.create(); + sc.setParameters("host_id", hostId); + sc.setParameters("template_id", templateId); sc.setParameters("destroyed", false); - if (!lock) - return findOneIncludingRemovedBy(sc); - else - return lockOneRandomRow(sc, true); - } - - //Based on computing node host id, and template id, find out the corresponding template_host_ref, assuming local secondary storage and computing node is in the same zone, and private ip - @Override - public VMTemplateHostVO findLocalSecondaryStorageByHostTemplate(long hostId, long templateId) { - HostVO computingHost = _hostDao.findById(hostId); - SearchCriteria sc = LOCAL_SECONDARY_STORAGE_SEARCH.create(); - sc.setJoinParameters("host", "private_ip_address", computingHost.getPrivateIpAddress()); - sc.setJoinParameters("host", "state", com.cloud.host.Status.Up); - sc.setJoinParameters("host", "data_center_id", computingHost.getDataCenterId()); - sc.setJoinParameters("host", "type", Host.Type.LocalSecondaryStorage); - sc.setParameters("template_id", templateId); - sc.setParameters("state", VMTemplateHostVO.Status.DOWNLOADED); + if (!lock) + return findOneIncludingRemovedBy(sc); + else + return lockOneRandomRow(sc, true); + } + + // Based on computing node host id, and template id, find out the + // corresponding template_host_ref, assuming local secondary storage and + // computing node is in the same zone, and private ip + @Override + public VMTemplateHostVO findLocalSecondaryStorageByHostTemplate(long hostId, long templateId) { + HostVO computingHost = _hostDao.findById(hostId); + SearchCriteria sc = LOCAL_SECONDARY_STORAGE_SEARCH.create(); + sc.setJoinParameters("host", "private_ip_address", computingHost.getPrivateIpAddress()); + sc.setJoinParameters("host", "state", com.cloud.host.Status.Up); + sc.setJoinParameters("host", "data_center_id", computingHost.getDataCenterId()); + sc.setJoinParameters("host", "type", Host.Type.LocalSecondaryStorage); + sc.setParameters("template_id", templateId); + sc.setParameters("state", VMTemplateHostVO.Status.DOWNLOADED); sc.setParameters("destroyed", false); - return findOneBy(sc); - } + return findOneBy(sc); + } @Override public void deleteByHost(Long hostId) { List tmpltHosts = listByHostId(hostId); - for (VMTemplateHostVO tmpltHost : tmpltHosts ) { + for (VMTemplateHostVO tmpltHost : tmpltHosts) { remove(tmpltHost.getId()); } } - + @Override - public boolean updateState(State currentState, Event event, - State nextState, DataObjectInStore vo, Object data) { - VMTemplateHostVO templateHost = (VMTemplateHostVO)vo; + public boolean updateState(State currentState, Event event, State nextState, DataObjectInStore vo, Object data) { + VMTemplateHostVO templateHost = (VMTemplateHostVO) vo; Long oldUpdated = templateHost.getUpdatedCount(); Date oldUpdatedTime = templateHost.getUpdated(); - - + SearchCriteria sc = updateStateSearch.create(); sc.setParameters("id", templateHost.getId()); sc.setParameters("state", currentState); @@ -411,14 +416,19 @@ public class VMTemplateHostDaoImpl extends GenericDaoBase 0; diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplatePoolDao.java b/engine/schema/src/com/cloud/storage/dao/VMTemplatePoolDao.java index 501c3ca5cc8..7e6360b8960 100644 --- a/engine/schema/src/com/cloud/storage/dao/VMTemplatePoolDao.java +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplatePoolDao.java @@ -25,25 +25,29 @@ import com.cloud.storage.VMTemplateStoragePoolVO; import com.cloud.utils.db.GenericDao; import com.cloud.utils.fsm.StateDao; -public interface VMTemplatePoolDao extends GenericDao, StateDao { - public List listByPoolId(long id); - - public List listByTemplateId(long templateId); - - public VMTemplateStoragePoolVO findByPoolTemplate(long poolId, long templateId); +public interface VMTemplatePoolDao extends GenericDao, + StateDao { + public List listByPoolId(long id); - public List listByTemplateStatus(long templateId, VMTemplateStoragePoolVO.Status downloadState); - - public List listByTemplateStatus(long templateId, VMTemplateStoragePoolVO.Status downloadState, long poolId); + public List listByTemplateId(long templateId); - public List listByTemplateStatus(long templateId, long datacenterId, VMTemplateStoragePoolVO.Status downloadState); - - public List listByTemplateStatus(long templateId, long datacenterId, long podId, VMTemplateStoragePoolVO.Status downloadState); + public VMTemplateStoragePoolVO findByPoolTemplate(long poolId, long templateId); - public List listByTemplateStates(long templateId, VMTemplateStoragePoolVO.Status ... states); + public List listByTemplateStatus(long templateId, + VMTemplateStoragePoolVO.Status downloadState); - - boolean templateAvailable(long templateId, long poolId); + public List listByTemplateStatus(long templateId, + VMTemplateStoragePoolVO.Status downloadState, long poolId); - public VMTemplateStoragePoolVO findByHostTemplate(Long hostId, Long templateId); + public List listByTemplateStatus(long templateId, long datacenterId, + VMTemplateStoragePoolVO.Status downloadState); + + public List listByTemplateStatus(long templateId, long datacenterId, long podId, + VMTemplateStoragePoolVO.Status downloadState); + + public List listByTemplateStates(long templateId, VMTemplateStoragePoolVO.Status... states); + + boolean templateAvailable(long templateId, long poolId); + + public VMTemplateStoragePoolVO findByHostTemplate(Long hostId, Long templateId); } diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplatePoolDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/VMTemplatePoolDaoImpl.java index 5f212ebbfea..ba8135b5f32 100644 --- a/engine/schema/src/com/cloud/storage/dao/VMTemplatePoolDaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplatePoolDaoImpl.java @@ -42,105 +42,104 @@ import com.cloud.utils.db.Transaction; import com.cloud.utils.db.UpdateBuilder; @Component -@Local(value={VMTemplatePoolDao.class}) +@Local(value = { VMTemplatePoolDao.class }) public class VMTemplatePoolDaoImpl extends GenericDaoBase implements VMTemplatePoolDao { - public static final Logger s_logger = Logger.getLogger(VMTemplatePoolDaoImpl.class.getName()); - - protected final SearchBuilder PoolSearch; - protected final SearchBuilder TemplateSearch; - protected final SearchBuilder PoolTemplateSearch; - protected final SearchBuilder TemplateStatusSearch; - protected final SearchBuilder TemplatePoolStatusSearch; - protected final SearchBuilder TemplateStatesSearch; - protected final SearchBuilder updateStateSearch; - - protected static final String UPDATE_TEMPLATE_HOST_REF = - "UPDATE template_spool_ref SET download_state = ?, download_pct= ?, last_updated = ? " - + ", error_str = ?, local_path = ?, job_id = ? " - + "WHERE pool_id = ? and template_id = ?"; - - protected static final String DOWNLOADS_STATE_DC= - "SELECT * FROM template_spool_ref t, storage_pool p where t.pool_id = p.id and p.data_center_id=? " - + " and t.template_id=? and t.download_state = ?" ; - - protected static final String DOWNLOADS_STATE_DC_POD= - "SELECT * FROM template_spool_ref tp, storage_pool_host_ref ph, host h where tp.pool_id = ph.pool_id and ph.host_id = h.id and h.data_center_id=? and h.pod_id=? " - + " and tp.template_id=? and tp.download_state=?" ; - - protected static final String HOST_TEMPLATE_SEARCH= - "SELECT * FROM template_spool_ref tp, storage_pool_host_ref ph, host h where tp.pool_id = ph.pool_id and ph.host_id = h.id and h.id=? " - + " and tp.template_id=? " ; - - - public VMTemplatePoolDaoImpl () { - PoolSearch = createSearchBuilder(); - PoolSearch.and("pool_id", PoolSearch.entity().getPoolId(), SearchCriteria.Op.EQ); - PoolSearch.done(); - - TemplateSearch = createSearchBuilder(); - TemplateSearch.and("template_id", TemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); - TemplateSearch.done(); - - PoolTemplateSearch = createSearchBuilder(); - PoolTemplateSearch.and("pool_id", PoolTemplateSearch.entity().getPoolId(), SearchCriteria.Op.EQ); - PoolTemplateSearch.and("template_id", PoolTemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); - PoolTemplateSearch.done(); - - TemplateStatusSearch = createSearchBuilder(); - TemplateStatusSearch.and("template_id", TemplateStatusSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); - TemplateStatusSearch.and("download_state", TemplateStatusSearch.entity().getDownloadState(), SearchCriteria.Op.EQ); - TemplateStatusSearch.done(); + public static final Logger s_logger = Logger.getLogger(VMTemplatePoolDaoImpl.class.getName()); - TemplatePoolStatusSearch = createSearchBuilder(); - TemplatePoolStatusSearch.and("pool_id", TemplatePoolStatusSearch.entity().getPoolId(), SearchCriteria.Op.EQ); - TemplatePoolStatusSearch.and("template_id", TemplatePoolStatusSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); - TemplatePoolStatusSearch.and("download_state", TemplatePoolStatusSearch.entity().getDownloadState(), SearchCriteria.Op.EQ); - TemplatePoolStatusSearch.done(); + protected final SearchBuilder PoolSearch; + protected final SearchBuilder TemplateSearch; + protected final SearchBuilder PoolTemplateSearch; + protected final SearchBuilder TemplateStatusSearch; + protected final SearchBuilder TemplatePoolStatusSearch; + protected final SearchBuilder TemplateStatesSearch; + protected final SearchBuilder updateStateSearch; + + protected static final String UPDATE_TEMPLATE_HOST_REF = "UPDATE template_spool_ref SET download_state = ?, download_pct= ?, last_updated = ? " + + ", error_str = ?, local_path = ?, job_id = ? " + "WHERE pool_id = ? and template_id = ?"; + + protected static final String DOWNLOADS_STATE_DC = "SELECT * FROM template_spool_ref t, storage_pool p where t.pool_id = p.id and p.data_center_id=? " + + " and t.template_id=? and t.download_state = ?"; + + protected static final String DOWNLOADS_STATE_DC_POD = "SELECT * FROM template_spool_ref tp, storage_pool_host_ref ph, host h where tp.pool_id = ph.pool_id and ph.host_id = h.id and h.data_center_id=? and h.pod_id=? " + + " and tp.template_id=? and tp.download_state=?"; + + protected static final String HOST_TEMPLATE_SEARCH = "SELECT * FROM template_spool_ref tp, storage_pool_host_ref ph, host h where tp.pool_id = ph.pool_id and ph.host_id = h.id and h.id=? " + + " and tp.template_id=? "; + + public VMTemplatePoolDaoImpl() { + PoolSearch = createSearchBuilder(); + PoolSearch.and("pool_id", PoolSearch.entity().getPoolId(), SearchCriteria.Op.EQ); + PoolSearch.done(); + + TemplateSearch = createSearchBuilder(); + TemplateSearch.and("template_id", TemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + TemplateSearch.done(); + + PoolTemplateSearch = createSearchBuilder(); + PoolTemplateSearch.and("pool_id", PoolTemplateSearch.entity().getPoolId(), SearchCriteria.Op.EQ); + PoolTemplateSearch.and("template_id", PoolTemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + PoolTemplateSearch.done(); + + TemplateStatusSearch = createSearchBuilder(); + TemplateStatusSearch.and("template_id", TemplateStatusSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + TemplateStatusSearch.and("download_state", TemplateStatusSearch.entity().getDownloadState(), + SearchCriteria.Op.EQ); + TemplateStatusSearch.done(); + + TemplatePoolStatusSearch = createSearchBuilder(); + TemplatePoolStatusSearch.and("pool_id", TemplatePoolStatusSearch.entity().getPoolId(), SearchCriteria.Op.EQ); + TemplatePoolStatusSearch.and("template_id", TemplatePoolStatusSearch.entity().getTemplateId(), + SearchCriteria.Op.EQ); + TemplatePoolStatusSearch.and("download_state", TemplatePoolStatusSearch.entity().getDownloadState(), + SearchCriteria.Op.EQ); + TemplatePoolStatusSearch.done(); TemplateStatesSearch = createSearchBuilder(); - TemplateStatesSearch.and("template_id", TemplateStatesSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); - TemplateStatesSearch.and("states", TemplateStatesSearch.entity().getDownloadState(), SearchCriteria.Op.IN); - TemplateStatesSearch.done(); + TemplateStatesSearch.and("template_id", TemplateStatesSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + TemplateStatesSearch.and("states", TemplateStatesSearch.entity().getDownloadState(), SearchCriteria.Op.IN); + TemplateStatesSearch.done(); - updateStateSearch = this.createSearchBuilder(); - updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ); - updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ); - updateStateSearch.and("updatedCount", updateStateSearch.entity().getUpdatedCount(), Op.EQ); - updateStateSearch.done(); - } + updateStateSearch = this.createSearchBuilder(); + updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ); + updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ); + updateStateSearch.and("updatedCount", updateStateSearch.entity().getUpdatedCount(), Op.EQ); + updateStateSearch.done(); + } - @Override - public List listByPoolId(long id) { - SearchCriteria sc = PoolSearch.create(); - sc.setParameters("pool_id", id); - return listIncludingRemovedBy(sc); - } + @Override + public List listByPoolId(long id) { + SearchCriteria sc = PoolSearch.create(); + sc.setParameters("pool_id", id); + return listIncludingRemovedBy(sc); + } - @Override - public List listByTemplateId(long templateId) { - SearchCriteria sc = TemplateSearch.create(); - sc.setParameters("template_id", templateId); - return listIncludingRemovedBy(sc); - } + @Override + public List listByTemplateId(long templateId) { + SearchCriteria sc = TemplateSearch.create(); + sc.setParameters("template_id", templateId); + return listIncludingRemovedBy(sc); + } - @Override - public VMTemplateStoragePoolVO findByPoolTemplate(long hostId, long templateId) { - SearchCriteria sc = PoolTemplateSearch.create(); - sc.setParameters("pool_id", hostId); - sc.setParameters("template_id", templateId); - return findOneIncludingRemovedBy(sc); - } + @Override + public VMTemplateStoragePoolVO findByPoolTemplate(long hostId, long templateId) { + SearchCriteria sc = PoolTemplateSearch.create(); + sc.setParameters("pool_id", hostId); + sc.setParameters("template_id", templateId); + return findOneIncludingRemovedBy(sc); + } - @Override - public List listByTemplateStatus(long templateId, VMTemplateStoragePoolVO.Status downloadState) { - SearchCriteria sc = TemplateStatusSearch.create(); - sc.setParameters("template_id", templateId); - sc.setParameters("download_state", downloadState.toString()); - return listIncludingRemovedBy(sc); - } + @Override + public List listByTemplateStatus(long templateId, + VMTemplateStoragePoolVO.Status downloadState) { + SearchCriteria sc = TemplateStatusSearch.create(); + sc.setParameters("template_id", templateId); + sc.setParameters("download_state", downloadState.toString()); + return listIncludingRemovedBy(sc); + } - @Override - public List listByTemplateStatus(long templateId, VMTemplateStoragePoolVO.Status downloadState, long poolId) { + @Override + public List listByTemplateStatus(long templateId, + VMTemplateStoragePoolVO.Status downloadState, long poolId) { SearchCriteria sc = TemplatePoolStatusSearch.create(); sc.setParameters("pool_id", poolId); sc.setParameters("template_id", templateId); @@ -148,130 +147,133 @@ public class VMTemplatePoolDaoImpl extends GenericDaoBase listByTemplateStatus(long templateId, long datacenterId, VMTemplateStoragePoolVO.Status downloadState) { + @Override + public List listByTemplateStatus(long templateId, long datacenterId, + VMTemplateStoragePoolVO.Status downloadState) { Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = null; - List result = new ArrayList(); - try { - String sql = DOWNLOADS_STATE_DC; - pstmt = txn.prepareAutoCloseStatement(sql); - pstmt.setLong(1, datacenterId); - pstmt.setLong(2, templateId); - pstmt.setString(3, downloadState.toString()); - ResultSet rs = pstmt.executeQuery(); - while (rs.next()) { + PreparedStatement pstmt = null; + List result = new ArrayList(); + try { + String sql = DOWNLOADS_STATE_DC; + pstmt = txn.prepareAutoCloseStatement(sql); + pstmt.setLong(1, datacenterId); + pstmt.setLong(2, templateId); + pstmt.setString(3, downloadState.toString()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { result.add(toEntityBean(rs, false)); } - } catch (Exception e) { - s_logger.warn("Exception: ", e); - } - return result; + } catch (Exception e) { + s_logger.warn("Exception: ", e); + } + return result; - } - - @Override - public List listByTemplateStatus(long templateId, long datacenterId, long podId, VMTemplateStoragePoolVO.Status downloadState) { - Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = null; - List result = new ArrayList(); - ResultSet rs = null; - try { - String sql = DOWNLOADS_STATE_DC_POD; - pstmt = txn.prepareStatement(sql); - - pstmt.setLong(1, datacenterId); - pstmt.setLong(2, podId); - pstmt.setLong(3, templateId); - pstmt.setString(4, downloadState.toString()); - rs = pstmt.executeQuery(); - while (rs.next()) { - // result.add(toEntityBean(rs, false)); TODO: this is buggy in GenericDaoBase for hand constructed queries - long id = rs.getLong(1); //ID column - result.add(findById(id)); - } - } catch (Exception e) { - s_logger.warn("Exception: ", e); - } finally { - try { - if (rs != null) { - rs.close(); - } - if (pstmt != null) { - pstmt.close(); - } - } catch (SQLException e) { - } - } - return result; - - } - - public List listByHostTemplate(long hostId, long templateId) { - Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = null; - List result = new ArrayList(); - ResultSet rs = null; - try { - String sql = HOST_TEMPLATE_SEARCH; - pstmt = txn.prepareStatement(sql); - - pstmt.setLong(1, hostId); - pstmt.setLong(2, templateId); - rs = pstmt.executeQuery(); - while (rs.next()) { - // result.add(toEntityBean(rs, false)); TODO: this is buggy in GenericDaoBase for hand constructed queries - long id = rs.getLong(1); //ID column - result.add(findById(id)); - } - } catch (Exception e) { - s_logger.warn("Exception: ", e); - } finally { - try { - if (rs != null) { - rs.close(); - } - if (pstmt != null) { - pstmt.close(); - } - } catch (SQLException e) { - } - } - return result; - - } - - @Override - public boolean templateAvailable(long templateId, long hostId) { - VMTemplateStorageResourceAssoc tmpltPool = findByPoolTemplate(hostId, templateId); - if (tmpltPool == null) - return false; - - return tmpltPool.getDownloadState()==Status.DOWNLOADED; - } - - @Override - public List listByTemplateStates(long templateId, VMTemplateStoragePoolVO.Status... states) { - SearchCriteria sc = TemplateStatesSearch.create(); - sc.setParameters("states", (Object[])states); - sc.setParameters("template_id", templateId); - - return search(sc, null); - } - - @Override - public VMTemplateStoragePoolVO findByHostTemplate(Long hostId, Long templateId) { - List result = listByHostTemplate(hostId, templateId); - return (result.size() == 0)?null:result.get(1); - } + } @Override - public boolean updateState(State currentState, Event event, - State nextState, DataObjectInStore vo, Object data) { - VMTemplateStoragePoolVO templatePool = (VMTemplateStoragePoolVO)vo; + public List listByTemplateStatus(long templateId, long datacenterId, long podId, + VMTemplateStoragePoolVO.Status downloadState) { + Transaction txn = Transaction.currentTxn(); + PreparedStatement pstmt = null; + List result = new ArrayList(); + ResultSet rs = null; + try { + String sql = DOWNLOADS_STATE_DC_POD; + pstmt = txn.prepareStatement(sql); + + pstmt.setLong(1, datacenterId); + pstmt.setLong(2, podId); + pstmt.setLong(3, templateId); + pstmt.setString(4, downloadState.toString()); + rs = pstmt.executeQuery(); + while (rs.next()) { + // result.add(toEntityBean(rs, false)); TODO: this is buggy in + // GenericDaoBase for hand constructed queries + long id = rs.getLong(1); // ID column + result.add(findById(id)); + } + } catch (Exception e) { + s_logger.warn("Exception: ", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + return result; + + } + + public List listByHostTemplate(long hostId, long templateId) { + Transaction txn = Transaction.currentTxn(); + PreparedStatement pstmt = null; + List result = new ArrayList(); + ResultSet rs = null; + try { + String sql = HOST_TEMPLATE_SEARCH; + pstmt = txn.prepareStatement(sql); + + pstmt.setLong(1, hostId); + pstmt.setLong(2, templateId); + rs = pstmt.executeQuery(); + while (rs.next()) { + // result.add(toEntityBean(rs, false)); TODO: this is buggy in + // GenericDaoBase for hand constructed queries + long id = rs.getLong(1); // ID column + result.add(findById(id)); + } + } catch (Exception e) { + s_logger.warn("Exception: ", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + return result; + + } + + @Override + public boolean templateAvailable(long templateId, long hostId) { + VMTemplateStorageResourceAssoc tmpltPool = findByPoolTemplate(hostId, templateId); + if (tmpltPool == null) + return false; + + return tmpltPool.getDownloadState() == Status.DOWNLOADED; + } + + @Override + public List listByTemplateStates(long templateId, VMTemplateStoragePoolVO.Status... states) { + SearchCriteria sc = TemplateStatesSearch.create(); + sc.setParameters("states", (Object[]) states); + sc.setParameters("template_id", templateId); + + return search(sc, null); + } + + @Override + public VMTemplateStoragePoolVO findByHostTemplate(Long hostId, Long templateId) { + List result = listByHostTemplate(hostId, templateId); + return (result.size() == 0) ? null : result.get(1); + } + + @Override + public boolean updateState(State currentState, Event event, State nextState, DataObjectInStore vo, Object data) { + VMTemplateStoragePoolVO templatePool = (VMTemplateStoragePoolVO) vo; Long oldUpdated = templatePool.getUpdatedCount(); Date oldUpdatedTime = templatePool.getUpdated(); - + SearchCriteria sc = updateStateSearch.create(); sc.setParameters("id", templatePool.getId()); sc.setParameters("state", currentState); @@ -288,14 +290,19 @@ public class VMTemplatePoolDaoImpl extends GenericDaoBase 0; diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateS3DaoImpl.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateS3DaoImpl.java index 7cfd3b5937c..d49645d944a 100644 --- a/engine/schema/src/com/cloud/storage/dao/VMTemplateS3DaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateS3DaoImpl.java @@ -34,8 +34,7 @@ import java.util.List; @Component @Local(VMTemplateS3Dao.class) -public class VMTemplateS3DaoImpl extends GenericDaoBase - implements VMTemplateS3Dao { +public class VMTemplateS3DaoImpl extends GenericDaoBase implements VMTemplateS3Dao { private final SearchBuilder searchBuilder; @@ -44,19 +43,15 @@ public class VMTemplateS3DaoImpl extends GenericDaoBase super(); this.searchBuilder = createSearchBuilder(); - this.searchBuilder - .and(S3_ID_COLUMN_NAME, this.searchBuilder.entity().getS3Id(), - EQ) - .and(TEMPLATE_ID_COLUMN_NAME, - this.searchBuilder.entity().getTemplateId(), EQ).done(); + this.searchBuilder.and(S3_ID_COLUMN_NAME, this.searchBuilder.entity().getS3Id(), EQ) + .and(TEMPLATE_ID_COLUMN_NAME, this.searchBuilder.entity().getTemplateId(), EQ).done(); } @Override public List listByS3Id(final long s3id) { - final SearchCriteria criteria = this.searchBuilder - .create(); + final SearchCriteria criteria = this.searchBuilder.create(); criteria.setParameters(S3_ID_COLUMN_NAME, s3id); @@ -67,8 +62,7 @@ public class VMTemplateS3DaoImpl extends GenericDaoBase @Override public VMTemplateS3VO findOneByTemplateId(final long templateId) { - final SearchCriteria criteria = this.searchBuilder - .create(); + final SearchCriteria criteria = this.searchBuilder.create(); criteria.setParameters(TEMPLATE_ID_COLUMN_NAME, templateId); @@ -77,11 +71,9 @@ public class VMTemplateS3DaoImpl extends GenericDaoBase } @Override - public VMTemplateS3VO findOneByS3Template(final long s3Id, - final long templateId) { + public VMTemplateS3VO findOneByS3Template(final long s3Id, final long templateId) { - final SearchCriteria criteria = this.searchBuilder - .create(); + final SearchCriteria criteria = this.searchBuilder.create(); criteria.setParameters(S3_ID_COLUMN_NAME, s3Id); criteria.setParameters(TEMPLATE_ID_COLUMN_NAME, templateId); @@ -93,8 +85,7 @@ public class VMTemplateS3DaoImpl extends GenericDaoBase @Override public void expungeAllByTemplateId(long templateId) { - final SearchCriteria criteria = this.searchBuilder - .create(); + final SearchCriteria criteria = this.searchBuilder.create(); criteria.setParameters(TEMPLATE_ID_COLUMN_NAME, templateId); diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateZoneDao.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateZoneDao.java index bb3aa010116..67f7c3f64d7 100755 --- a/engine/schema/src/com/cloud/storage/dao/VMTemplateZoneDao.java +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateZoneDao.java @@ -22,12 +22,14 @@ import com.cloud.storage.VMTemplateZoneVO; import com.cloud.utils.db.GenericDao; public interface VMTemplateZoneDao extends GenericDao { - public List listByZoneId(long id); - - public List listByTemplateId(long templateId); - - public VMTemplateZoneVO findByZoneTemplate(long zoneId, long templateId); - + public List listByZoneId(long id); + + public List listByTemplateId(long templateId); + + public VMTemplateZoneVO findByZoneTemplate(long zoneId, long templateId); + public List listByZoneTemplate(Long zoneId, long templateId); + public void deletePrimaryRecordsForTemplate(long templateId); + } diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateZoneDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateZoneDaoImpl.java index 916e0aceb2c..c4a4dc7230a 100644 --- a/engine/schema/src/com/cloud/storage/dao/VMTemplateZoneDaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateZoneDaoImpl.java @@ -27,63 +27,73 @@ import com.cloud.storage.VMTemplateZoneVO; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.Transaction; @Component -@Local(value={VMTemplateZoneDao.class}) +@Local(value = { VMTemplateZoneDao.class }) public class VMTemplateZoneDaoImpl extends GenericDaoBase implements VMTemplateZoneDao { - public static final Logger s_logger = Logger.getLogger(VMTemplateZoneDaoImpl.class.getName()); - - protected final SearchBuilder ZoneSearch; - protected final SearchBuilder TemplateSearch; - protected final SearchBuilder ZoneTemplateSearch; - - - public VMTemplateZoneDaoImpl () { - ZoneSearch = createSearchBuilder(); - ZoneSearch.and("zone_id", ZoneSearch.entity().getZoneId(), SearchCriteria.Op.EQ); - ZoneSearch.done(); - - TemplateSearch = createSearchBuilder(); - TemplateSearch.and("template_id", TemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); - TemplateSearch.done(); - - ZoneTemplateSearch = createSearchBuilder(); - ZoneTemplateSearch.and("zone_id", ZoneTemplateSearch.entity().getZoneId(), SearchCriteria.Op.EQ); - ZoneTemplateSearch.and("template_id", ZoneTemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); - ZoneTemplateSearch.done(); - } - + public static final Logger s_logger = Logger.getLogger(VMTemplateZoneDaoImpl.class.getName()); - @Override - public List listByZoneId(long id) { - SearchCriteria sc = ZoneSearch.create(); - sc.setParameters("zone_id", id); - return listIncludingRemovedBy(sc); - } + protected final SearchBuilder ZoneSearch; + protected final SearchBuilder TemplateSearch; + protected final SearchBuilder ZoneTemplateSearch; - @Override - public List listByTemplateId(long templateId) { - SearchCriteria sc = TemplateSearch.create(); - sc.setParameters("template_id", templateId); - return listIncludingRemovedBy(sc); - } + public VMTemplateZoneDaoImpl() { + ZoneSearch = createSearchBuilder(); + ZoneSearch.and("zone_id", ZoneSearch.entity().getZoneId(), SearchCriteria.Op.EQ); + ZoneSearch.done(); - @Override - public VMTemplateZoneVO findByZoneTemplate(long zoneId, long templateId) { - SearchCriteria sc = ZoneTemplateSearch.create(); - sc.setParameters("zone_id", zoneId); - sc.setParameters("template_id", templateId); - return findOneIncludingRemovedBy(sc); - } + TemplateSearch = createSearchBuilder(); + TemplateSearch.and("template_id", TemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + TemplateSearch.done(); - @Override + ZoneTemplateSearch = createSearchBuilder(); + ZoneTemplateSearch.and("zone_id", ZoneTemplateSearch.entity().getZoneId(), SearchCriteria.Op.EQ); + ZoneTemplateSearch.and("template_id", ZoneTemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + ZoneTemplateSearch.done(); + } + + @Override + public List listByZoneId(long id) { + SearchCriteria sc = ZoneSearch.create(); + sc.setParameters("zone_id", id); + return listIncludingRemovedBy(sc); + } + + @Override + public List listByTemplateId(long templateId) { + SearchCriteria sc = TemplateSearch.create(); + sc.setParameters("template_id", templateId); + return listIncludingRemovedBy(sc); + } + + @Override + public VMTemplateZoneVO findByZoneTemplate(long zoneId, long templateId) { + SearchCriteria sc = ZoneTemplateSearch.create(); + sc.setParameters("zone_id", zoneId); + sc.setParameters("template_id", templateId); + return findOneIncludingRemovedBy(sc); + } + + @Override public List listByZoneTemplate(Long zoneId, long templateId) { - SearchCriteria sc = ZoneTemplateSearch.create(); + SearchCriteria sc = ZoneTemplateSearch.create(); if (zoneId != null) { sc.setParameters("zone_id", zoneId); } - sc.setParameters("template_id", templateId); - return listBy(sc); - } + sc.setParameters("template_id", templateId); + return listBy(sc); + } + + @Override + public void deletePrimaryRecordsForTemplate(long templateId) { + SearchCriteria sc = TemplateSearch.create(); + sc.setParameters("template_id", templateId); + Transaction txn = Transaction.currentTxn(); + txn.start(); + remove(sc); + txn.commit(); + + } } diff --git a/engine/schema/src/com/cloud/storage/dao/VolumeDao.java b/engine/schema/src/com/cloud/storage/dao/VolumeDao.java index 251318108d8..79c0dc37786 100755 --- a/engine/schema/src/com/cloud/storage/dao/VolumeDao.java +++ b/engine/schema/src/com/cloud/storage/dao/VolumeDao.java @@ -62,7 +62,7 @@ public interface VolumeDao extends GenericDao, StateDao findUsableVolumesForInstance(long instanceId); - Long countAllocatedVolumesForAccount(long accountId); + Long countAllocatedVolumesForAccount(long accountId); HypervisorType getHypervisorType(long volumeId); @@ -76,15 +76,16 @@ public interface VolumeDao extends GenericDao, StateDao implements VolumeDao { private static final Logger s_logger = Logger.getLogger(VolumeDaoImpl.class); protected final SearchBuilder DetachedAccountIdSearch; @@ -63,23 +63,23 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol protected GenericSearchBuilder CountByAccount; protected GenericSearchBuilder primaryStorageSearch; protected GenericSearchBuilder secondaryStorageSearch; - @Inject ResourceTagDao _tagsDao; + @Inject + ResourceTagDao _tagsDao; protected static final String SELECT_VM_SQL = "SELECT DISTINCT instance_id from volumes v where v.host_id = ? and v.mirror_state = ?"; protected static final String SELECT_HYPERTYPE_FROM_VOLUME = "SELECT c.hypervisor_type from volumes v, storage_pool s, cluster c where v.pool_id = s.id and s.cluster_id = c.id and v.id = ?"; - private static final String ORDER_POOLS_NUMBER_OF_VOLUMES_FOR_ACCOUNT = "SELECT pool.id, SUM(IF(vol.state='Ready' AND vol.account_id = ?, 1, 0)) FROM `cloud`.`storage_pool` pool LEFT JOIN `cloud`.`volumes` vol ON pool.id = vol.pool_id WHERE pool.data_center_id = ? " + - " AND pool.pod_id = ? AND pool.cluster_id = ? " + - " GROUP BY pool.id ORDER BY 2 ASC "; - + private static final String ORDER_POOLS_NUMBER_OF_VOLUMES_FOR_ACCOUNT = "SELECT pool.id, SUM(IF(vol.state='Ready' AND vol.account_id = ?, 1, 0)) FROM `cloud`.`storage_pool` pool LEFT JOIN `cloud`.`volumes` vol ON pool.id = vol.pool_id WHERE pool.data_center_id = ? " + + " AND pool.pod_id = ? AND pool.cluster_id = ? " + " GROUP BY pool.id ORDER BY 2 ASC "; + @Override public List findDetachedByAccount(long accountId) { - SearchCriteria sc = DetachedAccountIdSearch.create(); - sc.setParameters("accountId", accountId); - sc.setParameters("destroyed", Volume.State.Destroy); - return listBy(sc); + SearchCriteria sc = DetachedAccountIdSearch.create(); + sc.setParameters("accountId", accountId); + sc.setParameters("destroyed", Volume.State.Destroy); + return listBy(sc); } - + @Override public List findByAccount(long accountId) { SearchCriteria sc = AllFieldsSearch.create(); @@ -87,172 +87,172 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol sc.setParameters("state", Volume.State.Ready); return listBy(sc); } - + @Override public List findByInstance(long id) { SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("instanceId", id); - return listBy(sc); - } - - @Override - public List findByInstanceAndDeviceId(long instanceId, long deviceId){ - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("instanceId", instanceId); - sc.setParameters("deviceId", deviceId); - return listBy(sc); + return listBy(sc); } - + + @Override + public List findByInstanceAndDeviceId(long instanceId, long deviceId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("instanceId", instanceId); + sc.setParameters("deviceId", deviceId); + return listBy(sc); + } + @Override public List findByPoolId(long poolId) { SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("poolId", poolId); sc.setParameters("notDestroyed", Volume.State.Destroy); sc.setParameters("vType", Volume.Type.ROOT.toString()); - return listBy(sc); - } - - @Override + return listBy(sc); + } + + @Override public List findCreatedByInstance(long id) { SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("instanceId", id); sc.setParameters("state", Volume.State.Ready); return listBy(sc); } - + @Override public List findUsableVolumesForInstance(long instanceId) { SearchCriteria sc = InstanceStatesSearch.create(); sc.setParameters("instance", instanceId); sc.setParameters("states", Volume.State.Creating, Volume.State.Ready, Volume.State.Allocated); - + return listBy(sc); } - - @Override - public List findByInstanceAndType(long id, Type vType) { + + @Override + public List findByInstanceAndType(long id, Type vType) { SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("instanceId", id); sc.setParameters("vType", vType.toString()); - return listBy(sc); - } - - @Override - public List findByInstanceIdDestroyed(long vmId) { - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("instanceId", vmId); - sc.setParameters("destroyed", Volume.State.Destroy); - return listBy(sc); - } - - @Override - public List findReadyRootVolumesByInstance(long instanceId) { - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("instanceId", instanceId); - sc.setParameters("state", Volume.State.Ready); - sc.setParameters("vType", Volume.Type.ROOT); - return listBy(sc); - } - - @Override - public List findByAccountAndPod(long accountId, long podId) { - SearchCriteria sc = AllFieldsSearch.create(); + return listBy(sc); + } + + @Override + public List findByInstanceIdDestroyed(long vmId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("instanceId", vmId); + sc.setParameters("destroyed", Volume.State.Destroy); + return listBy(sc); + } + + @Override + public List findReadyRootVolumesByInstance(long instanceId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("instanceId", instanceId); + sc.setParameters("state", Volume.State.Ready); + sc.setParameters("vType", Volume.Type.ROOT); + return listBy(sc); + } + + @Override + public List findByAccountAndPod(long accountId, long podId) { + SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("accountId", accountId); sc.setParameters("pod", podId); sc.setParameters("state", Volume.State.Ready); - - return listIncludingRemovedBy(sc); - } - - @Override - public List findByTemplateAndZone(long templateId, long zoneId) { - SearchCriteria sc = TemplateZoneSearch.create(); - sc.setParameters("template", templateId); - sc.setParameters("zone", zoneId); - - return listIncludingRemovedBy(sc); - } - @Override - public boolean isAnyVolumeActivelyUsingTemplateOnPool(long templateId, long poolId) { - SearchCriteria sc = ActiveTemplateSearch.create(); - sc.setParameters("template", templateId); - sc.setParameters("pool", poolId); - - List results = customSearchIncludingRemoved(sc, null); - assert results.size() > 0 : "How can this return a size of " + results.size(); - - return results.get(0) > 0; - } - + return listIncludingRemovedBy(sc); + } + + @Override + public List findByTemplateAndZone(long templateId, long zoneId) { + SearchCriteria sc = TemplateZoneSearch.create(); + sc.setParameters("template", templateId); + sc.setParameters("zone", zoneId); + + return listIncludingRemovedBy(sc); + } + + @Override + public boolean isAnyVolumeActivelyUsingTemplateOnPool(long templateId, long poolId) { + SearchCriteria sc = ActiveTemplateSearch.create(); + sc.setParameters("template", templateId); + sc.setParameters("pool", poolId); + + List results = customSearchIncludingRemoved(sc, null); + assert results.size() > 0 : "How can this return a size of " + results.size(); + + return results.get(0) > 0; + } + @Override public void deleteVolumesByInstance(long instanceId) { SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("instanceId", instanceId); expunge(sc); } - + @Override public void attachVolume(long volumeId, long vmId, long deviceId) { - VolumeVO volume = createForUpdate(volumeId); - volume.setInstanceId(vmId); - volume.setDeviceId(deviceId); - volume.setUpdated(new Date()); - volume.setAttached(new Date()); - update(volumeId, volume); + VolumeVO volume = createForUpdate(volumeId); + volume.setInstanceId(vmId); + volume.setDeviceId(deviceId); + volume.setUpdated(new Date()); + volume.setAttached(new Date()); + update(volumeId, volume); } - + @Override public void detachVolume(long volumeId) { - VolumeVO volume = createForUpdate(volumeId); - volume.setInstanceId(null); + VolumeVO volume = createForUpdate(volumeId); + volume.setInstanceId(null); volume.setDeviceId(null); - volume.setUpdated(new Date()); - volume.setAttached(null); - update(volumeId, volume); + volume.setUpdated(new Date()); + volume.setAttached(null); + update(volumeId, volume); } - + @Override @DB - public HypervisorType getHypervisorType(long volumeId) { - /*lookup from cluster of pool*/ - Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = null; + public HypervisorType getHypervisorType(long volumeId) { + /* lookup from cluster of pool */ + Transaction txn = Transaction.currentTxn(); + PreparedStatement pstmt = null; - try { - String sql = SELECT_HYPERTYPE_FROM_VOLUME; - pstmt = txn.prepareAutoCloseStatement(sql); - pstmt.setLong(1, volumeId); - ResultSet rs = pstmt.executeQuery(); - if (rs.next()) { + try { + String sql = SELECT_HYPERTYPE_FROM_VOLUME; + pstmt = txn.prepareAutoCloseStatement(sql); + pstmt.setLong(1, volumeId); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) { return HypervisorType.getType(rs.getString(1)); } - return HypervisorType.None; - } catch (SQLException e) { - throw new CloudRuntimeException("DB Exception on: " + SELECT_HYPERTYPE_FROM_VOLUME, e); - } catch (Throwable e) { - throw new CloudRuntimeException("Caught: " + SELECT_HYPERTYPE_FROM_VOLUME, e); - } - } - + return HypervisorType.None; + } catch (SQLException e) { + throw new CloudRuntimeException("DB Exception on: " + SELECT_HYPERTYPE_FROM_VOLUME, e); + } catch (Throwable e) { + throw new CloudRuntimeException("Caught: " + SELECT_HYPERTYPE_FROM_VOLUME, e); + } + } + @Override public ImageFormat getImageFormat(Long volumeId) { HypervisorType type = getHypervisorType(volumeId); - if ( type.equals(HypervisorType.KVM)) { + if (type.equals(HypervisorType.KVM)) { return ImageFormat.QCOW2; - } else if ( type.equals(HypervisorType.XenServer)) { + } else if (type.equals(HypervisorType.XenServer)) { return ImageFormat.VHD; - } else if ( type.equals(HypervisorType.VMware)) { + } else if (type.equals(HypervisorType.VMware)) { return ImageFormat.OVA; } else { s_logger.warn("Do not support hypervisor " + type.toString()); return null; } } - - public VolumeDaoImpl() { - AllFieldsSearch = createSearchBuilder(); - AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), Op.EQ); + + public VolumeDaoImpl() { + AllFieldsSearch = createSearchBuilder(); + AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), Op.EQ); AllFieldsSearch.and("accountId", AllFieldsSearch.entity().getAccountId(), Op.EQ); AllFieldsSearch.and("pod", AllFieldsSearch.entity().getPodId(), Op.EQ); AllFieldsSearch.and("instanceId", AllFieldsSearch.entity().getInstanceId(), Op.EQ); @@ -264,33 +264,33 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol AllFieldsSearch.and("notDestroyed", AllFieldsSearch.entity().getState(), Op.NEQ); AllFieldsSearch.and("updatedCount", AllFieldsSearch.entity().getUpdatedCount(), Op.EQ); AllFieldsSearch.done(); - + DetachedAccountIdSearch = createSearchBuilder(); DetachedAccountIdSearch.and("accountId", DetachedAccountIdSearch.entity().getAccountId(), Op.EQ); DetachedAccountIdSearch.and("destroyed", DetachedAccountIdSearch.entity().getState(), Op.NEQ); DetachedAccountIdSearch.and("instanceId", DetachedAccountIdSearch.entity().getInstanceId(), Op.NULL); DetachedAccountIdSearch.done(); - + TemplateZoneSearch = createSearchBuilder(); TemplateZoneSearch.and("template", TemplateZoneSearch.entity().getTemplateId(), Op.EQ); TemplateZoneSearch.and("zone", TemplateZoneSearch.entity().getDataCenterId(), Op.EQ); TemplateZoneSearch.done(); - + TotalSizeByPoolSearch = createSearchBuilder(SumCount.class); TotalSizeByPoolSearch.select("sum", Func.SUM, TotalSizeByPoolSearch.entity().getSize()); - TotalSizeByPoolSearch.select("count", Func.COUNT, (Object[])null); + TotalSizeByPoolSearch.select("count", Func.COUNT, (Object[]) null); TotalSizeByPoolSearch.and("poolId", TotalSizeByPoolSearch.entity().getPoolId(), Op.EQ); TotalSizeByPoolSearch.and("removed", TotalSizeByPoolSearch.entity().getRemoved(), Op.NULL); TotalSizeByPoolSearch.and("state", TotalSizeByPoolSearch.entity().getState(), Op.NEQ); TotalSizeByPoolSearch.done(); - + ActiveTemplateSearch = createSearchBuilder(Long.class); ActiveTemplateSearch.and("pool", ActiveTemplateSearch.entity().getPoolId(), Op.EQ); ActiveTemplateSearch.and("template", ActiveTemplateSearch.entity().getTemplateId(), Op.EQ); ActiveTemplateSearch.and("removed", ActiveTemplateSearch.entity().getRemoved(), Op.NULL); ActiveTemplateSearch.select(null, Func.COUNT, null); ActiveTemplateSearch.done(); - + InstanceStatesSearch = createSearchBuilder(); InstanceStatesSearch.and("instance", InstanceStatesSearch.entity().getInstanceId(), Op.EQ); InstanceStatesSearch.and("states", InstanceStatesSearch.entity().getState(), Op.IN); @@ -315,24 +315,25 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol secondaryStorageSearch.and("path", secondaryStorageSearch.entity().getPath(), Op.NULL); secondaryStorageSearch.and("isRemoved", secondaryStorageSearch.entity().getRemoved(), Op.NULL); secondaryStorageSearch.done(); - } + } - @Override @DB(txn=false) - public Pair getCountAndTotalByPool(long poolId) { + @Override + @DB(txn = false) + public Pair getCountAndTotalByPool(long poolId) { SearchCriteria sc = TotalSizeByPoolSearch.create(); sc.setParameters("poolId", poolId); List results = customSearch(sc, null); SumCount sumCount = results.get(0); return new Pair(sumCount.count, sumCount.sum); - } + } @Override - public Long countAllocatedVolumesForAccount(long accountId) { - SearchCriteria sc = CountByAccount.create(); + public Long countAllocatedVolumesForAccount(long accountId) { + SearchCriteria sc = CountByAccount.create(); sc.setParameters("account", accountId); - sc.setParameters("state", Volume.State.Destroy); + sc.setParameters("state", Volume.State.Destroy); return customSearch(sc, null).get(0); - } + } @Override public long primaryStorageUsedForAccount(long accountId) { @@ -358,55 +359,61 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol } } + public static class SumCount { + public long sum; + public long count; - public static class SumCount { - public long sum; - public long count; - public SumCount() { - } - } + public SumCount() { + } + } @Override public List listVolumesToBeDestroyed() { SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("state", Volume.State.Destroy); - + return listBy(sc); } - @Override - public boolean updateState(com.cloud.storage.Volume.State currentState, - Event event, com.cloud.storage.Volume.State nextState, Volume vo, - Object data) { - - Long oldUpdated = vo.getUpdatedCount(); - Date oldUpdatedTime = vo.getUpdated(); - - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("id", vo.getId()); - sc.setParameters("state", currentState); - sc.setParameters("updatedCount", vo.getUpdatedCount()); - - vo.incrUpdatedCount(); - - UpdateBuilder builder = getUpdateBuilder(vo); - builder.set(vo, "state", nextState); - builder.set(vo, "updated", new Date()); - - int rows = update((VolumeVO)vo, sc); - if (rows == 0 && s_logger.isDebugEnabled()) { - VolumeVO dbVol = findByIdIncludingRemoved(vo.getId()); - if (dbVol != null) { - StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); - str.append(": DB Data={id=").append(dbVol.getId()).append("; state=").append(dbVol.getState()).append("; updatecount=").append(dbVol.getUpdatedCount()).append(";updatedTime=").append(dbVol.getUpdated()); - str.append(": New Data={id=").append(vo.getId()).append("; state=").append(nextState).append("; event=").append(event).append("; updatecount=").append(vo.getUpdatedCount()).append("; updatedTime=").append(vo.getUpdated()); - str.append(": stale Data={id=").append(vo.getId()).append("; state=").append(currentState).append("; event=").append(event).append("; updatecount=").append(oldUpdated).append("; updatedTime=").append(oldUpdatedTime); - } else { - s_logger.debug("Unable to update volume: id=" + vo.getId() + ", as there is no such volume exists in the database anymore"); - } - } - return rows > 0; - } + @Override + public boolean updateState(com.cloud.storage.Volume.State currentState, Event event, + com.cloud.storage.Volume.State nextState, Volume vo, Object data) { + + Long oldUpdated = vo.getUpdatedCount(); + Date oldUpdatedTime = vo.getUpdated(); + + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("id", vo.getId()); + sc.setParameters("state", currentState); + sc.setParameters("updatedCount", vo.getUpdatedCount()); + + vo.incrUpdatedCount(); + + UpdateBuilder builder = getUpdateBuilder(vo); + builder.set(vo, "state", nextState); + builder.set(vo, "updated", new Date()); + + int rows = update((VolumeVO) vo, sc); + if (rows == 0 && s_logger.isDebugEnabled()) { + VolumeVO dbVol = findByIdIncludingRemoved(vo.getId()); + if (dbVol != null) { + StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); + str.append(": DB Data={id=").append(dbVol.getId()).append("; state=").append(dbVol.getState()) + .append("; updatecount=").append(dbVol.getUpdatedCount()).append(";updatedTime=") + .append(dbVol.getUpdated()); + str.append(": New Data={id=").append(vo.getId()).append("; state=").append(nextState) + .append("; event=").append(event).append("; updatecount=").append(vo.getUpdatedCount()) + .append("; updatedTime=").append(vo.getUpdated()); + str.append(": stale Data={id=").append(vo.getId()).append("; state=").append(currentState) + .append("; event=").append(event).append("; updatecount=").append(oldUpdated) + .append("; updatedTime=").append(oldUpdatedTime); + } else { + s_logger.debug("Unable to update volume: id=" + vo.getId() + + ", as there is no such volume exists in the database anymore"); + } + } + return rows > 0; + } @Override public List listPoolIdsByVolumeCount(long dcId, Long podId, Long clusterId, long accountId) { @@ -420,7 +427,7 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol pstmt.setLong(2, dcId); pstmt.setLong(3, podId); pstmt.setLong(4, clusterId); - + ResultSet rs = pstmt.executeQuery(); while (rs.next()) { result.add(rs.getLong(1)); @@ -432,8 +439,9 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol throw new CloudRuntimeException("Caught: " + ORDER_POOLS_NUMBER_OF_VOLUMES_FOR_ACCOUNT, e); } } - - @Override @DB(txn=false) + + @Override + @DB(txn = false) public Pair getNonDestroyedCountAndTotalByPool(long poolId) { SearchCriteria sc = TotalSizeByPoolSearch.create(); sc.setParameters("poolId", poolId); @@ -442,7 +450,7 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol SumCount sumCount = results.get(0); return new Pair(sumCount.count, sumCount.sum); } - + @Override @DB public boolean remove(Long id) { diff --git a/engine/schema/src/com/cloud/storage/dao/VolumeHostDao.java b/engine/schema/src/com/cloud/storage/dao/VolumeHostDao.java index 39dda12345b..ccb276b47f9 100755 --- a/engine/schema/src/com/cloud/storage/dao/VolumeHostDao.java +++ b/engine/schema/src/com/cloud/storage/dao/VolumeHostDao.java @@ -25,16 +25,17 @@ import com.cloud.storage.VolumeHostVO; import com.cloud.utils.db.GenericDao; import com.cloud.utils.fsm.StateDao; -public interface VolumeHostDao extends GenericDao, StateDao{ +public interface VolumeHostDao extends GenericDao, + StateDao { - VolumeHostVO findByHostVolume(long hostId, long volumeId); + VolumeHostVO findByHostVolume(long hostId, long volumeId); - VolumeHostVO findByVolumeId(long volumeId); + VolumeHostVO findByVolumeId(long volumeId); - List listBySecStorage(long sserverId); + List listBySecStorage(long sserverId); - List listDestroyed(long hostId); + List listDestroyed(long hostId); - VolumeHostVO findVolumeByZone(long zoneId, long volumeId); + VolumeHostVO findVolumeByZone(long zoneId, long volumeId); } diff --git a/engine/schema/src/com/cloud/storage/dao/VolumeHostDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/VolumeHostDaoImpl.java index 2fd39e6eeca..b731ebbeb4e 100755 --- a/engine/schema/src/com/cloud/storage/dao/VolumeHostDaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/VolumeHostDaoImpl.java @@ -35,7 +35,7 @@ import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.UpdateBuilder; @Component -@Local(value={VolumeHostDao.class}) +@Local(value = { VolumeHostDao.class }) public class VolumeHostDaoImpl extends GenericDaoBase implements VolumeHostDao { private static final Logger s_logger = Logger.getLogger(VolumeHostDaoImpl.class); protected final SearchBuilder HostVolumeSearch; @@ -44,7 +44,8 @@ public class VolumeHostDaoImpl extends GenericDaoBase implem protected final SearchBuilder HostSearch; protected final SearchBuilder HostDestroyedSearch; protected final SearchBuilder updateStateSearch; - public VolumeHostDaoImpl(){ + + public VolumeHostDaoImpl() { HostVolumeSearch = createSearchBuilder(); HostVolumeSearch.and("host_id", HostVolumeSearch.entity().getHostId(), SearchCriteria.Op.EQ); HostVolumeSearch.and("volume_id", HostVolumeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); @@ -58,7 +59,7 @@ public class VolumeHostDaoImpl extends GenericDaoBase implem ZoneVolumeSearch.done(); HostSearch = createSearchBuilder(); - HostSearch.and("host_id", HostSearch.entity().getHostId(), SearchCriteria.Op.EQ); + HostSearch.and("host_id", HostSearch.entity().getHostId(), SearchCriteria.Op.EQ); HostSearch.and("destroyed", HostSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); HostSearch.done(); @@ -70,8 +71,8 @@ public class VolumeHostDaoImpl extends GenericDaoBase implem HostDestroyedSearch = createSearchBuilder(); HostDestroyedSearch.and("host_id", HostDestroyedSearch.entity().getHostId(), SearchCriteria.Op.EQ); HostDestroyedSearch.and("destroyed", HostDestroyedSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); - HostDestroyedSearch.done(); - + HostDestroyedSearch.done(); + updateStateSearch = this.createSearchBuilder(); updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ); updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ); @@ -79,8 +80,6 @@ public class VolumeHostDaoImpl extends GenericDaoBase implem updateStateSearch.done(); } - - @Override public VolumeHostVO findByHostVolume(long hostId, long volumeId) { SearchCriteria sc = HostVolumeSearch.create(); @@ -88,7 +87,7 @@ public class VolumeHostDaoImpl extends GenericDaoBase implem sc.setParameters("volume_id", volumeId); sc.setParameters("destroyed", false); return findOneIncludingRemovedBy(sc); - } + } @Override public VolumeHostVO findVolumeByZone(long volumeId, long zoneId) { @@ -107,8 +106,6 @@ public class VolumeHostDaoImpl extends GenericDaoBase implem return findOneBy(sc); } - - @Override public List listBySecStorage(long ssHostId) { SearchCriteria sc = HostSearch.create(); @@ -118,7 +115,7 @@ public class VolumeHostDaoImpl extends GenericDaoBase implem } @Override - public List listDestroyed(long hostId){ + public List listDestroyed(long hostId) { SearchCriteria sc = HostDestroyedSearch.create(); sc.setParameters("host_id", hostId); sc.setParameters("destroyed", true); @@ -126,13 +123,11 @@ public class VolumeHostDaoImpl extends GenericDaoBase implem } @Override - public boolean updateState(State currentState, Event event, - State nextState, DataObjectInStore vo, Object data) { + public boolean updateState(State currentState, Event event, State nextState, DataObjectInStore vo, Object data) { VolumeHostVO volHost = (VolumeHostVO) vo; Long oldUpdated = volHost.getUpdatedCount(); Date oldUpdatedTime = volHost.getUpdated(); - - + SearchCriteria sc = updateStateSearch.create(); sc.setParameters("id", volHost.getId()); sc.setParameters("state", currentState); @@ -149,14 +144,18 @@ public class VolumeHostDaoImpl extends GenericDaoBase implem VolumeHostVO dbVol = findByIdIncludingRemoved(volHost.getId()); if (dbVol != null) { StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); - str.append(": DB Data={id=").append(dbVol.getId()).append("; state=").append(dbVol.getState()).append("; updatecount=").append(dbVol.getUpdatedCount()).append(";updatedTime=") + str.append(": DB Data={id=").append(dbVol.getId()).append("; state=").append(dbVol.getState()) + .append("; updatecount=").append(dbVol.getUpdatedCount()).append(";updatedTime=") .append(dbVol.getUpdated()); - str.append(": New Data={id=").append(volHost.getId()).append("; state=").append(nextState).append("; event=").append(event).append("; updatecount=").append(volHost.getUpdatedCount()) + str.append(": New Data={id=").append(volHost.getId()).append("; state=").append(nextState) + .append("; event=").append(event).append("; updatecount=").append(volHost.getUpdatedCount()) .append("; updatedTime=").append(volHost.getUpdated()); - str.append(": stale Data={id=").append(volHost.getId()).append("; state=").append(currentState).append("; event=").append(event).append("; updatecount=").append(oldUpdated) + str.append(": stale Data={id=").append(volHost.getId()).append("; state=").append(currentState) + .append("; event=").append(event).append("; updatecount=").append(oldUpdated) .append("; updatedTime=").append(oldUpdatedTime); } else { - s_logger.debug("Unable to update objectIndatastore: id=" + volHost.getId() + ", as there is no such object exists in the database anymore"); + s_logger.debug("Unable to update objectIndatastore: id=" + volHost.getId() + + ", as there is no such object exists in the database anymore"); } } return rows > 0; diff --git a/engine/schema/src/com/cloud/upgrade/DatabaseCreator.java b/engine/schema/src/com/cloud/upgrade/DatabaseCreator.java index 9b1be6bc6b6..c97085b6e9e 100755 --- a/engine/schema/src/com/cloud/upgrade/DatabaseCreator.java +++ b/engine/schema/src/com/cloud/upgrade/DatabaseCreator.java @@ -147,6 +147,13 @@ public class DatabaseCreator { databases = arg.substring(arg.lastIndexOf("=") + 1, arg.length()).split(","); } else if (arg.endsWith(".sql")) { sqlFiles.add(arg); + } else if (arg.endsWith(".sql.override")) { + if (fileExists(arg)) { + int index = arg.lastIndexOf(".override"); + String fileToOverride = arg.substring(0, index); + sqlFiles.remove(fileToOverride); + sqlFiles.add(arg); + } } else if (arg.endsWith(".properties")) { if (!dbPropsFile.endsWith("properties.override") && fileExists(arg)) dbPropsFile = arg; diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java index 8378eec005f..8f63a6c9485 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java @@ -18,9 +18,11 @@ package com.cloud.upgrade.dao; import com.cloud.deploy.DeploymentPlanner; -import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.Script; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider; import org.apache.log4j.Logger; import java.io.File; import java.sql.Connection; @@ -30,13 +32,20 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.UUID; import com.cloud.network.vpc.NetworkACL; public class Upgrade410to420 implements DbUpgrade { final static Logger s_logger = Logger.getLogger(Upgrade410to420.class); +// private Map host_store_id_map = new HashMap(); +// private Map s3_store_id_map = new HashMap(); +// private Map swift_store_id_map = new HashMap(); + @Override public String[] getUpgradableVersionRange() { return new String[] { "4.1.0", "4.2.0" }; @@ -83,6 +92,12 @@ public class Upgrade410to420 implements DbUpgrade { removeFirewallServiceFromSharedNetworkOfferingWithSGService(conn); fix22xKVMSnapshots(conn); addIndexForAlert(conn); + // storage refactor related migration + // TODO: add clean-up scripts to delete the deprecated table. + migrateSecondaryStorageToImageStore(conn); + migrateVolumeHostRef(conn); + migrateTemplateHostRef(conn); + migrateSnapshotStoreRef(conn); } private void addIndexForAlert(Connection conn) { @@ -113,8 +128,8 @@ public class Upgrade410to420 implements DbUpgrade { } - private void updateSystemVmTemplates(Connection conn) { - + private void updateSystemVmTemplates(Connection conn) { + // TODO: system vm template migration after storage refactoring PreparedStatement pstmt = null; ResultSet rs = null; boolean xenserver = false; @@ -125,7 +140,7 @@ public class Upgrade410to420 implements DbUpgrade { s_logger.debug("Updating System Vm template IDs"); try{ //Get all hypervisors in use - try { + try { pstmt = conn.prepareStatement("select distinct(hypervisor_type) from `cloud`.`cluster` where removed is null"); rs = pstmt.executeQuery(); while(rs.next()){ @@ -313,6 +328,7 @@ public class Upgrade410to420 implements DbUpgrade { } catch (SQLException e) { } } + /* pstmt = null; try { pstmt = conn.prepareStatement("update vm_template set image_data_store_id = 1 where type = 'SYSTEM' or type = 'BUILTIN'"); @@ -327,6 +343,8 @@ public class Upgrade410to420 implements DbUpgrade { } } } + */ + } private void updatePrimaryStore(Connection conn) { @@ -1131,8 +1149,8 @@ public class Upgrade410to420 implements DbUpgrade { } } } - - + + private void updateNetworksForPrivateGateways(Connection conn) { PreparedStatement pstmt = null; @@ -1150,7 +1168,7 @@ public class Upgrade410to420 implements DbUpgrade { pstmt.setLong(1, vpcId); pstmt.setLong(2, networkId); pstmt.executeUpdate(); - + } } catch (SQLException e) { throw new CloudRuntimeException("Failed to update private networks with VPC id.", e); @@ -1585,4 +1603,298 @@ public class Upgrade410to420 implements DbUpgrade { s_logger.info("Successfully upgraded network using F5 and SRX devices to have a entry in the network_external_lb_device_map and network_external_firewall_device_map"); } } + + // migrate secondary storages (NFS, S3, Swift) from host, s3, swift tables to image_store table + private void migrateSecondaryStorageToImageStore(Connection conn) { + PreparedStatement storeInsert = null; + PreparedStatement storeDetailInsert = null; + PreparedStatement storeQuery = null; + PreparedStatement s3Query = null; + PreparedStatement swiftQuery = null; + PreparedStatement nfsQuery = null; + ResultSet rs = null; + ResultSet storeInfo = null; + Long storeId = null; + + + try { + storeQuery = conn.prepareStatement("select id from `cloud`.`image_store` where uuid = ?"); + storeDetailInsert = conn + .prepareStatement("INSERT INTO `cloud`.`image_store_details` (store_id, name, value) values(?, ?, ?)"); + + /* + // migrate S3 secondary storage + storeInsert = conn + .prepareStatement("INSERT INTO `cloud`.`image_store` (uuid, name, image_provider_name, protocol, scope, role, created) values(?, ?, 'S3', ?, 'REGION', 'Image', ?)"); + s3Query = conn + .prepareStatement("select id, uuid, access_key, secret_key, end_point, bucket, https, connection_timeout, max_error_retry, socket_timeout, created from `cloud`.`s3`"); + rs = s3Query.executeQuery(); + + while (rs.next()) { + Long s3_id = rs.getLong("id"); + String s3_uuid = rs.getString("uuid"); + String s3_accesskey = rs.getString("access_key"); + String s3_secretkey = rs.getString("secret_key"); + String s3_endpoint = rs.getString("end_point"); + String s3_bucket = rs.getString("bucket"); + boolean s3_https = rs.getObject("https") != null ? (rs.getInt("https") == 0 ? false : true) : false; + Integer s3_connectiontimeout = rs.getObject("connection_timeout") != null ? rs + .getInt("connection_timeout") : null; + Integer s3_retry = rs.getObject("max_error_retry") != null ? rs.getInt("max_error_retry") : null; + Integer s3_sockettimeout = rs.getObject("socket_timeout") != null ? rs.getInt("socket_timeout") : null; + Date s3_created = rs.getDate("created"); + + // insert entry in image_store table and image_store_details + // table and store s3_id and store_id mapping + + storeInsert.setString(1, s3_uuid); + storeInsert.setString(2, s3_uuid); + storeInsert.setString(3, s3_https ? "https" : "http"); + storeInsert.setDate(4, s3_created); + storeInsert.executeUpdate(); + + storeQuery.setString(1, s3_uuid); + storeInfo = storeQuery.executeQuery(); + if (storeInfo.next()) { + storeId = storeInfo.getLong("id"); + } + + Map detailMap = new HashMap(); + detailMap.put(ApiConstants.S3_ACCESS_KEY, s3_accesskey); + detailMap.put(ApiConstants.S3_SECRET_KEY, s3_secretkey); + detailMap.put(ApiConstants.S3_BUCKET_NAME, s3_bucket); + detailMap.put(ApiConstants.S3_END_POINT, s3_endpoint); + detailMap.put(ApiConstants.S3_HTTPS_FLAG, String.valueOf(s3_https)); + if (s3_connectiontimeout != null) { + detailMap.put(ApiConstants.S3_CONNECTION_TIMEOUT, String.valueOf(s3_connectiontimeout)); + } + if (s3_retry != null) { + detailMap.put(ApiConstants.S3_MAX_ERROR_RETRY, String.valueOf(s3_retry)); + } + if (s3_sockettimeout != null) { + detailMap.put(ApiConstants.S3_SOCKET_TIMEOUT, String.valueOf(s3_sockettimeout)); + } + + Iterator keyIt = detailMap.keySet().iterator(); + while (keyIt.hasNext()) { + String key = keyIt.next(); + String val = detailMap.get(key); + storeDetailInsert.setLong(1, storeId); + storeDetailInsert.setString(2, key); + storeDetailInsert.setString(3, val); + storeDetailInsert.executeUpdate(); + } + s3_store_id_map.put(s3_id, storeId); + } + + // migrate SWIFT secondary storage + storeInsert = conn + .prepareStatement("INSERT INTO `cloud`.`image_store` (uuid, name, image_provider_name, protocol, url, scope, role, created) values(?, ?, 'Swift', 'http', ?, 'REGION', 'Image', ?)"); + swiftQuery = conn + .prepareStatement("select id, uuid, url, account, username, key, created from `cloud`.`swift`"); + rs = swiftQuery.executeQuery(); + + while (rs.next()) { + Long swift_id = rs.getLong("id"); + String swift_uuid = rs.getString("uuid"); + String swift_url = rs.getString("url"); + String swift_account = rs.getString("account"); + String swift_username = rs.getString("username"); + String swift_key = rs.getString("key"); + Date swift_created = rs.getDate("created"); + + // insert entry in image_store table and image_store_details + // table and store swift_id and store_id mapping + storeInsert.setString(1, swift_uuid); + storeInsert.setString(2, swift_uuid); + storeInsert.setString(3, swift_url); + storeInsert.setDate(4, swift_created); + storeInsert.executeUpdate(); + + storeQuery.setString(1, swift_uuid); + storeInfo = storeQuery.executeQuery(); + if (storeInfo.next()) { + storeId = storeInfo.getLong("id"); + } + + Map detailMap = new HashMap(); + detailMap.put(ApiConstants.ACCOUNT, swift_account); + detailMap.put(ApiConstants.USERNAME, swift_username); + detailMap.put(ApiConstants.KEY, swift_key); + + Iterator keyIt = detailMap.keySet().iterator(); + while (keyIt.hasNext()) { + String key = keyIt.next(); + String val = detailMap.get(key); + storeDetailInsert.setLong(1, storeId); + storeDetailInsert.setString(2, key); + storeDetailInsert.setString(3, val); + storeDetailInsert.executeUpdate(); + } + swift_store_id_map.put(swift_id, storeId); + } + */ + + // migrate NFS secondary storage, for nfs, keep previous host_id as the store_id + storeInsert = conn + .prepareStatement("INSERT INTO `cloud`.`image_store` (id, uuid, name, image_provider_name, protocol, url, data_center_id, scope, role, parent, total_size, created) values(?, ?, ?, 'NFS', 'nfs', ?, ?, 'ZONE', 'Image', ?, ?, ?)"); + nfsQuery = conn + .prepareStatement("select id, uuid, url, data_center_id, parent, total_size, created from `cloud`.`host` where type = 'SecondaryStorage' and removed is null"); + rs = nfsQuery.executeQuery(); + + while (rs.next()) { + Long nfs_id = rs.getLong("id"); + String nfs_uuid = rs.getString("uuid"); + String nfs_url = rs.getString("url"); + String nfs_parent = rs.getString("parent"); + int nfs_dcid = rs.getInt("data_center_id"); + Long nfs_totalsize = rs.getObject("total_size") != null ? rs.getLong("total_size") : null; + Date nfs_created = rs.getDate("created"); + + // insert entry in image_store table and image_store_details + // table and store host_id and store_id mapping + storeInsert.setLong(1, nfs_id); + storeInsert.setString(2, nfs_uuid); + storeInsert.setString(3, nfs_uuid); + storeInsert.setString(4, nfs_url); + storeInsert.setInt(5, nfs_dcid); + storeInsert.setString(6, nfs_parent); + if (nfs_totalsize != null){ + storeInsert.setLong(7, nfs_totalsize); + } + else{ + storeInsert.setNull(7, Types.BIGINT); + } + storeInsert.setDate(8, nfs_created); + storeInsert.executeUpdate(); + + storeQuery.setString(1, nfs_uuid); + storeInfo = storeQuery.executeQuery(); + if (storeInfo.next()) { + storeId = storeInfo.getLong("id"); + } + + //host_store_id_map.put(nfs_id, storeId); + } + } + catch (SQLException e) { + String msg = "Unable to migrate secondary storages." + e.getMessage(); + s_logger.error(msg); + throw new CloudRuntimeException(msg, e); + } finally { + try { + if (rs != null) { + rs.close(); + } + if (storeInfo != null) { + storeInfo.close(); + } + + if (storeInsert != null) { + storeInsert.close(); + } + if (storeDetailInsert != null) { + storeDetailInsert.close(); + } + if (storeQuery != null) { + storeQuery.close(); + } + if (swiftQuery != null) { + swiftQuery.close(); + } + if (s3Query != null) { + s3Query.close(); + } + if (nfsQuery != null) { + nfsQuery.close(); + } + } catch (SQLException e) { + } + } + } + + // migrate volume_host_ref to volume_store_ref + private void migrateVolumeHostRef(Connection conn) { + PreparedStatement volStoreInsert = null; + PreparedStatement volStoreUpdate = null; + + try { + + volStoreInsert = conn + .prepareStatement("INSERT INTO `cloud`.`volume_store_ref` (store_id, volume_id, zone_id, created, last_updated, job_id, download_pct, size, physical_size, download_state, checksum, error_str, local_path, install_path, url, destroyed, state) select host_id, volume_id, zone_id, created, last_updated, job_id, download_pct, size, physical_size, download_state, checksum, error_str, local_path, install_path, url, destroyed, 'Allocated' from `cloud`.`volume_host_ref`"); + volStoreInsert.executeUpdate(); + + volStoreUpdate = conn.prepareStatement("update `cloud`.`volume_store_ref` set state = 'Ready' where download_state = 'DOWNLOADED'"); + volStoreUpdate.executeUpdate(); + } + catch (SQLException e) { + String msg = "Unable to migrate volume_host_ref." + e.getMessage(); + s_logger.error(msg); + throw new CloudRuntimeException(msg, e); + } finally { + try{ + if (volStoreInsert != null) { + volStoreInsert.close(); + } + if (volStoreUpdate != null) { + volStoreUpdate.close(); + } + } catch (SQLException e) { + } + } + } + + // migrate template_host_ref to template_store_ref + private void migrateTemplateHostRef(Connection conn) { + PreparedStatement tmplStoreInsert = null; + PreparedStatement tmplStoreUpdate = null; + + try { + + tmplStoreInsert = conn + .prepareStatement("INSERT INTO `cloud`.`template_store_ref` (store_id, template_id, created, last_updated, job_id, download_pct, size, physical_size, download_state, error_str, local_path, install_path, url, destroyed, is_copy, store_role, state) select host_id, template_id, created, last_updated, job_id, download_pct, size, physical_size, download_state, error_str, local_path, install_path, url, destroyed, is_copy, 'Image', 'Allocated' from `cloud`.`template_host_ref`"); + tmplStoreInsert.executeUpdate(); + + tmplStoreUpdate = conn.prepareStatement("update `cloud`.`template_store_ref` set state = 'Ready' where download_state = 'DOWNLOADED'"); + tmplStoreUpdate.executeUpdate(); + } + catch (SQLException e) { + String msg = "Unable to migrate template_host_ref." + e.getMessage(); + s_logger.error(msg); + throw new CloudRuntimeException(msg, e); + } finally { + try{ + if (tmplStoreInsert != null) { + tmplStoreInsert.close(); + } + if (tmplStoreUpdate != null) { + tmplStoreUpdate.close(); + } + } catch (SQLException e) { + } + } + } + + // migrate some entry contents of snapshots to snapshot_store_ref + private void migrateSnapshotStoreRef(Connection conn) { + PreparedStatement snapshotStoreInsert = null; + + try { + snapshotStoreInsert = conn + .prepareStatement("INSERT INTO `cloud`.`snapshot_store_ref` (store_id, snapshot_id, created, size, parent_snapshot_id, install_path, state) select sechost_id, id, created, size, prev_snap_id, path, 'Ready' from `cloud`.`snapshots` where status = 'BackedUp' and sechost_id is not null and removed is null"); + snapshotStoreInsert.executeUpdate(); + } + catch (SQLException e) { + String msg = "Unable to migrate snapshot_store_ref." + e.getMessage(); + s_logger.error(msg); + throw new CloudRuntimeException(msg, e); + } finally { + try{ + if (snapshotStoreInsert != null) { + snapshotStoreInsert.close(); + } + } catch (SQLException e) { + } + } + } } diff --git a/engine/storage/backup/src/org/apache/cloudstack/storage/backup/BackupMotionService.java b/engine/storage/backup/src/org/apache/cloudstack/storage/backup/BackupMotionService.java deleted file mode 100644 index cb49027f3bf..00000000000 --- a/engine/storage/backup/src/org/apache/cloudstack/storage/backup/BackupMotionService.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.backup; - -public interface BackupMotionService { - boolean copySnapshot(String snapshotUri, String destSnapshotUri); -} diff --git a/engine/storage/backup/src/org/apache/cloudstack/storage/backup/BackupService.java b/engine/storage/backup/src/org/apache/cloudstack/storage/backup/BackupService.java deleted file mode 100644 index 67924d2ce73..00000000000 --- a/engine/storage/backup/src/org/apache/cloudstack/storage/backup/BackupService.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.backup; - -import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; - -public interface BackupService { - public boolean backupSnapshot(SnapshotInfo snapshot, long backupStoreId); - public SnapshotOnBackupStoreInfo getSnapshot(long snapshotId); -} diff --git a/engine/storage/backup/pom.xml b/engine/storage/cache/pom.xml similarity index 94% rename from engine/storage/backup/pom.xml rename to engine/storage/cache/pom.xml index 019e09c7204..f00f6cd1498 100644 --- a/engine/storage/backup/pom.xml +++ b/engine/storage/cache/pom.xml @@ -11,8 +11,8 @@ 4.0.0 - cloud-engine-storage-backup - Apache CloudStack Engine Storage Backup Component + cloud-engine-storage-cache + Apache CloudStack Engine Storage Cache Component org.apache.cloudstack cloud-engine diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/ImageDataStoreDriver.java b/engine/storage/cache/src/org/apache/cloudstack/storage/cache/allocator/StorageCacheAllocator.java similarity index 80% rename from engine/storage/src/org/apache/cloudstack/storage/image/ImageDataStoreDriver.java rename to engine/storage/cache/src/org/apache/cloudstack/storage/cache/allocator/StorageCacheAllocator.java index d352d972182..4259d9ed03f 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/ImageDataStoreDriver.java +++ b/engine/storage/cache/src/org/apache/cloudstack/storage/cache/allocator/StorageCacheAllocator.java @@ -16,9 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.storage.image; +package org.apache.cloudstack.storage.cache.allocator; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.Scope; -public interface ImageDataStoreDriver extends DataStoreDriver { +public interface StorageCacheAllocator { + DataStore getCacheStore(Scope scope); } diff --git a/engine/storage/cache/src/org/apache/cloudstack/storage/cache/allocator/StorageCacheRandomAllocator.java b/engine/storage/cache/src/org/apache/cloudstack/storage/cache/allocator/StorageCacheRandomAllocator.java new file mode 100644 index 00000000000..f244a0371b7 --- /dev/null +++ b/engine/storage/cache/src/org/apache/cloudstack/storage/cache/allocator/StorageCacheRandomAllocator.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.cache.allocator; + +import java.util.Collections; +import java.util.List; + +import javax.inject.Inject; + +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.Scope; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.storage.ScopeType; + +@Component +public class StorageCacheRandomAllocator implements StorageCacheAllocator { + private static final Logger s_logger = Logger.getLogger(StorageCacheRandomAllocator.class); + @Inject + DataStoreManager dataStoreMgr; + + @Override + public DataStore getCacheStore(Scope scope) { + if (scope.getScopeType() != ScopeType.ZONE) { + s_logger.debug("Can only support zone wide cache storage"); + return null; + } + + List cacheStores = dataStoreMgr.getImageCacheStores(scope); + if (cacheStores.size() <= 0) { + s_logger.debug("Can't find cache storage in zone: " + scope.getScopeId()); + return null; + } + + Collections.shuffle(cacheStores); + return cacheStores.get(0); + } +} diff --git a/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java b/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java new file mode 100644 index 00000000000..4b4e52106ff --- /dev/null +++ b/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java @@ -0,0 +1,254 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.cache.manager; + +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.storage.DataStoreRole; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.component.Manager; +import com.cloud.utils.concurrency.NamedThreadFactory; +import com.cloud.utils.db.GlobalLock; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria2; +import com.cloud.utils.db.SearchCriteriaService; +import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.cloudstack.engine.subsystem.api.storage.*; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; +import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.storage.cache.allocator.StorageCacheAllocator; +import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; +import org.apache.log4j.Logger; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +public class StorageCacheManagerImpl implements StorageCacheManager, Manager { + private static final Logger s_logger = Logger.getLogger(StorageCacheManagerImpl.class); + @Inject + List storageCacheAllocator; + @Inject + DataMotionService dataMotionSvr; + @Inject + ObjectInDataStoreManager objectInStoreMgr; + @Inject + DataStoreManager dataStoreManager; + @Inject + StorageCacheReplacementAlgorithm cacheReplacementAlgorithm; + @Inject + ConfigurationDao configDao; + Boolean cacheReplacementEnabled = Boolean.TRUE; + int workers; + ScheduledExecutorService executors; + int cacheReplaceMentInterval; + + @Override + public DataStore getCacheStorage(Scope scope) { + for (StorageCacheAllocator allocator : storageCacheAllocator) { + DataStore store = allocator.getCacheStore(scope); + if (store != null) { + return store; + } + } + return null; + } + + protected List getCacheStores() { + SearchCriteriaService sc = SearchCriteria2.create(ImageStoreVO.class); + sc.addAnd(sc.getEntity().getRole(), SearchCriteria.Op.EQ, DataStoreRole.ImageCache); + List imageStoreVOs = sc.list(); + List stores = new ArrayList(); + for (ImageStoreVO vo : imageStoreVOs) { + stores.add(dataStoreManager.getDataStore(vo.getId(), vo.getRole())); + } + return stores; + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setName(String name) { + // TODO Auto-generated method stub + + } + + @Override + public void setConfigParams(Map params) { + // TODO Auto-generated method stub + + } + + @Override + public Map getConfigParams() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getRunLevel() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public void setRunLevel(int level) { + // TODO Auto-generated method stub + + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + cacheReplacementEnabled = Boolean.parseBoolean(configDao.getValue(Config.StorageCacheReplacementEnabled.key())); + cacheReplaceMentInterval = NumbersUtil.parseInt(configDao.getValue(Config.StorageCacheReplacementInterval.key()), 86400); + workers = NumbersUtil.parseInt(configDao.getValue(Config.ExpungeWorkers.key()), 10); + executors = Executors.newScheduledThreadPool(workers, new NamedThreadFactory("StorageCacheManager-cache-replacement")); + return true; + } + + protected class CacheReplacementRunner implements Runnable { + + @Override + public void run() { + GlobalLock replacementLock = null; + try { + replacementLock = GlobalLock.getInternLock("storageCacheMgr.replacement"); + if (replacementLock.lock(3)) { + List stores = getCacheStores(); + Collections.shuffle(stores); + DataObject object = null; + DataStore findAStore = null; + for (DataStore store : stores) { + object = cacheReplacementAlgorithm.chooseOneToBeReplaced(store); + findAStore = store; + if (object != null) { + break; + } + } + + if (object == null) { + return; + } + + while(object != null) { + object.delete(); + object = cacheReplacementAlgorithm.chooseOneToBeReplaced(findAStore); + } + } + } catch (Exception e) { + s_logger.debug("Failed to execute CacheReplacementRunner: " + e.toString()); + } finally { + if (replacementLock != null) { + replacementLock.unlock(); + } + } + } + } + + @Override + public boolean start() { + if (cacheReplacementEnabled) { + Random generator = new Random(); + int initalDelay = generator.nextInt(cacheReplaceMentInterval); + executors.scheduleWithFixedDelay(new CacheReplacementRunner(), initalDelay, cacheReplaceMentInterval, TimeUnit.SECONDS); + } + return true; + } + + @Override + public boolean stop() { + // TODO Auto-generated method stub + return true; + } + + @Override + public DataObject createCacheObject(DataObject data, DataStore store) { + DataObjectInStore obj = objectInStoreMgr.findObject(data, store); + if (obj != null && obj.getState() == ObjectInDataStoreStateMachine.State.Ready) { + s_logger.debug("there is already one in the cache store"); + DataObject dataObj = objectInStoreMgr.get(data, store); + dataObj.incRefCount(); + return dataObj; + } + + DataObject objOnCacheStore = store.create(data); + + AsyncCallFuture future = new AsyncCallFuture(); + CopyCommandResult result = null; + try { + objOnCacheStore.processEvent(Event.CreateOnlyRequested); + + dataMotionSvr.copyAsync(data, objOnCacheStore, future); + result = future.get(); + + if (result.isFailed()) { + objOnCacheStore.processEvent(Event.OperationFailed); + } else { + objOnCacheStore.processEvent(Event.OperationSuccessed, result.getAnswer()); + objOnCacheStore.incRefCount(); + return objOnCacheStore; + } + } catch (InterruptedException e) { + s_logger.debug("create cache storage failed: " + e.toString()); + throw new CloudRuntimeException(e); + } catch (ExecutionException e) { + s_logger.debug("create cache storage failed: " + e.toString()); + throw new CloudRuntimeException(e); + } finally { + if (result == null) { + objOnCacheStore.processEvent(Event.OperationFailed); + } + } + return null; + } + + @Override + public DataObject createCacheObject(DataObject data, Scope scope) { + DataStore cacheStore = this.getCacheStorage(scope); + return this.createCacheObject(data, cacheStore); + } + + @Override + public DataObject getCacheObject(DataObject data, Scope scope) { + DataStore cacheStore = this.getCacheStorage(scope); + DataObject objOnCacheStore = cacheStore.create(data); + objOnCacheStore.incRefCount(); + return objOnCacheStore; + } + + @Override + public boolean releaseCacheObject(DataObject data) { + data.decRefCount(); + return true; + } + + @Override + public boolean deleteCacheObject(DataObject data) { + return data.getDataStore().delete(data); + } +} \ No newline at end of file diff --git a/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionDriver.java b/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheReplacementAlgorithm.java similarity index 79% rename from engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionDriver.java rename to engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheReplacementAlgorithm.java index 3a59b21238b..f7a23febecd 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionDriver.java +++ b/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheReplacementAlgorithm.java @@ -16,10 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.storage.motion; +package org.apache.cloudstack.storage.cache.manager; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -public interface DataMotionDriver { - public void copy(DataObject srcObj, DataObject destObj); +public interface StorageCacheReplacementAlgorithm { + DataObject chooseOneToBeReplaced(DataStore store); } diff --git a/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheReplacementAlgorithmLRU.java b/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheReplacementAlgorithmLRU.java new file mode 100644 index 00000000000..440bf53ebda --- /dev/null +++ b/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheReplacementAlgorithmLRU.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.cache.manager; +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.utils.DateUtil; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria2; +import com.cloud.utils.db.SearchCriteriaService; +import org.apache.cloudstack.engine.subsystem.api.storage.*; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; +import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO; +import org.apache.commons.lang.math.NumberUtils; + +import java.util.Calendar; +import java.util.Date; +import javax.annotation.PostConstruct; +import javax.inject.Inject; + + + +public class StorageCacheReplacementAlgorithmLRU implements StorageCacheReplacementAlgorithm { + @Inject + ConfigurationDao configDao; + @Inject + TemplateDataFactory templateFactory; + @Inject + VolumeDataFactory volumeFactory; + @Inject + SnapshotDataFactory snapshotFactory; + + Integer unusedTimeInterval; + + public StorageCacheReplacementAlgorithmLRU() { + + } + + @PostConstruct + public void initialize() { + unusedTimeInterval = NumbersUtil.parseInt(configDao.getValue(Config.StorageCacheReplacementLRUTimeInterval.key()), 30); + } + + public void setUnusedTimeInterval(Integer interval) { + unusedTimeInterval = interval; + } + + @Override + public DataObject chooseOneToBeReplaced(DataStore store) { + Calendar cal = Calendar.getInstance(); + cal.setTime(DateUtil.now()); + cal.add(Calendar.DAY_OF_MONTH, -unusedTimeInterval.intValue()); + Date bef = cal.getTime(); + + SearchCriteriaService sc = SearchCriteria2.create(TemplateDataStoreVO.class); + sc.addAnd(sc.getEntity().getLastUpdated(), SearchCriteria.Op.LT, bef); + sc.addAnd(sc.getEntity().getState(), SearchCriteria.Op.EQ, ObjectInDataStoreStateMachine.State.Ready); + sc.addAnd(sc.getEntity().getDataStoreId(), SearchCriteria.Op.EQ, store.getId()); + sc.addAnd(sc.getEntity().getDataStoreRole(), SearchCriteria.Op.EQ, store.getRole()); + sc.addAnd(sc.getEntity().getRefCnt(), SearchCriteria.Op.EQ, 0); + TemplateDataStoreVO template = sc.find(); + if (template != null) { + return templateFactory.getTemplate(template.getTemplateId(), store); + } + + SearchCriteriaService volSc = SearchCriteria2.create(VolumeDataStoreVO.class); + volSc.addAnd(volSc.getEntity().getLastUpdated(), SearchCriteria.Op.LT, bef); + volSc.addAnd(volSc.getEntity().getState(), SearchCriteria.Op.EQ, ObjectInDataStoreStateMachine.State.Ready); + volSc.addAnd(volSc.getEntity().getDataStoreId(), SearchCriteria.Op.EQ, store.getId()); + volSc.addAnd(volSc.getEntity().getRefCnt(), SearchCriteria.Op.EQ, 0); + VolumeDataStoreVO volume = volSc.find(); + if (volume != null) { + return volumeFactory.getVolume(volume.getVolumeId(), store); + } + + SearchCriteriaService snapshotSc = SearchCriteria2.create(SnapshotDataStoreVO.class); + snapshotSc.addAnd(snapshotSc.getEntity().getLastUpdated(), SearchCriteria.Op.LT, bef); + snapshotSc.addAnd(snapshotSc.getEntity().getState(), SearchCriteria.Op.EQ, ObjectInDataStoreStateMachine.State.Ready); + snapshotSc.addAnd(snapshotSc.getEntity().getDataStoreId(), SearchCriteria.Op.EQ, store.getId()); + snapshotSc.addAnd(snapshotSc.getEntity().getRole(), SearchCriteria.Op.EQ, store.getRole()); + snapshotSc.addAnd(snapshotSc.getEntity().getRefCnt(), SearchCriteria.Op.EQ, 0); + SnapshotDataStoreVO snapshot = snapshotSc.find(); + if (snapshot != null) { + return snapshotFactory.getSnapshot(snapshot.getSnapshotId(), store); + } + + return null; + } +} diff --git a/engine/storage/imagemotion/pom.xml b/engine/storage/datamotion/pom.xml similarity index 95% rename from engine/storage/imagemotion/pom.xml rename to engine/storage/datamotion/pom.xml index 9a7f3e017a2..8a3698c94d3 100644 --- a/engine/storage/imagemotion/pom.xml +++ b/engine/storage/datamotion/pom.xml @@ -11,8 +11,8 @@ 4.0.0 - cloud-engine-storage-imagemotion - Apache CloudStack Engine Storage Image Motion Component + cloud-engine-storage-datamotion + Apache CloudStack Engine Storage Data Motion Component org.apache.cloudstack cloud-engine diff --git a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java new file mode 100644 index 00000000000..631de6a47a3 --- /dev/null +++ b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java @@ -0,0 +1,414 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.motion; + +import java.util.Map; + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; +import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy; +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +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.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; +import org.apache.cloudstack.engine.subsystem.api.storage.Scope; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.storage.command.CopyCommand; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao; +import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.NfsTO; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.host.Host; +import com.cloud.host.dao.HostDao; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.StorageManager; +import com.cloud.storage.StoragePool; +import com.cloud.storage.VolumeManager; +import com.cloud.storage.dao.DiskOfferingDao; +import com.cloud.storage.dao.SnapshotDao; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VMTemplatePoolDao; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.storage.snapshot.SnapshotManager; +import com.cloud.template.TemplateManager; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.db.DB; +import com.cloud.utils.exception.CloudRuntimeException; + +@Component +public class AncientDataMotionStrategy implements DataMotionStrategy { + private static final Logger s_logger = Logger.getLogger(AncientDataMotionStrategy.class); + @Inject + EndPointSelector selector; + @Inject + TemplateManager templateMgr; + @Inject + VolumeDataStoreDao volumeStoreDao; + @Inject + HostDao hostDao; + @Inject + ConfigurationDao configDao; + @Inject + StorageManager storageMgr; + @Inject + VolumeDao volDao; + @Inject + VMTemplateDao templateDao; + @Inject + SnapshotManager snapshotMgr; + @Inject + SnapshotDao snapshotDao; + @Inject + SnapshotDataStoreDao _snapshotStoreDao; + @Inject + PrimaryDataStoreDao primaryDataStoreDao; + @Inject + DataStoreManager dataStoreMgr; + @Inject + TemplateDataStoreDao templateStoreDao; + @Inject + DiskOfferingDao diskOfferingDao; + @Inject + VMTemplatePoolDao templatePoolDao; + @Inject + VolumeManager volumeMgr; + @Inject + StorageCacheManager cacheMgr; + + @Override + public boolean canHandle(DataObject srcData, DataObject destData) { + // TODO Auto-generated method stub + return true; + } + + @Override + public boolean canHandle(Map volumeMap, Host srcHost, Host destHost) { + return false; + } + + protected boolean needCacheStorage(DataObject srcData, DataObject destData) { + DataTO srcTO = srcData.getTO(); + DataTO destTO = destData.getTO(); + DataStoreTO srcStoreTO = srcTO.getDataStore(); + DataStoreTO destStoreTO = destTO.getDataStore(); + if (srcStoreTO instanceof NfsTO || srcStoreTO.getRole() == DataStoreRole.ImageCache) { + return false; + } + + if (destStoreTO instanceof NfsTO || destStoreTO.getRole() == DataStoreRole.ImageCache) { + return false; + } + return true; + } + + private Scope getZoneScope(Scope destScope) { + ZoneScope zoneScope = null; + if (destScope instanceof ClusterScope) { + ClusterScope clusterScope = (ClusterScope) destScope; + zoneScope = new ZoneScope(clusterScope.getZoneId()); + } else if (destScope instanceof HostScope) { + HostScope hostScope = (HostScope) destScope; + zoneScope = new ZoneScope(hostScope.getZoneId()); + } else { + zoneScope = (ZoneScope) destScope; + } + return zoneScope; + } + + protected Answer copyObject(DataObject srcData, DataObject destData) { + String value = configDao.getValue(Config.PrimaryStorageDownloadWait.toString()); + int _primaryStorageDownloadWait = NumbersUtil.parseInt(value, + Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue())); + Answer answer = null; + DataObject cacheData = null; + try { + if (needCacheStorage(srcData, destData)) { + // need to copy it to image cache store + Scope destScope = getZoneScope(destData.getDataStore().getScope()); + cacheData = cacheMgr.createCacheObject(srcData, destScope); + CopyCommand cmd = new CopyCommand(cacheData.getTO(), destData.getTO(), _primaryStorageDownloadWait); + EndPoint ep = selector.select(cacheData, destData); + answer = ep.sendMessage(cmd); + } else { + // handle copy it to/from cache store + CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _primaryStorageDownloadWait); + EndPoint ep = selector.select(srcData, destData); + answer = ep.sendMessage(cmd); + } + if (cacheData != null) { + if (answer == null || !answer.getResult()) { + cacheMgr.deleteCacheObject(cacheData); + } else { + cacheMgr.releaseCacheObject(cacheData); + } + } + return answer; + } catch (Exception e) { + s_logger.debug("copy object failed: " + e.toString()); + if (cacheData != null) { + cacheMgr.deleteCacheObject(cacheData); + } + throw new CloudRuntimeException(e.toString()); + } + + } + + protected DataObject cacheSnapshotChain(SnapshotInfo snapshot) { + DataObject leafData = null; + DataStore store = cacheMgr.getCacheStorage(snapshot.getDataStore().getScope()); + while (snapshot != null) { + DataObject cacheData = cacheMgr.createCacheObject(snapshot, store); + if (leafData == null) { + leafData = cacheData; + } + snapshot = snapshot.getParent(); + } + return leafData; + } + + protected void deleteSnapshotCacheChain(SnapshotInfo snapshot) { + while (snapshot != null) { + cacheMgr.deleteCacheObject(snapshot); + snapshot = snapshot.getParent(); + } + } + + protected Answer copyVolumeFromSnapshot(DataObject snapObj, DataObject volObj) { + SnapshotInfo snapshot = (SnapshotInfo) snapObj; + StoragePool pool = (StoragePool) volObj.getDataStore(); + + String basicErrMsg = "Failed to create volume from " + snapshot.getName() + " on pool " + pool; + DataStore store = snapObj.getDataStore(); + DataStoreTO storTO = store.getTO(); + DataObject srcData = snapObj; + try { + if (!(storTO instanceof NfsTO)) { + srcData = cacheSnapshotChain(snapshot); + } + + String value = configDao.getValue(Config.CreateVolumeFromSnapshotWait.toString()); + int _createVolumeFromSnapshotWait = NumbersUtil.parseInt(value, + Integer.parseInt(Config.CreateVolumeFromSnapshotWait.getDefaultValue())); + + CopyCommand cmd = new CopyCommand(srcData.getTO(), volObj.getTO(), _createVolumeFromSnapshotWait); + EndPoint ep = selector.select(snapObj, volObj); + Answer answer = ep.sendMessage(cmd); + + return answer; + } catch (Exception e) { + s_logger.error(basicErrMsg, e); + throw new CloudRuntimeException(basicErrMsg); + } finally { + if (!(storTO instanceof NfsTO)) { + deleteSnapshotCacheChain((SnapshotInfo) srcData); + } + } + } + + protected Answer cloneVolume(DataObject template, DataObject volume) { + CopyCommand cmd = new CopyCommand(template.getTO(), volume.getTO(), 0); + try { + EndPoint ep = selector.select(volume.getDataStore()); + Answer answer = ep.sendMessage(cmd); + return answer; + } catch (Exception e) { + s_logger.debug("Failed to send to storage pool", e); + throw new CloudRuntimeException("Failed to send to storage pool", e); + } + } + + protected Answer copyVolumeBetweenPools(DataObject srcData, DataObject destData) { + String value = configDao.getValue(Config.CopyVolumeWait.key()); + int _copyvolumewait = NumbersUtil.parseInt(value, Integer.parseInt(Config.CopyVolumeWait.getDefaultValue())); + + Scope destScope = getZoneScope(destData.getDataStore().getScope()); + DataStore cacheStore = cacheMgr.getCacheStorage(destScope); + if (cacheStore == null) { + // need to find a nfs image store, assuming that can't copy volume + // directly to s3 + ImageStoreEntity imageStore = (ImageStoreEntity) this.dataStoreMgr.getImageStore(destScope.getScopeId()); + if (!imageStore.getProtocol().equalsIgnoreCase("nfs")) { + s_logger.debug("can't find a nfs image store"); + return null; + } + + DataObject objOnImageStore = imageStore.create(srcData); + objOnImageStore.processEvent(Event.CreateOnlyRequested); + + Answer answer = this.copyObject(srcData, objOnImageStore); + if (answer == null || !answer.getResult()) { + if (answer != null) { + s_logger.debug("copy to image store failed: " + answer.getDetails()); + } + objOnImageStore.processEvent(Event.OperationFailed); + imageStore.delete(objOnImageStore); + return answer; + } + + objOnImageStore.processEvent(Event.OperationSuccessed, answer); + + objOnImageStore.processEvent(Event.CopyingRequested); + + CopyCommand cmd = new CopyCommand(objOnImageStore.getTO(), destData.getTO(), _copyvolumewait); + EndPoint ep = selector.select(objOnImageStore, destData); + answer = ep.sendMessage(cmd); + + if (answer == null || !answer.getResult()) { + if (answer != null) { + s_logger.debug("copy to primary store failed: " + answer.getDetails()); + } + objOnImageStore.processEvent(Event.OperationFailed); + imageStore.delete(objOnImageStore); + return answer; + } + + objOnImageStore.processEvent(Event.OperationSuccessed); + imageStore.delete(objOnImageStore); + return answer; + } else { + DataObject cacheData = cacheMgr.createCacheObject(srcData, destScope); + CopyCommand cmd = new CopyCommand(cacheData.getTO(), destData.getTO(), _copyvolumewait); + EndPoint ep = selector.select(cacheData, destData); + Answer answer = ep.sendMessage(cmd); + return answer; + } + + } + + @Override + public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback callback) { + Answer answer = null; + String errMsg = null; + try { + + if (srcData.getType() == DataObjectType.SNAPSHOT && destData.getType() == DataObjectType.VOLUME) { + answer = copyVolumeFromSnapshot(srcData, destData); + } else if (srcData.getType() == DataObjectType.SNAPSHOT && destData.getType() == DataObjectType.TEMPLATE) { + answer = createTemplateFromSnapshot(srcData, destData); + } else if (srcData.getType() == DataObjectType.TEMPLATE && destData.getType() == DataObjectType.VOLUME) { + answer = cloneVolume(srcData, destData); + } else if (destData.getType() == DataObjectType.VOLUME && srcData.getType() == DataObjectType.VOLUME + && srcData.getDataStore().getRole() == DataStoreRole.Primary + && destData.getDataStore().getRole() == DataStoreRole.Primary) { + answer = copyVolumeBetweenPools(srcData, destData); + } else if (srcData.getType() == DataObjectType.SNAPSHOT && destData.getType() == DataObjectType.SNAPSHOT) { + answer = copySnapshot(srcData, destData); + } else { + answer = copyObject(srcData, destData); + } + + if (answer != null && !answer.getResult()) { + errMsg = answer.getDetails(); + } + } catch (Exception e) { + s_logger.debug("copy failed", e); + errMsg = e.toString(); + } + CopyCommandResult result = new CopyCommandResult(null, answer); + result.setResult(errMsg); + callback.complete(result); + return null; + } + + @DB + protected Answer createTemplateFromSnapshot(DataObject srcData, DataObject destData) { + + String value = configDao.getValue(Config.CreatePrivateTemplateFromSnapshotWait.toString()); + int _createprivatetemplatefromsnapshotwait = NumbersUtil.parseInt(value, + Integer.parseInt(Config.CreatePrivateTemplateFromSnapshotWait.getDefaultValue())); + + if (needCacheStorage(srcData, destData)) { + SnapshotInfo snapshot = (SnapshotInfo) srcData; + srcData = cacheSnapshotChain(snapshot); + } + + CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _createprivatetemplatefromsnapshotwait); + EndPoint ep = selector.select(srcData, destData); + Answer answer = ep.sendMessage(cmd); + return answer; + } + + protected Answer copySnapshot(DataObject srcData, DataObject destData) { + String value = configDao.getValue(Config.BackupSnapshotWait.toString()); + int _backupsnapshotwait = NumbersUtil.parseInt(value, + Integer.parseInt(Config.BackupSnapshotWait.getDefaultValue())); + + DataObject cacheData = null; + Answer answer = null; + try { + if (needCacheStorage(srcData, destData)) { + cacheData = cacheMgr.getCacheObject(srcData, destData.getDataStore().getScope()); + + CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _backupsnapshotwait); + cmd.setCacheTO(cacheData.getTO()); + EndPoint ep = selector.select(srcData, destData); + answer = ep.sendMessage(cmd); + } else { + CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _backupsnapshotwait); + EndPoint ep = selector.select(srcData, destData); + answer = ep.sendMessage(cmd); + } + // clean up cache entry in case of failure + if (answer == null || !answer.getResult()) { + if (cacheData != null) { + cacheMgr.deleteCacheObject(cacheData); + } + } + return answer; + } catch (Exception e) { + s_logger.debug("copy snasphot failed: " + e.toString()); + if (cacheData != null) { + cacheMgr.deleteCacheObject(cacheData); + } + throw new CloudRuntimeException(e.toString()); + } + + } + + @Override + public Void copyAsync(Map volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, + AsyncCompletionCallback callback) { + CopyCommandResult result = new CopyCommandResult(null, null); + result.setResult("Unsupported operation requested for copying data."); + callback.complete(result); + + return null; + } +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionServiceImpl.java b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/DataMotionServiceImpl.java similarity index 83% rename from engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionServiceImpl.java rename to engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/DataMotionServiceImpl.java index b74e10c460f..22de0b25279 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionServiceImpl.java +++ b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/DataMotionServiceImpl.java @@ -24,6 +24,8 @@ import java.util.Map; import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService; +import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; @@ -40,17 +42,13 @@ public class DataMotionServiceImpl implements DataMotionService { List strategies; @Override - public void copyAsync(DataObject srcData, DataObject destData, - AsyncCompletionCallback callback) { + public void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback callback) { if (srcData.getDataStore().getDriver().canCopy(srcData, destData)) { - srcData.getDataStore().getDriver() - .copyAsync(srcData, destData, callback); + srcData.getDataStore().getDriver().copyAsync(srcData, destData, callback); return; - } else if (destData.getDataStore().getDriver() - .canCopy(srcData, destData)) { - destData.getDataStore().getDriver() - .copyAsync(srcData, destData, callback); + } else if (destData.getDataStore().getDriver().canCopy(srcData, destData)) { + destData.getDataStore().getDriver().copyAsync(srcData, destData, callback); return; } @@ -64,8 +62,8 @@ public class DataMotionServiceImpl implements DataMotionService { } @Override - public void copyAsync(Map volumeMap, VirtualMachineTO vmTo, - Host srcHost, Host destHost, AsyncCompletionCallback callback) { + public void copyAsync(Map volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, + AsyncCompletionCallback callback) { for (DataMotionStrategy strategy : strategies) { if (strategy.canHandle(volumeMap, srcHost, destHost)) { strategy.copyAsync(volumeMap, vmTo, srcHost, destHost, callback); diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/ImageServiceImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/ImageServiceImpl.java deleted file mode 100644 index 99b1013f964..00000000000 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/ImageServiceImpl.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.image; - -import javax.inject.Inject; - -import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.ImageService; -import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; -import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; -import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent; -import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; -import org.apache.cloudstack.framework.async.AsyncCallFuture; -import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; -import org.apache.cloudstack.framework.async.AsyncCompletionCallback; -import org.apache.cloudstack.framework.async.AsyncRpcConext; -import org.apache.cloudstack.storage.datastore.DataObjectManager; -import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; -import org.apache.cloudstack.storage.image.store.TemplateObject; -import org.apache.cloudstack.storage.motion.DataMotionService; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - -import com.cloud.utils.fsm.NoTransitionException; - -@Component -public class ImageServiceImpl implements ImageService { - private static final Logger s_logger = Logger.getLogger(ImageServiceImpl.class); - @Inject - ObjectInDataStoreManager objectInDataStoreMgr; - @Inject - DataObjectManager dataObjectMgr; - @Inject - DataMotionService motionSrv; - - class CreateTemplateContext extends AsyncRpcConext { - final TemplateInfo srcTemplate; - final DataStore store; - final AsyncCallFuture future; - final DataObject templateOnStore; - - public CreateTemplateContext(AsyncCompletionCallback callback, TemplateInfo srcTemplate, - AsyncCallFuture future, - DataStore store, - DataObject templateOnStore - ) { - super(callback); - this.srcTemplate = srcTemplate; - this.future = future; - this.store = store; - 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; - } - - DataObject templateOnStore = store.create(template); - templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.CreateOnlyRequested); - - CreateTemplateContext context = new CreateTemplateContext(null, - template, - future, - store, - templateOnStore - ); - 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, - CreateTemplateContext context) { - TemplateObject template = (TemplateObject)context.srcTemplate; - AsyncCallFuture future = context.future; - CommandResult result = new CommandResult(); - DataObject templateOnStore = context.templateOnStore; - CreateCmdResult callbackResult = callback.getResult(); - if (callbackResult.isFailed()) { - try { - templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed); - template.stateTransit(TemplateEvent.OperationFailed); - } catch (NoTransitionException e) { - s_logger.debug("Failed to update template state", e); - } - result.setResult(callbackResult.getResult()); - future.complete(result); - return null; - } - - try { - templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed); - template.stateTransit(TemplateEvent.OperationSucceeded); - } catch (NoTransitionException e) { - s_logger.debug("Failed to transit state", e); - result.setResult(e.toString()); - future.complete(result); - return null; - } - - future.complete(result); - return null; - } - - @Override - public AsyncCallFuture deleteTemplateAsync( - TemplateInfo template) { - // TODO Auto-generated method stub - return null; - } - - private class CopyTemplateContext extends AsyncRpcConext { - final AsyncCallFuture future; - final DataObject object; - /** - * @param callback - */ - public CopyTemplateContext(AsyncCompletionCallback callback, AsyncCallFuture future, DataObject object) { - super(callback); - this.future = future; - this.object = object; - } - - } - @Override - public AsyncCallFuture createTemplateFromSnapshotAsync( - SnapshotInfo snapshot, TemplateInfo template, DataStore store) { - AsyncCallFuture future = new AsyncCallFuture(); - DataObject templateOnStore = null; - try { - templateOnStore = store.create(template); - templateOnStore.processEvent(Event.CreateOnlyRequested); - - CopyTemplateContext context = new CopyTemplateContext(null, future, templateOnStore); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); - caller.setCallback(caller.getTarget().copyTemplateAsyncCallback(null, null)) - .setContext(context); - this.motionSrv.copyAsync(snapshot, templateOnStore, caller); - } catch (Exception e) { - s_logger.debug("Failed to create template: " + template.getId() + "from snapshot: " + snapshot.getId() + ", due to " + e.toString()); - if (templateOnStore != null) { - try { - templateOnStore.processEvent(Event.OperationFailed); - } catch (Exception e1) { - - } - } - CommandResult result = new CommandResult(); - result.setResult(e.toString()); - future.complete(result); - } - return future; - } - - protected Void copyTemplateAsyncCallback(AsyncCallbackDispatcher callback, CopyTemplateContext context) { - CopyCommandResult result = callback.getResult(); - AsyncCallFuture future = context.future; - DataObject object = context.object; - CommandResult res = new CommandResult(); - if (result.isFailed()) { - res.setResult(result.getResult()); - object.processEvent(Event.OperationFailed); - } else { - object.processEvent(Event.OperationSuccessed); - } - future.complete(res); - return null; - } - - @Override - public AsyncCallFuture createTemplateFromVolumeAsync( - VolumeInfo volume, TemplateInfo template, DataStore store) { - AsyncCallFuture future = new AsyncCallFuture(); - DataObject templateOnStore = null; - try { - templateOnStore = store.create(template); - templateOnStore.processEvent(Event.CreateOnlyRequested); - - CopyTemplateContext context = new CopyTemplateContext(null, future, templateOnStore); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); - caller.setCallback(caller.getTarget().copyTemplateAsyncCallback(null, null)) - .setContext(context); - this.motionSrv.copyAsync(volume, templateOnStore, caller); - } catch (Exception e) { - s_logger.debug("Failed to create template: " + template.getId() + "from volume: " + volume.getId() + ", due to " + e.toString()); - if (templateOnStore != null) { - try { - templateOnStore.processEvent(Event.OperationFailed); - } catch (Exception e1) { - - } - } - CommandResult result = new CommandResult(); - result.setResult(e.toString()); - future.complete(result); - } - return future; - } -} diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/ImageDataFactoryImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java similarity index 61% rename from engine/storage/image/src/org/apache/cloudstack/storage/image/ImageDataFactoryImpl.java rename to engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java index 616e4789a27..e369c1c033e 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/ImageDataFactoryImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java @@ -21,42 +21,42 @@ package org.apache.cloudstack.storage.image; import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType; 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.ImageDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; -import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import org.apache.cloudstack.storage.image.store.TemplateObject; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.VMTemplateStoragePoolVO; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplatePoolDao; @Component -public class ImageDataFactoryImpl implements ImageDataFactory { - private static final Logger s_logger = Logger - .getLogger(ImageDataFactoryImpl.class); +public class TemplateDataFactoryImpl implements TemplateDataFactory { + private static final Logger s_logger = Logger.getLogger(TemplateDataFactoryImpl.class); @Inject VMTemplateDao imageDataDao; @Inject - ObjectInDataStoreManager objMap; - @Inject DataStoreManager storeMgr; @Inject VMTemplatePoolDao templatePoolDao; + @Inject + TemplateDataStoreDao templateStoreDao; + @Override public TemplateInfo getTemplate(long templateId, DataStore store) { VMTemplateVO templ = imageDataDao.findById(templateId); if (store == null) { - TemplateObject tmpl = TemplateObject.getTemplate(templ, null); + TemplateObject tmpl = TemplateObject.getTemplate(templ, null); return tmpl; } + // verify if the given input parameters are consistent with our db data. boolean found = false; if (store.getRole() == DataStoreRole.Primary) { VMTemplateStoragePoolVO templatePoolVO = templatePoolDao.findByPoolTemplate(store.getId(), templateId); @@ -64,28 +64,40 @@ public class ImageDataFactoryImpl implements ImageDataFactory { found = true; } } else { - DataObjectInStore obj = objMap.findObject(templ.getUuid(), DataObjectType.TEMPLATE, store.getUuid(), store.getRole()); - if (obj != null) { + TemplateDataStoreVO templateStoreVO = templateStoreDao.findByStoreTemplate(store.getId(), templateId); + if (templateStoreVO != null) { found = true; } } - + if (!found) { s_logger.debug("template " + templateId + " is not in store:" + store.getId() + ", type:" + store.getRole()); } - - TemplateObject tmpl = TemplateObject.getTemplate(templ, store); + + TemplateObject tmpl = TemplateObject.getTemplate(templ, store); return tmpl; } + @Override - public TemplateInfo getTemplate(long templateId) { - VMTemplateVO templ = imageDataDao.findById(templateId); - if (templ.getImageDataStoreId() == null) { - return this.getTemplate(templateId, null); - } - DataStore store = this.storeMgr.getDataStore(templ.getImageDataStoreId(), DataStoreRole.Image); + public TemplateInfo getTemplate(long templateId, DataStoreRole storeRole) { + TemplateDataStoreVO tmplStore = templateStoreDao.findByTemplate(templateId, storeRole); + DataStore store = null; + if (tmplStore != null) { + store = this.storeMgr.getDataStore(tmplStore.getDataStoreId(), storeRole); + } return this.getTemplate(templateId, store); } + + @Override + public TemplateInfo getTemplate(long templateId, DataStoreRole storeRole, Long zoneId) { + TemplateDataStoreVO tmplStore = templateStoreDao.findByTemplateZone(templateId, zoneId, storeRole); + DataStore store = null; + if (tmplStore != null) { + store = this.storeMgr.getDataStore(tmplStore.getDataStoreId(), storeRole); + } + return this.getTemplate(templateId, store); + } + @Override public TemplateInfo getTemplate(DataObject obj, DataStore store) { return this.getTemplate(obj.getId(), store); diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java new file mode 100644 index 00000000000..96c35f36f34 --- /dev/null +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java @@ -0,0 +1,610 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.image; + +import java.io.File; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService; +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +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.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateState; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; +import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.framework.async.AsyncRpcConext; +import org.apache.cloudstack.storage.command.CommandResult; +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.datastore.DataObjectManager; +import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; +import org.apache.cloudstack.storage.image.store.TemplateObject; +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.storage.ListTemplateAnswer; +import com.cloud.agent.api.storage.ListTemplateCommand; +import com.cloud.alert.AlertManager; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.StoragePool; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.VMTemplateZoneVO; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VMTemplatePoolDao; +import com.cloud.storage.dao.VMTemplateZoneDao; +import com.cloud.storage.template.TemplateConstants; +import com.cloud.storage.template.TemplateProp; +import com.cloud.template.TemplateManager; +import com.cloud.user.AccountManager; +import com.cloud.user.ResourceLimitService; +import com.cloud.utils.UriUtils; +import com.cloud.utils.fsm.NoTransitionException; + +@Component +public class TemplateServiceImpl implements TemplateService { + private static final Logger s_logger = Logger.getLogger(TemplateServiceImpl.class); + @Inject + ObjectInDataStoreManager _objectInDataStoreMgr; + @Inject + DataObjectManager _dataObjectMgr; + @Inject + DataStoreManager _storeMgr; + @Inject + DataMotionService _motionSrv; + @Inject + ResourceLimitService _resourceLimitMgr; + @Inject + AccountManager _accountMgr; + @Inject + AlertManager _alertMgr; + @Inject + VMTemplateDao _templateDao; + @Inject + TemplateDataStoreDao _vmTemplateStoreDao; + @Inject + DataCenterDao _dcDao = null; + @Inject + VMTemplateZoneDao _vmTemplateZoneDao; + @Inject + ClusterDao _clusterDao; + @Inject + TemplateDataFactory _templateFactory; + @Inject + VMTemplatePoolDao _tmpltPoolDao; + @Inject + EndPointSelector _epSelector; + @Inject + TemplateManager _tmpltMgr; + + class TemplateOpContext extends AsyncRpcConext { + final TemplateObject template; + final AsyncCallFuture future; + + public TemplateOpContext(AsyncCompletionCallback callback, TemplateObject template, + AsyncCallFuture future) { + super(callback); + this.template = template; + this.future = future; + } + + public TemplateObject getTemplate() { + return template; + } + + public AsyncCallFuture getFuture() { + return future; + } + + } + + @Override + public void createTemplateAsync(TemplateInfo template, DataStore store, + AsyncCompletionCallback callback) { + // persist template_store_ref entry + TemplateObject templateOnStore = (TemplateObject) store.create(template); + // update template_store_ref and template state + try { + templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.CreateOnlyRequested); + } catch (Exception e) { + TemplateApiResult result = new TemplateApiResult(templateOnStore); + result.setResult(e.toString()); + result.setSuccess(false); + if (callback != null) { + callback.complete(result); + } + return; + } + + TemplateOpContext context = new TemplateOpContext(callback, + templateOnStore, null); + + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().createTemplateCallback(null, null)).setContext(context); + store.getDriver().createAsync(templateOnStore, caller); + } + + @Override + public void downloadBootstrapSysTemplate(DataStore store) { + Set toBeDownloaded = new HashSet(); + + List rtngTmplts = _templateDao.listAllSystemVMTemplates(); + + for (VMTemplateVO rtngTmplt : rtngTmplts) { + toBeDownloaded.add(rtngTmplt); + } + + List availHypers = _clusterDao.getAvailableHypervisorInZone(store.getScope().getScopeId()); + if (availHypers.isEmpty()) { + /* + * This is for cloudzone, local secondary storage resource started + * before cluster created + */ + availHypers.add(HypervisorType.KVM); + } + /* Baremetal need not to download any template */ + availHypers.remove(HypervisorType.BareMetal); + availHypers.add(HypervisorType.None); // bug 9809: resume ISO + // download. + + for (VMTemplateVO template : toBeDownloaded) { + if (availHypers.contains(template.getHypervisorType())) { + // only download sys template applicable for current hypervisor + TemplateDataStoreVO tmpltHost = _vmTemplateStoreDao + .findByStoreTemplate(store.getId(), template.getId()); + if (tmpltHost == null || tmpltHost.getState() != ObjectInDataStoreStateMachine.State.Ready) { + TemplateInfo tmplt = _templateFactory.getTemplate(template.getId(), DataStoreRole.Image); + createTemplateAsync(tmplt, store, null); + } + } + } + } + + @Override + public void handleSysTemplateDownload(HypervisorType hostHyper, Long dcId) { + Set toBeDownloaded = new HashSet(); + List stores = _storeMgr.getImageStoresByScope(new ZoneScope(dcId)); + if (stores == null || stores.isEmpty()) { + return; + } + + /* Download all the templates in zone with the same hypervisortype */ + for (DataStore store : stores) { + 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) { + TemplateDataStoreVO tmpltHost = _vmTemplateStoreDao + .findByStoreTemplate(store.getId(), template.getId()); + if (tmpltHost == null || tmpltHost.getState() != ObjectInDataStoreStateMachine.State.Ready) { + TemplateInfo tmplt = _templateFactory.getTemplate(template.getId(), DataStoreRole.Image); + createTemplateAsync(tmplt, store, null); + } + } + } + } + + @Override + public void handleTemplateSync(DataStore store) { + if (store == null) { + s_logger.warn("Huh? image store is null"); + return; + } + long storeId = store.getId(); + Long zoneId = store.getScope().getScopeId(); + + Map templateInfos = listTemplate(store); + if (templateInfos == null) { + return; + } + + Set toBeDownloaded = new HashSet(); + List allTemplates = null; + if (zoneId == null) { + // region wide store + allTemplates = _templateDao.listAllActive(); + } else { + // zone wide store + allTemplates = _templateDao.listAllInZone(zoneId); + } + List rtngTmplts = _templateDao.listAllSystemVMTemplates(); + List defaultBuiltin = _templateDao.listDefaultBuiltinTemplates(); + + if (rtngTmplts != null) { + for (VMTemplateVO rtngTmplt : rtngTmplts) { + if (!allTemplates.contains(rtngTmplt)) { + allTemplates.add(rtngTmplt); + } + } + } + + if (defaultBuiltin != null) { + for (VMTemplateVO builtinTmplt : defaultBuiltin) { + if (!allTemplates.contains(builtinTmplt)) { + allTemplates.add(builtinTmplt); + } + } + } + + toBeDownloaded.addAll(allTemplates); + + for (VMTemplateVO tmplt : allTemplates) { + String uniqueName = tmplt.getUniqueName(); + TemplateDataStoreVO tmpltStore = _vmTemplateStoreDao.findByStoreTemplate(storeId, tmplt.getId()); + if (templateInfos.containsKey(uniqueName)) { + TemplateProp tmpltInfo = templateInfos.remove(uniqueName); + toBeDownloaded.remove(tmplt); + if (tmpltStore != null) { + s_logger.info("Template Sync found " + uniqueName + " already in the image store"); + if (tmpltStore.getDownloadState() != Status.DOWNLOADED) { + tmpltStore.setErrorString(""); + } + if (tmpltInfo.isCorrupted()) { + 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 image store: " + tmpltStore.getDataStoreId(); + s_logger.warn(msg); + } else { + toBeDownloaded.add(tmplt); + } + + } else { + tmpltStore.setDownloadPercent(100); + tmpltStore.setDownloadState(Status.DOWNLOADED); + tmpltStore.setInstallPath(tmpltInfo.getInstallPath()); + tmpltStore.setSize(tmpltInfo.getSize()); + tmpltStore.setPhysicalSize(tmpltInfo.getPhysicalSize()); + tmpltStore.setLastUpdated(new Date()); + // update size in vm_template table + VMTemplateVO tmlpt = _templateDao.findById(tmplt.getId()); + tmlpt.setSize(tmpltInfo.getSize()); + _templateDao.update(tmplt.getId(), tmlpt); + + if (tmpltInfo.getSize() > 0 && tmplt.getUrl() != null) { + long accountId = tmplt.getAccountId(); + try { + _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(accountId), + com.cloud.configuration.Resource.ResourceType.secondary_storage, + tmpltInfo.getSize() - UriUtils.getRemoteSize(tmplt.getUrl())); + } catch (ResourceAllocationException e) { + s_logger.warn(e.getMessage()); + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, zoneId, null, + e.getMessage(), e.getMessage()); + } finally { + _resourceLimitMgr.recalculateResourceCount(accountId, _accountMgr.getAccount(accountId) + .getDomainId(), com.cloud.configuration.Resource.ResourceType.secondary_storage + .getOrdinal()); + } + } + } + _vmTemplateStoreDao.update(tmpltStore.getId(), tmpltStore); + } else { + 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()); + tmpltStore.setDataStoreRole(store.getRole()); + _vmTemplateStoreDao.persist(tmpltStore); + + // update size in vm_template table + VMTemplateVO tmlpt = _templateDao.findById(tmplt.getId()); + tmlpt.setSize(tmpltInfo.getSize()); + _templateDao.update(tmplt.getId(), tmlpt); + associateTemplateToZone(tmplt.getId(), zoneId); + + + } + } else { + if (tmpltStore != null) { + s_logger.info("Template Sync did not find " + uniqueName + " on image store " + storeId + + ", may request download based on available hypervisor types"); + s_logger.info("Removing leftover template " + uniqueName + " entry from template store table"); + // remove those leftover entries + _vmTemplateStoreDao.remove(tmpltStore.getId()); + } + } + } + + if (toBeDownloaded.size() > 0) { + /* Only download templates whose hypervirsor type is in the zone */ + List availHypers = _clusterDao.getAvailableHypervisorInZone(zoneId); + if (availHypers.isEmpty()) { + /* + * This is for cloudzone, local secondary storage resource + * started before cluster created + */ + availHypers.add(HypervisorType.KVM); + } + /* Baremetal need not to download any template */ + availHypers.remove(HypervisorType.BareMetal); + availHypers.add(HypervisorType.None); // bug 9809: resume ISO + // download. + for (VMTemplateVO tmplt : toBeDownloaded) { + if (tmplt.getUrl() == null) { // If url is null we can't + // initiate the download + continue; + } + + // if this is private template, skip + if (!tmplt.isPublicTemplate() && !tmplt.isFeatured()) { + continue; + } + if (availHypers.contains(tmplt.getHypervisorType())) { + s_logger.info("Downloading template " + tmplt.getUniqueName() + " to image store " + + store.getName()); + associateTemplateToZone(tmplt.getId(), zoneId); + TemplateInfo tmpl = _templateFactory.getTemplate(tmplt.getId(), DataStoreRole.Image); + createTemplateAsync(tmpl, store, null); + } + } + } + + for (String uniqueName : templateInfos.keySet()) { + TemplateProp tInfo = templateInfos.get(uniqueName); + if (_tmpltMgr.templateIsDeleteable(tInfo.getId())) { + // we cannot directly call deleteTemplateSync here to + // reuse delete logic since in this case, our db does not have + // this template at all. + TemplateObjectTO tmplTO = new TemplateObjectTO(); + tmplTO.setDataStore(store.getTO()); + tmplTO.setPath(tInfo.getInstallPath()); + tmplTO.setId(tInfo.getId()); + DeleteCommand dtCommand = new DeleteCommand(tmplTO); + EndPoint ep = _epSelector.select(store); + Answer answer = ep.sendMessage(dtCommand); + if (answer == null || !answer.getResult()) { + s_logger.info("Failed to deleted template at store: " + store.getName()); + + } else { + String description = "Deleted template " + tInfo.getTemplateName() + " on secondary storage " + + storeId; + s_logger.info(description); + } + + } + } + + } + + // persist entry in template_zone_ref table. zoneId can be empty for + // region-wide image store, in that case, + // we will associate the template to all the zones. + private void associateTemplateToZone(long templateId, Long zoneId) { + 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, templateId); + if (tmpltZoneVO == null) { + tmpltZoneVO = new VMTemplateZoneVO(id, templateId, new Date()); + _vmTemplateZoneDao.persist(tmpltZoneVO); + } else { + tmpltZoneVO.setLastUpdated(new Date()); + _vmTemplateZoneDao.update(tmpltZoneVO.getId(), tmpltZoneVO); + } + } + } + + private Map listTemplate(DataStore ssStore) { + ListTemplateCommand cmd = new ListTemplateCommand(ssStore.getTO()); + EndPoint ep = _epSelector.select(ssStore); + Answer answer = ep.sendMessage(cmd); + if (answer != null && answer.getResult()) { + ListTemplateAnswer tanswer = (ListTemplateAnswer) answer; + return tanswer.getTemplateInfo(); + } else { + if (s_logger.isDebugEnabled()) { + s_logger.debug("can not list template for secondary storage host " + ssStore.getId()); + } + } + + return null; + } + + protected Void createTemplateCallback(AsyncCallbackDispatcher callback, + TemplateOpContext context) { + TemplateObject template = context.getTemplate(); + AsyncCompletionCallback parentCallback = context.getParentCallback(); + TemplateApiResult result = new TemplateApiResult(template); + CreateCmdResult callbackResult = callback.getResult(); + if (callbackResult.isFailed()) { + template.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed); + result.setResult(callbackResult.getResult()); + if (parentCallback != null) { + parentCallback.complete(result); + } + return null; + } + + try { + template.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed); + } catch (Exception e) { + result.setResult(e.toString()); + if (parentCallback != null) { + parentCallback.complete(result); + } + return null; + } + + if (parentCallback != null) { + parentCallback.complete(result); + } + return null; + } + + @Override + public AsyncCallFuture deleteTemplateAsync(TemplateInfo template) { + TemplateObject to = (TemplateObject) template; + // update template_store_ref status + to.processEvent(ObjectInDataStoreStateMachine.Event.DestroyRequested); + + AsyncCallFuture future = new AsyncCallFuture(); + + TemplateOpContext context = new TemplateOpContext(null, to, future); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().deleteTemplateCallback(null, null)).setContext(context); + to.getDataStore().getDriver().deleteAsync(to, caller); + return future; + } + + public Void deleteTemplateCallback(AsyncCallbackDispatcher callback, + TemplateOpContext context) { + CommandResult result = callback.getResult(); + TemplateObject vo = context.getTemplate(); + if (result.isSuccess()) { + vo.processEvent(Event.OperationSuccessed); + } else { + vo.processEvent(Event.OperationFailed); + } + TemplateApiResult apiResult = new TemplateApiResult(vo); + apiResult.setResult(result.getResult()); + apiResult.setSuccess(result.isSuccess()); + context.future.complete(apiResult); + return null; + } + + private AsyncCallFuture copyAsync(DataObject source, TemplateInfo template, DataStore store) { + AsyncCallFuture future = new AsyncCallFuture(); + DataObject templateOnStore = store.create(template); + templateOnStore.processEvent(Event.CreateOnlyRequested); + + TemplateOpContext context = new TemplateOpContext(null, + (TemplateObject) templateOnStore, future); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().copyTemplateCallBack(null, null)).setContext(context); + _motionSrv.copyAsync(source, templateOnStore, caller); + return future; + } + + @Override + public AsyncCallFuture createTemplateFromSnapshotAsync(SnapshotInfo snapshot, + TemplateInfo template, DataStore store) { + return copyAsync(snapshot, template, store); + } + + @Override + public AsyncCallFuture createTemplateFromVolumeAsync(VolumeInfo volume, TemplateInfo template, + DataStore store) { + return copyAsync(volume, template, store); + } + + @Override + public AsyncCallFuture copyTemplate(TemplateInfo srcTemplate, DataStore destStore) { + return copyAsync(srcTemplate, srcTemplate, destStore); + } + + @Override + public AsyncCallFuture prepareTemplateOnPrimary(TemplateInfo srcTemplate, StoragePool pool) { + return copyAsync(srcTemplate, srcTemplate, (DataStore) pool); + } + + protected Void copyTemplateCallBack(AsyncCallbackDispatcher callback, + TemplateOpContext context) { + TemplateInfo destTemplate = context.getTemplate(); + CopyCommandResult result = callback.getResult(); + AsyncCallFuture future = context.getFuture(); + TemplateApiResult res = new TemplateApiResult(destTemplate); + try { + if (result.isFailed()) { + res.setResult(result.getResult()); + destTemplate.processEvent(Event.OperationFailed); + } else { + destTemplate.processEvent(Event.OperationSuccessed, result.getAnswer()); + } + future.complete(res); + } catch (Exception e) { + s_logger.debug("Failed to process copy template callback", e); + res.setResult(e.toString()); + future.complete(res); + } + + return null; + } + + @Override + public void addSystemVMTemplatesToSecondary(DataStore store) { + long storeId = store.getId(); + List rtngTmplts = _templateDao.listAllSystemVMTemplates(); + for (VMTemplateVO tmplt : rtngTmplts) { + TemplateDataStoreVO tmpltStore = _vmTemplateStoreDao.findByStoreTemplate(storeId, tmplt.getId()); + if (tmpltStore == null) { + tmpltStore = new TemplateDataStoreVO(storeId, tmplt.getId(), new Date(), 100, Status.DOWNLOADED, null, + null, null, TemplateConstants.DEFAULT_SYSTEM_VM_TEMPLATE_PATH + tmplt.getId() + File.separator, + tmplt.getUrl()); + tmpltStore.setSize(0L); + tmpltStore.setPhysicalSize(0); // no size information for + // pre-seeded system vm templates + tmpltStore.setDataStoreRole(store.getRole()); + _vmTemplateStoreDao.persist(tmpltStore); + } + } + } +} diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/downloader/ImageDownloader.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/downloader/ImageDownloader.java deleted file mode 100644 index af572d49a5e..00000000000 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/downloader/ImageDownloader.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.image.downloader; - -import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; - -public interface ImageDownloader { - public void downloadImage(TemplateInfo template); -} diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java deleted file mode 100644 index 4c16f2fe4b1..00000000000 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.image.driver; - -import java.util.List; -import java.util.Set; - -import javax.inject.Inject; - -import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; -import org.apache.cloudstack.framework.async.AsyncCompletionCallback; -import org.apache.cloudstack.framework.async.AsyncRpcConext; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.cloudstack.storage.image.ImageDataStoreDriver; -import org.apache.log4j.Logger; - -import com.cloud.agent.AgentManager; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.DeleteSnapshotBackupCommand; -import com.cloud.agent.api.storage.DeleteVolumeCommand; -import com.cloud.agent.api.to.S3TO; -import com.cloud.agent.api.to.SwiftTO; -import com.cloud.host.HostVO; -import com.cloud.host.dao.HostDao; -import com.cloud.storage.RegisterVolumePayload; -import com.cloud.storage.SnapshotVO; -import com.cloud.storage.Storage.ImageFormat; -import com.cloud.storage.VMTemplateStorageResourceAssoc; -import com.cloud.storage.VMTemplateVO; -import com.cloud.storage.VMTemplateZoneVO; -import com.cloud.storage.VolumeHostVO; -import com.cloud.storage.VolumeVO; -import com.cloud.storage.dao.SnapshotDao; -import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VMTemplateHostDao; -import com.cloud.storage.dao.VMTemplateZoneDao; -import com.cloud.storage.dao.VolumeDao; -import com.cloud.storage.dao.VolumeHostDao; -import com.cloud.storage.download.DownloadMonitor; -import com.cloud.storage.s3.S3Manager; -import com.cloud.storage.snapshot.SnapshotManager; -import com.cloud.storage.swift.SwiftManager; -import com.cloud.utils.exception.CloudRuntimeException; - -public class AncientImageDataStoreDriverImpl implements ImageDataStoreDriver { - private static final Logger s_logger = Logger - .getLogger(AncientImageDataStoreDriverImpl.class); - @Inject - VMTemplateZoneDao templateZoneDao; - @Inject - VMTemplateDao templateDao; - @Inject DownloadMonitor _downloadMonitor; - @Inject - VMTemplateHostDao _vmTemplateHostDao; - @Inject VolumeDao volumeDao; - @Inject VolumeHostDao volumeHostDao; - @Inject HostDao hostDao; - @Inject SnapshotDao snapshotDao; - @Inject AgentManager agentMgr; - @Inject SnapshotManager snapshotMgr; - @Inject PrimaryDataStoreDao primaryDataStoreDao; - @Inject - private SwiftManager _swiftMgr; - @Inject - private S3Manager _s3Mgr; - @Override - public String grantAccess(DataObject data, EndPoint ep) { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean revokeAccess(DataObject data, EndPoint ep) { - // TODO Auto-generated method stub - return false; - } - - @Override - public Set listObjects(DataStore store) { - // TODO Auto-generated method stub - return null; - } - - class CreateContext extends AsyncRpcConext { - final DataObject data; - public CreateContext(AsyncCompletionCallback callback, DataObject data) { - super(callback); - this.data = data; - } - } - - @Override - public void createAsync(DataObject data, - AsyncCompletionCallback callback) { - if (data.getType() == DataObjectType.TEMPLATE) { - List templateZones = this.templateZoneDao.listByTemplateId(data.getId()); - for (VMTemplateZoneVO templateZone : templateZones) { - VMTemplateVO template = this.templateDao.findById(data.getId()); - _downloadMonitor.downloadTemplateToStorage(template, templateZone.getZoneId()); - } - } else if (data.getType() == DataObjectType.VOLUME) { - VolumeVO vol = this.volumeDao.findById(data.getId()); - VolumeInfo volInfo = (VolumeInfo)data; - RegisterVolumePayload payload = (RegisterVolumePayload)volInfo.getpayload(); - _downloadMonitor.downloadVolumeToStorage(vol, vol.getDataCenterId(), payload.getUrl(), - payload.getChecksum(), ImageFormat.valueOf(payload.getFormat().toUpperCase())); - } - - CreateCmdResult result = new CreateCmdResult(null, null); - callback.complete(result); - } - - private void deleteVolume(DataObject data, AsyncCompletionCallback callback) { - // TODO Auto-generated method stub - VolumeVO vol = volumeDao.findById(data.getId()); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Expunging " + vol); - } - - // Find out if the volume is present on secondary storage - VolumeHostVO volumeHost = volumeHostDao.findByVolumeId(vol.getId()); - if (volumeHost != null) { - if (volumeHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { - HostVO ssHost = hostDao.findById(volumeHost.getHostId()); - DeleteVolumeCommand dtCommand = new DeleteVolumeCommand( - ssHost.getStorageUrl(), volumeHost.getInstallPath()); - Answer answer = agentMgr.sendToSecStorage(ssHost, dtCommand); - if (answer == null || !answer.getResult()) { - s_logger.debug("Failed to delete " - + volumeHost - + " due to " - + ((answer == null) ? "answer is null" : answer - .getDetails())); - return; - } - } else if (volumeHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS) { - s_logger.debug("Volume: " + vol.getName() - + " is currently being uploaded; cant' delete it."); - throw new CloudRuntimeException( - "Please specify a volume that is not currently being uploaded."); - } - volumeHostDao.remove(volumeHost.getId()); - volumeDao.remove(vol.getId()); - CommandResult result = new CommandResult(); - callback.complete(result); - return; - } - } - - private void deleteTemplate(DataObject data, AsyncCompletionCallback callback) { - - } - - private void deleteSnapshot(DataObject data, AsyncCompletionCallback callback) { - Long snapshotId = data.getId(); - SnapshotVO snapshot = this.snapshotDao.findByIdIncludingRemoved(snapshotId); - CommandResult result = new CommandResult(); - if (snapshot == null) { - s_logger.debug("Destroying snapshot " + snapshotId + " backup failed due to unable to find snapshot "); - result.setResult("Unable to find snapshot: " + snapshotId); - callback.complete(result); - return; - } - - try { - String secondaryStoragePoolUrl = this.snapshotMgr.getSecondaryStorageURL(snapshot); - Long dcId = snapshot.getDataCenterId(); - Long accountId = snapshot.getAccountId(); - Long volumeId = snapshot.getVolumeId(); - - String backupOfSnapshot = snapshot.getBackupSnapshotId(); - if (backupOfSnapshot == null) { - callback.complete(result); - return; - } - SwiftTO swift = _swiftMgr.getSwiftTO(snapshot.getSwiftId()); - S3TO s3 = _s3Mgr.getS3TO(); - VolumeVO volume = volumeDao.findById(volumeId); - StoragePoolVO pool = primaryDataStoreDao.findById(volume.getPoolId()); - DeleteSnapshotBackupCommand cmd = new DeleteSnapshotBackupCommand( - pool, swift, s3, secondaryStoragePoolUrl, dcId, accountId, volumeId, - backupOfSnapshot, false); - Answer answer = agentMgr.sendToSSVM(dcId, cmd); - - if ((answer != null) && answer.getResult()) { - snapshot.setBackupSnapshotId(null); - snapshotDao.update(snapshotId, snapshot); - } else if (answer != null) { - result.setResult(answer.getDetails()); - } - } catch (Exception e) { - s_logger.debug("failed to delete snapshot: " + snapshotId + ": " + e.toString()); - result.setResult(e.toString()); - } - callback.complete(result); - } - - @Override - public void deleteAsync(DataObject data, - AsyncCompletionCallback callback) { - if (data.getType() == DataObjectType.VOLUME) { - deleteVolume(data, callback); - } else if (data.getType() == DataObjectType.TEMPLATE) { - deleteTemplate(data, callback); - } else if (data.getType() == DataObjectType.SNAPSHOT) { - deleteSnapshot(data, callback); - } - } - - @Override - public void copyAsync(DataObject srcdata, DataObject destData, - AsyncCompletionCallback callback) { - // TODO Auto-generated method stub - - } - - @Override - public boolean canCopy(DataObject srcData, DataObject destData) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void resize(DataObject data, - AsyncCompletionCallback callback) { - // TODO Auto-generated method stub - - } - -} diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/DefaultImageDataStoreDriverImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/DefaultImageDataStoreDriverImpl.java deleted file mode 100644 index 3d46c73cde2..00000000000 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/DefaultImageDataStoreDriverImpl.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.image.driver; - -import java.util.Set; - -import javax.inject.Inject; - -import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; -import org.apache.cloudstack.framework.async.AsyncCompletionCallback; -import org.apache.cloudstack.storage.command.CreateObjectAnswer; -import org.apache.cloudstack.storage.command.CreateObjectCommand; -import org.apache.cloudstack.storage.endpoint.EndPointSelector; -import org.apache.cloudstack.storage.image.ImageDataStoreDriver; - -import com.cloud.storage.dao.VMTemplateDao; - -//http-read-only based image store -public class DefaultImageDataStoreDriverImpl implements ImageDataStoreDriver { - @Inject - EndPointSelector selector; - @Inject - VMTemplateDao imageDataDao; - public DefaultImageDataStoreDriverImpl() { - } - - @Override - public String grantAccess(DataObject data, EndPoint ep) { - return data.getUri(); - } - - @Override - public boolean revokeAccess(DataObject data, EndPoint ep) { - // TODO Auto-generated method stub - return true; - } - - @Override - public Set listObjects(DataStore store) { - // TODO Auto-generated method stub - return null; - } - - @Override - public void createAsync(DataObject data, - AsyncCompletionCallback callback) { - //for default http data store, can create http based template/iso - CreateCmdResult result = new CreateCmdResult("", null); - if (!data.getUri().startsWith("http")) { - result.setResult("can't register an image which is not a http link"); - callback.complete(result); - return; - } - - if (data.getSize() == null && data.getType() == DataObjectType.TEMPLATE) { - //the template size is unknown during registration, need to find out the size of template - EndPoint ep = selector.select(data); - if (ep == null) { - result.setResult("can't find storage client for:" + data.getId() + "," + data.getType()); - callback.complete(result); - return; - } - CreateObjectCommand createCmd = new CreateObjectCommand(data.getUri()); - CreateObjectAnswer answer = (CreateObjectAnswer)ep.sendMessage(createCmd); - if (answer.getResult()) { - //update imagestorevo - - result = new CreateCmdResult(answer.getPath(), answer.getSize()); - } else { - result.setResult(answer.getDetails()); - } - - } - - callback.complete(result); - } - - @Override - public void deleteAsync(DataObject data, - AsyncCompletionCallback callback) { - CommandResult result = new CommandResult(); - callback.complete(result); - } - - @Override - public boolean canCopy(DataObject srcData, DataObject destData) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void copyAsync(DataObject srcdata, DataObject destData, - AsyncCompletionCallback callback) { - // TODO Auto-generated method stub - - } - - @Override - public void resize(DataObject data, - AsyncCompletionCallback callback) { - // TODO Auto-generated method stub - - } -} diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageDataManagerImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageDataManagerImpl.java deleted file mode 100644 index 83e98878158..00000000000 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageDataManagerImpl.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.image.manager; - -import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent; -import org.apache.cloudstack.engine.subsystem.api.storage.TemplateState; -import org.springframework.stereotype.Component; - -import com.cloud.storage.VMTemplateVO; -import com.cloud.utils.fsm.StateMachine2; - -@Component -public class ImageDataManagerImpl implements ImageDataManager { - private final StateMachine2 - stateMachine = new StateMachine2(); - - public ImageDataManagerImpl() { - stateMachine.addTransition(TemplateState.Allocated, TemplateEvent.CreateRequested, TemplateState.Creating); - stateMachine.addTransition(TemplateState.Creating, TemplateEvent.CreateRequested, TemplateState.Creating); - stateMachine.addTransition(TemplateState.Creating, TemplateEvent.OperationSucceeded, TemplateState.Ready); - stateMachine.addTransition(TemplateState.Creating, TemplateEvent.OperationFailed, TemplateState.Allocated); - stateMachine.addTransition(TemplateState.Creating, TemplateEvent.DestroyRequested, TemplateState.Destroying); - stateMachine.addTransition(TemplateState.Ready, TemplateEvent.DestroyRequested, TemplateState.Destroying); - stateMachine.addTransition(TemplateState.Allocated, TemplateEvent.DestroyRequested, TemplateState.Destroying); - stateMachine.addTransition(TemplateState.Destroying, TemplateEvent.DestroyRequested, TemplateState.Destroying); - stateMachine.addTransition(TemplateState.Destroying, TemplateEvent.OperationFailed, TemplateState.Destroying); - stateMachine.addTransition(TemplateState.Destroying, TemplateEvent.OperationSucceeded, TemplateState.Destroyed); - } - - @Override - public StateMachine2 getStateMachine() { - return stateMachine; - } -} diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageDataStoreManagerImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageDataStoreManagerImpl.java deleted file mode 100644 index bc546f8d0c1..00000000000 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageDataStoreManagerImpl.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.image.manager; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.annotation.PostConstruct; -import javax.inject.Inject; - -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.ImageDataStoreProvider; -import org.apache.cloudstack.storage.image.ImageDataStoreDriver; -import org.apache.cloudstack.storage.image.datastore.ImageDataStore; -import org.apache.cloudstack.storage.image.datastore.ImageDataStoreManager; -import org.apache.cloudstack.storage.image.db.ImageDataStoreDao; -import org.apache.cloudstack.storage.image.db.ImageDataStoreVO; -import org.apache.cloudstack.storage.image.store.DefaultImageDataStoreImpl; -import org.springframework.stereotype.Component; - -import com.cloud.storage.dao.VMTemplateDao; - -@Component -public class ImageDataStoreManagerImpl implements ImageDataStoreManager { - @Inject - ImageDataStoreDao dataStoreDao; - @Inject - VMTemplateDao imageDataDao; - @Inject - DataStoreProviderManager providerManager; - Map driverMaps; - - @PostConstruct - public void config() { - driverMaps = new HashMap(); - } - - @Override - public ImageDataStore getImageDataStore(long dataStoreId) { - ImageDataStoreVO dataStore = dataStoreDao.findById(dataStoreId); - String providerName = dataStore.getProviderName(); - ImageDataStoreProvider provider = (ImageDataStoreProvider)providerManager.getDataStoreProvider(providerName); - ImageDataStore imgStore = DefaultImageDataStoreImpl.getDataStore(dataStore, - driverMaps.get(provider.getName()), provider - ); - // TODO Auto-generated method stub - return imgStore; - } - - @Override - public boolean registerDriver(String providerName, ImageDataStoreDriver driver) { - if (driverMaps.containsKey(providerName)) { - return false; - } - driverMaps.put(providerName, driver); - return true; - } - - @Override - public ImageDataStore getImageDataStore(String uuid) { - ImageDataStoreVO dataStore = dataStoreDao.findByUuid(uuid); - return getImageDataStore(dataStore.getId()); - } - - @Override - public List getList() { - List stores = dataStoreDao.listAll(); - List imageStores = new ArrayList(); - for (ImageDataStoreVO store : stores) { - imageStores.add(getImageDataStore(store.getId())); - } - return imageStores; - } - -} 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 new file mode 100644 index 00000000000..64ef78f8e09 --- /dev/null +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageStoreProviderManagerImpl.java @@ -0,0 +1,130 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.image.manager; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; + +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; +import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity; +import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager; +import org.apache.cloudstack.storage.image.store.ImageStoreImpl; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.storage.ScopeType; +import com.cloud.storage.dao.VMTemplateDao; + +@Component +public class ImageStoreProviderManagerImpl implements ImageStoreProviderManager { + private static final Logger s_logger = Logger.getLogger(ImageStoreProviderManagerImpl.class); + @Inject + ImageStoreDao dataStoreDao; + @Inject + VMTemplateDao imageDataDao; + @Inject + DataStoreProviderManager providerManager; + Map driverMaps; + + @PostConstruct + public void config() { + driverMaps = new HashMap(); + } + + @Override + public ImageStoreEntity getImageStore(long dataStoreId) { + ImageStoreVO dataStore = dataStoreDao.findById(dataStoreId); + String providerName = dataStore.getProviderName(); + ImageStoreProvider provider = (ImageStoreProvider) providerManager.getDataStoreProvider(providerName); + ImageStoreEntity imgStore = ImageStoreImpl + .getDataStore(dataStore, driverMaps.get(provider.getName()), provider); + return imgStore; + } + + @Override + public boolean registerDriver(String providerName, ImageStoreDriver driver) { + if (driverMaps.containsKey(providerName)) { + return false; + } + driverMaps.put(providerName, driver); + return true; + } + + @Override + public ImageStoreEntity getImageStore(String uuid) { + ImageStoreVO dataStore = dataStoreDao.findByUuid(uuid); + return getImageStore(dataStore.getId()); + } + + @Override + public List listImageStores() { + List stores = dataStoreDao.listImageStores(); + List imageStores = new ArrayList(); + for (ImageStoreVO store : stores) { + imageStores.add(getImageStore(store.getId())); + } + return imageStores; + } + + @Override + public List listImageStoresByScope(ZoneScope scope) { + List stores = dataStoreDao.findByScope(scope); + List imageStores = new ArrayList(); + for (ImageStoreVO store : stores) { + imageStores.add(getImageStore(store.getId())); + } + return imageStores; + } + + @Override + public List listImageStoreByProvider(String provider) { + List stores = dataStoreDao.findByProvider(provider); + List imageStores = new ArrayList(); + for (ImageStoreVO store : stores) { + imageStores.add(getImageStore(store.getId())); + } + return imageStores; + } + + @Override + public List listImageCacheStores(Scope scope) { + if (scope.getScopeType() != ScopeType.ZONE) { + s_logger.debug("only support zone wide image cache stores"); + return null; + } + List stores = dataStoreDao.findImageCacheByScope(new ZoneScope(scope.getScopeId())); + List imageStores = new ArrayList(); + for (ImageStoreVO store : stores) { + imageStores.add(getImageStore(store.getId())); + } + return imageStores; + } +} diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/DefaultImageDataStoreImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java similarity index 50% rename from engine/storage/image/src/org/apache/cloudstack/storage/image/store/DefaultImageDataStoreImpl.java rename to engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java index 6eefc6f43f8..6d8e8e59c6f 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/DefaultImageDataStoreImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java @@ -18,112 +18,113 @@ */ package org.apache.cloudstack.storage.image.store; +import java.util.Date; import java.util.Set; +import java.util.concurrent.ExecutionException; import javax.inject.Inject; +import com.cloud.capacity.dao.CapacityDao; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole; -import org.apache.cloudstack.engine.subsystem.api.storage.ImageDataStoreProvider; +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.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; +import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.storage.command.CommandResult; import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; -import org.apache.cloudstack.storage.image.ImageDataStoreDriver; -import org.apache.cloudstack.storage.image.datastore.ImageDataStore; -import org.apache.cloudstack.storage.image.db.ImageDataStoreVO; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; +import org.apache.cloudstack.storage.image.ImageStoreDriver; +import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity; +import org.apache.log4j.Logger; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.utils.component.ComponentContext; -import com.cloud.utils.storage.encoding.EncodingType; - -public class DefaultImageDataStoreImpl implements ImageDataStore { +public class ImageStoreImpl implements ImageStoreEntity { + private static final Logger s_logger = Logger.getLogger(ImageStoreImpl.class); @Inject VMTemplateDao imageDao; @Inject private ObjectInDataStoreManager objectInStoreMgr; - protected ImageDataStoreDriver driver; - protected ImageDataStoreVO imageDataStoreVO; - protected ImageDataStoreProvider provider; - boolean needDownloadToCacheStorage = false; + @Inject + private CapacityDao capacityDao; + protected ImageStoreDriver driver; + protected ImageStoreVO imageDataStoreVO; + protected ImageStoreProvider provider; - public DefaultImageDataStoreImpl() { - + public ImageStoreImpl() { + super(); } - - protected void configure(ImageDataStoreVO dataStoreVO, ImageDataStoreDriver imageDataStoreDriver, - ImageDataStoreProvider provider) { + + protected void configure(ImageStoreVO dataStoreVO, ImageStoreDriver imageDataStoreDriver, + ImageStoreProvider provider) { this.driver = imageDataStoreDriver; this.imageDataStoreVO = dataStoreVO; this.provider = provider; } - public static ImageDataStore getDataStore(ImageDataStoreVO dataStoreVO, ImageDataStoreDriver imageDataStoreDriver, - ImageDataStoreProvider provider) { - DefaultImageDataStoreImpl instance = (DefaultImageDataStoreImpl)ComponentContext.inject(DefaultImageDataStoreImpl.class); + public static ImageStoreEntity getDataStore(ImageStoreVO dataStoreVO, ImageStoreDriver imageDataStoreDriver, + ImageStoreProvider provider) { + ImageStoreImpl instance = ComponentContext.inject(ImageStoreImpl.class); instance.configure(dataStoreVO, imageDataStoreDriver, provider); return instance; } @Override public Set listTemplates() { - // TODO Auto-generated method stub return null; } @Override public DataStoreDriver getDriver() { - // TODO Auto-generated method stub return this.driver; } @Override public DataStoreRole getRole() { - // TODO Auto-generated method stub - return DataStoreRole.Image; + return this.imageDataStoreVO.getRole(); } + @Override public long getId() { - // TODO Auto-generated method stub return this.imageDataStoreVO.getId(); } @Override public String getUri() { - return this.imageDataStoreVO.getProtocol() + "://" + "?" + EncodingType.ROLE + "=" + this.getRole(); + return this.imageDataStoreVO.getUrl(); } @Override public Scope getScope() { - return new ZoneScope(imageDataStoreVO.getDcId()); + return new ZoneScope(imageDataStoreVO.getDataCenterId()); } @Override public TemplateInfo getTemplate(long templateId) { - // TODO Auto-generated method stub return null; } @Override public VolumeInfo getVolume(long volumeId) { - // TODO Auto-generated method stub return null; } @Override public SnapshotInfo getSnapshot(long snapshotId) { - // TODO Auto-generated method stub return null; } @Override public boolean exists(DataObject object) { - return (objectInStoreMgr.findObject(object, - this) != null) ? true : false; + return (objectInStoreMgr.findObject(object, this) != null) ? true : false; } @Override @@ -131,6 +132,10 @@ public class DefaultImageDataStoreImpl implements ImageDataStore { return this.imageDataStoreVO.getUuid(); } + public Date getCreated() { + return this.imageDataStoreVO.getCreated(); + } + @Override public DataObject create(DataObject obj) { DataObject object = objectInStoreMgr.create(obj, this); @@ -139,7 +144,55 @@ public class DefaultImageDataStoreImpl implements ImageDataStore { @Override public boolean delete(DataObject obj) { - // TODO Auto-generated method stub - return false; + AsyncCallFuture future = new AsyncCallFuture(); + this.driver.deleteAsync(obj, future); + try { + future.get(); + } catch (InterruptedException e) { + s_logger.debug("failed delete obj", e); + return false; + } catch (ExecutionException e) { + s_logger.debug("failed delete obj", e); + return false; + } + objectInStoreMgr.delete(obj); + return true; } + + @Override + public String getName() { + return imageDataStoreVO.getName(); + } + + @Override + public Long getDataCenterId() { + return imageDataStoreVO.getDataCenterId(); + } + + @Override + public String getProviderName() { + return imageDataStoreVO.getProviderName(); + } + + @Override + public String getProtocol() { + return imageDataStoreVO.getProtocol(); + } + + @Override + public DataStoreTO getTO() { + return getDriver().getStoreTO(this); + } + + @Override + public String getMountPoint() { + return imageDataStoreVO.getParent(); + } + + @Override + public String createEntityExtractUrl(String installPath, ImageFormat format) { + return driver.createEntityExtractUrl(this, installPath, format); + } + + } diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java index b6c20046c1c..74a7d43e00b 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java @@ -18,40 +18,52 @@ */ package org.apache.cloudstack.storage.image.store; +import java.util.Date; +import java.util.Map; + import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat; +import org.apache.cloudstack.storage.command.CopyCmdAnswer; import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; -import org.apache.cloudstack.storage.image.manager.ImageDataManager; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; +import org.apache.cloudstack.storage.to.TemplateObjectTO; import org.apache.log4j.Logger; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataTO; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.Storage.TemplateType; +import com.cloud.storage.VMTemplateStoragePoolVO; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplatePoolDao; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.fsm.NoTransitionException; -import com.cloud.utils.storage.encoding.EncodingType; public class TemplateObject implements TemplateInfo { - private static final Logger s_logger = Logger - .getLogger(TemplateObject.class); + private static final Logger s_logger = Logger.getLogger(TemplateObject.class); private VMTemplateVO imageVO; private DataStore dataStore; @Inject - ImageDataManager imageMgr; - @Inject VMTemplateDao imageDao; @Inject - ObjectInDataStoreManager ojbectInStoreMgr; - @Inject VMTemplatePoolDao templatePoolDao; + ObjectInDataStoreManager objectInStoreMgr; + @Inject + VMTemplatePoolDao templatePoolDao; + @Inject + TemplateDataStoreDao templateStoreDao; public TemplateObject() { } @@ -67,10 +79,6 @@ public class TemplateObject implements TemplateInfo { return to; } - public void setImageStoreId(long id) { - this.imageVO.setImageDataStoreId(id); - } - public void setSize(Long size) { this.imageVO.setSize(size); } @@ -84,6 +92,11 @@ public class TemplateObject implements TemplateInfo { return this.dataStore; } + @Override + public String getUniqueName() { + return this.imageVO.getUniqueName(); + } + @Override public long getId() { return this.imageVO.getId(); @@ -97,27 +110,9 @@ public class TemplateObject implements TemplateInfo { @Override public String getUri() { VMTemplateVO image = imageDao.findById(this.imageVO.getId()); - if (this.dataStore == null) { - return image.getUrl(); - } else { - DataObjectInStore obj = ojbectInStoreMgr.findObject(this, this.dataStore); - StringBuilder builder = new StringBuilder(); - if (obj.getState() == ObjectInDataStoreStateMachine.State.Ready - || obj.getState() == ObjectInDataStoreStateMachine.State.Copying) { - builder.append(this.dataStore.getUri()); - builder.append("&" + EncodingType.OBJTYPE + "=" + DataObjectType.TEMPLATE); - builder.append("&" + EncodingType.PATH + "=" + obj.getInstallPath()); - builder.append("&" + EncodingType.SIZE + "=" + image.getSize()); - return builder.toString(); - } else { - builder.append(this.dataStore.getUri()); - builder.append("&" + EncodingType.OBJTYPE + "=" + DataObjectType.TEMPLATE); - builder.append("&" + EncodingType.SIZE + "=" + image.getSize()); - builder.append("&" + EncodingType.PATH + "=" + image.getUrl()); - return builder.toString(); - } - } + return image.getUrl(); + } @Override @@ -127,28 +122,21 @@ public class TemplateObject implements TemplateInfo { } /* - -// If the template that was passed into this allocator is not installed in the storage pool, - // add 3 * (template size on secondary storage) to the running total - VMTemplateHostVO templateHostVO = _storageMgr.findVmTemplateHost(templateForVmCreation.getId(), null); - - if (templateHostVO == null) { - VMTemplateSwiftVO templateSwiftVO = _swiftMgr.findByTmpltId(templateForVmCreation.getId()); - if (templateSwiftVO != null) { - long templateSize = templateSwiftVO.getPhysicalSize(); - if (templateSize == 0) { - templateSize = templateSwiftVO.getSize(); - } - totalAllocatedSize += (templateSize + _extraBytesPerVolume); - } - } else { - long templateSize = templateHostVO.getPhysicalSize(); - if ( templateSize == 0 ){ - templateSize = templateHostVO.getSize(); - } - totalAllocatedSize += (templateSize + _extraBytesPerVolume); - } - + * + * // If the template that was passed into this allocator is not + * installed in the storage pool, // add 3 * (template size on secondary + * storage) to the running total VMTemplateHostVO templateHostVO = + * _storageMgr.findVmTemplateHost(templateForVmCreation.getId(), null); + * + * if (templateHostVO == null) { VMTemplateSwiftVO templateSwiftVO = + * _swiftMgr.findByTmpltId(templateForVmCreation.getId()); if + * (templateSwiftVO != null) { long templateSize = + * templateSwiftVO.getPhysicalSize(); if (templateSize == 0) { + * templateSize = templateSwiftVO.getSize(); } totalAllocatedSize += + * (templateSize + _extraBytesPerVolume); } } else { long templateSize = + * templateHostVO.getPhysicalSize(); if ( templateSize == 0 ){ + * templateSize = templateHostVO.getSize(); } totalAllocatedSize += + * (templateSize + _extraBytesPerVolume); } */ VMTemplateVO image = imageDao.findById(this.imageVO.getId()); return image.getSize(); @@ -160,24 +148,299 @@ public class TemplateObject implements TemplateInfo { } @Override - public DiskFormat getFormat() { - return DiskFormat.valueOf(this.imageVO.getFormat().toString()); + public ImageFormat getFormat() { + return this.imageVO.getFormat(); } - public boolean stateTransit(TemplateEvent e) throws NoTransitionException { - boolean result= imageMgr.getStateMachine().transitTo(this.imageVO, e, null, - imageDao); - this.imageVO = imageDao.findById(this.imageVO.getId()); - return result; - } + // public boolean stateTransit(TemplateEvent e) throws NoTransitionException + // { + // this.imageVO = imageDao.findById(this.imageVO.getId()); + // boolean result = imageMgr.getStateMachine().transitTo(this.imageVO, e, + // null, imageDao); + // this.imageVO = imageDao.findById(this.imageVO.getId()); + // return result; + // } @Override public void processEvent(Event event) { try { - ojbectInStoreMgr.update(this, event); + if (this.getDataStore().getRole() == DataStoreRole.Image + || this.getDataStore().getRole() == DataStoreRole.ImageCache) { + TemplateEvent templEvent = null; + if (event == ObjectInDataStoreStateMachine.Event.CreateOnlyRequested) { + templEvent = TemplateEvent.CreateRequested; + } else if (event == ObjectInDataStoreStateMachine.Event.DestroyRequested) { + templEvent = TemplateEvent.DestroyRequested; + } else if (event == ObjectInDataStoreStateMachine.Event.OperationSuccessed) { + templEvent = TemplateEvent.OperationSucceeded; + } else if (event == ObjectInDataStoreStateMachine.Event.OperationFailed) { + templEvent = TemplateEvent.OperationFailed; + } + + // if (templEvent != null && this.getDataStore().getRole() == + // DataStoreRole.Image) { + // this.stateTransit(templEvent); + // } + } + + objectInStoreMgr.update(this, event); } catch (NoTransitionException e) { s_logger.debug("failed to update state", e); throw new CloudRuntimeException("Failed to update state" + e.toString()); + } finally { + // in case of OperationFailed, expunge the entry + if (event == ObjectInDataStoreStateMachine.Event.OperationFailed) { + objectInStoreMgr.delete(this); + } } } + + @Override + public void processEvent(ObjectInDataStoreStateMachine.Event event, Answer answer) { + try { + if (this.getDataStore().getRole() == DataStoreRole.Primary) { + if (answer instanceof CopyCmdAnswer) { + CopyCmdAnswer cpyAnswer = (CopyCmdAnswer) answer; + TemplateObjectTO newTemplate = (TemplateObjectTO) cpyAnswer.getNewData(); + VMTemplateStoragePoolVO templatePoolRef = templatePoolDao.findByPoolTemplate(this.getDataStore() + .getId(), this.getId()); + templatePoolRef.setDownloadPercent(100); + templatePoolRef.setDownloadState(Status.DOWNLOADED); + templatePoolRef.setLocalDownloadPath(newTemplate.getPath()); + templatePoolRef.setInstallPath(newTemplate.getPath()); + templatePoolDao.update(templatePoolRef.getId(), templatePoolRef); + } + } else if (this.getDataStore().getRole() == DataStoreRole.Image + || this.getDataStore().getRole() == DataStoreRole.ImageCache) { + if (answer instanceof CopyCmdAnswer) { + CopyCmdAnswer cpyAnswer = (CopyCmdAnswer) answer; + TemplateObjectTO newTemplate = (TemplateObjectTO) cpyAnswer.getNewData(); + TemplateDataStoreVO templateStoreRef = this.templateStoreDao.findByStoreTemplate(this + .getDataStore().getId(), this.getId()); + templateStoreRef.setInstallPath(newTemplate.getPath()); + templateStoreRef.setDownloadPercent(100); + templateStoreRef.setDownloadState(Status.DOWNLOADED); + templateStoreRef.setSize(newTemplate.getSize()); + templateStoreDao.update(templateStoreRef.getId(), templateStoreRef); + if (this.getDataStore().getRole() == DataStoreRole.Image) { + VMTemplateVO templateVO = this.imageDao.findById(this.getId()); + templateVO.setFormat(newTemplate.getFormat()); + templateVO.setSize(newTemplate.getSize()); + this.imageDao.update(templateVO.getId(), templateVO); + } + } + + TemplateEvent templEvent = null; + if (event == ObjectInDataStoreStateMachine.Event.CreateOnlyRequested) { + templEvent = TemplateEvent.CreateRequested; + } else if (event == ObjectInDataStoreStateMachine.Event.DestroyRequested) { + templEvent = TemplateEvent.DestroyRequested; + } else if (event == ObjectInDataStoreStateMachine.Event.OperationSuccessed) { + templEvent = TemplateEvent.OperationSucceeded; + } else if (event == ObjectInDataStoreStateMachine.Event.OperationFailed) { + templEvent = TemplateEvent.OperationFailed; + } + + // if (templEvent != null && this.getDataStore().getRole() == + // DataStoreRole.Image) { + // this.stateTransit(templEvent); + // } + } + objectInStoreMgr.update(this, event); + } catch (NoTransitionException e) { + s_logger.debug("failed to update state", e); + throw new CloudRuntimeException("Failed to update state" + e.toString()); + } catch (Exception ex) { + s_logger.debug("failed to process event and answer", ex); + objectInStoreMgr.delete(this); + throw new CloudRuntimeException("Failed to process event", ex); + } finally { + // in case of OperationFailed, expunge the entry + if (event == ObjectInDataStoreStateMachine.Event.OperationFailed) { + objectInStoreMgr.delete(this); + } + } + } + + @Override + public void incRefCount() { + if (this.dataStore == null) { + return; + } + + if (this.dataStore.getRole() == DataStoreRole.Image || this.dataStore.getRole() == DataStoreRole.ImageCache) { + TemplateDataStoreVO store = templateStoreDao.findByStoreTemplate(dataStore.getId(), this.getId()); + store.incrRefCnt(); + store.setLastUpdated(new Date()); + templateStoreDao.update(store.getId(), store); + } + } + + @Override + public void decRefCount() { + if (this.dataStore == null) { + return; + } + if (this.dataStore.getRole() == DataStoreRole.Image || this.dataStore.getRole() == DataStoreRole.ImageCache) { + TemplateDataStoreVO store = templateStoreDao.findByStoreTemplate(dataStore.getId(), this.getId()); + store.decrRefCnt(); + store.setLastUpdated(new Date()); + templateStoreDao.update(store.getId(), store); + } + } + + @Override + public Long getRefCount() { + if (this.dataStore == null) { + return null; + } + if (this.dataStore.getRole() == DataStoreRole.Image || this.dataStore.getRole() == DataStoreRole.ImageCache) { + TemplateDataStoreVO store = templateStoreDao.findByStoreTemplate(dataStore.getId(), this.getId()); + return store.getRefCnt(); + } + return null; + } + + @Override + public DataTO getTO() { + DataTO to = null; + if (this.dataStore == null) { + to = new TemplateObjectTO(this); + } else { + to = this.dataStore.getDriver().getTO(this); + if (to == null) { + to = new TemplateObjectTO(this); + } + } + + return to; + } + + @Override + public String getInstallPath() { + if (this.dataStore == null) { + return null; + } + DataObjectInStore obj = objectInStoreMgr.findObject(this, this.dataStore); + return obj.getInstallPath(); + } + + @Override + public long getAccountId() { + return this.imageVO.getAccountId(); + } + + @Override + public boolean isFeatured() { + return this.imageVO.isFeatured(); + } + + @Override + public boolean isPublicTemplate() { + return this.imageVO.isPublicTemplate(); + } + + @Override + public boolean isExtractable() { + return this.imageVO.isExtractable(); + } + + @Override + public String getName() { + return this.imageVO.getName(); + } + + @Override + public boolean isRequiresHvm() { + return this.imageVO.isRequiresHvm(); + } + + @Override + public String getDisplayText() { + return this.imageVO.getDisplayText(); + } + + @Override + public boolean getEnablePassword() { + return this.imageVO.getEnablePassword(); + } + + @Override + public boolean getEnableSshKey() { + return this.imageVO.getEnableSshKey(); + } + + @Override + public boolean isCrossZones() { + return this.imageVO.isCrossZones(); + } + + @Override + public Date getCreated() { + return this.imageVO.getCreated(); + } + + @Override + public long getGuestOSId() { + return this.imageVO.getGuestOSId(); + } + + @Override + public boolean isBootable() { + return this.imageVO.isBootable(); + } + + @Override + public TemplateType getTemplateType() { + return this.imageVO.getTemplateType(); + } + + @Override + public HypervisorType getHypervisorType() { + return this.imageVO.getHypervisorType(); + } + + @Override + public int getBits() { + return this.imageVO.getBits(); + } + + @Override + public String getUrl() { + return this.imageVO.getUrl(); + } + + @Override + public String getChecksum() { + return this.imageVO.getChecksum(); + } + + @Override + public Long getSourceTemplateId() { + return this.imageVO.getSourceTemplateId(); + } + + @Override + public String getTemplateTag() { + return this.imageVO.getTemplateTag(); + } + + @Override + public Map getDetails() { + return this.imageVO.getDetails(); + } + + @Override + public long getDomainId() { + return this.imageVO.getDomainId(); + } + + @Override + public boolean delete() { + if (dataStore != null) { + return dataStore.delete(this); + } + return true; + } + } diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/lifecycle/ImageDataStoreLifeCycle.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/lifecycle/ImageStoreLifeCycle.java similarity index 93% rename from engine/storage/image/src/org/apache/cloudstack/storage/image/store/lifecycle/ImageDataStoreLifeCycle.java rename to engine/storage/image/src/org/apache/cloudstack/storage/image/store/lifecycle/ImageStoreLifeCycle.java index a36823959df..121f8c544ca 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/lifecycle/ImageDataStoreLifeCycle.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/lifecycle/ImageStoreLifeCycle.java @@ -20,5 +20,5 @@ package org.apache.cloudstack.storage.image.store.lifecycle; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle; -public interface ImageDataStoreLifeCycle extends DataStoreLifeCycle { +public interface ImageStoreLifeCycle extends DataStoreLifeCycle { } diff --git a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java b/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java deleted file mode 100644 index 1c21496871f..00000000000 --- a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.image.motion; - -import java.util.Map; - -import javax.inject.Inject; - -import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; -import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; -import org.apache.cloudstack.framework.async.AsyncCompletionCallback; -import org.apache.cloudstack.framework.async.AsyncRpcConext; -import org.apache.cloudstack.storage.command.CopyCmd; -import org.apache.cloudstack.storage.command.CopyCmdAnswer; -import org.apache.cloudstack.storage.endpoint.EndPointSelector; -import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreInfo; - -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.to.VirtualMachineTO; -import com.cloud.host.Host; - -//At least one of datastore is coming from image store or image cache store - -public class DefaultImageMotionStrategy implements ImageMotionStrategy { - @Inject - EndPointSelector selector; - private class CreateTemplateContext extends AsyncRpcConext { - private final TemplateOnPrimaryDataStoreInfo template; - public CreateTemplateContext(AsyncCompletionCallback callback, TemplateOnPrimaryDataStoreInfo template) { - super(callback); - this.template = template; - } - - public TemplateOnPrimaryDataStoreInfo getTemplate() { - return this.template; - } - - } -/* - @Override - public void copyTemplateAsync(String destUri, String srcUri, EndPoint ep, AsyncCompletionCallback callback) { - - CopyCmd copyCommand = new CopyCmd(destUri, srcUri); - CreateTemplateContext context = new CreateTemplateContext(callback, null); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); - caller.setCallback(caller.getTarget().copyTemplateCallBack(null, null)) - .setContext(context); - - ep.sendMessageAsync(copyCommand, caller); - } - - public Object copyTemplateCallBack(AsyncCallbackDispatcher callback, CreateTemplateContext context) { - AsyncCompletionCallback parentCall = context.getParentCallback(); - CopyTemplateToPrimaryStorageAnswer answer = (CopyTemplateToPrimaryStorageAnswer)callback.getResult(); - CommandResult result = new CommandResult(); - - if (!answer.getResult()) { - result.setSuccess(answer.getResult()); - result.setResult(answer.getDetails()); - } else { - TemplateOnPrimaryDataStoreInfo templateStore = context.getTemplate(); - templateStore.setPath(answer.getPath()); - result.setSuccess(true); - } - - parentCall.complete(result); - return null; - }*/ - - @Override - public boolean canHandle(DataObject srcData, DataObject destData) { - /* - DataStore destStore = destData.getDataStore(); - DataStore srcStore = srcData.getDataStore(); - if (destStore.getRole() == DataStoreRole.Image || destStore.getRole() == DataStoreRole.ImageCache - || srcStore.getRole() == DataStoreRole.Image - || srcStore.getRole() == DataStoreRole.ImageCache) { - return true; - }*/ - return false; - } - - @Override - public boolean canHandle(Map volumeMap, Host srcHost, Host destHost) { - return false; - } - - @Override - public Void copyAsync(DataObject srcData, DataObject destData, - AsyncCompletionCallback callback) { - DataStore destStore = destData.getDataStore(); - DataStore srcStore = srcData.getDataStore(); - EndPoint ep = selector.select(srcData, destData); - CopyCommandResult result = new CopyCommandResult("", null); - if (ep == null) { - result.setResult("can't find end point"); - callback.complete(result); - return null; - } - - String srcUri = srcStore.getDriver().grantAccess(srcData, ep); - String destUri = destStore.getDriver().grantAccess(destData, ep); - CopyCmd cmd = new CopyCmd(srcUri, destUri); - - CreateTemplateContext context = new CreateTemplateContext(callback, null); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); - caller.setCallback(caller.getTarget().copyAsyncCallback(null, null)) - .setContext(context); - - ep.sendMessageAsync(cmd, caller); - return null; - } - - protected Void copyAsyncCallback(AsyncCallbackDispatcher callback, CreateTemplateContext context) { - AsyncCompletionCallback parentCall = context.getParentCallback(); - Answer answer = (Answer)callback.getResult(); - if (!answer.getResult()) { - CopyCommandResult result = new CopyCommandResult("", null); - result.setResult(answer.getDetails()); - parentCall.complete(result); - } else { - CopyCmdAnswer ans = (CopyCmdAnswer)answer; - CopyCommandResult result = new CopyCommandResult(ans.getPath(), null); - parentCall.complete(result); - } - return null; - - } - - @Override - public Void copyAsync(Map volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, - AsyncCompletionCallback callback) { - CopyCommandResult result = new CopyCommandResult("", null); - result.setResult("not implemented"); - callback.complete(result); - return null; - } -} diff --git a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/ImageMotionServiceImpl.java b/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/ImageMotionServiceImpl.java deleted file mode 100644 index 93ba4a5ad64..00000000000 --- a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/ImageMotionServiceImpl.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.image.motion; - -import java.util.List; - -import javax.inject.Inject; - -import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.ImageService; -import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService; -import org.apache.cloudstack.framework.async.AsyncCompletionCallback; - - -public class ImageMotionServiceImpl implements ImageMotionService { - @Inject - List motionStrategies; - @Inject - VolumeService volumeService; - @Inject - ImageService imageService; - - @Override - public boolean copyIso(String isoUri, String destIsoUri) { - // TODO Auto-generated method stub - return false; - } - - - - @Override - public void copyTemplateAsync(TemplateInfo destTemplate, TemplateInfo srcTemplate, AsyncCompletionCallback callback) { - /* ImageMotionStrategy ims = null; - for (ImageMotionStrategy strategy : motionStrategies) { - if (strategy.canHandle(srcTemplate)) { - ims = strategy; - break; - } - } - - if (ims == null) { - throw new CloudRuntimeException("Can't find proper image motion strategy"); - } - - EndPoint ep = ims.getEndPoint(destTemplate, srcTemplate); - String srcUri = srcTemplate.getDataStore().grantAccess(srcTemplate, ep); - String destUri = destTemplate.getDataStore().grantAccess(destTemplate, ep); - - ims.copyTemplateAsync(destUri, srcUri, ep, callback);*/ - } - - -} diff --git a/engine/storage/integration-test/pom.xml b/engine/storage/integration-test/pom.xml index 1bce37afd23..8a9dc15579c 100644 --- a/engine/storage/integration-test/pom.xml +++ b/engine/storage/integration-test/pom.xml @@ -46,7 +46,13 @@ org.apache.cloudstack - cloud-engine-storage-imagemotion + cloud-engine-storage-datamotion + ${project.version} + test + + + org.apache.cloudstack + cloud-engine-storage-cache ${project.version} test @@ -56,6 +62,48 @@ ${project.version} test + + org.apache.cloudstack + cloud-plugin-hypervisor-vmware + ${project.version} + test + + + org.apache.cloudstack + cloud-plugin-hypervisor-kvm + ${project.version} + test + + + org.apache.cloudstack + cloud-plugin-storage-volume-default + ${project.version} + test + + + org.apache.cloudstack + cloud-secondary-storage + ${project.version} + test + + + org.apache.cloudstack + cloud-plugin-storage-image-default + ${project.version} + test + + + org.apache.cloudstack + cloud-plugin-storage-image-s3 + ${project.version} + test + + + org.apache.cloudstack + cloud-plugin-storage-image-swift + ${project.version} + test + org.apache.httpcomponents httpclient diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/MockLocalNfsSecondaryStorageResource.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/MockLocalNfsSecondaryStorageResource.java new file mode 100644 index 00000000000..4d932964a64 --- /dev/null +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/MockLocalNfsSecondaryStorageResource.java @@ -0,0 +1,135 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage; + +import static com.cloud.utils.StringUtils.join; +import static java.util.Arrays.asList; + +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashMap; +import java.util.List; + +import javax.naming.ConfigurationException; + +import org.apache.cloudstack.storage.command.DownloadSystemTemplateCommand; +import org.apache.cloudstack.storage.resource.NfsSecondaryStorageResource; +import org.apache.cloudstack.storage.template.DownloadManagerImpl; +import org.springframework.stereotype.Component; + +import com.amazonaws.services.s3.model.S3ObjectSummary; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.storage.DownloadAnswer; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.NfsTO; +import com.cloud.agent.api.to.S3TO; +import com.cloud.agent.api.to.SwiftTO; +import com.cloud.storage.JavaStorageLayer; +import com.cloud.storage.StorageLayer; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.utils.S3Utils; +import com.cloud.utils.UriUtils; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; + +@Component +public class MockLocalNfsSecondaryStorageResource extends NfsSecondaryStorageResource { + + public MockLocalNfsSecondaryStorageResource() { + _dlMgr = new DownloadManagerImpl(); + _storage = new JavaStorageLayer(); + HashMap params = new HashMap(); + params.put(StorageLayer.InstanceConfigKey, _storage); + try { + _dlMgr.configure("downloadMgr", params); + } catch (ConfigurationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + createTemplateFromSnapshotXenScript = Script.findScript(getDefaultScriptsDir(), + "create_privatetemplate_from_snapshot_xen.sh"); + + } + + @Override + public String getRootDir(String secUrl) { + return "/mnt"; + } + + @Override + public Answer executeRequest(Command cmd) { + if (cmd instanceof DownloadSystemTemplateCommand) { + return execute((DownloadSystemTemplateCommand) cmd); + } else { + // return Answer.createUnsupportedCommandAnswer(cmd); + return super.executeRequest(cmd); + } + } + + private Answer execute(DownloadSystemTemplateCommand cmd) { + DataStoreTO dstore = cmd.getDataStore(); + if (dstore instanceof S3TO) { + // TODO: how to handle download progress for S3 + S3TO s3 = (S3TO) cmd.getDataStore(); + String url = cmd.getUrl(); + String user = null; + String password = null; + if (cmd.getAuth() != null) { + user = cmd.getAuth().getUserName(); + password = new String(cmd.getAuth().getPassword()); + } + // get input stream from the given url + InputStream in = UriUtils.getInputStreamFromUrl(url, user, password); + URL urlObj; + try { + urlObj = new URL(url); + } catch (MalformedURLException e) { + throw new CloudRuntimeException("URL is incorrect: " + url); + } + + final String bucket = s3.getBucketName(); + // convention is no / in the end for install path based on S3Utils + // implementation. + String path = determineS3TemplateDirectory(cmd.getAccountId(), cmd.getResourceId(), cmd.getName()); + // template key is + // TEMPLATE_ROOT_DIR/account_id/template_id/template_name + String key = join(asList(path, urlObj.getFile()), S3Utils.SEPARATOR); + S3Utils.putObject(s3, in, bucket, key); + List s3Obj = S3Utils.getDirectory(s3, bucket, path); + if (s3Obj == null || s3Obj.size() == 0) { + return new Answer(cmd, false, "Failed to download to S3 bucket: " + bucket + " with key: " + key); + } else { + return new DownloadAnswer(null, 100, null, Status.DOWNLOADED, path, path, s3Obj.get(0).getSize(), s3Obj + .get(0).getSize(), s3Obj.get(0).getETag()); + } + } else if (dstore instanceof NfsTO) { + return new Answer(cmd, false, "Nfs needs to be pre-installed with system vm templates"); + } else if (dstore instanceof SwiftTO) { + // TODO: need to move code from + // execute(uploadTemplateToSwiftFromSecondaryStorageCommand) here, + // but we need to handle + // source is url, most likely we need to modify our existing + // swiftUpload python script. + return new Answer(cmd, false, "Swift is not currently support DownloadCommand"); + } else { + return new Answer(cmd, false, "Unsupported image data store: " + dstore); + } + } +} diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/allocator/StorageAllocatorTest.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/allocator/StorageAllocatorTest.java index 9444fa5246e..40d9d418938 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/allocator/StorageAllocatorTest.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/allocator/StorageAllocatorTest.java @@ -16,8 +16,6 @@ // under the License. package org.apache.cloudstack.storage.allocator; -import static org.junit.Assert.fail; - import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -28,7 +26,6 @@ import junit.framework.Assert; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO; @@ -37,6 +34,7 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Matchers; import org.mockito.Mockito; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -55,6 +53,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.org.Cluster.ClusterType; import com.cloud.org.Managed.ManagedState; import com.cloud.storage.DiskOfferingVO; +import com.cloud.storage.ScopeType; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolStatus; @@ -70,370 +69,372 @@ import com.cloud.vm.VirtualMachineProfile; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:/storageContext.xml") public class StorageAllocatorTest { - @Inject - PrimaryDataStoreDao storagePoolDao; - @Inject - StorageManager storageMgr; - @Inject - DiskOfferingDao diskOfferingDao; - @Inject - VolumeDao volumeDao; - @Inject - HostPodDao podDao; - @Inject - ClusterDao clusterDao; - @Inject - DataCenterDao dcDao; - @Inject - StoragePoolDetailsDao poolDetailsDao; - @Inject - DataStoreProviderManager providerMgr; - Long dcId = 1l; - Long podId = 1l; - Long clusterId = 1l; - Long volumeId = null; - Long diskOfferingId = null; - Long storagePoolId = null; - VolumeVO volume = null; - DiskOfferingVO diskOffering = null; - StoragePoolVO storage = null; + @Inject + PrimaryDataStoreDao storagePoolDao; + @Inject + StorageManager storageMgr; + @Inject + DiskOfferingDao diskOfferingDao; + @Inject + VolumeDao volumeDao; + @Inject + HostPodDao podDao; + @Inject + ClusterDao clusterDao; + @Inject + DataCenterDao dcDao; + @Inject + StoragePoolDetailsDao poolDetailsDao; + @Inject + DataStoreProviderManager providerMgr; + Long dcId = 1l; + Long podId = 1l; + Long clusterId = 1l; + Long volumeId = null; + Long diskOfferingId = null; + Long storagePoolId = null; + VolumeVO volume = null; + DiskOfferingVO diskOffering = null; + StoragePoolVO storage = null; - @Before - public void setup() throws Exception { - ComponentContext.initComponentsLifeCycle(); + @Before + public void setup() throws Exception { + ComponentContext.initComponentsLifeCycle(); - } + } - protected void createDb() { - DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24", - null, null, NetworkType.Basic, null, null, true, true, null, null); - dc = dcDao.persist(dc); - dcId = dc.getId(); + protected void createDb() { + DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, + "10.0.0.1/24", null, null, NetworkType.Basic, null, null, true, true, null, null); + dc = dcDao.persist(dc); + dcId = dc.getId(); - HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), "255.255.255.255", "", 8, "test"); - pod = podDao.persist(pod); - podId = pod.getId(); - - ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster"); - cluster.setHypervisorType(HypervisorType.XenServer.toString()); - cluster.setClusterType(ClusterType.CloudManaged); - cluster.setManagedState(ManagedState.Managed); - cluster = clusterDao.persist(cluster); - clusterId = cluster.getId(); + HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), "255.255.255.255", "", 8, "test"); + pod = podDao.persist(pod); + podId = pod.getId(); - DataStoreProvider provider = providerMgr.getDataStoreProvider("ancient primary data store provider"); - storage = new StoragePoolVO(); - storage.setDataCenterId(dcId); - storage.setPodId(podId); - storage.setPoolType(StoragePoolType.NetworkFilesystem); - storage.setClusterId(clusterId); - storage.setStatus(StoragePoolStatus.Up); - storage.setScope(ScopeType.CLUSTER); - storage.setAvailableBytes(1000); - storage.setCapacityBytes(20000); - storage.setHostAddress(UUID.randomUUID().toString()); - storage.setPath(UUID.randomUUID().toString()); - storage.setStorageProviderName(provider.getName()); - storage = storagePoolDao.persist(storage); - storagePoolId = storage.getId(); + ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster"); + cluster.setHypervisorType(HypervisorType.XenServer.toString()); + cluster.setClusterType(ClusterType.CloudManaged); + cluster.setManagedState(ManagedState.Managed); + cluster = clusterDao.persist(cluster); + clusterId = cluster.getId(); - storageMgr.createCapacityEntry(storage.getId()); + DataStoreProvider provider = providerMgr.getDataStoreProvider("cloudstack primary data store provider"); + storage = new StoragePoolVO(); + storage.setDataCenterId(dcId); + storage.setPodId(podId); + storage.setPoolType(StoragePoolType.NetworkFilesystem); + storage.setClusterId(clusterId); + storage.setStatus(StoragePoolStatus.Up); + storage.setScope(ScopeType.CLUSTER); + storage.setUsedBytes(1000); + storage.setCapacityBytes(20000); + storage.setHostAddress(UUID.randomUUID().toString()); + storage.setPath(UUID.randomUUID().toString()); + storage.setStorageProviderName(provider.getName()); + storage = storagePoolDao.persist(storage); + storagePoolId = storage.getId(); - diskOffering = new DiskOfferingVO(); - diskOffering.setDiskSize(500); - diskOffering.setName("test-disk"); - diskOffering.setSystemUse(false); - diskOffering.setUseLocalStorage(false); - diskOffering.setCustomized(false); - diskOffering.setRecreatable(false); - diskOffering = diskOfferingDao.persist(diskOffering); - diskOfferingId = diskOffering.getId(); + storageMgr.createCapacityEntry(storage.getId()); - volume = new VolumeVO(Volume.Type.ROOT, "volume", dcId, 1, 1, diskOffering.getId(), diskOffering.getDiskSize()); - volume = volumeDao.persist(volume); - volumeId = volume.getId(); - } - - - - @Inject - List allocators; - @Test - public void testClusterAllocatorMultiplePools() { - Long newStorageId = null; - try { - createDb(); - - DataStoreProvider provider = providerMgr.getDataStoreProvider("ancient primary data store provider"); - storage = new StoragePoolVO(); - storage.setDataCenterId(dcId); - storage.setPodId(podId); - storage.setPoolType(StoragePoolType.NetworkFilesystem); - storage.setClusterId(clusterId); - storage.setStatus(StoragePoolStatus.Up); - storage.setScope(ScopeType.CLUSTER); - storage.setAvailableBytes(1000); - storage.setCapacityBytes(20000); - storage.setHostAddress(UUID.randomUUID().toString()); - storage.setPath(UUID.randomUUID().toString()); - storage.setStorageProviderName(provider.getName()); - StoragePoolVO newStorage = storagePoolDao.persist(storage); - newStorageId = newStorage.getId(); - - DiskProfile profile = new DiskProfile(volume, diskOffering, HypervisorType.XenServer); - VirtualMachineProfile vmProfile = Mockito.mock(VirtualMachineProfile.class); - Mockito.when(storageMgr.storagePoolHasEnoughSpace( - Mockito.anyListOf(Volume.class), Mockito.any(StoragePool.class))).thenReturn(true); - DeploymentPlan plan = new DataCenterDeployment(dcId, podId, clusterId, null, null, null); - int foundAcct = 0; - for (StoragePoolAllocator allocator : allocators) { - List pools = allocator.allocateToPool(profile, vmProfile, plan, new ExcludeList(), 1); - if (!pools.isEmpty()) { - Assert.assertEquals(pools.size(), 1); - foundAcct++; - } - } + diskOffering = new DiskOfferingVO(); + diskOffering.setDiskSize(500); + diskOffering.setName("test-disk"); + diskOffering.setSystemUse(false); + diskOffering.setUseLocalStorage(false); + diskOffering.setCustomized(false); + diskOffering.setRecreatable(false); + diskOffering = diskOfferingDao.persist(diskOffering); + diskOfferingId = diskOffering.getId(); - if (foundAcct > 1 || foundAcct == 0) { - Assert.fail(); - } - } catch (Exception e) { - cleanDb(); - - if (newStorageId != null) { - storagePoolDao.remove(newStorageId); - } - Assert.fail(); - } - } - - @Test - public void testClusterAllocator() { - try { - createDb(); - DiskProfile profile = new DiskProfile(volume, diskOffering, HypervisorType.XenServer); - VirtualMachineProfile vmProfile = Mockito.mock(VirtualMachineProfile.class); - Mockito.when(storageMgr.storagePoolHasEnoughSpace( - Mockito.anyListOf(Volume.class), Mockito.any(StoragePool.class))).thenReturn(true); - DeploymentPlan plan = new DataCenterDeployment(dcId, podId, clusterId, null, null, null); - int foundAcct = 0; - for (StoragePoolAllocator allocator : allocators) { - List pools = allocator.allocateToPool(profile, vmProfile, plan, new ExcludeList(), 1); - if (!pools.isEmpty()) { - Assert.assertEquals(pools.get(0).getId(), storage.getId()); - foundAcct++; - } - } + volume = new VolumeVO(Volume.Type.ROOT, "volume", dcId, 1, 1, diskOffering.getId(), diskOffering.getDiskSize()); + volume = volumeDao.persist(volume); + volumeId = volume.getId(); + } - if (foundAcct > 1 || foundAcct == 0) { - Assert.fail(); - } - } catch (Exception e) { - cleanDb(); - Assert.fail(); - } - } - - - @Test - public void testClusterAllocatorWithTags() { - try { - createDb(); - StoragePoolDetailVO detailVO = new StoragePoolDetailVO(this.storagePoolId, "high", "true"); - poolDetailsDao.persist(detailVO); - DiskOfferingVO diskOff = this.diskOfferingDao.findById(diskOffering.getId()); - List tags = new ArrayList(); - tags.add("high"); - diskOff.setTagsArray(tags); - diskOfferingDao.update(diskOff.getId(), diskOff); - - DiskProfile profile = new DiskProfile(volume, diskOff, HypervisorType.XenServer); - VirtualMachineProfile vmProfile = Mockito.mock(VirtualMachineProfile.class); - Mockito.when(storageMgr.storagePoolHasEnoughSpace( - Mockito.anyListOf(Volume.class), Mockito.any(StoragePool.class))).thenReturn(true); - DeploymentPlan plan = new DataCenterDeployment(dcId, podId, clusterId, null, null, null); - int foundAcct = 0; - for (StoragePoolAllocator allocator : allocators) { - List pools = allocator.allocateToPool(profile, vmProfile, plan, new ExcludeList(), 1); - if (!pools.isEmpty()) { - Assert.assertEquals(pools.get(0).getId(), storage.getId()); - foundAcct++; - } - } + @Inject + List allocators; - if (foundAcct > 1 || foundAcct == 0) { - Assert.fail(); - } - } catch (Exception e) { - cleanDb(); - Assert.fail(); - } - } - - @Test - public void testClusterAllocatorWithWrongTag() { - try { - createDb(); - StoragePoolDetailVO detailVO = new StoragePoolDetailVO(this.storagePoolId, "high", "true"); - poolDetailsDao.persist(detailVO); - DiskOfferingVO diskOff = this.diskOfferingDao.findById(diskOffering.getId()); - List tags = new ArrayList(); - tags.add("low"); - diskOff.setTagsArray(tags); - diskOfferingDao.update(diskOff.getId(), diskOff); - - DiskProfile profile = new DiskProfile(volume, diskOff, HypervisorType.XenServer); - VirtualMachineProfile vmProfile = Mockito.mock(VirtualMachineProfile.class); - Mockito.when(storageMgr.storagePoolHasEnoughSpace( - Mockito.anyListOf(Volume.class), Mockito.any(StoragePool.class))).thenReturn(true); - DeploymentPlan plan = new DataCenterDeployment(dcId, podId, clusterId, null, null, null); - int foundAcct = 0; - for (StoragePoolAllocator allocator : allocators) { - List pools = allocator.allocateToPool(profile, vmProfile, plan, new ExcludeList(), 1); - if (!pools.isEmpty()) { - foundAcct++; - } - } + @Test + public void testClusterAllocatorMultiplePools() { + Long newStorageId = null; + try { + createDb(); - if (foundAcct != 0) { - Assert.fail(); - } - } catch (Exception e) { - cleanDb(); - Assert.fail(); - } - } - - @Test - public void testZoneWideStorageAllocator() { - try { - createDb(); - - StoragePoolVO pool = storagePoolDao.findById(storagePoolId); - pool.setScope(ScopeType.ZONE); - storagePoolDao.update(pool.getId(), pool); - - DiskProfile profile = new DiskProfile(volume, diskOffering, HypervisorType.KVM); - VirtualMachineProfile vmProfile = Mockito.mock(VirtualMachineProfile.class); - Mockito.when(vmProfile.getHypervisorType()).thenReturn(HypervisorType.KVM); - Mockito.when(storageMgr.storagePoolHasEnoughSpace( - Mockito.anyListOf(Volume.class), Mockito.any(StoragePool.class))).thenReturn(true); - DeploymentPlan plan = new DataCenterDeployment(dcId, podId, clusterId, null, null, null); - int foundAcct = 0; - for (StoragePoolAllocator allocator : allocators) { - List pools = allocator.allocateToPool(profile, vmProfile, plan, new ExcludeList(), 1); - if (!pools.isEmpty()) { - Assert.assertEquals(pools.get(0).getId(), storage.getId()); - foundAcct++; - } - } + DataStoreProvider provider = providerMgr.getDataStoreProvider("cloudstack primary data store provider"); + storage = new StoragePoolVO(); + storage.setDataCenterId(dcId); + storage.setPodId(podId); + storage.setPoolType(StoragePoolType.NetworkFilesystem); + storage.setClusterId(clusterId); + storage.setStatus(StoragePoolStatus.Up); + storage.setScope(ScopeType.CLUSTER); + storage.setUsedBytes(1000); + storage.setCapacityBytes(20000); + storage.setHostAddress(UUID.randomUUID().toString()); + storage.setPath(UUID.randomUUID().toString()); + storage.setStorageProviderName(provider.getName()); + StoragePoolVO newStorage = storagePoolDao.persist(storage); + newStorageId = newStorage.getId(); - if (foundAcct > 1 || foundAcct == 0) { - Assert.fail(); - } - } catch (Exception e) { - cleanDb(); - Assert.fail(); - } - } - - @Test - public void testPoolStateIsNotUp() { - try { - createDb(); - - StoragePoolVO pool = storagePoolDao.findById(storagePoolId); - pool.setScope(ScopeType.ZONE); - pool.setStatus(StoragePoolStatus.Maintenance); - storagePoolDao.update(pool.getId(), pool); - - DiskProfile profile = new DiskProfile(volume, diskOffering, HypervisorType.XenServer); - VirtualMachineProfile vmProfile = Mockito.mock(VirtualMachineProfile.class); - Mockito.when(storageMgr.storagePoolHasEnoughSpace( - Mockito.anyListOf(Volume.class), Mockito.any(StoragePool.class))).thenReturn(true); - DeploymentPlan plan = new DataCenterDeployment(dcId, podId, clusterId, null, null, null); - int foundAcct = 0; - for (StoragePoolAllocator allocator : allocators) { - List pools = allocator.allocateToPool(profile, vmProfile, plan, new ExcludeList(), 1); - if (!pools.isEmpty()) { - Assert.assertEquals(pools.get(0).getId(), storage.getId()); - foundAcct++; - } - } + DiskProfile profile = new DiskProfile(volume, diskOffering, HypervisorType.XenServer); + VirtualMachineProfile vmProfile = Mockito.mock(VirtualMachineProfile.class); + Mockito.when( + storageMgr.storagePoolHasEnoughSpace(Matchers.anyListOf(Volume.class), + Matchers.any(StoragePool.class))).thenReturn(true); + DeploymentPlan plan = new DataCenterDeployment(dcId, podId, clusterId, null, null, null); + int foundAcct = 0; + for (StoragePoolAllocator allocator : allocators) { + List pools = allocator.allocateToPool(profile, vmProfile, plan, new ExcludeList(), 1); + if (!pools.isEmpty()) { + Assert.assertEquals(pools.size(), 1); + foundAcct++; + } + } - if (foundAcct == 1) { - Assert.fail(); - } - } catch (Exception e) { - cleanDb(); - Assert.fail(); - } - } - - - - - @Test - public void testLocalStorageAllocator() { - try { - createDb(); - - StoragePoolVO pool = storagePoolDao.findById(storagePoolId); - pool.setScope(ScopeType.HOST); - storagePoolDao.update(pool.getId(), pool); - - DiskOfferingVO diskOff = diskOfferingDao.findById(diskOfferingId); - diskOff.setUseLocalStorage(true); - diskOfferingDao.update(diskOfferingId, diskOff); - - DiskProfile profile = new DiskProfile(volume, diskOff, HypervisorType.XenServer); - VirtualMachineProfile vmProfile = Mockito.mock(VirtualMachineProfile.class); - Mockito.when(storageMgr.storagePoolHasEnoughSpace( - Mockito.anyListOf(Volume.class), Mockito.any(StoragePool.class))).thenReturn(true); - DeploymentPlan plan = new DataCenterDeployment(dcId, podId, clusterId, null, null, null); - int foundAcct = 0; - for (StoragePoolAllocator allocator : allocators) { - List pools = allocator.allocateToPool(profile, vmProfile, plan, new ExcludeList(), 1); - if (!pools.isEmpty()) { - Assert.assertEquals(pools.get(0).getId(), storage.getId()); - foundAcct++; - } - } + if (foundAcct > 1 || foundAcct == 0) { + Assert.fail(); + } + } catch (Exception e) { + cleanDb(); - if (foundAcct > 1 || foundAcct == 0) { - Assert.fail(); - } - } catch (Exception e) { - cleanDb(); - Assert.fail(); - } - } - - protected void cleanDb() { - if (volumeId != null) { - volumeDao.remove(volumeId); - volumeId = null; - } - if (diskOfferingId != null) { - diskOfferingDao.remove(diskOfferingId); - diskOfferingId = null; - } - if (storagePoolId != null) { - storagePoolDao.remove(storagePoolId); - storagePoolId = null; - } - if (clusterId != null) { - clusterDao.remove(clusterId); - clusterId = null; - } - if (podId != null) { - podDao.remove(podId); - podId = null; - } - if (dcId != null) { - dcDao.remove(dcId); - dcId = null; - } - } + if (newStorageId != null) { + storagePoolDao.remove(newStorageId); + } + Assert.fail(); + } + } + + @Test + public void testClusterAllocator() { + try { + createDb(); + DiskProfile profile = new DiskProfile(volume, diskOffering, HypervisorType.XenServer); + VirtualMachineProfile vmProfile = Mockito.mock(VirtualMachineProfile.class); + Mockito.when( + storageMgr.storagePoolHasEnoughSpace(Matchers.anyListOf(Volume.class), + Matchers.any(StoragePool.class))).thenReturn(true); + DeploymentPlan plan = new DataCenterDeployment(dcId, podId, clusterId, null, null, null); + int foundAcct = 0; + for (StoragePoolAllocator allocator : allocators) { + List pools = allocator.allocateToPool(profile, vmProfile, plan, new ExcludeList(), 1); + if (!pools.isEmpty()) { + Assert.assertEquals(pools.get(0).getId(), storage.getId()); + foundAcct++; + } + } + + if (foundAcct > 1 || foundAcct == 0) { + Assert.fail(); + } + } catch (Exception e) { + cleanDb(); + Assert.fail(); + } + } + + @Test + public void testClusterAllocatorWithTags() { + try { + createDb(); + StoragePoolDetailVO detailVO = new StoragePoolDetailVO(this.storagePoolId, "high", "true"); + poolDetailsDao.persist(detailVO); + DiskOfferingVO diskOff = this.diskOfferingDao.findById(diskOffering.getId()); + List tags = new ArrayList(); + tags.add("high"); + diskOff.setTagsArray(tags); + diskOfferingDao.update(diskOff.getId(), diskOff); + + DiskProfile profile = new DiskProfile(volume, diskOff, HypervisorType.XenServer); + VirtualMachineProfile vmProfile = Mockito.mock(VirtualMachineProfile.class); + Mockito.when( + storageMgr.storagePoolHasEnoughSpace(Matchers.anyListOf(Volume.class), + Matchers.any(StoragePool.class))).thenReturn(true); + DeploymentPlan plan = new DataCenterDeployment(dcId, podId, clusterId, null, null, null); + int foundAcct = 0; + for (StoragePoolAllocator allocator : allocators) { + List pools = allocator.allocateToPool(profile, vmProfile, plan, new ExcludeList(), 1); + if (!pools.isEmpty()) { + Assert.assertEquals(pools.get(0).getId(), storage.getId()); + foundAcct++; + } + } + + if (foundAcct > 1 || foundAcct == 0) { + Assert.fail(); + } + } catch (Exception e) { + cleanDb(); + Assert.fail(); + } + } + + @Test + public void testClusterAllocatorWithWrongTag() { + try { + createDb(); + StoragePoolDetailVO detailVO = new StoragePoolDetailVO(this.storagePoolId, "high", "true"); + poolDetailsDao.persist(detailVO); + DiskOfferingVO diskOff = this.diskOfferingDao.findById(diskOffering.getId()); + List tags = new ArrayList(); + tags.add("low"); + diskOff.setTagsArray(tags); + diskOfferingDao.update(diskOff.getId(), diskOff); + + DiskProfile profile = new DiskProfile(volume, diskOff, HypervisorType.XenServer); + VirtualMachineProfile vmProfile = Mockito.mock(VirtualMachineProfile.class); + Mockito.when( + storageMgr.storagePoolHasEnoughSpace(Matchers.anyListOf(Volume.class), + Matchers.any(StoragePool.class))).thenReturn(true); + DeploymentPlan plan = new DataCenterDeployment(dcId, podId, clusterId, null, null, null); + int foundAcct = 0; + for (StoragePoolAllocator allocator : allocators) { + List pools = allocator.allocateToPool(profile, vmProfile, plan, new ExcludeList(), 1); + if (!pools.isEmpty()) { + foundAcct++; + } + } + + if (foundAcct != 0) { + Assert.fail(); + } + } catch (Exception e) { + cleanDb(); + Assert.fail(); + } + } + + @Test + public void testZoneWideStorageAllocator() { + try { + createDb(); + + StoragePoolVO pool = storagePoolDao.findById(storagePoolId); + pool.setScope(ScopeType.ZONE); + storagePoolDao.update(pool.getId(), pool); + + DiskProfile profile = new DiskProfile(volume, diskOffering, HypervisorType.KVM); + VirtualMachineProfile vmProfile = Mockito.mock(VirtualMachineProfile.class); + Mockito.when(vmProfile.getHypervisorType()).thenReturn(HypervisorType.KVM); + Mockito.when( + storageMgr.storagePoolHasEnoughSpace(Matchers.anyListOf(Volume.class), + Matchers.any(StoragePool.class))).thenReturn(true); + DeploymentPlan plan = new DataCenterDeployment(dcId, podId, clusterId, null, null, null); + int foundAcct = 0; + for (StoragePoolAllocator allocator : allocators) { + List pools = allocator.allocateToPool(profile, vmProfile, plan, new ExcludeList(), 1); + if (!pools.isEmpty()) { + Assert.assertEquals(pools.get(0).getId(), storage.getId()); + foundAcct++; + } + } + + if (foundAcct > 1 || foundAcct == 0) { + Assert.fail(); + } + } catch (Exception e) { + cleanDb(); + Assert.fail(); + } + } + + @Test + public void testPoolStateIsNotUp() { + try { + createDb(); + + StoragePoolVO pool = storagePoolDao.findById(storagePoolId); + pool.setScope(ScopeType.ZONE); + pool.setStatus(StoragePoolStatus.Maintenance); + storagePoolDao.update(pool.getId(), pool); + + DiskProfile profile = new DiskProfile(volume, diskOffering, HypervisorType.XenServer); + VirtualMachineProfile vmProfile = Mockito.mock(VirtualMachineProfile.class); + Mockito.when( + storageMgr.storagePoolHasEnoughSpace(Matchers.anyListOf(Volume.class), + Matchers.any(StoragePool.class))).thenReturn(true); + DeploymentPlan plan = new DataCenterDeployment(dcId, podId, clusterId, null, null, null); + int foundAcct = 0; + for (StoragePoolAllocator allocator : allocators) { + List pools = allocator.allocateToPool(profile, vmProfile, plan, new ExcludeList(), 1); + if (!pools.isEmpty()) { + Assert.assertEquals(pools.get(0).getId(), storage.getId()); + foundAcct++; + } + } + + if (foundAcct == 1) { + Assert.fail(); + } + } catch (Exception e) { + cleanDb(); + Assert.fail(); + } + } + + @Test + public void testLocalStorageAllocator() { + try { + createDb(); + + StoragePoolVO pool = storagePoolDao.findById(storagePoolId); + pool.setScope(ScopeType.HOST); + storagePoolDao.update(pool.getId(), pool); + + DiskOfferingVO diskOff = diskOfferingDao.findById(diskOfferingId); + diskOff.setUseLocalStorage(true); + diskOfferingDao.update(diskOfferingId, diskOff); + + DiskProfile profile = new DiskProfile(volume, diskOff, HypervisorType.XenServer); + VirtualMachineProfile vmProfile = Mockito.mock(VirtualMachineProfile.class); + Mockito.when( + storageMgr.storagePoolHasEnoughSpace(Matchers.anyListOf(Volume.class), + Matchers.any(StoragePool.class))).thenReturn(true); + DeploymentPlan plan = new DataCenterDeployment(dcId, podId, clusterId, null, null, null); + int foundAcct = 0; + for (StoragePoolAllocator allocator : allocators) { + List pools = allocator.allocateToPool(profile, vmProfile, plan, new ExcludeList(), 1); + if (!pools.isEmpty()) { + Assert.assertEquals(pools.get(0).getId(), storage.getId()); + foundAcct++; + } + } + + if (foundAcct > 1 || foundAcct == 0) { + Assert.fail(); + } + } catch (Exception e) { + cleanDb(); + Assert.fail(); + } + } + + protected void cleanDb() { + if (volumeId != null) { + volumeDao.remove(volumeId); + volumeId = null; + } + if (diskOfferingId != null) { + diskOfferingDao.remove(diskOfferingId); + diskOfferingId = null; + } + if (storagePoolId != null) { + storagePoolDao.remove(storagePoolId); + storagePoolId = null; + } + if (clusterId != null) { + clusterDao.remove(clusterId); + clusterId = null; + } + if (podId != null) { + podDao.remove(podId); + podId = null; + } + if (dcId != null) { + dcDao.remove(dcId); + dcId = null; + } + } } diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/allocator/StorageAllocatorTestConfiguration.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/allocator/StorageAllocatorTestConfiguration.java index 4790086b2e1..e3172176f9a 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/allocator/StorageAllocatorTestConfiguration.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/allocator/StorageAllocatorTestConfiguration.java @@ -39,35 +39,28 @@ import com.cloud.storage.dao.StoragePoolDetailsDaoImpl; import com.cloud.storage.dao.VMTemplateDaoImpl; import com.cloud.vm.UserVmManager; - @Configuration -@ComponentScan(basePackageClasses={ - StoragePoolDetailsDaoImpl.class, - PrimaryDataStoreDaoImpl.class, - VMTemplateDaoImpl.class, - HostDaoImpl.class, - DomainDaoImpl.class, - DataCenterDaoImpl.class}, - includeFilters={@Filter(value=Library.class, type=FilterType.CUSTOM)}, - useDefaultFilters=false - ) +@ComponentScan(basePackageClasses = { StoragePoolDetailsDaoImpl.class, PrimaryDataStoreDaoImpl.class, + VMTemplateDaoImpl.class, HostDaoImpl.class, DomainDaoImpl.class, DataCenterDaoImpl.class }, + includeFilters = { @Filter(value = Library.class, type = FilterType.CUSTOM) }, useDefaultFilters = false) public class StorageAllocatorTestConfiguration { - @Bean - public UserVmManager UserVmManager() { - return Mockito.mock(UserVmManager.class); - } - @Bean - public StorageManager StorageManager() { - return Mockito.mock(StorageManager.class); - } + @Bean + public UserVmManager UserVmManager() { + return Mockito.mock(UserVmManager.class); + } - public static class Library implements TypeFilter { + @Bean + public StorageManager StorageManager() { + return Mockito.mock(StorageManager.class); + } - @Override - public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException { - mdr.getClassMetadata().getClassName(); - ComponentScan cs = StorageAllocatorTestConfiguration.class.getAnnotation(ComponentScan.class); - return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs); - } - } + public static class Library implements TypeFilter { + + @Override + public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException { + mdr.getClassMetadata().getClassName(); + ComponentScan cs = StorageAllocatorTestConfiguration.class.getAnnotation(ComponentScan.class); + return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs); + } + } } diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/cache/manager/StorageCacheReplacementAlgorithmLRUTest.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/cache/manager/StorageCacheReplacementAlgorithmLRUTest.java new file mode 100644 index 00000000000..7d40ea796e1 --- /dev/null +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/cache/manager/StorageCacheReplacementAlgorithmLRUTest.java @@ -0,0 +1,226 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.cache.manager; + +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.Storage; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.utils.DateUtil; +import com.cloud.utils.component.ComponentContext; +import junit.framework.Assert; +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.DataStoreProvider; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import javax.inject.Inject; +import java.util.Calendar; +import java.util.Date; +import java.util.UUID; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = "classpath:/storageContext.xml") +public class StorageCacheReplacementAlgorithmLRUTest { + @Inject + VMTemplateDao templateDao; + @Inject + ImageStoreDao imageStoreDao; + @Inject + TemplateDataStoreDao templateDataStoreDao; + @Inject + StorageCacheReplacementAlgorithmLRU cacheReplacementAlgorithm; + @Inject + DataStoreManager dataStoreManager; + @Before + public void setup() throws Exception { + ComponentContext.initComponentsLifeCycle(); + } + @Test + public void testSelectObject() { + cacheReplacementAlgorithm.setUnusedTimeInterval(1); + try { + VMTemplateVO template = new VMTemplateVO(); + template.setTemplateType(Storage.TemplateType.USER); + template.setUrl(UUID.randomUUID().toString()); + template.setUniqueName(UUID.randomUUID().toString()); + template.setName(UUID.randomUUID().toString()); + template.setPublicTemplate(true); + template.setFeatured(true); + template.setRequiresHvm(true); + template.setBits(64); + template.setFormat(Storage.ImageFormat.VHD); + template.setEnablePassword(true); + template.setEnableSshKey(true); + template.setGuestOSId(1); + template.setBootable(true); + template.setPrepopulate(true); + template.setCrossZones(true); + template.setExtractable(true); + template = templateDao.persist(template); + + VMTemplateVO template2 = new VMTemplateVO(); + template2.setTemplateType(Storage.TemplateType.USER); + template2.setUrl(UUID.randomUUID().toString()); + template2.setUniqueName(UUID.randomUUID().toString()); + template2.setName(UUID.randomUUID().toString()); + template2.setPublicTemplate(true); + template2.setFeatured(true); + template2.setRequiresHvm(true); + template2.setBits(64); + template2.setFormat(Storage.ImageFormat.VHD); + template2.setEnablePassword(true); + template2.setEnableSshKey(true); + template2.setGuestOSId(1); + template2.setBootable(true); + template2.setPrepopulate(true); + template2.setCrossZones(true); + template2.setExtractable(true); + template2 = templateDao.persist(template2); + + ImageStoreVO imageStoreVO = new ImageStoreVO(); + imageStoreVO.setRole(DataStoreRole.ImageCache); + imageStoreVO.setName(UUID.randomUUID().toString()); + imageStoreVO.setProviderName(DataStoreProvider.NFS_IMAGE); + imageStoreVO.setProtocol("nfs"); + imageStoreVO.setUrl(UUID.randomUUID().toString()); + imageStoreVO = imageStoreDao.persist(imageStoreVO); + + Calendar cal = Calendar.getInstance(); + cal.setTime(DateUtil.now()); + cal.add(Calendar.DAY_OF_MONTH, -2); + Date date = cal.getTime(); + + TemplateDataStoreVO templateStoreVO1 = new TemplateDataStoreVO(); + templateStoreVO1.setLastUpdated(date); + templateStoreVO1.setDataStoreRole(DataStoreRole.ImageCache); + templateStoreVO1.setDataStoreId(imageStoreVO.getId()); + templateStoreVO1.setState(ObjectInDataStoreStateMachine.State.Ready); + templateStoreVO1.setCopy(true); + templateStoreVO1.setTemplateId(template.getId()); + templateDataStoreDao.persist(templateStoreVO1); + + TemplateDataStoreVO templateStoreVO2 = new TemplateDataStoreVO(); + templateStoreVO2.setLastUpdated(date); + templateStoreVO2.setDataStoreRole(DataStoreRole.ImageCache); + templateStoreVO2.setDataStoreId(imageStoreVO.getId()); + templateStoreVO2.setState(ObjectInDataStoreStateMachine.State.Ready); + templateStoreVO2.setCopy(true); + templateStoreVO2.setTemplateId(template2.getId()); + templateDataStoreDao.persist(templateStoreVO2); + + DataStore store = dataStoreManager.getDataStore(imageStoreVO.getId(), DataStoreRole.ImageCache); + Assert.assertNotNull(cacheReplacementAlgorithm.chooseOneToBeReplaced(store)); + + } catch (Exception e) { + Assert.fail(); + } + } + + + @Test + public void testSelectObjectFailed() { + cacheReplacementAlgorithm.setUnusedTimeInterval(1); + try { + VMTemplateVO template = new VMTemplateVO(); + template.setTemplateType(Storage.TemplateType.USER); + template.setUrl(UUID.randomUUID().toString()); + template.setUniqueName(UUID.randomUUID().toString()); + template.setName(UUID.randomUUID().toString()); + template.setPublicTemplate(true); + template.setFeatured(true); + template.setRequiresHvm(true); + template.setBits(64); + template.setFormat(Storage.ImageFormat.VHD); + template.setEnablePassword(true); + template.setEnableSshKey(true); + template.setGuestOSId(1); + template.setBootable(true); + template.setPrepopulate(true); + template.setCrossZones(true); + template.setExtractable(true); + template = templateDao.persist(template); + + VMTemplateVO template2 = new VMTemplateVO(); + template2.setTemplateType(Storage.TemplateType.USER); + template2.setUrl(UUID.randomUUID().toString()); + template2.setUniqueName(UUID.randomUUID().toString()); + template2.setName(UUID.randomUUID().toString()); + template2.setPublicTemplate(true); + template2.setFeatured(true); + template2.setRequiresHvm(true); + template2.setBits(64); + template2.setFormat(Storage.ImageFormat.VHD); + template2.setEnablePassword(true); + template2.setEnableSshKey(true); + template2.setGuestOSId(1); + template2.setBootable(true); + template2.setPrepopulate(true); + template2.setCrossZones(true); + template2.setExtractable(true); + template2 = templateDao.persist(template2); + + ImageStoreVO imageStoreVO = new ImageStoreVO(); + imageStoreVO.setRole(DataStoreRole.ImageCache); + imageStoreVO.setName(UUID.randomUUID().toString()); + imageStoreVO.setProviderName(DataStoreProvider.NFS_IMAGE); + imageStoreVO.setProtocol("nfs"); + imageStoreVO.setUrl(UUID.randomUUID().toString()); + imageStoreVO = imageStoreDao.persist(imageStoreVO); + + + Date date = DateUtil.now(); + + TemplateDataStoreVO templateStoreVO1 = new TemplateDataStoreVO(); + templateStoreVO1.setLastUpdated(date); + templateStoreVO1.setDataStoreRole(DataStoreRole.ImageCache); + templateStoreVO1.setDataStoreId(imageStoreVO.getId()); + templateStoreVO1.setState(ObjectInDataStoreStateMachine.State.Ready); + templateStoreVO1.setCopy(true); + templateStoreVO1.setTemplateId(template.getId()); + templateDataStoreDao.persist(templateStoreVO1); + + TemplateDataStoreVO templateStoreVO2 = new TemplateDataStoreVO(); + templateStoreVO2.setLastUpdated(date); + templateStoreVO2.setDataStoreRole(DataStoreRole.ImageCache); + templateStoreVO2.setDataStoreId(imageStoreVO.getId()); + templateStoreVO2.setState(ObjectInDataStoreStateMachine.State.Ready); + templateStoreVO2.setCopy(true); + templateStoreVO2.setTemplateId(template2.getId()); + templateDataStoreDao.persist(templateStoreVO2); + + DataStore store = dataStoreManager.getDataStore(imageStoreVO.getId(), DataStoreRole.ImageCache); + Assert.assertNull(cacheReplacementAlgorithm.chooseOneToBeReplaced(store)); + + } catch (Exception e) { + Assert.fail(); + } + } + + +} diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/AopTest.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/AopTest.java index bde5804e624..3fee7ac3bea 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/AopTest.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/AopTest.java @@ -23,7 +23,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; -@Target({TYPE, METHOD}) +@Target({ TYPE, METHOD }) @Retention(RUNTIME) public @interface AopTest { diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/AopTestAdvice.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/AopTestAdvice.java index 63669c453d7..902f5953eb1 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/AopTestAdvice.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/AopTestAdvice.java @@ -21,14 +21,14 @@ import org.aspectj.lang.ProceedingJoinPoint; import com.cloud.utils.db.Transaction; public class AopTestAdvice { - public Object AopTestMethod(ProceedingJoinPoint call) throws Throwable { - Transaction txn = Transaction.open(call.getSignature().getName()); - Object ret = null; - try { - ret = call.proceed(); - } finally { - txn.close(); - } - return ret; - } + public Object AopTestMethod(ProceedingJoinPoint call) throws Throwable { + Transaction txn = Transaction.open(call.getSignature().getName()); + Object ret = null; + try { + ret = call.proceed(); + } finally { + txn.close(); + } + return ret; + } } diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java index 0dcdebd6553..60f86d86ddb 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java @@ -20,9 +20,9 @@ import java.io.IOException; import org.apache.cloudstack.acl.APIChecker; import org.apache.cloudstack.engine.service.api.OrchestrationService; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; import org.apache.cloudstack.framework.rpc.RpcProvider; -import org.apache.cloudstack.storage.HostEndpointRpcServer; -import org.apache.cloudstack.storage.endpoint.EndPointSelector; +import org.apache.cloudstack.storage.cache.manager.StorageCacheManagerImpl; import org.apache.cloudstack.storage.test.ChildTestConfiguration.Library; import org.apache.cloudstack.test.utils.SpringUtils; import org.mockito.Mockito; @@ -43,15 +43,19 @@ import com.cloud.cluster.agentlb.dao.HostTransferMapDaoImpl; import com.cloud.configuration.dao.ConfigurationDaoImpl; import com.cloud.dc.ClusterDetailsDaoImpl; import com.cloud.dc.dao.ClusterDaoImpl; +import com.cloud.dc.dao.DataCenterDaoImpl; import com.cloud.dc.dao.DataCenterIpAddressDaoImpl; import com.cloud.dc.dao.DataCenterLinkLocalIpAddressDaoImpl; import com.cloud.dc.dao.DataCenterVnetDaoImpl; import com.cloud.dc.dao.DcDetailsDaoImpl; import com.cloud.dc.dao.HostPodDaoImpl; import com.cloud.dc.dao.PodVlanDaoImpl; +import com.cloud.domain.dao.DomainDaoImpl; +import com.cloud.host.dao.HostDao; import com.cloud.host.dao.HostDaoImpl; import com.cloud.host.dao.HostDetailsDaoImpl; import com.cloud.host.dao.HostTagsDaoImpl; +import com.cloud.hypervisor.HypervisorGuruManager; import com.cloud.resource.ResourceManager; import com.cloud.server.ManagementServer; import com.cloud.server.auth.UserAuthenticator; @@ -61,6 +65,7 @@ import com.cloud.storage.StorageManager; import com.cloud.storage.VolumeManager; import com.cloud.storage.dao.DiskOfferingDaoImpl; import com.cloud.storage.dao.SnapshotDaoImpl; +import com.cloud.storage.dao.StoragePoolDetailsDaoImpl; import com.cloud.storage.dao.StoragePoolHostDaoImpl; import com.cloud.storage.dao.StoragePoolWorkDaoImpl; import com.cloud.storage.dao.VMTemplateDaoImpl; @@ -70,11 +75,16 @@ import com.cloud.storage.dao.VMTemplatePoolDaoImpl; import com.cloud.storage.dao.VMTemplateZoneDaoImpl; import com.cloud.storage.dao.VolumeDaoImpl; import com.cloud.storage.dao.VolumeHostDaoImpl; +import com.cloud.storage.download.DownloadMonitorImpl; import com.cloud.storage.s3.S3Manager; +import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.storage.snapshot.SnapshotManager; import com.cloud.storage.swift.SwiftManager; import com.cloud.tags.dao.ResourceTagsDaoImpl; import com.cloud.template.TemplateManager; +import com.cloud.user.AccountManager; +import com.cloud.user.ResourceLimitService; +import com.cloud.user.dao.AccountDaoImpl; import com.cloud.user.dao.UserDaoImpl; import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.dao.ConsoleProxyDaoImpl; @@ -85,137 +95,138 @@ import com.cloud.vm.dao.UserVmDaoImpl; import com.cloud.vm.dao.UserVmDetailsDaoImpl; import com.cloud.vm.dao.VMInstanceDaoImpl; import com.cloud.vm.snapshot.dao.VMSnapshotDaoImpl; + @Configuration -@ComponentScan(basePackageClasses={ - NicDaoImpl.class, - VMInstanceDaoImpl.class, - VMTemplateHostDaoImpl.class, - VolumeHostDaoImpl.class, - VolumeDaoImpl.class, - VMTemplatePoolDaoImpl.class, - ResourceTagsDaoImpl.class, - VMTemplateDaoImpl.class, - MockStorageMotionStrategy.class, - ConfigurationDaoImpl.class, - ClusterDaoImpl.class, - HostPodDaoImpl.class, - VMTemplateZoneDaoImpl.class, - VMTemplateDetailsDaoImpl.class, - HostDaoImpl.class, - HostDetailsDaoImpl.class, - HostTagsDaoImpl.class, - HostTransferMapDaoImpl.class, - DataCenterIpAddressDaoImpl.class, - DataCenterLinkLocalIpAddressDaoImpl.class, - DataCenterVnetDaoImpl.class, - PodVlanDaoImpl.class, - DcDetailsDaoImpl.class, - DiskOfferingDaoImpl.class, - StoragePoolHostDaoImpl.class, - UserVmDaoImpl.class, - UserVmDetailsDaoImpl.class, - ServiceOfferingDaoImpl.class, - CapacityDaoImpl.class, - SnapshotDaoImpl.class, - VMSnapshotDaoImpl.class, - OCFS2ManagerImpl.class, - ClusterDetailsDaoImpl.class, - SecondaryStorageVmDaoImpl.class, - - ConsoleProxyDaoImpl.class, - StoragePoolWorkDaoImpl.class, - UserDaoImpl.class - -}, -includeFilters={@Filter(value=Library.class, type=FilterType.CUSTOM)}, -useDefaultFilters=false -) +@ComponentScan(basePackageClasses = { NicDaoImpl.class, VMInstanceDaoImpl.class, VMTemplateHostDaoImpl.class, + VolumeHostDaoImpl.class, VolumeDaoImpl.class, VMTemplatePoolDaoImpl.class, ResourceTagsDaoImpl.class, + VMTemplateDaoImpl.class, MockStorageMotionStrategy.class, ConfigurationDaoImpl.class, ClusterDaoImpl.class, + HostPodDaoImpl.class, VMTemplateZoneDaoImpl.class, VMTemplateDetailsDaoImpl.class, HostDetailsDaoImpl.class, + HostTagsDaoImpl.class, HostTransferMapDaoImpl.class, DataCenterIpAddressDaoImpl.class, + DataCenterLinkLocalIpAddressDaoImpl.class, DataCenterVnetDaoImpl.class, PodVlanDaoImpl.class, + DcDetailsDaoImpl.class, DiskOfferingDaoImpl.class, StoragePoolHostDaoImpl.class, UserVmDaoImpl.class, + UserVmDetailsDaoImpl.class, ServiceOfferingDaoImpl.class, CapacityDaoImpl.class, SnapshotDaoImpl.class, + VMSnapshotDaoImpl.class, OCFS2ManagerImpl.class, ClusterDetailsDaoImpl.class, SecondaryStorageVmDaoImpl.class, + ConsoleProxyDaoImpl.class, StoragePoolWorkDaoImpl.class, StorageCacheManagerImpl.class, UserDaoImpl.class, + DataCenterDaoImpl.class, StoragePoolDetailsDaoImpl.class, DomainDaoImpl.class, DownloadMonitorImpl.class, + AccountDaoImpl.class }, includeFilters = { @Filter(value = Library.class, type = FilterType.CUSTOM) }, + useDefaultFilters = false) public class ChildTestConfiguration extends TestConfiguration { - - @Bean - public EndPointSelector selector() { - return Mockito.mock(EndPointSelector.class); - } - @Bean - public AgentManager agentMgr() { - return new DirectAgentManagerSimpleImpl(); - } - @Bean - public HostEndpointRpcServer rpcServer() { - return new MockHostEndpointRpcServerDirectCallResource(); + public SecondaryStorageVmManager secondaryStoreageMgr() { + return Mockito.mock(SecondaryStorageVmManager.class); } - + + @Bean + public HostDao hostDao() { + return Mockito.spy(new HostDaoImpl()); + } + + @Bean + public EndPointSelector selector() { + return Mockito.mock(EndPointSelector.class); + } + + @Bean + public AgentManager agentMgr() { + return new DirectAgentManagerSimpleImpl(); + } + + @Bean + public ResourceLimitService limtServe() { + return Mockito.mock(ResourceLimitService.class); + } + + @Bean + public AccountManager acctMgt() { + return Mockito.mock(AccountManager.class); + } + @Bean public RpcProvider rpcProvider() { - return Mockito.mock(RpcProvider.class); + return Mockito.mock(RpcProvider.class); } + @Bean public ClusteredAgentRebalanceService _rebalanceService() { return Mockito.mock(ClusteredAgentRebalanceService.class); } + @Bean public UserAuthenticator authenticator() { return Mockito.mock(UserAuthenticator.class); } + @Bean public OrchestrationService orchSrvc() { return Mockito.mock(OrchestrationService.class); } + @Bean public APIChecker apiChecker() { return Mockito.mock(APIChecker.class); } + @Bean public TemplateManager templateMgr() { - return Mockito.mock(TemplateManager.class); + return Mockito.mock(TemplateManager.class); } - + @Bean public VolumeManager volumeMgr() { - return Mockito.mock(VolumeManager.class); + return Mockito.mock(VolumeManager.class); } + @Bean public SwiftManager switfMgr() { - return Mockito.mock(SwiftManager.class); + return Mockito.mock(SwiftManager.class); } + @Bean public ManagementServer server() { - return Mockito.mock(ManagementServer.class); + return Mockito.mock(ManagementServer.class); } + @Bean public VirtualMachineManager vmMgr() { - return Mockito.mock(VirtualMachineManager.class); + return Mockito.mock(VirtualMachineManager.class); } - + @Bean public S3Manager s3Mgr() { - return Mockito.mock(S3Manager.class); + return Mockito.mock(S3Manager.class); } + @Bean public SnapshotManager snapshotMgr() { return Mockito.mock(SnapshotManager.class); } - + @Bean public ResourceManager resourceMgr() { - return Mockito.mock(ResourceManager.class); + return Mockito.mock(ResourceManager.class); } + @Bean public DomainRouterDao domainRouterDao() { - return Mockito.mock(DomainRouterDao.class); + return Mockito.mock(DomainRouterDao.class); } + @Bean public StorageManager storageMgr() { - return Mockito.mock(StorageManager.class); + return Mockito.mock(StorageManager.class); } - + @Bean public AlertManager alertMgr() { return Mockito.mock(AlertManager.class); } + @Bean + public HypervisorGuruManager hypervisorGuruMgr() { + return Mockito.mock(HypervisorGuruManager.class); + } + public static class Library implements TypeFilter { @Override diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/CloudStackTestNGBase.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/CloudStackTestNGBase.java index dc7223c9e84..26f4c5da0e9 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/CloudStackTestNGBase.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/CloudStackTestNGBase.java @@ -24,7 +24,7 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Parameters; import org.testng.annotations.Test; -import com.cloud.utils.db.DB; +import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.utils.db.Transaction; public class CloudStackTestNGBase extends AbstractTestNGSpringContextTests { @@ -35,36 +35,49 @@ public class CloudStackTestNGBase extends AbstractTestNGSpringContextTests { private String templateUrl; private String localStorageUuid; private String primaryStorageUrl; + private String secondaryStorage; + private String imageInstallPath; + private String scriptPath; + private HypervisorType hypervisor; private Transaction txn; - + + private String s3AccessKey; + private String s3SecretKey; + private String s3EndPoint; + private String s3TemplateBucket; + private String primaryStorageUuid; + private boolean s3UseHttps; + protected void injectMockito() { - + } - + @BeforeMethod(alwaysRun = true) - protected void injectDB(Method testMethod) throws Exception { + protected void injectDB(Method testMethod) throws Exception { txn = Transaction.open(testMethod.getName()); } - + @Test - protected void injectMockitoTest() { + protected void injectMockitoTest() { injectMockito(); } - + @AfterMethod(alwaysRun = true) protected void closeDB(Method testMethod) throws Exception { if (txn != null) { txn.close(); } } - + @BeforeMethod(alwaysRun = true) - @Parameters({"devcloud-host-uuid", "devcloud-host-gateway", "devcloud-host-cidr", - "devcloud-host-ip", "template-url", "devcloud-local-storage-uuid", - "primary-storage-want-to-add"}) - protected void setup(String hostuuid, String gateway, String cidr, - String hostIp, String templateUrl, String localStorageUuid, - String primaryStorage) { + @Parameters({ "devcloud-host-uuid", "devcloud-host-gateway", "devcloud-host-cidr", "devcloud-host-ip", + "template-url", "devcloud-local-storage-uuid", "primary-storage-want-to-add", "devcloud-secondary-storage", + "s3-accesskey", "s3-secretkey", "s3-endpoint", "s3-template-bucket", "s3-usehttps", "image-install-path", + "primary-storage-uuid-want-to-add", "script-path", "hypervisor" }) + protected void setup(String hostuuid, String gateway, String cidr, String hostIp, String templateUrl, + String localStorageUuid, String primaryStorage, String secondaryStorage, String s3_accessKey, + String s3_secretKey, String s3_endpoint, String s3_template_bucket, String s3_usehttps, + String imageInstallPath, String primaryStorageUuid, String scriptPath, String hypervisor) { this.hostGuid = hostuuid; this.hostGateway = gateway; this.hostCidr = cidr; @@ -72,33 +85,108 @@ public class CloudStackTestNGBase extends AbstractTestNGSpringContextTests { this.templateUrl = templateUrl; this.localStorageUuid = localStorageUuid; this.primaryStorageUrl = primaryStorage; + this.primaryStorageUuid = primaryStorageUuid; + this.imageInstallPath = imageInstallPath; + this.hypervisor = HypervisorType.getType(hypervisor); + this.setSecondaryStorage(secondaryStorage); + // set S3 parameters + this.s3AccessKey = s3_accessKey; + this.s3SecretKey = s3_secretKey; + this.s3EndPoint = s3_endpoint; + this.s3TemplateBucket = s3_template_bucket; + this.s3UseHttps = Boolean.parseBoolean(s3_usehttps); + this.scriptPath = scriptPath; + if (this.scriptPath != null) { + System.setProperty("paths.script", this.getScriptPath()); + } } - + protected String getHostGuid() { return this.hostGuid; } - + protected String getHostGateway() { return this.hostGateway; } - + protected String getHostCidr() { return this.hostCidr; } - + protected String getHostIp() { return this.hostIp; } - + protected String getTemplateUrl() { return this.templateUrl; } - + protected String getLocalStorageUuid() { return this.localStorageUuid; } - + protected String getPrimaryStorageUrl() { return this.primaryStorageUrl; } + + public String getSecondaryStorage() { + return secondaryStorage; + } + + public void setSecondaryStorage(String secondaryStorage) { + this.secondaryStorage = secondaryStorage; + } + + public String getS3AccessKey() { + return s3AccessKey; + } + + public String getS3SecretKey() { + return s3SecretKey; + } + + public String getS3EndPoint() { + return s3EndPoint; + } + + public String getS3TemplateBucket() { + return s3TemplateBucket; + } + + public boolean isS3UseHttps() { + return s3UseHttps; + } + + public String getImageInstallPath() { + return imageInstallPath; + } + + public void setImageInstallPath(String imageInstallPath) { + this.imageInstallPath = imageInstallPath; + } + + public String getPrimaryStorageUuid() { + return primaryStorageUuid; + } + + public void setPrimaryStorageUuid(String primaryStorageUuid) { + this.primaryStorageUuid = primaryStorageUuid; + } + + public String getScriptPath() { + return scriptPath; + } + + public void setScriptPath(String scriptPath) { + this.scriptPath = scriptPath; + } + + public HypervisorType getHypervisor() { + return hypervisor; + } + + public void setHypervisor(HypervisorType hypervisor) { + this.hypervisor = hypervisor; + } + } diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentManagerSimpleImpl.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentManagerSimpleImpl.java index 575bc8e2ba2..ac50e9bde95 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentManagerSimpleImpl.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentManagerSimpleImpl.java @@ -18,6 +18,8 @@ */ package org.apache.cloudstack.storage.test; +import java.net.URI; +import java.net.URISyntaxException; import java.util.HashMap; import java.util.Map; @@ -35,23 +37,35 @@ import com.cloud.agent.api.SetupCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.manager.AgentAttache; import com.cloud.agent.manager.Commands; +import com.cloud.dc.ClusterDetailsDao; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.dao.ClusterDao; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConnectionException; +import com.cloud.exception.DiscoveryException; import com.cloud.exception.OperationTimedoutException; import com.cloud.host.HostEnvironment; import com.cloud.host.HostVO; import com.cloud.host.Status.Event; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; +import com.cloud.hypervisor.vmware.VmwareServerDiscoverer; import com.cloud.hypervisor.xen.resource.XcpOssResource; import com.cloud.resource.ServerResource; import com.cloud.utils.component.ManagerBase; +import com.cloud.utils.exception.CloudRuntimeException; public class DirectAgentManagerSimpleImpl extends ManagerBase implements AgentManager { private static final Logger logger = Logger.getLogger(DirectAgentManagerSimpleImpl.class); private Map hostResourcesMap = new HashMap(); @Inject HostDao hostDao; + @Inject + ClusterDao clusterDao; + @Inject + ClusterDetailsDao clusterDetailsDao; + @Override public boolean configure(String name, Map params) throws ConfigurationException { // TODO Auto-generated method stub @@ -78,7 +92,15 @@ public class DirectAgentManagerSimpleImpl extends ManagerBase implements AgentMa @Override public Answer easySend(Long hostId, Command cmd) { - // TODO Auto-generated method stub + try { + return this.send(hostId, cmd); + } catch (AgentUnavailableException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (OperationTimedoutException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } return null; } @@ -91,37 +113,74 @@ public class DirectAgentManagerSimpleImpl extends ManagerBase implements AgentMa params.put("password", "password"); params.put("zone", String.valueOf(host.getDataCenterId())); params.put("pod", String.valueOf(host.getPodId())); - + ServerResource resource = null; if (host.getHypervisorType() == HypervisorType.XenServer) { - resource = new XcpOssResource(); - } - - try { - resource.configure(host.getName(), params); - hostResourcesMap.put(hostId, resource); - } catch (ConfigurationException e) { - logger.debug("Failed to load resource:" + e.toString()); + resource = new XcpOssResource(); + try { + resource.configure(host.getName(), params); + + } catch (ConfigurationException e) { + logger.debug("Failed to load resource:" + e.toString()); + } + } else if (host.getHypervisorType() == HypervisorType.KVM) { + resource = new LibvirtComputingResource(); + try { + params.put("public.network.device", "cloudbr0"); + params.put("private.network.device", "cloudbr0"); + resource.configure(host.getName(), params); + } catch (ConfigurationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } else if (host.getHypervisorType() == HypervisorType.VMware) { + ClusterVO cluster = clusterDao.findById(host.getClusterId()); + String url = clusterDetailsDao.findDetail(cluster.getId(), "url").getValue(); + URI uri; + try { + uri = new URI(url); + String userName = clusterDetailsDao.findDetail(cluster.getId(), "username").getValue(); + String password = clusterDetailsDao.findDetail(cluster.getId(), "password").getValue(); + VmwareServerDiscoverer discover = new VmwareServerDiscoverer(); + + Map> resources = discover.find(host.getDataCenterId(), + host.getPodId(), host.getClusterId(), uri, userName, password, null); + for (Map.Entry> entry : resources.entrySet()) { + resource = entry.getKey(); + } + if (resource == null) { + throw new CloudRuntimeException("can't find resource"); + } + } catch (DiscoveryException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (URISyntaxException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } + + hostResourcesMap.put(hostId, resource); HostEnvironment env = new HostEnvironment(); SetupCommand cmd = new SetupCommand(env); cmd.setNeedSetup(true); - + resource.executeRequest(cmd); } @Override - public synchronized Answer send(Long hostId, Command cmd) throws AgentUnavailableException, OperationTimedoutException { + public synchronized Answer send(Long hostId, Command cmd) throws AgentUnavailableException, + OperationTimedoutException { ServerResource resource = hostResourcesMap.get(hostId); if (resource == null) { loadResource(hostId); resource = hostResourcesMap.get(hostId); } - + if (resource == null) { return null; } - + Answer answer = resource.executeRequest(cmd); return answer; } @@ -133,7 +192,8 @@ public class DirectAgentManagerSimpleImpl extends ManagerBase implements AgentMa } @Override - public Answer[] send(Long hostId, Commands cmds, int timeout) throws AgentUnavailableException, OperationTimedoutException { + public Answer[] send(Long hostId, Commands cmds, int timeout) throws AgentUnavailableException, + OperationTimedoutException { // TODO Auto-generated method stub return null; } @@ -174,18 +234,6 @@ public class DirectAgentManagerSimpleImpl extends ManagerBase implements AgentMa return null; } - @Override - public void sendToSecStorage(HostVO ssHost, Command cmd, Listener listener) throws AgentUnavailableException { - // TODO Auto-generated method stub - - } - - @Override - public Answer sendToSecStorage(HostVO ssHost, Command cmd) { - // TODO Auto-generated method stub - return null; - } - @Override public boolean tapLoadingAgents(Long hostId, TapAgentsAction action) { // TODO Auto-generated method stub @@ -193,7 +241,8 @@ public class DirectAgentManagerSimpleImpl extends ManagerBase implements AgentMa } @Override - public AgentAttache handleDirectConnectAgent(HostVO host, StartupCommand[] cmds, ServerResource resource, boolean forRebalance) throws ConnectionException { + public AgentAttache handleDirectConnectAgent(HostVO host, StartupCommand[] cmds, ServerResource resource, + boolean forRebalance) throws ConnectionException { // TODO Auto-generated method stub return null; } @@ -240,10 +289,10 @@ public class DirectAgentManagerSimpleImpl extends ManagerBase implements AgentMa return null; } - @Override - public void disconnectWithInvestigation(long hostId, Event event) { - // TODO Auto-generated method stub - - } + @Override + public void disconnectWithInvestigation(long hostId, Event event) { + // TODO Auto-generated method stub + + } } diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentTest.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentTest.java index fc4aea85822..b52b1e4fe91 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentTest.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentTest.java @@ -22,14 +22,14 @@ import java.util.UUID; import javax.inject.Inject; -import org.apache.cloudstack.storage.to.ImageDataStoreTO; -import org.apache.cloudstack.storage.to.ImageOnPrimaryDataStoreTO; -import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; -import org.apache.cloudstack.storage.to.TemplateTO; import org.mockito.Mockito; import org.springframework.test.context.ContextConfiguration; import org.testng.annotations.Test; +import org.apache.cloudstack.storage.to.ImageStoreTO; +import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; +import org.apache.cloudstack.storage.to.TemplateObjectTO; + import com.cloud.agent.AgentManager; import com.cloud.agent.api.Command; import com.cloud.agent.api.ReadyCommand; @@ -50,11 +50,11 @@ import com.cloud.org.Cluster.ClusterType; import com.cloud.org.Managed.ManagedState; import com.cloud.resource.ResourceState; -@ContextConfiguration(locations="classpath:/storageContext.xml") +@ContextConfiguration(locations = "classpath:/storageContext.xml") public class DirectAgentTest extends CloudStackTestNGBase { @Inject AgentManager agentMgr; - @Inject + @Inject HostDao hostDao; @Inject HostPodDao podDao; @@ -65,39 +65,40 @@ public class DirectAgentTest extends CloudStackTestNGBase { private long dcId; private long clusterId; private long hostId; - + @Test(priority = -1) public void setUp() { - HostVO host = hostDao.findByGuid(this.getHostGuid()); + HostVO host = hostDao.findByGuid(getHostGuid()); if (host != null) { hostId = host.getId(); dcId = host.getDataCenterId(); clusterId = host.getClusterId(); return; } - //create data center - DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24", - null, null, NetworkType.Basic, null, null, true, true, null, null); + // create data center + DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, + "10.0.0.1/24", null, null, NetworkType.Basic, null, null, true, true, null, null); dc = dcDao.persist(dc); dcId = dc.getId(); - //create pod + // create pod - HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), this.getHostGateway(), this.getHostCidr(), 8, "test"); + HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), getHostGateway(), getHostCidr(), 8, + "test"); pod = podDao.persist(pod); - //create xen cluster + // create xen cluster ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster"); cluster.setHypervisorType(HypervisorType.XenServer.toString()); cluster.setClusterType(ClusterType.CloudManaged); cluster.setManagedState(ManagedState.Managed); cluster = clusterDao.persist(cluster); clusterId = cluster.getId(); - //create xen host + // create xen host - host = new HostVO(this.getHostGuid()); + host = new HostVO(getHostGuid()); host.setName("devcloud xen host"); host.setType(Host.Type.Routing); host.setHypervisorType(HypervisorType.XenServer); - host.setPrivateIpAddress(this.getHostIp()); + host.setPrivateIpAddress(getHostIp()); host.setDataCenterId(dc.getId()); host.setVersion("6.0.1"); host.setAvailable(true); @@ -109,7 +110,7 @@ public class DirectAgentTest extends CloudStackTestNGBase { host = hostDao.persist(host); hostId = host.getId(); } - + @Test public void testInitResource() { ReadyCommand cmd = new ReadyCommand(dcId); @@ -123,23 +124,24 @@ public class DirectAgentTest extends CloudStackTestNGBase { e.printStackTrace(); } } - + @Test public void testDownloadTemplate() { - ImageOnPrimaryDataStoreTO image = Mockito.mock(ImageOnPrimaryDataStoreTO.class); + ImageStoreTO image = Mockito.mock(ImageStoreTO.class); PrimaryDataStoreTO primaryStore = Mockito.mock(PrimaryDataStoreTO.class); - Mockito.when(primaryStore.getUuid()).thenReturn(this.getLocalStorageUuid()); - Mockito.when(image.getPrimaryDataStore()).thenReturn(primaryStore); - - ImageDataStoreTO imageStore = Mockito.mock(ImageDataStoreTO.class); - Mockito.when(imageStore.getType()).thenReturn("http"); - - TemplateTO template = Mockito.mock(TemplateTO.class); - Mockito.when(template.getPath()).thenReturn(this.getTemplateUrl()); - Mockito.when(template.getImageDataStore()).thenReturn(imageStore); - - Mockito.when(image.getTemplate()).thenReturn(template); - //CopyTemplateToPrimaryStorageCmd cmd = new CopyTemplateToPrimaryStorageCmd(image); + Mockito.when(primaryStore.getUuid()).thenReturn(getLocalStorageUuid()); + // Mockito.when(image.get).thenReturn(primaryStore); + + ImageStoreTO imageStore = Mockito.mock(ImageStoreTO.class); + Mockito.when(imageStore.getProtocol()).thenReturn("http"); + + TemplateObjectTO template = Mockito.mock(TemplateObjectTO.class); + Mockito.when(template.getPath()).thenReturn(getTemplateUrl()); + Mockito.when(template.getDataStore()).thenReturn(imageStore); + + // Mockito.when(image.getTemplate()).thenReturn(template); + // CopyTemplateToPrimaryStorageCmd cmd = new + // CopyTemplateToPrimaryStorageCmd(image); Command cmd = null; try { agentMgr.send(hostId, cmd); diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHostEndpointRpcServerDirectCallResource.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHostEndpointRpcServerDirectCallResource.java deleted file mode 100644 index 4ec2436b06d..00000000000 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHostEndpointRpcServerDirectCallResource.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.test; - -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import javax.inject.Inject; - -import org.apache.cloudstack.framework.async.AsyncCompletionCallback; -import org.apache.cloudstack.storage.HostEndpointRpcServer; -import org.apache.cloudstack.storage.HypervisorHostEndPoint; -import org.apache.log4j.Logger; - -import com.cloud.agent.AgentManager; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.Command; -import com.cloud.exception.AgentUnavailableException; -import com.cloud.exception.OperationTimedoutException; -import com.cloud.utils.component.ComponentContext; - - -public class MockHostEndpointRpcServerDirectCallResource implements HostEndpointRpcServer { - private static final Logger s_logger = Logger.getLogger(MockHostEndpointRpcServerDirectCallResource.class); - private ScheduledExecutorService executor; - @Inject - AgentManager agentMgr; - public MockHostEndpointRpcServerDirectCallResource() { - executor = Executors.newScheduledThreadPool(10); - } - - public void sendCommandAsync(HypervisorHostEndPoint host, final Command command, final AsyncCompletionCallback callback) { - // new MockRpcCallBack(host.getHostId(), command, callback); - MockRpcCallBack run = ComponentContext.inject(MockRpcCallBack.class); - run.setCallback(callback); - run.setCmd(command); - run.setHostId(host.getId()); - executor.schedule(run, 10, TimeUnit.SECONDS); - } - - @Override - public Answer sendCommand(HypervisorHostEndPoint host, Command command) { - Answer answer; - try { - answer = agentMgr.send(host.getId(), command); - return answer; - } catch (AgentUnavailableException e) { - return null; - } catch (OperationTimedoutException e) { - return null; - } - } -} diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHypervisorHostEndPointRpcServer.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHypervisorHostEndPointRpcServer.java deleted file mode 100644 index 8fc161bae1e..00000000000 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHypervisorHostEndPointRpcServer.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.test; - -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import org.apache.cloudstack.framework.async.AsyncCompletionCallback; -import org.apache.cloudstack.storage.HostEndpointRpcServer; -import org.apache.cloudstack.storage.HypervisorHostEndPoint; - -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.Command; - -public class MockHypervisorHostEndPointRpcServer implements HostEndpointRpcServer { - private ScheduledExecutorService executor; - public MockHypervisorHostEndPointRpcServer() { - executor = Executors.newScheduledThreadPool(10); - } - - protected class MockRpcCallBack implements Runnable { - private final Command cmd; - private final AsyncCompletionCallback callback; - public MockRpcCallBack(Command cmd, final AsyncCompletionCallback callback) { - this.cmd = cmd; - this.callback = callback; - } - @Override - public void run() { - try { - Answer answer = new Answer(cmd, false, "unknown command"); - /*if (cmd instanceof CopyTemplateToPrimaryStorageCmd) { - answer = new CopyTemplateToPrimaryStorageAnswer(cmd, UUID.randomUUID().toString()); - } else if (cmd instanceof CreateVolumeFromBaseImageCommand) { - answer = new CreateVolumeAnswer(cmd, UUID.randomUUID().toString()); - }*/ - - callback.complete(answer); - } catch (Exception e) { - e.printStackTrace(); - } - } - - } - - public void sendCommandAsync(HypervisorHostEndPoint host, final Command command, final AsyncCompletionCallback callback) { - executor.schedule(new MockRpcCallBack(command, callback), 10, TimeUnit.SECONDS); - } - - @Override - public Answer sendCommand(HypervisorHostEndPoint host, Command command) { - // TODO Auto-generated method stub - return null; - } -} diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockLocalHostEndPoint.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockLocalHostEndPoint.java new file mode 100644 index 00000000000..74caba3a86c --- /dev/null +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockLocalHostEndPoint.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.test; + +import org.apache.cloudstack.storage.LocalHostEndpoint; +import org.apache.cloudstack.storage.command.CopyCommand; +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.command.DownloadCommand; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; + +public class MockLocalHostEndPoint extends LocalHostEndpoint { + @Override + public Answer sendMessage(Command cmd) { + if ((cmd instanceof CopyCommand) || (cmd instanceof DownloadCommand) + || (cmd instanceof DeleteCommand)) { + return resource.executeRequest(cmd); + } + // TODO Auto-generated method stub + return new Answer(cmd, false, "unsupported command:" + cmd.toString()); + } +} diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockRpcCallBack.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockRpcCallBack.java index e0ffb48281a..60308da274b 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockRpcCallBack.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockRpcCallBack.java @@ -32,20 +32,20 @@ public class MockRpcCallBack implements Runnable { AgentManager agentMgr; private Command cmd; private long hostId; - private AsyncCompletionCallback callback; - + private AsyncCompletionCallback callback; + public void setCmd(Command cmd) { this.cmd = cmd; } - + public void setHostId(long hostId) { this.hostId = hostId; } - + public void setCallback(AsyncCompletionCallback callback) { this.callback = callback; } - + @Override @DB public void run() { @@ -56,5 +56,5 @@ public class MockRpcCallBack implements Runnable { s_logger.debug("send command failed:", e); } } - + } diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java index a84f3087d59..52ccf410c8d 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java @@ -21,11 +21,11 @@ package org.apache.cloudstack.storage.test; import java.util.Map; import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; -import org.apache.cloudstack.storage.motion.DataMotionStrategy; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.host.Host; @@ -44,8 +44,7 @@ public class MockStorageMotionStrategy implements DataMotionStrategy { } @Override - public Void copyAsync(DataObject srcData, DataObject destData, - AsyncCompletionCallback callback) { + public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback callback) { CopyCommandResult result = new CopyCommandResult("something", null); callback.complete(result); return null; diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/S3TemplateTest.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/S3TemplateTest.java new file mode 100644 index 00000000000..0bb724d10e4 --- /dev/null +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/S3TemplateTest.java @@ -0,0 +1,180 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.test; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +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.DataStoreProvider; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService.TemplateApiResult; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; +import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.storage.LocalHostEndpoint; +import org.apache.cloudstack.storage.MockLocalNfsSecondaryStorageResource; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailVO; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; +import org.apache.cloudstack.storage.image.datastore.ImageStoreHelper; +import org.mockito.Matchers; +import org.mockito.Mockito; +import org.springframework.test.context.ContextConfiguration; +import org.testng.annotations.Test; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertNotNull; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.DataCenter.NetworkType; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ScopeType; +import com.cloud.storage.Storage; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.Storage.TemplateType; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.download.DownloadMonitorImpl; +import com.cloud.utils.component.ComponentContext; + +@ContextConfiguration(locations = { "classpath:/storageContext.xml" }) +public class S3TemplateTest extends CloudStackTestNGBase { + @Inject + DataCenterDao dcDao; + ImageStoreVO imageStore; + ImageStoreDetailVO imageStoreDetail; + @Inject + ImageStoreDao imageStoreDao; + @Inject + TemplateService templateSvr; + @Inject + VMTemplateDao templateDao; + @Inject + TemplateDataFactory templateFactory; + @Inject + DataStoreManager dataStoreMgr; + @Inject + EndPointSelector epSelector; + @Inject + DownloadMonitorImpl downloadMonitor; + @Inject + ImageStoreHelper imageStoreHelper; + @Inject + StorageCacheManager cacheMgr; + long dcId; + long templateId; + + @Test(priority = -1) + public void setUp() { + ComponentContext.initComponentsLifeCycle(); + // create data center + DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, + "10.0.0.1/24", null, null, NetworkType.Basic, null, null, true, true, null, null); + dc = dcDao.persist(dc); + dcId = dc.getId(); + + // add s3 image store + Map sParams = new HashMap(); + sParams.put("name", "test"); + sParams.put("protocol", "http"); + sParams.put("providerName", "S3"); + sParams.put("scope", ScopeType.REGION); + sParams.put("role", DataStoreRole.Image); + Map sDetails = new HashMap(); + sDetails.put(ApiConstants.S3_ACCESS_KEY, this.getS3AccessKey()); + sDetails.put(ApiConstants.S3_SECRET_KEY, this.getS3SecretKey()); + sDetails.put(ApiConstants.S3_BUCKET_NAME, this.getS3TemplateBucket()); + sDetails.put(ApiConstants.S3_END_POINT, this.getS3EndPoint()); + this.imageStoreHelper.createImageStore(sParams, sDetails); + + // add nfs cache storage + Map cParams = new HashMap(); + cParams.put("name", "testCache"); + cParams.put("protocol", "nfs"); + cParams.put("providerName", DataStoreProvider.NFS_IMAGE); + cParams.put("scope", ScopeType.ZONE); + cParams.put("role", DataStoreRole.ImageCache); + cParams.put("url", this.getSecondaryStorage()); + cParams.put("zoneId", dcId); + this.imageStoreHelper.createImageStore(cParams); + + VMTemplateVO image = new VMTemplateVO(); + image.setTemplateType(TemplateType.SYSTEM); + image.setUrl(this.getTemplateUrl()); + image.setUniqueName(UUID.randomUUID().toString()); + image.setName(UUID.randomUUID().toString()); + image.setPublicTemplate(false); + image.setFeatured(false); + image.setRequiresHvm(false); + image.setBits(64); + image.setFormat(Storage.ImageFormat.VHD); + image.setEnablePassword(false); + image.setEnableSshKey(false); + image.setGuestOSId(133); + image.setBootable(true); + image.setPrepopulate(true); + image.setCrossZones(true); + image.setExtractable(true); + image.setAccountId(2); + image = templateDao.persist(image); + templateId = image.getId(); + + // inject mockito + LocalHostEndpoint ep = new LocalHostEndpoint(); + ep.setResource(new MockLocalNfsSecondaryStorageResource()); + Mockito.when(epSelector.select(Matchers.any(DataObject.class))).thenReturn(ep); + Mockito.when(epSelector.select(Matchers.any(DataStore.class))).thenReturn(ep); + Mockito.when(epSelector.select(Matchers.any(DataObject.class), Matchers.any(DataObject.class))).thenReturn(ep); + } + + @Test(priority = 1) + public void registerTemplate() { + TemplateInfo template = templateFactory.getTemplate(templateId, DataStoreRole.Image); + DataStore store = dataStoreMgr.getImageStore(dcId); + AsyncCallFuture future = new AsyncCallFuture(); + templateSvr.createTemplateAsync(template, store, future); + try { + TemplateApiResult result = future.get(); + assertTrue(result.isSuccess(), "failed to register template: " + result.getResult()); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + assertTrue(false, e.getMessage()); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + assertTrue(false, e.getMessage()); + } + } + + @Test(priority = 2) + public void copyTemplateToCache() { + TemplateInfo template = templateFactory.getTemplate(templateId, DataStoreRole.Image); + DataObject cacheObj = this.cacheMgr.createCacheObject(template, new ZoneScope(dcId)); + assertNotNull(cacheObj, "failed to create cache object"); + } + +} diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java new file mode 100644 index 00000000000..2579a38157d --- /dev/null +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java @@ -0,0 +1,500 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.test; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import javax.inject.Inject; + +import junit.framework.Assert; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +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.DataStoreProvider; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService.TemplateApiResult; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult; +import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.storage.LocalHostEndpoint; +import org.apache.cloudstack.storage.MockLocalNfsSecondaryStorageResource; +import org.apache.cloudstack.storage.RemoteHostEndPoint; +import org.apache.cloudstack.storage.command.CopyCmdAnswer; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.mockito.Matchers; +import org.mockito.Mockito; +import org.springframework.test.context.ContextConfiguration; +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Command; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.DataCenter.NetworkType; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.HostPodVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.HostPodDao; +import com.cloud.host.Host; +import com.cloud.host.Host.Type; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.hypervisor.HypervisorGuruManager; +import com.cloud.org.Cluster.ClusterType; +import com.cloud.org.Managed.ManagedState; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceState; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ScopeType; +import com.cloud.storage.Snapshot; +import com.cloud.storage.SnapshotVO; +import com.cloud.storage.Storage; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.storage.Storage.TemplateType; +import com.cloud.storage.StoragePoolStatus; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.Volume; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.SnapshotDao; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.utils.component.ComponentContext; + +@ContextConfiguration(locations = { "classpath:/storageContext.xml" }) +public class SnapshotTest extends CloudStackTestNGBase { + @Inject + ImageStoreDao imageStoreDao; + ImageStoreVO imageStore; + Long dcId; + Long clusterId; + Long podId; + HostVO host; + String primaryName = "my primary data store"; + DataStore primaryStore; + @Inject + HostDao hostDao; + @Inject + TemplateService imageService; + @Inject + VolumeService volumeService; + @Inject + VMTemplateDao imageDataDao; + @Inject + HostPodDao podDao; + @Inject + ClusterDao clusterDao; + @Inject + DataCenterDao dcDao; + @Inject + PrimaryDataStoreDao primaryStoreDao; + @Inject + DataStoreProviderManager dataStoreProviderMgr; + @Inject + TemplateDataStoreDao templateStoreDao; + @Inject + TemplateDataFactory templateFactory; + @Inject + PrimaryDataStoreDao primaryDataStoreDao; + @Inject + AgentManager agentMgr; + @Inject + HypervisorGuruManager hyGuruMgr; + @Inject + DataStoreManager dataStoreMgr; + @Inject + ResourceManager resourceMgr; + @Inject + VolumeDataFactory volFactory; + @Inject + SnapshotDataFactory snapshotFactory; + @Inject + List snapshotStrategies; + @Inject + SnapshotService snapshotSvr; + @Inject + SnapshotDao snapshotDao; + @Inject + EndPointSelector epSelector; + @Inject + VolumeDao volumeDao; + + long primaryStoreId; + VMTemplateVO image; + String imageStoreName = "testImageStore"; + RemoteHostEndPoint remoteEp; + + @Test(priority = -1) + public void setUp() { + ComponentContext.initComponentsLifeCycle(); + + host = hostDao.findByGuid(this.getHostGuid()); + if (host != null) { + dcId = host.getDataCenterId(); + clusterId = host.getClusterId(); + podId = host.getPodId(); + imageStore = this.imageStoreDao.findByName(imageStoreName); + } else { + // create data center + DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, + "10.0.0.1/24", null, null, NetworkType.Basic, null, null, true, true, null, null); + dc = dcDao.persist(dc); + dcId = dc.getId(); + // create pod + + HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), this.getHostGateway(), + this.getHostCidr(), 8, "test"); + pod = podDao.persist(pod); + podId = pod.getId(); + // create xen cluster + ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster"); + cluster.setHypervisorType(this.getHypervisor().toString()); + cluster.setClusterType(ClusterType.CloudManaged); + cluster.setManagedState(ManagedState.Managed); + cluster = clusterDao.persist(cluster); + clusterId = cluster.getId(); + // create xen host + + host = new HostVO(this.getHostGuid()); + host.setName("devcloud xen host"); + host.setType(Host.Type.Routing); + host.setPrivateIpAddress(this.getHostIp()); + host.setDataCenterId(dc.getId()); + host.setVersion("6.0.1"); + host.setAvailable(true); + host.setSetup(true); + host.setPodId(podId); + host.setLastPinged(0); + host.setResourceState(ResourceState.Enabled); + host.setHypervisorType(this.getHypervisor()); + host.setClusterId(cluster.getId()); + + host = hostDao.persist(host); + + imageStore = new ImageStoreVO(); + imageStore.setName(imageStoreName); + imageStore.setDataCenterId(dcId); + imageStore.setProviderName(DataStoreProvider.NFS_IMAGE); + imageStore.setRole(DataStoreRole.Image); + imageStore.setUrl(this.getSecondaryStorage()); + imageStore.setUuid(UUID.randomUUID().toString()); + imageStore.setProtocol("nfs"); + imageStore = imageStoreDao.persist(imageStore); + } + + image = new VMTemplateVO(); + image.setTemplateType(TemplateType.USER); + image.setUrl(this.getTemplateUrl()); + image.setUniqueName(UUID.randomUUID().toString()); + image.setName(UUID.randomUUID().toString()); + image.setPublicTemplate(true); + image.setFeatured(true); + image.setRequiresHvm(true); + image.setBits(64); + image.setFormat(Storage.ImageFormat.VHD); + image.setEnablePassword(true); + image.setEnableSshKey(true); + image.setGuestOSId(1); + image.setBootable(true); + image.setPrepopulate(true); + image.setCrossZones(true); + image.setExtractable(true); + + image = imageDataDao.persist(image); + + /* + * TemplateDataStoreVO templateStore = new TemplateDataStoreVO(); + * + * templateStore.setDataStoreId(imageStore.getId()); + * templateStore.setDownloadPercent(100); + * templateStore.setDownloadState(Status.DOWNLOADED); + * templateStore.setDownloadUrl(imageStore.getUrl()); + * templateStore.setInstallPath(this.getImageInstallPath()); + * templateStore.setTemplateId(image.getId()); + * templateStoreDao.persist(templateStore); + */ + + DataStore store = this.dataStoreMgr.getDataStore(imageStore.getId(), DataStoreRole.Image); + TemplateInfo template = templateFactory.getTemplate(image.getId(), DataStoreRole.Image); + DataObject templateOnStore = store.create(template); + TemplateObjectTO to = new TemplateObjectTO(); + to.setPath(this.getImageInstallPath()); + to.setFormat(ImageFormat.VHD); + to.setSize(1000L); + CopyCmdAnswer answer = new CopyCmdAnswer(to); + templateOnStore.processEvent(Event.CreateOnlyRequested); + templateOnStore.processEvent(Event.OperationSuccessed, answer); + + } + + @Override + protected void injectMockito() { + List hosts = new ArrayList(); + hosts.add(this.host); + Mockito.when( + resourceMgr.listAllUpAndEnabledHosts((Type) Matchers.any(), Matchers.anyLong(), Matchers.anyLong(), + Matchers.anyLong())).thenReturn(hosts); + + remoteEp = RemoteHostEndPoint.getHypervisorHostEndPoint(this.host.getId(), this.host.getPrivateIpAddress(), + this.host.getPublicIpAddress()); + Mockito.when(epSelector.select(Matchers.any(DataObject.class), Matchers.any(DataObject.class))).thenReturn( + remoteEp); + Mockito.when(epSelector.select(Matchers.any(DataObject.class))).thenReturn(remoteEp); + Mockito.when(epSelector.select(Matchers.any(DataStore.class))).thenReturn(remoteEp); + Mockito.when(hyGuruMgr.getGuruProcessedCommandTargetHost(Matchers.anyLong(), Matchers.any(Command.class))) + .thenReturn(this.host.getId()); + + } + + public DataStore createPrimaryDataStore() { + try { + String uuid = UUID.nameUUIDFromBytes(this.getPrimaryStorageUrl().getBytes()).toString(); + List pools = primaryDataStoreDao.findPoolByName(this.primaryName); + if (pools.size() > 0) { + return this.dataStoreMgr.getPrimaryDataStore(pools.get(0).getId()); + } + + /* + * DataStoreProvider provider = + * dataStoreProviderMgr.getDataStoreProvider + * ("cloudstack primary data store provider"); Map + * params = new HashMap(); URI uri = new + * URI(this.getPrimaryStorageUrl()); params.put("url", + * this.getPrimaryStorageUrl()); params.put("server", + * uri.getHost()); params.put("path", uri.getPath()); + * params.put("protocol", + * Storage.StoragePoolType.NetworkFilesystem); params.put("zoneId", + * dcId); params.put("clusterId", clusterId); params.put("name", + * this.primaryName); params.put("port", 1); params.put("podId", + * this.podId); params.put("roles", + * DataStoreRole.Primary.toString()); params.put("uuid", uuid); + * params.put("providerName", String.valueOf(provider.getName())); + * + * DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle(); + * DataStore store = lifeCycle.initialize(params); ClusterScope + * scope = new ClusterScope(clusterId, podId, dcId); + * lifeCycle.attachCluster(store, scope); + */ + + StoragePoolVO pool = new StoragePoolVO(); + pool.setClusterId(clusterId); + pool.setDataCenterId(dcId); + URI uri = new URI(this.getPrimaryStorageUrl()); + pool.setHostAddress(uri.getHost()); + pool.setPath(uri.getPath()); + pool.setPort(0); + pool.setName(this.primaryName); + pool.setUuid(this.getPrimaryStorageUuid()); + pool.setStatus(StoragePoolStatus.Up); + pool.setPoolType(StoragePoolType.NetworkFilesystem); + pool.setPodId(podId); + pool.setScope(ScopeType.CLUSTER); + pool.setStorageProviderName(DataStoreProvider.DEFAULT_PRIMARY); + pool = this.primaryStoreDao.persist(pool); + DataStore store = this.dataStoreMgr.getPrimaryDataStore(pool.getId()); + return store; + } catch (Exception e) { + return null; + } + } + + private SnapshotVO createSnapshotInDb(VolumeInfo volume) { + Snapshot.Type snapshotType = Snapshot.Type.MANUAL; + SnapshotVO snapshotVO = new SnapshotVO(volume.getDataCenterId(), 2, 1, volume.getId(), 1L, UUID.randomUUID() + .toString(), (short) snapshotType.ordinal(), snapshotType.name(), volume.getSize(), + HypervisorType.XenServer); + return this.snapshotDao.persist(snapshotVO); + } + + private VolumeVO createVolume(Long templateId, long dataStoreId) { + + VolumeVO volume = new VolumeVO(Volume.Type.DATADISK, UUID.randomUUID().toString(), this.dcId, 1L, 1L, 1L, 1000); + volume.setDataCenterId(this.dcId); + volume.setPoolId(dataStoreId); + volume = volumeDao.persist(volume); + return volume; + } + + public VolumeInfo createCopyBaseImage() throws InterruptedException, ExecutionException { + DataStore primaryStore = createPrimaryDataStore(); + primaryStoreId = primaryStore.getId(); + primaryStore = this.dataStoreMgr.getPrimaryDataStore(primaryStoreId); + VolumeVO volume = createVolume(image.getId(), primaryStore.getId()); + VolumeInfo volInfo = this.volFactory.getVolume(volume.getId()); + AsyncCallFuture future = this.volumeService.createVolumeFromTemplateAsync(volInfo, + this.primaryStoreId, this.templateFactory.getTemplate(this.image.getId(), DataStoreRole.Image)); + + VolumeApiResult result; + result = future.get(); + Assert.assertTrue(result.isSuccess()); + return result.getVolume(); + + } + + + + private VMTemplateVO createTemplateInDb() { + VMTemplateVO image = new VMTemplateVO(); + image.setTemplateType(TemplateType.USER); + + image.setUniqueName(UUID.randomUUID().toString()); + image.setName(UUID.randomUUID().toString()); + image.setPublicTemplate(true); + image.setFeatured(true); + image.setRequiresHvm(true); + image.setBits(64); + image.setFormat(Storage.ImageFormat.VHD); + image.setEnablePassword(true); + image.setEnableSshKey(true); + image.setGuestOSId(1); + image.setBootable(true); + image.setPrepopulate(true); + image.setCrossZones(true); + image.setExtractable(true); + image = imageDataDao.persist(image); + return image; + } + + @Test + public void createVolumeFromSnapshot() throws InterruptedException, ExecutionException { + VolumeInfo vol = createCopyBaseImage(); + SnapshotVO snapshotVO = createSnapshotInDb(vol); + SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore()); + boolean result = false; + for (SnapshotStrategy strategy : this.snapshotStrategies) { + if (strategy.canHandle(snapshot)) { + snapshot = strategy.takeSnapshot(snapshot); + result = true; + } + } + + AssertJUnit.assertTrue(result); + + VolumeVO volVO = createVolume(vol.getTemplateId(), vol.getPoolId()); + VolumeInfo newVol = this.volFactory.getVolume(volVO.getId()); + AsyncCallFuture volFuture = this.volumeService.createVolumeFromSnapshot(newVol, newVol.getDataStore(), snapshot); + VolumeApiResult apiResult = volFuture.get(); + Assert.assertTrue(apiResult.isSuccess()); + } + + @Test + public void deleteSnapshot() throws InterruptedException, ExecutionException { + VolumeInfo vol = createCopyBaseImage(); + SnapshotVO snapshotVO = createSnapshotInDb(vol); + SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore()); + SnapshotInfo newSnapshot = null; + for (SnapshotStrategy strategy : this.snapshotStrategies) { + if (strategy.canHandle(snapshot)) { + newSnapshot = strategy.takeSnapshot(snapshot); + } + } + AssertJUnit.assertNotNull(newSnapshot); + + // create another snapshot + for (SnapshotStrategy strategy : this.snapshotStrategies) { + if (strategy.canHandle(snapshot)) { + strategy.deleteSnapshot(newSnapshot.getId()); + } + } + + } + + @Test + public void createTemplateFromSnapshot() throws InterruptedException, ExecutionException { + VolumeInfo vol = createCopyBaseImage(); + SnapshotVO snapshotVO = createSnapshotInDb(vol); + SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore()); + boolean result = false; + for (SnapshotStrategy strategy : this.snapshotStrategies) { + if (strategy.canHandle(snapshot)) { + snapshot = strategy.takeSnapshot(snapshot); + result = true; + } + } + + AssertJUnit.assertTrue(result); + LocalHostEndpoint ep = new LocalHostEndpoint(); + ep.setResource(new MockLocalNfsSecondaryStorageResource()); + Mockito.when(epSelector.select(Matchers.any(DataObject.class), Matchers.any(DataObject.class))).thenReturn(ep); + + try { + VMTemplateVO templateVO = createTemplateInDb(); + TemplateInfo tmpl = this.templateFactory.getTemplate(templateVO.getId(), DataStoreRole.Image); + DataStore imageStore = this.dataStoreMgr.getImageStore(this.dcId); + AsyncCallFuture templateFuture = this.imageService.createTemplateFromSnapshotAsync(snapshot, tmpl, imageStore); + TemplateApiResult apiResult = templateFuture.get(); + Assert.assertTrue(apiResult.isSuccess()); + } finally { + Mockito.when(epSelector.select(Matchers.any(DataObject.class), Matchers.any(DataObject.class))).thenReturn(remoteEp); + } + } + + @Test + public void createSnapshot() throws InterruptedException, ExecutionException { + VolumeInfo vol = createCopyBaseImage(); + SnapshotVO snapshotVO = createSnapshotInDb(vol); + SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore()); + SnapshotInfo newSnapshot = null; + for (SnapshotStrategy strategy : this.snapshotStrategies) { + if (strategy.canHandle(snapshot)) { + newSnapshot = strategy.takeSnapshot(snapshot); + } + } + AssertJUnit.assertNotNull(newSnapshot); + + LocalHostEndpoint ep = new MockLocalHostEndPoint(); + ep.setResource(new MockLocalNfsSecondaryStorageResource()); + Mockito.when(epSelector.select(Matchers.any(DataStore.class))).thenReturn(ep); + + try { + for (SnapshotStrategy strategy : this.snapshotStrategies) { + if (strategy.canHandle(snapshot)) { + boolean res = strategy.deleteSnapshot(newSnapshot.getId()); + Assert.assertTrue(res); + } + } + } finally { + Mockito.when(epSelector.select(Matchers.any(DataStore.class))).thenReturn(remoteEp); + } + } + +} diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/StorageFactoryBean.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/StorageFactoryBean.java index 2ac6dac4c16..53a6464304a 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/StorageFactoryBean.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/StorageFactoryBean.java @@ -16,16 +16,15 @@ // under the License. package org.apache.cloudstack.storage.test; - import org.mockito.Mockito; import org.springframework.beans.factory.FactoryBean; /** - * A {@link FactoryBean} for creating mocked beans based on Mockito so that they + * A {@link FactoryBean} for creating mocked beans based on Mockito so that they * can be {@link @Autowired} into Spring test configurations. - * + * * @author Mattias Severson, Jayway - * + * * @see FactoryBean * @see org.mockito.Mockito */ @@ -35,7 +34,9 @@ public class StorageFactoryBean implements FactoryBean { /** * Creates a Mockito mock instance of the provided class. - * @param classToBeMocked The class to be mocked. + * + * @param classToBeMocked + * The class to be mocked. */ public StorageFactoryBean(Class classToBeMocked) { this.classToBeMocked = classToBeMocked; diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/StorageTest.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/StorageTest.java index 0ee7fe0a431..5db3a0f09b0 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/StorageTest.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/StorageTest.java @@ -23,14 +23,13 @@ import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations="classpath:resource/storageContext.xml") +@ContextConfiguration(locations = "classpath:resource/storageContext.xml") public class StorageTest { - @Test - public void test() { - fail("Not yet implemented"); - } + @Test + public void test() { + fail("Not yet implemented"); + } } diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TemplateTest.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TemplateTest.java new file mode 100644 index 00000000000..da4c17b6041 --- /dev/null +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TemplateTest.java @@ -0,0 +1,167 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.test; + +import static org.testng.Assert.assertTrue; + +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +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.DataStoreProvider; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService.TemplateApiResult; +import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.storage.LocalHostEndpoint; +import org.apache.cloudstack.storage.MockLocalNfsSecondaryStorageResource; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; +import org.mockito.Matchers; +import org.mockito.Mockito; +import org.springframework.test.context.ContextConfiguration; +import org.testng.annotations.Test; + +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.DataCenter.NetworkType; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.Storage; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.Storage.TemplateType; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.download.DownloadMonitorImpl; +import com.cloud.utils.component.ComponentContext; + +@ContextConfiguration(locations = { "classpath:/storageContext.xml" }) +public class TemplateTest extends CloudStackTestNGBase { + @Inject + DataCenterDao dcDao; + ImageStoreVO imageStore; + @Inject + ImageStoreDao imageStoreDao; + @Inject + TemplateService templateSvr; + @Inject + VMTemplateDao templateDao; + @Inject + TemplateDataFactory templateFactory; + @Inject + DataStoreManager dataStoreMgr; + @Inject + EndPointSelector epSelector; + @Inject + DownloadMonitorImpl downloadMonitor; + + long dcId; + long templateId; + + @Test(priority = -1) + public void setUp() { + ComponentContext.initComponentsLifeCycle(); + + // create data center + DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, + "10.0.0.1/24", null, null, NetworkType.Basic, null, null, true, true, null, null); + dc = dcDao.persist(dc); + dcId = dc.getId(); + + imageStore = new ImageStoreVO(); + imageStore.setName("test"); + imageStore.setDataCenterId(dcId); + imageStore.setProviderName(DataStoreProvider.NFS_IMAGE); + imageStore.setRole(DataStoreRole.Image); + imageStore.setUrl(this.getSecondaryStorage()); + imageStore.setUuid(UUID.randomUUID().toString()); + imageStore.setProtocol("nfs"); + imageStore = imageStoreDao.persist(imageStore); + + VMTemplateVO image = new VMTemplateVO(); + image.setTemplateType(TemplateType.USER); + image.setUrl(this.getTemplateUrl()); + image.setUniqueName(UUID.randomUUID().toString()); + image.setName(UUID.randomUUID().toString()); + image.setPublicTemplate(true); + image.setFeatured(true); + image.setRequiresHvm(true); + image.setBits(64); + image.setFormat(Storage.ImageFormat.VHD); + image.setEnablePassword(true); + image.setEnableSshKey(true); + image.setGuestOSId(1); + image.setBootable(true); + image.setPrepopulate(true); + image.setCrossZones(true); + image.setExtractable(true); + + // image.setImageDataStoreId(storeId); + image = templateDao.persist(image); + templateId = image.getId(); + + // inject mockito + LocalHostEndpoint ep = new LocalHostEndpoint(); + ep.setResource(new MockLocalNfsSecondaryStorageResource()); + Mockito.when(epSelector.select(Matchers.any(DataObject.class))).thenReturn(ep); + Mockito.when(epSelector.select(Matchers.any(DataStore.class))).thenReturn(ep); + } + + @Test + public void registerTemplate() { + TemplateInfo template = templateFactory.getTemplate(templateId, DataStoreRole.Image); + DataStore store = dataStoreMgr.getImageStore(dcId); + AsyncCallFuture future = new AsyncCallFuture(); + templateSvr.createTemplateAsync(template, store, future); + try { + TemplateApiResult result = future.get(); + assertTrue(result.isSuccess(), "failed to register template: " + result.getResult()); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + assertTrue(false, e.getMessage()); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + assertTrue(false, e.getMessage()); + } + } + + // @Test + public void deleteTemplate() { + TemplateInfo template = templateFactory.getTemplate(templateId, DataStoreRole.Image); + DataStore store = dataStoreMgr.getImageStore(dcId); + AsyncCallFuture future = new AsyncCallFuture(); + templateSvr.deleteTemplateAsync(template); + try { + TemplateApiResult result = future.get(); + assertTrue(result.isSuccess(), "failed to delete template: " + result.getResult()); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + assertTrue(false, e.getMessage()); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + assertTrue(false, e.getMessage()); + } + } +} diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TestHttp.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TestHttp.java index 8b10f7e3224..11d4931fd7d 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TestHttp.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TestHttp.java @@ -22,28 +22,21 @@ import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; -import java.nio.channels.FileChannel; - import junit.framework.Assert; import org.apache.commons.httpclient.HttpException; -import org.apache.cxf.helpers.IOUtils; -import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpHead; import org.apache.http.impl.client.DefaultHttpClient; import org.junit.Test; -import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; import org.testng.annotations.Parameters; -@ContextConfiguration(locations="classpath:/storageContext.xml") +@ContextConfiguration(locations = "classpath:/storageContext.xml") public class TestHttp extends AbstractTestNGSpringContextTests { @Test @Parameters("template-url") @@ -59,13 +52,13 @@ public class TestHttp extends AbstractTestNGSpringContextTests { System.out.println(response.getFirstHeader("Content-Length").getValue()); File localFile = new File("/tmp/test"); if (!localFile.exists()) { - localFile.createNewFile(); + localFile.createNewFile(); } - + HttpGet getMethod = new HttpGet(templateUrl); response = client.execute(getMethod); HttpEntity entity = response.getEntity(); - + output = new BufferedOutputStream(new FileOutputStream(localFile)); entity.writeTo(output); } catch (HttpException e) { @@ -83,7 +76,7 @@ public class TestHttp extends AbstractTestNGSpringContextTests { e.printStackTrace(); } } - + File f = new File("/tmp/test"); Assert.assertEquals(f.length(), length); } diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TestNG.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TestNG.java index b3ecd3c22cb..e85c3d8db35 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TestNG.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TestNG.java @@ -20,12 +20,11 @@ import junit.framework.Assert; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; -import org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests; -import org.testng.annotations.Parameters; import org.testng.annotations.Test; import com.cloud.utils.db.DB; -@ContextConfiguration(locations="classpath:/storageContext.xml") + +@ContextConfiguration(locations = "classpath:/storageContext.xml") public class TestNG extends AbstractTestNGSpringContextTests { @Test @DB diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TestNGAop.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TestNGAop.java index 130ecd21980..515c5c80532 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TestNGAop.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TestNGAop.java @@ -31,8 +31,7 @@ import com.cloud.utils.db.Transaction; public class TestNGAop implements IMethodInterceptor { @Override - public List intercept(List methods, - ITestContext context) { + public List intercept(List methods, ITestContext context) { for (IMethodInstance methodIns : methods) { ITestNGMethod method = methodIns.getMethod(); ConstructorOrMethod meth = method.getConstructorOrMethod(); @@ -44,8 +43,7 @@ public class TestNGAop implements IMethodInterceptor { } } } - - + // TODO Auto-generated method stub return methods; } diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/VolumeTest.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/VolumeTest.java new file mode 100644 index 00000000000..70fdb1b5829 --- /dev/null +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/VolumeTest.java @@ -0,0 +1,433 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.test; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import javax.inject.Inject; + +import junit.framework.Assert; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +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.DataStoreProvider; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService.TemplateApiResult; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult; +import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.storage.RemoteHostEndPoint; +import org.apache.cloudstack.storage.command.CopyCmdAnswer; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.mockito.Matchers; +import org.mockito.Mockito; +import org.springframework.test.context.ContextConfiguration; +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Command; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.DataCenter.NetworkType; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.HostPodVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.HostPodDao; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.host.Host; +import com.cloud.host.Host.Type; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.HypervisorGuruManager; +import com.cloud.org.Cluster.ClusterType; +import com.cloud.org.Managed.ManagedState; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceState; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ScopeType; +import com.cloud.storage.Storage; +import com.cloud.storage.Volume; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.storage.Storage.TemplateType; +import com.cloud.storage.StoragePoolStatus; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.utils.component.ComponentContext; + +@ContextConfiguration(locations = { "classpath:/storageContext.xml" }) +public class VolumeTest extends CloudStackTestNGBase { + @Inject + ImageStoreDao imageStoreDao; + ImageStoreVO imageStore; + Long dcId; + Long clusterId; + Long podId; + HostVO host; + String primaryName = "my primary data store"; + DataStore primaryStore; + @Inject + HostDao hostDao; + @Inject + TemplateService imageService; + @Inject + VolumeService volumeService; + @Inject + VMTemplateDao imageDataDao; + @Inject + VolumeDao volumeDao; + @Inject + HostPodDao podDao; + @Inject + ClusterDao clusterDao; + @Inject + DataCenterDao dcDao; + @Inject + PrimaryDataStoreDao primaryStoreDao; + @Inject + DataStoreProviderManager dataStoreProviderMgr; + @Inject + TemplateDataStoreDao templateStoreDao; + @Inject + TemplateDataFactory templateFactory; + @Inject + PrimaryDataStoreDao primaryDataStoreDao; + @Inject + AgentManager agentMgr; + @Inject + DataStoreManager dataStoreMgr; + @Inject + ResourceManager resourceMgr; + @Inject + VolumeDataFactory volFactory; + @Inject + EndPointSelector epSelector; + @Inject + HypervisorGuruManager hyGuruMgr; + long primaryStoreId; + VMTemplateVO image; + String imageStoreName = "testImageStore"; + + @Test(priority = -1) + public void setUp() { + ComponentContext.initComponentsLifeCycle(); + + host = hostDao.findByGuid(this.getHostGuid()); + if (host != null) { + dcId = host.getDataCenterId(); + clusterId = host.getClusterId(); + podId = host.getPodId(); + imageStore = this.imageStoreDao.findByName(imageStoreName); + } else { + // create data center + DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, + "10.0.0.1/24", null, null, NetworkType.Basic, null, null, true, true, null, null); + dc = dcDao.persist(dc); + dcId = dc.getId(); + // create pod + + HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), this.getHostGateway(), + this.getHostCidr(), 8, "test"); + pod = podDao.persist(pod); + podId = pod.getId(); + // create xen cluster + ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster"); + cluster.setHypervisorType(this.getHypervisor().toString()); + cluster.setClusterType(ClusterType.CloudManaged); + cluster.setManagedState(ManagedState.Managed); + cluster = clusterDao.persist(cluster); + clusterId = cluster.getId(); + // create xen host + + host = new HostVO(this.getHostGuid()); + host.setName("devcloud xen host"); + host.setType(Host.Type.Routing); + host.setPrivateIpAddress(this.getHostIp()); + host.setDataCenterId(dc.getId()); + host.setVersion("6.0.1"); + host.setAvailable(true); + host.setSetup(true); + host.setPodId(podId); + host.setLastPinged(0); + host.setResourceState(ResourceState.Enabled); + host.setHypervisorType(this.getHypervisor()); + host.setClusterId(cluster.getId()); + + host = hostDao.persist(host); + + imageStore = new ImageStoreVO(); + imageStore.setName(imageStoreName); + imageStore.setDataCenterId(dcId); + imageStore.setProviderName(DataStoreProvider.NFS_IMAGE); + imageStore.setRole(DataStoreRole.Image); + imageStore.setUrl(this.getSecondaryStorage()); + imageStore.setUuid(UUID.randomUUID().toString()); + imageStore.setProtocol("nfs"); + imageStore = imageStoreDao.persist(imageStore); + } + + image = new VMTemplateVO(); + image.setTemplateType(TemplateType.USER); + image.setUrl(this.getTemplateUrl()); + image.setUniqueName(UUID.randomUUID().toString()); + image.setName(UUID.randomUUID().toString()); + image.setPublicTemplate(true); + image.setFeatured(true); + image.setRequiresHvm(true); + image.setBits(64); + image.setFormat(Storage.ImageFormat.VHD); + image.setEnablePassword(true); + image.setEnableSshKey(true); + image.setGuestOSId(1); + image.setBootable(true); + image.setPrepopulate(true); + image.setCrossZones(true); + image.setExtractable(true); + + image = imageDataDao.persist(image); + + /* + * TemplateDataStoreVO templateStore = new TemplateDataStoreVO(); + * + * templateStore.setDataStoreId(imageStore.getId()); + * templateStore.setDownloadPercent(100); + * templateStore.setDownloadState(Status.DOWNLOADED); + * templateStore.setDownloadUrl(imageStore.getUrl()); + * templateStore.setInstallPath(this.getImageInstallPath()); + * templateStore.setTemplateId(image.getId()); + * templateStoreDao.persist(templateStore); + */ + + DataStore store = this.dataStoreMgr.getDataStore(imageStore.getId(), DataStoreRole.Image); + TemplateInfo template = templateFactory.getTemplate(image.getId(), DataStoreRole.Image); + DataObject templateOnStore = store.create(template); + TemplateObjectTO to = new TemplateObjectTO(); + to.setPath(this.getImageInstallPath()); + to.setFormat(ImageFormat.VHD); + to.setSize(100L); + CopyCmdAnswer answer = new CopyCmdAnswer(to); + templateOnStore.processEvent(Event.CreateOnlyRequested); + templateOnStore.processEvent(Event.OperationSuccessed, answer); + + } + + @Override + protected void injectMockito() { + List hosts = new ArrayList(); + hosts.add(this.host); + Mockito.when( + resourceMgr.listAllUpAndEnabledHosts((Type) Matchers.any(), Matchers.anyLong(), Matchers.anyLong(), + Matchers.anyLong())).thenReturn(hosts); + + RemoteHostEndPoint ep = RemoteHostEndPoint.getHypervisorHostEndPoint(this.host.getId(), + this.host.getPrivateIpAddress(), this.host.getPublicIpAddress()); + Mockito.when(epSelector.select(Matchers.any(DataObject.class), Matchers.any(DataObject.class))).thenReturn(ep); + Mockito.when(epSelector.select(Matchers.any(DataObject.class))).thenReturn(ep); + Mockito.when(epSelector.select(Matchers.any(DataStore.class))).thenReturn(ep); + Mockito.when(hyGuruMgr.getGuruProcessedCommandTargetHost(Matchers.anyLong(), Matchers.any(Command.class))) + .thenReturn(this.host.getId()); + } + + public DataStore createPrimaryDataStore() { + try { + String uuid = UUID.nameUUIDFromBytes(this.getPrimaryStorageUrl().getBytes()).toString(); + List pools = primaryDataStoreDao.findPoolByName(this.primaryName); + if (pools.size() > 0) { + return this.dataStoreMgr.getPrimaryDataStore(pools.get(0).getId()); + } + + /* + * DataStoreProvider provider = + * dataStoreProviderMgr.getDataStoreProvider + * ("cloudstack primary data store provider"); Map + * params = new HashMap(); URI uri = new + * URI(this.getPrimaryStorageUrl()); params.put("url", + * this.getPrimaryStorageUrl()); params.put("server", + * uri.getHost()); params.put("path", uri.getPath()); + * params.put("protocol", + * Storage.StoragePoolType.NetworkFilesystem); params.put("zoneId", + * dcId); params.put("clusterId", clusterId); params.put("name", + * this.primaryName); params.put("port", 1); params.put("podId", + * this.podId); params.put("roles", + * DataStoreRole.Primary.toString()); params.put("uuid", uuid); + * params.put("providerName", String.valueOf(provider.getName())); + * + * DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle(); + * DataStore store = lifeCycle.initialize(params); ClusterScope + * scope = new ClusterScope(clusterId, podId, dcId); + * lifeCycle.attachCluster(store, scope); + */ + + StoragePoolVO pool = new StoragePoolVO(); + pool.setClusterId(clusterId); + pool.setDataCenterId(dcId); + URI uri = new URI(this.getPrimaryStorageUrl()); + pool.setHostAddress(uri.getHost()); + pool.setPath(uri.getPath()); + pool.setPort(0); + pool.setName(this.primaryName); + pool.setUuid(this.getPrimaryStorageUuid()); + pool.setStatus(StoragePoolStatus.Up); + pool.setPoolType(StoragePoolType.NetworkFilesystem); + pool.setPodId(podId); + pool.setScope(ScopeType.CLUSTER); + pool.setStorageProviderName(DataStoreProvider.DEFAULT_PRIMARY); + pool = this.primaryStoreDao.persist(pool); + DataStore store = this.dataStoreMgr.getPrimaryDataStore(pool.getId()); + return store; + } catch (Exception e) { + return null; + } + } + + private VolumeVO createVolume(Long templateId, long dataStoreId) { + VolumeVO volume = new VolumeVO(Volume.Type.DATADISK, UUID.randomUUID().toString(), this.dcId, 1L, 1L, 1L, 1000); + ; + volume.setPoolId(dataStoreId); + volume = volumeDao.persist(volume); + return volume; + } + + @Test + public void testCopyBaseImage() { + DataStore primaryStore = createPrimaryDataStore(); + primaryStoreId = primaryStore.getId(); + primaryStore = this.dataStoreMgr.getPrimaryDataStore(primaryStoreId); + VolumeVO volume = createVolume(image.getId(), primaryStore.getId()); + VolumeInfo volInfo = this.volFactory.getVolume(volume.getId()); + AsyncCallFuture future = this.volumeService.createVolumeFromTemplateAsync(volInfo, + this.primaryStoreId, this.templateFactory.getTemplate(this.image.getId(), DataStoreRole.Image)); + try { + VolumeApiResult result = future.get(); + + AssertJUnit.assertTrue(result.isSuccess()); + + VolumeInfo newVol = result.getVolume(); + boolean res = this.volumeService.destroyVolume(newVol.getId()); + Assert.assertTrue(res); + VolumeInfo vol = this.volFactory.getVolume(volume.getId()); + future = this.volumeService.expungeVolumeAsync(vol); + result = future.get(); + Assert.assertTrue(result.isSuccess()); + } catch (InterruptedException e) { + Assert.fail(e.toString()); + } catch (ExecutionException e) { + Assert.fail(e.toString()); + } catch (ConcurrentOperationException e) { + Assert.fail(e.toString()); + } + } + + @Test + public void testCreateDataDisk() throws InterruptedException, ExecutionException { + DataStore primaryStore = createPrimaryDataStore(); + primaryStoreId = primaryStore.getId(); + primaryStore = this.dataStoreMgr.getPrimaryDataStore(primaryStoreId); + VolumeVO volume = createVolume(null, primaryStore.getId()); + VolumeInfo volInfo = this.volFactory.getVolume(volume.getId()); + AsyncCallFuture future = this.volumeService.createVolumeAsync(volInfo, primaryStore); + VolumeApiResult result = future.get(); + Assert.assertTrue(result.isSuccess()); + } + + @Test + public void testDeleteDisk() throws InterruptedException, ExecutionException, ConcurrentOperationException { + DataStore primaryStore = createPrimaryDataStore(); + primaryStoreId = primaryStore.getId(); + primaryStore = this.dataStoreMgr.getPrimaryDataStore(primaryStoreId); + VolumeVO volume = createVolume(null, primaryStore.getId()); + VolumeInfo volInfo = this.volFactory.getVolume(volume.getId()); + AsyncCallFuture future = this.volumeService.createVolumeAsync(volInfo, primaryStore); + + VolumeApiResult result = future.get(); + Assert.assertTrue(result.isSuccess()); + VolumeInfo vol = result.getVolume(); + + boolean res = this.volumeService.destroyVolume(volInfo.getId()); + Assert.assertTrue(res); + volInfo = this.volFactory.getVolume(vol.getId()); + future = this.volumeService.expungeVolumeAsync(volInfo); + result = future.get(); + Assert.assertTrue(result.isSuccess()); + } + + private VMTemplateVO createTemplateInDb() { + image = new VMTemplateVO(); + image.setTemplateType(TemplateType.USER); + + image.setUniqueName(UUID.randomUUID().toString()); + image.setName(UUID.randomUUID().toString()); + image.setPublicTemplate(true); + image.setFeatured(true); + image.setRequiresHvm(true); + image.setBits(64); + image.setFormat(Storage.ImageFormat.VHD); + image.setEnablePassword(true); + image.setEnableSshKey(true); + image.setGuestOSId(1); + image.setBootable(true); + image.setPrepopulate(true); + image.setCrossZones(true); + image.setExtractable(true); + image = imageDataDao.persist(image); + return image; + } + + @Test + public void testCreateTemplateFromVolume() throws InterruptedException, ExecutionException { + DataStore primaryStore = createPrimaryDataStore(); + primaryStoreId = primaryStore.getId(); + primaryStore = this.dataStoreMgr.getPrimaryDataStore(primaryStoreId); + VolumeVO volume = createVolume(null, primaryStore.getId()); + VolumeInfo volInfo = this.volFactory.getVolume(volume.getId()); + AsyncCallFuture future = this.volumeService.createVolumeAsync(volInfo, primaryStore); + + VolumeApiResult result = future.get(); + + AssertJUnit.assertTrue(result.isSuccess()); + volInfo = result.getVolume(); + VMTemplateVO templateVO = createTemplateInDb(); + TemplateInfo tmpl = this.templateFactory.getTemplate(templateVO.getId(), DataStoreRole.Image); + DataStore imageStore = this.dataStoreMgr.getImageStore(this.dcId); + + AsyncCallFuture templateResult = this.imageService.createTemplateFromVolumeAsync(volInfo, tmpl, imageStore); + TemplateApiResult templateApiResult = templateResult.get(); + Assert.assertTrue(templateApiResult.isSuccess()); + } +} diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/VolumeTestVmware.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/VolumeTestVmware.java new file mode 100644 index 00000000000..4acc8dc7de8 --- /dev/null +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/VolumeTestVmware.java @@ -0,0 +1,444 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.test; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +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.DataStoreProviderManager; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult; +import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.storage.RemoteHostEndPoint; +import org.apache.cloudstack.storage.command.CopyCmdAnswer; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.mockito.Matchers; +import org.mockito.Mockito; +import org.springframework.test.context.ContextConfiguration; +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + +import com.cloud.agent.AgentManager; +import com.cloud.dc.ClusterDetailsDao; +import com.cloud.dc.ClusterDetailsVO; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.DataCenter.NetworkType; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.HostPodVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.HostPodDao; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.host.Host; +import com.cloud.host.Host.Type; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.org.Cluster.ClusterType; +import com.cloud.org.Managed.ManagedState; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceState; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ScopeType; +import com.cloud.storage.Storage; +import com.cloud.storage.Volume; +import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.storage.Storage.TemplateType; +import com.cloud.storage.StoragePoolStatus; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.utils.component.ComponentContext; + +@ContextConfiguration(locations = { "classpath:/storageContext.xml" }) +public class VolumeTestVmware extends CloudStackTestNGBase { + @Inject + ImageStoreDao imageStoreDao; + ImageStoreVO imageStore; + Long dcId; + Long clusterId; + Long podId; + HostVO host; + String primaryName = "my primary data store"; + DataStore primaryStore; + @Inject + HostDao hostDao; + @Inject + TemplateService imageService; + @Inject + VolumeService volumeService; + @Inject + VMTemplateDao imageDataDao; + @Inject + VolumeDao volumeDao; + @Inject + HostPodDao podDao; + @Inject + ClusterDao clusterDao; + @Inject + ClusterDetailsDao clusterDetailsDao; + @Inject + DataCenterDao dcDao; + @Inject + PrimaryDataStoreDao primaryStoreDao; + @Inject + DataStoreProviderManager dataStoreProviderMgr; + @Inject + TemplateDataStoreDao templateStoreDao; + @Inject + TemplateDataFactory templateFactory; + @Inject + PrimaryDataStoreDao primaryDataStoreDao; + @Inject + AgentManager agentMgr; + @Inject + DataStoreManager dataStoreMgr; + @Inject + ResourceManager resourceMgr; + @Inject + VolumeDataFactory volFactory; + @Inject + EndPointSelector epSelector; + long primaryStoreId; + VMTemplateVO image; + String imageStoreName = "testImageStore"; + + @Test(priority = -1) + public void setUp() { + ComponentContext.initComponentsLifeCycle(); + + host = hostDao.findByGuid(this.getHostGuid()); + if (host != null) { + dcId = host.getDataCenterId(); + clusterId = host.getClusterId(); + podId = host.getPodId(); + imageStore = this.imageStoreDao.findByName(imageStoreName); + } else { + // create data center + DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, + "10.0.0.1/24", null, null, NetworkType.Basic, null, null, true, true, null, null); + dc = dcDao.persist(dc); + dcId = dc.getId(); + // create pod + + HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), this.getHostGateway(), + this.getHostCidr(), 8, "test"); + pod = podDao.persist(pod); + podId = pod.getId(); + // create xen cluster + ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster"); + cluster.setHypervisorType(HypervisorType.VMware.toString()); + cluster.setClusterType(ClusterType.ExternalManaged); + cluster.setManagedState(ManagedState.Managed); + cluster = clusterDao.persist(cluster); + clusterId = cluster.getId(); + + // setup vcenter + ClusterDetailsVO clusterDetailVO = new ClusterDetailsVO(cluster.getId(), "url", null); + this.clusterDetailsDao.persist(clusterDetailVO); + clusterDetailVO = new ClusterDetailsVO(cluster.getId(), "username", null); + this.clusterDetailsDao.persist(clusterDetailVO); + clusterDetailVO = new ClusterDetailsVO(cluster.getId(), "password", null); + this.clusterDetailsDao.persist(clusterDetailVO); + // create xen host + + host = new HostVO(this.getHostGuid()); + host.setName("devcloud vmware host"); + host.setType(Host.Type.Routing); + host.setPrivateIpAddress(this.getHostIp()); + host.setDataCenterId(dc.getId()); + host.setVersion("6.0.1"); + host.setAvailable(true); + host.setSetup(true); + host.setPodId(podId); + host.setLastPinged(0); + host.setResourceState(ResourceState.Enabled); + host.setHypervisorType(HypervisorType.VMware); + host.setClusterId(cluster.getId()); + + host = hostDao.persist(host); + + imageStore = new ImageStoreVO(); + imageStore.setName(imageStoreName); + imageStore.setDataCenterId(dcId); + imageStore.setProviderName("CloudStack ImageStore Provider"); + imageStore.setRole(DataStoreRole.Image); + imageStore.setUrl(this.getSecondaryStorage()); + imageStore.setUuid(UUID.randomUUID().toString()); + imageStore.setProtocol("nfs"); + imageStore = imageStoreDao.persist(imageStore); + } + + image = new VMTemplateVO(); + image.setTemplateType(TemplateType.USER); + image.setUrl(this.getTemplateUrl()); + image.setUniqueName(UUID.randomUUID().toString()); + image.setName(UUID.randomUUID().toString()); + image.setPublicTemplate(true); + image.setFeatured(true); + image.setRequiresHvm(true); + image.setBits(64); + image.setFormat(Storage.ImageFormat.VHD); + image.setEnablePassword(true); + image.setEnableSshKey(true); + image.setGuestOSId(1); + image.setBootable(true); + image.setPrepopulate(true); + image.setCrossZones(true); + image.setExtractable(true); + + image = imageDataDao.persist(image); + + /* + * TemplateDataStoreVO templateStore = new TemplateDataStoreVO(); + * + * templateStore.setDataStoreId(imageStore.getId()); + * templateStore.setDownloadPercent(100); + * templateStore.setDownloadState(Status.DOWNLOADED); + * templateStore.setDownloadUrl(imageStore.getUrl()); + * templateStore.setInstallPath(this.getImageInstallPath()); + * templateStore.setTemplateId(image.getId()); + * templateStoreDao.persist(templateStore); + */ + + DataStore store = this.dataStoreMgr.getDataStore(imageStore.getId(), DataStoreRole.Image); + TemplateInfo template = templateFactory.getTemplate(image.getId(), DataStoreRole.Image); + DataObject templateOnStore = store.create(template); + TemplateObjectTO to = new TemplateObjectTO(); + to.setPath(this.getImageInstallPath()); + CopyCmdAnswer answer = new CopyCmdAnswer(to); + templateOnStore.processEvent(Event.CreateOnlyRequested); + templateOnStore.processEvent(Event.OperationSuccessed, answer); + + } + + @Override + protected void injectMockito() { + List hosts = new ArrayList(); + hosts.add(this.host); + Mockito.when( + resourceMgr.listAllUpAndEnabledHosts((Type) Matchers.any(), Matchers.anyLong(), Matchers.anyLong(), + Matchers.anyLong())).thenReturn(hosts); + + RemoteHostEndPoint ep = RemoteHostEndPoint.getHypervisorHostEndPoint(this.host.getId(), + this.host.getPrivateIpAddress(), this.host.getPublicIpAddress()); + Mockito.when(epSelector.select(Matchers.any(DataObject.class), Matchers.any(DataObject.class))).thenReturn(ep); + Mockito.when(epSelector.select(Matchers.any(DataObject.class))).thenReturn(ep); + Mockito.when(epSelector.select(Matchers.any(DataStore.class))).thenReturn(ep); + } + + public DataStore createPrimaryDataStore() { + try { + String uuid = UUID.nameUUIDFromBytes(this.getPrimaryStorageUrl().getBytes()).toString(); + List pools = primaryDataStoreDao.findPoolByName(this.primaryName); + if (pools.size() > 0) { + return this.dataStoreMgr.getPrimaryDataStore(pools.get(0).getId()); + } + + /* + * DataStoreProvider provider = + * dataStoreProviderMgr.getDataStoreProvider + * ("cloudstack primary data store provider"); Map + * params = new HashMap(); URI uri = new + * URI(this.getPrimaryStorageUrl()); params.put("url", + * this.getPrimaryStorageUrl()); params.put("server", + * uri.getHost()); params.put("path", uri.getPath()); + * params.put("protocol", + * Storage.StoragePoolType.NetworkFilesystem); params.put("zoneId", + * dcId); params.put("clusterId", clusterId); params.put("name", + * this.primaryName); params.put("port", 1); params.put("podId", + * this.podId); params.put("roles", + * DataStoreRole.Primary.toString()); params.put("uuid", uuid); + * params.put("providerName", String.valueOf(provider.getName())); + * + * DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle(); + * DataStore store = lifeCycle.initialize(params); ClusterScope + * scope = new ClusterScope(clusterId, podId, dcId); + * lifeCycle.attachCluster(store, scope); + */ + + StoragePoolVO pool = new StoragePoolVO(); + pool.setClusterId(clusterId); + pool.setDataCenterId(dcId); + URI uri = new URI(this.getPrimaryStorageUrl()); + pool.setHostAddress(uri.getHost()); + pool.setPath(uri.getPath()); + pool.setPort(0); + pool.setName(this.primaryName); + pool.setUuid(this.getPrimaryStorageUuid()); + pool.setStatus(StoragePoolStatus.Up); + pool.setPoolType(StoragePoolType.VMFS); + pool.setPodId(podId); + pool.setScope(ScopeType.CLUSTER); + pool.setStorageProviderName("cloudstack primary data store provider"); + pool = this.primaryStoreDao.persist(pool); + DataStore store = this.dataStoreMgr.getPrimaryDataStore(pool.getId()); + return store; + } catch (Exception e) { + return null; + } + } + + private VolumeVO createVolume(Long templateId, long dataStoreId) { + VolumeVO volume = new VolumeVO(Volume.Type.DATADISK, UUID.randomUUID().toString(), this.dcId, 1L, 1L, 1L, 1000); + ; + volume.setPoolId(dataStoreId); + volume = volumeDao.persist(volume); + return volume; + } + + // @Test + public void testCopyBaseImage() { + DataStore primaryStore = createPrimaryDataStore(); + primaryStoreId = primaryStore.getId(); + primaryStore = this.dataStoreMgr.getPrimaryDataStore(primaryStoreId); + VolumeVO volume = createVolume(image.getId(), primaryStore.getId()); + VolumeInfo volInfo = this.volFactory.getVolume(volume.getId()); + AsyncCallFuture future = this.volumeService.createVolumeFromTemplateAsync(volInfo, + this.primaryStoreId, this.templateFactory.getTemplate(this.image.getId(), DataStoreRole.Image)); + try { + VolumeApiResult result = future.get(); + + AssertJUnit.assertTrue(result.isSuccess()); + + VolumeInfo newVol = result.getVolume(); + this.volumeService.destroyVolume(newVol.getId()); + VolumeInfo vol = this.volFactory.getVolume(volume.getId()); + this.volumeService.expungeVolumeAsync(vol); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ConcurrentOperationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testCreateDataDisk() { + DataStore primaryStore = createPrimaryDataStore(); + primaryStoreId = primaryStore.getId(); + primaryStore = this.dataStoreMgr.getPrimaryDataStore(primaryStoreId); + VolumeVO volume = createVolume(null, primaryStore.getId()); + VolumeInfo volInfo = this.volFactory.getVolume(volume.getId()); + this.volumeService.createVolumeAsync(volInfo, primaryStore); + } + + @Test + public void testDeleteDisk() { + DataStore primaryStore = createPrimaryDataStore(); + primaryStoreId = primaryStore.getId(); + primaryStore = this.dataStoreMgr.getPrimaryDataStore(primaryStoreId); + VolumeVO volume = createVolume(null, primaryStore.getId()); + VolumeInfo volInfo = this.volFactory.getVolume(volume.getId()); + AsyncCallFuture future = this.volumeService.createVolumeAsync(volInfo, primaryStore); + try { + VolumeApiResult result = future.get(); + VolumeInfo vol = result.getVolume(); + + this.volumeService.destroyVolume(volInfo.getId()); + volInfo = this.volFactory.getVolume(vol.getId()); + this.volumeService.expungeVolumeAsync(volInfo); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ConcurrentOperationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + private VMTemplateVO createTemplateInDb() { + image = new VMTemplateVO(); + image.setTemplateType(TemplateType.USER); + + image.setUniqueName(UUID.randomUUID().toString()); + image.setName(UUID.randomUUID().toString()); + image.setPublicTemplate(true); + image.setFeatured(true); + image.setRequiresHvm(true); + image.setBits(64); + image.setFormat(Storage.ImageFormat.VHD); + image.setEnablePassword(true); + image.setEnableSshKey(true); + image.setGuestOSId(1); + image.setBootable(true); + image.setPrepopulate(true); + image.setCrossZones(true); + image.setExtractable(true); + image = imageDataDao.persist(image); + return image; + } + + @Test + public void testCreateTemplateFromVolume() { + DataStore primaryStore = createPrimaryDataStore(); + primaryStoreId = primaryStore.getId(); + primaryStore = this.dataStoreMgr.getPrimaryDataStore(primaryStoreId); + VolumeVO volume = createVolume(null, primaryStore.getId()); + VolumeInfo volInfo = this.volFactory.getVolume(volume.getId()); + AsyncCallFuture future = this.volumeService.createVolumeAsync(volInfo, primaryStore); + try { + VolumeApiResult result = future.get(); + + AssertJUnit.assertTrue(result.isSuccess()); + volInfo = result.getVolume(); + VMTemplateVO templateVO = createTemplateInDb(); + TemplateInfo tmpl = this.templateFactory.getTemplate(templateVO.getId(), DataStoreRole.Image); + DataStore imageStore = this.dataStoreMgr.getImageStore(this.dcId); + + this.imageService.createTemplateFromVolumeAsync(volInfo, tmpl, imageStore); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } +} diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/volumeServiceTest.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/volumeServiceTest.java index 35a1790a0a9..42b0463c71b 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/volumeServiceTest.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/volumeServiceTest.java @@ -30,30 +30,27 @@ import java.util.concurrent.ExecutionException; import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; -import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole; import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; -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.ScopeType; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult; -import org.apache.cloudstack.engine.subsystem.api.storage.type.RootDisk; import org.apache.cloudstack.framework.async.AsyncCallFuture; -import org.apache.cloudstack.storage.HypervisorHostEndPoint; +import org.apache.cloudstack.storage.RemoteHostEndPoint; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.cloudstack.storage.endpoint.EndPointSelector; -import org.apache.cloudstack.storage.volume.db.VolumeDao2; -import org.apache.cloudstack.storage.volume.db.VolumeVO; +import org.mockito.Matchers; import org.mockito.Mockito; import org.springframework.test.context.ContextConfiguration; import org.testng.Assert; @@ -74,61 +71,64 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.org.Cluster.ClusterType; import com.cloud.org.Managed.ManagedState; import com.cloud.resource.ResourceState; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ScopeType; import com.cloud.storage.Storage; +import com.cloud.storage.Volume; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VolumeDao; import com.cloud.utils.component.ComponentContext; -@ContextConfiguration(locations={"classpath:/storageContext.xml"}) +@ContextConfiguration(locations = { "classpath:/storageContext.xml" }) public class volumeServiceTest extends CloudStackTestNGBase { - //@Inject - //ImageDataStoreProviderManager imageProviderMgr; - @Inject - ImageService imageService; - @Inject - VolumeService volumeService; - @Inject - VMTemplateDao imageDataDao; - @Inject - VolumeDao2 volumeDao; - @Inject - HostDao hostDao; - @Inject - HostPodDao podDao; - @Inject - ClusterDao clusterDao; - @Inject - DataCenterDao dcDao; - @Inject - PrimaryDataStoreDao primaryStoreDao; - @Inject - DataStoreProviderManager dataStoreProviderMgr; - @Inject - AgentManager agentMgr; - @Inject - EndPointSelector selector; - @Inject - ImageDataFactory imageDataFactory; - @Inject - VolumeDataFactory volumeFactory; - Long dcId; - Long clusterId; - Long podId; - HostVO host; - String primaryName = "my primary data store"; - DataStore primaryStore; - + // @Inject + // ImageDataStoreProviderManager imageProviderMgr; + @Inject + TemplateService imageService; + @Inject + VolumeService volumeService; + @Inject + VMTemplateDao imageDataDao; + @Inject + VolumeDao volumeDao; + @Inject + HostDao hostDao; + @Inject + HostPodDao podDao; + @Inject + ClusterDao clusterDao; + @Inject + DataCenterDao dcDao; + @Inject + PrimaryDataStoreDao primaryStoreDao; + @Inject + DataStoreProviderManager dataStoreProviderMgr; + @Inject + AgentManager agentMgr; + @Inject + EndPointSelector selector; + @Inject + TemplateDataFactory imageDataFactory; + @Inject + VolumeDataFactory volumeFactory; + @Inject + ImageStoreDao imageStoreDao; + ImageStoreVO imageStore; + Long dcId; + Long clusterId; + Long podId; + HostVO host; + String primaryName = "my primary data store"; + DataStore primaryStore; + @Test(priority = -1) - public void setUp() { + public void setUp() { ComponentContext.initComponentsLifeCycle(); - /* try { - dataStoreProviderMgr.configure(null, new HashMap()); - } catch (ConfigurationException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - }*/ + host = hostDao.findByGuid(this.getHostGuid()); if (host != null) { dcId = host.getDataCenterId(); @@ -136,59 +136,53 @@ public class volumeServiceTest extends CloudStackTestNGBase { podId = host.getPodId(); return; } - //create data center - DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24", - null, null, NetworkType.Basic, null, null, true, true, null, null); - dc = dcDao.persist(dc); - dcId = dc.getId(); - //create pod + // create data center + DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, + "10.0.0.1/24", null, null, NetworkType.Basic, null, null, true, true, null, null); + dc = dcDao.persist(dc); + dcId = dc.getId(); + // create pod - HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), this.getHostGateway(), this.getHostCidr(), 8, "test"); - pod = podDao.persist(pod); - podId = pod.getId(); - //create xen cluster - ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster"); - cluster.setHypervisorType(HypervisorType.XenServer.toString()); - cluster.setClusterType(ClusterType.CloudManaged); - cluster.setManagedState(ManagedState.Managed); - cluster = clusterDao.persist(cluster); - clusterId = cluster.getId(); - //create xen host + HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), this.getHostGateway(), + this.getHostCidr(), 8, "test"); + pod = podDao.persist(pod); + podId = pod.getId(); + // create xen cluster + ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster"); + cluster.setHypervisorType(HypervisorType.XenServer.toString()); + cluster.setClusterType(ClusterType.CloudManaged); + cluster.setManagedState(ManagedState.Managed); + cluster = clusterDao.persist(cluster); + clusterId = cluster.getId(); + // create xen host - host = new HostVO(this.getHostGuid()); - host.setName("devcloud xen host"); - host.setType(Host.Type.Routing); - host.setPrivateIpAddress(this.getHostIp()); - host.setDataCenterId(dc.getId()); - host.setVersion("6.0.1"); - host.setAvailable(true); - host.setSetup(true); - host.setPodId(podId); - host.setLastPinged(0); - host.setResourceState(ResourceState.Enabled); - host.setHypervisorType(HypervisorType.XenServer); - host.setClusterId(cluster.getId()); + host = new HostVO(this.getHostGuid()); + host.setName("devcloud xen host"); + host.setType(Host.Type.Routing); + host.setPrivateIpAddress(this.getHostIp()); + host.setDataCenterId(dc.getId()); + host.setVersion("6.0.1"); + host.setAvailable(true); + host.setSetup(true); + host.setPodId(podId); + host.setLastPinged(0); + host.setResourceState(ResourceState.Enabled); + host.setHypervisorType(HypervisorType.XenServer); + host.setClusterId(cluster.getId()); - host = hostDao.persist(host); + host = hostDao.persist(host); - //primaryStore = createPrimaryDataStore(); - - //CreateVolumeAnswer createVolumeFromImageAnswer = new CreateVolumeAnswer(UUID.randomUUID().toString()); + imageStore = new ImageStoreVO(); + imageStore.setName("test"); + imageStore.setDataCenterId(dcId); + imageStore.setProviderName("CloudStack ImageStore Provider"); + imageStore.setRole(DataStoreRole.Image); + imageStore.setUrl(this.getSecondaryStorage()); + imageStore.setUuid(UUID.randomUUID().toString()); + imageStore = imageStoreDao.persist(imageStore); - /*try { - Mockito.when(agentMgr.send(Mockito.anyLong(), Mockito.any(CreateVolumeFromBaseImageCommand.class))).thenReturn(createVolumeFromImageAnswer); - } catch (AgentUnavailableException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (OperationTimedoutException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - }*/ + } - - //Mockito.when(primaryStoreDao.findById(Mockito.anyLong())).thenReturn(primaryStore); - } - @Override protected void injectMockito() { if (host == null) { @@ -197,72 +191,79 @@ public class volumeServiceTest extends CloudStackTestNGBase { List results = new ArrayList(); results.add(host); Mockito.when(hostDao.listAll()).thenReturn(results); - Mockito.when(hostDao.findById(Mockito.anyLong())).thenReturn(host); - Mockito.when(hostDao.findHypervisorHostInCluster(Mockito.anyLong())).thenReturn(results); + Mockito.when(hostDao.findById(Matchers.anyLong())).thenReturn(host); + Mockito.when(hostDao.findHypervisorHostInCluster(Matchers.anyLong())).thenReturn(results); List eps = new ArrayList(); - eps.add(HypervisorHostEndPoint.getHypervisorHostEndPoint(host.getId(), - host.getPrivateIpAddress())); - Mockito.when(selector.selectAll(Mockito.any(DataStore.class))).thenReturn(eps); - Mockito.when(selector.select(Mockito.any(DataObject.class))).thenReturn(eps.get(0)); - Mockito.when(selector.select(Mockito.any(DataObject.class), Mockito.any(DataObject.class))).thenReturn(eps.get(0)); + eps.add(RemoteHostEndPoint.getHypervisorHostEndPoint(host.getId(), host.getPrivateIpAddress(), + host.getPublicIpAddress())); + Mockito.when(selector.selectAll(Matchers.any(DataStore.class))).thenReturn(eps); + Mockito.when(selector.select(Matchers.any(DataObject.class))).thenReturn(eps.get(0)); + Mockito.when(selector.select(Matchers.any(DataObject.class), Matchers.any(DataObject.class))).thenReturn( + eps.get(0)); } - private VMTemplateVO createImageData() { - VMTemplateVO image = new VMTemplateVO(); - image.setTemplateType(TemplateType.USER); - image.setUrl(this.getTemplateUrl()); - image.setUniqueName(UUID.randomUUID().toString()); - image.setName(UUID.randomUUID().toString()); - image.setPublicTemplate(true); - image.setFeatured(true); - image.setRequiresHvm(true); - image.setBits(64); - image.setFormat(Storage.ImageFormat.VHD); - image.setEnablePassword(true); - image.setEnableSshKey(true); - image.setGuestOSId(1); - image.setBootable(true); - image.setPrepopulate(true); - image.setCrossZones(true); - image.setExtractable(true); - - //image.setImageDataStoreId(storeId); - image = imageDataDao.persist(image); - - return image; - } + private VMTemplateVO createImageData() { + VMTemplateVO image = new VMTemplateVO(); + image.setTemplateType(TemplateType.USER); + image.setUrl(this.getTemplateUrl()); + image.setUniqueName(UUID.randomUUID().toString()); + image.setName(UUID.randomUUID().toString()); + image.setPublicTemplate(true); + image.setFeatured(true); + image.setRequiresHvm(true); + image.setBits(64); + image.setFormat(Storage.ImageFormat.VHD); + image.setEnablePassword(true); + image.setEnableSshKey(true); + image.setGuestOSId(1); + image.setBootable(true); + image.setPrepopulate(true); + image.setCrossZones(true); + image.setExtractable(true); - private TemplateInfo createTemplate() { - try { - DataStore store = createImageStore(); - VMTemplateVO image = createImageData(); - TemplateInfo template = imageDataFactory.getTemplate(image.getId(), store); - AsyncCallFuture future = imageService.createTemplateAsync(template, store); - future.get(); - template = imageDataFactory.getTemplate(image.getId(), store); - /*imageProviderMgr.configure("image Provider", new HashMap()); - VMTemplateVO image = createImageData(); - ImageDataStoreProvider defaultProvider = imageProviderMgr.getProvider("DefaultProvider"); - ImageDataStoreLifeCycle lifeCycle = defaultProvider.getLifeCycle(); - ImageDataStore store = lifeCycle.registerDataStore("defaultHttpStore", new HashMap()); - imageService.registerTemplate(image.getId(), store.getImageDataStoreId()); - TemplateEntity te = imageService.getTemplateEntity(image.getId()); - return te;*/ - return template; - } catch (Exception e) { - Assert.fail("failed", e); - return null; - } - } + // image.setImageDataStoreId(storeId); + image = imageDataDao.persist(image); - //@Test - public void createTemplateTest() { - createTemplate(); - } - - @Test - public void testCreatePrimaryStorage() { - DataStoreProvider provider = dataStoreProviderMgr.getDataStoreProvider("default primary data store provider"); + return image; + } + + private TemplateInfo createTemplate() { + try { + DataStore store = createImageStore(); + VMTemplateVO image = createImageData(); + TemplateInfo template = imageDataFactory.getTemplate(image.getId(), store); + // AsyncCallFuture future = + // imageService.createTemplateAsync(template, store); + // future.get(); + template = imageDataFactory.getTemplate(image.getId(), store); + /* + * imageProviderMgr.configure("image Provider", new HashMap()); VMTemplateVO image = createImageData(); + * ImageDataStoreProvider defaultProvider = + * imageProviderMgr.getProvider("DefaultProvider"); + * ImageDataStoreLifeCycle lifeCycle = + * defaultProvider.getLifeCycle(); ImageDataStore store = + * lifeCycle.registerDataStore("defaultHttpStore", new + * HashMap()); + * imageService.registerTemplate(image.getId(), + * store.getImageDataStoreId()); TemplateEntity te = + * imageService.getTemplateEntity(image.getId()); return te; + */ + return template; + } catch (Exception e) { + Assert.fail("failed", e); + return null; + } + } + + // @Test + public void createTemplateTest() { + createTemplate(); + } + + @Test + public void testCreatePrimaryStorage() { + DataStoreProvider provider = dataStoreProviderMgr.getDataStoreProvider("sample primary data store provider"); Map params = new HashMap(); URI uri = null; try { @@ -282,15 +283,15 @@ public class volumeServiceTest extends CloudStackTestNGBase { params.put("roles", DataStoreRole.Primary.toString()); params.put("uuid", UUID.nameUUIDFromBytes(this.getPrimaryStorageUrl().getBytes()).toString()); params.put("providerName", String.valueOf(provider.getName())); - + DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle(); - this.primaryStore = lifeCycle.initialize(params); + this.primaryStore = lifeCycle.initialize(params); ClusterScope scope = new ClusterScope(clusterId, podId, dcId); lifeCycle.attachCluster(this.primaryStore, scope); - } - - private DataStore createImageStore() { - DataStoreProvider provider = dataStoreProviderMgr.getDataStoreProvider("default image data store"); + } + + private DataStore createImageStore() { + DataStoreProvider provider = dataStoreProviderMgr.getDataStoreProvider("sample image data store provider"); Map params = new HashMap(); String name = UUID.randomUUID().toString(); params.put("name", name); @@ -301,19 +302,20 @@ public class volumeServiceTest extends CloudStackTestNGBase { DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle(); DataStore store = lifeCycle.initialize(params); return store; - } - //@Test - public void testcreateImageStore() { - createImageStore(); - } - + } - public DataStore createPrimaryDataStore() { - try { - DataStoreProvider provider = dataStoreProviderMgr.getDataStoreProvider("default primary data store provider"); - Map params = new HashMap(); - URI uri = new URI(this.getPrimaryStorageUrl()); - params.put("url", this.getPrimaryStorageUrl()); + // @Test + public void testcreateImageStore() { + createImageStore(); + } + + public DataStore createPrimaryDataStore() { + try { + DataStoreProvider provider = dataStoreProviderMgr + .getDataStoreProvider("sample primary data store provider"); + Map params = new HashMap(); + URI uri = new URI(this.getPrimaryStorageUrl()); + params.put("url", this.getPrimaryStorageUrl()); params.put("server", uri.getHost()); params.put("path", uri.getPath()); params.put("protocol", Storage.StoragePoolType.NetworkFilesystem); @@ -324,58 +326,59 @@ public class volumeServiceTest extends CloudStackTestNGBase { params.put("roles", DataStoreRole.Primary.toString()); params.put("uuid", UUID.nameUUIDFromBytes(this.getPrimaryStorageUrl().getBytes()).toString()); params.put("providerName", String.valueOf(provider.getName())); - - DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle(); - DataStore store = lifeCycle.initialize(params); - ClusterScope scope = new ClusterScope(clusterId, podId, dcId); - lifeCycle.attachCluster(store, scope); - - /* - PrimaryDataStoreProvider provider = primaryDataStoreProviderMgr.getDataStoreProvider("default primary data store provider"); - primaryDataStoreProviderMgr.configure("primary data store mgr", new HashMap()); - - List ds = primaryStoreDao.findPoolByName(this.primaryName); - if (ds.size() >= 1) { - PrimaryDataStoreVO store = ds.get(0); - if (store.getRemoved() == null) { - return provider.getDataStore(store.getId()); - } - } - - - Map params = new HashMap(); - params.put("url", this.getPrimaryStorageUrl()); - params.put("dcId", dcId.toString()); - params.put("clusterId", clusterId.toString()); - params.put("name", this.primaryName); - PrimaryDataStoreInfo primaryDataStoreInfo = provider.registerDataStore(params); - PrimaryDataStoreLifeCycle lc = primaryDataStoreInfo.getLifeCycle(); - ClusterScope scope = new ClusterScope(clusterId, podId, dcId); - lc.attachCluster(scope); - return primaryDataStoreInfo; - */ - return store; - } catch (Exception e) { - return null; - } - } - private VolumeVO createVolume(Long templateId, long dataStoreId) { - VolumeVO volume = new VolumeVO(1000, new RootDisk().toString(), UUID.randomUUID().toString(), templateId); - volume.setPoolId(dataStoreId); - volume = volumeDao.persist(volume); - return volume; - } + DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle(); + DataStore store = lifeCycle.initialize(params); + ClusterScope scope = new ClusterScope(clusterId, podId, dcId); + lifeCycle.attachCluster(store, scope); - @Test(priority=2) - public void createVolumeFromTemplate() { - DataStore primaryStore = this.primaryStore; - TemplateInfo te = createTemplate(); - VolumeVO volume = createVolume(te.getId(), primaryStore.getId()); - VolumeInfo vol = volumeFactory.getVolume(volume.getId(), primaryStore); - //ve.createVolumeFromTemplate(primaryStore.getId(), new VHD(), te); - AsyncCallFuture future = volumeService.createVolumeFromTemplateAsync(vol, primaryStore.getId(), te); - try { + /* + * PrimaryDataStoreProvider provider = + * primaryDataStoreProviderMgr.getDataStoreProvider + * ("sample primary data store provider"); + * primaryDataStoreProviderMgr.configure("primary data store mgr", + * new HashMap()); + * + * List ds = + * primaryStoreDao.findPoolByName(this.primaryName); if (ds.size() + * >= 1) { PrimaryDataStoreVO store = ds.get(0); if + * (store.getRemoved() == null) { return + * provider.getDataStore(store.getId()); } } + * + * + * Map params = new HashMap(); + * params.put("url", this.getPrimaryStorageUrl()); + * params.put("dcId", dcId.toString()); params.put("clusterId", + * clusterId.toString()); params.put("name", this.primaryName); + * PrimaryDataStoreInfo primaryDataStoreInfo = + * provider.registerDataStore(params); PrimaryDataStoreLifeCycle lc + * = primaryDataStoreInfo.getLifeCycle(); ClusterScope scope = new + * ClusterScope(clusterId, podId, dcId); lc.attachCluster(scope); + * return primaryDataStoreInfo; + */ + return store; + } catch (Exception e) { + return null; + } + } + + private VolumeVO createVolume(Long templateId, long dataStoreId) { + VolumeVO volume = new VolumeVO(Volume.Type.DATADISK, UUID.randomUUID().toString(), this.dcId, 1L, 1L, 1L, 1000); + volume.setPoolId(dataStoreId); + volume = volumeDao.persist(volume); + return volume; + } + + @Test(priority = 2) + public void createVolumeFromTemplate() { + DataStore primaryStore = this.primaryStore; + TemplateInfo te = createTemplate(); + VolumeVO volume = createVolume(te.getId(), primaryStore.getId()); + VolumeInfo vol = volumeFactory.getVolume(volume.getId(), primaryStore); + // ve.createVolumeFromTemplate(primaryStore.getId(), new VHD(), te); + AsyncCallFuture future = volumeService.createVolumeFromTemplateAsync(vol, + primaryStore.getId(), te); + try { future.get(); } catch (InterruptedException e) { // TODO Auto-generated catch block @@ -384,15 +387,15 @@ public class volumeServiceTest extends CloudStackTestNGBase { // TODO Auto-generated catch block e.printStackTrace(); } - } - - //@Test(priority=3) - public void createDataDisk() { - DataStore primaryStore = this.primaryStore; - VolumeVO volume = createVolume(null, primaryStore.getId()); - VolumeInfo vol = volumeFactory.getVolume(volume.getId(), primaryStore); - AsyncCallFuture future = volumeService.createVolumeAsync(vol, primaryStore); - try { + } + + // @Test(priority=3) + public void createDataDisk() { + DataStore primaryStore = this.primaryStore; + VolumeVO volume = createVolume(null, primaryStore.getId()); + VolumeInfo vol = volumeFactory.getVolume(volume.getId(), primaryStore); + AsyncCallFuture future = volumeService.createVolumeAsync(vol, primaryStore); + try { future.get(); } catch (InterruptedException e) { // TODO Auto-generated catch block @@ -401,28 +404,15 @@ public class volumeServiceTest extends CloudStackTestNGBase { // TODO Auto-generated catch block e.printStackTrace(); } - } - - //@Test(priority=3) - public void createAndDeleteDataDisk() { - DataStore primaryStore = this.primaryStore; - VolumeVO volume = createVolume(null, primaryStore.getId()); - VolumeInfo vol = volumeFactory.getVolume(volume.getId(), primaryStore); - AsyncCallFuture future = volumeService.createVolumeAsync(vol, primaryStore); - try { - future.get(); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (ExecutionException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - //delete the volume - vol = volumeFactory.getVolume(volume.getId(), primaryStore); - future = volumeService.expungeVolumeAsync(vol); - try { + } + + // @Test(priority=3) + public void createAndDeleteDataDisk() { + DataStore primaryStore = this.primaryStore; + VolumeVO volume = createVolume(null, primaryStore.getId()); + VolumeInfo vol = volumeFactory.getVolume(volume.getId(), primaryStore); + AsyncCallFuture future = volumeService.createVolumeAsync(vol, primaryStore); + try { future.get(); } catch (InterruptedException e) { // TODO Auto-generated catch block @@ -431,41 +421,53 @@ public class volumeServiceTest extends CloudStackTestNGBase { // TODO Auto-generated catch block e.printStackTrace(); } - } - //@Test(priority=3) - public void tearDown() { - List ds = primaryStoreDao.findPoolByName(this.primaryName); - for (int i = 0; i < ds.size(); i++) { - StoragePoolVO store = ds.get(i); - store.setUuid(null); - primaryStoreDao.remove(ds.get(i).getId()); - primaryStoreDao.expunge(ds.get(i).getId()); - } - } + // delete the volume + vol = volumeFactory.getVolume(volume.getId(), primaryStore); + future = volumeService.expungeVolumeAsync(vol); + try { + future.get(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } - //@Test - //@Test + // @Test(priority=3) + public void tearDown() { + List ds = primaryStoreDao.findPoolByName(this.primaryName); + for (int i = 0; i < ds.size(); i++) { + StoragePoolVO store = ds.get(i); + store.setUuid(null); + primaryStoreDao.remove(ds.get(i).getId()); + primaryStoreDao.expunge(ds.get(i).getId()); + } + } + + // @Test + // @Test public void test1() { - /*System.out.println(VolumeTypeHelper.getType("Root")); - System.out.println(VolumeDiskTypeHelper.getDiskType("vmdk")); - System.out.println(ImageFormatHelper.getFormat("ova")); - AssertJUnit.assertFalse(new VMDK().equals(new VHD())); - VMDK vmdk = new VMDK(); - AssertJUnit.assertTrue(vmdk.equals(vmdk)); - VMDK newvmdk = new VMDK(); - AssertJUnit.assertTrue(vmdk.equals(newvmdk)); - - ImageFormat ova = new OVA(); - ImageFormat iso = new ISO(); - AssertJUnit.assertTrue(ova.equals(new OVA())); - AssertJUnit.assertFalse(ova.equals(iso)); - AssertJUnit.assertTrue(ImageFormatHelper.getFormat("test").equals(new Unknown())); - - VolumeDiskType qcow2 = new QCOW2(); - ImageFormat qcow2format = new org.apache.cloudstack.storage.image.format.QCOW2(); - AssertJUnit.assertFalse(qcow2.equals(qcow2format)); -*/ - } + /* + * System.out.println(VolumeTypeHelper.getType("Root")); + * System.out.println(VolumeDiskTypeHelper.getDiskType("vmdk")); + * System.out.println(ImageFormatHelper.getFormat("ova")); + * AssertJUnit.assertFalse(new VMDK().equals(new VHD())); VMDK vmdk = + * new VMDK(); AssertJUnit.assertTrue(vmdk.equals(vmdk)); VMDK newvmdk = + * new VMDK(); AssertJUnit.assertTrue(vmdk.equals(newvmdk)); + * + * ImageFormat ova = new OVA(); ImageFormat iso = new ISO(); + * AssertJUnit.assertTrue(ova.equals(new OVA())); + * AssertJUnit.assertFalse(ova.equals(iso)); + * AssertJUnit.assertTrue(ImageFormatHelper.getFormat("test").equals(new + * Unknown())); + * + * VolumeDiskType qcow2 = new QCOW2(); ImageFormat qcow2format = new + * org.apache.cloudstack.storage.image.format.QCOW2(); + * AssertJUnit.assertFalse(qcow2.equals(qcow2format)); + */ + } } diff --git a/engine/storage/integration-test/test/resource/s3_testng.xml b/engine/storage/integration-test/test/resource/s3_testng.xml new file mode 100644 index 00000000000..017cc9ba2f0 --- /dev/null +++ b/engine/storage/integration-test/test/resource/s3_testng.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/engine/storage/integration-test/test/resource/storageContext.xml b/engine/storage/integration-test/test/resource/storageContext.xml index 7c5382d49f9..9f4f102edec 100644 --- a/engine/storage/integration-test/test/resource/storageContext.xml +++ b/engine/storage/integration-test/test/resource/storageContext.xml @@ -21,23 +21,70 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - - - - - - - - - - - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/engine/storage/integration-test/test/resource/testng.xml b/engine/storage/integration-test/test/resource/testng.xml index db32c247d1b..fb4330999f3 100644 --- a/engine/storage/integration-test/test/resource/testng.xml +++ b/engine/storage/integration-test/test/resource/testng.xml @@ -23,12 +23,25 @@ - + - - + + + + + + + + + + + + + + + diff --git a/engine/storage/pom.xml b/engine/storage/pom.xml index 270fe47c743..cc561161602 100644 --- a/engine/storage/pom.xml +++ b/engine/storage/pom.xml @@ -47,10 +47,15 @@ org.apache.cloudstack - cloud-engine-api + cloud-secondary-storage ${project.version} + org.apache.cloudstack + cloud-engine-api + ${project.version} + + mysql mysql-connector-java ${cs.mysql.version} diff --git a/engine/storage/snapshot/pom.xml b/engine/storage/snapshot/pom.xml index 211cdac574e..350a9a9eed6 100644 --- a/engine/storage/snapshot/pom.xml +++ b/engine/storage/snapshot/pom.xml @@ -25,6 +25,11 @@ cloud-engine-storage ${project.version} + + org.apache.cloudstack + cloud-engine-api + ${project.version} + mysql mysql-connector-java 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..aafdad05ff0 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 @@ -21,19 +21,16 @@ package org.apache.cloudstack.storage.snapshot; import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType; 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.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; -import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; import org.springframework.stereotype.Component; -import com.cloud.storage.Snapshot; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.SnapshotVO; import com.cloud.storage.dao.SnapshotDao; import com.cloud.utils.exception.CloudRuntimeException; @@ -43,42 +40,38 @@ public class SnapshotDataFactoryImpl implements SnapshotDataFactory { @Inject SnapshotDao snapshotDao; @Inject - ObjectInDataStoreManager objMap; + SnapshotDataStoreDao snapshotStoreDao; @Inject DataStoreManager storeMgr; @Inject VolumeDataFactory volumeFactory; + @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()); - if (obj == null) { - return null; - } - SnapshotObject so = SnapshotObject.getSnapshotObject(snapshot, store); + SnapshotVO snapshot = snapshotDao.findById(snapshotId); + SnapshotObject so = SnapshotObject.getSnapshotObject(snapshot, store); return so; } - @Override - public SnapshotInfo getSnapshot(long snapshotId) { - SnapshotVO snapshot = snapshotDao.findByIdIncludingRemoved(snapshotId); - SnapshotObject so = null; - if (snapshot.getState() == Snapshot.State.BackedUp) { - DataStore store = objMap.findStore(snapshot.getUuid(), DataObjectType.SNAPSHOT, DataStoreRole.Image); - so = SnapshotObject.getSnapshotObject(snapshot, store); - } else { - VolumeInfo volume = this.volumeFactory.getVolume(snapshot.getVolumeId()); - so = SnapshotObject.getSnapshotObject(snapshot, volume.getDataStore()); - } - return so; - } - + @Override public SnapshotInfo getSnapshot(DataObject obj, DataStore store) { - SnapshotVO snapshot = snapshotDao.findByIdIncludingRemoved(obj.getId()); + SnapshotVO snapshot = snapshotDao.findById(obj.getId()); if (snapshot == null) { throw new CloudRuntimeException("Can't find snapshot: " + obj.getId()); } - SnapshotObject so = SnapshotObject.getSnapshotObject(snapshot, store); + SnapshotObject so = SnapshotObject.getSnapshotObject(snapshot, store); + return so; + } + + @Override + public SnapshotInfo getSnapshot(long snapshotId, DataStoreRole role) { + SnapshotVO snapshot = snapshotDao.findById(snapshotId); + SnapshotDataStoreVO snapshotStore = snapshotStoreDao.findBySnapshot(snapshotId, role); + if (snapshotStore == null) { + return null; + } + DataStore store = this.storeMgr.getDataStore(snapshotStore.getDataStoreId(), role); + SnapshotObject so = SnapshotObject.getSnapshotObject(snapshot, store); return so; } } diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java index 37238b72121..1cba96efd40 100644 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java @@ -22,50 +22,68 @@ import java.util.Date; import javax.inject.Inject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat; +import org.apache.cloudstack.storage.command.CopyCmdAnswer; +import org.apache.cloudstack.storage.command.CreateObjectAnswer; import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; +import org.apache.cloudstack.storage.to.SnapshotObjectTO; import org.apache.log4j.Logger; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataTO; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.Snapshot; import com.cloud.storage.SnapshotVO; import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.VolumeDao; import com.cloud.utils.component.ComponentContext; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.SearchCriteria2; +import com.cloud.utils.db.SearchCriteriaService; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.fsm.NoTransitionException; public class SnapshotObject implements SnapshotInfo { - private static final Logger s_logger = Logger.getLogger(SnapshotObject.class); + private static final Logger s_logger = Logger.getLogger(SnapshotObject.class); private SnapshotVO snapshot; private DataStore store; @Inject - protected SnapshotDao snapshotDao; + protected SnapshotDao snapshotDao; @Inject protected VolumeDao volumeDao; - @Inject protected VolumeDataFactory volFactory; - @Inject protected SnapshotStateMachineManager stateMachineMgr; @Inject - ObjectInDataStoreManager ojbectInStoreMgr; + protected VolumeDataFactory volFactory; + @Inject + protected SnapshotStateMachineManager stateMachineMgr; + @Inject + SnapshotDataFactory snapshotFactory; + @Inject + ObjectInDataStoreManager objectInStoreMgr; + @Inject + SnapshotDataStoreDao snapshotStoreDao; + public SnapshotObject() { - + } - + protected void configure(SnapshotVO snapshot, DataStore store) { - this.snapshot = snapshot; - this.store = store; + this.snapshot = snapshot; + this.store = store; } - + public static SnapshotObject getSnapshotObject(SnapshotVO snapshot, DataStore store) { - SnapshotObject snapObj = ComponentContext.inject(SnapshotObject.class); - snapObj.configure(snapshot, store); - return snapObj; + SnapshotObject snapObj = ComponentContext.inject(SnapshotObject.class); + snapObj.configure(snapshot, store); + return snapObj; } public DataStore getStore() { @@ -74,14 +92,32 @@ public class SnapshotObject implements SnapshotInfo { @Override public SnapshotInfo getParent() { - // TODO Auto-generated method stub - return null; + SnapshotDataStoreVO snapStoreVO = this.snapshotStoreDao.findByStoreSnapshot(this.store.getRole(), + this.store.getId(), this.snapshot.getId()); + if (snapStoreVO == null) { + return null; + } + + long parentId = snapStoreVO.getParentSnapshotId(); + if (parentId == 0) { + return null; + } + + return this.snapshotFactory.getSnapshot(parentId, store); } @Override public SnapshotInfo getChild() { - // TODO Auto-generated method stub - return null; + SearchCriteriaService sc = SearchCriteria2 + .create(SnapshotDataStoreVO.class); + sc.addAnd(sc.getEntity().getDataStoreId(), Op.EQ, this.store.getId()); + sc.addAnd(sc.getEntity().getRole(), Op.EQ, this.store.getRole()); + sc.addAnd(sc.getEntity().getParentSnapshotId(), Op.EQ, this.getId()); + SnapshotDataStoreVO vo = sc.find(); + if (vo == null) { + return null; + } + return this.snapshotFactory.getSnapshot(vo.getId(), store); } @Override @@ -91,7 +127,7 @@ public class SnapshotObject implements SnapshotInfo { @Override public long getId() { - return this.snapshot.getId(); + return this.snapshot.getId(); } @Override @@ -106,17 +142,12 @@ public class SnapshotObject implements SnapshotInfo { @Override public Long getSize() { - return this.snapshot.getSize(); + return this.snapshot.getSize(); } @Override public DataObjectType getType() { - return DataObjectType.SNAPSHOT; - } - - @Override - public DiskFormat getFormat() { - return null; + return DataObjectType.SNAPSHOT; } @Override @@ -124,100 +155,180 @@ public class SnapshotObject implements SnapshotInfo { return this.snapshot.getUuid(); } - @Override - public void processEvent( - ObjectInDataStoreStateMachine.Event event) { - try { - ojbectInStoreMgr.update(this, event); - } catch (Exception e) { - s_logger.debug("Failed to update state:" + e.toString()); - throw new CloudRuntimeException("Failed to update state: " + e.toString()); - } - } + @Override + public void processEvent(ObjectInDataStoreStateMachine.Event event) { + try { + objectInStoreMgr.update(this, event); + } catch (Exception e) { + s_logger.debug("Failed to update state:" + e.toString()); + throw new CloudRuntimeException("Failed to update state: " + e.toString()); + } finally { + if (event == ObjectInDataStoreStateMachine.Event.OperationFailed) { + objectInStoreMgr.delete(this); + } + } + } - @Override - public long getAccountId() { - return this.snapshot.getAccountId(); - } + @Override + public long getAccountId() { + return this.snapshot.getAccountId(); + } - @Override - public long getVolumeId() { - return this.snapshot.getVolumeId(); - } + @Override + public long getVolumeId() { + return this.snapshot.getVolumeId(); + } - @Override - public String getPath() { - return this.snapshot.getPath(); - } - - public void setPath(String path) { - this.snapshot.setPath(path); - } + @Override + public String getPath() { + return this.objectInStoreMgr.findObject(this, getDataStore()).getInstallPath(); + } - @Override - public String getName() { - return this.snapshot.getName(); - } + @Override + public String getName() { + return this.snapshot.getName(); + } - @Override - public Date getCreated() { - return this.snapshot.getCreated(); - } + @Override + public Date getCreated() { + return this.snapshot.getCreated(); + } - @Override - public Type getRecurringType() { - return this.snapshot.getRecurringType(); - } + @Override + public Type getRecurringType() { + return this.snapshot.getRecurringType(); + } - @Override - public State getState() { - return this.snapshot.getState(); - } + @Override + public State getState() { + return this.snapshot.getState(); + } - @Override - public HypervisorType getHypervisorType() { - return this.snapshot.getHypervisorType(); - } + @Override + public HypervisorType getHypervisorType() { + return this.snapshot.getHypervisorType(); + } - @Override - public boolean isRecursive() { - return this.snapshot.isRecursive(); - } + @Override + public boolean isRecursive() { + return this.snapshot.isRecursive(); + } - @Override - public short getsnapshotType() { - return this.snapshot.getsnapshotType(); - } + @Override + public short getsnapshotType() { + return this.snapshot.getsnapshotType(); + } - @Override - public long getDomainId() { - return this.snapshot.getDomainId(); - } - - public void setPrevSnapshotId(Long id) { - this.snapshot.setPrevSnapshotId(id); - } + @Override + public long getDomainId() { + return this.snapshot.getDomainId(); + } - @Override - public Long getDataCenterId() { - return this.snapshot.getDataCenterId(); - } - - public void processEvent(Snapshot.Event event) - throws NoTransitionException { - stateMachineMgr.processEvent(this.snapshot, event); - } + @Override + public Long getDataCenterId() { + return this.snapshot.getDataCenterId(); + } - @Override - public Long getPrevSnapshotId() { - return this.snapshot.getPrevSnapshotId(); - } - - public void setBackupSnapshotId(String id) { - this.snapshot.setBackupSnapshotId(id); - } - - public String getBackupSnapshotId() { - return this.snapshot.getBackupSnapshotId(); - } + public void processEvent(Snapshot.Event event) throws NoTransitionException { + stateMachineMgr.processEvent(this.snapshot, event); + } + + public SnapshotVO getSnapshotVO() { + return this.snapshot; + } + + @Override + public DataTO getTO() { + DataTO to = this.store.getDriver().getTO(this); + if (to == null) { + return new SnapshotObjectTO(this); + } + return to; + } + + @Override + public void processEvent(ObjectInDataStoreStateMachine.Event event, Answer answer) { + try { + SnapshotDataStoreVO snapshotStore = this.snapshotStoreDao.findByStoreSnapshot( + this.getDataStore().getRole(), this.getDataStore().getId(), this.getId()); + if (answer instanceof CreateObjectAnswer) { + SnapshotObjectTO snapshotTO = (SnapshotObjectTO) ((CreateObjectAnswer) answer).getData(); + snapshotStore.setInstallPath(snapshotTO.getPath()); + this.snapshotStoreDao.update(snapshotStore.getId(), snapshotStore); + } else if (answer instanceof CopyCmdAnswer) { + SnapshotObjectTO snapshotTO = (SnapshotObjectTO) ((CopyCmdAnswer) answer).getNewData(); + snapshotStore.setInstallPath(snapshotTO.getPath()); + if (snapshotTO.getParentSnapshotPath() == null) { + snapshotStore.setParentSnapshotId(0L); + } + this.snapshotStoreDao.update(snapshotStore.getId(), snapshotStore); + } else { + throw new CloudRuntimeException("Unknown answer: " + answer.getClass()); + } + } catch (RuntimeException ex) { + if (event == ObjectInDataStoreStateMachine.Event.OperationFailed) { + objectInStoreMgr.delete(this); + } + throw ex; + } + this.processEvent(event); + } + + public void incRefCount() { + if (this.store == null) { + return; + } + + if (this.store.getRole() == DataStoreRole.Image || this.store.getRole() == DataStoreRole.ImageCache) { + SnapshotDataStoreVO store = snapshotStoreDao.findByStoreSnapshot(this.store.getRole(), this.store.getId(), + this.getId()); + store.incrRefCnt(); + store.setLastUpdated(new Date()); + snapshotStoreDao.update(store.getId(), store); + } + } + + @Override + public void decRefCount() { + if (this.store == null) { + return; + } + if (this.store.getRole() == DataStoreRole.Image || this.store.getRole() == DataStoreRole.ImageCache) { + SnapshotDataStoreVO store = snapshotStoreDao.findByStoreSnapshot(this.store.getRole(), this.store.getId(), + this.getId()); + store.decrRefCnt(); + store.setLastUpdated(new Date()); + snapshotStoreDao.update(store.getId(), store); + } + } + + @Override + public Long getRefCount() { + if (this.store == null) { + return null; + } + if (this.store.getRole() == DataStoreRole.Image || this.store.getRole() == DataStoreRole.ImageCache) { + SnapshotDataStoreVO store = snapshotStoreDao.findByStoreSnapshot(this.store.getRole(), this.store.getId(), + this.getId()); + return store.getRefCnt(); + } + return null; + } + + @Override + public ObjectInDataStoreStateMachine.State getStatus() { + return this.objectInStoreMgr.findObject(this, store).getObjectInStoreState(); + } + + @Override + public void addPayload(Object data) { + } + + @Override + public boolean delete() { + if (store != null) { + return store.delete(this); + } + return true; + } } diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java index 1b64fd0cae3..631d220f69d 100644 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java @@ -14,43 +14,369 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + package org.apache.cloudstack.storage.snapshot; -import org.apache.cloudstack.engine.cloud.entity.api.SnapshotEntity; -import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.Snapshot; +import com.cloud.storage.VolumeManager; +import com.cloud.storage.dao.SnapshotDao; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.storage.snapshot.SnapshotManager; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.fsm.NoTransitionException; +import com.cloud.vm.dao.UserVmDao; +import com.cloud.vm.snapshot.dao.VMSnapshotDao; +import org.apache.cloudstack.engine.subsystem.api.storage.*; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; +import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.framework.async.AsyncRpcConext; +import org.apache.cloudstack.storage.command.CommandResult; +import org.apache.cloudstack.storage.command.CopyCmdAnswer; +import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; +import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import javax.inject.Inject; +import java.util.concurrent.ExecutionException; + @Component public class SnapshotServiceImpl implements SnapshotService { - - public SnapshotServiceImpl() { - - } + private static final Logger s_logger = Logger.getLogger(SnapshotServiceImpl.class); + @Inject + protected VolumeDao _volsDao; + @Inject + protected UserVmDao _vmDao; + @Inject + protected PrimaryDataStoreDao _storagePoolDao; + @Inject + protected ClusterDao _clusterDao; + @Inject + protected SnapshotDao _snapshotDao; + @Inject + protected SnapshotDataStoreDao _snapshotStoreDao; - @Override - public SnapshotEntity getSnapshotEntity(long snapshotId) { - // TODO Auto-generated method stub - return null; - } + @Inject + protected SnapshotManager snapshotMgr; + @Inject + protected VolumeManager volumeMgr; + @Inject + protected SnapshotStateMachineManager stateMachineManager; + @Inject + SnapshotDataFactory snapshotfactory; + @Inject + DataStoreManager dataStoreMgr; + @Inject + DataMotionService motionSrv; + @Inject + ObjectInDataStoreManager objInStoreMgr; + @Inject + VMSnapshotDao _vmSnapshotDao; - @Override - public boolean takeSnapshot(SnapshotInfo snapshot) { - // TODO Auto-generated method stub - return false; - } + static private class CreateSnapshotContext extends AsyncRpcConext { + final SnapshotInfo snapshot; + final AsyncCallFuture future; - @Override - public boolean revertSnapshot(SnapshotInfo snapshot) { - // TODO Auto-generated method stub - return false; - } + public CreateSnapshotContext(AsyncCompletionCallback callback, VolumeInfo volume, SnapshotInfo snapshot, + AsyncCallFuture future) { + super(callback); + this.snapshot = snapshot; + this.future = future; + } + } - @Override - public boolean deleteSnapshot(SnapshotInfo snapshot) { - // TODO Auto-generated method stub - return false; - } - - + static private class DeleteSnapshotContext extends AsyncRpcConext { + final SnapshotInfo snapshot; + final AsyncCallFuture future; + + public DeleteSnapshotContext(AsyncCompletionCallback callback, SnapshotInfo snapshot, + AsyncCallFuture future) { + super(callback); + this.snapshot = snapshot; + this.future = future; + } + + } + + static private class CopySnapshotContext extends AsyncRpcConext { + final SnapshotInfo srcSnapshot; + final SnapshotInfo destSnapshot; + final AsyncCallFuture future; + + public CopySnapshotContext(AsyncCompletionCallback callback, SnapshotInfo srcSnapshot, + SnapshotInfo destSnapshot, AsyncCallFuture future) { + super(callback); + this.srcSnapshot = srcSnapshot; + this.destSnapshot = destSnapshot; + this.future = future; + } + + } + + protected Void createSnapshotAsyncCallback(AsyncCallbackDispatcher callback, + CreateSnapshotContext context) { + CreateCmdResult result = callback.getResult(); + SnapshotObject snapshot = (SnapshotObject) context.snapshot; + AsyncCallFuture future = context.future; + SnapshotResult snapResult = new SnapshotResult(snapshot, result.getAnswer()); + if (result.isFailed()) { + s_logger.debug("create snapshot " + context.snapshot.getName() + " failed: " + result.getResult()); + try { + snapshot.processEvent(Snapshot.Event.OperationFailed); + snapshot.processEvent(Event.OperationFailed); + } catch (Exception e) { + s_logger.debug("Failed to update snapshot state due to " + e.getMessage()); + } + + snapResult.setResult(result.getResult()); + future.complete(snapResult); + return null; + } + + try { + snapshot.processEvent(Event.OperationSuccessed, result.getAnswer()); + snapshot.processEvent(Snapshot.Event.OperationSucceeded); + } catch (Exception e) { + s_logger.debug("Failed to create snapshot: ", e); + snapResult.setResult(e.toString()); + try { + snapshot.processEvent(Snapshot.Event.OperationFailed); + } catch (NoTransitionException e1) { + s_logger.debug("Failed to change snapshot state: " + e1.toString()); + } + } + + future.complete(snapResult); + return null; + } + + @Override + public SnapshotResult takeSnapshot(SnapshotInfo snap) { + SnapshotObject snapshot = (SnapshotObject) snap; + + SnapshotObject snapshotOnPrimary = null; + try { + snapshotOnPrimary = (SnapshotObject) snap.getDataStore().create(snapshot); + } catch (Exception e) { + s_logger.debug("Failed to create snapshot state on data store due to " + e.getMessage()); + throw new CloudRuntimeException(e); + } + + try { + snapshotOnPrimary.processEvent(Snapshot.Event.CreateRequested); + } catch (NoTransitionException e) { + s_logger.debug("Failed to change snapshot state: " + e.toString()); + throw new CloudRuntimeException(e); + } + + try { + snapshotOnPrimary.processEvent(Event.CreateOnlyRequested); + } catch (Exception e) { + s_logger.debug("Failed to change snapshot state: " + e.toString()); + try { + snapshotOnPrimary.processEvent(Snapshot.Event.OperationFailed); + } catch (NoTransitionException e1) { + s_logger.debug("Failed to change snapshot state: " + e1.toString()); + } + throw new CloudRuntimeException(e); + } + + AsyncCallFuture future = new AsyncCallFuture(); + try { + CreateSnapshotContext context = new CreateSnapshotContext(null, + snap.getBaseVolume(), snapshotOnPrimary, future); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().createSnapshotAsyncCallback(null, null)).setContext(context); + PrimaryDataStoreDriver primaryStore = (PrimaryDataStoreDriver) snapshotOnPrimary.getDataStore().getDriver(); + primaryStore.takeSnapshot(snapshot, caller); + } catch (Exception e) { + s_logger.debug("Failed to take snapshot: " + snapshot.getId(), e); + try { + snapshot.processEvent(Snapshot.Event.OperationFailed); + } catch (NoTransitionException e1) { + s_logger.debug("Failed to change state for event: OperationFailed", e); + } + throw new CloudRuntimeException("Failed to take snapshot" + snapshot.getId()); + } + + SnapshotResult result; + + try { + result = future.get(); + if (result.isFailed()) { + s_logger.debug("Failed to create snapshot:" + result.getResult()); + throw new CloudRuntimeException(result.getResult()); + } + return result; + } catch (InterruptedException e) { + s_logger.debug("Failed to create snapshot", e); + throw new CloudRuntimeException("Failed to create snapshot", e); + } catch (ExecutionException e) { + s_logger.debug("Failed to create snapshot", e); + throw new CloudRuntimeException("Failed to create snapshot", e); + } + + } + + // if a snapshot has parent snapshot, the new snapshot should be stored in + // the same store as its parent since + // we are taking delta snapshot + private DataStore findSnapshotImageStore(SnapshotInfo snapshot) { + if (snapshot.getParent() == null) { + return dataStoreMgr.getImageStore(snapshot.getDataCenterId()); + } else { + SnapshotInfo parentSnapshot = snapshot.getParent(); + // Note that DataStore information in parentSnapshot is for primary + // data store here, we need to + // find the image store where the parent snapshot backup is located + SnapshotDataStoreVO parentSnapshotOnBackupStore = _snapshotStoreDao.findBySnapshot(parentSnapshot.getId(), + DataStoreRole.Image); + return dataStoreMgr.getDataStore(parentSnapshotOnBackupStore.getDataStoreId(), + parentSnapshotOnBackupStore.getRole()); + } + } + + @Override + public SnapshotInfo backupSnapshot(SnapshotInfo snapshot) { + SnapshotObject snapObj = (SnapshotObject) snapshot; + AsyncCallFuture future = new AsyncCallFuture(); + SnapshotResult result = new SnapshotResult(snapshot, null); + try { + + snapObj.processEvent(Snapshot.Event.BackupToSecondary); + + DataStore imageStore = this.findSnapshotImageStore(snapshot); + if (imageStore == null) { + throw new CloudRuntimeException("can not find an image stores"); + } + + SnapshotInfo snapshotOnImageStore = (SnapshotInfo) imageStore.create(snapshot); + + snapshotOnImageStore.processEvent(Event.CreateOnlyRequested); + CopySnapshotContext context = new CopySnapshotContext(null, snapshot, + snapshotOnImageStore, future); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher + .create(this); + caller.setCallback(caller.getTarget().copySnapshotAsyncCallback(null, null)).setContext(context); + this.motionSrv.copyAsync(snapshot, snapshotOnImageStore, caller); + } catch (Exception e) { + s_logger.debug("Failed to copy snapshot", e); + result.setResult("Failed to copy snapshot:" + e.toString()); + try { + snapObj.processEvent(Snapshot.Event.OperationFailed); + } catch (NoTransitionException e1) { + s_logger.debug("Failed to change state: " + e1.toString()); + } + future.complete(result); + } + + try { + SnapshotResult res = future.get(); + if (res.isFailed()) { + throw new CloudRuntimeException(res.getResult()); + } + SnapshotInfo destSnapshot = res.getSnashot(); + return destSnapshot; + } catch (InterruptedException e) { + s_logger.debug("failed copy snapshot", e); + throw new CloudRuntimeException("Failed to copy snapshot", e); + } catch (ExecutionException e) { + s_logger.debug("Failed to copy snapshot", e); + throw new CloudRuntimeException("Failed to copy snapshot", e); + } + + } + + protected Void copySnapshotAsyncCallback(AsyncCallbackDispatcher callback, + CopySnapshotContext context) { + CopyCommandResult result = callback.getResult(); + SnapshotInfo destSnapshot = context.destSnapshot; + SnapshotObject srcSnapshot = (SnapshotObject) context.srcSnapshot; + AsyncCallFuture future = context.future; + SnapshotResult snapResult = new SnapshotResult(destSnapshot, result.getAnswer()); + if (result.isFailed()) { + try { + destSnapshot.processEvent(Event.OperationFailed); + srcSnapshot.processEvent(Snapshot.Event.OperationFailed); + } catch (NoTransitionException e) { + s_logger.debug("Failed to update state: " + e.toString()); + } + snapResult.setResult(result.getResult()); + future.complete(snapResult); + return null; + } + + try { + CopyCmdAnswer answer = (CopyCmdAnswer) result.getAnswer(); + destSnapshot.processEvent(Event.OperationSuccessed, result.getAnswer()); + srcSnapshot.processEvent(Snapshot.Event.OperationSucceeded); + snapResult = new SnapshotResult(this.snapshotfactory.getSnapshot(destSnapshot.getId(), + destSnapshot.getDataStore()), answer); + future.complete(snapResult); + } catch (Exception e) { + s_logger.debug("Failed to update snapshot state", e); + snapResult.setResult(e.toString()); + future.complete(snapResult); + } + return null; + } + + + protected Void deleteSnapshotCallback(AsyncCallbackDispatcher callback, + DeleteSnapshotContext context) { + CommandResult result = callback.getResult(); + AsyncCallFuture future = context.future; + SnapshotInfo snapshot = context.snapshot; + if (result.isFailed()) { + s_logger.debug("delete snapshot failed" + result.getResult()); + snapshot.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed); + SnapshotResult res = new SnapshotResult(context.snapshot, null); + future.complete(res); + return null; + } + snapshot.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed); + SnapshotResult res = new SnapshotResult(context.snapshot, null); + future.complete(res); + return null; + } + + @Override + public boolean deleteSnapshot(SnapshotInfo snapInfo) { + snapInfo.processEvent(ObjectInDataStoreStateMachine.Event.DestroyRequested); + + AsyncCallFuture future = new AsyncCallFuture(); + DeleteSnapshotContext context = new DeleteSnapshotContext(null, snapInfo, future); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().deleteSnapshotCallback(null, null)).setContext(context); + DataStore store = snapInfo.getDataStore(); + store.getDriver().deleteAsync(snapInfo, caller); + + SnapshotResult result = null; + try { + result = future.get(); + if (result.isFailed()) { + throw new CloudRuntimeException(result.getResult()); + } + return true; + } catch (InterruptedException e) { + s_logger.debug("delete snapshot is failed: " + e.toString()); + } catch (ExecutionException e) { + s_logger.debug("delete snapshot is failed: " + e.toString()); + } + + return false; + + } + + @Override + public boolean revertSnapshot(SnapshotInfo snapshot) { + return false; + } } diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManager.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManager.java index c6057704cd8..2ad4ae7d073 100644 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManager.java +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManager.java @@ -22,5 +22,5 @@ import com.cloud.storage.SnapshotVO; import com.cloud.utils.fsm.NoTransitionException; public interface SnapshotStateMachineManager { - public void processEvent(SnapshotVO snapshot, Event event) throws NoTransitionException; + void processEvent(SnapshotVO snapshot, Event event) throws NoTransitionException; } diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java index aa1cf684d7a..c756ddb4876 100644 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java @@ -31,24 +31,31 @@ import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.fsm.StateMachine2; @Component -public class SnapshotStateMachineManagerImpl implements -SnapshotStateMachineManager { - private StateMachine2 stateMachine = new StateMachine2(); +public class SnapshotStateMachineManagerImpl implements SnapshotStateMachineManager { + private StateMachine2 stateMachine = new StateMachine2(); @Inject - protected SnapshotDao snapshotDao; - public SnapshotStateMachineManagerImpl() { - stateMachine.addTransition(Snapshot.State.Allocated, Event.CreateRequested, Snapshot.State.Creating); - stateMachine.addTransition(Snapshot.State.Creating, Event.OperationSucceeded, Snapshot.State.CreatedOnPrimary); - stateMachine.addTransition(Snapshot.State.Creating, Event.OperationNotPerformed, Snapshot.State.BackedUp); - stateMachine.addTransition(Snapshot.State.Creating, Event.OperationFailed, Snapshot.State.Error); - stateMachine.addTransition(Snapshot.State.CreatedOnPrimary, Event.BackupToSecondary, Snapshot.State.BackingUp); - stateMachine.addTransition(Snapshot.State.BackingUp, Event.OperationSucceeded, Snapshot.State.BackedUp); - stateMachine.addTransition(Snapshot.State.BackingUp, Event.OperationFailed, Snapshot.State.CreatedOnPrimary); - - stateMachine.registerListener(new SnapshotStateListener()); - } - - public void processEvent(SnapshotVO snapshot, Event event) throws NoTransitionException { - stateMachine.transitTo(snapshot, event, null, snapshotDao); - } -} + protected SnapshotDao snapshotDao; + + public SnapshotStateMachineManagerImpl() { + stateMachine.addTransition(Snapshot.State.Allocated, Event.CreateRequested, Snapshot.State.Creating); + stateMachine.addTransition(Snapshot.State.Creating, Event.OperationSucceeded, Snapshot.State.CreatedOnPrimary); + stateMachine.addTransition(Snapshot.State.Creating, Event.OperationNotPerformed, Snapshot.State.BackedUp); + stateMachine.addTransition(Snapshot.State.Creating, Event.OperationFailed, Snapshot.State.Error); + stateMachine.addTransition(Snapshot.State.CreatedOnPrimary, Event.BackupToSecondary, Snapshot.State.BackingUp); + stateMachine.addTransition(Snapshot.State.BackingUp, Event.OperationSucceeded, Snapshot.State.BackedUp); + stateMachine.addTransition(Snapshot.State.BackingUp, Event.OperationFailed, Snapshot.State.CreatedOnPrimary); + stateMachine.addTransition(Snapshot.State.BackedUp, Event.DestroyRequested, Snapshot.State.Destroying); + stateMachine.addTransition(Snapshot.State.BackedUp, Event.CopyingRequested, Snapshot.State.Copying); + stateMachine.addTransition(Snapshot.State.Copying, Event.OperationSucceeded, Snapshot.State.BackedUp); + stateMachine.addTransition(Snapshot.State.Copying, Event.OperationFailed, Snapshot.State.BackedUp); + stateMachine.addTransition(Snapshot.State.Destroying, Event.OperationSucceeded, Snapshot.State.Destroyed); + stateMachine.addTransition(Snapshot.State.Destroying, Event.OperationFailed, Snapshot.State.Error); + + stateMachine.registerListener(new SnapshotStateListener()); + } + + @Override + public void processEvent(SnapshotVO snapshot, Event event) throws NoTransitionException { + stateMachine.transitTo(snapshot, event, null, snapshotDao); + } +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotService.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStrategyBase.java similarity index 57% rename from engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotService.java rename to engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStrategyBase.java index f3e5c4aea50..1b579227f84 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotService.java +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStrategyBase.java @@ -11,17 +11,28 @@ // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the +// KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package org.apache.cloudstack.storage.snapshot; -import org.apache.cloudstack.engine.cloud.entity.api.SnapshotEntity; -import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; +import javax.inject.Inject; -public interface SnapshotService { - public SnapshotEntity getSnapshotEntity(long snapshotId); - public boolean takeSnapshot(SnapshotInfo snapshot); - public boolean revertSnapshot(SnapshotInfo snapshot); - public boolean deleteSnapshot(SnapshotInfo snapshot); +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy; + +public abstract class SnapshotStrategyBase implements SnapshotStrategy { + @Inject + SnapshotService snapshotSvr; + + @Override + public SnapshotInfo takeSnapshot(SnapshotInfo snapshot) { + return snapshotSvr.takeSnapshot(snapshot).getSnashot(); + } + + @Override + public SnapshotInfo backupSnapshot(SnapshotInfo snapshot) { + return snapshotSvr.backupSnapshot(snapshot); + } } diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java new file mode 100644 index 00000000000..92af8c2b071 --- /dev/null +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java @@ -0,0 +1,204 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.snapshot; + +import javax.inject.Inject; + +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.ObjectInDataStoreStateMachine.Event; +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.SnapshotInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService; +import org.apache.cloudstack.storage.command.CreateObjectAnswer; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; +import org.apache.cloudstack.storage.to.SnapshotObjectTO; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.Snapshot; +import com.cloud.storage.SnapshotVO; +import com.cloud.storage.dao.SnapshotDao; +import com.cloud.storage.snapshot.SnapshotManager; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.fsm.NoTransitionException; + +@Component +public class XenserverSnapshotStrategy extends SnapshotStrategyBase { + private static final Logger s_logger = Logger.getLogger(XenserverSnapshotStrategy.class); + + @Inject + SnapshotManager snapshotMgr; + @Inject + SnapshotService snapshotSvr; + @Inject + DataStoreManager dataStoreMgr; + @Inject + SnapshotDataStoreDao snapshotStoreDao; + @Inject + ConfigurationDao configDao; + @Inject + SnapshotDao snapshotDao; + @Inject + SnapshotDataFactory snapshotDataFactory; + + @Override + public SnapshotInfo backupSnapshot(SnapshotInfo snapshot) { + SnapshotInfo parentSnapshot = snapshot.getParent(); + if (parentSnapshot != null && parentSnapshot.getPath().equalsIgnoreCase(snapshot.getPath())) { + s_logger.debug("backup an empty snapshot"); + // don't need to backup this snapshot + SnapshotDataStoreVO parentSnapshotOnBackupStore = this.snapshotStoreDao.findBySnapshot( + parentSnapshot.getId(), DataStoreRole.Image); + if (parentSnapshotOnBackupStore != null && parentSnapshotOnBackupStore.getState() == State.Ready) { + DataStore store = dataStoreMgr.getDataStore(parentSnapshotOnBackupStore.getDataStoreId(), + parentSnapshotOnBackupStore.getRole()); + + SnapshotInfo snapshotOnImageStore = (SnapshotInfo) store.create(snapshot); + snapshotOnImageStore.processEvent(Event.CreateOnlyRequested); + + SnapshotObjectTO snapTO = new SnapshotObjectTO(); + snapTO.setPath(parentSnapshotOnBackupStore.getInstallPath()); + CreateObjectAnswer createSnapshotAnswer = new CreateObjectAnswer(snapTO); + + snapshotOnImageStore.processEvent(Event.OperationSuccessed, createSnapshotAnswer); + SnapshotObject snapObj = (SnapshotObject) snapshot; + try { + snapObj.processEvent(Snapshot.Event.OperationNotPerformed); + } catch (NoTransitionException e) { + s_logger.debug("Failed to change state: " + snapshot.getId() + ": " + e.toString()); + throw new CloudRuntimeException(e.toString()); + } + return this.snapshotDataFactory.getSnapshot(snapObj.getId(), store); + } else { + s_logger.debug("parent snapshot hasn't been backed up yet"); + } + } + + // determine full snapshot backup or not + + boolean fullBackup = false; + + if (parentSnapshot != null) { + int _deltaSnapshotMax = NumbersUtil.parseInt(configDao.getValue("snapshot.delta.max"), + SnapshotManager.DELTAMAX); + int deltaSnap = _deltaSnapshotMax; + + int i; + SnapshotDataStoreVO parentSnapshotOnBackupStore = null; + for (i = 1; i < deltaSnap; i++) { + parentSnapshotOnBackupStore = this.snapshotStoreDao.findBySnapshot(parentSnapshot.getId(), + DataStoreRole.Image); + + Long prevBackupId = parentSnapshotOnBackupStore.getParentSnapshotId(); + + if (prevBackupId == 0) { + break; + } + + parentSnapshotOnBackupStore = this.snapshotStoreDao.findBySnapshot(prevBackupId, DataStoreRole.Image); + } + if (i >= deltaSnap) { + fullBackup = true; + } + } + + snapshot.addPayload(fullBackup); + return this.snapshotSvr.backupSnapshot(snapshot); + } + + protected void deleteSnapshotChain(SnapshotInfo snapshot) { + while (snapshot != null) { + SnapshotInfo child = snapshot.getChild(); + SnapshotInfo parent = snapshot.getParent(); + if (child == null) { + if (parent == null || !parent.getPath().equalsIgnoreCase(snapshot.getPath())) { + this.snapshotSvr.deleteSnapshot(snapshot); + snapshot = parent; + continue; + } + break; + } else { + break; + } + } + } + + @Override + public boolean deleteSnapshot(Long snapshotId) { + SnapshotVO snapshotVO = snapshotDao.findById(snapshotId); + if (snapshotVO.getState() == Snapshot.State.Destroyed) { + return true; + } + + if (!Snapshot.State.BackedUp.equals(snapshotVO.getState())) { + throw new InvalidParameterValueException("Can't delete snapshotshot " + snapshotId + + " due to it is not in BackedUp Status"); + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Calling deleteSnapshot for snapshotId: " + snapshotId); + } + + // firt mark the snapshot as destroyed, so that ui can't see it, but we + // may not destroy the snapshot on the storage, as other snaphosts may + // depend on it. + SnapshotInfo snapshotOnPrimary = this.snapshotDataFactory.getSnapshot(snapshotId, DataStoreRole.Primary); + SnapshotObject obj = (SnapshotObject) snapshotOnPrimary; + try { + obj.processEvent(Snapshot.Event.DestroyRequested); + } catch (NoTransitionException e) { + s_logger.debug("Failed to destroy snapshot: " + e.toString()); + return false; + } + + try { + SnapshotInfo snapshotOnImage = this.snapshotDataFactory.getSnapshot(snapshotId, DataStoreRole.Image); + if (snapshotOnImage != null) { + deleteSnapshotChain(snapshotOnImage); + } + + obj.processEvent(Snapshot.Event.OperationSucceeded); + } catch (Exception e) { + s_logger.debug("Failed to delete snapshot: " + e.toString()); + try { + obj.processEvent(Snapshot.Event.OperationFailed); + } catch (NoTransitionException e1) { + s_logger.debug("Failed to change snapshot state: " + e.toString()); + } + } + + return true; + } + + @Override + public SnapshotInfo takeSnapshot(SnapshotInfo snapshot) { + snapshot = snapshotSvr.takeSnapshot(snapshot).getSnashot(); + return this.backupSnapshot(snapshot); + } + + @Override + public boolean canHandle(Snapshot snapshot) { + return true; + } +} diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/db/SnapshotDao2.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/db/SnapshotDao2.java deleted file mode 100644 index d531ede0aba..00000000000 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/db/SnapshotDao2.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.snapshot.db; - -import com.cloud.utils.db.GenericDao; - -public interface SnapshotDao2 extends GenericDao { - -} diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/db/SnapshotDao2Impl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/db/SnapshotDao2Impl.java deleted file mode 100644 index 74cec5e76e5..00000000000 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/db/SnapshotDao2Impl.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.snapshot.db; - -import org.springframework.stereotype.Component; - -import com.cloud.utils.db.GenericDaoBase; - -@Component -public class SnapshotDao2Impl extends GenericDaoBase implements SnapshotDao2 { - -} diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/db/SnapshotVO.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/db/SnapshotVO.java deleted file mode 100644 index b05b803623f..00000000000 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/db/SnapshotVO.java +++ /dev/null @@ -1,296 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// 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, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package org.apache.cloudstack.storage.snapshot.db; - -import java.util.Date; -import java.util.UUID; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.Table; - -import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.storage.Snapshot.State; -import com.cloud.storage.Snapshot.Type; -import com.cloud.utils.db.GenericDao; -import com.google.gson.annotations.Expose; - -@Entity -@Table(name="snapshots") -public class SnapshotVO { - @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - @Column(name="id") - private final long id = -1; - - @Column(name="data_center_id") - long dataCenterId; - - @Column(name="account_id") - long accountId; - - @Column(name="domain_id") - long domainId; - - @Column(name="volume_id") - Long volumeId; - - @Column(name="disk_offering_id") - Long diskOfferingId; - - @Expose - @Column(name="path") - String path; - - @Expose - @Column(name="name") - String name; - - @Expose - @Column(name="status", updatable = true, nullable=false) - @Enumerated(value=EnumType.STRING) - private State status; - - @Column(name="snapshot_type") - short snapshotType; - - @Column(name="type_description") - String typeDescription; - - @Column(name="size") - long size; - - @Column(name=GenericDao.CREATED_COLUMN) - Date created; - - @Column(name=GenericDao.REMOVED_COLUMN) - Date removed; - - @Column(name="backup_snap_id") - String backupSnapshotId; - - @Column(name="swift_id") - Long swiftId; - - @Column(name="s3_id") - Long s3Id; - - @Column(name="sechost_id") - Long secHostId; - - @Column(name="prev_snap_id") - long prevSnapshotId; - - @Column(name="hypervisor_type") - @Enumerated(value=EnumType.STRING) - HypervisorType hypervisorType; - - @Expose - @Column(name="version") - String version; - - @Column(name="uuid") - String uuid; - - public SnapshotVO() { - this.uuid = UUID.randomUUID().toString(); - } - - public SnapshotVO(long dcId, long accountId, long domainId, Long volumeId, Long diskOfferingId, String path, String name, short snapshotType, String typeDescription, long size, HypervisorType hypervisorType ) { - this.dataCenterId = dcId; - this.accountId = accountId; - this.domainId = domainId; - this.volumeId = volumeId; - this.diskOfferingId = diskOfferingId; - this.path = path; - this.name = name; - this.snapshotType = snapshotType; - this.typeDescription = typeDescription; - this.size = size; - this.status = State.Creating; - this.prevSnapshotId = 0; - this.hypervisorType = hypervisorType; - this.version = "2.2"; - this.uuid = UUID.randomUUID().toString(); - } - - public long getId() { - return id; - } - - public long getDataCenterId() { - return dataCenterId; - } - - - public long getAccountId() { - return accountId; - } - - - public long getDomainId() { - return domainId; - } - - public long getVolumeId() { - return volumeId; - } - - public long getDiskOfferingId() { - return diskOfferingId; - } - - public void setVolumeId(Long volumeId) { - this.volumeId = volumeId; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public String getName() { - return name; - } - - public short getsnapshotType() { - return snapshotType; - } - - public Type getType() { - if (snapshotType < 0 || snapshotType >= Type.values().length) { - return null; - } - return Type.values()[snapshotType]; - } - - public Long getSwiftId() { - return swiftId; - } - - public void setSwiftId(Long swiftId) { - this.swiftId = swiftId; - } - - public Long getSecHostId() { - return secHostId; - } - - public void setSecHostId(Long secHostId) { - this.secHostId = secHostId; - } - - public HypervisorType getHypervisorType() { - return hypervisorType; - } - - public void setSnapshotType(short snapshotType) { - this.snapshotType = snapshotType; - } - - public boolean isRecursive(){ - if ( snapshotType >= Type.HOURLY.ordinal() && snapshotType <= Type.MONTHLY.ordinal() ) { - return true; - } - return false; - } - - public long getSize() { - return size; - } - - public String getTypeDescription() { - return typeDescription; - } - public void setTypeDescription(String typeDescription) { - this.typeDescription = typeDescription; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public Date getCreated() { - return created; - } - - public Date getRemoved() { - return removed; - } - - public State getStatus() { - return status; - } - - public void setStatus(State status) { - this.status = status; - } - - public String getBackupSnapshotId(){ - return backupSnapshotId; - } - - public long getPrevSnapshotId(){ - return prevSnapshotId; - } - - public void setBackupSnapshotId(String backUpSnapshotId){ - this.backupSnapshotId = backUpSnapshotId; - } - - public void setPrevSnapshotId(long prevSnapshotId){ - this.prevSnapshotId = prevSnapshotId; - } - - public static Type getSnapshotType(String snapshotType) { - for ( Type type : Type.values()) { - if ( type.equals(snapshotType)) { - return type; - } - } - return null; - } - - public String getUuid() { - return this.uuid; - } - - public void setUuid(String uuid) { - this.uuid = uuid; - } - - public Long getS3Id() { - return s3Id; - } - - public void setS3Id(Long s3Id) { - this.s3Id = s3Id; - } - -} diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/AncientSnapshotStrategy.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/AncientSnapshotStrategy.java deleted file mode 100644 index 4aba3d919b5..00000000000 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/AncientSnapshotStrategy.java +++ /dev/null @@ -1,613 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// 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, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -package org.apache.cloudstack.storage.snapshot.strategy; - -import java.util.List; -import java.util.concurrent.ExecutionException; - -import javax.inject.Inject; - -import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType; -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.ObjectInDataStoreStateMachine; -import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; -import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; -import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; -import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; -import org.apache.cloudstack.framework.async.AsyncCallFuture; -import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; -import org.apache.cloudstack.framework.async.AsyncCompletionCallback; -import org.apache.cloudstack.framework.async.AsyncRpcConext; -import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.motion.DataMotionService; -import org.apache.cloudstack.storage.snapshot.SnapshotObject; -import org.apache.cloudstack.storage.snapshot.SnapshotStateMachineManager; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.BackupSnapshotAnswer; -import com.cloud.agent.api.DeleteSnapshotBackupCommand; -import com.cloud.agent.api.to.S3TO; -import com.cloud.agent.api.to.SwiftTO; -import com.cloud.configuration.Resource.ResourceType; -import com.cloud.configuration.dao.ConfigurationDao; -import com.cloud.dc.ClusterVO; -import com.cloud.dc.dao.ClusterDao; -import com.cloud.event.EventTypes; -import com.cloud.event.UsageEventUtils; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.host.HostVO; -import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.resource.ResourceManager; -import com.cloud.storage.Snapshot; -import com.cloud.storage.SnapshotVO; -import com.cloud.storage.StoragePool; -import com.cloud.storage.VolumeManager; -import com.cloud.storage.VolumeVO; -import com.cloud.storage.dao.SnapshotDao; -import com.cloud.storage.dao.VolumeDao; -import com.cloud.storage.s3.S3Manager; -import com.cloud.storage.snapshot.SnapshotManager; -import com.cloud.storage.swift.SwiftManager; -import com.cloud.utils.NumbersUtil; -import com.cloud.utils.db.DB; -import com.cloud.utils.db.Transaction; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.fsm.NoTransitionException; -import com.cloud.vm.UserVmVO; -import com.cloud.vm.VirtualMachine.State; -import com.cloud.vm.dao.UserVmDao; -import com.cloud.vm.snapshot.VMSnapshot; -import com.cloud.vm.snapshot.VMSnapshotVO; -import com.cloud.vm.snapshot.dao.VMSnapshotDao; - -@Component -public class AncientSnapshotStrategy implements SnapshotStrategy { - private static final Logger s_logger = Logger.getLogger(AncientSnapshotStrategy.class); - @Inject - protected VolumeDao _volsDao; - @Inject - protected UserVmDao _vmDao; - @Inject - protected PrimaryDataStoreDao _storagePoolDao; - @Inject - protected ClusterDao _clusterDao; - @Inject - protected SnapshotDao snapshotDao; - @Inject - private ResourceManager _resourceMgr; - @Inject - protected SnapshotDao _snapshotDao; - @Inject - protected SnapshotManager snapshotMgr; - @Inject - protected VolumeManager volumeMgr; - @Inject - private ConfigurationDao _configDao; - @Inject - protected SnapshotStateMachineManager stateMachineManager; - @Inject - private VolumeDao volumeDao; - @Inject - SnapshotDataFactory snapshotfactory; - @Inject - DataStoreManager dataStoreMgr; - @Inject - DataMotionService motionSrv; - @Inject - ObjectInDataStoreManager objInStoreMgr; - @Inject - VMSnapshotDao _vmSnapshotDao; - - - @Override - public boolean canHandle(SnapshotInfo snapshot) { - return true; - } - - static private class CreateSnapshotContext extends AsyncRpcConext { - final VolumeInfo volume; - final SnapshotInfo snapshot; - final AsyncCallFuture future; - public CreateSnapshotContext(AsyncCompletionCallback callback, VolumeInfo volume, - SnapshotInfo snapshot, - AsyncCallFuture future) { - super(callback); - this.volume = volume; - this.snapshot = snapshot; - this.future = future; - } - } - - static private class DeleteSnapshotContext extends AsyncRpcConext { - final SnapshotInfo snapshot; - final AsyncCallFuture future; - public DeleteSnapshotContext(AsyncCompletionCallback callback, SnapshotInfo snapshot, - AsyncCallFuture future) { - super(callback); - this.snapshot = snapshot; - this.future = future; - } - - } - - static private class CopySnapshotContext extends AsyncRpcConext { - final SnapshotInfo srcSnapshot; - final SnapshotInfo destSnapshot; - final AsyncCallFuture future; - public CopySnapshotContext(AsyncCompletionCallback callback, - SnapshotInfo srcSnapshot, - SnapshotInfo destSnapshot, - AsyncCallFuture future) { - super(callback); - this.srcSnapshot = srcSnapshot; - this.destSnapshot = destSnapshot; - this.future = future; - } - - } - - protected Void createSnapshotAsyncCallback(AsyncCallbackDispatcher callback, - CreateSnapshotContext context) { - CreateCmdResult result = callback.getResult(); - SnapshotObject snapshot = (SnapshotObject)context.snapshot; - VolumeInfo volume = context.volume; - AsyncCallFuture future = context.future; - SnapshotResult snapResult = new SnapshotResult(snapshot); - if (result.isFailed()) { - s_logger.debug("create snapshot " + context.snapshot.getName() + " failed: " + result.getResult()); - try { - snapshot.processEvent(Snapshot.Event.OperationFailed); - } catch (NoTransitionException nte) { - s_logger.debug("Failed to update snapshot state due to " + nte.getMessage()); - } - - - snapResult.setResult(result.getResult()); - future.complete(snapResult); - return null; - } - - try { - SnapshotVO preSnapshotVO = this.snapshotMgr.getParentSnapshot(volume, snapshot); - String preSnapshotPath = null; - if (preSnapshotVO != null) { - preSnapshotPath = preSnapshotVO.getPath(); - } - SnapshotVO snapshotVO = this.snapshotDao.findById(snapshot.getId()); - // The snapshot was successfully created - if (preSnapshotPath != null && preSnapshotPath.equals(result.getPath())) { - // empty snapshot - s_logger.debug("CreateSnapshot: this is empty snapshot "); - - snapshotVO.setPath(preSnapshotPath); - snapshotVO.setBackupSnapshotId(preSnapshotVO.getBackupSnapshotId()); - snapshotVO.setSwiftId(preSnapshotVO.getSwiftId()); - snapshotVO.setPrevSnapshotId(preSnapshotVO.getId()); - snapshotVO.setSecHostId(preSnapshotVO.getSecHostId()); - snapshot.processEvent(Snapshot.Event.OperationNotPerformed); - } else { - long preSnapshotId = 0; - - if (preSnapshotVO != null && preSnapshotVO.getBackupSnapshotId() != null) { - preSnapshotId = preSnapshotVO.getId(); - int _deltaSnapshotMax = NumbersUtil.parseInt(_configDao.getValue("snapshot.delta.max"), SnapshotManager.DELTAMAX); - int deltaSnap = _deltaSnapshotMax; - - int i; - for (i = 1; i < deltaSnap; i++) { - String prevBackupUuid = preSnapshotVO.getBackupSnapshotId(); - // previous snapshot doesn't have backup, create a full snapshot - if (prevBackupUuid == null) { - preSnapshotId = 0; - break; - } - long preSSId = preSnapshotVO.getPrevSnapshotId(); - if (preSSId == 0) { - break; - } - preSnapshotVO = _snapshotDao.findByIdIncludingRemoved(preSSId); - } - if (i >= deltaSnap) { - preSnapshotId = 0; - } - } - - //If the volume is moved around, backup a full snapshot to secondary storage - if (volume.getLastPoolId() != null && !volume.getLastPoolId().equals(volume.getPoolId())) { - preSnapshotId = 0; - //TODO: fix this hack - VolumeVO volumeVO = this.volumeDao.findById(volume.getId()); - volumeVO.setLastPoolId(volume.getPoolId()); - this.volumeDao.update(volume.getId(), volumeVO); - } - - snapshot.setPath(result.getPath()); - snapshot.setPrevSnapshotId(preSnapshotId); - - snapshot.processEvent(Snapshot.Event.OperationSucceeded); - snapResult = new SnapshotResult(this.snapshotfactory.getSnapshot(snapshot.getId())); - } - } catch (Exception e) { - s_logger.debug("Failed to create snapshot: ", e); - snapResult.setResult(e.toString()); - try { - snapshot.processEvent(Snapshot.Event.OperationFailed); - } catch (NoTransitionException e1) { - s_logger.debug("Failed to change snapshot state: " + e1.toString()); - } - } - - future.complete(snapResult); - return null; - } - - class SnapshotResult extends CommandResult { - SnapshotInfo snashot; - public SnapshotResult(SnapshotInfo snapshot) { - this.snashot = snapshot; - } - } - - protected SnapshotInfo createSnapshotOnPrimary(VolumeInfo volume, Long snapshotId) { - SnapshotObject snapshot = (SnapshotObject)this.snapshotfactory.getSnapshot(snapshotId); - if (snapshot == null) { - throw new CloudRuntimeException("Can not find snapshot " + snapshotId); - } - - try { - snapshot.processEvent(Snapshot.Event.CreateRequested); - } catch (NoTransitionException nte) { - s_logger.debug("Failed to update snapshot state due to " + nte.getMessage()); - throw new CloudRuntimeException("Failed to update snapshot state due to " + nte.getMessage()); - } - - AsyncCallFuture future = new AsyncCallFuture(); - try { - CreateSnapshotContext context = new CreateSnapshotContext( - null, volume, snapshot, future); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher - .create(this); - caller.setCallback( - caller.getTarget().createSnapshotAsyncCallback(null, null)) - .setContext(context); - PrimaryDataStoreDriver primaryStore = (PrimaryDataStoreDriver)volume.getDataStore().getDriver(); - primaryStore.takeSnapshot(snapshot, caller); - } catch (Exception e) { - s_logger.debug("Failed to take snapshot: " + snapshot.getId(), e); - try { - snapshot.processEvent(Snapshot.Event.OperationFailed); - } catch (NoTransitionException e1) { - s_logger.debug("Failed to change state for event: OperationFailed" , e); - } - throw new CloudRuntimeException("Failed to take snapshot" + snapshot.getId()); - } - - SnapshotResult result; - - try { - result = future.get(); - if (result.isFailed()) { - s_logger.debug("Failed to create snapshot:" + result.getResult()); - throw new CloudRuntimeException(result.getResult()); - } - return result.snashot; - } catch (InterruptedException e) { - s_logger.debug("Failed to create snapshot", e); - throw new CloudRuntimeException("Failed to create snapshot", e); - } catch (ExecutionException e) { - s_logger.debug("Failed to create snapshot", e); - throw new CloudRuntimeException("Failed to create snapshot", e); - } - - } - - private boolean hostSupportSnapsthot(HostVO host) { - if (host.getHypervisorType() != HypervisorType.KVM) { - return true; - } - // Determine host capabilities - String caps = host.getCapabilities(); - - if (caps != null) { - String[] tokens = caps.split(","); - for (String token : tokens) { - if (token.contains("snapshot")) { - return true; - } - } - } - return false; - } - - protected boolean supportedByHypervisor(VolumeInfo volume) { - if (volume.getHypervisorType().equals(HypervisorType.KVM)) { - StoragePool storagePool = (StoragePool)volume.getDataStore(); - ClusterVO cluster = _clusterDao.findById(storagePool.getClusterId()); - List hosts = _resourceMgr.listAllHostsInCluster(cluster.getId()); - if (hosts != null && !hosts.isEmpty()) { - HostVO host = hosts.get(0); - if (!hostSupportSnapsthot(host)) { - throw new CloudRuntimeException("KVM Snapshot is not supported on cluster: " + host.getId()); - } - } - } - - // if volume is attached to a vm in destroyed or expunging state; disallow - if (volume.getInstanceId() != null) { - UserVmVO userVm = _vmDao.findById(volume.getInstanceId()); - if (userVm != null) { - if (userVm.getState().equals(State.Destroyed) || userVm.getState().equals(State.Expunging)) { - throw new CloudRuntimeException("Creating snapshot failed due to volume:" + volume.getId() + " is associated with vm:" + userVm.getInstanceName() + " is in " - + userVm.getState().toString() + " state"); - } - - if(userVm.getHypervisorType() == HypervisorType.VMware || userVm.getHypervisorType() == HypervisorType.KVM) { - List activeSnapshots = _snapshotDao.listByInstanceId(volume.getInstanceId(), Snapshot.State.Creating, Snapshot.State.CreatedOnPrimary, Snapshot.State.BackingUp); - if(activeSnapshots.size() > 1) - throw new CloudRuntimeException("There is other active snapshot tasks on the instance to which the volume is attached, please try again later"); - } - - List activeVMSnapshots = _vmSnapshotDao.listByInstanceId(userVm.getId(), - VMSnapshot.State.Creating, VMSnapshot.State.Reverting, VMSnapshot.State.Expunging); - if (activeVMSnapshots.size() > 0) { - throw new CloudRuntimeException( - "There is other active vm snapshot tasks on the instance to which the volume is attached, please try again later"); - } - } - } - - return true; - } - - @Override - public SnapshotInfo takeSnapshot(VolumeInfo volume, Long snapshotId) { - - supportedByHypervisor(volume); - - SnapshotInfo snapshot = createSnapshotOnPrimary(volume, snapshotId); - return snapshot; - } - - @Override - public SnapshotInfo backupSnapshot(SnapshotInfo snapshot) { - SnapshotObject snapObj = (SnapshotObject)snapshot; - AsyncCallFuture future = new AsyncCallFuture(); - SnapshotResult result = new SnapshotResult(snapshot); - try { - - snapObj.processEvent(Snapshot.Event.BackupToSecondary); - - ZoneScope scope = new ZoneScope(snapshot.getDataCenterId()); - List stores = this.dataStoreMgr.getImageStores(scope); - if (stores.size() != 1) { - throw new CloudRuntimeException("find out more than one image stores"); - } - - DataStore imageStore = stores.get(0); - SnapshotInfo snapshotOnImageStore = (SnapshotInfo)imageStore.create(snapshot); - - snapshotOnImageStore.processEvent(Event.CreateOnlyRequested); - CopySnapshotContext context = new CopySnapshotContext(null, snapshot, - snapshotOnImageStore, future); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher - .create(this); - caller.setCallback( - caller.getTarget().copySnapshotAsyncCallback(null, null)) - .setContext(context); - this.motionSrv.copyAsync(snapshot, snapshotOnImageStore, caller); - } catch (Exception e) { - s_logger.debug("Failed to copy snapshot", e); - result.setResult("Failed to copy snapshot:" +e.toString()); - try { - snapObj.processEvent(Snapshot.Event.OperationFailed); - } catch (NoTransitionException e1) { - s_logger.debug("Failed to change state: " + e1.toString()); - } - future.complete(result); - } - - try { - SnapshotResult res = future.get(); - SnapshotInfo destSnapshot = res.snashot; - return destSnapshot; - } catch (InterruptedException e) { - s_logger.debug("failed copy snapshot", e); - throw new CloudRuntimeException("Failed to copy snapshot" , e); - } catch (ExecutionException e) { - s_logger.debug("Failed to copy snapshot", e); - throw new CloudRuntimeException("Failed to copy snapshot" , e); - } - - } - - protected Void copySnapshotAsyncCallback(AsyncCallbackDispatcher callback, - CopySnapshotContext context) { - CopyCommandResult result = callback.getResult(); - SnapshotInfo destSnapshot = context.destSnapshot; - SnapshotObject srcSnapshot = (SnapshotObject)context.srcSnapshot; - AsyncCallFuture future = context.future; - SnapshotResult snapResult = new SnapshotResult(destSnapshot); - if (result.isFailed()) { - snapResult.setResult(result.getResult()); - future.complete(snapResult); - return null; - } - - try { - BackupSnapshotAnswer answer = (BackupSnapshotAnswer)result.getAnswer(); - - DataObjectInStore dataInStore = objInStoreMgr.findObject(destSnapshot, destSnapshot.getDataStore()); - dataInStore.setInstallPath(answer.getBackupSnapshotName()); - objInStoreMgr.update(destSnapshot, Event.OperationSuccessed); - - srcSnapshot.processEvent(Snapshot.Event.OperationSucceeded); - snapResult = new SnapshotResult(this.snapshotfactory.getSnapshot(destSnapshot.getId())); - future.complete(snapResult); - } catch (Exception e) { - s_logger.debug("Failed to update snapshot state", e); - snapResult.setResult(e.toString()); - future.complete(snapResult); - } - return null; - } - - @DB - protected boolean destroySnapshotBackUp(SnapshotVO snapshot) { - DataStore store = objInStoreMgr.findStore(snapshot.getUuid(), DataObjectType.SNAPSHOT, DataStoreRole.Image); - if (store == null) { - s_logger.debug("Can't find snapshot" + snapshot.getId() + " backed up into image store"); - return false; - } - - try { - SnapshotInfo snapshotInfo = this.snapshotfactory.getSnapshot(snapshot.getId(), store); - snapshotInfo.processEvent(ObjectInDataStoreStateMachine.Event.DestroyRequested); - - AsyncCallFuture future = new AsyncCallFuture(); - DeleteSnapshotContext context = new DeleteSnapshotContext(null, - snapshotInfo, future); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher - .create(this); - caller.setCallback( - caller.getTarget().deleteSnapshotCallback(null, null)) - .setContext(context); - - store.getDriver().deleteAsync(snapshotInfo, caller); - - SnapshotResult result = future.get(); - if (result.isFailed()) { - s_logger.debug("Failed to delete snapsoht: " + result.getResult()); - } - return result.isSuccess(); - } catch (Exception e) { - s_logger.debug("Failed to delete snapshot", e); - return false; - } - } - - protected Void deleteSnapshotCallback(AsyncCallbackDispatcher callback, - DeleteSnapshotContext context) { - CommandResult result = callback.getResult(); - AsyncCallFuture future = context.future; - SnapshotInfo snapshot = context.snapshot; - if (result.isFailed()) { - s_logger.debug("delete snapshot failed" + result.getResult()); - snapshot.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed); - SnapshotResult res = new SnapshotResult(context.snapshot); - future.complete(res); - return null; - } - snapshot.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed); - SnapshotResult res = new SnapshotResult(context.snapshot); - future.complete(res); - return null; - } - - @Override - public boolean deleteSnapshot(SnapshotInfo snapInfo) { - Long snapshotId = snapInfo.getId(); - SnapshotObject snapshot = (SnapshotObject)snapInfo; - - if (Snapshot.State.Error.equals(snapshot.getState())) { - _snapshotDao.remove(snapshotId); - return true; - } - - if (!Snapshot.State.BackedUp.equals(snapshot.getState())) { - throw new InvalidParameterValueException("Can't delete snapshotshot " + snapshotId + " due to it is not in BackedUp Status"); - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Calling deleteSnapshot for snapshotId: " + snapshotId); - } - SnapshotVO lastSnapshot = null; - if (snapshot.getBackupSnapshotId() != null) { - List snaps = _snapshotDao.listByBackupUuid(snapshot.getVolumeId(), snapshot.getBackupSnapshotId()); - if (snaps != null && snaps.size() > 1) { - snapshot.setBackupSnapshotId(null); - SnapshotVO snapshotVO = this._snapshotDao.findById(snapshotId); - _snapshotDao.update(snapshot.getId(), snapshotVO); - } - } - - _snapshotDao.remove(snapshotId); - - long lastId = snapshotId; - boolean destroy = false; - while (true) { - lastSnapshot = _snapshotDao.findNextSnapshot(lastId); - if (lastSnapshot == null) { - // if all snapshots after this snapshot in this chain are removed, remove those snapshots. - destroy = true; - break; - } - if (lastSnapshot.getRemoved() == null) { - // if there is one child not removed, then can not remove back up snapshot. - break; - } - lastId = lastSnapshot.getId(); - } - if (destroy) { - lastSnapshot = _snapshotDao.findByIdIncludingRemoved(lastId); - while (lastSnapshot.getRemoved() != null) { - String BackupSnapshotId = lastSnapshot.getBackupSnapshotId(); - if (BackupSnapshotId != null) { - List snaps = _snapshotDao.listByBackupUuid(lastSnapshot.getVolumeId(), BackupSnapshotId); - if (snaps != null && snaps.size() > 1) { - lastSnapshot.setBackupSnapshotId(null); - _snapshotDao.update(lastSnapshot.getId(), lastSnapshot); - } else { - if (destroySnapshotBackUp(lastSnapshot)) { - - } else { - s_logger.debug("Destroying snapshot backup failed " + lastSnapshot); - break; - } - } - } - lastId = lastSnapshot.getPrevSnapshotId(); - if (lastId == 0) { - break; - } - lastSnapshot = _snapshotDao.findByIdIncludingRemoved(lastId); - } - } - return true; - - } - - @Override - public boolean revertSnapshot(SnapshotInfo snapshot) { - // TODO Auto-generated method stub - return false; - } - -} diff --git a/engine/storage/snapshot/test/src/SnapshotDataFactoryTest.java b/engine/storage/snapshot/test/src/SnapshotDataFactoryTest.java index e722ab55c70..317521de734 100644 --- a/engine/storage/snapshot/test/src/SnapshotDataFactoryTest.java +++ b/engine/storage/snapshot/test/src/SnapshotDataFactoryTest.java @@ -18,33 +18,24 @@ */ package src; -import javax.inject.Inject; - -import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import com.cloud.utils.component.ComponentContext; - import junit.framework.TestCase; //@RunWith(SpringJUnit4ClassRunner.class) //@ContextConfiguration(locations = "classpath:/SnapshotManagerTestContext.xml") public class SnapshotDataFactoryTest extends TestCase { - //@Inject SnapshotDataFactory snapshotFactory; - + // @Inject SnapshotDataFactory snapshotFactory; + @Before public void setup() throws Exception { - //ComponentContext.initComponentsLifeCycle(); - + // ComponentContext.initComponentsLifeCycle(); + } - + @Test public void testGestSnapshot() { - //snapshotFactory.getSnapshot(snapshotId); + // snapshotFactory.getSnapshot(snapshotId); } - + } diff --git a/engine/storage/src/org/apache/cloudstack/storage/BaseType.java b/engine/storage/src/org/apache/cloudstack/storage/BaseType.java index a5b45e17f03..539792628c1 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/BaseType.java +++ b/engine/storage/src/org/apache/cloudstack/storage/BaseType.java @@ -19,6 +19,7 @@ package org.apache.cloudstack.storage; public abstract class BaseType { + @Override public boolean equals(Object that) { if (this == that) { return true; diff --git a/engine/storage/src/org/apache/cloudstack/storage/HypervisorHostEndPoint.java b/engine/storage/src/org/apache/cloudstack/storage/HypervisorHostEndPoint.java deleted file mode 100644 index 6c49b1a0e9e..00000000000 --- a/engine/storage/src/org/apache/cloudstack/storage/HypervisorHostEndPoint.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage; - -import javax.inject.Inject; - -import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; -import org.apache.cloudstack.framework.async.AsyncCompletionCallback; -import org.apache.log4j.Logger; - -import com.cloud.agent.AgentManager; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.Command; -import com.cloud.exception.AgentUnavailableException; -import com.cloud.exception.OperationTimedoutException; -import com.cloud.utils.component.ComponentContext; - -public class HypervisorHostEndPoint implements EndPoint { - private static final Logger s_logger = Logger.getLogger(HypervisorHostEndPoint.class); - private long hostId; - private String hostAddress; - @Inject - AgentManager agentMgr; - @Inject - HostEndpointRpcServer rpcServer; - - protected HypervisorHostEndPoint() { - - } - - private void configure(long hostId, String hostAddress) { - this.hostId = hostId; - this.hostAddress = hostAddress; - } - - public static HypervisorHostEndPoint getHypervisorHostEndPoint(long hostId, String hostAddress) { - HypervisorHostEndPoint ep = ComponentContext.inject(HypervisorHostEndPoint.class); - ep.configure(hostId, hostAddress); - return ep; - } - - public String getHostAddr() { - return this.hostAddress; - } - - public long getId() { - return this.hostId; - } - - @Override - public Answer sendMessage(Command cmd) { - return rpcServer.sendCommand(this, cmd); - } - - @Override - public void sendMessageAsync(Command cmd, AsyncCompletionCallback callback) { - rpcServer.sendCommandAsync(this, cmd, callback); - } -} diff --git a/engine/storage/src/org/apache/cloudstack/storage/HypervisorHostEndPointRpcServer.java b/engine/storage/src/org/apache/cloudstack/storage/HypervisorHostEndPointRpcServer.java deleted file mode 100644 index 060b490e6a8..00000000000 --- a/engine/storage/src/org/apache/cloudstack/storage/HypervisorHostEndPointRpcServer.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage; - -import javax.annotation.PostConstruct; -import javax.inject.Inject; - -import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; -import org.apache.cloudstack.framework.async.AsyncCompletionCallback; -import org.apache.cloudstack.framework.async.AsyncRpcConext; -import org.apache.cloudstack.framework.rpc.RpcCallbackListener; -import org.apache.cloudstack.framework.rpc.RpcException; -import org.apache.cloudstack.framework.rpc.RpcProvider; -import org.apache.cloudstack.framework.rpc.RpcServiceDispatcher; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.Command; -import com.cloud.utils.exception.CloudRuntimeException; - -@Component -public class HypervisorHostEndPointRpcServer implements HostEndpointRpcServer { - private static final Logger s_logger = Logger.getLogger(HypervisorHostEndPointRpcServer.class); - - @Inject - private RpcProvider rpcProvider; - - public HypervisorHostEndPointRpcServer() { - } - - public HypervisorHostEndPointRpcServer(RpcProvider rpcProvider) { - this.rpcProvider = rpcProvider; - rpcProvider.registerRpcServiceEndpoint(RpcServiceDispatcher.getDispatcher(this)); - } - - @PostConstruct - public void Initialize() { - rpcProvider.registerRpcServiceEndpoint(RpcServiceDispatcher.getDispatcher(this)); - } - - @Override - public void sendCommandAsync(HypervisorHostEndPoint host, final Command command, final AsyncCompletionCallback callback) { - rpcProvider.newCall(host.getHostAddr()).addCallbackListener(new RpcCallbackListener() { - @Override - public void onSuccess(Answer result) { - callback.complete(result); - } - - @Override - public void onFailure(RpcException e) { - Answer answer = new Answer(command, false, e.toString()); - callback.complete(answer); - } - }).apply(); - } - - private class SendCommandContext extends AsyncRpcConext { - private T answer; - - public SendCommandContext(AsyncCompletionCallback callback) { - super(callback); - } - - public void setAnswer(T answer) { - this.answer = answer; - } - - public T getAnswer() { - return this.answer; - } - - } - - @Override - public Answer sendCommand(HypervisorHostEndPoint host, Command command) { - SendCommandContext context = new SendCommandContext(null); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); - caller.setCallback(caller.getTarget().sendCommandCallback(null, null)) - .setContext(context); - - this.sendCommandAsync(host, command, caller); - - synchronized (context) { - try { - context.wait(); - } catch (InterruptedException e) { - s_logger.debug(e.toString()); - throw new CloudRuntimeException("wait on context is interrupted", e); - } - } - - return context.getAnswer(); - } - - protected Object sendCommandCallback(AsyncCallbackDispatcher callback, SendCommandContext context) { - context.setAnswer((Answer)callback.getResult()); - synchronized(context) { - context.notify(); - } - return null; - } -} diff --git a/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java b/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java new file mode 100644 index 00000000000..18fcd7178d2 --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java @@ -0,0 +1,101 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.storage.command.CopyCommand; +import org.apache.cloudstack.storage.command.DownloadCommand; +import org.apache.cloudstack.storage.resource.LocalNfsSecondaryStorageResource; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.resource.ServerResource; +import com.cloud.utils.net.NetUtils; + +public class LocalHostEndpoint implements EndPoint { + private ScheduledExecutorService executor; + protected ServerResource resource; + + public LocalHostEndpoint() { + resource = new LocalNfsSecondaryStorageResource(); + executor = Executors.newScheduledThreadPool(10); + } + + @Override + public long getId() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getHostAddr() { + return "127.0.0.0"; + } + + @Override + public String getPublicAddr() { + String hostIp = NetUtils.getDefaultHostIp(); + if (hostIp != null) + return hostIp; + else + return "127.0.0.0"; + } + + @Override + public Answer sendMessage(Command cmd) { + if ((cmd instanceof CopyCommand) || (cmd instanceof DownloadCommand)) { + return resource.executeRequest(cmd); + } + // TODO Auto-generated method stub + return new Answer(cmd, false, "unsupported command:" + cmd.toString()); + } + + private class CmdRunner implements Runnable { + final Command cmd; + final AsyncCompletionCallback callback; + + public CmdRunner(Command cmd, AsyncCompletionCallback callback) { + this.cmd = cmd; + this.callback = callback; + } + + @Override + public void run() { + Answer answer = sendMessage(cmd); + callback.complete(answer); + } + } + + @Override + public void sendMessageAsync(Command cmd, AsyncCompletionCallback callback) { + executor.schedule(new CmdRunner(cmd, callback), 10, TimeUnit.SECONDS); + } + + public ServerResource getResource() { + return resource; + } + + public void setResource(ServerResource resource) { + this.resource = resource; + } + +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/RemoteHostEndPoint.java b/engine/storage/src/org/apache/cloudstack/storage/RemoteHostEndPoint.java new file mode 100644 index 00000000000..cd64ab2457c --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/RemoteHostEndPoint.java @@ -0,0 +1,178 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.log4j.Logger; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.Listener; +import com.cloud.agent.api.AgentControlAnswer; +import com.cloud.agent.api.AgentControlCommand; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.manager.Commands; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.ConnectionException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.host.Host; +import com.cloud.host.Status; +import com.cloud.hypervisor.HypervisorGuruManager; +import com.cloud.utils.component.ComponentContext; +import com.cloud.utils.exception.CloudRuntimeException; + +public class RemoteHostEndPoint implements EndPoint { + private static final Logger s_logger = Logger.getLogger(RemoteHostEndPoint.class); + private long hostId; + private String hostAddress; + private String publicAddress; + @Inject + AgentManager agentMgr; + @Inject + protected HypervisorGuruManager _hvGuruMgr; + private ScheduledExecutorService executor; + + public RemoteHostEndPoint() { + executor = Executors.newScheduledThreadPool(10); + } + + private void configure(long hostId, String hostAddress, String publicAddress) { + this.hostId = hostId; + this.hostAddress = hostAddress; + this.publicAddress = publicAddress; + } + + public static RemoteHostEndPoint getHypervisorHostEndPoint(long hostId, String hostAddress, String publicAddress) { + RemoteHostEndPoint ep = ComponentContext.inject(RemoteHostEndPoint.class); + ep.configure(hostId, hostAddress, publicAddress); + return ep; + } + + @Override + public String getHostAddr() { + return this.hostAddress; + } + + @Override + public String getPublicAddr() { + return this.publicAddress; + } + + @Override + public long getId() { + return this.hostId; + } + + @Override + public Answer sendMessage(Command cmd) { + String errMsg = null; + try { + long newHostId = _hvGuruMgr.getGuruProcessedCommandTargetHost(hostId, cmd); + return agentMgr.send(newHostId, cmd); + } catch (AgentUnavailableException e) { + errMsg = e.toString(); + s_logger.debug("Failed to send command, due to Agent:" + getId() + ", " + e.toString()); + } catch (OperationTimedoutException e) { + errMsg = e.toString(); + s_logger.debug("Failed to send command, due to Agent:" + getId() + ", " + e.toString()); + } + throw new CloudRuntimeException("Failed to send command, due to Agent:" + getId() + ", " + errMsg); + } + + private class CmdRunner implements Listener, Runnable { + final AsyncCompletionCallback callback; + Answer answer; + + public CmdRunner(AsyncCompletionCallback callback) { + this.callback = callback; + } + + @Override + public boolean processAnswers(long agentId, long seq, Answer[] answers) { + this.answer = answers[0]; + executor.schedule(this, 10, TimeUnit.SECONDS); + return true; + } + + @Override + public boolean processCommands(long agentId, long seq, Command[] commands) { + // TODO Auto-generated method stub + return false; + } + + @Override + public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { + // TODO Auto-generated method stub + + } + + @Override + public boolean processDisconnect(long agentId, Status state) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isRecurring() { + // TODO Auto-generated method stub + return false; + } + + @Override + public int getTimeout() { + // TODO Auto-generated method stub + return -1; + } + + @Override + public boolean processTimeout(long agentId, long seq) { + // TODO Auto-generated method stub + return false; + } + + @Override + public void run() { + callback.complete(answer); + } + } + + @Override + public void sendMessageAsync(Command cmd, AsyncCompletionCallback callback) { + try { + long newHostId = _hvGuruMgr.getGuruProcessedCommandTargetHost(this.hostId, cmd); + agentMgr.send(newHostId, new Commands(cmd), new CmdRunner(callback)); + } catch (AgentUnavailableException e) { + throw new CloudRuntimeException("Unable to send message", e); + } + } +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java index 53267013412..e16703ecf2f 100755 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java @@ -53,134 +53,154 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; public abstract class AbstractStoragePoolAllocator extends AdapterBase implements StoragePoolAllocator { - private static final Logger s_logger = Logger.getLogger(AbstractStoragePoolAllocator.class); - @Inject StorageManager storageMgr; - protected @Inject PrimaryDataStoreDao _storagePoolDao; - @Inject VolumeDao _volumeDao; - @Inject ConfigurationDao _configDao; - @Inject ClusterDao _clusterDao; - protected @Inject DataStoreManager dataStoreMgr; - protected BigDecimal _storageOverprovisioningFactor = new BigDecimal(1); + private static final Logger s_logger = Logger.getLogger(AbstractStoragePoolAllocator.class); + @Inject + StorageManager storageMgr; + protected @Inject + PrimaryDataStoreDao _storagePoolDao; + @Inject + VolumeDao _volumeDao; + @Inject + ConfigurationDao _configDao; + @Inject + ClusterDao _clusterDao; + protected @Inject + DataStoreManager dataStoreMgr; + protected BigDecimal _storageOverprovisioningFactor = new BigDecimal(1); long _extraBytesPerVolume = 0; Random _rand; boolean _dontMatter; protected String _allocationAlgorithm = "random"; @Inject DiskOfferingDao _diskOfferingDao; - + @Override public boolean configure(String name, Map params) throws ConfigurationException { super.configure(name, params); - + Map configs = _configDao.getConfiguration(null, params); - + String globalStorageOverprovisioningFactor = configs.get("storage.overprovisioning.factor"); - _storageOverprovisioningFactor = new BigDecimal(NumbersUtil.parseFloat(globalStorageOverprovisioningFactor, 2.0f)); - + _storageOverprovisioningFactor = new BigDecimal(NumbersUtil.parseFloat(globalStorageOverprovisioningFactor, + 2.0f)); + _extraBytesPerVolume = 0; - + _rand = new Random(System.currentTimeMillis()); _dontMatter = Boolean.parseBoolean(configs.get("storage.overwrite.provisioning")); String allocationAlgorithm = configs.get("vm.allocation.algorithm"); if (allocationAlgorithm != null) { - _allocationAlgorithm = allocationAlgorithm; + _allocationAlgorithm = allocationAlgorithm; } return true; } - - protected abstract List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo); - + + protected abstract List select(DiskProfile dskCh, + VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, + int returnUpTo); + @Override - public - List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { - List pools = select(dskCh, vmProfile, plan, avoid, returnUpTo); - return reOrder(pools, vmProfile, plan); + public List allocateToPool(DiskProfile dskCh, + VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, + int returnUpTo) { + List pools = select(dskCh, vmProfile, plan, avoid, returnUpTo); + return reOrder(pools, vmProfile, plan); } - - protected List reorderPoolsByNumberOfVolumes(DeploymentPlan plan, List pools, Account account) { - if(account == null){ + + protected List reorderPoolsByNumberOfVolumes(DeploymentPlan plan, List pools, + Account account) { + if (account == null) { return pools; } long dcId = plan.getDataCenterId(); Long podId = plan.getPodId(); Long clusterId = plan.getClusterId(); - - List poolIdsByVolCount = _volumeDao.listPoolIdsByVolumeCount(dcId, podId, clusterId, account.getAccountId()); + + List poolIdsByVolCount = _volumeDao.listPoolIdsByVolumeCount(dcId, podId, clusterId, + account.getAccountId()); if (s_logger.isDebugEnabled()) { - s_logger.debug("List of pools in ascending order of number of volumes for account id: "+ account.getAccountId() + " is: "+ poolIdsByVolCount); + s_logger.debug("List of pools in ascending order of number of volumes for account id: " + + account.getAccountId() + " is: " + poolIdsByVolCount); } - - //now filter the given list of Pools by this ordered list - Map poolMap = new HashMap(); + + // now filter the given list of Pools by this ordered list + Map poolMap = new HashMap(); for (StoragePool pool : pools) { poolMap.put(pool.getId(), pool); } List matchingPoolIds = new ArrayList(poolMap.keySet()); - + poolIdsByVolCount.retainAll(matchingPoolIds); - + List reorderedPools = new ArrayList(); - for(Long id: poolIdsByVolCount){ + for (Long id : poolIdsByVolCount) { reorderedPools.add(poolMap.get(id)); } - + return reorderedPools; } - - protected List reOrder(List pools, - VirtualMachineProfile vmProfile, - DeploymentPlan plan) { - Account account = null; - if(vmProfile.getVirtualMachine() != null){ - account = vmProfile.getOwner(); - } - - if(_allocationAlgorithm.equals("random") || _allocationAlgorithm.equals("userconcentratedpod_random") || (account == null)) { - // Shuffle this so that we don't check the pools in the same order. - Collections.shuffle(pools); - }else if(_allocationAlgorithm.equals("userdispersing")){ - pools = reorderPoolsByNumberOfVolumes(plan, pools, account); - } - return pools; - } - - protected boolean filter(ExcludeList avoid, StoragePool pool, DiskProfile dskCh, - DeploymentPlan plan) { - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Checking if storage pool is suitable, name: " + pool.getName()+ " ,poolId: "+ pool.getId()); + + protected List reOrder(List pools, + VirtualMachineProfile vmProfile, DeploymentPlan plan) { + Account account = null; + if (vmProfile.getVirtualMachine() != null) { + account = vmProfile.getOwner(); } - if (avoid.shouldAvoid(pool)) { - if (s_logger.isDebugEnabled()) { + + if (_allocationAlgorithm.equals("random") || _allocationAlgorithm.equals("userconcentratedpod_random") + || (account == null)) { + // Shuffle this so that we don't check the pools in the same order. + Collections.shuffle(pools); + } else if (_allocationAlgorithm.equals("userdispersing")) { + pools = reorderPoolsByNumberOfVolumes(plan, pools, account); + } + return pools; + } + + protected boolean filter(ExcludeList avoid, StoragePool pool, DiskProfile dskCh, DeploymentPlan plan) { + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Checking if storage pool is suitable, name: " + pool.getName() + " ,poolId: " + + pool.getId()); + } + if (avoid.shouldAvoid(pool)) { + if (s_logger.isDebugEnabled()) { s_logger.debug("StoragePool is in avoid set, skipping this pool"); - } - return false; - } - - if(dskCh.getType().equals(Type.ROOT) && pool.getPoolType().equals(StoragePoolType.Iscsi)){ - if (s_logger.isDebugEnabled()) { - s_logger.debug("Disk needed for ROOT volume, but StoragePoolType is Iscsi, skipping this and trying other available pools"); - } + } return false; } - - - Long clusterId = pool.getClusterId(); - ClusterVO cluster = _clusterDao.findById(clusterId); - if (!(cluster.getHypervisorType() == dskCh.getHypervisorType())) { - if (s_logger.isDebugEnabled()) { + + if (dskCh.getType().equals(Type.ROOT) && pool.getPoolType().equals(StoragePoolType.Iscsi)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Disk needed for ROOT volume, but StoragePoolType is Iscsi, skipping this and trying other available pools"); + } + return false; + } + + + DiskOfferingVO diskOffering = _diskOfferingDao.findById(dskCh.getDiskOfferingId()); + if (diskOffering.getSystemUse() && pool.getPoolType() == StoragePoolType.RBD) { + s_logger.debug("Skipping RBD pool " + pool.getName() + + " as a suitable pool. RBD is not supported for System VM's"); + return false; + } + + Long clusterId = pool.getClusterId(); + ClusterVO cluster = _clusterDao.findById(clusterId); + if (!(cluster.getHypervisorType() == dskCh.getHypervisorType())) { + if (s_logger.isDebugEnabled()) { s_logger.debug("StoragePool's Cluster does not have required hypervisorType, skipping this pool"); } - return false; - } + return false; + } - // check capacity - Volume volume = _volumeDao.findById(dskCh.getVolumeId()); + // check capacity + Volume volume = _volumeDao.findById(dskCh.getVolumeId()); List requestVolumes = new ArrayList(); requestVolumes.add(volume); return storageMgr.storagePoolHasEnoughSpace(requestVolumes, pool); - } + } } diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/ClusterScopeStoragePoolAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/ClusterScopeStoragePoolAllocator.java index 5b1f8cd699a..0933adcd3bc 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/ClusterScopeStoragePoolAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/ClusterScopeStoragePoolAllocator.java @@ -40,7 +40,7 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; @Component -@Local(value=StoragePoolAllocator.class) +@Local(value = StoragePoolAllocator.class) public class ClusterScopeStoragePoolAllocator extends AbstractStoragePoolAllocator { private static final Logger s_logger = Logger.getLogger(ClusterScopeStoragePoolAllocator.class); protected String _allocationAlgorithm = "random"; @@ -49,19 +49,21 @@ public class ClusterScopeStoragePoolAllocator extends AbstractStoragePoolAllocat DiskOfferingDao _diskOfferingDao; @Override - protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, + DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { s_logger.debug("ClusterScopeStoragePoolAllocator looking for storage pool"); - List suitablePools = new ArrayList(); + List suitablePools = new ArrayList(); - long dcId = plan.getDataCenterId(); - Long podId = plan.getPodId(); - Long clusterId = plan.getClusterId(); + long dcId = plan.getDataCenterId(); + Long podId = plan.getPodId(); + Long clusterId = plan.getClusterId(); - if(dskCh.getTags() != null && dskCh.getTags().length != 0){ - s_logger.debug("Looking for pools in dc: " + dcId + " pod:" + podId + " cluster:" + clusterId + " having tags:" + Arrays.toString(dskCh.getTags())); - }else{ - s_logger.debug("Looking for pools in dc: " + dcId + " pod:" + podId + " cluster:" + clusterId); + if (dskCh.getTags() != null && dskCh.getTags().length != 0) { + s_logger.debug("Looking for pools in dc: " + dcId + " pod:" + podId + " cluster:" + clusterId + + " having tags:" + Arrays.toString(dskCh.getTags())); + } else { + s_logger.debug("Looking for pools in dc: " + dcId + " pod:" + podId + " cluster:" + clusterId); } List pools = _storagePoolDao.findPoolsByTags(dcId, podId, clusterId, dskCh.getTags()); @@ -75,30 +77,31 @@ public class ClusterScopeStoragePoolAllocator extends AbstractStoragePoolAllocat if (pools.size() == 0) { if (s_logger.isDebugEnabled()) { - String storageType = dskCh.useLocalStorage() ? ServiceOffering.StorageType.local.toString() : ServiceOffering.StorageType.shared.toString(); + String storageType = dskCh.useLocalStorage() ? ServiceOffering.StorageType.local.toString() + : ServiceOffering.StorageType.shared.toString(); s_logger.debug("No storage pools available for " + storageType + " volume allocation, returning"); } return suitablePools; } - for (StoragePoolVO pool: pools) { - if(suitablePools.size() == returnUpTo){ - break; - } - StoragePool pol = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(pool.getId()); - if (filter(avoid, pol, dskCh, plan)) { - suitablePools.add(pol); + for (StoragePoolVO pool : pools) { + if (suitablePools.size() == returnUpTo) { + break; + } + StoragePool pol = (StoragePool) this.dataStoreMgr.getPrimaryDataStore(pool.getId()); + if (filter(avoid, pol, dskCh, plan)) { + suitablePools.add(pol); } else { avoid.addPool(pool.getId()); - } + } } if (s_logger.isDebugEnabled()) { - s_logger.debug("FirstFitStoragePoolAllocator returning "+suitablePools.size() +" suitable storage pools"); + s_logger.debug("FirstFitStoragePoolAllocator returning " + suitablePools.size() + " suitable storage pools"); } return suitablePools; - } + } @Override public boolean configure(String name, Map params) throws ConfigurationException { diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/GarbageCollectingStoragePoolAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/GarbageCollectingStoragePoolAllocator.java index 02032ee4fbd..979ea73cd23 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/GarbageCollectingStoragePoolAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/GarbageCollectingStoragePoolAllocator.java @@ -36,18 +36,21 @@ import com.cloud.vm.DiskProfile; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; -@Local(value=StoragePoolAllocator.class) +@Local(value = StoragePoolAllocator.class) public class GarbageCollectingStoragePoolAllocator extends AbstractStoragePoolAllocator { private static final Logger s_logger = Logger.getLogger(GarbageCollectingStoragePoolAllocator.class); StoragePoolAllocator _firstFitStoragePoolAllocator; StoragePoolAllocator _localStoragePoolAllocator; - @Inject StorageManager storageMgr; - @Inject ConfigurationDao _configDao; + @Inject + StorageManager storageMgr; + @Inject + ConfigurationDao _configDao; boolean _storagePoolCleanupEnabled; @Override - public List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + public List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, + DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { s_logger.debug("GarbageCollectingStoragePoolAllocator looking for storage pool"); if (!_storagePoolCleanupEnabled) { s_logger.debug("Storage pool cleanup is not enabled, so GarbageCollectingStoragePoolAllocator is being skipped."); @@ -65,7 +68,8 @@ public class GarbageCollectingStoragePoolAllocator extends AbstractStoragePoolAl } // Try to find a storage pool after cleanup - ExcludeList myAvoids = new ExcludeList(avoid.getDataCentersToAvoid(), avoid.getPodsToAvoid(), avoid.getClustersToAvoid(), avoid.getHostsToAvoid(), avoid.getPoolsToAvoid()); + ExcludeList myAvoids = new ExcludeList(avoid.getDataCentersToAvoid(), avoid.getPodsToAvoid(), + avoid.getClustersToAvoid(), avoid.getHostsToAvoid(), avoid.getPoolsToAvoid()); return allocator.allocateToPool(dskCh, vmProfile, plan, myAvoids, returnUpTo); } @@ -80,7 +84,8 @@ public class GarbageCollectingStoragePoolAllocator extends AbstractStoragePoolAl _localStoragePoolAllocator.configure("GCLocalStoragePoolAllocator", params); String storagePoolCleanupEnabled = _configDao.getValue("storage.pool.cleanup.enabled"); - _storagePoolCleanupEnabled = (storagePoolCleanupEnabled == null) ? true : Boolean.parseBoolean(storagePoolCleanupEnabled); + _storagePoolCleanupEnabled = (storagePoolCleanupEnabled == null) ? true : Boolean + .parseBoolean(storagePoolCleanupEnabled); return true; } diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java index 632ba439cb0..ef9e84eee15 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java @@ -65,7 +65,8 @@ public class LocalStoragePoolAllocator extends AbstractStoragePoolAllocator { ConfigurationDao _configDao; @Override - protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, + DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { List suitablePools = new ArrayList(); @@ -78,13 +79,13 @@ public class LocalStoragePoolAllocator extends AbstractStoragePoolAllocator { // data disk and host identified from deploying vm (attach volume case) if (dskCh.getType() == Volume.Type.DATADISK && plan.getHostId() != null) { List hostPools = _poolHostDao.listByHostId(plan.getHostId()); - for (StoragePoolHostVO hostPool: hostPools) { + for (StoragePoolHostVO hostPool : hostPools) { StoragePoolVO pool = _storagePoolDao.findById(hostPool.getPoolId()); if (pool != null && pool.isLocal()) { - StoragePool pol = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(pool.getId()); - if (filter(avoid, pol, dskCh, plan)) { - s_logger.debug("Found suitable local storage pool " + pool.getId() + ", adding to list"); - suitablePools.add(pol); + StoragePool pol = (StoragePool) this.dataStoreMgr.getPrimaryDataStore(pool.getId()); + if (filter(avoid, pol, dskCh, plan)) { + s_logger.debug("Found suitable local storage pool " + pool.getId() + ", adding to list"); + suitablePools.add(pol); } else { avoid.addPool(pool.getId()); } @@ -95,18 +96,19 @@ public class LocalStoragePoolAllocator extends AbstractStoragePoolAllocator { } } } else { - List availablePools = _storagePoolDao.findLocalStoragePoolsByTags(plan.getDataCenterId(), plan.getPodId(), plan.getClusterId(), dskCh.getTags()); - for (StoragePoolVO pool : availablePools) { - if (suitablePools.size() == returnUpTo) { - break; - } - StoragePool pol = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(pool.getId()); - if (filter(avoid, pol, dskCh, plan)) { - suitablePools.add(pol); + List availablePools = _storagePoolDao.findLocalStoragePoolsByTags(plan.getDataCenterId(), + plan.getPodId(), plan.getClusterId(), dskCh.getTags()); + for (StoragePoolVO pool : availablePools) { + if (suitablePools.size() == returnUpTo) { + break; + } + StoragePool pol = (StoragePool) this.dataStoreMgr.getPrimaryDataStore(pool.getId()); + if (filter(avoid, pol, dskCh, plan)) { + suitablePools.add(pol); } else { avoid.addPool(pool.getId()); } - } + } // add remaining pools in cluster, that did not match tags, to avoid // set diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/UseLocalForRootAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/UseLocalForRootAllocator.java index 4663b12e97e..d0571382191 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/UseLocalForRootAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/UseLocalForRootAllocator.java @@ -34,22 +34,24 @@ import com.cloud.vm.DiskProfile; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; -@Local(value=StoragePoolAllocator.class) +@Local(value = StoragePoolAllocator.class) public class UseLocalForRootAllocator extends LocalStoragePoolAllocator implements StoragePoolAllocator { @Inject DataCenterDao _dcDao; @Override - public List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + public List allocateToPool(DiskProfile dskCh, + VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, + int returnUpTo) { DataCenterVO dc = _dcDao.findById(plan.getDataCenterId()); if (!dc.isLocalStorageEnabled()) { return null; } - + return super.allocateToPool(dskCh, vmProfile, plan, avoid, returnUpTo); } - + @Override public boolean configure(String name, Map params) throws ConfigurationException { super.configure(name, params); diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java index d8d413283ad..29b3400bbbb 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java @@ -39,21 +39,21 @@ import com.cloud.vm.VirtualMachineProfile; @Component public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator { private static final Logger s_logger = Logger.getLogger(ZoneWideStoragePoolAllocator.class); - @Inject PrimaryDataStoreDao _storagePoolDao; - @Inject DataStoreManager dataStoreMgr; + @Inject + PrimaryDataStoreDao _storagePoolDao; + @Inject + DataStoreManager dataStoreMgr; @Override - protected boolean filter(ExcludeList avoid, StoragePool pool, DiskProfile dskCh, - DeploymentPlan plan) { - Volume volume = _volumeDao.findById(dskCh.getVolumeId()); + protected boolean filter(ExcludeList avoid, StoragePool pool, DiskProfile dskCh, DeploymentPlan plan) { + Volume volume = _volumeDao.findById(dskCh.getVolumeId()); List requestVolumes = new ArrayList(); requestVolumes.add(volume); return storageMgr.storagePoolHasEnoughSpace(requestVolumes, pool); } @Override - protected List select(DiskProfile dskCh, - VirtualMachineProfile vmProfile, + protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { s_logger.debug("ZoneWideStoragePoolAllocator to find storage pool"); List suitablePools = new ArrayList(); @@ -80,7 +80,7 @@ public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator { if (suitablePools.size() == returnUpTo) { break; } - StoragePool pol = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(storage.getId()); + StoragePool pol = (StoragePool) this.dataStoreMgr.getPrimaryDataStore(storage.getId()); if (filter(avoid, pol, dskCh, plan)) { suitablePools.add(pol); } else { diff --git a/engine/storage/src/org/apache/cloudstack/storage/backup/SnapshotOnBackupStoreInfo.java b/engine/storage/src/org/apache/cloudstack/storage/backup/SnapshotOnBackupStoreInfo.java index 5f5ce2f4a92..36da9665bcc 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/backup/SnapshotOnBackupStoreInfo.java +++ b/engine/storage/src/org/apache/cloudstack/storage/backup/SnapshotOnBackupStoreInfo.java @@ -19,6 +19,7 @@ package org.apache.cloudstack.storage.backup; import org.apache.cloudstack.storage.backup.datastore.BackupStoreInfo; public interface SnapshotOnBackupStoreInfo { - public String getName(); - public BackupStoreInfo getBackupStore(); + public String getName(); + + public BackupStoreInfo getBackupStore(); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/backup/datastore/BackupStoreInfo.java b/engine/storage/src/org/apache/cloudstack/storage/backup/datastore/BackupStoreInfo.java index ca1454af570..fc41d4739c1 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/backup/datastore/BackupStoreInfo.java +++ b/engine/storage/src/org/apache/cloudstack/storage/backup/datastore/BackupStoreInfo.java @@ -19,6 +19,7 @@ package org.apache.cloudstack.storage.backup.datastore; import org.apache.cloudstack.storage.backup.SnapshotOnBackupStoreInfo; public interface BackupStoreInfo { - public SnapshotOnBackupStoreInfo getSnapshot(long snapshotId); - public boolean deleteSnapshot(SnapshotOnBackupStoreInfo snapshot); + public SnapshotOnBackupStoreInfo getSnapshot(long snapshotId); + + public boolean deleteSnapshot(SnapshotOnBackupStoreInfo snapshot); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/DataObjectManager.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/DataObjectManager.java index 20bf0545dc9..ef215284ddd 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/DataObjectManager.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/DataObjectManager.java @@ -18,20 +18,25 @@ */ package org.apache.cloudstack.storage.datastore; -import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.storage.command.CommandResult; public interface DataObjectManager { - public void createAsync(DataObject data, DataStore store, AsyncCompletionCallback callback, boolean noCopy); + public void createAsync(DataObject data, DataStore store, AsyncCompletionCallback callback, + boolean noCopy); + /* - * Only create internal state, without actually send down create command. + * Only create internal state, without actually send down create command. * It's up to device driver decides whether to create object before copying */ public DataObject createInternalStateOnly(DataObject data, DataStore store); + public void update(DataObject data, String path, Long size); + public void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback callback); + public void deleteAsync(DataObject data, AsyncCompletionCallback callback); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/DataObjectManagerImpl.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/DataObjectManagerImpl.java index 9d1afbeacad..6e97e6f9f74 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/DataObjectManagerImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/DataObjectManagerImpl.java @@ -20,9 +20,9 @@ package org.apache.cloudstack.storage.datastore; import javax.inject.Inject; -import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; @@ -31,7 +31,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreState import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.framework.async.AsyncRpcConext; -import org.apache.cloudstack.storage.motion.DataMotionService; +import org.apache.cloudstack.storage.command.CommandResult; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -40,17 +40,15 @@ import com.cloud.utils.fsm.NoTransitionException; @Component public class DataObjectManagerImpl implements DataObjectManager { - private static final Logger s_logger = Logger - .getLogger(DataObjectManagerImpl.class); + private static final Logger s_logger = Logger.getLogger(DataObjectManagerImpl.class); @Inject ObjectInDataStoreManager objectInDataStoreMgr; @Inject DataMotionService motionSrv; protected long waitingTime = 1800; // half an hour protected long waitingRetries = 10; - - protected DataObject waitingForCreated(DataObject dataObj, - DataStore dataStore) { + + protected DataObject waitingForCreated(DataObject dataObj, DataStore dataStore) { long retries = this.waitingRetries; DataObjectInStore obj = null; do { @@ -61,8 +59,7 @@ public class DataObjectManagerImpl implements DataObjectManager { throw new CloudRuntimeException("sleep interrupted", e); } - obj = objectInDataStoreMgr.findObject(dataObj, - dataStore); + obj = objectInDataStoreMgr.findObject(dataObj, dataStore); if (obj == null) { s_logger.debug("can't find object in db, maybe it's cleaned up already, exit waiting"); break; @@ -75,40 +72,35 @@ public class DataObjectManagerImpl implements DataObjectManager { if (obj == null || retries <= 0) { s_logger.debug("waiting too long for template downloading, marked it as failed"); - throw new CloudRuntimeException( - "waiting too long for template downloading, marked it as failed"); + throw new CloudRuntimeException("waiting too long for template downloading, marked it as failed"); } return objectInDataStoreMgr.get(dataObj, dataStore); } + class CreateContext extends AsyncRpcConext { final DataObject objInStrore; - public CreateContext(AsyncCompletionCallback callback, - DataObject objInStore) { + public CreateContext(AsyncCompletionCallback callback, DataObject objInStore) { super(callback); - this.objInStrore = objInStore; + this.objInStrore = objInStore; } } - + @Override - public void createAsync(DataObject data, DataStore store, - AsyncCompletionCallback callback, boolean noCopy) { - DataObjectInStore obj = objectInDataStoreMgr.findObject( - data, store); + public void createAsync(DataObject data, DataStore store, AsyncCompletionCallback callback, + boolean noCopy) { + DataObjectInStore obj = objectInDataStoreMgr.findObject(data, store); DataObject objInStore = null; boolean freshNewTemplate = false; if (obj == null) { try { - objInStore = objectInDataStoreMgr.create( - data, store); + objInStore = objectInDataStoreMgr.create(data, store); freshNewTemplate = true; } catch (Throwable e) { - obj = objectInDataStoreMgr.findObject(data, - store); + obj = objectInDataStoreMgr.findObject(data, store); if (obj == null) { - CreateCmdResult result = new CreateCmdResult( - null, null); + CreateCmdResult result = new CreateCmdResult(null, null); result.setSuccess(false); result.setResult(e.toString()); callback.complete(result); @@ -117,11 +109,9 @@ public class DataObjectManagerImpl implements DataObjectManager { } } - if (!freshNewTemplate - && obj.getState() != ObjectInDataStoreStateMachine.State.Ready) { + if (!freshNewTemplate && obj.getState() != ObjectInDataStoreStateMachine.State.Ready) { try { - objInStore = waitingForCreated( - data, store); + objInStore = waitingForCreated(data, store); } catch (Exception e) { CreateCmdResult result = new CreateCmdResult(null, null); result.setSuccess(false); @@ -130,8 +120,7 @@ public class DataObjectManagerImpl implements DataObjectManager { return; } - CreateCmdResult result = new CreateCmdResult( - null, null); + CreateCmdResult result = new CreateCmdResult(null, null); callback.complete(result); return; } @@ -143,12 +132,10 @@ public class DataObjectManagerImpl implements DataObjectManager { } else { event = ObjectInDataStoreStateMachine.Event.CreateRequested; } - objectInDataStoreMgr.update(objInStore, - event); + objectInDataStoreMgr.update(objInStore, event); } catch (NoTransitionException e) { try { - objectInDataStoreMgr.update(objInStore, - ObjectInDataStoreStateMachine.Event.OperationFailed); + objectInDataStoreMgr.update(objInStore, ObjectInDataStoreStateMachine.Event.OperationFailed); } catch (NoTransitionException e1) { s_logger.debug("state transation failed", e1); } @@ -159,24 +146,19 @@ public class DataObjectManagerImpl implements DataObjectManager { return; } - CreateContext context = new CreateContext( - callback, objInStore); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher - .create(this); - caller.setCallback( - caller.getTarget().createAsynCallback(null, null)) - .setContext(context); + CreateContext context = new CreateContext(callback, objInStore); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().createAsynCallback(null, null)).setContext(context); store.getDriver().createAsync(objInStore, caller); return; } - + protected Void createAsynCallback(AsyncCallbackDispatcher callback, CreateContext context) { CreateCmdResult result = callback.getResult(); DataObject objInStrore = context.objInStrore; - CreateCmdResult upResult = new CreateCmdResult( - null, null); + CreateCmdResult upResult = new CreateCmdResult(null, null); if (result.isFailed()) { upResult.setResult(result.getResult()); context.getParentCallback().complete(upResult); @@ -184,12 +166,10 @@ public class DataObjectManagerImpl implements DataObjectManager { } try { - objectInDataStoreMgr.update(objInStrore, - ObjectInDataStoreStateMachine.Event.OperationSuccessed); + objectInDataStoreMgr.update(objInStrore, ObjectInDataStoreStateMachine.Event.OperationSuccessed); } catch (NoTransitionException e) { try { - objectInDataStoreMgr.update(objInStrore, - ObjectInDataStoreStateMachine.Event.OperationFailed); + objectInDataStoreMgr.update(objInStrore, ObjectInDataStoreStateMachine.Event.OperationFailed); } catch (NoTransitionException e1) { s_logger.debug("failed to change state", e1); } @@ -198,18 +178,16 @@ public class DataObjectManagerImpl implements DataObjectManager { context.getParentCallback().complete(upResult); return null; } - + context.getParentCallback().complete(result); return null; } - + class CopyContext extends AsyncRpcConext { DataObject destObj; DataObject srcObj; - public CopyContext(AsyncCompletionCallback callback, - DataObject srcObj, - DataObject destObj) { + public CopyContext(AsyncCompletionCallback callback, DataObject srcObj, DataObject destObj) { super(callback); this.srcObj = srcObj; this.destObj = destObj; @@ -217,16 +195,13 @@ public class DataObjectManagerImpl implements DataObjectManager { } @Override - public void copyAsync(DataObject srcData, DataObject destData, - AsyncCompletionCallback callback) { + public void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback callback) { try { - objectInDataStoreMgr.update(destData, - ObjectInDataStoreStateMachine.Event.CopyingRequested); + objectInDataStoreMgr.update(destData, ObjectInDataStoreStateMachine.Event.CopyingRequested); } catch (NoTransitionException e) { s_logger.debug("failed to change state", e); try { - objectInDataStoreMgr.update(destData, - ObjectInDataStoreStateMachine.Event.OperationFailed); + objectInDataStoreMgr.update(destData, ObjectInDataStoreStateMachine.Event.OperationFailed); } catch (NoTransitionException e1) { } @@ -235,18 +210,14 @@ public class DataObjectManagerImpl implements DataObjectManager { callback.complete(res); } - CopyContext anotherCall = new CopyContext( - callback, srcData, destData); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher - .create(this); - caller.setCallback(caller.getTarget().copyCallback(null, null)) - .setContext(anotherCall); + CopyContext anotherCall = new CopyContext(callback, srcData, destData); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().copyCallback(null, null)).setContext(anotherCall); motionSrv.copyAsync(srcData, destData, caller); } - - protected Void copyCallback( - AsyncCallbackDispatcher callback, + + protected Void copyCallback(AsyncCallbackDispatcher callback, CopyContext context) { CopyCommandResult result = callback.getResult(); DataObject destObj = context.destObj; @@ -257,66 +228,56 @@ public class DataObjectManagerImpl implements DataObjectManager { } catch (NoTransitionException e) { s_logger.debug("Failed to update copying state", e); } - CreateCmdResult res = new CreateCmdResult( - null, null); + CreateCmdResult res = new CreateCmdResult(null, null); res.setResult(result.getResult()); context.getParentCallback().complete(res); } try { - objectInDataStoreMgr.update(destObj, - ObjectInDataStoreStateMachine.Event.OperationSuccessed); + objectInDataStoreMgr.update(destObj, ObjectInDataStoreStateMachine.Event.OperationSuccessed); } catch (NoTransitionException e) { s_logger.debug("Failed to update copying state: ", e); try { - objectInDataStoreMgr.update(destObj, - ObjectInDataStoreStateMachine.Event.OperationFailed); + objectInDataStoreMgr.update(destObj, ObjectInDataStoreStateMachine.Event.OperationFailed); } catch (NoTransitionException e1) { } - CreateCmdResult res = new CreateCmdResult( - null, null); + CreateCmdResult res = new CreateCmdResult(null, null); res.setResult("Failed to update copying state: " + e.toString()); context.getParentCallback().complete(res); } - CreateCmdResult res = new CreateCmdResult( - result.getPath(), null); + CreateCmdResult res = new CreateCmdResult(result.getPath(), null); context.getParentCallback().complete(res); return null; } - - class DeleteContext extends AsyncRpcConext { + class DeleteContext extends AsyncRpcConext { private final DataObject obj; + public DeleteContext(AsyncCompletionCallback callback, DataObject obj) { super(callback); this.obj = obj; } - + } + @Override - public void deleteAsync(DataObject data, - AsyncCompletionCallback callback) { + public void deleteAsync(DataObject data, AsyncCompletionCallback callback) { try { objectInDataStoreMgr.update(data, Event.DestroyRequested); } catch (NoTransitionException e) { s_logger.debug("destroy failed", e); - CreateCmdResult res = new CreateCmdResult( - null, null); + CreateCmdResult res = new CreateCmdResult(null, null); callback.complete(res); } - - DeleteContext context = new DeleteContext( - callback, data); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher - .create(this); - caller.setCallback( - caller.getTarget().deleteAsynCallback(null, null)) - .setContext(context); + + DeleteContext context = new DeleteContext(callback, data); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().deleteAsynCallback(null, null)).setContext(context); data.getDataStore().getDriver().deleteAsync(data, caller); return; } - + protected Void deleteAsynCallback(AsyncCallbackDispatcher callback, DeleteContext context) { DataObject destObj = context.obj; @@ -326,47 +287,44 @@ public class DataObjectManagerImpl implements DataObjectManager { try { objectInDataStoreMgr.update(destObj, Event.OperationFailed); } catch (NoTransitionException e) { - s_logger.debug("delete failed", e); + s_logger.debug("delete failed", e); } - + } else { try { objectInDataStoreMgr.update(destObj, Event.OperationSuccessed); } catch (NoTransitionException e) { - s_logger.debug("delete failed", e); + s_logger.debug("delete failed", e); } } - + context.getParentCallback().complete(res); return null; } @Override public DataObject createInternalStateOnly(DataObject data, DataStore store) { - DataObjectInStore obj = objectInDataStoreMgr.findObject( - data, store); + DataObjectInStore obj = objectInDataStoreMgr.findObject(data, store); DataObject objInStore = null; if (obj == null) { - objInStore = objectInDataStoreMgr.create( - data, store); + objInStore = objectInDataStoreMgr.create(data, store); } try { ObjectInDataStoreStateMachine.Event event = null; event = ObjectInDataStoreStateMachine.Event.CreateRequested; - objectInDataStoreMgr.update(objInStore, - event); - + objectInDataStoreMgr.update(objInStore, event); + objectInDataStoreMgr.update(objInStore, ObjectInDataStoreStateMachine.Event.OperationSuccessed); } catch (NoTransitionException e) { s_logger.debug("Failed to update state", e); throw new CloudRuntimeException("Failed to update state", e); } - + return objInStore; } @Override public void update(DataObject data, String path, Long size) { - throw new CloudRuntimeException("not implemented"); + throw new CloudRuntimeException("not implemented"); } } 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 a2fd08d1e8f..b92f92f655e 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/DataStoreManagerImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/DataStoreManagerImpl.java @@ -25,50 +25,73 @@ import javax.inject.Inject; 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.storage.image.datastore.ImageDataStoreManager; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; +import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager; import org.springframework.stereotype.Component; +import com.cloud.storage.DataStoreRole; import com.cloud.utils.exception.CloudRuntimeException; +import edu.emory.mathcs.backport.java.util.Collections; + @Component public class DataStoreManagerImpl implements DataStoreManager { @Inject PrimaryDataStoreProviderManager primaryStorMgr; @Inject - ImageDataStoreManager imageDataStoreMgr; + ImageStoreProviderManager imageDataStoreMgr; @Override public DataStore getDataStore(long storeId, DataStoreRole role) { if (role == DataStoreRole.Primary) { return primaryStorMgr.getPrimaryDataStore(storeId); } else if (role == DataStoreRole.Image) { - return imageDataStoreMgr.getImageDataStore(storeId); + return imageDataStoreMgr.getImageStore(storeId); + } else if (role == DataStoreRole.ImageCache) { + return imageDataStoreMgr.getImageStore(storeId); } throw new CloudRuntimeException("un recognized type" + role); } - @Override - public DataStore registerDataStore(Map params, - String providerUuid) { - return null; - } + @Override public DataStore getDataStore(String uuid, DataStoreRole role) { if (role == DataStoreRole.Primary) { return primaryStorMgr.getPrimaryDataStore(uuid); } else if (role == DataStoreRole.Image) { - return imageDataStoreMgr.getImageDataStore(uuid); + return imageDataStoreMgr.getImageStore(uuid); } throw new CloudRuntimeException("un recognized type" + role); } + @Override - public List getImageStores(Scope scope) { - return imageDataStoreMgr.getList(); + public List getImageStoresByScope(ZoneScope scope) { + return imageDataStoreMgr.listImageStoresByScope(scope); } + + @Override + public DataStore getImageStore(long zoneId) { + List stores = getImageStoresByScope(new ZoneScope(zoneId)); + if (stores == null || stores.size() == 0) { + return null; + } + Collections.shuffle(stores); + return stores.get(0); + } + @Override public DataStore getPrimaryDataStore(long storeId) { return primaryStorMgr.getPrimaryDataStore(storeId); } + @Override + public List getImageCacheStores(Scope scope) { + return imageDataStoreMgr.listImageCacheStores(scope); + } + + @Override + public List listImageStores() { + return imageDataStoreMgr.listImageStores(); + } + } 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..b72d07b2d88 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManager.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManager.java @@ -18,19 +18,25 @@ package org.apache.cloudstack.storage.datastore; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType; 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.ObjectInDataStoreStateMachine.Event; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.storage.DataStoreRole; import com.cloud.utils.fsm.NoTransitionException; public interface ObjectInDataStoreManager { - public DataObject create(DataObject template, DataStore dataStore); + public DataObject create(DataObject dataObj, DataStore dataStore); + + public boolean delete(DataObject dataObj); + 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); + + DataStore findStore(long objId, 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..4b3d4a622d5 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java @@ -20,132 +20,235 @@ import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType; 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.ImageDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; 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.SnapshotInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; +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.ObjectInDataStoreDao; -import org.apache.cloudstack.storage.db.ObjectInDataStoreVO; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.S3TO; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.VMTemplateStoragePoolVO; -import com.cloud.storage.dao.VMTemplateHostDao; +import com.cloud.storage.dao.SnapshotDao; +import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplatePoolDao; -import com.cloud.storage.dao.VolumeHostDao; -import com.cloud.utils.db.SearchCriteria.Op; -import com.cloud.utils.db.SearchCriteria2; -import com.cloud.utils.db.SearchCriteriaService; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.storage.template.TemplateConstants; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.fsm.StateMachine2; @Component public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager { - private static final Logger s_logger = Logger - .getLogger(ObjectInDataStoreManagerImpl.class); + private static final Logger s_logger = Logger.getLogger(ObjectInDataStoreManagerImpl.class); @Inject - ImageDataFactory imageFactory; + TemplateDataFactory imageFactory; @Inject DataStoreManager storeMgr; @Inject VolumeDataFactory volumeFactory; @Inject - ObjectInDataStoreDao objectDataStoreDao; + TemplateDataStoreDao templateDataStoreDao; @Inject - VolumeHostDao volumeHostDao; + SnapshotDataStoreDao snapshotDataStoreDao; @Inject - VMTemplateHostDao templateHostDao; + VolumeDataStoreDao volumeDataStoreDao; @Inject VMTemplatePoolDao templatePoolDao; @Inject SnapshotDataFactory snapshotFactory; + @Inject + ObjectInDataStoreDao objInStoreDao; + @Inject + VMTemplateDao templateDao; + @Inject + SnapshotDao snapshotDao; + @Inject + VolumeDao volumeDao; protected StateMachine2 stateMachines; public ObjectInDataStoreManagerImpl() { stateMachines = new StateMachine2(); - stateMachines.addTransition(State.Allocated, Event.CreateRequested, - State.Creating); - stateMachines.addTransition(State.Creating, Event.OperationSuccessed, - State.Created); - stateMachines.addTransition(State.Creating, Event.OperationFailed, - State.Failed); - stateMachines.addTransition(State.Failed, Event.CreateRequested, - State.Creating); - stateMachines.addTransition(State.Ready, Event.DestroyRequested, - State.Destroying); - stateMachines.addTransition(State.Destroying, Event.OperationSuccessed, - State.Destroyed); - stateMachines.addTransition(State.Destroying, Event.OperationFailed, - State.Destroying); - stateMachines.addTransition(State.Destroying, Event.DestroyRequested, - State.Destroying); - stateMachines.addTransition(State.Created, Event.CopyingRequested, - State.Copying); - stateMachines.addTransition(State.Copying, Event.OperationFailed, - State.Created); - stateMachines.addTransition(State.Copying, Event.OperationSuccessed, - State.Ready); - stateMachines.addTransition(State.Allocated, Event.CreateOnlyRequested, - State.Creating2); - stateMachines.addTransition(State.Creating2, Event.OperationFailed, - State.Allocated); - stateMachines.addTransition(State.Creating2, Event.OperationSuccessed, - State.Ready); + stateMachines.addTransition(State.Allocated, Event.CreateOnlyRequested, State.Creating); + stateMachines.addTransition(State.Creating, Event.OperationFailed, State.Allocated); + stateMachines.addTransition(State.Creating, Event.OperationSuccessed, State.Ready); + stateMachines.addTransition(State.Ready, Event.CopyingRequested, State.Copying); + stateMachines.addTransition(State.Copying, Event.OperationSuccessed, State.Ready); + stateMachines.addTransition(State.Copying, Event.OperationFailed, State.Ready); + stateMachines.addTransition(State.Ready, Event.DestroyRequested, State.Destroying); + stateMachines.addTransition(State.Destroying, Event.DestroyRequested, State.Destroying); + stateMachines.addTransition(State.Destroying, Event.OperationSuccessed, State.Destroyed); + stateMachines.addTransition(State.Destroying, Event.OperationFailed, State.Destroying); + // TODO: further investigate why an extra event is sent when it is + // alreay Ready for DownloadListener + stateMachines.addTransition(State.Ready, Event.OperationSuccessed, State.Ready); } @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 if (obj.getType() == DataObjectType.SNAPSHOT) { + SnapshotDataStoreVO ss = new SnapshotDataStoreVO(); + ss.setSnapshotId(obj.getId()); + ss.setDataStoreId(dataStore.getId()); + ss.setRole(dataStore.getRole()); + ss.setState(ObjectInDataStoreStateMachine.State.Allocated); + ss = snapshotDataStoreDao.persist(ss); + } } 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.setDataStoreRole(dataStore.getRole()); + String installPath = TemplateConstants.DEFAULT_TMPLT_ROOT_DIR + "/" + + TemplateConstants.DEFAULT_TMPLT_FIRST_LEVEL_DIR + + templateDao.findById(obj.getId()).getAccountId() + "/" + obj.getId(); + if (dataStore.getTO() instanceof S3TO) { + TemplateInfo tmpl = (TemplateInfo) obj; + installPath += "/" + tmpl.getUniqueName(); // for S3, we + // append + // template name + // in the path + // for template + // sync since we + // don't have + // template.properties + // there + } + ts.setInstallPath(installPath); + ts.setState(ObjectInDataStoreStateMachine.State.Allocated); + ts = templateDataStoreDao.persist(ts); + break; + case SNAPSHOT: + SnapshotInfo snapshot = (SnapshotInfo) obj; + SnapshotDataStoreVO ss = new SnapshotDataStoreVO(); + ss.setSnapshotId(obj.getId()); + ss.setDataStoreId(dataStore.getId()); + ss.setRole(dataStore.getRole()); + ss.setRole(dataStore.getRole()); + ss.setInstallPath(TemplateConstants.DEFAULT_SNAPSHOT_ROOT_DIR + "/" + + snapshotDao.findById(obj.getId()).getAccountId() + "/" + snapshot.getVolumeId()); + ss.setState(ObjectInDataStoreStateMachine.State.Allocated); + ss = snapshotDataStoreDao.persist(ss); + break; + case VOLUME: + VolumeDataStoreVO vs = new VolumeDataStoreVO(); + vs.setVolumeId(obj.getId()); + vs.setDataStoreId(dataStore.getId()); + vs.setInstallPath(TemplateConstants.DEFAULT_VOLUME_ROOT_DIR + "/" + + volumeDao.findById(obj.getId()).getAccountId() + "/" + obj.getId()); + vs.setState(ObjectInDataStoreStateMachine.State.Allocated); + 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 { - DataObjectInStore obj = this.findObject(data, data.getDataStore()); - if (obj == null) { - throw new CloudRuntimeException( - "can't find mapping in ObjectInDataStore table for: " - + data); - } - - if (data.getType() == DataObjectType.TEMPLATE && data.getDataStore().getRole() == DataStoreRole.Primary) { - try { - this.stateMachines.transitTo(obj, event, null, - templatePoolDao); - } catch (NoTransitionException e) { - if (event == Event.CreateOnlyRequested || event == Event.OperationSuccessed) { - s_logger.debug("allow muliple create requests"); + public boolean delete(DataObject dataObj) { + long objId = dataObj.getId(); + DataStore dataStore = dataObj.getDataStore(); + if (dataStore.getRole() == DataStoreRole.Primary) { + if (dataObj.getType() == DataObjectType.TEMPLATE) { + VMTemplateStoragePoolVO destTmpltPool = templatePoolDao.findByPoolTemplate(dataStore.getId(), objId); + if (destTmpltPool != null) { + return templatePoolDao.remove(destTmpltPool.getId()); } else { - throw e; + s_logger.warn("Template " + objId + " is not found on storage pool " + dataStore.getId() + + ", so no need to delete"); + return true; } } } else { - this.stateMachines.transitTo(obj, event, null, objectDataStoreDao); + // Image store + switch (dataObj.getType()) { + case TEMPLATE: + TemplateDataStoreVO destTmpltStore = templateDataStoreDao.findByStoreTemplate(dataStore.getId(), objId); + if (destTmpltStore != null) { + return templateDataStoreDao.remove(destTmpltStore.getId()); + } else { + s_logger.warn("Template " + objId + " is not found on image store " + dataStore.getId() + + ", so no need to delete"); + return true; + } + case SNAPSHOT: + SnapshotDataStoreVO destSnapshotStore = snapshotDataStoreDao.findByStoreSnapshot(dataStore.getRole(), + dataStore.getId(), objId); + if (destSnapshotStore != null) { + return snapshotDataStoreDao.remove(destSnapshotStore.getId()); + } else { + s_logger.warn("Snapshot " + objId + " is not found on image store " + dataStore.getId() + + ", so no need to delete"); + return true; + } + case VOLUME: + VolumeDataStoreVO destVolumeStore = volumeDataStoreDao.findByStoreVolume(dataStore.getId(), objId); + if (destVolumeStore != null) { + return volumeDataStoreDao.remove(destVolumeStore.getId()); + } else { + s_logger.warn("Volume " + objId + " is not found on image store " + dataStore.getId() + + ", so no need to delete"); + return true; + } + } + } + + s_logger.warn("Unsupported data object (" + dataObj.getType() + ", " + dataObj.getDataStore() + ")"); + return false; + } + + @Override + public boolean update(DataObject data, Event event) throws NoTransitionException { + DataObjectInStore obj = this.findObject(data, data.getDataStore()); + if (obj == null) { + throw new CloudRuntimeException("can't find mapping in ObjectInDataStore table for: " + data); + } + + if (data.getDataStore().getRole() == DataStoreRole.Image + || data.getDataStore().getRole() == DataStoreRole.ImageCache) { + switch (data.getType()) { + case TEMPLATE: + this.stateMachines.transitTo(obj, event, null, templateDataStoreDao); + break; + case SNAPSHOT: + this.stateMachines.transitTo(obj, event, null, snapshotDataStoreDao); + break; + case VOLUME: + this.stateMachines.transitTo(obj, event, null, volumeDataStoreDao); + break; + } + } else if (data.getType() == DataObjectType.TEMPLATE && data.getDataStore().getRole() == DataStoreRole.Primary) { + + this.stateMachines.transitTo(obj, event, null, templatePoolDao); + + } else if (data.getType() == DataObjectType.SNAPSHOT && data.getDataStore().getRole() == DataStoreRole.Primary) { + this.stateMachines.transitTo(obj, event, null, snapshotDataStoreDao); + } else { + throw new CloudRuntimeException("Invalid data or store type: " + data.getType() + " " + + data.getDataStore().getRole()); } return true; } @@ -155,58 +258,65 @@ 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(); + if (role == DataStoreRole.Image || role == DataStoreRole.ImageCache) { + switch (type) { + case TEMPLATE: + vo = templateDataStoreDao.findByStoreTemplate(dataStoreId, objId); + break; + case SNAPSHOT: + vo = snapshotDataStoreDao.findByStoreSnapshot(role, dataStoreId, objId); + break; + case VOLUME: + vo = volumeDataStoreDao.findByStoreVolume(dataStoreId, objId); + break; + } + } else if (type == DataObjectType.TEMPLATE && role == DataStoreRole.Primary) { + vo = templatePoolDao.findByPoolTemplate(dataStoreId, objId); + } else if (type == DataObjectType.SNAPSHOT && role == DataStoreRole.Primary) { + vo = snapshotDataStoreDao.findByStoreSnapshot(role, 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) { + public DataStore findStore(long objId, DataObjectType type, DataStoreRole role) { DataStore store = null; if (role == DataStoreRole.Image) { - SearchCriteriaService sc = SearchCriteria2.create(ObjectInDataStoreVO.class); - sc.addAnd(sc.getEntity().getDataStoreRole(), Op.EQ, role); - sc.addAnd(sc.getEntity().getObjectUuid(), Op.EQ, objUuid); - sc.addAnd(sc.getEntity().getObjectType(), Op.EQ, type); - ObjectInDataStoreVO vo = sc.find(); + DataObjectInStore vo = null; + switch (type) { + case TEMPLATE: + vo = templateDataStoreDao.findByTemplate(objId, role); + break; + case SNAPSHOT: + vo = snapshotDataStoreDao.findBySnapshot(objId, role); + break; + case VOLUME: + vo = volumeDataStoreDao.findByVolume(objId); + break; + } if (vo != null) { - store = this.storeMgr.getDataStore(vo.getDataStoreUuid(), vo.getDataStoreRole()); + store = this.storeMgr.getDataStore(vo.getDataStoreId(), role); } } return store; diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStore.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStore.java index fdaaace49d7..d8b2a734792 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStore.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStore.java @@ -36,9 +36,8 @@ public interface PrimaryDataStore extends DataStore, PrimaryDataStoreInfo { boolean exists(DataObject data); TemplateInfo getTemplate(long templateId); - - SnapshotInfo getSnapshot(long snapshotId); + SnapshotInfo getSnapshot(long snapshotId); DiskFormat getDefaultDiskType(); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreEntityImpl.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreEntityImpl.java index 2dc3e255b38..e861910116a 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreEntityImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreEntityImpl.java @@ -31,11 +31,11 @@ import com.cloud.storage.StoragePoolStatus; public class PrimaryDataStoreEntityImpl implements StorageEntity { private PrimaryDataStoreInfo dataStore; - + public PrimaryDataStoreEntityImpl(PrimaryDataStoreInfo dataStore) { this.dataStore = dataStore; } - + @Override public boolean enable() { // TODO Auto-generated method stub @@ -72,7 +72,7 @@ public class PrimaryDataStoreEntityImpl implements StorageEntity { @Override public String getCurrentState() { - return null; + return null; } @Override @@ -105,7 +105,6 @@ public class PrimaryDataStoreEntityImpl implements StorageEntity { return null; } - @Override public void addDetail(String name, String value) { // TODO Auto-generated method stub @@ -132,7 +131,7 @@ public class PrimaryDataStoreEntityImpl implements StorageEntity { @Override public State getState() { - //return this.dataStore.getManagedState(); + // return this.dataStore.getManagedState(); return null; } @@ -171,7 +170,7 @@ public class PrimaryDataStoreEntityImpl implements StorageEntity { } @Override - public long getAvailableBytes() { + public long getUsedBytes() { // TODO Auto-generated method stub return 0; } @@ -230,17 +229,16 @@ public class PrimaryDataStoreEntityImpl implements StorageEntity { return null; } - public String getStorageType() { // TODO Auto-generated method stub return null; } - @Override - public void persist() { - // TODO Auto-generated method stub - - } + @Override + public void persist() { + // TODO Auto-generated method stub + + } @Override public boolean isInMaintenance() { diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreProviderManager.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreProviderManager.java index b3ed0aaab68..8613668b180 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreProviderManager.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreProviderManager.java @@ -21,11 +21,12 @@ package org.apache.cloudstack.storage.datastore; import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; - public interface PrimaryDataStoreProviderManager { public PrimaryDataStore getPrimaryDataStore(long dataStoreId); + public PrimaryDataStore getPrimaryDataStore(String uuid); boolean registerDriver(String providerName, PrimaryDataStoreDriver driver); + boolean registerHostListener(String providerName, HypervisorHostListener listener); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/protocol/DataStoreProtocol.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/protocol/DataStoreProtocol.java index b0a7d50c57d..b27c96edbb7 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/protocol/DataStoreProtocol.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/protocol/DataStoreProtocol.java @@ -17,14 +17,14 @@ package org.apache.cloudstack.storage.datastore.protocol; public enum DataStoreProtocol { - NFS("nfs"), - ISCSI("iscsi"); - + NFS("nfs"), ISCSI("iscsi"); + private String name; + DataStoreProtocol(String name) { this.name = name; } - + @Override public String toString() { return this.name; diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/provider/DataStoreProviderManagerImpl.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/provider/DataStoreProviderManagerImpl.java index 40a65dcf07f..50238a89a70 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/provider/DataStoreProviderManagerImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/provider/DataStoreProviderManagerImpl.java @@ -31,11 +31,10 @@ import org.apache.cloudstack.api.response.StorageProviderResponse; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider.DataStoreProviderType; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager; -import org.apache.cloudstack.engine.subsystem.api.storage.ImageDataStoreProvider; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; -import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreProvider; import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager; -import org.apache.cloudstack.storage.datastore.db.DataStoreProviderDao; +import org.apache.cloudstack.storage.image.ImageStoreDriver; +import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -44,30 +43,24 @@ import com.cloud.utils.component.ManagerBase; @Component public class DataStoreProviderManagerImpl extends ManagerBase implements DataStoreProviderManager { - private static final Logger s_logger = Logger - .getLogger(DataStoreProviderManagerImpl.class); + private static final Logger s_logger = Logger.getLogger(DataStoreProviderManagerImpl.class); @Inject List providers; - @Inject - DataStoreProviderDao providerDao; protected Map providerMap = new HashMap(); @Inject PrimaryDataStoreProviderManager primaryDataStoreProviderMgr; + @Inject + ImageStoreProviderManager imageDataStoreProviderMgr; + @Override public DataStoreProvider getDataStoreProvider(String name) { return providerMap.get(name); } - @Override - public List getDataStoreProviders() { - // TODO Auto-generated method stub - return null; - } - public List getPrimaryDataStoreProviders() { List providers = new ArrayList(); for (DataStoreProvider provider : providerMap.values()) { - if (provider instanceof PrimaryDataStoreProvider) { + if (provider.getTypes().contains(DataStoreProviderType.PRIMARY)) { StorageProviderResponse response = new StorageProviderResponse(); response.setName(provider.getName()); response.setType(DataStoreProvider.DataStoreProviderType.PRIMARY.toString()); @@ -76,11 +69,11 @@ public class DataStoreProviderManagerImpl extends ManagerBase implements DataSto } return providers; } - + public List getImageDataStoreProviders() { List providers = new ArrayList(); for (DataStoreProvider provider : providerMap.values()) { - if (provider instanceof ImageDataStoreProvider) { + if (provider.getTypes().contains(DataStoreProviderType.IMAGE)) { StorageProviderResponse response = new StorageProviderResponse(); response.setName(provider.getName()); response.setType(DataStoreProvider.DataStoreProviderType.IMAGE.toString()); @@ -90,20 +83,33 @@ public class DataStoreProviderManagerImpl extends ManagerBase implements DataSto return providers; } + public List getCacheDataStoreProviders() { + List providers = new ArrayList(); + for (DataStoreProvider provider : providerMap.values()) { + if (provider.getTypes().contains(DataStoreProviderType.ImageCache)) { + StorageProviderResponse response = new StorageProviderResponse(); + response.setName(provider.getName()); + response.setType(DataStoreProviderType.ImageCache.toString()); + providers.add(response); + } + } + return providers; + } + @Override - public boolean configure(String name, Map params) - throws ConfigurationException { + public boolean configure(String name, Map params) throws ConfigurationException { Map copyParams = new HashMap(params); for (DataStoreProvider provider : providers) { String providerName = provider.getName(); if (providerMap.get(providerName) != null) { - s_logger.debug("Failed to register data store provider, provider name: " + providerName + " is not unique"); + s_logger.debug("Failed to register data store provider, provider name: " + providerName + + " is not unique"); return false; } - + s_logger.debug("registering data store provider:" + provider.getName()); - + providerMap.put(providerName, provider); try { boolean registrationResult = provider.configure(copyParams); @@ -112,24 +118,39 @@ public class DataStoreProviderManagerImpl extends ManagerBase implements DataSto s_logger.debug("Failed to register data store provider: " + providerName); return false; } - + Set types = provider.getTypes(); if (types.contains(DataStoreProviderType.PRIMARY)) { - primaryDataStoreProviderMgr.registerDriver(provider.getName(), (PrimaryDataStoreDriver)provider.getDataStoreDriver()); + primaryDataStoreProviderMgr.registerDriver(provider.getName(), + (PrimaryDataStoreDriver) provider.getDataStoreDriver()); primaryDataStoreProviderMgr.registerHostListener(provider.getName(), provider.getHostListener()); + } else if (types.contains(DataStoreProviderType.IMAGE)) { + imageDataStoreProviderMgr.registerDriver(provider.getName(), + (ImageStoreDriver) provider.getDataStoreDriver()); } - } catch(Exception e) { + } catch (Exception e) { s_logger.debug("configure provider failed", e); providerMap.remove(providerName); + return false; } } - + return true; } @Override public DataStoreProvider getDefaultPrimaryDataStoreProvider() { - return this.getDataStoreProvider("ancient primary data store provider"); + return this.getDataStoreProvider(DataStoreProvider.DEFAULT_PRIMARY); + } + + @Override + public DataStoreProvider getDefaultImageDataStoreProvider() { + return this.getDataStoreProvider(DataStoreProvider.NFS_IMAGE); + } + + @Override + public DataStoreProvider getDefaultCacheDataStoreProvider() { + return this.getDataStoreProvider(DataStoreProvider.NFS_IMAGE); } @Override @@ -141,6 +162,8 @@ public class DataStoreProviderManagerImpl extends ManagerBase implements DataSto return this.getPrimaryDataStoreProviders(); } else if (type.equalsIgnoreCase(DataStoreProvider.DataStoreProviderType.IMAGE.toString())) { return this.getImageDataStoreProviders(); + } else if (type.equalsIgnoreCase(DataStoreProvider.DataStoreProviderType.ImageCache.toString())) { + return this.getCacheDataStoreProviders(); } else { throw new InvalidParameterValueException("Invalid parameter: " + type); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/db/ObjectInDataStoreDao.java b/engine/storage/src/org/apache/cloudstack/storage/db/ObjectInDataStoreDao.java index fb7dec0fa41..37d089d816d 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/db/ObjectInDataStoreDao.java +++ b/engine/storage/src/org/apache/cloudstack/storage/db/ObjectInDataStoreDao.java @@ -22,6 +22,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreState import com.cloud.utils.db.GenericDao; import com.cloud.utils.fsm.StateDao; -public interface ObjectInDataStoreDao extends GenericDao, StateDao { +public interface ObjectInDataStoreDao extends GenericDao, + StateDao { } diff --git a/engine/storage/src/org/apache/cloudstack/storage/db/ObjectInDataStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/db/ObjectInDataStoreDaoImpl.java index 9965d60b23d..aac1d134e34 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/db/ObjectInDataStoreDaoImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/db/ObjectInDataStoreDaoImpl.java @@ -15,6 +15,7 @@ // specific language governing permissions and limitations // under the License. package org.apache.cloudstack.storage.db; + import java.util.Date; import java.util.Map; @@ -36,10 +37,11 @@ import com.cloud.utils.db.UpdateBuilder; public class ObjectInDataStoreDaoImpl extends GenericDaoBase implements ObjectInDataStoreDao { private static final Logger s_logger = Logger.getLogger(ObjectInDataStoreDaoImpl.class); private SearchBuilder updateStateSearch; + @Override public boolean configure(String name, Map params) throws ConfigurationException { - super.configure(name, params); - + super.configure(name, params); + updateStateSearch = this.createSearchBuilder(); updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ); updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ); @@ -47,14 +49,13 @@ public class ObjectInDataStoreDaoImpl extends GenericDaoBase sc = updateStateSearch.create(); sc.setParameters("id", vo.getId()); sc.setParameters("state", currentState); @@ -66,19 +67,23 @@ public class ObjectInDataStoreDaoImpl extends GenericDaoBase 0; diff --git a/engine/storage/src/org/apache/cloudstack/storage/db/ObjectInDataStoreVO.java b/engine/storage/src/org/apache/cloudstack/storage/db/ObjectInDataStoreVO.java index 0fbcbb1f956..df9c83641f6 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/db/ObjectInDataStoreVO.java +++ b/engine/storage/src/org/apache/cloudstack/storage/db/ObjectInDataStoreVO.java @@ -30,10 +30,11 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.Storage; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.utils.db.GenericDaoBase; @@ -46,16 +47,16 @@ public class ObjectInDataStoreVO implements StateObject ssAHosts = listUpAndConnectingSecondaryStorageVmHost(dcId); + if (ssAHosts == null || ssAHosts.isEmpty()) { + return new LocalHostEndpoint(); // use local host as endpoint in + // case of no ssvm existing + } + Collections.shuffle(ssAHosts); + HostVO host = ssAHosts.get(0); + return RemoteHostEndPoint.getHypervisorHostEndPoint(host.getId(), host.getPrivateIpAddress(), + host.getPublicIpAddress()); + } + + private List listUpAndConnectingSecondaryStorageVmHost(Long dcId) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + if (dcId != null) { + sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId); + } + sc.addAnd(sc.getEntity().getStatus(), Op.IN, com.cloud.host.Status.Up, com.cloud.host.Status.Connecting); + sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.SecondaryStorageVM); + return sc.list(); + } + @Override public EndPoint select(DataObject object) { DataStore store = object.getDataStore(); + return select(store); + } + + @Override + public EndPoint select(DataStore store) { if (store.getRole() == DataStoreRole.Primary) { return findEndpointForPrimaryStorage(store); } else if (store.getRole() == DataStoreRole.Image) { - //in case there is no ssvm, directly send down command hypervisor host - //TODO: add code to handle in case ssvm is there - return findEndpointForPrimaryStorage(store); - }else { + // in case there is no ssvm, directly send down command hypervisor + // host + // otherwise, send to localhost for bootstrap system vm template + // download + return findEndpointForImageStorage(store); + } else { throw new CloudRuntimeException("not implemented yet"); } - } - + @Override public List selectAll(DataStore store) { List endPoints = new ArrayList(); if (store.getScope().getScopeType() == ScopeType.HOST) { HostVO host = hostDao.findById(store.getScope().getScopeId()); - endPoints.add(HypervisorHostEndPoint.getHypervisorHostEndPoint(host.getId(), - host.getPrivateIpAddress())); + endPoints.add(RemoteHostEndPoint.getHypervisorHostEndPoint(host.getId(), host.getPrivateIpAddress(), + host.getPublicIpAddress())); } else if (store.getScope().getScopeType() == ScopeType.CLUSTER) { SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); sc.addAnd(sc.getEntity().getClusterId(), Op.EQ, store.getScope().getScopeId()); sc.addAnd(sc.getEntity().getStatus(), Op.EQ, Status.Up); List hosts = sc.find(); for (HostVO host : hosts) { - endPoints.add(HypervisorHostEndPoint.getHypervisorHostEndPoint(host.getId(), - host.getPrivateIpAddress())); + endPoints.add(RemoteHostEndPoint.getHypervisorHostEndPoint(host.getId(), host.getPrivateIpAddress(), + host.getPublicIpAddress())); } - + } else { throw new CloudRuntimeException("shouldn't use it for other scope"); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/BaseImageStoreDriverImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/BaseImageStoreDriverImpl.java new file mode 100644 index 00000000000..93b0c2b373d --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/image/BaseImageStoreDriverImpl.java @@ -0,0 +1,216 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.image; + +import java.util.Date; +import java.util.Set; +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.framework.async.AsyncRpcConext; +import org.apache.cloudstack.storage.command.CommandResult; +import org.apache.cloudstack.storage.command.DeleteCommand; +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.image.ImageStoreDriver; +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.storage.DownloadAnswer; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataTO; +import com.cloud.storage.VMTemplateStorageResourceAssoc; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.storage.download.DownloadMonitor; + +public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver { + private static final Logger s_logger = Logger.getLogger(BaseImageStoreDriverImpl.class); + @Inject + VMTemplateDao templateDao; + @Inject + DownloadMonitor _downloadMonitor; + @Inject + VolumeDao volumeDao; + @Inject + VolumeDataStoreDao _volumeStoreDao; + @Inject + TemplateDataStoreDao _templateStoreDao; + @Inject + EndPointSelector _epSelector; + + @Override + public DataTO getTO(DataObject data) { + return null; + } + + class CreateContext extends AsyncRpcConext { + final DataObject data; + + public CreateContext(AsyncCompletionCallback callback, DataObject data) { + super(callback); + this.data = data; + } + } + + @Override + public void createAsync(DataObject data, AsyncCompletionCallback callback) { + CreateContext context = new CreateContext(callback, data); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher + .create(this); + caller.setContext(context); + if (data.getType() == DataObjectType.TEMPLATE) { + caller.setCallback(caller.getTarget().createTemplateAsyncCallback(null, null)); + _downloadMonitor.downloadTemplateToStorage(data, caller); + } else if (data.getType() == DataObjectType.VOLUME) { + caller.setCallback(caller.getTarget().createVolumeAsyncCallback(null, null)); + _downloadMonitor.downloadVolumeToStorage(data, caller); + } + } + + protected Void createTemplateAsyncCallback(AsyncCallbackDispatcher callback, + CreateContext context) { + DownloadAnswer answer = callback.getResult(); + DataObject obj = context.data; + DataStore store = obj.getDataStore(); + + TemplateDataStoreVO tmpltStoreVO = _templateStoreDao.findByStoreTemplate(store.getId(), obj.getId()); + if (tmpltStoreVO != null) { + TemplateDataStoreVO updateBuilder = _templateStoreDao.createForUpdate(); + updateBuilder.setDownloadPercent(answer.getDownloadPct()); + updateBuilder.setDownloadState(answer.getDownloadStatus()); + updateBuilder.setLastUpdated(new Date()); + updateBuilder.setErrorString(answer.getErrorString()); + updateBuilder.setJobId(answer.getJobId()); + updateBuilder.setLocalDownloadPath(answer.getDownloadPath()); + updateBuilder.setInstallPath(answer.getInstallPath()); + updateBuilder.setSize(answer.getTemplateSize()); + updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize()); + _templateStoreDao.update(tmpltStoreVO.getId(), updateBuilder); + // update size in vm_template table + VMTemplateVO tmlptUpdater = templateDao.createForUpdate(); + tmlptUpdater.setSize(answer.getTemplateSize()); + templateDao.update(obj.getId(), tmlptUpdater); + } + + AsyncCompletionCallback caller = context.getParentCallback(); + + if (answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR + || answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.ABANDONED + || answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.UNKNOWN) { + CreateCmdResult result = new CreateCmdResult(null, null); + result.setSuccess(false); + result.setResult(answer.getErrorString()); + caller.complete(result); + } else if (answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { + if (answer.getCheckSum() != null) { + VMTemplateVO templateDaoBuilder = templateDao.createForUpdate(); + templateDaoBuilder.setChecksum(answer.getCheckSum()); + templateDao.update(obj.getId(), templateDaoBuilder); + } + + CreateCmdResult result = new CreateCmdResult(null, null); + caller.complete(result); + } + return null; + } + + protected Void createVolumeAsyncCallback(AsyncCallbackDispatcher callback, + CreateContext context) { + DownloadAnswer answer = callback.getResult(); + DataObject obj = context.data; + DataStore store = obj.getDataStore(); + + VolumeDataStoreVO volStoreVO = _volumeStoreDao.findByStoreVolume(store.getId(), obj.getId()); + if (volStoreVO != null) { + VolumeDataStoreVO updateBuilder = _volumeStoreDao.createForUpdate(); + updateBuilder.setDownloadPercent(answer.getDownloadPct()); + updateBuilder.setDownloadState(answer.getDownloadStatus()); + updateBuilder.setLastUpdated(new Date()); + updateBuilder.setErrorString(answer.getErrorString()); + updateBuilder.setJobId(answer.getJobId()); + updateBuilder.setLocalDownloadPath(answer.getDownloadPath()); + updateBuilder.setInstallPath(answer.getInstallPath()); + updateBuilder.setSize(answer.getTemplateSize()); + updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize()); + _volumeStoreDao.update(volStoreVO.getId(), updateBuilder); + // update size in volume table + VolumeVO volUpdater = volumeDao.createForUpdate(); + volUpdater.setSize(answer.getTemplateSize()); + volumeDao.update(obj.getId(), volUpdater); + } + + AsyncCompletionCallback caller = context.getParentCallback(); + + if (answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR + || answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.ABANDONED + || answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.UNKNOWN) { + CreateCmdResult result = new CreateCmdResult(null, null); + result.setSuccess(false); + result.setResult(answer.getErrorString()); + caller.complete(result); + } else if (answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { + CreateCmdResult result = new CreateCmdResult(null, null); + caller.complete(result); + } + return null; + } + + @Override + public void deleteAsync(DataObject data, AsyncCompletionCallback callback) { + DeleteCommand cmd = new DeleteCommand(data.getTO()); + + CommandResult result = new CommandResult(); + try { + EndPoint ep = _epSelector.select(data); + Answer answer = ep.sendMessage(cmd); + if (answer != null && !answer.getResult()) { + result.setResult(answer.getDetails()); + } + } catch (Exception ex) { + s_logger.debug("Unable to destoy " + data.getType().toString() + ": " + data.getId(), ex); + result.setResult(ex.toString()); + } + callback.complete(result); + } + + @Override + public void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback callback) { + } + + @Override + public boolean canCopy(DataObject srcData, DataObject destData) { + return false; + } + + @Override + public void resize(DataObject data, AsyncCompletionCallback callback) { + } +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/ImageStoreDriver.java b/engine/storage/src/org/apache/cloudstack/storage/image/ImageStoreDriver.java new file mode 100644 index 00000000000..85a42ff7c0c --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/image/ImageStoreDriver.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.image; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver; + +import com.cloud.storage.Storage.ImageFormat; + +public interface ImageStoreDriver extends DataStoreDriver { + String createEntityExtractUrl(DataStore store, String installPath, ImageFormat format); +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/TemplateEntityImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/TemplateEntityImpl.java index cbf3a1fdce4..138f57c334e 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/TemplateEntityImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/TemplateEntityImpl.java @@ -25,7 +25,7 @@ import java.util.Map; import org.apache.cloudstack.engine.cloud.entity.api.TemplateEntity; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; -import org.apache.cloudstack.storage.image.datastore.ImageDataStoreInfo; +import org.apache.cloudstack.storage.image.datastore.ImageStoreInfo; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.Storage.ImageFormat; @@ -38,12 +38,12 @@ public class TemplateEntityImpl implements TemplateEntity { this.templateInfo = templateInfo; } - public ImageDataStoreInfo getImageDataStore() { - return (ImageDataStoreInfo)templateInfo.getDataStore(); + public ImageStoreInfo getImageDataStore() { + return (ImageStoreInfo) templateInfo.getDataStore(); } public long getImageDataStoreId() { - return getImageDataStore().getImageDataStoreId(); + return getImageDataStore().getImageStoreId(); } public TemplateInfo getTemplateInfo() { @@ -57,7 +57,7 @@ public class TemplateEntityImpl implements TemplateEntity { @Override public long getId() { - return this.templateInfo.getId(); + return this.templateInfo.getId(); } public String getExternalId() { @@ -103,11 +103,9 @@ public class TemplateEntityImpl implements TemplateEntity { @Override public Boolean isDynamicallyScalable() { - // TODO Auto-generated method stub - return false; + return null; //To change body of implemented methods use File | Settings | File Templates. } - @Override public void addDetail(String name, String value) { // TODO Auto-generated method stub diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageDataStoreHelper.java b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageDataStoreHelper.java deleted file mode 100644 index 3f1632cf13c..00000000000 --- a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageDataStoreHelper.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.image.datastore; - -import java.util.Map; - -import javax.inject.Inject; - -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; -import org.apache.cloudstack.storage.image.db.ImageDataStoreDao; -import org.apache.cloudstack.storage.image.db.ImageDataStoreVO; -import org.springframework.stereotype.Component; - -import com.cloud.utils.exception.CloudRuntimeException; - -@Component -public class ImageDataStoreHelper { - @Inject - ImageDataStoreDao imageStoreDao; - public ImageDataStoreVO createImageDataStore(Map params) { - ImageDataStoreVO store = imageStoreDao.findByName((String)params.get("name")); - if (store != null) { - return store; - } - store = new ImageDataStoreVO(); - store.setName((String)params.get("name")); - store.setProtocol((String)params.get("protocol")); - store.setProviderName((String)params.get("providerName")); - store.setScope((ScopeType)params.get("scope")); - store.setUuid((String)params.get("uuid")); - store = imageStoreDao.persist(store); - return store; - } - - public boolean deleteImageDataStore(long id) { - ImageDataStoreVO store = imageStoreDao.findById(id); - if (store == null) { - throw new CloudRuntimeException("can't find image store:" + id); - } - - imageStoreDao.remove(id); - return true; - } -} diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java new file mode 100644 index 00000000000..a2d61f91fbe --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.image.datastore; + +import java.util.Iterator; +import java.util.Map; +import java.util.UUID; + +import javax.inject.Inject; + +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailVO; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; +import org.springframework.stereotype.Component; + +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ScopeType; +import com.cloud.utils.exception.CloudRuntimeException; + +@Component +public class ImageStoreHelper { + @Inject + ImageStoreDao imageStoreDao; + @Inject + ImageStoreDetailsDao imageStoreDetailsDao; + + public ImageStoreVO createImageStore(Map params) { + ImageStoreVO store = imageStoreDao.findByName((String) params.get("name")); + if (store != null) { + return store; + } + store = new ImageStoreVO(); + store.setProtocol((String) params.get("protocol")); + store.setProviderName((String) params.get("providerName")); + store.setScope((ScopeType) params.get("scope")); + store.setDataCenterId((Long) params.get("zoneId")); + String uuid = (String) params.get("uuid"); + if (uuid != null) { + store.setUuid(uuid); + } else { + store.setUuid(UUID.randomUUID().toString()); + } + store.setName((String) params.get("name")); + if (store.getName() == null) { + store.setName(store.getUuid()); + } + store.setUrl((String) params.get("url")); + store.setRole((DataStoreRole) params.get("role")); + store = imageStoreDao.persist(store); + return store; + } + + public ImageStoreVO createImageStore(Map params, Map details) { + ImageStoreVO store = imageStoreDao.findByName((String) params.get("name")); + if (store != null) { + return store; + } + store = new ImageStoreVO(); + store.setProtocol((String) params.get("protocol")); + store.setProviderName((String) params.get("providerName")); + store.setScope((ScopeType) params.get("scope")); + store.setDataCenterId((Long) params.get("zoneId")); + String uuid = (String) params.get("uuid"); + if (uuid != null) { + store.setUuid(uuid); + } else { + store.setUuid(UUID.randomUUID().toString()); + } + store.setUrl((String) params.get("url")); + store.setName((String) params.get("name")); + if (store.getName() == null) { + store.setName(store.getUuid()); + } + store.setRole((DataStoreRole) params.get("role")); + store = imageStoreDao.persist(store); + + // persist details + if (details != null) { + Iterator keyIter = details.keySet().iterator(); + while (keyIter.hasNext()) { + String key = keyIter.next(); + ImageStoreDetailVO detail = new ImageStoreDetailVO(); + detail.setStoreId(store.getId()); + detail.setName(key); + detail.setValue(details.get(key)); + imageStoreDetailsDao.persist(detail); + } + } + return store; + } + + public boolean deleteImageStore(long id) { + ImageStoreVO store = imageStoreDao.findById(id); + if (store == null) { + throw new CloudRuntimeException("can't find image store:" + id); + } + + imageStoreDao.remove(id); + return true; + } +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageDataStoreManager.java b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreProviderManager.java similarity index 60% rename from engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageDataStoreManager.java rename to engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreProviderManager.java index b6d84cdcef2..be66cc51401 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageDataStoreManager.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreProviderManager.java @@ -21,11 +21,22 @@ package org.apache.cloudstack.storage.image.datastore; import java.util.List; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.storage.image.ImageDataStoreDriver; +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 ImageDataStoreManager { - ImageDataStore getImageDataStore(long dataStoreId); - ImageDataStore getImageDataStore(String uuid); - List getList(); - boolean registerDriver(String uuid, ImageDataStoreDriver driver); +public interface ImageStoreProviderManager { + ImageStoreEntity getImageStore(long dataStoreId); + + ImageStoreEntity getImageStore(String uuid); + + List listImageStores(); + + List listImageStoresByScope(ZoneScope scope); + + List listImageStoreByProvider(String provider); + + List listImageCacheStores(Scope scope); + + boolean registerDriver(String uuid, ImageStoreDriver driver); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDataStoreDao.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDataStoreDao.java deleted file mode 100644 index d7358be9140..00000000000 --- a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDataStoreDao.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.image.db; - -import com.cloud.utils.db.GenericDao; - -public interface ImageDataStoreDao extends GenericDao { - public ImageDataStoreVO findByName(String name); -} diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDataStoreProviderDao.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDataStoreProviderDao.java deleted file mode 100644 index 1b13b7ae4e2..00000000000 --- a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDataStoreProviderDao.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.image.db; - -import com.cloud.utils.db.GenericDao; - -public interface ImageDataStoreProviderDao extends GenericDao { - public ImageDataStoreProviderVO findByName(String name); -} diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDataStoreProviderDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDataStoreProviderDaoImpl.java deleted file mode 100644 index 0e19dbec1b7..00000000000 --- a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDataStoreProviderDaoImpl.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.image.db; - -import org.springframework.stereotype.Component; - -import com.cloud.utils.db.GenericDaoBase; -import com.cloud.utils.db.SearchCriteria2; -import com.cloud.utils.db.SearchCriteriaService; -import com.cloud.utils.db.SearchCriteria.Op; - -@Component -public class ImageDataStoreProviderDaoImpl extends GenericDaoBase implements ImageDataStoreProviderDao { - - public ImageDataStoreProviderDaoImpl() { - } - - @Override - public ImageDataStoreProviderVO findByName(String name) { - SearchCriteriaService service = SearchCriteria2.create(ImageDataStoreProviderVO.class); - service.addAnd(service.getEntity().getName(), Op.EQ, name); - return service.find(); - } -} diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDataStoreProviderVO.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDataStoreProviderVO.java deleted file mode 100644 index 5cc5b8ddcef..00000000000 --- a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDataStoreProviderVO.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.image.db; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Table; -import javax.persistence.TableGenerator; - -@Entity -@Table(name = "image_data_store_provider") -public class ImageDataStoreProviderVO { - @Id - @TableGenerator(name = "image_data_store_provider_sq", table = "sequence", pkColumnName = "name", valueColumnName = "value", pkColumnValue = "image_data_store_provider_seq", allocationSize = 1) - @Column(name = "id", nullable = false) - private long id; - - @Column(name = "name", nullable = false) - private String name; - - public long getId() { - return this.id; - } - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } -} 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 new file mode 100644 index 00000000000..acbbc7d74a8 --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDaoImpl.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.image.db; + +import java.util.List; +import java.util.Map; + +import javax.naming.ConfigurationException; + +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.springframework.stereotype.Component; + +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ScopeType; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + +@Component +public class ImageStoreDaoImpl extends GenericDaoBase implements ImageStoreDao { + private SearchBuilder nameSearch; + private SearchBuilder providerSearch; + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + super.configure(name, params); + + nameSearch = createSearchBuilder(); + nameSearch.and("name", nameSearch.entity().getName(), SearchCriteria.Op.EQ); + nameSearch.and("role", nameSearch.entity().getRole(), SearchCriteria.Op.EQ); + nameSearch.done(); + + providerSearch = createSearchBuilder(); + providerSearch.and("providerName", providerSearch.entity().getProviderName(), SearchCriteria.Op.EQ); + providerSearch.and("role", providerSearch.entity().getProviderName(), SearchCriteria.Op.EQ); + providerSearch.done(); + + return true; + } + + @Override + public ImageStoreVO findByName(String name) { + SearchCriteria sc = nameSearch.create(); + sc.setParameters("name", name); + return findOneBy(sc); + } + + @Override + public List findByProvider(String provider) { + SearchCriteria sc = providerSearch.create(); + sc.setParameters("providerName", provider); + sc.setParameters("role", DataStoreRole.Image); + return listBy(sc); + } + + @Override + public List findByScope(ZoneScope scope) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("role", SearchCriteria.Op.EQ, DataStoreRole.Image); + if (scope.getScopeId() != null) { + SearchCriteria scc = createSearchCriteria(); + scc.addOr("scope", SearchCriteria.Op.EQ, ScopeType.REGION); + scc.addOr("dcId", SearchCriteria.Op.EQ, scope.getScopeId()); + sc.addAnd("scope", SearchCriteria.Op.SC, scc); + } + // we should return all image stores if cross-zone scope is passed + // (scopeId = null) + return listBy(sc); + } + + @Override + public List findImageCacheByScope(ZoneScope scope) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("role", SearchCriteria.Op.EQ, DataStoreRole.ImageCache); + if (scope.getScopeId() != null) { + sc.addAnd("scope", SearchCriteria.Op.EQ, ScopeType.ZONE); + sc.addAnd("dcId", SearchCriteria.Op.EQ, scope.getScopeId()); + } + return listBy(sc); + } + + @Override + public List listImageStores() { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("role", SearchCriteria.Op.EQ, DataStoreRole.Image); + return listBy(sc); + } + +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDetailsDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDetailsDaoImpl.java new file mode 100644 index 00000000000..ad52042bc7c --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDetailsDaoImpl.java @@ -0,0 +1,88 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.image.db; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.ejb.Local; + +import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailVO; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao; +import org.springframework.stereotype.Component; + +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.Transaction; + +@Component +@Local(value = ImageStoreDetailsDao.class) +public class ImageStoreDetailsDaoImpl extends GenericDaoBase implements ImageStoreDetailsDao { + + protected final SearchBuilder storeSearch; + + protected ImageStoreDetailsDaoImpl() { + super(); + storeSearch = createSearchBuilder(); + storeSearch.and("store", storeSearch.entity().getStoreId(), SearchCriteria.Op.EQ); + storeSearch.done(); + } + + @Override + public void update(long storeId, Map details) { + Transaction txn = Transaction.currentTxn(); + SearchCriteria sc = storeSearch.create(); + sc.setParameters("store", storeId); + + txn.start(); + expunge(sc); + for (Map.Entry entry : details.entrySet()) { + ImageStoreDetailVO detail = new ImageStoreDetailVO(storeId, entry.getKey(), entry.getValue()); + persist(detail); + } + txn.commit(); + } + + @Override + public Map getDetails(long storeId) { + SearchCriteria sc = storeSearch.create(); + sc.setParameters("store", storeId); + + List details = listBy(sc); + Map detailsMap = new HashMap(); + for (ImageStoreDetailVO detail : details) { + detailsMap.put(detail.getName(), detail.getValue()); + } + + return detailsMap; + } + + @Override + public void deleteDetails(long storeId) { + SearchCriteria sc = storeSearch.create(); + sc.setParameters("store", storeId); + + List results = search(sc, null); + for (ImageStoreDetailVO result : results) { + remove(result.getId()); + } + + } + +} 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 new file mode 100644 index 00000000000..a198004370d --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java @@ -0,0 +1,168 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.image.db; + +import java.util.Date; +import java.util.List; +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; +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; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.storage.DataStoreRole; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.UpdateBuilder; + +@Component +public class SnapshotDataStoreDaoImpl extends GenericDaoBase implements SnapshotDataStoreDao { + private static final Logger s_logger = Logger.getLogger(SnapshotDataStoreDaoImpl.class); + private SearchBuilder updateStateSearch; + private SearchBuilder storeSearch; + private SearchBuilder destroyedSearch; + private SearchBuilder snapshotSearch; + private SearchBuilder storeSnapshotSearch; + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + super.configure(name, params); + + storeSearch = createSearchBuilder(); + storeSearch.and("store_id", storeSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ); + storeSearch.and("store_role", storeSearch.entity().getRole(), SearchCriteria.Op.EQ); + storeSearch.done(); + + destroyedSearch = createSearchBuilder(); + destroyedSearch.and("store_id", destroyedSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ); + destroyedSearch.and("store_role", destroyedSearch.entity().getRole(), SearchCriteria.Op.EQ); + destroyedSearch.and("state", destroyedSearch.entity().getState(), SearchCriteria.Op.EQ); + destroyedSearch.done(); + + updateStateSearch = this.createSearchBuilder(); + updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ); + updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ); + updateStateSearch.and("updatedCount", updateStateSearch.entity().getUpdatedCount(), Op.EQ); + updateStateSearch.done(); + + snapshotSearch = createSearchBuilder(); + snapshotSearch.and("snapshot_id", snapshotSearch.entity().getSnapshotId(), SearchCriteria.Op.EQ); + snapshotSearch.and("store_role", snapshotSearch.entity().getRole(), SearchCriteria.Op.EQ); + snapshotSearch.done(); + + storeSnapshotSearch = createSearchBuilder(); + storeSnapshotSearch.and("snapshot_id", storeSnapshotSearch.entity().getSnapshotId(), SearchCriteria.Op.EQ); + storeSnapshotSearch.and("store_id", storeSnapshotSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ); + storeSnapshotSearch.and("store_role", storeSnapshotSearch.entity().getRole(), SearchCriteria.Op.EQ); + storeSnapshotSearch.done(); + + return true; + } + + @Override + public boolean updateState(State currentState, Event event, State nextState, DataObjectInStore vo, Object data) { + SnapshotDataStoreVO dataObj = (SnapshotDataStoreVO) vo; + Long oldUpdated = dataObj.getUpdatedCount(); + Date oldUpdatedTime = dataObj.getUpdated(); + + SearchCriteria sc = updateStateSearch.create(); + sc.setParameters("id", dataObj.getId()); + sc.setParameters("state", currentState); + sc.setParameters("updatedCount", dataObj.getUpdatedCount()); + + dataObj.incrUpdatedCount(); + + UpdateBuilder builder = getUpdateBuilder(dataObj); + builder.set(dataObj, "state", nextState); + builder.set(dataObj, "updated", new Date()); + + int rows = update(dataObj, sc); + if (rows == 0 && s_logger.isDebugEnabled()) { + SnapshotDataStoreVO dbVol = findByIdIncludingRemoved(dataObj.getId()); + if (dbVol != null) { + StringBuilder str = new StringBuilder("Unable to update ").append(dataObj.toString()); + str.append(": DB Data={id=").append(dbVol.getId()).append("; state=").append(dbVol.getState()) + .append("; updatecount=").append(dbVol.getUpdatedCount()).append(";updatedTime=") + .append(dbVol.getUpdated()); + str.append(": New Data={id=").append(dataObj.getId()).append("; state=").append(nextState) + .append("; event=").append(event).append("; updatecount=").append(dataObj.getUpdatedCount()) + .append("; updatedTime=").append(dataObj.getUpdated()); + str.append(": stale Data={id=").append(dataObj.getId()).append("; state=").append(currentState) + .append("; event=").append(event).append("; updatecount=").append(oldUpdated) + .append("; updatedTime=").append(oldUpdatedTime); + } else { + s_logger.debug("Unable to update objectIndatastore: id=" + dataObj.getId() + + ", as there is no such object exists in the database anymore"); + } + } + return rows > 0; + } + + @Override + public List listByStoreId(long id, DataStoreRole role) { + SearchCriteria sc = storeSearch.create(); + sc.setParameters("store_id", id); + sc.setParameters("store_role", role); + return listBy(sc); + } + + @Override + public void deletePrimaryRecordsForStore(long id) { + SearchCriteria sc = storeSearch.create(); + sc.setParameters("store_id", id); + Transaction txn = Transaction.currentTxn(); + txn.start(); + remove(sc); + txn.commit(); + } + + @Override + public SnapshotDataStoreVO findByStoreSnapshot(DataStoreRole role, long storeId, long snapshotId) { + SearchCriteria sc = storeSnapshotSearch.create(); + sc.setParameters("store_id", storeId); + sc.setParameters("snapshot_id", snapshotId); + sc.setParameters("store_role", role); + return findOneIncludingRemovedBy(sc); + } + + @Override + public SnapshotDataStoreVO findBySnapshot(long snapshotId, DataStoreRole role) { + SearchCriteria sc = snapshotSearch.create(); + sc.setParameters("snapshot_id", snapshotId); + sc.setParameters("store_role", role); + return findOneBy(sc); + } + + @Override + public List listDestroyed(long id) { + SearchCriteria sc = destroyedSearch.create(); + sc.setParameters("store_id", id); + sc.setParameters("store_role", DataStoreRole.Image); + sc.setParameters("state", ObjectInDataStoreStateMachine.State.Destroyed); + return listBy(sc); + } +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java new file mode 100644 index 00000000000..362f7a6aa96 --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java @@ -0,0 +1,325 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.image.db; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; +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.ObjectInDataStoreStateMachine.Event; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State; +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; + +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.UpdateBuilder; + +import edu.emory.mathcs.backport.java.util.Collections; + +@Component +public class TemplateDataStoreDaoImpl extends GenericDaoBase implements TemplateDataStoreDao { + private static final Logger s_logger = Logger.getLogger(TemplateDataStoreDaoImpl.class); + private SearchBuilder updateStateSearch; + private SearchBuilder storeSearch; + private SearchBuilder templateSearch; + private SearchBuilder templateRoleSearch; + private SearchBuilder storeTemplateSearch; + private SearchBuilder storeTemplateStateSearch; + private SearchBuilder storeTemplateDownloadStatusSearch; + + @Inject + private DataStoreManager _storeMgr; + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + super.configure(name, params); + + storeSearch = createSearchBuilder(); + storeSearch.and("store_id", storeSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ); + storeSearch.and("destroyed", storeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + storeSearch.done(); + + templateSearch = createSearchBuilder(); + templateSearch.and("template_id", templateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + templateSearch.and("destroyed", templateSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + templateSearch.done(); + + templateRoleSearch = createSearchBuilder(); + templateRoleSearch.and("template_id", templateRoleSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + templateRoleSearch.and("store_role", templateRoleSearch.entity().getDataStoreRole(), SearchCriteria.Op.EQ); + templateRoleSearch.and("destroyed", templateRoleSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + templateRoleSearch.done(); + + updateStateSearch = this.createSearchBuilder(); + updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ); + updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ); + updateStateSearch.and("updatedCount", updateStateSearch.entity().getUpdatedCount(), Op.EQ); + updateStateSearch.done(); + + storeTemplateSearch = createSearchBuilder(); + storeTemplateSearch.and("template_id", storeTemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + storeTemplateSearch.and("store_id", storeTemplateSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ); + storeTemplateSearch.and("destroyed", storeTemplateSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + storeTemplateSearch.done(); + + storeTemplateStateSearch = createSearchBuilder(); + storeTemplateStateSearch.and("template_id", storeTemplateStateSearch.entity().getTemplateId(), + SearchCriteria.Op.EQ); + storeTemplateStateSearch.and("store_id", storeTemplateStateSearch.entity().getDataStoreId(), + SearchCriteria.Op.EQ); + storeTemplateStateSearch.and("states", storeTemplateStateSearch.entity().getState(), SearchCriteria.Op.IN); + storeTemplateStateSearch.and("destroyed", storeTemplateStateSearch.entity().getDestroyed(), + SearchCriteria.Op.EQ); + storeTemplateStateSearch.done(); + + storeTemplateDownloadStatusSearch = createSearchBuilder(); + storeTemplateDownloadStatusSearch.and("template_id", + storeTemplateDownloadStatusSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + storeTemplateDownloadStatusSearch.and("store_id", storeTemplateDownloadStatusSearch.entity().getDataStoreId(), + SearchCriteria.Op.EQ); + storeTemplateDownloadStatusSearch.and("downloadState", storeTemplateDownloadStatusSearch.entity() + .getDownloadState(), SearchCriteria.Op.IN); + storeTemplateDownloadStatusSearch.and("destroyed", storeTemplateDownloadStatusSearch.entity().getDestroyed(), + SearchCriteria.Op.EQ); + storeTemplateDownloadStatusSearch.done(); + + storeTemplateSearch = createSearchBuilder(); + storeTemplateSearch.and("store_id", storeTemplateSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ); + storeTemplateSearch.and("template_id", storeTemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + storeTemplateSearch.and("destroyed", storeTemplateSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + storeTemplateSearch.done(); + + return true; + } + + @Override + public boolean updateState(State currentState, Event event, State nextState, DataObjectInStore vo, Object data) { + TemplateDataStoreVO dataObj = (TemplateDataStoreVO) vo; + Long oldUpdated = dataObj.getUpdatedCount(); + Date oldUpdatedTime = dataObj.getUpdated(); + + SearchCriteria sc = updateStateSearch.create(); + sc.setParameters("id", dataObj.getId()); + sc.setParameters("state", currentState); + sc.setParameters("updatedCount", dataObj.getUpdatedCount()); + + dataObj.incrUpdatedCount(); + + UpdateBuilder builder = getUpdateBuilder(dataObj); + builder.set(dataObj, "state", nextState); + builder.set(dataObj, "updated", new Date()); + if (nextState == State.Destroyed) { + builder.set(dataObj, "destroyed", true); + } + + int rows = update(dataObj, sc); + if (rows == 0 && s_logger.isDebugEnabled()) { + TemplateDataStoreVO dbVol = findByIdIncludingRemoved(dataObj.getId()); + if (dbVol != null) { + StringBuilder str = new StringBuilder("Unable to update ").append(dataObj.toString()); + str.append(": DB Data={id=").append(dbVol.getId()).append("; state=").append(dbVol.getState()) + .append("; updatecount=").append(dbVol.getUpdatedCount()).append(";updatedTime=") + .append(dbVol.getUpdated()); + str.append(": New Data={id=").append(dataObj.getId()).append("; state=").append(nextState) + .append("; event=").append(event).append("; updatecount=").append(dataObj.getUpdatedCount()) + .append("; updatedTime=").append(dataObj.getUpdated()); + str.append(": stale Data={id=").append(dataObj.getId()).append("; state=").append(currentState) + .append("; event=").append(event).append("; updatecount=").append(oldUpdated) + .append("; updatedTime=").append(oldUpdatedTime); + } else { + s_logger.debug("Unable to update objectIndatastore: id=" + dataObj.getId() + + ", as there is no such object exists in the database anymore"); + } + } + return rows > 0; + } + + @Override + public List listByStoreId(long id) { + SearchCriteria sc = storeSearch.create(); + sc.setParameters("store_id", id); + sc.setParameters("destroyed", false); + return listIncludingRemovedBy(sc); + } + + @Override + public List listDestroyed(long id) { + SearchCriteria sc = storeSearch.create(); + sc.setParameters("store_id", id); + sc.setParameters("destroyed", true); + return listIncludingRemovedBy(sc); + } + + @Override + public void deletePrimaryRecordsForStore(long id) { + SearchCriteria sc = storeSearch.create(); + sc.setParameters("store_id", id); + Transaction txn = Transaction.currentTxn(); + txn.start(); + remove(sc); + txn.commit(); + } + + @Override + public void deletePrimaryRecordsForTemplate(long templateId) { + SearchCriteria sc = templateSearch.create(); + sc.setParameters("template_id", templateId); + Transaction txn = Transaction.currentTxn(); + txn.start(); + expunge(sc); + txn.commit(); + } + + @Override + public List listByTemplateStore(long templateId, long storeId) { + SearchCriteria sc = storeTemplateSearch.create(); + sc.setParameters("template_id", templateId); + sc.setParameters("store_id", storeId); + sc.setParameters("destroyed", false); + return search(sc, null); + } + + @Override + public List 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); + sc.setParameters("destroyed", false); + return search(sc, null); + } + + @Override + public List listByTemplateStoreDownloadStatus(long templateId, long storeId, Status... status) { + SearchCriteria sc = storeTemplateDownloadStatusSearch.create(); + sc.setParameters("template_id", templateId); + sc.setParameters("store_id", storeId); + sc.setParameters("downloadState", (Object[]) status); + sc.setParameters("destroyed", false); + return search(sc, null); + } + + @Override + public List listByTemplateZoneDownloadStatus(long templateId, Long zoneId, Status... status) { + // get all elgible image stores + List imgStores = this._storeMgr.getImageStoresByScope(new ZoneScope(zoneId)); + if (imgStores != null) { + List result = new ArrayList(); + for (DataStore store : imgStores) { + List sRes = this.listByTemplateStoreDownloadStatus(templateId, store.getId(), + status); + if (sRes != null && sRes.size() > 0) { + result.addAll(sRes); + } + } + return result; + } + return null; + } + + @Override + public TemplateDataStoreVO findByTemplateZoneDownloadStatus(long templateId, Long zoneId, Status... status) { + // get all elgible image stores + List imgStores = this._storeMgr.getImageStoresByScope(new ZoneScope(zoneId)); + if (imgStores != null) { + for (DataStore store : imgStores) { + List sRes = this.listByTemplateStoreDownloadStatus(templateId, store.getId(), + status); + if (sRes != null && sRes.size() > 0) { + Collections.shuffle(sRes); + return sRes.get(0); + } + } + } + return 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); + } + + @Override + public TemplateDataStoreVO findByStoreTemplate(long storeId, long templateId, boolean lock) { + SearchCriteria sc = storeTemplateSearch.create(); + sc.setParameters("store_id", storeId); + sc.setParameters("template_id", templateId); + sc.setParameters("destroyed", false); + if (!lock) + return findOneIncludingRemovedBy(sc); + else + return lockOneRandomRow(sc, true); + } + + @Override + public TemplateDataStoreVO findByTemplate(long templateId, DataStoreRole role) { + SearchCriteria sc = templateRoleSearch.create(); + sc.setParameters("template_id", templateId); + sc.setParameters("store_role", role); + sc.setParameters("destroyed", false); + return findOneIncludingRemovedBy(sc); + } + + @Override + public List listByTemplate(long templateId) { + SearchCriteria sc = templateSearch.create(); + sc.setParameters("template_id", templateId); + sc.setParameters("destroyed", false); + return search(sc, null); + } + + @Override + public TemplateDataStoreVO findByTemplateZone(long templateId, Long zoneId, DataStoreRole role) { + // get all elgible image stores + List imgStores = null; + if (role == DataStoreRole.Image) { + imgStores = this._storeMgr.getImageStoresByScope(new ZoneScope(zoneId)); + } else if (role == DataStoreRole.ImageCache) { + imgStores = this._storeMgr.getImageCacheStores(new ZoneScope(zoneId)); + } + if (imgStores != null) { + for (DataStore store : imgStores) { + List sRes = this.listByTemplateStore(templateId, store.getId()); + if (sRes != null && sRes.size() > 0) { + return sRes.get(0); + } + } + } + return null; + } + +} 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 new file mode 100644 index 00000000000..56020720914 --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/VolumeDataStoreDaoImpl.java @@ -0,0 +1,172 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.image.db; + +import java.util.Date; +import java.util.List; +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.VolumeDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.UpdateBuilder; + +@Component +public class VolumeDataStoreDaoImpl extends GenericDaoBase implements VolumeDataStoreDao { + private static final Logger s_logger = Logger.getLogger(VolumeDataStoreDaoImpl.class); + private SearchBuilder updateStateSearch; + private SearchBuilder volumeSearch; + private SearchBuilder storeSearch; + private SearchBuilder storeVolumeSearch; + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + super.configure(name, params); + + storeSearch = createSearchBuilder(); + storeSearch.and("store_id", storeSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ); + storeSearch.and("destroyed", storeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + storeSearch.done(); + + volumeSearch = createSearchBuilder(); + volumeSearch.and("volume_id", volumeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); + volumeSearch.and("destroyed", volumeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + volumeSearch.done(); + + storeVolumeSearch = createSearchBuilder(); + storeVolumeSearch.and("store_id", storeVolumeSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ); + storeVolumeSearch.and("volume_id", storeVolumeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); + storeVolumeSearch.and("destroyed", storeVolumeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + storeVolumeSearch.done(); + + updateStateSearch = this.createSearchBuilder(); + updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ); + updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ); + updateStateSearch.and("updatedCount", updateStateSearch.entity().getUpdatedCount(), Op.EQ); + updateStateSearch.done(); + return true; + } + + @Override + public boolean updateState(State currentState, Event event, State nextState, DataObjectInStore vo, Object data) { + VolumeDataStoreVO dataObj = (VolumeDataStoreVO) vo; + Long oldUpdated = dataObj.getUpdatedCount(); + Date oldUpdatedTime = dataObj.getUpdated(); + + SearchCriteria sc = updateStateSearch.create(); + sc.setParameters("id", dataObj.getId()); + sc.setParameters("state", currentState); + sc.setParameters("updatedCount", dataObj.getUpdatedCount()); + + dataObj.incrUpdatedCount(); + + UpdateBuilder builder = getUpdateBuilder(dataObj); + builder.set(dataObj, "state", nextState); + builder.set(dataObj, "updated", new Date()); + if (nextState == State.Destroyed) { + builder.set(dataObj, "destroyed", true); + } + + int rows = update(dataObj, sc); + if (rows == 0 && s_logger.isDebugEnabled()) { + VolumeDataStoreVO dbVol = findByIdIncludingRemoved(dataObj.getId()); + if (dbVol != null) { + StringBuilder str = new StringBuilder("Unable to update ").append(dataObj.toString()); + str.append(": DB Data={id=").append(dbVol.getId()).append("; state=").append(dbVol.getState()) + .append("; updatecount=").append(dbVol.getUpdatedCount()).append(";updatedTime=") + .append(dbVol.getUpdated()); + str.append(": New Data={id=").append(dataObj.getId()).append("; state=").append(nextState) + .append("; event=").append(event).append("; updatecount=").append(dataObj.getUpdatedCount()) + .append("; updatedTime=").append(dataObj.getUpdated()); + str.append(": stale Data={id=").append(dataObj.getId()).append("; state=").append(currentState) + .append("; event=").append(event).append("; updatecount=").append(oldUpdated) + .append("; updatedTime=").append(oldUpdatedTime); + } else { + s_logger.debug("Unable to update objectIndatastore: id=" + dataObj.getId() + + ", as there is no such object exists in the database anymore"); + } + } + return rows > 0; + } + + @Override + public List listByStoreId(long id) { + SearchCriteria sc = storeSearch.create(); + sc.setParameters("store_id", id); + sc.setParameters("destroyed", false); + return listIncludingRemovedBy(sc); + } + + @Override + public void deletePrimaryRecordsForStore(long id) { + SearchCriteria sc = storeSearch.create(); + sc.setParameters("store_id", id); + Transaction txn = Transaction.currentTxn(); + txn.start(); + remove(sc); + txn.commit(); + } + + @Override + public VolumeDataStoreVO findByVolume(long volumeId) { + SearchCriteria sc = volumeSearch.create(); + sc.setParameters("volume_id", volumeId); + sc.setParameters("destroyed", false); + return findOneBy(sc); + } + + @Override + public VolumeDataStoreVO findByStoreVolume(long storeId, long volumeId) { + SearchCriteria sc = storeVolumeSearch.create(); + sc.setParameters("store_id", storeId); + sc.setParameters("volume_id", volumeId); + sc.setParameters("destroyed", false); + return findOneBy(sc); + } + + @Override + public VolumeDataStoreVO findByStoreVolume(long storeId, long volumeId, boolean lock) { + SearchCriteria sc = storeVolumeSearch.create(); + sc.setParameters("store_id", storeId); + sc.setParameters("volume_id", volumeId); + sc.setParameters("destroyed", false); + if (!lock) + return findOneIncludingRemovedBy(sc); + else + return lockOneRandomRow(sc, true); + } + + @Override + public List listDestroyed(long id) { + SearchCriteria sc = storeSearch.create(); + sc.setParameters("store_id", id); + sc.setParameters("destroyed", true); + return listIncludingRemovedBy(sc); + } +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/motion/ImageMotionService.java b/engine/storage/src/org/apache/cloudstack/storage/image/motion/ImageMotionService.java index 908d6d52c20..b00e95d4d7d 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/motion/ImageMotionService.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/motion/ImageMotionService.java @@ -18,13 +18,13 @@ */ package org.apache.cloudstack.storage.image.motion; -import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; -import org.apache.cloudstack.storage.db.ObjectInDataStoreVO; -import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreInfo; +import org.apache.cloudstack.storage.command.CommandResult; public interface ImageMotionService { - void copyTemplateAsync(TemplateInfo destTemplate, TemplateInfo srcTemplate, AsyncCompletionCallback callback); + void copyTemplateAsync(TemplateInfo destTemplate, TemplateInfo srcTemplate, + AsyncCompletionCallback callback); + boolean copyIso(String isoUri, String destIsoUri); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java b/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java deleted file mode 100644 index cb7940e94e4..00000000000 --- a/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java +++ /dev/null @@ -1,812 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.motion; - -import java.util.Date; -import java.util.List; -import java.util.Map; - -import javax.inject.Inject; - -import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType; -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.SnapshotInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; -import org.apache.cloudstack.framework.async.AsyncCompletionCallback; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - -import com.cloud.agent.AgentManager; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.BackupSnapshotAnswer; -import com.cloud.agent.api.BackupSnapshotCommand; -import com.cloud.agent.api.Command; -import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand; -import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand; -import com.cloud.agent.api.CreateVolumeFromSnapshotAnswer; -import com.cloud.agent.api.CreateVolumeFromSnapshotCommand; -import com.cloud.agent.api.UpgradeSnapshotCommand; -import com.cloud.agent.api.storage.CopyVolumeAnswer; -import com.cloud.agent.api.storage.CopyVolumeCommand; -import com.cloud.agent.api.storage.CreateAnswer; -import com.cloud.agent.api.storage.CreateCommand; -import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer; -import com.cloud.agent.api.storage.MigrateVolumeAnswer; -import com.cloud.agent.api.storage.MigrateVolumeCommand; -import com.cloud.agent.api.to.S3TO; -import com.cloud.agent.api.to.StorageFilerTO; -import com.cloud.agent.api.to.SwiftTO; -import com.cloud.agent.api.to.VirtualMachineTO; -import com.cloud.configuration.Config; -import com.cloud.configuration.dao.ConfigurationDao; -import com.cloud.exception.AgentUnavailableException; -import com.cloud.exception.OperationTimedoutException; -import com.cloud.exception.StorageUnavailableException; -import com.cloud.host.Host; -import com.cloud.host.HostVO; -import com.cloud.host.dao.HostDao; -import com.cloud.server.ManagementServer; -import com.cloud.storage.DiskOfferingVO; -import com.cloud.storage.SnapshotVO; -import com.cloud.storage.Storage.ImageFormat; -import com.cloud.storage.StorageManager; -import com.cloud.storage.StoragePool; -import com.cloud.storage.VMTemplateHostVO; -import com.cloud.storage.VMTemplateStoragePoolVO; -import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; -import com.cloud.storage.VMTemplateVO; -import com.cloud.storage.VolumeHostVO; -import com.cloud.storage.VolumeManager; -import com.cloud.storage.VolumeVO; -import com.cloud.storage.dao.DiskOfferingDao; -import com.cloud.storage.dao.SnapshotDao; -import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VMTemplateHostDao; -import com.cloud.storage.dao.VMTemplatePoolDao; -import com.cloud.storage.dao.VolumeDao; -import com.cloud.storage.dao.VolumeHostDao; -import com.cloud.storage.s3.S3Manager; -import com.cloud.storage.snapshot.SnapshotManager; -import com.cloud.storage.swift.SwiftManager; -import com.cloud.template.TemplateManager; -import com.cloud.utils.NumbersUtil; -import com.cloud.utils.db.DB; -import com.cloud.utils.db.Transaction; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.vm.DiskProfile; -import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.dao.VMInstanceDao; - -@Component -public class AncientDataMotionStrategy implements DataMotionStrategy { - private static final Logger s_logger = Logger - .getLogger(AncientDataMotionStrategy.class); - @Inject - TemplateManager templateMgr; - @Inject - VolumeHostDao volumeHostDao; - @Inject - HostDao hostDao; - @Inject - ConfigurationDao configDao; - @Inject - StorageManager storageMgr; - @Inject - AgentManager agentMgr; - @Inject - VolumeDao volDao; - @Inject - VMInstanceDao instanceDao; - @Inject - VMTemplateDao templateDao; - @Inject - SnapshotManager snapshotMgr; - @Inject - SnapshotDao snapshotDao; - @Inject - PrimaryDataStoreDao primaryDataStoreDao; - @Inject - DataStoreManager dataStoreMgr; - @Inject - VMTemplateHostDao templateHostDao; - @Inject DiskOfferingDao diskOfferingDao; - @Inject VMTemplatePoolDao templatePoolDao; - @Inject - VolumeManager volumeMgr; - @Inject - private SwiftManager _swiftMgr; - @Inject - private S3Manager _s3Mgr; - @Inject - private ManagementServer _mgmtServer; - - protected boolean _executeInSequence; - - - @Override - public boolean canHandle(DataObject srcData, DataObject destData) { - // TODO Auto-generated method stub - return true; - } - - @Override - public boolean canHandle(Map volumeMap, Host srcHost, Host destHost) { - return false; - } - - @DB - protected Answer copyVolumeFromImage(DataObject srcData, DataObject destData) { - String value = configDao.getValue(Config.RecreateSystemVmEnabled.key()); - int _copyvolumewait = NumbersUtil.parseInt(value, - Integer.parseInt(Config.CopyVolumeWait.getDefaultValue())); - - VolumeHostVO volumeHostVO = volumeHostDao.findByVolumeId(srcData - .getId()); - HostVO secStorage = hostDao.findById(volumeHostVO.getHostId()); - String secondaryStorageURL = secStorage.getStorageUrl(); - String[] volumePath = volumeHostVO.getInstallPath().split("/"); - String volumeUUID = volumePath[volumePath.length - 1].split("\\.")[0]; - StoragePool destPool = (StoragePool) destData.getDataStore(); - CopyVolumeCommand cvCmd = new CopyVolumeCommand(srcData.getId(), - volumeUUID, destPool, secondaryStorageURL, false, - _copyvolumewait, _mgmtServer.getExecuteInSequence()); - CopyVolumeAnswer cvAnswer = null; - String errMsg = null; - try { - cvAnswer = (CopyVolumeAnswer) this.storageMgr.sendToPool(destPool, - cvCmd); - } catch (StorageUnavailableException e1) { - s_logger.debug("Failed to copy volume " + srcData.getId() + " to " - + destData.getId(), e1); - errMsg = e1.toString(); - } - - if (cvAnswer == null || !cvAnswer.getResult()) { - errMsg = cvAnswer.getDetails(); - } - - VolumeVO vol = this.volDao.findById(destData.getId()); - Transaction txn = Transaction.currentTxn(); - txn.start(); - vol.setPath(cvAnswer.getVolumePath()); - vol.setFolder(destPool.getPath()); - vol.setPodId(destPool.getPodId()); - vol.setPoolId(destPool.getId()); - vol.setPodId(destPool.getPodId()); - - this.volDao.update(vol.getId(), vol); - volumeHostDao.remove(volumeHostVO.getId()); - txn.commit(); - return cvAnswer; - } - - private Answer copyTemplate(DataObject srcData, DataObject destData) { - VMTemplateVO template = this.templateDao.findById(srcData.getId()); - templateMgr.prepareTemplateForCreate(template, - (StoragePool) destData.getDataStore()); - return null; - } - - protected Answer copyFromSnapshot(DataObject snapObj, DataObject volObj) { - SnapshotVO snapshot = this.snapshotDao.findById(snapObj.getId()); - StoragePool pool = (StoragePool) volObj.getDataStore(); - String vdiUUID = null; - Long snapshotId = snapshot.getId(); - Long volumeId = snapshot.getVolumeId(); - Long dcId = snapshot.getDataCenterId(); - String secondaryStoragePoolUrl = this.snapshotMgr - .getSecondaryStorageURL(snapshot); - long accountId = snapshot.getAccountId(); - - String backedUpSnapshotUuid = snapshot.getBackupSnapshotId(); - snapshot = snapshotDao.findById(snapshotId); - if (snapshot.getVersion().trim().equals("2.1")) { - VolumeVO volume = this.volDao.findByIdIncludingRemoved(volumeId); - if (volume == null) { - throw new CloudRuntimeException("failed to upgrade snapshot " - + snapshotId + " due to unable to find orignal volume:" - + volumeId + ", try it later "); - } - if (volume.getTemplateId() == null) { - snapshotDao.updateSnapshotVersion(volumeId, "2.1", "2.2"); - } else { - VMTemplateVO template = templateDao - .findByIdIncludingRemoved(volume.getTemplateId()); - if (template == null) { - throw new CloudRuntimeException( - "failed to upgrade snapshot " - + snapshotId - + " due to unalbe to find orignal template :" - + volume.getTemplateId() - + ", try it later "); - } - Long templateId = template.getId(); - Long tmpltAccountId = template.getAccountId(); - if (!snapshotDao.lockInLockTable(snapshotId.toString(), 10)) { - throw new CloudRuntimeException( - "failed to upgrade snapshot " - + snapshotId - + " due to this snapshot is being used, try it later "); - } - UpgradeSnapshotCommand cmd = new UpgradeSnapshotCommand(null, - secondaryStoragePoolUrl, dcId, accountId, volumeId, - templateId, tmpltAccountId, null, - snapshot.getBackupSnapshotId(), snapshot.getName(), - "2.1"); - Answer answer = null; - try { - answer = this.storageMgr.sendToPool(pool, cmd); - } catch (StorageUnavailableException e) { - } finally { - snapshotDao.unlockFromLockTable(snapshotId.toString()); - } - if ((answer != null) && answer.getResult()) { - snapshotDao.updateSnapshotVersion(volumeId, "2.1", "2.2"); - } else { - throw new CloudRuntimeException("Unable to upgrade snapshot from 2.1 to 2.2 for " - + snapshot.getId()); - } - } - } - String basicErrMsg = "Failed to create volume from " - + snapshot.getName() + " on pool " + pool; - - try { - if (snapshot.getSwiftId() != null && snapshot.getSwiftId() != 0) { - snapshotMgr.downloadSnapshotsFromSwift(snapshot); - } else if (snapshot.getS3Id() != null && snapshot.getS3Id() != 0) { - snapshotMgr.downloadSnapshotsFromS3(snapshot); - } - String value = configDao - .getValue(Config.CreateVolumeFromSnapshotWait.toString()); - int _createVolumeFromSnapshotWait = NumbersUtil.parseInt(value, - Integer.parseInt(Config.CreateVolumeFromSnapshotWait - .getDefaultValue())); - CreateVolumeFromSnapshotCommand createVolumeFromSnapshotCommand = new CreateVolumeFromSnapshotCommand( - pool, secondaryStoragePoolUrl, dcId, accountId, volumeId, - backedUpSnapshotUuid, snapshot.getName(), - _createVolumeFromSnapshotWait); - CreateVolumeFromSnapshotAnswer answer; - if (!snapshotDao.lockInLockTable(snapshotId.toString(), 10)) { - throw new CloudRuntimeException("failed to create volume from " - + snapshotId - + " due to this snapshot is being used, try it later "); - } - answer = (CreateVolumeFromSnapshotAnswer) this.storageMgr - .sendToPool(pool, createVolumeFromSnapshotCommand); - if (answer != null && answer.getResult()) { - vdiUUID = answer.getVdi(); - VolumeVO vol = this.volDao.findById(volObj.getId()); - vol.setPath(vdiUUID); - this.volDao.update(vol.getId(), vol); - return null; - } else { - s_logger.error(basicErrMsg + " due to " - + ((answer == null) ? "null" : answer.getDetails())); - throw new CloudRuntimeException(basicErrMsg); - } - } catch (StorageUnavailableException e) { - s_logger.error(basicErrMsg, e); - throw new CloudRuntimeException(basicErrMsg); - } finally { - if (snapshot.getSwiftId() != null) { - snapshotMgr.deleteSnapshotsDirForVolume( - secondaryStoragePoolUrl, dcId, accountId, volumeId); - } - } - } - - protected Answer cloneVolume(DataObject template, DataObject volume) { - VolumeInfo volInfo = (VolumeInfo)volume; - DiskOfferingVO offering = diskOfferingDao.findById(volInfo.getDiskOfferingId()); - VMTemplateStoragePoolVO tmpltStoredOn = templatePoolDao.findByPoolTemplate(template.getDataStore().getId(), template.getId()); - - DiskProfile diskProfile = new DiskProfile(volInfo, offering, - null); - CreateCommand cmd = new CreateCommand(diskProfile, - tmpltStoredOn.getLocalDownloadPath(), - new StorageFilerTO((StoragePool)template.getDataStore()), _mgmtServer.getExecuteInSequence()); - Answer answer = null; - StoragePool pool = (StoragePool)volume.getDataStore(); - String errMsg = null; - try { - answer = storageMgr.sendToPool(pool, null, cmd); - } catch (StorageUnavailableException e) { - s_logger.debug("Failed to send to storage pool", e); - throw new CloudRuntimeException("Failed to send to storage pool", e); - } - - if (answer.getResult()) { - VolumeVO vol = this.volDao.findById(volume.getId()); - CreateAnswer createAnswer = (CreateAnswer) answer; - vol.setFolder(pool.getPath()); - vol.setPath(createAnswer.getVolume().getPath()); - vol.setSize(createAnswer.getVolume().getSize()); - vol.setPoolType(pool.getPoolType()); - vol.setPoolId(pool.getId()); - vol.setPodId(pool.getPodId()); - this.volDao.update(vol.getId(), vol); - - } else { - if (tmpltStoredOn != null - && (answer instanceof CreateAnswer) - && ((CreateAnswer) answer) - .templateReloadRequested()) { - if (!templateMgr - .resetTemplateDownloadStateOnPool(tmpltStoredOn - .getId())) { - - } - } - errMsg = answer.getDetails(); - } - - return answer; - } - - protected Answer copyVolumeBetweenPools(DataObject srcData, DataObject destData) { - VolumeInfo volume = (VolumeInfo)srcData; - VolumeInfo destVolume = (VolumeInfo)destData; - String secondaryStorageURL = this.templateMgr.getSecondaryStorageURL(volume - .getDataCenterId()); - StoragePool srcPool = (StoragePool)this.dataStoreMgr.getDataStore(volume - .getPoolId(), DataStoreRole.Primary); - - StoragePool destPool = (StoragePool)this.dataStoreMgr.getDataStore(destVolume.getPoolId(), DataStoreRole.Primary); - - String value = this.configDao.getValue(Config.CopyVolumeWait.toString()); - int _copyvolumewait = NumbersUtil.parseInt(value, - Integer.parseInt(Config.CopyVolumeWait.getDefaultValue())); - CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), - volume.getPath(), srcPool, secondaryStorageURL, true, - _copyvolumewait, _mgmtServer.getExecuteInSequence()); - CopyVolumeAnswer cvAnswer; - try { - cvAnswer = (CopyVolumeAnswer) this.storageMgr.sendToPool(srcPool, cvCmd); - } catch (StorageUnavailableException e1) { - throw new CloudRuntimeException( - "Failed to copy the volume from the source primary storage pool to secondary storage.", - e1); - } - - if (cvAnswer == null || !cvAnswer.getResult()) { - throw new CloudRuntimeException( - "Failed to copy the volume from the source primary storage pool to secondary storage."); - } - - String secondaryStorageVolumePath = cvAnswer.getVolumePath(); - - cvCmd = new CopyVolumeCommand(volume.getId(), - secondaryStorageVolumePath, destPool, - secondaryStorageURL, false, _copyvolumewait, _mgmtServer.getExecuteInSequence()); - try { - cvAnswer = (CopyVolumeAnswer) this.storageMgr.sendToPool(destPool, cvCmd); - } catch (StorageUnavailableException e1) { - throw new CloudRuntimeException( - "Failed to copy the volume from secondary storage to the destination primary storage pool."); - } - - if (cvAnswer == null || !cvAnswer.getResult()) { - throw new CloudRuntimeException( - "Failed to copy the volume from secondary storage to the destination primary storage pool."); - } - - VolumeVO destVol = this.volDao.findById(destVolume.getId()); - destVol.setPath(cvAnswer.getVolumePath()); - this.volDao.update(destVol.getId(), destVol); - return cvAnswer; - } - - protected Answer migrateVolumeToPool(DataObject srcData, DataStore destStore) { - VolumeInfo volume = (VolumeInfo)srcData; - Long instanceId = volume.getInstanceId(); - StoragePool destPool = (StoragePool)this.dataStoreMgr.getDataStore(destStore.getId(), DataStoreRole.Primary); - MigrateVolumeAnswer answer = null; - VMInstanceVO vmInstance = null; - if (instanceId != null) { - vmInstance = instanceDao.findById(instanceId); - } - - Long hostId = null; - if (vmInstance != null) { - hostId = vmInstance.getHostId(); - } - - try { - if (hostId != null) { - MigrateVolumeCommand command = new MigrateVolumeCommand(volume.getId(), volume.getPath(), destPool); - answer = (MigrateVolumeAnswer) this.agentMgr.send(hostId, command); - } - } catch (OperationTimedoutException e) { - s_logger.error("Operation timed out on storage motion for volume " + volume, e); - throw new CloudRuntimeException("Failed to live migrate volume " + volume + " to storage pool " + - destPool, e); - } catch (AgentUnavailableException e) { - s_logger.error("Agent unavailable exception while doing storage motion for volume " + volume, e); - throw new CloudRuntimeException("Failed to live migrate volume " + volume + " to storage pool " + - destPool, e); - } - - if (answer == null || !answer.getResult()) { - throw new CloudRuntimeException("Failed to migrate volume " + volume + " to storage pool " + destPool); - } else { - // Update the volume details after migration. - VolumeVO volumeVo = this.volDao.findById(volume.getId()); - Long oldPoolId = volume.getPoolId(); - volumeVo.setPath(answer.getVolumePath()); - volumeVo.setFolder(destPool.getPath()); - volumeVo.setPodId(destPool.getPodId()); - volumeVo.setPoolId(destPool.getId()); - volumeVo.setLastPoolId(oldPoolId); - this.volDao.update(volume.getId(), volumeVo); - } - - return answer; - } - - @Override - public Void copyAsync(DataObject srcData, DataObject destData, - AsyncCompletionCallback callback) { - Answer answer = null; - String errMsg = null; - try { - if (destData.getType() == DataObjectType.VOLUME - && srcData.getType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Image) { - answer = copyVolumeFromImage(srcData, destData); - } else if (destData.getType() == DataObjectType.TEMPLATE - && srcData.getType() == DataObjectType.TEMPLATE) { - answer = copyTemplate(srcData, destData); - } else if (srcData.getType() == DataObjectType.SNAPSHOT - && destData.getType() == DataObjectType.VOLUME) { - answer = copyFromSnapshot(srcData, destData); - } else if (srcData.getType() == DataObjectType.SNAPSHOT - && destData.getType() == DataObjectType.TEMPLATE) { - answer = createTemplateFromSnashot(srcData, destData); - } else if (srcData.getType() == DataObjectType.VOLUME - && destData.getType() == DataObjectType.TEMPLATE) { - answer = createTemplateFromVolume(srcData, destData); - } else if (srcData.getType() == DataObjectType.TEMPLATE - && destData.getType() == DataObjectType.VOLUME) { - answer = cloneVolume(srcData, destData); - } else if (destData.getType() == DataObjectType.VOLUME - && srcData.getType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Primary) { - if (srcData.getId() == destData.getId()) { - // The volume has to be migrated across storage pools. - answer = migrateVolumeToPool(srcData, destData.getDataStore()); - } else { - answer = copyVolumeBetweenPools(srcData, destData); - } - } else if (srcData.getType() == DataObjectType.SNAPSHOT && - destData.getType() == DataObjectType.SNAPSHOT) { - answer = copySnapshot(srcData, destData); - } - } catch (Exception e) { - s_logger.debug("copy failed", e); - errMsg = e.toString(); - } - CopyCommandResult result = new CopyCommandResult(null, answer); - result.setResult(errMsg); - callback.complete(result); - - return null; - } - - @Override - public Void copyAsync(Map volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, - AsyncCompletionCallback callback) { - CopyCommandResult result = new CopyCommandResult(null, null); - result.setResult("Unsupported operation requested for copying data."); - callback.complete(result); - - return null; - } - - @DB - protected Answer createTemplateFromSnashot(DataObject srcData, - DataObject destData) { - long snapshotId = srcData.getId(); - SnapshotVO snapshot = snapshotDao.findById(snapshotId); - if (snapshot == null) { - throw new CloudRuntimeException("Unable to find Snapshot for Id " - + srcData.getId()); - } - Long zoneId = snapshot.getDataCenterId(); - HostVO secondaryStorageHost = this.templateMgr - .getSecondaryStorageHost(zoneId); - String secondaryStorageURL = snapshotMgr - .getSecondaryStorageURL(snapshot); - VMTemplateVO template = this.templateDao.findById(destData.getId()); - String name = template.getName(); - String backupSnapshotUUID = snapshot.getBackupSnapshotId(); - if (backupSnapshotUUID == null) { - throw new CloudRuntimeException( - "Unable to create private template from snapshot " - + snapshotId - + " due to there is no backupSnapshotUUID for this snapshot"); - } - - Long dcId = snapshot.getDataCenterId(); - Long accountId = snapshot.getAccountId(); - Long volumeId = snapshot.getVolumeId(); - - String origTemplateInstallPath = null; - List pools = this.storageMgr - .ListByDataCenterHypervisor(zoneId, - snapshot.getHypervisorType()); - if (pools == null || pools.size() == 0) { - throw new CloudRuntimeException( - "Unable to find storage pools in zone " + zoneId); - } - StoragePoolVO poolvo = pools.get(0); - StoragePool pool = (StoragePool) this.dataStoreMgr.getDataStore( - poolvo.getId(), DataStoreRole.Primary); - if (snapshot.getVersion() != null - && snapshot.getVersion().equalsIgnoreCase("2.1")) { - VolumeVO volume = this.volDao.findByIdIncludingRemoved(volumeId); - if (volume == null) { - throw new CloudRuntimeException("failed to upgrade snapshot " - + snapshotId + " due to unable to find orignal volume:" - + volumeId + ", try it later "); - } - if (volume.getTemplateId() == null) { - snapshotDao.updateSnapshotVersion(volumeId, "2.1", "2.2"); - } else { - template = templateDao.findByIdIncludingRemoved(volume - .getTemplateId()); - if (template == null) { - throw new CloudRuntimeException( - "failed to upgrade snapshot " - + snapshotId - + " due to unalbe to find orignal template :" - + volume.getTemplateId() - + ", try it later "); - } - Long origTemplateId = template.getId(); - Long origTmpltAccountId = template.getAccountId(); - if (!this.volDao.lockInLockTable(volumeId.toString(), 10)) { - throw new CloudRuntimeException( - "failed to upgrade snapshot " + snapshotId - + " due to volume:" + volumeId - + " is being used, try it later "); - } - UpgradeSnapshotCommand cmd = new UpgradeSnapshotCommand(null, - secondaryStorageURL, dcId, accountId, volumeId, - origTemplateId, origTmpltAccountId, null, - snapshot.getBackupSnapshotId(), snapshot.getName(), - "2.1"); - if (!this.volDao.lockInLockTable(volumeId.toString(), 10)) { - throw new CloudRuntimeException( - "Creating template failed due to volume:" - + volumeId - + " is being used, try it later "); - } - Answer answer = null; - try { - answer = this.storageMgr.sendToPool(pool, cmd); - cmd = null; - } catch (StorageUnavailableException e) { - } finally { - this.volDao.unlockFromLockTable(volumeId.toString()); - } - if ((answer != null) && answer.getResult()) { - snapshotDao.updateSnapshotVersion(volumeId, "2.1", "2.2"); - } else { - throw new CloudRuntimeException( - "Unable to upgrade snapshot"); - } - } - } - if (snapshot.getSwiftId() != null && snapshot.getSwiftId() != 0) { - snapshotMgr.downloadSnapshotsFromSwift(snapshot); - } - String value = configDao - .getValue(Config.CreatePrivateTemplateFromSnapshotWait - .toString()); - int _createprivatetemplatefromsnapshotwait = NumbersUtil.parseInt( - value, Integer - .parseInt(Config.CreatePrivateTemplateFromSnapshotWait - .getDefaultValue())); - - CreatePrivateTemplateFromSnapshotCommand cmd = new CreatePrivateTemplateFromSnapshotCommand( - pool, secondaryStorageURL, dcId, accountId, - snapshot.getVolumeId(), backupSnapshotUUID, snapshot.getName(), - origTemplateInstallPath, template.getId(), name, - _createprivatetemplatefromsnapshotwait); - - return sendCommand(cmd, pool, template.getId(), dcId, - secondaryStorageHost.getId()); - } - - @DB - protected Answer sendCommand(Command cmd, StoragePool pool, - long templateId, long zoneId, long hostId) { - - CreatePrivateTemplateAnswer answer = null; - try { - answer = (CreatePrivateTemplateAnswer) this.storageMgr.sendToPool( - pool, cmd); - } catch (StorageUnavailableException e) { - throw new CloudRuntimeException( - "Failed to execute CreatePrivateTemplateFromSnapshotCommand", - e); - } - - if (answer == null || !answer.getResult()) { - return answer; - } - - VMTemplateVO privateTemplate = templateDao.findById(templateId); - String answerUniqueName = answer.getUniqueName(); - if (answerUniqueName != null) { - privateTemplate.setUniqueName(answerUniqueName); - } - ImageFormat format = answer.getImageFormat(); - if (format != null) { - privateTemplate.setFormat(format); - } else { - // This never occurs. - // Specify RAW format makes it unusable for snapshots. - privateTemplate.setFormat(ImageFormat.RAW); - } - - String checkSum = this.templateMgr - .getChecksum(hostId, answer.getPath()); - - - - privateTemplate.setChecksum(checkSum); - templateDao.update(privateTemplate.getId(), privateTemplate); - - // add template zone ref for this template - templateDao.addTemplateToZone(privateTemplate, zoneId); - VMTemplateHostVO templateHostVO = new VMTemplateHostVO(hostId, - privateTemplate.getId()); - templateHostVO.setDownloadPercent(100); - templateHostVO.setDownloadState(Status.DOWNLOADED); - templateHostVO.setInstallPath(answer.getPath()); - templateHostVO.setLastUpdated(new Date()); - templateHostVO.setSize(answer.getVirtualSize()); - templateHostVO.setPhysicalSize(answer.getphysicalSize()); - - templateHostDao.persist(templateHostVO); - - return answer; - } - - private Answer createTemplateFromVolume(DataObject srcObj, - DataObject destObj) { - long volumeId = srcObj.getId(); - VolumeVO volume = this.volDao.findById(volumeId); - if (volume == null) { - throw new CloudRuntimeException("Unable to find volume for Id " - + volumeId); - } - long accountId = volume.getAccountId(); - - String vmName = this.volumeMgr.getVmNameOnVolume(volume); - Long zoneId = volume.getDataCenterId(); - HostVO secondaryStorageHost = this.templateMgr - .getSecondaryStorageHost(zoneId); - if (secondaryStorageHost == null) { - throw new CloudRuntimeException( - "Can not find the secondary storage for zoneId " + zoneId); - } - String secondaryStorageURL = secondaryStorageHost.getStorageUrl(); - VMTemplateVO template = this.templateDao.findById(destObj.getId()); - StoragePool pool = (StoragePool) this.dataStoreMgr.getDataStore( - volume.getPoolId(), DataStoreRole.Primary); - String value = configDao - .getValue(Config.CreatePrivateTemplateFromVolumeWait.toString()); - int _createprivatetemplatefromvolumewait = NumbersUtil.parseInt(value, - Integer.parseInt(Config.CreatePrivateTemplateFromVolumeWait - .getDefaultValue())); - - CreatePrivateTemplateFromVolumeCommand cmd = new CreatePrivateTemplateFromVolumeCommand( - pool, secondaryStorageURL, destObj.getId(), accountId, - template.getName(), template.getUniqueName(), volume.getPath(), - vmName, _createprivatetemplatefromvolumewait); - - return sendCommand(cmd, pool, template.getId(), zoneId, - secondaryStorageHost.getId()); - } - - private HostVO getSecHost(long volumeId, long dcId) { - Long id = snapshotDao.getSecHostId(volumeId); - if ( id != null) { - return hostDao.findById(id); - } - return this.templateMgr.getSecondaryStorageHost(dcId); - } - - protected Answer copySnapshot(DataObject srcObject, DataObject destObject) { - SnapshotInfo srcSnapshot = (SnapshotInfo)srcObject; - VolumeInfo baseVolume = srcSnapshot.getBaseVolume(); - Long dcId = baseVolume.getDataCenterId(); - Long accountId = baseVolume.getAccountId(); - - HostVO secHost = getSecHost(baseVolume.getId(), baseVolume.getDataCenterId()); - Long secHostId = secHost.getId(); - String secondaryStoragePoolUrl = secHost.getStorageUrl(); - String snapshotUuid = srcSnapshot.getPath(); - // In order to verify that the snapshot is not empty, - // we check if the parent of the snapshot is not the same as the parent of the previous snapshot. - // We pass the uuid of the previous snapshot to the plugin to verify this. - SnapshotVO prevSnapshot = null; - String prevSnapshotUuid = null; - String prevBackupUuid = null; - - - SwiftTO swift = _swiftMgr.getSwiftTO(); - S3TO s3 = _s3Mgr.getS3TO(); - - long prevSnapshotId = srcSnapshot.getPrevSnapshotId(); - if (prevSnapshotId > 0) { - prevSnapshot = snapshotDao.findByIdIncludingRemoved(prevSnapshotId); - if ( prevSnapshot.getBackupSnapshotId() != null && swift == null) { - if (prevSnapshot.getVersion() != null && prevSnapshot.getVersion().equals("2.2")) { - prevBackupUuid = prevSnapshot.getBackupSnapshotId(); - prevSnapshotUuid = prevSnapshot.getPath(); - } - } else if ((prevSnapshot.getSwiftId() != null && swift != null) - || (prevSnapshot.getS3Id() != null && s3 != null)) { - prevBackupUuid = prevSnapshot.getBackupSnapshotId(); - prevSnapshotUuid = prevSnapshot.getPath(); - } - } - boolean isVolumeInactive = this.volumeMgr.volumeInactive(baseVolume); - String vmName = this.volumeMgr.getVmNameOnVolume(baseVolume); - StoragePool srcPool = (StoragePool)dataStoreMgr.getPrimaryDataStore(baseVolume.getPoolId()); - String value = configDao.getValue(Config.BackupSnapshotWait.toString()); - int _backupsnapshotwait = NumbersUtil.parseInt(value, Integer.parseInt(Config.BackupSnapshotWait.getDefaultValue())); - BackupSnapshotCommand backupSnapshotCommand = new BackupSnapshotCommand(secondaryStoragePoolUrl, dcId, accountId, baseVolume.getId(), srcSnapshot.getId(), secHostId, baseVolume.getPath(), srcPool, snapshotUuid, - srcSnapshot.getName(), prevSnapshotUuid, prevBackupUuid, isVolumeInactive, vmName, _backupsnapshotwait); - - if ( swift != null ) { - backupSnapshotCommand.setSwift(swift); - } else if (s3 != null) { - backupSnapshotCommand.setS3(s3); - } - BackupSnapshotAnswer answer = (BackupSnapshotAnswer) this.snapshotMgr.sendToPool(baseVolume, backupSnapshotCommand); - if (answer != null && answer.getResult()) { - SnapshotVO snapshotVO = this.snapshotDao.findById(srcSnapshot.getId()); - if (backupSnapshotCommand.getSwift() != null ) { - snapshotVO.setSwiftId(swift.getId()); - snapshotVO.setBackupSnapshotId(answer.getBackupSnapshotName()); - } else if (backupSnapshotCommand.getS3() != null) { - snapshotVO.setS3Id(s3.getId()); - snapshotVO.setBackupSnapshotId(answer.getBackupSnapshotName()); - } else { - snapshotVO.setSecHostId(secHost.getId()); - snapshotVO.setBackupSnapshotId(answer.getBackupSnapshotName()); - } - if (answer.isFull()) { - snapshotVO.setPrevSnapshotId(0L); - } - this.snapshotDao.update(srcSnapshot.getId(), snapshotVO); - } - return answer; - } - -} diff --git a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java b/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java index 0a91186aaab..fb3ec48d744 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java @@ -27,166 +27,160 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; public class SnapshotEntityImpl implements SnapshotEntity { - @Override - public String getUuid() { - // TODO Auto-generated method stub - return null; - } + @Override + public String getUuid() { + // TODO Auto-generated method stub + return null; + } - @Override - public long getId() { - // TODO Auto-generated method stub - return 0; - } + @Override + public long getId() { + // TODO Auto-generated method stub + return 0; + } - @Override - public String getCurrentState() { - // TODO Auto-generated method stub - return null; - } + @Override + public String getCurrentState() { + // TODO Auto-generated method stub + return null; + } - @Override - public String getDesiredState() { - // TODO Auto-generated method stub - return null; - } + @Override + public String getDesiredState() { + // TODO Auto-generated method stub + return null; + } - @Override - public Date getCreatedTime() { - // TODO Auto-generated method stub - return null; - } + @Override + public Date getCreatedTime() { + // TODO Auto-generated method stub + return null; + } - @Override - public Date getLastUpdatedTime() { - // TODO Auto-generated method stub - return null; - } + @Override + public Date getLastUpdatedTime() { + // TODO Auto-generated method stub + return null; + } - @Override - public String getOwner() { - // TODO Auto-generated method stub - return null; - } + @Override + public String getOwner() { + // TODO Auto-generated method stub + return null; + } - @Override - public List getApplicableActions() { - // TODO Auto-generated method stub - return null; - } + @Override + public List getApplicableActions() { + // TODO Auto-generated method stub + return null; + } - @Override - public long getAccountId() { - // TODO Auto-generated method stub - return 0; - } + @Override + public long getAccountId() { + // TODO Auto-generated method stub + return 0; + } - @Override - public long getVolumeId() { - // TODO Auto-generated method stub - return 0; - } + @Override + public long getVolumeId() { + // TODO Auto-generated method stub + return 0; + } - @Override - public String getPath() { - // TODO Auto-generated method stub - return null; - } + @Override + public String getName() { + // TODO Auto-generated method stub + return null; + } - @Override - public String getName() { - // TODO Auto-generated method stub - return null; - } + @Override + public Date getCreated() { + // TODO Auto-generated method stub + return null; + } - @Override - public Date getCreated() { - // TODO Auto-generated method stub - return null; - } + @Override + public HypervisorType getHypervisorType() { + // TODO Auto-generated method stub + return null; + } - @Override - public HypervisorType getHypervisorType() { - // TODO Auto-generated method stub - return null; - } + @Override + public boolean isRecursive() { + // TODO Auto-generated method stub + return false; + } - @Override - public boolean isRecursive() { - // TODO Auto-generated method stub - return false; - } + @Override + public short getsnapshotType() { + // TODO Auto-generated method stub + return 0; + } - @Override - public short getsnapshotType() { - // TODO Auto-generated method stub - return 0; - } + @Override + public long getDomainId() { + // TODO Auto-generated method stub + return 0; + } - @Override - public long getDomainId() { - // TODO Auto-generated method stub - return 0; - } + @Override + public String reserveForBackup(int expiration) { + // TODO Auto-generated method stub + return null; + } - @Override - public String reserveForBackup(int expiration) { - // TODO Auto-generated method stub - return null; - } + @Override + public void backup(String reservationToken) { + // TODO Auto-generated method stub - @Override - public void backup(String reservationToken) { - // TODO Auto-generated method stub + } - } + @Override + public void restore(String vm) { + // TODO Auto-generated method stub - @Override - public void restore(String vm) { - // TODO Auto-generated method stub + } - } + @Override + public void destroy() { + // TODO Auto-generated method stub - @Override - public void destroy() { - // TODO Auto-generated method stub + } - } + @Override + public Map getDetails() { + // TODO Auto-generated method stub + return null; + } - @Override - public Map getDetails() { - // TODO Auto-generated method stub - return null; - } + @Override + public void addDetail(String name, String value) { + // TODO Auto-generated method stub - @Override - public void addDetail(String name, String value) { - // TODO Auto-generated method stub - - } + } - @Override - public void delDetail(String name, String value) { - // TODO Auto-generated method stub - - } + @Override + public void delDetail(String name, String value) { + // TODO Auto-generated method stub - @Override - public void updateDetail(String name, String value) { - // TODO Auto-generated method stub - - } + } - @Override - public State getState() { - // TODO Auto-generated method stub - return null; - } + @Override + public void updateDetail(String name, String value) { + // TODO Auto-generated method stub - @Override - public Type getRecurringType() { - // TODO Auto-generated method stub - return null; - } + } + + @Override + public State getState() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Type getRecurringType() { + // TODO Auto-generated method stub + return null; + } } diff --git a/engine/storage/src/org/apache/cloudstack/storage/to/ImageDataStoreTO.java b/engine/storage/src/org/apache/cloudstack/storage/to/ImageDataStoreTO.java deleted file mode 100644 index b1de88f0e2a..00000000000 --- a/engine/storage/src/org/apache/cloudstack/storage/to/ImageDataStoreTO.java +++ /dev/null @@ -1,36 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// 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, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package org.apache.cloudstack.storage.to; - -import org.apache.cloudstack.storage.image.datastore.ImageDataStoreInfo; - -public class ImageDataStoreTO { - private final String type; - private final String uri; - public ImageDataStoreTO(ImageDataStoreInfo dataStore) { - this.type = dataStore.getType(); - this.uri = dataStore.getUri(); - } - - public String getType() { - return this.type; - } - - public String getUri() { - return this.uri; - } -} diff --git a/engine/storage/src/org/apache/cloudstack/storage/to/ImageOnPrimaryDataStoreTO.java b/engine/storage/src/org/apache/cloudstack/storage/to/ImageOnPrimaryDataStoreTO.java deleted file mode 100644 index a9a3cc43c0e..00000000000 --- a/engine/storage/src/org/apache/cloudstack/storage/to/ImageOnPrimaryDataStoreTO.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.to; - -import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreInfo; - -public class ImageOnPrimaryDataStoreTO { - private final String pathOnPrimaryDataStore; - private PrimaryDataStoreTO dataStore; - private final TemplateTO template; - public ImageOnPrimaryDataStoreTO(TemplateOnPrimaryDataStoreInfo template) { - this.pathOnPrimaryDataStore = template.getPath(); - //this.dataStore = template.getPrimaryDataStore().getDataStoreTO(); - this.template = new TemplateTO(template.getTemplate()); - } - - public String getPathOnPrimaryDataStore() { - return this.pathOnPrimaryDataStore; - } - - public PrimaryDataStoreTO getPrimaryDataStore() { - return this.dataStore; - } - - public TemplateTO getTemplate() { - return this.template; - } -} diff --git a/engine/storage/src/org/apache/cloudstack/storage/to/TemplateTO.java b/engine/storage/src/org/apache/cloudstack/storage/to/TemplateTO.java deleted file mode 100644 index bc55ea8c3ea..00000000000 --- a/engine/storage/src/org/apache/cloudstack/storage/to/TemplateTO.java +++ /dev/null @@ -1,51 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// 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, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package org.apache.cloudstack.storage.to; - -import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat; -import org.apache.cloudstack.storage.image.datastore.ImageDataStoreInfo; - -public class TemplateTO { - private final String path; - private final String uuid; - private DiskFormat diskType; - private final ImageDataStoreTO imageDataStore; - - public TemplateTO(TemplateInfo template) { - this.path = null; - this.uuid = template.getUuid(); - //this.diskType = template.getDiskType(); - this.imageDataStore = new ImageDataStoreTO((ImageDataStoreInfo)template.getDataStore()); - } - - public String getPath() { - return this.path; - } - - public String getUuid() { - return this.uuid; - } - - public DiskFormat getDiskType() { - return this.diskType; - } - - public ImageDataStoreTO getImageDataStore() { - return this.imageDataStore; - } -} diff --git a/engine/storage/src/org/apache/cloudstack/storage/to/VolumeTO.java b/engine/storage/src/org/apache/cloudstack/storage/to/VolumeTO.java deleted file mode 100644 index c65b6525827..00000000000 --- a/engine/storage/src/org/apache/cloudstack/storage/to/VolumeTO.java +++ /dev/null @@ -1,77 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// 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, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package org.apache.cloudstack.storage.to; - -import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat; -import org.apache.cloudstack.engine.subsystem.api.storage.type.VolumeType; - -public class VolumeTO { - private final String uuid; - private final String path; - private VolumeType volumeType; - private DiskFormat diskType; - private PrimaryDataStoreTO dataStore; - private String name; - private final long size; - public VolumeTO(VolumeInfo volume) { - this.uuid = volume.getUuid(); - this.path = volume.getUri(); - //this.volumeType = volume.getType(); - //this.diskType = volume.getDiskType(); - if (volume.getDataStore() != null) { - this.dataStore = new PrimaryDataStoreTO((PrimaryDataStoreInfo)volume.getDataStore()); - } else { - this.dataStore = null; - } - //this.name = volume.getName(); - this.size = volume.getSize(); - } - - public String getUuid() { - return this.uuid; - } - - public String getPath() { - return this.path; - } - - public VolumeType getVolumeType() { - return this.volumeType; - } - - public DiskFormat getDiskType() { - return this.diskType; - } - - public PrimaryDataStoreTO getDataStore() { - return this.dataStore; - } - - public void setDataStore(PrimaryDataStoreTO dataStore) { - this.dataStore = dataStore; - } - - public String getName() { - return this.name; - } - - public long getSize() { - return this.size; - } -} diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java b/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java index 349f6ba9079..6815dec4d99 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java +++ b/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java @@ -25,10 +25,8 @@ import javax.inject.Inject; 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.HostScope; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreParameters; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.log4j.Logger; @@ -38,6 +36,8 @@ import com.cloud.agent.api.StoragePoolInfo; import com.cloud.capacity.Capacity; import com.cloud.capacity.CapacityVO; import com.cloud.capacity.dao.CapacityDao; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ScopeType; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePoolHostVO; @@ -48,8 +48,7 @@ import com.cloud.utils.exception.CloudRuntimeException; @Component public class PrimaryDataStoreHelper { - private static final Logger s_logger = Logger - .getLogger(PrimaryDataStoreHelper.class); + private static final Logger s_logger = Logger.getLogger(PrimaryDataStoreHelper.class); @Inject private PrimaryDataStoreDao dataStoreDao; @Inject @@ -60,6 +59,7 @@ public class PrimaryDataStoreHelper { protected CapacityDao _capacityDao; @Inject protected StoragePoolHostDao storagePoolHostDao; + public DataStore createPrimaryDataStore(PrimaryDataStoreParameters params) { StoragePoolVO dataStoreVO = dataStoreDao.findPoolByUUID(params.getUuid()); if (dataStoreVO != null) { @@ -108,11 +108,12 @@ public class PrimaryDataStoreHelper { StoragePoolVO pool = this.dataStoreDao.findById(store.getId()); pool.setScope(scope.getScopeType()); - pool.setAvailableBytes(existingInfo.getAvailableBytes()); + pool.setUsedBytes(existingInfo.getAvailableBytes()); pool.setCapacityBytes(existingInfo.getCapacityBytes()); pool.setStatus(StoragePoolStatus.Up); this.dataStoreDao.update(pool.getId(), pool); - this.storageMgr.createCapacityEntry(pool, Capacity.CAPACITY_TYPE_LOCAL_STORAGE, pool.getCapacityBytes() - pool.getAvailableBytes()); + this.storageMgr.createCapacityEntry(pool, Capacity.CAPACITY_TYPE_LOCAL_STORAGE, + pool.getUsedBytes()); return dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary); } @@ -158,12 +159,9 @@ public class PrimaryDataStoreHelper { return true; } - protected boolean deletePoolStats(Long poolId) { - CapacityVO capacity1 = _capacityDao.findByHostIdType(poolId, - CapacityVO.CAPACITY_TYPE_STORAGE); - CapacityVO capacity2 = _capacityDao.findByHostIdType(poolId, - CapacityVO.CAPACITY_TYPE_STORAGE_ALLOCATED); + CapacityVO capacity1 = _capacityDao.findByHostIdType(poolId, Capacity.CAPACITY_TYPE_STORAGE); + CapacityVO capacity2 = _capacityDao.findByHostIdType(poolId, Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED); if (capacity1 != null) { _capacityDao.remove(capacity1.getId()); } @@ -176,26 +174,22 @@ public class PrimaryDataStoreHelper { } public boolean deletePrimaryDataStore(DataStore store) { - List hostPoolRecords = this.storagePoolHostDao - .listByPoolId(store.getId()); + List hostPoolRecords = this.storagePoolHostDao.listByPoolId(store.getId()); StoragePoolVO poolVO = this.dataStoreDao.findById(store.getId()); Transaction txn = Transaction.currentTxn(); txn.start(); for (StoragePoolHostVO host : hostPoolRecords) { - storagePoolHostDao.deleteStoragePoolHostDetails( - host.getHostId(), host.getPoolId()); + storagePoolHostDao.deleteStoragePoolHostDetails(host.getHostId(), host.getPoolId()); } poolVO.setUuid(null); this.dataStoreDao.update(poolVO.getId(), poolVO); dataStoreDao.remove(poolVO.getId()); deletePoolStats(poolVO.getId()); // Delete op_host_capacity entries - this._capacityDao.removeBy(Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED, - null, null, null, poolVO.getId()); + this._capacityDao.removeBy(Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED, null, null, null, poolVO.getId()); txn.commit(); - s_logger.debug("Storage pool id=" + poolVO.getId() - + " is removed successfully"); + s_logger.debug("Storage pool id=" + poolVO.getId() + " is removed successfully"); return true; } diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDetailsDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/volume/db/PrimaryDataStoreDetailsDaoImpl.java similarity index 68% rename from engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDetailsDaoImpl.java rename to engine/storage/src/org/apache/cloudstack/storage/volume/db/PrimaryDataStoreDetailsDaoImpl.java index 59c488cf6d4..9d174348c73 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDetailsDaoImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/volume/db/PrimaryDataStoreDetailsDaoImpl.java @@ -14,11 +14,14 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package org.apache.cloudstack.storage.datastore.db; +package org.apache.cloudstack.storage.volume.db; import java.util.HashMap; import java.util.List; import java.util.Map; + +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDetailVO; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDetailsDao; import org.springframework.stereotype.Component; import com.cloud.utils.db.GenericDaoBase; @@ -27,25 +30,25 @@ import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; @Component -public class PrimaryDataStoreDetailsDaoImpl extends GenericDaoBase implements PrimaryDataStoreDetailsDao { - +public class PrimaryDataStoreDetailsDaoImpl extends GenericDaoBase implements + PrimaryDataStoreDetailsDao { + protected final SearchBuilder PoolSearch = null; - + protected PrimaryDataStoreDetailsDaoImpl() { /* - super(); - PoolSearch = createSearchBuilder(); - PoolSearch.and("pool", PoolSearch.entity().getPoolId(), SearchCriteria.Op.EQ); - PoolSearch.done(); - */ + * super(); PoolSearch = createSearchBuilder(); PoolSearch.and("pool", + * PoolSearch.entity().getPoolId(), SearchCriteria.Op.EQ); + * PoolSearch.done(); + */ } - + @Override public void update(long poolId, Map details) { Transaction txn = Transaction.currentTxn(); SearchCriteria sc = PoolSearch.create(); sc.setParameters("pool", poolId); - + txn.start(); expunge(sc); for (Map.Entry entry : details.entrySet()) { @@ -54,18 +57,18 @@ public class PrimaryDataStoreDetailsDaoImpl extends GenericDaoBase getDetails(long poolId) { - SearchCriteria sc = PoolSearch.create(); - sc.setParameters("pool", poolId); - - List details = listBy(sc); - Map detailsMap = new HashMap(); - for (PrimaryDataStoreDetailVO detail : details) { - detailsMap.put(detail.getName(), detail.getValue()); - } - - return detailsMap; + SearchCriteria sc = PoolSearch.create(); + sc.setParameters("pool", poolId); + + List details = listBy(sc); + Map detailsMap = new HashMap(); + for (PrimaryDataStoreDetailVO detail : details) { + detailsMap.put(detail.getName(), detail.getValue()); + } + + return detailsMap; } } diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreDao.java b/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreDao.java index 63cdb16c596..1827edfe861 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreDao.java +++ b/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreDao.java @@ -23,7 +23,9 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreState import com.cloud.utils.db.GenericDao; import com.cloud.utils.fsm.StateDao; -public interface TemplatePrimaryDataStoreDao extends GenericDao, StateDao { +public interface TemplatePrimaryDataStoreDao extends GenericDao, + StateDao { public TemplatePrimaryDataStoreVO findByTemplateIdAndPoolId(long templateId, long poolId); + public TemplatePrimaryDataStoreVO findByTemplateIdAndPoolIdAndReady(long templateId, long poolId); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreDaoImpl.java index ad561502266..7c986403636 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreDaoImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreDaoImpl.java @@ -35,9 +35,11 @@ import com.cloud.utils.db.SearchCriteriaService; import com.cloud.utils.db.UpdateBuilder; @Component -public class TemplatePrimaryDataStoreDaoImpl extends GenericDaoBase implements TemplatePrimaryDataStoreDao { +public class TemplatePrimaryDataStoreDaoImpl extends GenericDaoBase implements + TemplatePrimaryDataStoreDao { private static final Logger s_logger = Logger.getLogger(TemplatePrimaryDataStoreDaoImpl.class); protected final SearchBuilder updateSearchBuilder; + public TemplatePrimaryDataStoreDaoImpl() { updateSearchBuilder = createSearchBuilder(); updateSearchBuilder.and("id", updateSearchBuilder.entity().getId(), Op.EQ); @@ -45,9 +47,11 @@ public class TemplatePrimaryDataStoreDaoImpl extends GenericDaoBase sc = SearchCriteria2.create(TemplatePrimaryDataStoreVO.class); + SearchCriteriaService sc = SearchCriteria2 + .create(TemplatePrimaryDataStoreVO.class); sc.addAnd(sc.getEntity().getTemplateId(), Op.EQ, templateId); sc.addAnd(sc.getEntity().getPoolId(), Op.EQ, poolId); return sc.find(); @@ -55,7 +59,8 @@ public class TemplatePrimaryDataStoreDaoImpl extends GenericDaoBase sc = SearchCriteria2.create(TemplatePrimaryDataStoreVO.class); + SearchCriteriaService sc = SearchCriteria2 + .create(TemplatePrimaryDataStoreVO.class); sc.addAnd(sc.getEntity().getTemplateId(), Op.EQ, templateId); sc.addAnd(sc.getEntity().getPoolId(), Op.EQ, poolId); sc.addAnd(sc.getEntity().getState(), Op.EQ, ObjectInDataStoreStateMachine.State.Ready); @@ -63,34 +68,42 @@ public class TemplatePrimaryDataStoreDaoImpl extends GenericDaoBase sc = updateSearchBuilder.create(); sc.setParameters("id", vo.getId()); sc.setParameters("state", currentState); sc.setParameters("updatedCount", vo.getUpdatedCount()); - + vo.incrUpdatedCount(); - + UpdateBuilder builder = getUpdateBuilder(vo); builder.set(vo, "state", nextState); builder.set(vo, "lastUpdated", new Date()); - - int rows = update((TemplatePrimaryDataStoreVO)vo, sc); + + int rows = update(vo, sc); if (rows == 0 && s_logger.isDebugEnabled()) { - TemplatePrimaryDataStoreVO template = findByIdIncludingRemoved(vo.getId()); + TemplatePrimaryDataStoreVO template = findByIdIncludingRemoved(vo.getId()); if (template != null) { StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); - str.append(": DB Data={id=").append(template.getId()).append("; state=").append(template.getState()).append("; updatecount=").append(template.getUpdatedCount()).append(";updatedTime=").append(template.getLastUpdated()); - str.append(": New Data={id=").append(vo.getId()).append("; state=").append(nextState).append("; event=").append(event).append("; updatecount=").append(vo.getUpdatedCount()).append("; updatedTime=").append(vo.getLastUpdated()); - str.append(": stale Data={id=").append(vo.getId()).append("; state=").append(currentState).append("; event=").append(event).append("; updatecount=").append(oldUpdated).append("; updatedTime=").append(oldUpdatedTime); + str.append(": DB Data={id=").append(template.getId()).append("; state=").append(template.getState()) + .append("; updatecount=").append(template.getUpdatedCount()).append(";updatedTime=") + .append(template.getLastUpdated()); + str.append(": New Data={id=").append(vo.getId()).append("; state=").append(nextState) + .append("; event=").append(event).append("; updatecount=").append(vo.getUpdatedCount()) + .append("; updatedTime=").append(vo.getLastUpdated()); + str.append(": stale Data={id=").append(vo.getId()).append("; state=").append(currentState) + .append("; event=").append(event).append("; updatecount=").append(oldUpdated) + .append("; updatedTime=").append(oldUpdatedTime); } else { - s_logger.debug("Unable to update template: id=" + vo.getId() + ", as there is no such template exists in the database anymore"); + s_logger.debug("Unable to update template: id=" + vo.getId() + + ", as there is no such template exists in the database anymore"); } } return rows > 0; } - + } diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreVO.java b/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreVO.java index 48a9f334a19..44765ed40a3 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreVO.java +++ b/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreVO.java @@ -82,22 +82,22 @@ public class TemplatePrimaryDataStoreVO implements StateObject, StateDao { - - List findDetachedByAccount(long accountId); - - List findByAccount(long accountId); - - Pair getCountAndTotalByPool(long poolId); - - Pair getNonDestroyedCountAndTotalByPool(long poolId); - - List findByInstance(long id); - - List findByInstanceAndType(long id, VolumeType vType); - - List findByInstanceIdDestroyed(long vmId); - - List findByAccountAndPod(long accountId, long podId); - - List findByTemplateAndZone(long templateId, long zoneId); - - void deleteVolumesByInstance(long instanceId); - - void attachVolume(long volumeId, long vmId, long deviceId); - - void detachVolume(long volumeId); - - boolean isAnyVolumeActivelyUsingTemplateOnPool(long templateId, long poolId); - - List findCreatedByInstance(long id); - - List findByPoolId(long poolId); - - List findByInstanceAndDeviceId(long instanceId, long deviceId); - - List findUsableVolumesForInstance(long instanceId); - - Long countAllocatedVolumesForAccount(long accountId); - - HypervisorType getHypervisorType(long volumeId); - - List listVolumesToBeDestroyed(); - - ImageFormat getImageFormat(Long volumeId); - - List findReadyRootVolumesByInstance(long instanceId); - - List listPoolIdsByVolumeCount(long dcId, Long podId, Long clusterId, long accountId); - - VolumeVO allocVolume(long size, VolumeType type, String volName, Long templateId); - - VolumeVO findByVolumeIdAndPoolId(long volumeId, long poolId); -} diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/db/VolumeDao2Impl.java b/engine/storage/src/org/apache/cloudstack/storage/volume/db/VolumeDao2Impl.java deleted file mode 100644 index d8497e2f3da..00000000000 --- a/engine/storage/src/org/apache/cloudstack/storage/volume/db/VolumeDao2Impl.java +++ /dev/null @@ -1,440 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// 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, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package org.apache.cloudstack.storage.volume.db; - -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import javax.ejb.Local; -import javax.inject.Inject; - -import org.apache.cloudstack.engine.subsystem.api.storage.type.RootDisk; -import org.apache.cloudstack.engine.subsystem.api.storage.type.VolumeType; -import org.apache.cloudstack.storage.volume.VolumeEvent; - -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - -import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.server.ResourceTag.TaggedResourceType; -import com.cloud.storage.Storage.ImageFormat; -import com.cloud.storage.Volume; -import com.cloud.tags.dao.ResourceTagDao; -import com.cloud.tags.dao.ResourceTagsDaoImpl; -import com.cloud.utils.Pair; - -import com.cloud.utils.db.DB; -import com.cloud.utils.db.GenericDaoBase; -import com.cloud.utils.db.GenericSearchBuilder; -import com.cloud.utils.db.SearchBuilder; -import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.db.SearchCriteria.Func; -import com.cloud.utils.db.SearchCriteria.Op; -import com.cloud.utils.db.SearchCriteria2; -import com.cloud.utils.db.SearchCriteriaService; -import com.cloud.utils.db.Transaction; -import com.cloud.utils.db.UpdateBuilder; -import com.cloud.utils.exception.CloudRuntimeException; - -@Local(value = VolumeDao2.class) -@Component -public class VolumeDao2Impl extends GenericDaoBase implements VolumeDao2 { - private static final Logger s_logger = Logger.getLogger(VolumeDao2Impl.class); - protected final SearchBuilder DetachedAccountIdSearch; - protected final SearchBuilder TemplateZoneSearch; - protected final GenericSearchBuilder TotalSizeByPoolSearch; - protected final GenericSearchBuilder ActiveTemplateSearch; - protected final SearchBuilder InstanceStatesSearch; - protected final SearchBuilder AllFieldsSearch; - protected GenericSearchBuilder CountByAccount; - @Inject ResourceTagDao _tagsDao = null; - protected static final String SELECT_VM_SQL = "SELECT DISTINCT instance_id from volumes v where v.host_id = ? and v.mirror_state = ?"; - protected static final String SELECT_HYPERTYPE_FROM_VOLUME = "SELECT c.hypervisor_type from volumes v, storage_pool s, cluster c where v.pool_id = s.id and s.cluster_id = c.id and v.id = ?"; - - private static final String ORDER_POOLS_NUMBER_OF_VOLUMES_FOR_ACCOUNT = "SELECT pool.id, SUM(IF(vol.state='Ready' AND vol.account_id = ?, 1, 0)) FROM `cloud`.`storage_pool` pool LEFT JOIN `cloud`.`volumes` vol ON pool.id = vol.pool_id WHERE pool.data_center_id = ? " - + " AND pool.pod_id = ? AND pool.cluster_id = ? " + " GROUP BY pool.id ORDER BY 2 ASC "; - - @Override - public List findDetachedByAccount(long accountId) { - SearchCriteria sc = DetachedAccountIdSearch.create(); - sc.setParameters("accountId", accountId); - sc.setParameters("destroyed", Volume.State.Destroy); - return listBy(sc); - } - - @Override - public List findByAccount(long accountId) { - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("accountId", accountId); - sc.setParameters("state", Volume.State.Ready); - return listBy(sc); - } - - @Override - public List findByInstance(long id) { - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("instanceId", id); - return listBy(sc); - } - - @Override - public List findByInstanceAndDeviceId(long instanceId, long deviceId) { - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("instanceId", instanceId); - sc.setParameters("deviceId", deviceId); - return listBy(sc); - } - - @Override - public List findByPoolId(long poolId) { - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("poolId", poolId); - sc.setParameters("notDestroyed", Volume.State.Destroy); - sc.setParameters("vType", new RootDisk().toString()); - return listBy(sc); - } - - @Override - public List findCreatedByInstance(long id) { - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("instanceId", id); - sc.setParameters("state", Volume.State.Ready); - return listBy(sc); - } - - @Override - public List findUsableVolumesForInstance(long instanceId) { - SearchCriteria sc = InstanceStatesSearch.create(); - sc.setParameters("instance", instanceId); - sc.setParameters("states", Volume.State.Creating, Volume.State.Ready, Volume.State.Allocated); - - return listBy(sc); - } - - @Override - public List findByInstanceAndType(long id, VolumeType vType) { - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("instanceId", id); - sc.setParameters("vType", vType.toString()); - return listBy(sc); - } - - @Override - public List findByInstanceIdDestroyed(long vmId) { - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("instanceId", vmId); - sc.setParameters("destroyed", Volume.State.Destroy); - return listBy(sc); - } - - @Override - public List findReadyRootVolumesByInstance(long instanceId) { - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("instanceId", instanceId); - sc.setParameters("state", Volume.State.Ready); - sc.setParameters("vType", new RootDisk().toString()); - return listBy(sc); - } - - @Override - public List findByAccountAndPod(long accountId, long podId) { - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("accountId", accountId); - sc.setParameters("pod", podId); - sc.setParameters("state", Volume.State.Ready); - - return listIncludingRemovedBy(sc); - } - - @Override - public List findByTemplateAndZone(long templateId, long zoneId) { - SearchCriteria sc = TemplateZoneSearch.create(); - sc.setParameters("template", templateId); - sc.setParameters("zone", zoneId); - - return listIncludingRemovedBy(sc); - } - - @Override - public boolean isAnyVolumeActivelyUsingTemplateOnPool(long templateId, long poolId) { - SearchCriteria sc = ActiveTemplateSearch.create(); - sc.setParameters("template", templateId); - sc.setParameters("pool", poolId); - - List results = customSearchIncludingRemoved(sc, null); - assert results.size() > 0 : "How can this return a size of " + results.size(); - - return results.get(0) > 0; - } - - @Override - public void deleteVolumesByInstance(long instanceId) { - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("instanceId", instanceId); - expunge(sc); - } - - @Override - public void attachVolume(long volumeId, long vmId, long deviceId) { - VolumeVO volume = createForUpdate(volumeId); - volume.setInstanceId(vmId); - volume.setDeviceId(deviceId); - volume.setUpdated(new Date()); - volume.setAttached(new Date()); - update(volumeId, volume); - } - - @Override - public void detachVolume(long volumeId) { - VolumeVO volume = createForUpdate(volumeId); - volume.setInstanceId(null); - volume.setDeviceId(null); - volume.setUpdated(new Date()); - volume.setAttached(null); - update(volumeId, volume); - } - - @Override - @DB - public HypervisorType getHypervisorType(long volumeId) { - /* lookup from cluster of pool */ - Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = null; - - try { - String sql = SELECT_HYPERTYPE_FROM_VOLUME; - pstmt = txn.prepareAutoCloseStatement(sql); - pstmt.setLong(1, volumeId); - ResultSet rs = pstmt.executeQuery(); - if (rs.next()) { - return HypervisorType.getType(rs.getString(1)); - } - return HypervisorType.None; - } catch (SQLException e) { - throw new CloudRuntimeException("DB Exception on: " + SELECT_HYPERTYPE_FROM_VOLUME, e); - } catch (Throwable e) { - throw new CloudRuntimeException("Caught: " + SELECT_HYPERTYPE_FROM_VOLUME, e); - } - } - - @Override - public ImageFormat getImageFormat(Long volumeId) { - HypervisorType type = getHypervisorType(volumeId); - if (type.equals(HypervisorType.KVM)) { - return ImageFormat.QCOW2; - } else if (type.equals(HypervisorType.XenServer)) { - return ImageFormat.VHD; - } else if (type.equals(HypervisorType.VMware)) { - return ImageFormat.OVA; - } else { - s_logger.warn("Do not support hypervisor " + type.toString()); - return null; - } - } - - protected VolumeDao2Impl() { - AllFieldsSearch = createSearchBuilder(); - AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), Op.EQ); - AllFieldsSearch.and("accountId", AllFieldsSearch.entity().getAccountId(), Op.EQ); - AllFieldsSearch.and("pod", AllFieldsSearch.entity().getPodId(), Op.EQ); - AllFieldsSearch.and("instanceId", AllFieldsSearch.entity().getInstanceId(), Op.EQ); - AllFieldsSearch.and("deviceId", AllFieldsSearch.entity().getDeviceId(), Op.EQ); - AllFieldsSearch.and("poolId", AllFieldsSearch.entity().getPoolId(), Op.EQ); - AllFieldsSearch.and("vType", AllFieldsSearch.entity().getVolumeType(), Op.EQ); - AllFieldsSearch.and("id", AllFieldsSearch.entity().getId(), Op.EQ); - AllFieldsSearch.and("destroyed", AllFieldsSearch.entity().getState(), Op.EQ); - AllFieldsSearch.and("notDestroyed", AllFieldsSearch.entity().getState(), Op.NEQ); - AllFieldsSearch.and("updatedCount", AllFieldsSearch.entity().getUpdatedCount(), Op.EQ); - AllFieldsSearch.done(); - - DetachedAccountIdSearch = createSearchBuilder(); - DetachedAccountIdSearch.and("accountId", DetachedAccountIdSearch.entity().getAccountId(), Op.EQ); - DetachedAccountIdSearch.and("destroyed", DetachedAccountIdSearch.entity().getState(), Op.NEQ); - DetachedAccountIdSearch.and("instanceId", DetachedAccountIdSearch.entity().getInstanceId(), Op.NULL); - DetachedAccountIdSearch.done(); - - TemplateZoneSearch = createSearchBuilder(); - TemplateZoneSearch.and("template", TemplateZoneSearch.entity().getTemplateId(), Op.EQ); - TemplateZoneSearch.and("zone", TemplateZoneSearch.entity().getDataCenterId(), Op.EQ); - TemplateZoneSearch.done(); - - TotalSizeByPoolSearch = createSearchBuilder(SumCount.class); - TotalSizeByPoolSearch.select("sum", Func.SUM, TotalSizeByPoolSearch.entity().getSize()); - TotalSizeByPoolSearch.select("count", Func.COUNT, (Object[]) null); - TotalSizeByPoolSearch.and("poolId", TotalSizeByPoolSearch.entity().getPoolId(), Op.EQ); - TotalSizeByPoolSearch.and("removed", TotalSizeByPoolSearch.entity().getRemoved(), Op.NULL); - TotalSizeByPoolSearch.and("state", TotalSizeByPoolSearch.entity().getState(), Op.NEQ); - TotalSizeByPoolSearch.done(); - - ActiveTemplateSearch = createSearchBuilder(Long.class); - ActiveTemplateSearch.and("pool", ActiveTemplateSearch.entity().getPoolId(), Op.EQ); - ActiveTemplateSearch.and("template", ActiveTemplateSearch.entity().getTemplateId(), Op.EQ); - ActiveTemplateSearch.and("removed", ActiveTemplateSearch.entity().getRemoved(), Op.NULL); - ActiveTemplateSearch.select(null, Func.COUNT, null); - ActiveTemplateSearch.done(); - - InstanceStatesSearch = createSearchBuilder(); - InstanceStatesSearch.and("instance", InstanceStatesSearch.entity().getInstanceId(), Op.EQ); - InstanceStatesSearch.and("states", InstanceStatesSearch.entity().getState(), Op.IN); - InstanceStatesSearch.done(); - - CountByAccount = createSearchBuilder(Long.class); - CountByAccount.select(null, Func.COUNT, null); - CountByAccount.and("account", CountByAccount.entity().getAccountId(), SearchCriteria.Op.EQ); - CountByAccount.and("state", CountByAccount.entity().getState(), SearchCriteria.Op.NIN); - CountByAccount.done(); - } - - @Override - @DB(txn = false) - public Pair getCountAndTotalByPool(long poolId) { - SearchCriteria sc = TotalSizeByPoolSearch.create(); - sc.setParameters("poolId", poolId); - List results = customSearch(sc, null); - SumCount sumCount = results.get(0); - return new Pair(sumCount.count, sumCount.sum); - } - - @Override - public Long countAllocatedVolumesForAccount(long accountId) { - SearchCriteria sc = CountByAccount.create(); - sc.setParameters("account", accountId); - sc.setParameters("state", Volume.State.Destroy); - return customSearch(sc, null).get(0); - } - - public static class SumCount { - public long sum; - public long count; - - public SumCount() { - } - } - - @Override - public List listVolumesToBeDestroyed() { - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("state", Volume.State.Destroy); - - return listBy(sc); - } - - @Override - public boolean updateState(Volume.State currentState, Volume.Event event, Volume.State nextState, VolumeVO vo, Object data) { - - Long oldUpdated = vo.getUpdatedCount(); - Date oldUpdatedTime = vo.getUpdated(); - - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("id", vo.getId()); - sc.setParameters("state", currentState); - sc.setParameters("updatedCount", vo.getUpdatedCount()); - - vo.incrUpdatedCount(); - - UpdateBuilder builder = getUpdateBuilder(vo); - builder.set(vo, "state", nextState); - builder.set(vo, "updated", new Date()); - - int rows = update((VolumeVO) vo, sc); - if (rows == 0 && s_logger.isDebugEnabled()) { - VolumeVO dbVol = findByIdIncludingRemoved(vo.getId()); - if (dbVol != null) { - StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); - str.append(": DB Data={id=").append(dbVol.getId()).append("; state=").append(dbVol.getState()).append("; updatecount=").append(dbVol.getUpdatedCount()).append(";updatedTime=") - .append(dbVol.getUpdated()); - str.append(": New Data={id=").append(vo.getId()).append("; state=").append(nextState).append("; event=").append(event).append("; updatecount=").append(vo.getUpdatedCount()) - .append("; updatedTime=").append(vo.getUpdated()); - str.append(": stale Data={id=").append(vo.getId()).append("; state=").append(currentState).append("; event=").append(event).append("; updatecount=").append(oldUpdated) - .append("; updatedTime=").append(oldUpdatedTime); - } else { - s_logger.debug("Unable to update volume: id=" + vo.getId() + ", as there is no such volume exists in the database anymore"); - } - } - return rows > 0; - } - - @Override - public List listPoolIdsByVolumeCount(long dcId, Long podId, Long clusterId, long accountId) { - Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = null; - List result = new ArrayList(); - try { - String sql = ORDER_POOLS_NUMBER_OF_VOLUMES_FOR_ACCOUNT; - pstmt = txn.prepareAutoCloseStatement(sql); - pstmt.setLong(1, accountId); - pstmt.setLong(2, dcId); - pstmt.setLong(3, podId); - pstmt.setLong(4, clusterId); - - ResultSet rs = pstmt.executeQuery(); - while (rs.next()) { - result.add(rs.getLong(1)); - } - return result; - } catch (SQLException e) { - throw new CloudRuntimeException("DB Exception on: " + ORDER_POOLS_NUMBER_OF_VOLUMES_FOR_ACCOUNT, e); - } catch (Throwable e) { - throw new CloudRuntimeException("Caught: " + ORDER_POOLS_NUMBER_OF_VOLUMES_FOR_ACCOUNT, e); - } - } - - @Override - @DB(txn = false) - public Pair getNonDestroyedCountAndTotalByPool(long poolId) { - SearchCriteria sc = TotalSizeByPoolSearch.create(); - sc.setParameters("poolId", poolId); - sc.setParameters("state", Volume.State.Destroy); - List results = customSearch(sc, null); - SumCount sumCount = results.get(0); - return new Pair(sumCount.count, sumCount.sum); - } - - @Override - @DB - public boolean remove(Long id) { - Transaction txn = Transaction.currentTxn(); - txn.start(); - VolumeVO entry = findById(id); - if (entry != null) { - _tagsDao.removeByIdAndType(id, TaggedResourceType.Volume); - } - boolean result = super.remove(id); - txn.commit(); - return result; - } - - @Override - @DB - public VolumeVO allocVolume(long size, VolumeType type, String volName, Long templateId) { - VolumeVO vol = new VolumeVO(size, type.toString(), volName, templateId); - vol = this.persist(vol); - return vol; - } - - @Override - public VolumeVO findByVolumeIdAndPoolId(long volumeId, long poolId) { - SearchCriteriaService sc = SearchCriteria2.create(VolumeVO.class); - sc.addAnd(sc.getEntity().getId(), Op.EQ, volumeId); - sc.addAnd(sc.getEntity().getPoolId(), Op.EQ, poolId); - return sc.find(); - } -} diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/db/VolumeVO.java b/engine/storage/src/org/apache/cloudstack/storage/volume/db/VolumeVO.java deleted file mode 100644 index 831022455c9..00000000000 --- a/engine/storage/src/org/apache/cloudstack/storage/volume/db/VolumeVO.java +++ /dev/null @@ -1,418 +0,0 @@ -//Licensed to the Apache Software Foundation (ASF) under one -//or more contributor license agreements. See the NOTICE file -//distributed with this work for additional information -//regarding copyright ownership. The ASF licenses this file -//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, -//software distributed under the License is distributed on an -//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -//KIND, either express or implied. See the License for the -//specific language governing permissions and limitations -//under the License. - -package org.apache.cloudstack.storage.volume.db; - -import java.util.Date; -import java.util.UUID; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.Table; -import javax.persistence.TableGenerator; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; - -import org.apache.cloudstack.api.Identity; -import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat; - -import com.cloud.storage.Storage.StoragePoolType; -import com.cloud.storage.Volume; -import com.cloud.utils.NumbersUtil; -import com.cloud.utils.db.GenericDao; -import com.cloud.utils.fsm.StateObject; - -@Entity -@Table(name = "volumes") -public class VolumeVO implements Identity, StateObject { - @Id - @TableGenerator(name = "volume_sq", table = "sequence", pkColumnName = "name", valueColumnName = "value", pkColumnValue = "volume_seq", allocationSize = 1) - @GeneratedValue(strategy = GenerationType.TABLE) - @Column(name = "id") - long id; - - @Column(name = "name") - String name; - - @Column(name = "pool_id") - Long poolId; - - @Column(name = "last_pool_id") - Long lastPoolId; - - @Column(name = "account_id") - long accountId; - - @Column(name = "domain_id") - long domainId; - - @Column(name = "instance_id") - Long instanceId = null; - - @Column(name = "device_id") - Long deviceId = null; - - @Column(name = "size") - long size; - - @Column(name = "folder") - String folder; - - @Column(name = "path") - String path; - - @Column(name = "pod_id") - Long podId; - - @Column(name = "created") - Date created; - - @Column(name = "attached") - @Temporal(value = TemporalType.TIMESTAMP) - Date attached; - - @Column(name = "data_center_id") - long dataCenterId; - - @Column(name = "host_ip") - String hostip; - - @Column(name = "disk_offering_id") - long diskOfferingId; - - @Column(name = "template_id") - Long templateId; - - @Column(name = "first_snapshot_backup_uuid") - String firstSnapshotBackupUuid; - - @Column(name = "volume_type") - String volumeType = "UNKNOWN"; - - @Column(name = "pool_type") - @Enumerated(EnumType.STRING) - StoragePoolType poolType; - - @Column(name = "disk_type") - DiskFormat diskType; - - @Column(name = GenericDao.REMOVED_COLUMN) - Date removed; - - @Column(name = "updated") - @Temporal(value = TemporalType.TIMESTAMP) - Date updated; - - @Column(name = "update_count", updatable = true, nullable = false) - protected long updatedCount; // This field should be updated everytime the - // state is updated. There's no set method in - // the vo object because it is done with in the - // dao code. - - @Column(name = "recreatable") - boolean recreatable; - - @Column(name = "state") - @Enumerated(value = EnumType.STRING) - private Volume.State state; - - @Column(name = "chain_info") - String chainInfo; - - @Column(name = "uuid") - String uuid; - - // Real Constructor - public VolumeVO(long size, String type, String name, Long templateId) { - this.volumeType = type; - this.size = size; - this.name = name; - this.templateId = templateId; - this.uuid = UUID.randomUUID().toString(); - this.state = Volume.State.Allocated; - } - - // Copy Constructor - public VolumeVO(VolumeVO that) { - this(that.getSize(), that.getVolumeType(), that.getName(), that.getTemplateId()); - this.recreatable = that.isRecreatable(); - this.state = that.getState(); - - this.size = that.getSize(); - this.diskOfferingId = that.getDiskOfferingId(); - this.poolId = that.getPoolId(); - this.attached = that.getAttached(); - this.chainInfo = that.getChainInfo(); - this.templateId = that.getTemplateId(); - this.deviceId = that.getDeviceId(); - this.uuid = UUID.randomUUID().toString(); - } - - public long getUpdatedCount() { - return this.updatedCount; - } - - public void incrUpdatedCount() { - this.updatedCount++; - } - - public void decrUpdatedCount() { - this.updatedCount--; - } - - public boolean isRecreatable() { - return recreatable; - } - - public void setRecreatable(boolean recreatable) { - this.recreatable = recreatable; - } - - public long getId() { - return id; - } - - public Long getPodId() { - return podId; - } - - public long getDataCenterId() { - return dataCenterId; - } - - public String getName() { - return name; - } - - public long getAccountId() { - return accountId; - } - - public void setPoolType(StoragePoolType poolType) { - this.poolType = poolType; - } - - public StoragePoolType getPoolType() { - return poolType; - } - - public long getDomainId() { - return domainId; - } - - public String getFolder() { - return folder; - } - - public String getPath() { - return path; - } - - protected VolumeVO() { - } - - public long getSize() { - return size; - } - - public void setSize(long size) { - this.size = size; - } - - public Long getInstanceId() { - return instanceId; - } - - public Long getDeviceId() { - return deviceId; - } - - public void setDeviceId(Long deviceId) { - this.deviceId = deviceId; - } - - public String getVolumeType() { - return volumeType; - } - - public void setName(String name) { - this.name = name; - } - - public void setFolder(String folder) { - this.folder = folder; - } - - public void setAccountId(long accountId) { - this.accountId = accountId; - } - - public void setDomainId(long domainId) { - this.domainId = domainId; - } - - public void setInstanceId(Long instanceId) { - this.instanceId = instanceId; - } - - public void setPath(String path) { - this.path = path; - } - - public String getHostIp() { - return hostip; - } - - public void setHostIp(String hostip) { - this.hostip = hostip; - } - - public void setPodId(Long podId) { - this.podId = podId; - } - - public void setDataCenterId(long dataCenterId) { - this.dataCenterId = dataCenterId; - } - - public void setVolumeType(String type) { - volumeType = type; - } - - public Date getCreated() { - return created; - } - - public Date getRemoved() { - return removed; - } - - public void setRemoved(Date removed) { - this.removed = removed; - } - - public long getDiskOfferingId() { - return diskOfferingId; - } - - public void setDiskOfferingId(long diskOfferingId) { - this.diskOfferingId = diskOfferingId; - } - - public Long getTemplateId() { - return templateId; - } - - public void setTemplateId(Long templateId) { - this.templateId = templateId; - } - - public String getFirstSnapshotBackupUuid() { - return firstSnapshotBackupUuid; - } - - public void setFirstSnapshotBackupUuid(String firstSnapshotBackupUuid) { - this.firstSnapshotBackupUuid = firstSnapshotBackupUuid; - } - - public Long getPoolId() { - return poolId; - } - - public void setPoolId(Long poolId) { - this.poolId = poolId; - } - - public Date getUpdated() { - return updated; - } - - @Override - public Volume.State getState() { - return state; - } - - public void setUpdated(Date updated) { - this.updated = updated; - } - - @Override - public String toString() { - return new StringBuilder("Vol[").append(id).append("|vm=").append(instanceId).append("|").append(volumeType).append("]").toString(); - } - - public Date getAttached() { - return this.attached; - } - - public void setAttached(Date attached) { - this.attached = attached; - } - - public String getChainInfo() { - return this.chainInfo; - } - - public void setChainInfo(String chainInfo) { - this.chainInfo = chainInfo; - } - - public Long getLastPoolId() { - return this.lastPoolId; - } - - public void setLastPoolId(Long poolId) { - this.lastPoolId = poolId; - } - - @Override - public int hashCode() { - return NumbersUtil.hash(id); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof VolumeVO) { - return id == ((VolumeVO) obj).id; - } else { - return false; - } - } - - @Override - public String getUuid() { - return this.uuid; - } - - public void setUuid(String uuid) { - this.uuid = uuid; - } - - public DiskFormat getDiskType() { - return diskType; - } - - public void setDiskType(DiskFormat type) { - diskType = type; - } - -} diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/DefaultPrimaryDataStore.java b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java similarity index 82% rename from engine/storage/volume/src/org/apache/cloudstack/storage/datastore/DefaultPrimaryDataStore.java rename to engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java index 31e6908e28f..cfdb5c0821d 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/DefaultPrimaryDataStore.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java @@ -25,17 +25,14 @@ import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole; import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; -import org.apache.cloudstack.engine.subsystem.api.storage.ImageDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle; import org.apache.cloudstack.engine.subsystem.api.storage.Scope; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; @@ -44,11 +41,16 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; import org.apache.cloudstack.storage.volume.VolumeObject; import org.apache.log4j.Logger; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataStoreTO; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ScopeType; import com.cloud.storage.StoragePoolHostVO; import com.cloud.storage.StoragePoolStatus; import com.cloud.storage.VMTemplateStoragePoolVO; @@ -60,9 +62,8 @@ import com.cloud.utils.component.ComponentContext; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.storage.encoding.EncodingType; -public class DefaultPrimaryDataStore implements PrimaryDataStore { - private static final Logger s_logger = Logger - .getLogger(DefaultPrimaryDataStore.class); +public class PrimaryDataStoreImpl implements PrimaryDataStore { + private static final Logger s_logger = Logger.getLogger(PrimaryDataStoreImpl.class); protected PrimaryDataStoreDriver driver; protected StoragePoolVO pdsv; @Inject @@ -71,7 +72,7 @@ public class DefaultPrimaryDataStore implements PrimaryDataStore { @Inject private ObjectInDataStoreManager objectInStoreMgr; @Inject - ImageDataFactory imageDataFactory; + TemplateDataFactory imageDataFactory; @Inject SnapshotDataFactory snapshotFactory; protected DataStoreProvider provider; @@ -80,23 +81,22 @@ public class DefaultPrimaryDataStore implements PrimaryDataStore { @Inject StoragePoolHostDao poolHostDao; + @Inject private VolumeDao volumeDao; - public DefaultPrimaryDataStore() { - + public PrimaryDataStoreImpl() { + } - - public void configure(StoragePoolVO pdsv, - PrimaryDataStoreDriver driver, DataStoreProvider provider) { + + public void configure(StoragePoolVO pdsv, PrimaryDataStoreDriver driver, DataStoreProvider provider) { this.pdsv = pdsv; this.driver = driver; this.provider = provider; } - public static DefaultPrimaryDataStore createDataStore( - StoragePoolVO pdsv, PrimaryDataStoreDriver driver, + public static PrimaryDataStoreImpl createDataStore(StoragePoolVO pdsv, PrimaryDataStoreDriver driver, DataStoreProvider provider) { - DefaultPrimaryDataStore dataStore = (DefaultPrimaryDataStore)ComponentContext.inject(DefaultPrimaryDataStore.class); + PrimaryDataStoreImpl dataStore = ComponentContext.inject(PrimaryDataStoreImpl.class); dataStore.configure(pdsv, driver, provider); return dataStore; } @@ -153,14 +153,13 @@ public class DefaultPrimaryDataStore implements PrimaryDataStore { public Scope getScope() { StoragePoolVO vo = dataStoreDao.findById(this.pdsv.getId()); if (vo.getScope() == ScopeType.CLUSTER) { - return new ClusterScope(vo.getClusterId(), vo.getPodId(), - vo.getDataCenterId()); + return new ClusterScope(vo.getClusterId(), vo.getPodId(), vo.getDataCenterId()); } else if (vo.getScope() == ScopeType.ZONE) { return new ZoneScope(vo.getDataCenterId()); } else if (vo.getScope() == ScopeType.HOST) { List poolHosts = poolHostDao.listByPoolId(vo.getId()); if (poolHosts.size() > 0) { - return new HostScope(poolHosts.get(0).getHostId()); + return new HostScope(poolHosts.get(0).getHostId(), vo.getDataCenterId()); } s_logger.debug("can't find a local storage in pool host table: " + vo.getId()); } @@ -169,23 +168,19 @@ public class DefaultPrimaryDataStore implements PrimaryDataStore { @Override public boolean isHypervisorSupported(HypervisorType hypervisor) { - // TODO Auto-generated method stub return true; } @Override public boolean isLocalStorageSupported() { - // TODO Auto-generated method stub return false; } @Override public boolean isVolumeDiskTypeSupported(DiskFormat diskType) { - // TODO Auto-generated method stub return false; } - @Override public String getUuid() { return this.pdsv.getUuid(); @@ -218,25 +213,24 @@ public class DefaultPrimaryDataStore implements PrimaryDataStore { @Override public SnapshotInfo getSnapshot(long snapshotId) { - // TODO Auto-generated method stub return null; } @Override public DiskFormat getDefaultDiskType() { - // TODO Auto-generated method stub return null; } @Override public DataObject create(DataObject obj) { - //create template on primary storage + // create template on primary storage if (obj.getType() == DataObjectType.TEMPLATE) { - VMTemplateStoragePoolVO templateStoragePoolRef = templatePoolDao.findByPoolTemplate(this.getId(), obj.getId()); + VMTemplateStoragePoolVO templateStoragePoolRef = templatePoolDao.findByPoolTemplate(this.getId(), + obj.getId()); if (templateStoragePoolRef == null) { try { - templateStoragePoolRef = new VMTemplateStoragePoolVO(this.getId(), obj.getId()); - templateStoragePoolRef = templatePoolDao.persist(templateStoragePoolRef); + templateStoragePoolRef = new VMTemplateStoragePoolVO(this.getId(), obj.getId()); + templateStoragePoolRef = templatePoolDao.persist(templateStoragePoolRef); } catch (Throwable t) { templateStoragePoolRef = templatePoolDao.findByPoolTemplate(this.getId(), obj.getId()); if (templateStoragePoolRef == null) { @@ -244,16 +238,18 @@ public class DefaultPrimaryDataStore implements PrimaryDataStore { } } } - + } else if (obj.getType() == DataObjectType.SNAPSHOT) { + return objectInStoreMgr.create(obj, this); } - + return objectInStoreMgr.get(obj, this); } @Override public boolean delete(DataObject obj) { - // TODO Auto-generated method stub - return false; + //TODO: clean up through driver + objectInStoreMgr.delete(obj); + return true; } @Override @@ -268,27 +264,27 @@ public class DefaultPrimaryDataStore implements PrimaryDataStore { @Override public StoragePoolType getPoolType() { - return this.pdsv.getPoolType(); + return this.pdsv.getPoolType(); } @Override public Date getCreated() { - return this.pdsv.getCreated(); + return this.pdsv.getCreated(); } @Override public Date getUpdateTime() { - return this.pdsv.getUpdateTime(); + return this.pdsv.getUpdateTime(); } @Override public long getCapacityBytes() { - return this.pdsv.getCapacityBytes(); + return this.pdsv.getCapacityBytes(); } @Override - public long getAvailableBytes() { - return this.pdsv.getAvailableBytes(); + public long getUsedBytes() { + return this.pdsv.getUsedBytes(); } @Override @@ -308,7 +304,7 @@ public class DefaultPrimaryDataStore implements PrimaryDataStore { @Override public boolean isShared() { - return this.pdsv.getScope() == ScopeType.HOST ? false : true; + return this.pdsv.getScope() == ScopeType.HOST ? false : true; } @Override @@ -340,4 +336,14 @@ public class DefaultPrimaryDataStore implements PrimaryDataStore { public String getStorageProviderName() { return this.pdsv.getStorageProviderName(); } + + @Override + public DataStoreTO getTO() { + DataStoreTO to = getDriver().getStoreTO(this); + if (to == null) { + PrimaryDataStoreTO primaryTO = new PrimaryDataStoreTO(this); + return primaryTO; + } + return to; + } } diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/DefaultPrimaryDataStoreDriverImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/DefaultPrimaryDataStoreDriverImpl.java deleted file mode 100644 index e5ee742f5ba..00000000000 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/DefaultPrimaryDataStoreDriverImpl.java +++ /dev/null @@ -1,249 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// 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, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package org.apache.cloudstack.storage.datastore.driver; - -import java.net.URISyntaxException; -import java.util.Set; - -import javax.inject.Inject; - -import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; -import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; -import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; -import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; -import org.apache.cloudstack.framework.async.AsyncCompletionCallback; -import org.apache.cloudstack.framework.async.AsyncRpcConext; -import org.apache.cloudstack.storage.command.CreateObjectAnswer; -import org.apache.cloudstack.storage.command.CreateObjectCommand; -import org.apache.cloudstack.storage.command.DeleteCommand; -import org.apache.cloudstack.storage.datastore.DataObjectManager; -import org.apache.cloudstack.storage.endpoint.EndPointSelector; -import org.apache.log4j.Logger; - -import com.cloud.agent.api.Answer; -import com.cloud.storage.dao.StoragePoolHostDao; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.storage.encoding.DecodedDataObject; -import com.cloud.utils.storage.encoding.Decoder; - - -public class DefaultPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver { - private static final Logger s_logger = Logger.getLogger(DefaultPrimaryDataStoreDriverImpl.class); - @Inject - EndPointSelector selector; - @Inject - StoragePoolHostDao storeHostDao; - @Inject - DataObjectManager dataObjMgr; - public DefaultPrimaryDataStoreDriverImpl() { - - } - - private class CreateVolumeContext extends AsyncRpcConext { - private final DataObject volume; - /** - * @param callback - */ - public CreateVolumeContext(AsyncCompletionCallback callback, DataObject volume) { - super(callback); - this.volume = volume; - } - - public DataObject getVolume() { - return this.volume; - } - - } - - public Void createAsyncCallback(AsyncCallbackDispatcher callback, CreateVolumeContext context) { - CreateCmdResult result = null; - CreateObjectAnswer volAnswer = (CreateObjectAnswer) callback.getResult(); - if (volAnswer.getResult()) { - result = new CreateCmdResult(volAnswer.getPath(), volAnswer.getSize()); - } else { - result = new CreateCmdResult("", null); - result.setResult(volAnswer.getDetails()); - } - - context.getParentCallback().complete(result); - return null; - } - - @Override - public void deleteAsync(DataObject vo, AsyncCompletionCallback callback) { - DeleteCommand cmd = new DeleteCommand(vo.getUri()); - - EndPoint ep = selector.select(vo); - AsyncRpcConext context = new AsyncRpcConext(callback); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); - caller.setCallback(caller.getTarget().deleteCallback(null, null)) - .setContext(context); - ep.sendMessageAsync(cmd, caller); - } - - public Void deleteCallback(AsyncCallbackDispatcher callback, AsyncRpcConext context) { - CommandResult result = new CommandResult(); - Answer answer = callback.getResult(); - if (!answer.getResult()) { - result.setResult(answer.getDetails()); - } - context.getParentCallback().complete(result); - return null; - } - /* - private class CreateVolumeFromBaseImageContext extends AsyncRpcConext { - private final VolumeObject volume; - - public CreateVolumeFromBaseImageContext(AsyncCompletionCallback callback, VolumeObject volume) { - super(callback); - this.volume = volume; - } - - public VolumeObject getVolume() { - return this.volume; - } - - } - - @Override - public void createVolumeFromBaseImageAsync(VolumeObject volume, TemplateInfo template, AsyncCompletionCallback callback) { - VolumeTO vol = this.dataStore.getVolumeTO(volume); - List endPoints = this.dataStore.getEndPoints(); - EndPoint ep = endPoints.get(0); - String templateUri = template.getDataStore().grantAccess(template, ep); - CreateVolumeFromBaseImageCommand cmd = new CreateVolumeFromBaseImageCommand(vol, templateUri); - - CreateVolumeFromBaseImageContext context = new CreateVolumeFromBaseImageContext(callback, volume); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); - caller.setContext(context) - .setCallback(caller.getTarget().createVolumeFromBaseImageAsyncCallback(null, null)); - - ep.sendMessageAsync(cmd, caller); - }*/ - /* - public Object createVolumeFromBaseImageAsyncCallback(AsyncCallbackDispatcher callback, CreateVolumeFromBaseImageContext context) { - CreateVolumeAnswer answer = (CreateVolumeAnswer)callback.getResult(); - CommandResult result = new CommandResult(); - if (answer == null || answer.getDetails() != null) { - result.setSuccess(false); - if (answer != null) { - result.setResult(answer.getDetails()); - } - } else { - result.setSuccess(true); - VolumeObject volume = context.getVolume(); - volume.setPath(answer.getVolumeUuid()); - } - AsyncCompletionCallback parentCall = context.getParentCallback(); - parentCall.complete(result); - return null; - }*/ - - @Override - public void createAsync(DataObject vol, - AsyncCompletionCallback callback) { - EndPoint ep = selector.select(vol); - CreateObjectCommand createCmd = new CreateObjectCommand(vol.getUri()); - - CreateVolumeContext context = new CreateVolumeContext(callback, vol); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); - caller.setContext(context) - .setCallback(caller.getTarget().createAsyncCallback(null, null)); - - ep.sendMessageAsync(createCmd, caller); - } - - @Override - public String grantAccess(DataObject object, EndPoint ep) { - //StoragePoolHostVO poolHost = storeHostDao.findByPoolHost(object.getDataStore().getId(), ep.getId()); - - String uri = object.getUri(); - try { - DecodedDataObject obj = Decoder.decode(uri); - if (obj.getPath() == null) { - //create an obj - EndPoint newEp = selector.select(object); - CreateObjectCommand createCmd = new CreateObjectCommand(uri); - CreateObjectAnswer answer = (CreateObjectAnswer)ep.sendMessage(createCmd); - if (answer.getResult()) { - dataObjMgr.update(object, answer.getPath(), answer.getSize()); - } else { - s_logger.debug("failed to create object" + answer.getDetails()); - throw new CloudRuntimeException("failed to create object" + answer.getDetails()); - } - } - - return object.getUri(); - } catch (URISyntaxException e) { - throw new CloudRuntimeException("uri parsed error", e); - } - } - - @Override - public boolean revokeAccess(DataObject vol, EndPoint ep) { - // TODO Auto-generated method stub - return false; - } - - @Override - public Set listObjects(DataStore store) { - // TODO Auto-generated method stub - return null; - } - - @Override - public void revertSnapshot(SnapshotInfo snapshot, - AsyncCompletionCallback callback) { - // TODO Auto-generated method stub - - } - - - - @Override - public boolean canCopy(DataObject srcData, DataObject destData) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void copyAsync(DataObject srcdata, DataObject destData, - AsyncCompletionCallback callback) { - // TODO Auto-generated method stub - - } - - @Override - public void resize(DataObject data, - AsyncCompletionCallback callback) { - // TODO Auto-generated method stub - - } - - @Override - public void takeSnapshot(SnapshotInfo snapshot, - AsyncCompletionCallback callback) { - // TODO Auto-generated method stub - - } - -} diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/manager/DefaultPrimaryDataStoreProviderManagerImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/manager/PrimaryDataStoreProviderManagerImpl.java similarity index 86% rename from engine/storage/volume/src/org/apache/cloudstack/storage/datastore/manager/DefaultPrimaryDataStoreProviderManagerImpl.java rename to engine/storage/volume/src/org/apache/cloudstack/storage/datastore/manager/PrimaryDataStoreProviderManagerImpl.java index e38c3b306fa..06b54e0a46c 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/manager/DefaultPrimaryDataStoreProviderManagerImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/manager/PrimaryDataStoreProviderManagerImpl.java @@ -28,10 +28,9 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager; import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; -import org.apache.cloudstack.storage.datastore.DefaultPrimaryDataStore; +import org.apache.cloudstack.storage.datastore.PrimaryDataStoreImpl; import org.apache.cloudstack.storage.datastore.PrimaryDataStore; import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager; -import org.apache.cloudstack.storage.datastore.db.DataStoreProviderDao; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.springframework.stereotype.Component; @@ -39,30 +38,30 @@ import org.springframework.stereotype.Component; import com.cloud.storage.StorageManager; @Component -public class DefaultPrimaryDataStoreProviderManagerImpl implements PrimaryDataStoreProviderManager { - @Inject - DataStoreProviderDao dataStoreProviderDao; +public class PrimaryDataStoreProviderManagerImpl implements PrimaryDataStoreProviderManager { @Inject DataStoreProviderManager providerManager; @Inject PrimaryDataStoreDao dataStoreDao; Map driverMaps; - @Inject StorageManager storageMgr; + @Inject + StorageManager storageMgr; @PostConstruct public void config() { driverMaps = new HashMap(); } - + @Override public PrimaryDataStore getPrimaryDataStore(long dataStoreId) { StoragePoolVO dataStoreVO = dataStoreDao.findById(dataStoreId); String providerName = dataStoreVO.getStorageProviderName(); DataStoreProvider provider = providerManager.getDataStoreProvider(providerName); - DefaultPrimaryDataStore dataStore = DefaultPrimaryDataStore.createDataStore(dataStoreVO, driverMaps.get(provider.getName()), provider); + PrimaryDataStoreImpl dataStore = PrimaryDataStoreImpl.createDataStore(dataStoreVO, + driverMaps.get(provider.getName()), provider); return dataStore; } - + @Override public boolean registerDriver(String providerName, PrimaryDataStoreDriver driver) { if (driverMaps.get(providerName) != null) { diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java index 2f0b43ad9f6..fa5e2167cc8 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java @@ -21,7 +21,6 @@ package org.apache.cloudstack.storage.datastore.provider; import javax.inject.Inject; 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.HypervisorHostListener; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; @@ -32,22 +31,28 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.ModifyStoragePoolAnswer; import com.cloud.agent.api.ModifyStoragePoolCommand; import com.cloud.alert.AlertManager; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolHostVO; import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.utils.exception.CloudRuntimeException; public class DefaultHostListener implements HypervisorHostListener { - private static final Logger s_logger = Logger - .getLogger(DefaultHostListener.class); - @Inject AgentManager agentMgr; - @Inject DataStoreManager dataStoreMgr; - @Inject AlertManager alertMgr; - @Inject StoragePoolHostDao storagePoolHostDao; - @Inject PrimaryDataStoreDao primaryStoreDao; + private static final Logger s_logger = Logger.getLogger(DefaultHostListener.class); + @Inject + AgentManager agentMgr; + @Inject + DataStoreManager dataStoreMgr; + @Inject + AlertManager alertMgr; + @Inject + StoragePoolHostDao storagePoolHostDao; + @Inject + PrimaryDataStoreDao primaryStoreDao; + @Override public boolean hostConnect(long hostId, long poolId) { - StoragePool pool = (StoragePool)this.dataStoreMgr.getDataStore(poolId, DataStoreRole.Primary); + StoragePool pool = (StoragePool) this.dataStoreMgr.getDataStore(poolId, DataStoreRole.Primary); ModifyStoragePoolCommand cmd = new ModifyStoragePoolCommand(true, pool); final Answer answer = agentMgr.easySend(hostId, cmd); @@ -58,22 +63,25 @@ public class DefaultHostListener implements HypervisorHostListener { if (!answer.getResult()) { String msg = "Unable to attach storage pool" + poolId + " to the host" + hostId; alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, pool.getDataCenterId(), pool.getPodId(), msg, msg); - throw new CloudRuntimeException("Unable establish connection from storage head to storage pool " + pool.getId() + " due to " + answer.getDetails() + pool.getId()); + throw new CloudRuntimeException("Unable establish connection from storage head to storage pool " + + pool.getId() + " due to " + answer.getDetails() + pool.getId()); } - assert (answer instanceof ModifyStoragePoolAnswer) : "Well, now why won't you actually return the ModifyStoragePoolAnswer when it's ModifyStoragePoolCommand? Pool=" + pool.getId() + "Host=" + hostId; + assert (answer instanceof ModifyStoragePoolAnswer) : "Well, now why won't you actually return the ModifyStoragePoolAnswer when it's ModifyStoragePoolCommand? Pool=" + + pool.getId() + "Host=" + hostId; ModifyStoragePoolAnswer mspAnswer = (ModifyStoragePoolAnswer) answer; StoragePoolHostVO poolHost = storagePoolHostDao.findByPoolHost(pool.getId(), hostId); if (poolHost == null) { - poolHost = new StoragePoolHostVO(pool.getId(), hostId, mspAnswer.getPoolInfo().getLocalPath().replaceAll("//", "/")); + poolHost = new StoragePoolHostVO(pool.getId(), hostId, mspAnswer.getPoolInfo().getLocalPath() + .replaceAll("//", "/")); storagePoolHostDao.persist(poolHost); } else { poolHost.setLocalPath(mspAnswer.getPoolInfo().getLocalPath().replaceAll("//", "/")); } - + StoragePoolVO poolVO = this.primaryStoreDao.findById(poolId); - poolVO.setAvailableBytes(mspAnswer.getPoolInfo().getAvailableBytes()); + poolVO.setUsedBytes(mspAnswer.getPoolInfo().getAvailableBytes()); poolVO.setCapacityBytes(mspAnswer.getPoolInfo().getCapacityBytes()); primaryStoreDao.update(pool.getId(), poolVO); diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplateInstallStrategy.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplateInstallStrategy.java deleted file mode 100644 index 99b34cbcf18..00000000000 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplateInstallStrategy.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.volume; - -import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; -import org.apache.cloudstack.framework.async.AsyncCompletionCallback; -import org.apache.cloudstack.storage.datastore.PrimaryDataStore; -import org.apache.cloudstack.storage.volume.VolumeServiceImpl.CreateBaseImageResult; - -public interface TemplateInstallStrategy { - public Void installAsync(TemplateInfo template, PrimaryDataStore store, AsyncCompletionCallback callback); -} diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplateInstallStrategyImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplateInstallStrategyImpl.java deleted file mode 100644 index e09961913de..00000000000 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplateInstallStrategyImpl.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.volume; - -import javax.inject.Inject; - -import org.apache.cloudstack.engine.subsystem.api.storage.ImageDataFactory; -import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; -import org.apache.cloudstack.framework.async.AsyncCompletionCallback; -import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; -import org.apache.cloudstack.storage.datastore.PrimaryDataStore; -import org.apache.cloudstack.storage.motion.DataMotionService; -import org.apache.cloudstack.storage.volume.VolumeServiceImpl.CreateBaseImageResult; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - -@Component -public class TemplateInstallStrategyImpl implements TemplateInstallStrategy { - private static final Logger s_logger = Logger - .getLogger(TemplateInstallStrategyImpl.class); - @Inject - ObjectInDataStoreManager objectInDataStoreMgr; - @Inject - DataMotionService motionSrv; - @Inject - ImageDataFactory imageFactory; - protected long waitingTime = 1800; // half an hour - protected long waitingRetries = 10; -/* - protected TemplateInfo waitingForTemplateDownload(TemplateInfo template, - PrimaryDataStore dataStore) { - long retries = this.waitingRetries; - ObjectInDataStoreVO obj = null; - do { - try { - Thread.sleep(waitingTime); - } catch (InterruptedException e) { - s_logger.debug("sleep interrupted", e); - throw new CloudRuntimeException("sleep interrupted", e); - } - - obj = objectInDataStoreMgr.findObject(template.getId(), - template.getType(), dataStore.getId(), dataStore.getRole()); - if (obj == null) { - s_logger.debug("can't find object in db, maybe it's cleaned up already, exit waiting"); - break; - } - if (obj.getState() == ObjectInDataStoreStateMachine.State.Ready) { - break; - } - retries--; - } while (retries > 0); - - if (obj == null || retries <= 0) { - s_logger.debug("waiting too long for template downloading, marked it as failed"); - throw new CloudRuntimeException( - "waiting too long for template downloading, marked it as failed"); - } - return imageFactory.getTemplate(template.getId(), dataStore); - } - - class InstallContext extends AsyncRpcConext { - final TemplateInfo destTemplate; - final TemplateInfo srcTemplate; - - public InstallContext(AsyncCompletionCallback callback, - TemplateInfo destTemplate, TemplateInfo srcTemplate) { - super(callback); - this.destTemplate = destTemplate; - this.srcTemplate = srcTemplate; - } - - } - - @Override - public Void installAsync(TemplateInfo template, PrimaryDataStore store, - AsyncCompletionCallback callback) { - ObjectInDataStoreVO obj = objectInDataStoreMgr.findObject( - template.getId(), template.getType(), store.getId(), - store.getRole()); - TemplateInfo templateOnPrimaryStoreObj = null; - boolean freshNewTemplate = false; - if (obj == null) { - try { - templateOnPrimaryStoreObj = objectInDataStoreMgr.create( - template, store); - freshNewTemplate = true; - } catch (Throwable e) { - obj = objectInDataStoreMgr.findObject(template.getId(), - template.getType(), store.getId(), store.getRole()); - if (obj == null) { - CreateBaseImageResult result = new CreateBaseImageResult( - null); - result.setSuccess(false); - result.setResult(e.toString()); - callback.complete(result); - return null; - } - } - } - - if (!freshNewTemplate - && obj.getState() != ObjectInDataStoreStateMachine.State.Ready) { - try { - templateOnPrimaryStoreObj = waitingForTemplateDownload( - template, store); - } catch (Exception e) { - CreateBaseImageResult result = new CreateBaseImageResult(null); - result.setSuccess(false); - result.setResult(e.toString()); - callback.complete(result); - return null; - } - - CreateBaseImageResult result = new CreateBaseImageResult( - templateOnPrimaryStoreObj); - callback.complete(result); - return null; - } - - try { - objectInDataStoreMgr.update(templateOnPrimaryStoreObj, - ObjectInDataStoreStateMachine.Event.CreateRequested); - } catch (NoTransitionException e) { - try { - objectInDataStoreMgr.update(templateOnPrimaryStoreObj, - ObjectInDataStoreStateMachine.Event.OperationFailed); - } catch (NoTransitionException e1) { - s_logger.debug("state transation failed", e1); - } - CreateBaseImageResult result = new CreateBaseImageResult(null); - result.setSuccess(false); - result.setResult(e.toString()); - callback.complete(result); - return null; - } - - InstallContext context = new InstallContext( - callback, templateOnPrimaryStoreObj, template); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher - .create(this); - caller.setCallback( - caller.getTarget().installTemplateCallback(null, null)) - .setContext(context); - - store.getDriver().createAsync(templateOnPrimaryStoreObj, caller); - return null; - } - - class CopyTemplateContext extends AsyncRpcConext { - TemplateInfo template; - - public CopyTemplateContext(AsyncCompletionCallback callback, - TemplateInfo template) { - super(callback); - this.template = template; - } - } - - protected Void installTemplateCallback( - AsyncCallbackDispatcher callback, - InstallContext context) { - CreateCmdResult result = callback.getResult(); - TemplateInfo templateOnPrimaryStoreObj = context.destTemplate; - CreateBaseImageResult upResult = new CreateBaseImageResult( - templateOnPrimaryStoreObj); - if (result.isFailed()) { - upResult.setResult(result.getResult()); - context.getParentCallback().complete(upResult); - return null; - } - - ObjectInDataStoreVO obj = objectInDataStoreMgr.findObject( - templateOnPrimaryStoreObj.getId(), templateOnPrimaryStoreObj - .getType(), templateOnPrimaryStoreObj.getDataStore() - .getId(), templateOnPrimaryStoreObj.getDataStore() - .getRole()); - - obj.setInstallPath(result.getPath()); - obj.setSize(result.getSize()); - try { - objectInDataStoreMgr.update(obj, - ObjectInDataStoreStateMachine.Event.OperationSuccessed); - } catch (NoTransitionException e) { - try { - objectInDataStoreMgr.update(obj, - ObjectInDataStoreStateMachine.Event.OperationFailed); - } catch (NoTransitionException e1) { - s_logger.debug("failed to change state", e1); - } - - upResult.setResult(e.toString()); - context.getParentCallback().complete(upResult); - return null; - } - - moveTemplate(context.srcTemplate, templateOnPrimaryStoreObj, obj, - context.getParentCallback()); - return null; - } - - protected void moveTemplate(TemplateInfo srcTemplate, - TemplateInfo destTemplate, ObjectInDataStoreVO obj, - AsyncCompletionCallback callback) { - // move template into primary storage - try { - objectInDataStoreMgr.update(destTemplate, - ObjectInDataStoreStateMachine.Event.CopyingRequested); - } catch (NoTransitionException e) { - s_logger.debug("failed to change state", e); - try { - objectInDataStoreMgr.update(destTemplate, - ObjectInDataStoreStateMachine.Event.OperationFailed); - } catch (NoTransitionException e1) { - - } - CreateBaseImageResult res = new CreateBaseImageResult(destTemplate); - res.setResult("Failed to change state: " + e.toString()); - callback.complete(res); - } - - CopyTemplateContext anotherCall = new CopyTemplateContext( - callback, destTemplate); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher - .create(this); - caller.setCallback(caller.getTarget().copyTemplateCallback(null, null)) - .setContext(anotherCall); - - motionSrv.copyAsync(srcTemplate, destTemplate, caller); - } - - protected Void copyTemplateCallback( - AsyncCallbackDispatcher callback, - CopyTemplateContext context) { - CopyCommandResult result = callback.getResult(); - TemplateInfo templateOnPrimaryStoreObj = context.template; - if (result.isFailed()) { - CreateBaseImageResult res = new CreateBaseImageResult( - templateOnPrimaryStoreObj); - res.setResult(result.getResult()); - context.getParentCallback().complete(res); - } - DataObjectInStore obj = objectInDataStoreMgr.findObject( - templateOnPrimaryStoreObj, templateOnPrimaryStoreObj.getDataStore()); - - - CreateBaseImageResult res = new CreateBaseImageResult( - templateOnPrimaryStoreObj); - try { - objectInDataStoreMgr.update(obj, - ObjectInDataStoreStateMachine.Event.OperationSuccessed); - } catch (NoTransitionException e) { - s_logger.debug("Failed to update copying state: ", e); - try { - objectInDataStoreMgr.update(templateOnPrimaryStoreObj, - ObjectInDataStoreStateMachine.Event.OperationFailed); - } catch (NoTransitionException e1) { - } - - res.setResult("Failed to update copying state: " + e.toString()); - context.getParentCallback().complete(res); - } - context.getParentCallback().complete(res); - return null; - }*/ - @Override - public Void installAsync(TemplateInfo template, PrimaryDataStore store, - AsyncCompletionCallback callback) { - // TODO Auto-generated method stub - return null; - } - -} diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeDataFactoryImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeDataFactoryImpl.java index e0ecd165d7f..8d0a5a82bb1 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeDataFactoryImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeDataFactoryImpl.java @@ -21,15 +21,15 @@ package org.apache.cloudstack.storage.volume; import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType; 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.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; -import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; +import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO; import org.springframework.stereotype.Component; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.VolumeDao; @@ -38,24 +38,29 @@ public class VolumeDataFactoryImpl implements VolumeDataFactory { @Inject VolumeDao volumeDao; @Inject - ObjectInDataStoreManager objMap; + VolumeDataStoreDao volumeStoreDao; @Inject DataStoreManager storeMgr; + @Override public VolumeInfo getVolume(long volumeId, DataStore store) { VolumeVO volumeVO = volumeDao.findById(volumeId); - + VolumeObject vol = VolumeObject.getVolumeObject(store, volumeVO); - + return vol; } - + @Override public VolumeInfo getVolume(long volumeId) { VolumeVO volumeVO = volumeDao.findById(volumeId); VolumeObject vol = null; if (volumeVO.getPoolId() == null) { - DataStore store = objMap.findStore(volumeVO.getUuid(), DataObjectType.VOLUME, DataStoreRole.Image); + DataStore store = null; + VolumeDataStoreVO volumeStore = volumeStoreDao.findByVolume(volumeId); + if (volumeStore != null) { + store = this.storeMgr.getDataStore(volumeStore.getDataStoreId(), DataStoreRole.Image); + } vol = VolumeObject.getVolumeObject(store, volumeVO); } else { DataStore store = this.storeMgr.getDataStore(volumeVO.getPoolId(), DataStoreRole.Primary); @@ -66,8 +71,8 @@ public class VolumeDataFactoryImpl implements VolumeDataFactory { @Override public VolumeInfo getVolume(DataObject volume, DataStore store) { - VolumeInfo vol = (VolumeObject)getVolume(volume.getId(), store); - vol.addPayload(((VolumeInfo)volume).getpayload()); + VolumeInfo vol = getVolume(volume.getId(), store); + vol.addPayload(((VolumeInfo) volume).getpayload()); return vol; } diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeEntityImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeEntityImpl.java deleted file mode 100644 index d3e8c543b54..00000000000 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeEntityImpl.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.volume; - -import java.lang.reflect.Method; -import java.util.Date; -import java.util.List; -import java.util.Map; - -import org.apache.cloudstack.engine.cloud.entity.api.SnapshotEntity; -import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity; -import org.apache.cloudstack.engine.datacenter.entity.api.StorageEntity; -import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult; -import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat; -import org.apache.cloudstack.engine.subsystem.api.storage.type.VolumeType; -import org.apache.cloudstack.storage.datastore.PrimaryDataStoreEntityImpl; - -public class VolumeEntityImpl implements VolumeEntity { - private VolumeInfo volumeInfo; - private final VolumeService vs; - private VolumeApiResult result; - - public VolumeEntityImpl() { - this.vs = null; - } - - public VolumeEntityImpl(VolumeInfo volumeObject, VolumeService vs) { - this.volumeInfo = volumeObject; - this.vs = vs; - } - - public VolumeInfo getVolumeInfo() { - return volumeInfo; - } - - @Override - public String getUuid() { - return volumeInfo.getUuid(); - } - - @Override - public long getId() { - return volumeInfo.getId(); - } - - public String getExternalId() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getCurrentState() { - return null; - } - - @Override - public String getDesiredState() { - return null; - } - - @Override - public Date getCreatedTime() { - return null; - } - - @Override - public Date getLastUpdatedTime() { - return null; - } - - @Override - public String getOwner() { - return null; - } - - - @Override - public List getApplicableActions() { - // TODO Auto-generated method stub - return null; - } - - @Override - public SnapshotEntity takeSnapshotOf(boolean full) { - // TODO Auto-generated method stub - return null; - } - - @Override - public String reserveForMigration(long expirationTime) { - // TODO Auto-generated method stub - return null; - } - - @Override - public void migrate(String reservationToken) { - // TODO Auto-generated method stub - - } - - @Override - public VolumeEntity setupForCopy() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void copy(VolumeEntity dest) { - // TODO Auto-generated method stub - - } - - @Override - public void attachTo(String vm, long deviceId) { - // TODO Auto-generated method stub - - } - - @Override - public void detachFrom() { - // TODO Auto-generated method stub - - } - - - @Override - public long getSize() { - return volumeInfo.getSize(); - } - - @Override - public DiskFormat getDiskType() { - return null; - } - - @Override - public VolumeType getType() { - return null; - } - - @Override - public StorageEntity getDataStore() { - return new PrimaryDataStoreEntityImpl((PrimaryDataStoreInfo) volumeInfo.getDataStore()); - } - - @Override - public void destroy() { - /*AsyncCallFuture future = vs.deleteVolumeAsync(volumeInfo); - try { - result = future.get(); - if (!result.isSuccess()) { - throw new CloudRuntimeException("Failed to create volume:" + result.getResult()); - } - } catch (InterruptedException e) { - throw new CloudRuntimeException("wait to delete volume info failed", e); - } catch (ExecutionException e) { - throw new CloudRuntimeException("wait to delete volume failed", e); - }*/ - } - - @Override - public Map getDetails() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void addDetail(String name, String value) { - // TODO Auto-generated method stub - - } - - @Override - public void delDetail(String name, String value) { - // TODO Auto-generated method stub - - } - - @Override - public void updateDetail(String name, String value) { - // TODO Auto-generated method stub - - } - -} diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeMotionService.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeMotionService.java deleted file mode 100644 index 9349e6b11cc..00000000000 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeMotionService.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cloudstack.storage.volume; - -public interface VolumeMotionService { - boolean copyVolume(String volumeUri, String destVolumeUri); -} diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java index ea31be3d6a0..071c110da48 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java @@ -20,17 +20,27 @@ import java.util.Date; import javax.inject.Inject; +import com.cloud.storage.DiskOfferingVO; +import com.cloud.storage.dao.DiskOfferingDao; import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType; 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.ObjectInDataStoreStateMachine; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat; +import org.apache.cloudstack.storage.command.CopyCmdAnswer; +import org.apache.cloudstack.storage.command.CreateObjectAnswer; import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; +import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.log4j.Logger; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.storage.DownloadAnswer; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataTO; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Volume; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.VolumeDao; @@ -39,6 +49,8 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.fsm.StateMachine2; import com.cloud.utils.storage.encoding.EncodingType; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.dao.VMInstanceDao; public class VolumeObject implements VolumeInfo { private static final Logger s_logger = Logger.getLogger(VolumeObject.class); @@ -48,13 +60,19 @@ public class VolumeObject implements VolumeInfo { @Inject VolumeDao volumeDao; @Inject - ObjectInDataStoreManager ojbectInStoreMgr; + VolumeDataStoreDao volumeStoreDao; + @Inject + ObjectInDataStoreManager objectInStoreMgr; + @Inject + VMInstanceDao vmInstanceDao; + @Inject + DiskOfferingDao diskOfferingDao; private Object payload; public VolumeObject() { _volStateMachine = Volume.State.getStateMachine(); } - + protected void configure(DataStore dataStore, VolumeVO volumeVO) { this.volumeVO = volumeVO; this.dataStore = dataStore; @@ -66,19 +84,34 @@ public class VolumeObject implements VolumeInfo { return vo; } + @Override + public String getAttachedVmName() { + Long vmId = this.volumeVO.getInstanceId(); + if (vmId != null) { + VMInstanceVO vm = vmInstanceDao.findById(vmId); + + if (vm == null) { + return null; + } + return vm.getInstanceName(); + } + return null; + } + @Override public String getUuid() { return volumeVO.getUuid(); } - public void setPath(String uuid) { - volumeVO.setPath(uuid); - } - - public void setSize(Long size) { - volumeVO.setSize(size); + public void setUuid(String uuid) { + volumeVO.setUuid(uuid); } + public void setSize(Long size) { + volumeVO.setSize(size); + } + + @Override public Volume.State getState() { return volumeVO.getState(); } @@ -96,9 +129,12 @@ public class VolumeObject implements VolumeInfo { public long getVolumeId() { return volumeVO.getId(); } + + @Override public boolean stateTransit(Volume.Event event) { boolean result = false; try { + volumeVO = volumeDao.findById(volumeVO.getId()); result = _volStateMachine.transitTo(volumeVO, event, null, volumeDao); volumeVO = volumeDao.findById(volumeVO.getId()); } catch (NoTransitionException e) { @@ -109,6 +145,50 @@ public class VolumeObject implements VolumeInfo { return result; } + private DiskOfferingVO getDiskOfferingVO() { + if (getDiskOfferingId() != null) { + DiskOfferingVO diskOfferingVO = diskOfferingDao.findById(getDiskOfferingId()); + return diskOfferingVO; + } + return null; + } + + @Override + public Long getBytesReadRate() { + DiskOfferingVO diskOfferingVO = getDiskOfferingVO(); + if (diskOfferingVO != null) { + return diskOfferingVO.getBytesReadRate(); + } + return null; + } + + @Override + public Long getBytesWriteRate() { + DiskOfferingVO diskOfferingVO = getDiskOfferingVO(); + if (diskOfferingVO != null) { + return diskOfferingVO.getBytesWriteRate(); + } + return null; + } + + @Override + public Long getIopsReadRate() { + DiskOfferingVO diskOfferingVO = getDiskOfferingVO(); + if (diskOfferingVO != null) { + return diskOfferingVO.getIopsReadRate(); + } + return null; + } + + @Override + public Long getIopsWriteRate() { + DiskOfferingVO diskOfferingVO = getDiskOfferingVO(); + if (diskOfferingVO != null) { + return diskOfferingVO.getIopsWriteRate(); + } + return null; + } + public void update() { volumeDao.update(volumeVO.getId(), volumeVO); volumeVO = volumeDao.findById(volumeVO.getId()); @@ -129,16 +209,15 @@ public class VolumeObject implements VolumeInfo { if (this.dataStore == null) { throw new CloudRuntimeException("datastore must be set before using this object"); } - DataObjectInStore obj = ojbectInStoreMgr.findObject(this.volumeVO.getUuid(), DataObjectType.VOLUME, this.dataStore.getUuid(), this.dataStore.getRole()); + DataObjectInStore obj = objectInStoreMgr.findObject(this.volumeVO.getId(), DataObjectType.VOLUME, + this.dataStore.getId(), this.dataStore.getRole()); if (obj.getState() != ObjectInDataStoreStateMachine.State.Ready) { - return this.dataStore.getUri() + - "&" + EncodingType.OBJTYPE + "=" + DataObjectType.VOLUME + - "&" + EncodingType.SIZE + "=" + this.volumeVO.getSize() + - "&" + EncodingType.NAME + "=" + this.volumeVO.getName(); + return this.dataStore.getUri() + "&" + EncodingType.OBJTYPE + "=" + DataObjectType.VOLUME + "&" + + EncodingType.SIZE + "=" + this.volumeVO.getSize() + "&" + EncodingType.NAME + "=" + + this.volumeVO.getName(); } else { - return this.dataStore.getUri() + - "&" + EncodingType.OBJTYPE + "=" + DataObjectType.VOLUME + - "&" + EncodingType.PATH + "=" + obj.getInstallPath(); + return this.dataStore.getUri() + "&" + EncodingType.OBJTYPE + "=" + DataObjectType.VOLUME + "&" + + EncodingType.PATH + "=" + obj.getInstallPath(); } } @@ -148,31 +227,31 @@ public class VolumeObject implements VolumeInfo { } @Override - public DiskFormat getFormat() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void processEvent( - ObjectInDataStoreStateMachine.Event event) { + public void processEvent(ObjectInDataStoreStateMachine.Event event) { if (this.dataStore == null) { return; } try { Volume.Event volEvent = null; + if (this.dataStore.getRole() == DataStoreRole.ImageCache) { + objectInStoreMgr.update(this, event); + return; + } if (this.dataStore.getRole() == DataStoreRole.Image) { - ojbectInStoreMgr.update(this, event); - if (event == ObjectInDataStoreStateMachine.Event.CreateRequested) { + objectInStoreMgr.update(this, event); + if (this.volumeVO.getState() == Volume.State.Migrating + || this.volumeVO.getState() == Volume.State.Copying + || this.volumeVO.getState() == Volume.State.Uploaded) { + return; + } + if (event == ObjectInDataStoreStateMachine.Event.CreateOnlyRequested) { volEvent = Volume.Event.UploadRequested; - } else if (event == ObjectInDataStoreStateMachine.Event.OperationSuccessed) { - volEvent = Volume.Event.CopySucceeded; - } else if (event == ObjectInDataStoreStateMachine.Event.OperationFailed) { - volEvent = Volume.Event.CopyFailed; + } else if (event == ObjectInDataStoreStateMachine.Event.MigrationRequested) { + volEvent = Volume.Event.CopyRequested; } } else { - if (event == ObjectInDataStoreStateMachine.Event.CreateRequested || - event == ObjectInDataStoreStateMachine.Event.CreateOnlyRequested) { + if (event == ObjectInDataStoreStateMachine.Event.CreateRequested + || event == ObjectInDataStoreStateMachine.Event.CreateOnlyRequested) { volEvent = Volume.Event.CreateRequested; } else if (event == ObjectInDataStoreStateMachine.Event.CopyingRequested) { volEvent = Volume.Event.CopyRequested; @@ -180,7 +259,7 @@ public class VolumeObject implements VolumeInfo { volEvent = Volume.Event.MigrationRequested; } } - + if (event == ObjectInDataStoreStateMachine.Event.DestroyRequested) { volEvent = Volume.Event.DestroyRequested; } else if (event == ObjectInDataStoreStateMachine.Event.ExpungeRequested) { @@ -190,16 +269,37 @@ public class VolumeObject implements VolumeInfo { } else if (event == ObjectInDataStoreStateMachine.Event.OperationFailed) { volEvent = Volume.Event.OperationFailed; } else if (event == ObjectInDataStoreStateMachine.Event.ResizeRequested) { - volEvent = Volume.Event.ResizeRequested; + volEvent = Volume.Event.ResizeRequested; } this.stateTransit(volEvent); } catch (Exception e) { s_logger.debug("Failed to update state", e); throw new CloudRuntimeException("Failed to update state:" + e.toString()); + } finally { + // in case of OperationFailed, expunge the entry + if (event == ObjectInDataStoreStateMachine.Event.OperationFailed + && (this.volumeVO.getState() != Volume.State.Copying && this.volumeVO.getState() != Volume.State.Uploaded)) { + objectInStoreMgr.delete(this); + } } } + @Override + public void processEventOnly(ObjectInDataStoreStateMachine.Event event) { + try { + objectInStoreMgr.update(this, event); + } catch (Exception e) { + s_logger.debug("Failed to update state", e); + throw new CloudRuntimeException("Failed to update state:" + e.toString()); + } finally { + // in case of OperationFailed, expunge the entry + if (event == ObjectInDataStoreStateMachine.Event.OperationFailed) { + objectInStoreMgr.delete(this); + } + } + } + @Override public String getName() { return this.volumeVO.getName(); @@ -217,7 +317,12 @@ public class VolumeObject implements VolumeInfo { @Override public String getPath() { - return this.volumeVO.getPath(); + if (this.dataStore.getRole() == DataStoreRole.Primary) { + return this.volumeVO.getPath(); + } else { + DataObjectInStore objInStore = this.objectInStoreMgr.findObject(this, dataStore); + return objInStore.getInstallPath(); + } } @Override @@ -256,7 +361,7 @@ public class VolumeObject implements VolumeInfo { } @Override - public long getDiskOfferingId() { + public Long getDiskOfferingId() { return this.volumeVO.getDiskOfferingId(); } @@ -317,16 +422,180 @@ public class VolumeObject implements VolumeInfo { @Override public Object getpayload() { - return this.payload; + return this.payload; } - @Override - public HypervisorType getHypervisorType() { - return this.volumeDao.getHypervisorType(this.volumeVO.getId()); - } + public VolumeVO getVolume() { + return this.volumeVO; + } - @Override - public Long getLastPoolId() { - return this.volumeVO.getLastPoolId(); - } + @Override + public HypervisorType getHypervisorType() { + return this.volumeDao.getHypervisorType(this.volumeVO.getId()); + } + + @Override + public Long getLastPoolId() { + return this.volumeVO.getLastPoolId(); + } + + @Override + public DataTO getTO() { + DataTO to = this.getDataStore().getDriver().getTO(this); + if (to == null) { + to = new VolumeObjectTO(this); + } + return to; + } + + @Override + public void processEvent(ObjectInDataStoreStateMachine.Event event, Answer answer) { + try { + if (this.dataStore.getRole() == DataStoreRole.Primary) { + if (answer instanceof CopyCmdAnswer) { + CopyCmdAnswer cpyAnswer = (CopyCmdAnswer) answer; + VolumeVO vol = this.volumeDao.findById(this.getId()); + VolumeObjectTO newVol = (VolumeObjectTO) cpyAnswer.getNewData(); + vol.setPath(newVol.getPath()); + vol.setSize(newVol.getSize()); + vol.setPoolId(this.getDataStore().getId()); + volumeDao.update(vol.getId(), vol); + } else if (answer instanceof CreateObjectAnswer) { + CreateObjectAnswer createAnswer = (CreateObjectAnswer) answer; + VolumeObjectTO newVol = (VolumeObjectTO) createAnswer.getData(); + VolumeVO vol = this.volumeDao.findById(this.getId()); + vol.setPath(newVol.getPath()); + vol.setSize(newVol.getSize()); + vol.setPoolId(this.getDataStore().getId()); + volumeDao.update(vol.getId(), vol); + } + } else { + // image store or imageCache store + if (answer instanceof DownloadAnswer) { + DownloadAnswer dwdAnswer = (DownloadAnswer) answer; + VolumeDataStoreVO volStore = this.volumeStoreDao.findByStoreVolume(this.dataStore.getId(), + this.getId()); + volStore.setInstallPath(dwdAnswer.getInstallPath()); + volStore.setChecksum(dwdAnswer.getCheckSum()); + this.volumeStoreDao.update(volStore.getId(), volStore); + } else if (answer instanceof CopyCmdAnswer) { + CopyCmdAnswer cpyAnswer = (CopyCmdAnswer) answer; + VolumeDataStoreVO volStore = this.volumeStoreDao.findByStoreVolume(this.dataStore.getId(), + this.getId()); + VolumeObjectTO newVol = (VolumeObjectTO) cpyAnswer.getNewData(); + volStore.setInstallPath(newVol.getPath()); + volStore.setSize(newVol.getSize()); + this.volumeStoreDao.update(volStore.getId(), volStore); + } + } + } catch (RuntimeException ex) { + if (event == ObjectInDataStoreStateMachine.Event.OperationFailed) { + objectInStoreMgr.delete(this); + } + throw ex; + } + this.processEvent(event); + + } + + public void incRefCount() { + if (this.dataStore == null) { + return; + } + + if (this.dataStore.getRole() == DataStoreRole.Image || this.dataStore.getRole() == DataStoreRole.ImageCache) { + VolumeDataStoreVO store = volumeStoreDao.findByStoreVolume(this.dataStore.getId(), this.getId()); + store.incrRefCnt(); + store.setLastUpdated(new Date()); + volumeStoreDao.update(store.getId(), store); + } + } + + @Override + public void decRefCount() { + if (this.dataStore == null) { + return; + } + if (this.dataStore.getRole() == DataStoreRole.Image || this.dataStore.getRole() == DataStoreRole.ImageCache) { + VolumeDataStoreVO store = volumeStoreDao.findByStoreVolume(this.dataStore.getId(), this.getId()); + store.decrRefCnt(); + store.setLastUpdated(new Date()); + volumeStoreDao.update(store.getId(), store); + } + } + + @Override + public Long getRefCount() { + if (this.dataStore == null) { + return null; + } + if (this.dataStore.getRole() == DataStoreRole.Image || this.dataStore.getRole() == DataStoreRole.ImageCache) { + VolumeDataStoreVO store = volumeStoreDao.findByStoreVolume(this.dataStore.getId(), this.getId()); + return store.getRefCnt(); + } + return null; + } + + @Override + public void processEventOnly(ObjectInDataStoreStateMachine.Event event, Answer answer) { + try { + if (this.dataStore.getRole() == DataStoreRole.Primary) { + if (answer instanceof CopyCmdAnswer) { + CopyCmdAnswer cpyAnswer = (CopyCmdAnswer) answer; + VolumeVO vol = this.volumeDao.findById(this.getId()); + VolumeObjectTO newVol = (VolumeObjectTO) cpyAnswer.getNewData(); + vol.setPath(newVol.getPath()); + vol.setSize(newVol.getSize()); + vol.setPoolId(this.getDataStore().getId()); + volumeDao.update(vol.getId(), vol); + } else if (answer instanceof CreateObjectAnswer) { + CreateObjectAnswer createAnswer = (CreateObjectAnswer) answer; + VolumeObjectTO newVol = (VolumeObjectTO) createAnswer.getData(); + VolumeVO vol = this.volumeDao.findById(this.getId()); + vol.setPath(newVol.getPath()); + vol.setSize(newVol.getSize()); + vol.setPoolId(this.getDataStore().getId()); + volumeDao.update(vol.getId(), vol); + } + } else { + // image store or imageCache store + if (answer instanceof DownloadAnswer) { + DownloadAnswer dwdAnswer = (DownloadAnswer) answer; + VolumeDataStoreVO volStore = this.volumeStoreDao.findByStoreVolume(this.dataStore.getId(), + this.getId()); + volStore.setInstallPath(dwdAnswer.getInstallPath()); + volStore.setChecksum(dwdAnswer.getCheckSum()); + this.volumeStoreDao.update(volStore.getId(), volStore); + } else if (answer instanceof CopyCmdAnswer) { + CopyCmdAnswer cpyAnswer = (CopyCmdAnswer) answer; + VolumeDataStoreVO volStore = this.volumeStoreDao.findByStoreVolume(this.dataStore.getId(), + this.getId()); + VolumeObjectTO newVol = (VolumeObjectTO) cpyAnswer.getNewData(); + volStore.setInstallPath(newVol.getPath()); + volStore.setSize(newVol.getSize()); + this.volumeStoreDao.update(volStore.getId(), volStore); + } + } + } catch (RuntimeException ex) { + if (event == ObjectInDataStoreStateMachine.Event.OperationFailed) { + objectInStoreMgr.delete(this); + } + throw ex; + } + this.processEventOnly(event); + + } + + @Override + public ImageFormat getFormat() { + return this.volumeVO.getFormat(); + } + + @Override + public boolean delete() { + if (dataStore != null) { + return dataStore.delete(this); + } + return true; + } } diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java index 54dcbd2599e..1d36f938fdf 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java @@ -18,20 +18,22 @@ */ package org.apache.cloudstack.storage.volume; -import java.util.Map; -import java.util.List; import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; import javax.inject.Inject; import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity; -import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; @@ -41,33 +43,46 @@ import org.apache.cloudstack.framework.async.AsyncCallFuture; import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.framework.async.AsyncRpcConext; +import org.apache.cloudstack.storage.command.CommandResult; +import org.apache.cloudstack.storage.command.DeleteCommand; import org.apache.cloudstack.storage.datastore.DataObjectManager; import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; import org.apache.cloudstack.storage.datastore.PrimaryDataStore; import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.cloudstack.storage.motion.DataMotionService; +import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.storage.ListVolumeAnswer; +import com.cloud.agent.api.storage.ListVolumeCommand; import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.alert.AlertManager; +import com.cloud.configuration.Config; +import com.cloud.configuration.Resource.ResourceType; +import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.ResourceAllocationException; import com.cloud.host.Host; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.StoragePool; +import com.cloud.storage.VMTemplateStorageResourceAssoc; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.Volume; -import com.cloud.storage.Volume.Type; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.snapshot.SnapshotManager; +import com.cloud.storage.template.TemplateProp; +import com.cloud.user.AccountManager; +import com.cloud.user.ResourceLimitService; +import com.cloud.utils.NumbersUtil; import com.cloud.utils.db.DB; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.vm.VirtualMachine; -import com.cloud.vm.dao.VMInstanceDao; @Component public class VolumeServiceImpl implements VolumeService { - private static final Logger s_logger = Logger - .getLogger(VolumeServiceImpl.class); + private static final Logger s_logger = Logger.getLogger(VolumeServiceImpl.class); @Inject VolumeDao volDao; @Inject @@ -79,87 +94,98 @@ public class VolumeServiceImpl implements VolumeService { @Inject DataMotionService motionSrv; @Inject - TemplateInstallStrategy templateInstallStrategy; - @Inject VolumeDataFactory volFactory; - @Inject SnapshotManager snapshotMgr; - @Inject VMInstanceDao vmDao; + @Inject + SnapshotManager snapshotMgr; + @Inject + ResourceLimitService _resourceLimitMgr; + @Inject + AccountManager _accountMgr; + @Inject + AlertManager _alertMgr; + @Inject + ConfigurationDao configDao; + @Inject + VolumeDataStoreDao _volumeStoreDao; + @Inject + VolumeDao _volumeDao; + @Inject + EndPointSelector _epSelector; public VolumeServiceImpl() { } - + private class CreateVolumeContext extends AsyncRpcConext { - private DataObject volume; - private AsyncCallFuture future; - /** - * @param callback - */ - public CreateVolumeContext(AsyncCompletionCallback callback, DataObject volume, AsyncCallFuture future) { + private final DataObject volume; + private final AsyncCallFuture future; + + public CreateVolumeContext(AsyncCompletionCallback callback, DataObject volume, + AsyncCallFuture future) { super(callback); this.volume = volume; this.future = future; } - + public DataObject getVolume() { return this.volume; } - + public AsyncCallFuture getFuture() { return this.future; } - + } - + @Override public AsyncCallFuture createVolumeAsync(VolumeInfo volume, DataStore dataStore) { AsyncCallFuture future = new AsyncCallFuture(); DataObject volumeOnStore = dataStore.create(volume); volumeOnStore.processEvent(Event.CreateOnlyRequested); - CreateVolumeContext context = new CreateVolumeContext(null, volumeOnStore, future); + CreateVolumeContext context = new CreateVolumeContext(null, volumeOnStore, + future); AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); - caller.setCallback(caller.getTarget().createVolumeCallback(null, null)) - .setContext(context); - + caller.setCallback(caller.getTarget().createVolumeCallback(null, null)).setContext(context); + dataStore.getDriver().createAsync(volumeOnStore, caller); return future; } - - protected Void createVolumeCallback(AsyncCallbackDispatcher callback, CreateVolumeContext context) { + + protected Void createVolumeCallback(AsyncCallbackDispatcher callback, + CreateVolumeContext context) { CreateCmdResult result = callback.getResult(); DataObject vo = context.getVolume(); String errMsg = null; if (result.isSuccess()) { - vo.processEvent(Event.OperationSuccessed); + vo.processEvent(Event.OperationSuccessed, result.getAnswer()); } else { vo.processEvent(Event.OperationFailed); errMsg = result.getResult(); } - VolumeApiResult volResult = new VolumeApiResult((VolumeObject)vo); + VolumeApiResult volResult = new VolumeApiResult((VolumeObject) vo); if (errMsg != null) { volResult.setResult(errMsg); } context.getFuture().complete(volResult); return null; } - + private class DeleteVolumeContext extends AsyncRpcConext { private final VolumeObject volume; - private AsyncCallFuture future; - /** - * @param callback - */ - public DeleteVolumeContext(AsyncCompletionCallback callback, VolumeObject volume, AsyncCallFuture future) { + private final AsyncCallFuture future; + + public DeleteVolumeContext(AsyncCompletionCallback callback, VolumeObject volume, + AsyncCallFuture future) { super(callback); this.volume = volume; this.future = future; } - + public VolumeObject getVolume() { return this.volume; } - + public AsyncCallFuture getFuture() { return this.future; } @@ -167,51 +193,51 @@ public class VolumeServiceImpl implements VolumeService { @DB @Override - public AsyncCallFuture expungeVolumeAsync(VolumeInfo volume) { + public AsyncCallFuture expungeVolumeAsync(VolumeInfo volume) { AsyncCallFuture future = new AsyncCallFuture(); VolumeApiResult result = new VolumeApiResult(volume); if (volume.getDataStore() == null) { - this.volDao.remove(volume.getId()); + volDao.remove(volume.getId()); future.complete(result); return future; } - - String vmName = null; - VolumeVO vol = this.volDao.findById(volume.getId()); - if (vol.getVolumeType() == Type.ROOT && vol.getInstanceId() != null) { - VirtualMachine vm = vmDao.findByIdIncludingRemoved(vol - .getInstanceId()); - if (vm != null) { - vmName = vm.getInstanceName(); + + // Find out if the volume is at state of download_in_progress on secondary storage + VolumeDataStoreVO volumeStore = _volumeStoreDao.findByVolume(volume.getId()); + if (volumeStore != null) { + if (volumeStore.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS) { + s_logger.debug("Volume: " + volume.getName() + " is currently being uploaded; cant' delete it."); + future.complete(result); + return future; } } + VolumeVO vol = volDao.findById(volume.getId()); + String volumePath = vol.getPath(); Long poolId = vol.getPoolId(); if (poolId == null || volumePath == null || volumePath.trim().isEmpty()) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Marking volume that was never created as destroyed: " - + vol); + s_logger.debug("Marking volume that was never created as destroyed: " + vol); } - this.volDao.remove(vol.getId()); + volDao.remove(vol.getId()); future.complete(result); return future; } - VolumeObject vo = (VolumeObject)volume; - + VolumeObject vo = (VolumeObject) volume; + volume.processEvent(Event.ExpungeRequested); - - + DeleteVolumeContext context = new DeleteVolumeContext(null, vo, future); AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); - caller.setCallback(caller.getTarget().deleteVolumeCallback(null, null)) - .setContext(context); - + caller.setCallback(caller.getTarget().deleteVolumeCallback(null, null)).setContext(context); + volume.getDataStore().getDriver().deleteAsync(volume, caller); return future; } - - public Void deleteVolumeCallback(AsyncCallbackDispatcher callback, DeleteVolumeContext context) { + + public Void deleteVolumeCallback(AsyncCallbackDispatcher callback, + DeleteVolumeContext context) { CommandResult result = callback.getResult(); VolumeObject vo = context.getVolume(); VolumeApiResult apiResult = new VolumeApiResult(vo); @@ -234,17 +260,7 @@ public class VolumeServiceImpl implements VolumeService { @Override public VolumeEntity getVolumeEntity(long volumeId) { - VolumeVO vo = volDao.findById(volumeId); - if (vo == null) { - return null; - } - - if (vo.getPoolId() == null) { - return new VolumeEntityImpl(VolumeObject.getVolumeObject(null, vo), this); - } else { - PrimaryDataStore dataStore = dataStoreMgr.getPrimaryDataStore(vo.getPoolId()); - return new VolumeEntityImpl(dataStore.getVolume(volumeId), this); - } + return null; } class CreateBaseImageContext extends AsyncRpcConext { @@ -253,9 +269,10 @@ public class VolumeServiceImpl implements VolumeService { private final TemplateInfo srcTemplate; private final AsyncCallFuture future; final DataObject destObj; - public CreateBaseImageContext(AsyncCompletionCallback callback, VolumeInfo volume, PrimaryDataStore datastore, - TemplateInfo srcTemplate, - AsyncCallFuture future, DataObject destObj) { + + public CreateBaseImageContext(AsyncCompletionCallback callback, VolumeInfo volume, + PrimaryDataStore datastore, TemplateInfo srcTemplate, AsyncCallFuture future, + DataObject destObj) { super(callback); this.volume = volume; this.dataStore = datastore; @@ -263,11 +280,11 @@ public class VolumeServiceImpl implements VolumeService { this.srcTemplate = srcTemplate; this.destObj = destObj; } - + public VolumeInfo getVolume() { return this.volume; } - + public PrimaryDataStore getDataStore() { return this.dataStore; } @@ -275,35 +292,68 @@ public class VolumeServiceImpl implements VolumeService { public TemplateInfo getSrcTemplate() { return this.srcTemplate; } - + public AsyncCallFuture getFuture() { return this.future; } - + } - - static class CreateBaseImageResult extends CommandResult { - final TemplateInfo template; - public CreateBaseImageResult(TemplateInfo template) { - super(); - this.template = template; + + private TemplateInfo waitForTemplateDownloaded(PrimaryDataStore store, TemplateInfo template) { + int storagePoolMaxWaitSeconds = NumbersUtil.parseInt( + configDao.getValue(Config.StoragePoolMaxWaitSeconds.key()), 3600); + int sleepTime = 120; + int tries = storagePoolMaxWaitSeconds / sleepTime; + while (tries > 0) { + TemplateInfo tmpl = store.getTemplate(template.getId()); + if (tmpl != null) { + return tmpl; + } + try { + Thread.sleep(sleepTime * 1000); + } catch (InterruptedException e) { + s_logger.debug("waiting for template download been interrupted: " + e.toString()); + } + tries--; } + return null; } - + @DB - protected void createBaseImageAsync(VolumeInfo volume, PrimaryDataStore dataStore, TemplateInfo template, AsyncCallFuture future) { - + protected void createBaseImageAsync(VolumeInfo volume, PrimaryDataStore dataStore, TemplateInfo template, + AsyncCallFuture future) { + DataObject templateOnPrimaryStoreObj = dataStore.create(template); - CreateBaseImageContext context = new CreateBaseImageContext(null, volume, - dataStore, - template, - future, templateOnPrimaryStoreObj); + CreateBaseImageContext context = new CreateBaseImageContext(null, volume, + dataStore, template, future, templateOnPrimaryStoreObj); AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); - caller.setCallback(caller.getTarget().copyBaseImageCallback(null, null)) - .setContext(context); - - templateOnPrimaryStoreObj.processEvent(Event.CreateOnlyRequested); - + caller.setCallback(caller.getTarget().copyBaseImageCallback(null, null)).setContext(context); + + try { + templateOnPrimaryStoreObj.processEvent(Event.CreateOnlyRequested); + } catch (Exception e) { + s_logger.info("Got exception in case of multi-thread"); + try { + templateOnPrimaryStoreObj = waitForTemplateDownloaded(dataStore, template); + } catch (Exception e1) { + s_logger.debug("wait for template:" + template.getId() + " downloading finished, but failed"); + VolumeApiResult result = new VolumeApiResult(volume); + result.setResult(e1.toString()); + future.complete(result); + return; + } + if (templateOnPrimaryStoreObj == null) { + VolumeApiResult result = new VolumeApiResult(volume); + result.setResult("wait for template:" + template.getId() + " downloading finished, but failed"); + future.complete(result); + return; + } else { + s_logger.debug("waiting for template:" + template.getId() + " downloading finished, success"); + createVolumeFromBaseImageAsync(volume, templateOnPrimaryStoreObj, dataStore, future); + return; + } + } + try { motionSrv.copyAsync(template, templateOnPrimaryStoreObj, caller); } catch (Exception e) { @@ -311,16 +361,17 @@ public class VolumeServiceImpl implements VolumeService { templateOnPrimaryStoreObj.processEvent(Event.OperationFailed); VolumeApiResult result = new VolumeApiResult(volume); result.setResult(e.toString()); - caller.complete(result); + future.complete(result); } return; } - + @DB - protected Void copyBaseImageCallback(AsyncCallbackDispatcher callback, CreateBaseImageContext context) { + protected Void copyBaseImageCallback(AsyncCallbackDispatcher callback, + CreateBaseImageContext context) { CopyCommandResult result = callback.getResult(); VolumeApiResult res = new VolumeApiResult(context.getVolume()); - + AsyncCallFuture future = context.getFuture(); DataObject templateOnPrimaryStoreObj = context.destObj; if (!result.isSuccess()) { @@ -329,65 +380,64 @@ public class VolumeServiceImpl implements VolumeService { future.complete(res); return null; } - - templateOnPrimaryStoreObj.processEvent(Event.OperationSuccessed); + + templateOnPrimaryStoreObj.processEvent(Event.OperationSuccessed, result.getAnswer()); createVolumeFromBaseImageAsync(context.volume, templateOnPrimaryStoreObj, context.dataStore, future); return null; } - + private class CreateVolumeFromBaseImageContext extends AsyncRpcConext { - private final VolumeObject vo; + private final DataObject vo; private final AsyncCallFuture future; - private final DataStore primaryStore; private final DataObject templateOnStore; - public CreateVolumeFromBaseImageContext(AsyncCompletionCallback callback, VolumeObject vo, - DataStore primaryStore, - DataObject templateOnStore, - AsyncCallFuture future) { + private final SnapshotInfo snapshot; + + public CreateVolumeFromBaseImageContext(AsyncCompletionCallback callback, DataObject vo, + DataStore primaryStore, DataObject templateOnStore, AsyncCallFuture future, + SnapshotInfo snapshot) { super(callback); this.vo = vo; this.future = future; - this.primaryStore = primaryStore; this.templateOnStore = templateOnStore; + this.snapshot = snapshot; } - public AsyncCallFuture getFuture() { return this.future; } } - - @DB - protected void createVolumeFromBaseImageAsync(VolumeInfo volume, DataObject templateOnPrimaryStore, PrimaryDataStore pd, AsyncCallFuture future) { - VolumeObject vo = (VolumeObject)volume; - CreateVolumeFromBaseImageContext context = new CreateVolumeFromBaseImageContext(null, vo, pd, templateOnPrimaryStore, future); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); - caller.setCallback(caller.getTarget().copyBaseImageCallBack(null, null)) - .setContext(context); + @DB + protected void createVolumeFromBaseImageAsync(VolumeInfo volume, DataObject templateOnPrimaryStore, + PrimaryDataStore pd, AsyncCallFuture future) { DataObject volumeOnPrimaryStorage = pd.create(volume); - volume.processEvent(Event.CreateOnlyRequested); + volumeOnPrimaryStorage.processEvent(Event.CreateOnlyRequested); + + CreateVolumeFromBaseImageContext context = new CreateVolumeFromBaseImageContext( + null, volumeOnPrimaryStorage, pd, templateOnPrimaryStore, future, null); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().createVolumeFromBaseImageCallBack(null, null)); + caller.setContext(context); motionSrv.copyAsync(context.templateOnStore, volumeOnPrimaryStorage, caller); return; } - + @DB - public Void copyBaseImageCallBack(AsyncCallbackDispatcher callback, CreateVolumeFromBaseImageContext context) { - VolumeObject vo = context.vo; + protected Void createVolumeFromBaseImageCallBack( + AsyncCallbackDispatcher callback, + CreateVolumeFromBaseImageContext context) { + DataObject vo = context.vo; CopyCommandResult result = callback.getResult(); - VolumeApiResult volResult = new VolumeApiResult(vo); - + VolumeApiResult volResult = new VolumeApiResult((VolumeObject) vo); + if (result.isSuccess()) { - if (result.getPath() != null) { - vo.setPath(result.getPath()); - } - vo.processEvent(Event.OperationSuccessed); + vo.processEvent(Event.OperationSuccessed, result.getAnswer()); } else { vo.processEvent(Event.OperationFailed); volResult.setResult(result.getResult()); } - + AsyncCallFuture future = context.getFuture(); future.complete(volResult); return null; @@ -395,50 +445,48 @@ public class VolumeServiceImpl implements VolumeService { @DB @Override - public AsyncCallFuture createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId, TemplateInfo template) { + public AsyncCallFuture createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId, + TemplateInfo template) { PrimaryDataStore pd = dataStoreMgr.getPrimaryDataStore(dataStoreId); TemplateInfo templateOnPrimaryStore = pd.getTemplate(template.getId()); AsyncCallFuture future = new AsyncCallFuture(); - VolumeApiResult result = new VolumeApiResult(volume); - + if (templateOnPrimaryStore == null) { createBaseImageAsync(volume, pd, template, future); return future; } - + createVolumeFromBaseImageAsync(volume, templateOnPrimaryStore, pd, future); return future; } @Override @DB - public boolean destroyVolume(long volumeId) - throws ConcurrentOperationException { - - VolumeInfo vol = this.volFactory.getVolume(volumeId); + public boolean destroyVolume(long volumeId) throws ConcurrentOperationException { + + VolumeInfo vol = volFactory.getVolume(volumeId); vol.processEvent(Event.DestroyRequested); - this.snapshotMgr.deletePoliciesForVolume(volumeId); + snapshotMgr.deletePoliciesForVolume(volumeId); vol.processEvent(Event.OperationSuccessed); - + return true; } @Override - public AsyncCallFuture createVolumeFromSnapshot( - VolumeInfo volume, DataStore store, SnapshotInfo snapshot) { + public AsyncCallFuture createVolumeFromSnapshot(VolumeInfo volume, DataStore store, + SnapshotInfo snapshot) { AsyncCallFuture future = new AsyncCallFuture(); try { DataObject volumeOnStore = store.create(volume); - volume = this.volFactory.getVolume(volume.getId(), store); - volume.processEvent(Event.CreateOnlyRequested); - CreateVolumeFromBaseImageContext context = new CreateVolumeFromBaseImageContext(null, - (VolumeObject)volume, store, volumeOnStore, future); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); - caller.setCallback(caller.getTarget().createVolumeFromSnapshotCallback(null, null)) - .setContext(context); - this.motionSrv.copyAsync(snapshot, volumeOnStore, caller); + volumeOnStore.processEvent(Event.CreateOnlyRequested); + snapshot.processEvent(Event.CopyingRequested); + CreateVolumeFromBaseImageContext context = new CreateVolumeFromBaseImageContext( + null, volume, store, volumeOnStore, future, snapshot); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().createVolumeFromSnapshotCallback(null, null)).setContext(context); + motionSrv.copyAsync(snapshot, volumeOnStore, caller); } catch (Exception e) { s_logger.debug("create volume from snapshot failed", e); VolumeApiResult result = new VolumeApiResult(volume); @@ -449,10 +497,12 @@ public class VolumeServiceImpl implements VolumeService { return future; } - protected Void createVolumeFromSnapshotCallback(AsyncCallbackDispatcher callback, + protected Void createVolumeFromSnapshotCallback( + AsyncCallbackDispatcher callback, CreateVolumeFromBaseImageContext context) { CopyCommandResult result = callback.getResult(); - VolumeInfo volume = context.vo; + VolumeInfo volume = (VolumeInfo) context.templateOnStore; + SnapshotInfo snapshot = context.snapshot; VolumeApiResult apiResult = new VolumeApiResult(volume); Event event = null; if (result.isFailed()) { @@ -463,7 +513,12 @@ public class VolumeServiceImpl implements VolumeService { } try { - volume.processEvent(event); + if (result.isSuccess()) { + volume.processEvent(event, result.getAnswer()); + } else { + volume.processEvent(event); + } + snapshot.processEvent(event); } catch (Exception e) { s_logger.debug("create volume from snapshot failed", e); apiResult.setResult(e.toString()); @@ -483,64 +538,179 @@ public class VolumeServiceImpl implements VolumeService { newVol.setPoolId(pool.getId()); newVol.setLastPoolId(lastPoolId); newVol.setPodId(pool.getPodId()); - return this.volDao.persist(newVol); + return volDao.persist(newVol); } - private class CopyVolumeContext extends AsyncRpcConext { final VolumeInfo srcVolume; final VolumeInfo destVolume; - final DataStore destStore; final AsyncCallFuture future; - /** - * @param callback - */ - public CopyVolumeContext(AsyncCompletionCallback callback, AsyncCallFuture future, VolumeInfo srcVolume, VolumeInfo destVolume, - DataStore destStore) { + + public CopyVolumeContext(AsyncCompletionCallback callback, AsyncCallFuture future, + VolumeInfo srcVolume, VolumeInfo destVolume, DataStore destStore) { super(callback); this.srcVolume = srcVolume; this.destVolume = destVolume; - this.destStore = destStore; this.future = future; } - + } + + protected AsyncCallFuture copyVolumeFromImageToPrimary(VolumeInfo srcVolume, DataStore destStore) { + AsyncCallFuture future = new AsyncCallFuture(); + VolumeApiResult res = new VolumeApiResult(srcVolume); + VolumeInfo destVolume = null; + try { + destVolume = (VolumeInfo) destStore.create(srcVolume); + destVolume.processEvent(Event.CopyingRequested); + srcVolume.processEvent(Event.CopyingRequested); + + CopyVolumeContext context = new CopyVolumeContext(null, future, + srcVolume, destVolume, destStore); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().copyVolumeFromImageToPrimaryCallback(null, null)).setContext(context); + + motionSrv.copyAsync(srcVolume, destVolume, caller); + return future; + } catch (Exception e) { + s_logger.error("failed to copy volume from image store", e); + if (destVolume != null) { + destVolume.processEvent(Event.OperationFailed); + } + + srcVolume.processEvent(Event.OperationFailed); + res.setResult(e.toString()); + future.complete(res); + return future; + } + } + + protected Void copyVolumeFromImageToPrimaryCallback( + AsyncCallbackDispatcher callback, + CopyVolumeContext context) { + VolumeInfo srcVolume = context.srcVolume; + VolumeInfo destVolume = context.destVolume; + CopyCommandResult result = callback.getResult(); + AsyncCallFuture future = context.future; + VolumeApiResult res = new VolumeApiResult(destVolume); + try { + if (res.isFailed()) { + destVolume.processEvent(Event.OperationFailed); + srcVolume.processEvent(Event.OperationFailed); + res.setResult(result.getResult()); + future.complete(res); + return null; + } + + srcVolume.processEvent(Event.OperationSuccessed); + destVolume.processEvent(Event.OperationSuccessed, result.getAnswer()); + srcVolume.getDataStore().delete(srcVolume); + future.complete(res); + } catch (Exception e) { + res.setResult(e.toString()); + future.complete(res); + } + return null; + } + + + protected AsyncCallFuture copyVolumeFromPrimaryToImage(VolumeInfo srcVolume, DataStore destStore) { + AsyncCallFuture future = new AsyncCallFuture(); + VolumeApiResult res = new VolumeApiResult(srcVolume); + VolumeInfo destVolume = null; + try { + destVolume = (VolumeInfo)destStore.create(srcVolume); + srcVolume.processEvent(Event.MigrationRequested); // this is just used for locking that src volume record in DB to avoid using lock + destVolume.processEventOnly(Event.CreateOnlyRequested); + + CopyVolumeContext context = new CopyVolumeContext(null, future, srcVolume, + destVolume, + destStore); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().copyVolumeFromPrimaryToImageCallback(null, null)) + .setContext(context); + + motionSrv.copyAsync(srcVolume, destVolume, caller); + return future; + } catch (Exception e) { + s_logger.error("failed to copy volume to image store", e); + if (destVolume != null) { + destVolume.getDataStore().delete(destVolume); + } + srcVolume.processEvent(Event.OperationFailed); // unlock source volume record + res.setResult(e.toString()); + future.complete(res); + return future; + } + } + + protected Void copyVolumeFromPrimaryToImageCallback(AsyncCallbackDispatcher callback, CopyVolumeContext context) { + VolumeInfo srcVolume = context.srcVolume; + VolumeInfo destVolume = context.destVolume; + CopyCommandResult result = callback.getResult(); + AsyncCallFuture future = context.future; + VolumeApiResult res = new VolumeApiResult(destVolume); + try { + if (res.isFailed()) { + srcVolume.processEvent(Event.OperationFailed); // back to Ready state in Volume table + destVolume.processEventOnly(Event.OperationFailed); + res.setResult(result.getResult()); + future.complete(res); + }else{ + srcVolume.processEvent(Event.OperationSuccessed); // back to Ready state in Volume table + destVolume.processEventOnly(Event.OperationSuccessed, result.getAnswer()); + future.complete(res); + } + } catch (Exception e) { + res.setResult(e.toString()); + future.complete(res); + } + return null; + } + + @Override - public AsyncCallFuture copyVolume(VolumeInfo srcVolume, - DataStore destStore) { + public AsyncCallFuture copyVolume(VolumeInfo srcVolume, DataStore destStore) { + + if (srcVolume.getState() == Volume.State.Uploaded) { + return copyVolumeFromImageToPrimary(srcVolume, destStore); + } + + if (destStore.getRole() == DataStoreRole.Image) { + return copyVolumeFromPrimaryToImage(srcVolume, destStore); + } + AsyncCallFuture future = new AsyncCallFuture(); VolumeApiResult res = new VolumeApiResult(srcVolume); try { - if (!this.snapshotMgr.canOperateOnVolume(srcVolume)) { - s_logger.debug( - "There are snapshots creating on this volume, can not move this volume"); - + if (!snapshotMgr.canOperateOnVolume(srcVolume)) { + s_logger.debug("There are snapshots creating on this volume, can not move this volume"); + res.setResult("There are snapshots creating on this volume, can not move this volume"); future.complete(res); return future; } - VolumeVO destVol = duplicateVolumeOnAnotherStorage(srcVolume, (StoragePool)destStore); - VolumeInfo destVolume = this.volFactory.getVolume(destVol.getId(), destStore); + VolumeVO destVol = duplicateVolumeOnAnotherStorage(srcVolume, (StoragePool) destStore); + VolumeInfo destVolume = volFactory.getVolume(destVol.getId(), destStore); destVolume.processEvent(Event.MigrationRequested); srcVolume.processEvent(Event.MigrationRequested); - CopyVolumeContext context = new CopyVolumeContext(null, future, srcVolume, - destVolume, - destStore); + CopyVolumeContext context = new CopyVolumeContext(null, future, + srcVolume, destVolume, destStore); AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); - caller.setCallback(caller.getTarget().copyVolumeCallBack(null, null)) - .setContext(context); - this.motionSrv.copyAsync(srcVolume, destVolume, caller); + caller.setCallback(caller.getTarget().copyVolumeCallBack(null, null)).setContext(context); + motionSrv.copyAsync(srcVolume, destVolume, caller); } catch (Exception e) { - s_logger.debug("Failed to copy volume", e); + s_logger.debug("Failed to copy volume" + e); res.setResult(e.toString()); future.complete(res); } return future; } - - protected Void copyVolumeCallBack(AsyncCallbackDispatcher callback, CopyVolumeContext context) { + + protected Void copyVolumeCallBack(AsyncCallbackDispatcher callback, + CopyVolumeContext context) { VolumeInfo srcVolume = context.srcVolume; VolumeInfo destVolume = context.destVolume; CopyCommandResult result = callback.getResult(); @@ -552,34 +722,34 @@ public class VolumeServiceImpl implements VolumeService { destVolume.processEvent(Event.OperationFailed); srcVolume.processEvent(Event.OperationFailed); destroyVolume(destVolume.getId()); - destVolume = this.volFactory.getVolume(destVolume.getId()); - AsyncCallFuture destroyFuture = this.expungeVolumeAsync(destVolume); + destVolume = volFactory.getVolume(destVolume.getId()); + AsyncCallFuture destroyFuture = expungeVolumeAsync(destVolume); destroyFuture.get(); future.complete(res); return null; } srcVolume.processEvent(Event.OperationSuccessed); - destVolume.processEvent(Event.OperationSuccessed); + destVolume.processEvent(Event.OperationSuccessed, result.getAnswer()); destroyVolume(srcVolume.getId()); - srcVolume = this.volFactory.getVolume(srcVolume.getId()); - AsyncCallFuture destroyFuture = this.expungeVolumeAsync(srcVolume); + srcVolume = volFactory.getVolume(srcVolume.getId()); + AsyncCallFuture destroyFuture = expungeVolumeAsync(srcVolume); destroyFuture.get(); future.complete(res); return null; } catch (Exception e) { - s_logger.debug("Failed to process copy volume callback",e); + s_logger.debug("Failed to process copy volume callback", e); res.setResult(e.toString()); future.complete(res); } - + return null; } private class MigrateVolumeContext extends AsyncRpcConext { final VolumeInfo srcVolume; final VolumeInfo destVolume; - final DataStore destStore; final AsyncCallFuture future; + /** * @param callback */ @@ -588,7 +758,6 @@ public class VolumeServiceImpl implements VolumeService { super(callback); this.srcVolume = srcVolume; this.destVolume = destVolume; - this.destStore = destStore; this.future = future; } } @@ -598,20 +767,20 @@ public class VolumeServiceImpl implements VolumeService { AsyncCallFuture future = new AsyncCallFuture(); VolumeApiResult res = new VolumeApiResult(srcVolume); try { - if (!this.snapshotMgr.canOperateOnVolume(srcVolume)) { + if (!snapshotMgr.canOperateOnVolume(srcVolume)) { s_logger.debug("Snapshots are being created on this volume. This volume cannot be migrated now."); res.setResult("Snapshots are being created on this volume. This volume cannot be migrated now."); future.complete(res); return future; } - VolumeInfo destVolume = this.volFactory.getVolume(srcVolume.getId(), destStore); + VolumeInfo destVolume = volFactory.getVolume(srcVolume.getId(), destStore); srcVolume.processEvent(Event.MigrationRequested); MigrateVolumeContext context = new MigrateVolumeContext(null, future, srcVolume, destVolume, destStore); AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); caller.setCallback(caller.getTarget().migrateVolumeCallBack(null, null)).setContext(context); - this.motionSrv.copyAsync(srcVolume, destVolume, caller); + motionSrv.copyAsync(srcVolume, destVolume, caller); } catch (Exception e) { s_logger.debug("Failed to copy volume", e); res.setResult(e.toString()); @@ -623,7 +792,6 @@ public class VolumeServiceImpl implements VolumeService { protected Void migrateVolumeCallBack(AsyncCallbackDispatcher callback, MigrateVolumeContext context) { VolumeInfo srcVolume = context.srcVolume; - VolumeInfo destVolume = context.destVolume; CopyCommandResult result = callback.getResult(); AsyncCallFuture future = context.future; VolumeApiResult res = new VolumeApiResult(srcVolume); @@ -648,9 +816,7 @@ public class VolumeServiceImpl implements VolumeService { private class MigrateVmWithVolumesContext extends AsyncRpcConext { final Map volumeToPool; final AsyncCallFuture future; - /** - * @param callback - */ + public MigrateVmWithVolumesContext(AsyncCompletionCallback callback, AsyncCallFuture future, Map volumeToPool) { super(callback); @@ -665,17 +831,19 @@ public class VolumeServiceImpl implements VolumeService { AsyncCallFuture future = new AsyncCallFuture(); CommandResult res = new CommandResult(); try { - // Check to make sure there are no snapshot operations on a volume and + // Check to make sure there are no snapshot operations on a volume + // and // put it in the migrating state. List volumesMigrating = new ArrayList(); for (Map.Entry entry : volumeMap.entrySet()) { VolumeInfo volume = entry.getKey(); - if (!this.snapshotMgr.canOperateOnVolume(volume)) { + if (!snapshotMgr.canOperateOnVolume(volume)) { s_logger.debug("Snapshots are being created on a volume. Volumes cannot be migrated now."); res.setResult("Snapshots are being created on a volume. Volumes cannot be migrated now."); future.complete(res); - // All the volumes that are already in migrating state need to be put back in ready state. + // All the volumes that are already in migrating state need + // to be put back in ready state. for (VolumeInfo volumeMigrating : volumesMigrating) { volumeMigrating.processEvent(Event.OperationFailed); } @@ -690,7 +858,7 @@ public class VolumeServiceImpl implements VolumeService { future, volumeMap); AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); caller.setCallback(caller.getTarget().migrateVmWithVolumesCallBack(null, null)).setContext(context); - this.motionSrv.copyAsync(volumeMap, vmTo, srcHost, destHost, caller); + motionSrv.copyAsync(volumeMap, vmTo, srcHost, destHost, caller); } catch (Exception e) { s_logger.debug("Failed to copy volume", e); @@ -733,85 +901,250 @@ public class VolumeServiceImpl implements VolumeService { @Override public AsyncCallFuture registerVolume(VolumeInfo volume, DataStore store) { - - AsyncCallFuture future = new AsyncCallFuture(); - VolumeObject vo = (VolumeObject) volume; - CreateVolumeContext context = new CreateVolumeContext(null, vo, future); + AsyncCallFuture future = new AsyncCallFuture(); + DataObject volumeOnStore = store.create(volume); + + volumeOnStore.processEvent(Event.CreateOnlyRequested); + + CreateVolumeContext context = new CreateVolumeContext(null, volumeOnStore, + future); AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); - caller.setCallback(caller.getTarget().registerVolumeCallback(null, null)) - .setContext(context); - - dataObjectMgr.createAsync(volume, store, caller, true); + caller.setCallback(caller.getTarget().registerVolumeCallback(null, null)); + caller.setContext(context); + + store.getDriver().createAsync(volumeOnStore, caller); return future; } - - protected Void registerVolumeCallback(AsyncCallbackDispatcher callback, CreateVolumeContext context) { - CreateCmdResult result = callback.getResult(); - VolumeObject vo = (VolumeObject)context.volume; - if (result.isFailed()) { - vo.stateTransit(Volume.Event.OperationFailed); - } else { - vo.stateTransit(Volume.Event.OperationSucceeded); - } - VolumeApiResult res = new VolumeApiResult(vo); - context.future.complete(res); - return null; - } - - @Override - public AsyncCallFuture resize(VolumeInfo volume) { - AsyncCallFuture future = new AsyncCallFuture(); - VolumeApiResult result = new VolumeApiResult(volume); - try { - volume.processEvent(Event.ResizeRequested); - } catch (Exception e) { - s_logger.debug("Failed to change state to resize", e); - result.setResult(e.toString()); - future.complete(result); - return future; - } - CreateVolumeContext context = new CreateVolumeContext(null, volume, future); + protected Void registerVolumeCallback(AsyncCallbackDispatcher callback, + CreateVolumeContext context) { + CreateCmdResult result = callback.getResult(); + try { + VolumeObject vo = (VolumeObject) context.volume; + if (result.isFailed()) { + vo.processEvent(Event.OperationFailed); + } else { + vo.processEvent(Event.OperationSuccessed, result.getAnswer()); + } + + _resourceLimitMgr.incrementResourceCount(vo.getAccountId(), ResourceType.secondary_storage, vo.getSize()); + VolumeApiResult res = new VolumeApiResult(vo); + context.future.complete(res); + return null; + } catch (Exception e) { + s_logger.error("register volume failed: ", e); + VolumeApiResult res = new VolumeApiResult(null); + context.future.complete(res); + return null; + } + } + + @Override + public AsyncCallFuture resize(VolumeInfo volume) { + AsyncCallFuture future = new AsyncCallFuture(); + VolumeApiResult result = new VolumeApiResult(volume); + try { + volume.processEvent(Event.ResizeRequested); + } catch (Exception e) { + s_logger.debug("Failed to change state to resize", e); + result.setResult(e.toString()); + future.complete(result); + return future; + } + CreateVolumeContext context = new CreateVolumeContext(null, volume, future); AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); caller.setCallback(caller.getTarget().resizeVolumeCallback(caller, context)).setContext(context); - volume.getDataStore().getDriver().resize(volume, caller); - return future; - } - - protected Void resizeVolumeCallback(AsyncCallbackDispatcher callback, CreateVolumeContext context) { - CreateCmdResult result = callback.getResult(); - AsyncCallFuture future = context.future; - VolumeInfo volume = (VolumeInfo)context.volume; - - if (result.isFailed()) { - try { - volume.processEvent(Event.OperationFailed); - } catch (Exception e) { - s_logger.debug("Failed to change state", e); - } - VolumeApiResult res = new VolumeApiResult(volume); - res.setResult(result.getResult()); - future.complete(res); - return null; - } - - try { - volume.processEvent(Event.OperationSuccessed); - } catch(Exception e) { - s_logger.debug("Failed to change state", e); - VolumeApiResult res = new VolumeApiResult(volume); - res.setResult(result.getResult()); - future.complete(res); - return null; - } - - VolumeApiResult res = new VolumeApiResult(volume); - future.complete(res); - - return null; - } - - + volume.getDataStore().getDriver().resize(volume, caller); + return future; + } + + protected Void resizeVolumeCallback(AsyncCallbackDispatcher callback, + CreateVolumeContext context) { + CreateCmdResult result = callback.getResult(); + AsyncCallFuture future = context.future; + VolumeInfo volume = (VolumeInfo) context.volume; + + if (result.isFailed()) { + try { + volume.processEvent(Event.OperationFailed); + } catch (Exception e) { + s_logger.debug("Failed to change state", e); + } + VolumeApiResult res = new VolumeApiResult(volume); + res.setResult(result.getResult()); + future.complete(res); + return null; + } + + try { + volume.processEvent(Event.OperationSuccessed); + } catch (Exception e) { + s_logger.debug("Failed to change state", e); + VolumeApiResult res = new VolumeApiResult(volume); + res.setResult(result.getResult()); + future.complete(res); + return null; + } + + VolumeApiResult res = new VolumeApiResult(volume); + future.complete(res); + + return null; + } + + @Override + public void handleVolumeSync(DataStore store) { + if (store == null) { + s_logger.warn("Huh? ssHost is null"); + return; + } + long storeId = store.getId(); + + Map volumeInfos = listVolume(store); + if (volumeInfos == null) { + return; + } + + List dbVolumes = _volumeStoreDao.listByStoreId(storeId); + List toBeDownloaded = new ArrayList(dbVolumes); + for (VolumeDataStoreVO volumeStore : dbVolumes) { + VolumeVO volume = _volumeDao.findById(volumeStore.getVolumeId()); + // Exists then don't download + if (volumeInfos.containsKey(volume.getId())) { + TemplateProp volInfo = volumeInfos.remove(volume.getId()); + toBeDownloaded.remove(volumeStore); + s_logger.info("Volume Sync found " + volume.getUuid() + " already in the volume image store table"); + if (volumeStore.getDownloadState() != Status.DOWNLOADED) { + volumeStore.setErrorString(""); + } + if (volInfo.isCorrupted()) { + volumeStore.setDownloadState(Status.DOWNLOAD_ERROR); + String msg = "Volume " + volume.getUuid() + " is corrupted on image store "; + volumeStore.setErrorString(msg); + s_logger.info("msg"); + if (volumeStore.getDownloadUrl() == null) { + msg = "Volume (" + volume.getUuid() + ") with install path " + volInfo.getInstallPath() + + "is corrupted, please check in image store: " + volumeStore.getDataStoreId(); + s_logger.warn(msg); + } else { + toBeDownloaded.add(volumeStore); + } + + } else { // Put them in right status + volumeStore.setDownloadPercent(100); + volumeStore.setDownloadState(Status.DOWNLOADED); + volumeStore.setInstallPath(volInfo.getInstallPath()); + volumeStore.setSize(volInfo.getSize()); + volumeStore.setPhysicalSize(volInfo.getPhysicalSize()); + volumeStore.setLastUpdated(new Date()); + _volumeStoreDao.update(volumeStore.getId(), volumeStore); + + if (volume.getSize() == 0) { + // Set volume size in volumes table + volume.setSize(volInfo.getSize()); + _volumeDao.update(volumeStore.getVolumeId(), volume); + } + + if (volInfo.getSize() > 0) { + try { + _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()), + com.cloud.configuration.Resource.ResourceType.secondary_storage, volInfo.getSize() + - volInfo.getPhysicalSize()); + } catch (ResourceAllocationException e) { + s_logger.warn(e.getMessage()); + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, + volume.getDataCenterId(), volume.getPodId(), e.getMessage(), e.getMessage()); + } finally { + _resourceLimitMgr.recalculateResourceCount(volume.getAccountId(), volume.getDomainId(), + com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal()); + } + } + } + continue; + } + // Volume is not on secondary but we should download. + if (volumeStore.getDownloadState() != Status.DOWNLOADED) { + s_logger.info("Volume Sync did not find " + volume.getName() + " ready on image store " + storeId + + ", will request download to start/resume shortly"); + toBeDownloaded.add(volumeStore); + } + } + + // Download volumes which haven't been downloaded yet. + if (toBeDownloaded.size() > 0) { + for (VolumeDataStoreVO 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 " + store.getName()); + // TODO: pass a callback later + VolumeInfo vol = volFactory.getVolume(volumeHost.getVolumeId()); + createVolumeAsync(vol, store); + } + } + + // Delete volumes which are not present on DB. + for (Long uniqueName : volumeInfos.keySet()) { + TemplateProp tInfo = volumeInfos.get(uniqueName); + + //we cannot directly call expungeVolumeAsync here to + // reuse delete logic since in this case, our db does not have + // this template at all. + VolumeObjectTO tmplTO = new VolumeObjectTO(); + tmplTO.setDataStore(store.getTO()); + tmplTO.setPath(tInfo.getInstallPath()); + tmplTO.setId(tInfo.getId()); + DeleteCommand dtCommand = new DeleteCommand(tmplTO); + EndPoint ep = _epSelector.select(store); + Answer answer = ep.sendMessage(dtCommand); + if (answer == null || !answer.getResult()) { + s_logger.info("Failed to deleted volume at store: " + store.getName()); + + } else { + String description = "Deleted volume " + tInfo.getTemplateName() + " on secondary storage " + storeId; + s_logger.info(description); + } + } + } + + private Map listVolume(DataStore store) { + ListVolumeCommand cmd = new ListVolumeCommand(store.getTO(), store.getUri()); + EndPoint ep = _epSelector.select(store); + Answer answer = ep.sendMessage(cmd); + if (answer != null && answer.getResult()) { + ListVolumeAnswer tanswer = (ListVolumeAnswer) answer; + return tanswer.getTemplateInfo(); + } else { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Can not list volumes for image store " + store.getId()); + } + } + + return null; + } + + @Override + public SnapshotInfo takeSnapshot(VolumeInfo volume) { + VolumeObject vol = (VolumeObject) volume; + vol.stateTransit(Volume.Event.SnapshotRequested); + + SnapshotInfo snapshot = null; + try { + snapshot = snapshotMgr.takeSnapshot(volume); + } catch (Exception e) { + s_logger.debug("Take snapshot: " + volume.getId() + " failed: " + e.toString()); + } finally { + if (snapshot != null) { + vol.stateTransit(Volume.Event.OperationSucceeded); + } else { + vol.stateTransit(Volume.Event.OperationFailed); + } + } + + return snapshot; + } } diff --git a/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/ConfiguratorTest.java b/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/ConfiguratorTest.java index 122c3532a09..ddbccb2fdb5 100644 --- a/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/ConfiguratorTest.java +++ b/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/ConfiguratorTest.java @@ -18,56 +18,50 @@ */ package org.apache.cloudstack.storage.volume.test; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import java.util.HashMap; import java.util.List; -import java.util.Map; - import javax.inject.Inject; -import javax.naming.ConfigurationException; - import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreProvider; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mockito; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import com.cloud.dc.ClusterVO; import com.cloud.dc.dao.ClusterDao; -import com.cloud.hypervisor.Hypervisor.HypervisorType; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations="classpath:/testContext.xml") +@ContextConfiguration(locations = "classpath:/testContext.xml") public class ConfiguratorTest { - @Inject + @Inject List providers; - + @Inject ClusterDao clusterDao; + @Before public void setup() { - /* ClusterVO cluster = new ClusterVO(); - cluster.setHypervisorType(HypervisorType.XenServer.toString()); - Mockito.when(clusterDao.findById(Mockito.anyLong())).thenReturn(cluster); - try { - providerMgr.configure("manager", null); - } catch (ConfigurationException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - }*/ + /* + * ClusterVO cluster = new ClusterVO(); + * cluster.setHypervisorType(HypervisorType.XenServer.toString()); + * Mockito + * .when(clusterDao.findById(Mockito.anyLong())).thenReturn(cluster); + * try { providerMgr.configure("manager", null); } catch + * (ConfigurationException e) { // TODO Auto-generated catch block + * e.printStackTrace(); } + */ } + @Test public void testLoadConfigurator() { - /*for (PrimaryDataStoreConfigurator configurator : configurators) { - System.out.println(configurator.getClass().getName()); - }*/ + /* + * for (PrimaryDataStoreConfigurator configurator : configurators) { + * System.out.println(configurator.getClass().getName()); } + */ } - + @Test public void testProvider() { for (PrimaryDataStoreProvider provider : providers) { @@ -76,19 +70,21 @@ public class ConfiguratorTest { } } } - + @Test public void getProvider() { - // assertNotNull(providerMgr.getDataStoreProvider("default primary data store provider")); + // assertNotNull(providerMgr.getDataStoreProvider("sample primary data store provider")); } - + @Test public void createDataStore() { - /*PrimaryDataStoreProvider provider = providerMgr.getDataStoreProvider("default primary data store provider"); - Map params = new HashMap(); - params.put("url", "nfs://localhost/mnt"); - params.put("clusterId", "1"); - params.put("name", "nfsprimary"); - assertNotNull(provider.registerDataStore(params));*/ + /* + * PrimaryDataStoreProvider provider = + * providerMgr.getDataStoreProvider("sample primary data store provider" + * ); Map params = new HashMap(); + * params.put("url", "nfs://localhost/mnt"); params.put("clusterId", + * "1"); params.put("name", "nfsprimary"); + * assertNotNull(provider.registerDataStore(params)); + */ } } diff --git a/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/Server.java b/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/Server.java index f19d68e8ea1..b7874ebb111 100644 --- a/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/Server.java +++ b/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/Server.java @@ -22,19 +22,22 @@ import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; public class Server { Server1 svr; + public Server() { svr = new Server1(); } + void foo() { - // svr.foo1("foo", new AsyncCallbackDispatcher(this).setOperationName("callback").setContextParam("name", "foo")); + // svr.foo1("foo", new + // AsyncCallbackDispatcher(this).setOperationName("callback").setContextParam("name", + // "foo")); } - + void foocallback(AsyncCallbackDispatcher callback) { /* - System.out.println(callback.getContextParam("name")); - String result = callback.getResult(); - System.out.println(result); - */ + * System.out.println(callback.getContextParam("name")); String result = + * callback.getResult(); System.out.println(result); + */ } - + } diff --git a/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/TestConfiguration.java b/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/TestConfiguration.java index 1d3202f123b..eb871a54ae2 100644 --- a/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/TestConfiguration.java +++ b/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/TestConfiguration.java @@ -33,7 +33,7 @@ public class TestConfiguration { public ImageMotionService imageMotion() { return Mockito.mock(ImageMotionService.class); } - + @Bean public ClusterDao clusterDao() { return Mockito.mock(ClusterDaoImpl.class); diff --git a/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/TestInProcessAsync.java b/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/TestInProcessAsync.java index 67418717989..df099692db4 100644 --- a/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/TestInProcessAsync.java +++ b/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/TestInProcessAsync.java @@ -25,14 +25,15 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations="classpath:/resource/testContext.xml") +@ContextConfiguration(locations = "classpath:/resource/testContext.xml") public class TestInProcessAsync { Server svr; - @Before + + @Before public void setup() { svr = new Server(); } - + @Test public void testRpc() { svr.foo(); diff --git a/framework/ipc/src/org/apache/cloudstack/framework/async/AsyncCallbackDispatcher.java b/framework/ipc/src/org/apache/cloudstack/framework/async/AsyncCallbackDispatcher.java index 26f46da37ba..acbc5b60541 100644 --- a/framework/ipc/src/org/apache/cloudstack/framework/async/AsyncCallbackDispatcher.java +++ b/framework/ipc/src/org/apache/cloudstack/framework/async/AsyncCallbackDispatcher.java @@ -22,6 +22,8 @@ package org.apache.cloudstack.framework.async; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import org.apache.log4j.Logger; + import net.sf.cglib.proxy.CallbackFilter; import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.Enhancer; @@ -30,32 +32,40 @@ import net.sf.cglib.proxy.MethodProxy; @SuppressWarnings("rawtypes") public class AsyncCallbackDispatcher implements AsyncCompletionCallback { - private Method _callbackMethod; + private static final Logger s_logger = Logger.getLogger(AsyncCallbackDispatcher.class); + + private Method _callbackMethod; private T _targetObject; private Object _contextObject; private Object _resultObject; - private AsyncCallbackDriver _driver = new InplaceAsyncCallbackDriver(); - + private AsyncCallbackDriver _driver = new InplaceAsyncCallbackDriver(); + private AsyncCallbackDispatcher(T target) { assert(target != null); _targetObject = target; } - + public AsyncCallbackDispatcher attachDriver(AsyncCallbackDriver driver) { assert(driver != null); _driver = driver; - + return this; } - + public Method getCallbackMethod() { return _callbackMethod; } - + @SuppressWarnings("unchecked") public T getTarget() { Enhancer en = new Enhancer(); - en.setSuperclass(_targetObject.getClass()); + + Class clz = _targetObject.getClass(); + String clzName = clz.getName(); + if(clzName.contains("EnhancerByCloudStack")) + clz = clz.getSuperclass(); + + en.setSuperclass(clz); en.setCallbacks(new Callback[]{new MethodInterceptor() { @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, @@ -64,7 +74,7 @@ public class AsyncCallbackDispatcher implements AsyncCompletionCallback { _callbackMethod.setAccessible(true); return null; } - }, + }, new MethodInterceptor() { @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, @@ -81,23 +91,30 @@ public class AsyncCallbackDispatcher implements AsyncCompletionCallback { return 0; }} ); - return (T)en.create(); + + try { + return (T)en.create(); + } catch(Throwable e) { + s_logger.error("Unexpected exception", e); + } + + return null; } public AsyncCallbackDispatcher setCallback(Object useless) { return this; } - + public AsyncCallbackDispatcher setContext(Object context) { _contextObject = context; return this; } - + @SuppressWarnings("unchecked") public

P getContext() { return (P)_contextObject; } - + public void complete(Object resultObject) { _resultObject = resultObject; _driver.performCompletionCallback(this); @@ -112,15 +129,15 @@ public class AsyncCallbackDispatcher implements AsyncCompletionCallback { Object getTargetObject() { return _targetObject; } - + public static AsyncCallbackDispatcher create(P target) { return new AsyncCallbackDispatcher(target); } - + public static boolean dispatch(Object target, AsyncCallbackDispatcher callback) { assert(callback != null); assert(target != null); - + try { callback.getCallbackMethod().invoke(target, callback, callback.getContext()); } catch (IllegalArgumentException e) { @@ -130,7 +147,7 @@ public class AsyncCallbackDispatcher implements AsyncCompletionCallback { } catch (InvocationTargetException e) { throw new RuntimeException("InvocationTargetException when invoking RPC callback for command: " + callback.getCallbackMethod().getName(), e); } - + return true; } } diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalTemplateAdapter.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalTemplateAdapter.java index 928183ba3df..5a3997149ab 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalTemplateAdapter.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalTemplateAdapter.java @@ -5,20 +5,20 @@ // 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, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// // Automatically generated by addcopyright.py at 01/29/2013 // Apache License, Version 2.0 (the "License"); you may not use this // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// +// // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.baremetal.manager; @@ -31,6 +31,7 @@ import javax.inject.Inject; import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd; import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd; import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import org.apache.log4j.Logger; import com.cloud.configuration.Resource.ResourceType; @@ -64,11 +65,11 @@ public class BareMetalTemplateAdapter extends TemplateAdapterBase implements Tem public String getName() { return TemplateAdapterType.BareMetal.getName(); } - + @Override public TemplateProfile prepare(RegisterTemplateCmd cmd) throws ResourceAllocationException { TemplateProfile profile = super.prepare(cmd); - + if (profile.getZoneId() == null || profile.getZoneId() == -1) { List dcs = _dcDao.listAllIncludingRemoved(); for (DataCenterVO dc : dcs) { @@ -90,53 +91,39 @@ public class BareMetalTemplateAdapter extends TemplateAdapterBase implements Tem return profile; } - + @Override public TemplateProfile prepare(RegisterIsoCmd cmd) throws ResourceAllocationException { throw new CloudRuntimeException("Baremetal doesn't support ISO template"); } - - private void templateCreateUsage(VMTemplateVO template, HostVO host) { + + private void templateCreateUsage(VMTemplateVO template, long dcId) { if (template.getAccountId() != Account.ACCOUNT_ID_SYSTEM) { - UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_TEMPLATE_CREATE, template.getAccountId(), host.getDataCenterId(), + UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_TEMPLATE_CREATE, template.getAccountId(), dcId, template.getId(), template.getName(), null, template.getSourceTemplateId(), 0L); _usageEventDao.persist(usageEvent); } } - + @Override public VMTemplateVO create(TemplateProfile profile) { VMTemplateVO template = persistTemplate(profile); Long zoneId = profile.getZoneId(); - - /* There is no secondary storage vm for baremetal, we use pxe server id. - * Tempalte is not bound to pxeserver right now, and we assume the pxeserver - * cannot be removed once it was added. so we use host id of first found pxe - * server as reference in template_host_ref. - * This maybe a FIXME in future. - */ - VMTemplateHostVO vmTemplateHost = null; + + // create an entry at template_store_ref with store_id = null to represent that this template is ready for use. + TemplateDataStoreVO vmTemplateHost = new TemplateDataStoreVO(null, template.getId(), new Date(), 100, + Status.DOWNLOADED, null, null, null, null, template.getUrl()); + this._tmpltStoreDao.persist(vmTemplateHost); + if (zoneId == null || zoneId == -1) { List dcs = _dcDao.listAllIncludingRemoved(); - for (DataCenterVO dc : dcs) { - HostVO pxe = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, dc.getId()).get(0); - - vmTemplateHost = _tmpltHostDao.findByHostTemplate(dc.getId(), template.getId()); - if (vmTemplateHost == null) { - vmTemplateHost = new VMTemplateHostVO(pxe.getId(), template.getId(), new Date(), 100, - Status.DOWNLOADED, null, null, null, null, template.getUrl()); - _tmpltHostDao.persist(vmTemplateHost); - templateCreateUsage(template, pxe); - } + if ( dcs != null && dcs.size() > 0 ){ + templateCreateUsage(template, dcs.get(0).getId()); } } else { - HostVO pxe = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, zoneId).get(0); - vmTemplateHost = new VMTemplateHostVO(pxe.getId(), template.getId(), new Date(), 100, - Status.DOWNLOADED, null, null, null, null, template.getUrl()); - _tmpltHostDao.persist(vmTemplateHost); - templateCreateUsage(template, pxe); + templateCreateUsage(template, zoneId); } - + _resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template); _resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.secondary_storage, UriUtils.getRemoteSize(profile.getUrl())); @@ -146,65 +133,70 @@ public class BareMetalTemplateAdapter extends TemplateAdapterBase implements Tem public TemplateProfile prepareDelete(DeleteIsoCmd cmd) { throw new CloudRuntimeException("Baremetal doesn't support ISO, how the delete get here???"); } - + @Override @DB public boolean delete(TemplateProfile profile) { VMTemplateVO template = profile.getTemplate(); Long templateId = template.getId(); boolean success = true; String zoneName; - boolean isAllZone; - + if (!template.isCrossZones() && profile.getZoneId() != null) { - isAllZone = false; zoneName = profile.getZoneId().toString(); } else { zoneName = "all zones"; - isAllZone = true; } - + s_logger.debug("Attempting to mark template host refs for template: " + template.getName() + " as destroyed in zone: " + zoneName); Account account = _accountDao.findByIdIncludingRemoved(template.getAccountId()); String eventType = EventTypes.EVENT_TEMPLATE_DELETE; - List templateHostVOs = _tmpltHostDao.listByTemplateId(templateId); - - for (VMTemplateHostVO vo : templateHostVOs) { - VMTemplateHostVO lock = null; - try { - HostVO pxeServer = _hostDao.findById(vo.getHostId()); - if (!isAllZone && pxeServer.getDataCenterId() != profile.getZoneId()) { - continue; - } + List templateHostVOs = this._tmpltStoreDao.listByTemplate(templateId); - lock = _tmpltHostDao.acquireInLockTable(vo.getId()); + for (TemplateDataStoreVO vo : templateHostVOs) { + TemplateDataStoreVO lock = null; + try { + lock = _tmpltStoreDao.acquireInLockTable(vo.getId()); if (lock == null) { - s_logger.debug("Failed to acquire lock when deleting templateHostVO with ID: " + vo.getId()); + s_logger.debug("Failed to acquire lock when deleting templateDataStoreVO with ID: " + vo.getId()); success = false; break; } vo.setDestroyed(true); - _tmpltHostDao.update(vo.getId(), vo); - VMTemplateZoneVO templateZone = _tmpltZoneDao.findByZoneTemplate(pxeServer.getDataCenterId(), templateId); - if (templateZone != null) { - _tmpltZoneDao.remove(templateZone.getId()); - } + _tmpltStoreDao.update(vo.getId(), vo); + - UsageEventVO usageEvent = new UsageEventVO(eventType, account.getId(), pxeServer.getDataCenterId(), templateId, null); - _usageEventDao.persist(usageEvent); } finally { if (lock != null) { - _tmpltHostDao.releaseFromLockTable(lock.getId()); + _tmpltStoreDao.releaseFromLockTable(lock.getId()); } } } - + + if ( profile.getZoneId() != null ){ + UsageEventVO usageEvent = new UsageEventVO(eventType, account.getId(), profile.getZoneId(), templateId, null); + _usageEventDao.persist(usageEvent); + } + else{ + List dcs = _dcDao.listAllIncludingRemoved(); + for ( DataCenterVO dc : dcs){ + UsageEventVO usageEvent = new UsageEventVO(eventType, account.getId(), dc.getId(), templateId, null); + _usageEventDao.persist(usageEvent); + } + } + + VMTemplateZoneVO templateZone = _tmpltZoneDao.findByZoneTemplate(profile.getZoneId(), templateId); + + if (templateZone != null) { + _tmpltZoneDao.remove(templateZone.getId()); + } + s_logger.debug("Successfully marked template host refs for template: " + template.getName() + " as destroyed in zone: " + zoneName); - + // If there are no more non-destroyed template host entries for this template, delete it - if (success && (_tmpltHostDao.listByTemplateId(templateId).size() == 0)) { + if (success && (_tmpltStoreDao.listByTemplate(templateId).size() == 0)) { long accountId = template.getAccountId(); - + VMTemplateVO lock = _tmpltDao.acquireInLockTable(templateId); try { @@ -225,7 +217,7 @@ public class BareMetalTemplateAdapter extends TemplateAdapterBase implements Tem } s_logger.debug("Removed template: " + template.getName() + " because all of its template host refs were marked as destroyed."); } - + return success; } } diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 7d90f6a5cc3..46003e9e289 100755 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -39,11 +39,11 @@ import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.HashSet; import java.util.Properties; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; @@ -56,11 +56,14 @@ import java.util.regex.Pattern; import javax.ejb.Local; import javax.naming.ConfigurationException; -import org.apache.log4j.Logger; -import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; +import org.apache.cloudstack.storage.command.StorageSubSystemCommand; +import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.cloudstack.utils.qemu.QemuImg; -import org.apache.cloudstack.utils.qemu.QemuImgFile; +import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; import org.apache.cloudstack.utils.qemu.QemuImgException; +import org.apache.cloudstack.utils.qemu.QemuImgFile; +import org.apache.log4j.Logger; import org.libvirt.Connect; import org.libvirt.Domain; import org.libvirt.DomainBlockStats; @@ -90,9 +93,6 @@ import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand; import com.cloud.agent.api.CreateStoragePoolCommand; import com.cloud.agent.api.CreateVolumeFromSnapshotAnswer; import com.cloud.agent.api.CreateVolumeFromSnapshotCommand; -import com.cloud.agent.api.DeleteSnapshotBackupAnswer; -import com.cloud.agent.api.DeleteSnapshotBackupCommand; -import com.cloud.agent.api.DeleteSnapshotsDirCommand; import com.cloud.agent.api.DeleteStoragePoolCommand; import com.cloud.agent.api.FenceAnswer; import com.cloud.agent.api.FenceCommand; @@ -171,9 +171,13 @@ import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer; import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; -import com.cloud.agent.api.storage.ResizeVolumeCommand; import com.cloud.agent.api.storage.ResizeVolumeAnswer; +import com.cloud.agent.api.storage.ResizeVolumeCommand; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.DiskTO; import com.cloud.agent.api.to.IpAddressTO; +import com.cloud.agent.api.to.NfsTO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.agent.api.to.VirtualMachineTO; @@ -199,11 +203,12 @@ import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InputDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef.hostNicType; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SerialDef; -import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.VirtioSerialDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.TermPolicy; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.VirtioSerialDef; import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk; import com.cloud.hypervisor.kvm.storage.KVMStoragePool; import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager; +import com.cloud.hypervisor.kvm.storage.KVMStorageProcessor; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.IsolationType; import com.cloud.network.Networks.RouterPrivateIpStrategy; @@ -217,14 +222,16 @@ import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.StorageLayer; import com.cloud.storage.Volume; +import com.cloud.storage.resource.StorageSubsystemCommandHandler; +import com.cloud.storage.resource.StorageSubsystemCommandHandlerBase; import com.cloud.storage.template.Processor; import com.cloud.storage.template.Processor.FormatInfo; import com.cloud.storage.template.QCOW2Processor; -import com.cloud.storage.template.TemplateInfo; import com.cloud.storage.template.TemplateLocation; +import com.cloud.storage.template.TemplateProp; +import com.cloud.utils.FileUtil; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; -import com.cloud.utils.FileUtil; import com.cloud.utils.PropertiesUtil; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; @@ -238,7 +245,7 @@ import com.cloud.vm.VirtualMachineName; /** * LibvirtComputingResource execute requests on the computing/routing host using * the libvirt API - * + * * @config {@table || Param Name | Description | Values | Default || || * hypervisor.type | type of local hypervisor | string | kvm || || * hypervisor.uri | local hypervisor to connect to | URI | @@ -354,7 +361,6 @@ ServerResource { protected String _localStoragePath; protected String _localStorageUUID; private final Map _pifs = new HashMap(); - private final Map> hostNetInfo = new HashMap>(); private final Map _vmStats = new ConcurrentHashMap(); protected boolean _disconnected = true; @@ -393,6 +399,8 @@ ServerResource { protected BridgeType _bridgeType; + protected StorageSubsystemCommandHandler storageHandler; + private String getEndIpFromStartIp(String startIp, int numIps) { String[] tokens = startIp.split("[.]"); assert (tokens.length == 4); @@ -460,7 +468,7 @@ ServerResource { } protected String getDefaultDomrScriptsDir() { - return "scripts/network/domr/kvm"; + return "scripts/network/domr"; } protected String getNetworkDirectSourceMode() { @@ -601,13 +609,13 @@ ServerResource { throw new ConfigurationException( "Unable to find the ovs-pvlan-dhcp-host.sh"); } - + _ovsPvlanVmPath = Script.findScript(networkScriptsDir, "ovs-pvlan-vm.sh"); if ( _ovsPvlanVmPath == null) { throw new ConfigurationException( "Unable to find the ovs-pvlan-vm.sh"); } - + String value = (String) params.get("developer"); boolean isDeveloper = Boolean.parseBoolean(value); @@ -687,13 +695,13 @@ ServerResource { if (_localStoragePath == null) { _localStoragePath = "/var/lib/libvirt/images/"; } - + File storagePath = new File(_localStoragePath); _localStoragePath = storagePath.getAbsolutePath(); _localStorageUUID = (String) params.get("local.storage.uuid"); if (_localStorageUUID == null) { - throw new ConfigurationException("local.storage.uuid is not set! Please set this to a valid UUID"); + _localStorageUUID = UUID.nameUUIDFromBytes(_localStoragePath.getBytes()).toString(); } value = (String) params.get("scripts.timeout"); @@ -834,6 +842,10 @@ ServerResource { configureVifDrivers(params); + KVMStorageProcessor storageProcessor = new KVMStorageProcessor(this._storagePoolMgr, this); + storageProcessor.configure(name, params); + storageHandler = new StorageSubsystemCommandHandlerBase(storageProcessor); + return true; } @@ -982,17 +994,12 @@ ServerResource { return pif; } - private String getOvsPif(String bridge) { - String pif = Script.runSimpleBashScript("ovs-vsctl list-ports " + bridge); - return pif; - } - private String matchPifFileInDirectory(String bridgeName){ File f = new File("/sys/devices/virtual/net/" + bridgeName + "/brif"); if (! f.isDirectory()){ s_logger.debug("failing to get physical interface from bridge" - + bridgeName + ", does " + f.getAbsolutePath() + + bridgeName + ", does " + f.getAbsolutePath() + "exist?"); return ""; } @@ -1062,7 +1069,7 @@ ServerResource { return vnetId; } - private void passCmdLine(String vmName, String cmdLine) + private void passCmdLine(String vmName, String cmdLine) throws InternalErrorException { final Script command = new Script(_patchViaSocketPath, _timeout, s_logger); String result; @@ -1245,6 +1252,8 @@ ServerResource { return execute((CheckNetworkCommand) cmd); } else if (cmd instanceof NetworkRulesVmSecondaryIpCommand) { return execute((NetworkRulesVmSecondaryIpCommand) cmd); + } else if (cmd instanceof StorageSubSystemCommand) { + return this.storageHandler.handleStorageCommands((StorageSubSystemCommand)cmd); } else if (cmd instanceof PvlanSetupCommand) { return execute((PvlanSetupCommand) cmd); } else { @@ -1397,7 +1406,7 @@ ServerResource { disksize = dskch.getSize(); if (cmd.getTemplateUrl() != null) { - if(primaryPool.getType() == StoragePoolType.CLVM) { + if(primaryPool.getType() == StoragePoolType.CLVM) { vol = templateToPrimaryDownload(cmd.getTemplateUrl(),primaryPool); } else { BaseVol = primaryPool.getPhysicalDisk(cmd.getTemplateUrl()); @@ -1478,7 +1487,7 @@ ServerResource { private String getResizeScriptType (KVMStoragePool pool, KVMPhysicalDisk vol) { StoragePoolType poolType = pool.getType(); PhysicalDiskFormat volFormat = vol.getFormat(); - + if(pool.getType() == StoragePoolType.CLVM && volFormat == PhysicalDiskFormat.RAW) { return "CLVM"; } else if ((poolType == StoragePoolType.NetworkFilesystem @@ -1490,7 +1499,7 @@ ServerResource { return null; } - /* uses a local script now, eventually support for virStorageVolResize() will maybe work on + /* uses a local script now, eventually support for virStorageVolResize() will maybe work on qcow2 and lvm and we can do this in libvirt calls */ public Answer execute(ResizeVolumeCommand cmd) { String volid = cmd.getPath(); @@ -1507,16 +1516,16 @@ ServerResource { String type = getResizeScriptType(pool, vol); if (type == null) { - return new ResizeVolumeAnswer(cmd, false, "Unsupported volume format: pool type '" + return new ResizeVolumeAnswer(cmd, false, "Unsupported volume format: pool type '" + pool.getType() + "' and volume format '" + vol.getFormat() + "'"); } else if (type.equals("QCOW2") && shrinkOk) { return new ResizeVolumeAnswer(cmd, false, "Unable to shrink volumes of type " + type); } - s_logger.debug("got to the stage where we execute the volume resize, params:" + s_logger.debug("got to the stage where we execute the volume resize, params:" + path + "," + currentSize + "," + newSize + "," + type + "," + vmInstanceName + "," + shrinkOk); final Script resizecmd = new Script(_resizeVolumePath, - _cmdsTimeout, s_logger); + _cmdsTimeout, s_logger); resizecmd.add("-s",String.valueOf(newSize)); resizecmd.add("-c",String.valueOf(currentSize)); resizecmd.add("-p",path); @@ -1540,8 +1549,8 @@ ServerResource { s_logger.debug(error); return new ResizeVolumeAnswer(cmd, false, error); } - - } + + } public Answer execute(DestroyCommand cmd) { VolumeTO vol = cmd.getVolume(); @@ -1551,8 +1560,6 @@ ServerResource { vol.getPoolType(), vol.getPoolUuid()); pool.deletePhysicalDisk(vol.getPath()); - String vmName = cmd.getVmName(); - String poolPath = pool.getLocalPath(); return new Answer(cmd, true, "Success"); } catch (CloudRuntimeException e) { s_logger.debug("Failed to delete volume: " + e.toString()); @@ -1567,7 +1574,7 @@ ServerResource { if(pifparts.length == 2) { return pifparts[1]; } else { - s_logger.debug("failed to get vlan id from bridge " + brName + s_logger.debug("failed to get vlan id from bridge " + brName + "attached to physical interface" + pif); return ""; } @@ -1582,13 +1589,13 @@ ServerResource { String dhcpIp = cmd.getDhcpIp(); String vmMac = cmd.getVmMac(); boolean add = true; - + String opr = "-A"; if (op.equals("delete")) { opr = "-D"; add = false; } - + String result = null; Connect conn; try { @@ -1720,7 +1727,6 @@ ServerResource { try { conn = LibvirtConnection.getConnectionByVmName(routerName); - Domain vm = getDomain(conn, routerName); List pluggedNics = getInterfaces(conn, routerName); InterfaceDef routerNic = null; @@ -1735,7 +1741,6 @@ ServerResource { return new SetupGuestNetworkAnswer(cmd, false, "Can not find nic with mac " + nic.getMac() + " for VM " + routerName); } - String args = "vpc_guestnw.sh " + routerIP + " -C"; String dev = "eth" + nic.getDeviceId(); String netmask = NetUtils.getSubNet(routerGIP, nic.getNetmask()); String result = _virtRouterResource.assignGuestNetwork(dev, routerIP, @@ -1754,15 +1759,11 @@ ServerResource { private SetNetworkACLAnswer execute(SetNetworkACLCommand cmd) { String[] results = new String[cmd.getRules().length]; - String callResult; - Connect conn; - String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); String privateGw = cmd.getAccessDetail(NetworkElementCommand.VPC_PRIVATE_GATEWAY); try { - conn = LibvirtConnection.getConnectionByVmName(routerName); - Domain vm = getDomain(conn, routerName); String [][] rules = cmd.generateFwRules(); String[] aclRules = rules[0]; NicTO nic = cmd.getNic(); @@ -1786,7 +1787,7 @@ ServerResource { } return new SetNetworkACLAnswer(cmd, true, results); - } catch (LibvirtException e) { + } catch (Exception e) { String msg = "SetNetworkACL failed due to " + e.toString(); s_logger.error(msg, e); return new SetNetworkACLAnswer(cmd, false, results); @@ -1801,7 +1802,6 @@ ServerResource { try { conn = LibvirtConnection.getConnectionByVmName(routerName); - Domain vm = getDomain(conn, routerName); Integer devNum = 0; String pubVlan = pubIP.getVlanId(); List pluggedNics = getInterfaces(conn, routerName); @@ -1809,7 +1809,7 @@ ServerResource { for (InterfaceDef pluggedNic : pluggedNics) { String pluggedVlanBr = pluggedNic.getBrName(); String pluggedVlanId = getVlanIdFromBridge(pluggedVlanBr); - if (pubVlan.equalsIgnoreCase(Vlan.UNTAGGED) + if (pubVlan.equalsIgnoreCase(Vlan.UNTAGGED) && pluggedVlanBr.equalsIgnoreCase(_publicBridgeName)) { break; } else if (pluggedVlanBr.equalsIgnoreCase(_linkLocalBridgeName)){ @@ -1848,7 +1848,6 @@ ServerResource { try { conn = LibvirtConnection.getConnectionByVmName(routerName); IpAddressTO[] ips = cmd.getIpAddresses(); - Domain vm = getDomain(conn, routerName); Integer devNum = 0; Map vlanToNicNum = new HashMap(); List pluggedNics = getInterfaces(conn, routerName); @@ -1856,7 +1855,7 @@ ServerResource { for (InterfaceDef pluggedNic : pluggedNics) { String pluggedVlan = pluggedNic.getBrName(); if (pluggedVlan.equalsIgnoreCase(_linkLocalBridgeName)) { - vlanToNicNum.put("LinkLocal",devNum); + vlanToNicNum.put("LinkLocal",devNum); } else if (pluggedVlan.equalsIgnoreCase(_publicBridgeName) || pluggedVlan.equalsIgnoreCase(_privBridgeName) || pluggedVlan.equalsIgnoreCase(_guestBridgeName)) { @@ -1902,8 +1901,8 @@ ServerResource { if (nic.getBrName().equalsIgnoreCase(_linkLocalBridgeName)) { vlanAllocatedToVM.put("LinkLocal", nicPos); } else { - if (nic.getBrName().equalsIgnoreCase(_publicBridgeName) - || nic.getBrName().equalsIgnoreCase(_privBridgeName) + if (nic.getBrName().equalsIgnoreCase(_publicBridgeName) + || nic.getBrName().equalsIgnoreCase(_privBridgeName) || nic.getBrName().equalsIgnoreCase(_guestBridgeName)) { vlanAllocatedToVM.put(Vlan.UNTAGGED, nicPos); } else { @@ -2034,7 +2033,6 @@ ServerResource { Long volumeId = cmd.getVolumeId(); String secondaryStoragePoolUrl = cmd.getSecondaryStorageUrl(); String snapshotName = cmd.getSnapshotName(); - String snapshotPath = cmd.getVolumePath(); String snapshotDestPath = null; String snapshotRelPath = null; String vmName = cmd.getVmName(); @@ -2130,66 +2128,6 @@ ServerResource { + File.separator + snapshotName, true); } - protected DeleteSnapshotBackupAnswer execute( - final DeleteSnapshotBackupCommand cmd) { - Long dcId = cmd.getDataCenterId(); - Long accountId = cmd.getAccountId(); - Long volumeId = cmd.getVolumeId(); - KVMStoragePool secondaryStoragePool = null; - try { - secondaryStoragePool = _storagePoolMgr.getStoragePoolByURI(cmd - .getSecondaryStorageUrl()); - - String ssPmountPath = secondaryStoragePool.getLocalPath(); - String snapshotDestPath = ssPmountPath + File.separator - + "snapshots" + File.separator + dcId + File.separator - + accountId + File.separator + volumeId; - - final Script command = new Script(_manageSnapshotPath, - _cmdsTimeout, s_logger); - command.add("-d", snapshotDestPath); - command.add("-n", cmd.getSnapshotName()); - - command.execute(); - } catch (CloudRuntimeException e) { - return new DeleteSnapshotBackupAnswer(cmd, false, e.toString()); - } finally { - if (secondaryStoragePool != null) { - _storagePoolMgr.deleteStoragePool(secondaryStoragePool.getType(),secondaryStoragePool.getUuid()); - } - } - return new DeleteSnapshotBackupAnswer(cmd, true, null); - } - - protected Answer execute(DeleteSnapshotsDirCommand cmd) { - Long dcId = cmd.getDcId(); - Long accountId = cmd.getAccountId(); - Long volumeId = cmd.getVolumeId(); - KVMStoragePool secondaryStoragePool = null; - try { - secondaryStoragePool = _storagePoolMgr.getStoragePoolByURI(cmd - .getSecondaryStorageUrl()); - - String ssPmountPath = secondaryStoragePool.getLocalPath(); - String snapshotDestPath = ssPmountPath + File.separator - + "snapshots" + File.separator + dcId + File.separator - + accountId + File.separator + volumeId; - - final Script command = new Script(_manageSnapshotPath, - _cmdsTimeout, s_logger); - command.add("-d", snapshotDestPath); - command.add("-f"); - command.execute(); - } catch (CloudRuntimeException e) { - return new Answer(cmd, false, e.toString()); - } finally { - if (secondaryStoragePool != null) { - _storagePoolMgr.deleteStoragePool(secondaryStoragePool.getType(),secondaryStoragePool.getUuid()); - } - - } - return new Answer(cmd, true, null); - } protected CreateVolumeFromSnapshotAnswer execute( final CreateVolumeFromSnapshotCommand cmd) { @@ -2309,7 +2247,6 @@ ServerResource { KVMStoragePool secondaryStorage = null; KVMStoragePool primary = null; try { - Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName()); String templateFolder = cmd.getAccountId() + File.separator + cmd.getTemplateId() + File.separator; String templateInstallFolder = "/template/tmpl/" + templateFolder; @@ -2405,10 +2342,6 @@ ServerResource { templateInstallFolder + cmd.getUniqueName() + ".qcow2", info.virtualSize, info.size, cmd.getUniqueName(), ImageFormat.QCOW2); - } catch (LibvirtException e) { - s_logger.debug("Failed to get secondary storage pool: " - + e.toString()); - return new CreatePrivateTemplateAnswer(cmd, false, e.toString()); } catch (InternalErrorException e) { return new CreatePrivateTemplateAnswer(cmd, false, e.toString()); } catch (IOException e) { @@ -2487,7 +2420,6 @@ ServerResource { } protected Answer execute(ModifyStoragePoolCommand cmd) { - String poolType = cmd.getPool().getType().toString(); KVMStoragePool storagepool = _storagePoolMgr.createStoragePool(cmd .getPool().getUuid(), cmd.getPool().getHost(), cmd.getPool().getPort(), cmd.getPool().getPath(), @@ -2496,7 +2428,7 @@ ServerResource { return new Answer(cmd, false, " Failed to create storage pool"); } - Map tInfo = new HashMap(); + Map tInfo = new HashMap(); ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, storagepool.getCapacity(), storagepool.getUsed(), tInfo); @@ -2816,8 +2748,8 @@ ServerResource { } /* setup disks, e.g for iso */ - VolumeTO[] volumes = vm.getDisks(); - for (VolumeTO volume : volumes) { + DiskTO[] volumes = vm.getDisks(); + for (DiskTO volume : volumes) { if (volume.getType() == Volume.Type.ISO) { getVolumePath(conn, volume); } @@ -3420,10 +3352,14 @@ ServerResource { } } - private String getVolumePath(Connect conn, VolumeTO volume) + private String getVolumePath(Connect conn, DiskTO volume) throws LibvirtException, URISyntaxException { - if (volume.getType() == Volume.Type.ISO && volume.getPath() != null) { - String isoPath = volume.getPath(); + DataTO data = volume.getData(); + DataStoreTO store = data.getDataStore(); + + if (volume.getType() == Volume.Type.ISO && data.getPath() != null) { + NfsTO nfsStore = (NfsTO)store; + String isoPath = nfsStore.getUrl() + File.separator + data.getPath(); int index = isoPath.lastIndexOf("/"); String path = isoPath.substring(0, index); String name = isoPath.substring(index + 1); @@ -3432,26 +3368,28 @@ ServerResource { KVMPhysicalDisk isoVol = secondaryPool.getPhysicalDisk(name); return isoVol.getPath(); } else { - return volume.getPath(); + return data.getPath(); } } protected void createVbd(Connect conn, VirtualMachineTO vmSpec, String vmName, LibvirtVMDef vm) throws InternalErrorException, LibvirtException, URISyntaxException { - List disks = Arrays.asList(vmSpec.getDisks()); - Collections.sort(disks, new Comparator() { + List disks = Arrays.asList(vmSpec.getDisks()); + Collections.sort(disks, new Comparator() { @Override - public int compare(VolumeTO arg0, VolumeTO arg1) { - return arg0.getDeviceId() > arg1.getDeviceId() ? 1 : -1; + public int compare(DiskTO arg0, DiskTO arg1) { + return arg0.getDiskSeq() > arg1.getDiskSeq() ? 1 : -1; } }); - for (VolumeTO volume : disks) { + for (DiskTO volume : disks) { KVMPhysicalDisk physicalDisk = null; KVMStoragePool pool = null; - if (volume.getType() == Volume.Type.ISO && volume.getPath() != null) { - String volPath = volume.getPath(); + DataTO data = volume.getData(); + if (volume.getType() == Volume.Type.ISO && data.getPath() != null) { + NfsTO nfsStore = (NfsTO)data.getDataStore(); + String volPath = nfsStore.getUrl() + File.separator + data.getPath(); int index = volPath.lastIndexOf("/"); String volDir = volPath.substring(0, index); String volName = volPath.substring(index + 1); @@ -3459,10 +3397,11 @@ ServerResource { getStoragePoolByURI(volDir); physicalDisk = secondaryStorage.getPhysicalDisk(volName); } else if (volume.getType() != Volume.Type.ISO) { + PrimaryDataStoreTO store = (PrimaryDataStoreTO)data.getDataStore(); pool = _storagePoolMgr.getStoragePool( - volume.getPoolType(), - volume.getPoolUuid()); - physicalDisk = pool.getPhysicalDisk(volume.getPath()); + store.getPoolType(), + store.getUuid()); + physicalDisk = pool.getPhysicalDisk(data.getPath()); } String volPath = null; @@ -3480,7 +3419,7 @@ ServerResource { disk.defISODisk(volPath); } } else { - int devId = (int) volume.getDeviceId(); + int devId = volume.getDiskSeq().intValue(); if (pool.getType() == StoragePoolType.RBD) { /* @@ -3507,14 +3446,16 @@ ServerResource { } - if ((volume.getBytesReadRate() != null) && (volume.getBytesReadRate() > 0)) - disk.setBytesReadRate(volume.getBytesReadRate()); - if ((volume.getBytesWriteRate() != null) && (volume.getBytesWriteRate() > 0)) - disk.setBytesWriteRate(volume.getBytesWriteRate()); - if ((volume.getIopsReadRate() != null) && (volume.getIopsReadRate() > 0)) - disk.setIopsReadRate(volume.getIopsReadRate()); - if ((volume.getIopsWriteRate() != null) && (volume.getIopsWriteRate() > 0)) - disk.setIopsWriteRate(volume.getIopsWriteRate()); + VolumeObjectTO volumeObjectTO = (VolumeObjectTO)data; + + if ((volumeObjectTO.getBytesReadRate() != null) && (volumeObjectTO.getBytesReadRate() > 0)) + disk.setBytesReadRate(volumeObjectTO.getBytesReadRate()); + if ((volumeObjectTO.getBytesWriteRate() != null) && (volumeObjectTO.getBytesWriteRate() > 0)) + disk.setBytesWriteRate(volumeObjectTO.getBytesWriteRate()); + if ((volumeObjectTO.getIopsReadRate() != null) && (volumeObjectTO.getIopsReadRate() > 0)) + disk.setIopsReadRate(volumeObjectTO.getIopsReadRate()); + if ((volumeObjectTO.getIopsWriteRate() != null) && (volumeObjectTO.getIopsWriteRate() > 0)) + disk.setIopsWriteRate(volumeObjectTO.getIopsWriteRate()); vm.getDevices().addDevice(disk); } @@ -3529,12 +3470,14 @@ ServerResource { // For LXC, find and add the root filesystem if (HypervisorType.LXC.toString().toLowerCase().equals(vm.getHvsType())) { - for (VolumeTO volume : disks) { + for (DiskTO volume : disks) { if (volume.getType() == Volume.Type.ROOT) { + DataTO data = volume.getData(); + PrimaryDataStoreTO store = (PrimaryDataStoreTO)data.getDataStore(); KVMStoragePool pool = _storagePoolMgr.getStoragePool( - volume.getPoolType(), - volume.getPoolUuid()); - KVMPhysicalDisk physicalDisk = pool.getPhysicalDisk(volume.getPath()); + store.getPoolType(), + store.getUuid()); + KVMPhysicalDisk physicalDisk = pool.getPhysicalDisk(data.getPath()); FilesystemDef rootFs = new FilesystemDef(physicalDisk.getPath(), "/"); vm.getDevices().addDevice(rootFs); break; @@ -3544,16 +3487,6 @@ ServerResource { } - private VolumeTO getVolume(VirtualMachineTO vmSpec, Volume.Type type) { - VolumeTO volumes[] = vmSpec.getDisks(); - for (VolumeTO volume : volumes) { - if (volume.getType() == type) { - return volume; - } - } - return null; - } - private void createVif(LibvirtVMDef vm, NicTO nic) throws InternalErrorException, LibvirtException { vm.getDevices().addDevice( @@ -3582,7 +3515,7 @@ ServerResource { return new CheckSshAnswer(cmd); } - private boolean cleanupDisk(Connect conn, DiskDef disk) { + public boolean cleanupDisk(Connect conn, DiskDef disk) { // need to umount secondary storage String path = disk.getDiskPath(); String poolUuid = null; @@ -4017,21 +3950,21 @@ ServerResource { Connect conn = null; if (_hypervisorType == HypervisorType.LXC) { - try { - conn = LibvirtConnection.getConnectionByType(HypervisorType.LXC.toString()); - vmStates.putAll(getAllVms(conn)); - } catch (LibvirtException e) { - s_logger.debug("Failed to get connection: " + e.getMessage()); - } + try { + conn = LibvirtConnection.getConnectionByType(HypervisorType.LXC.toString()); + vmStates.putAll(getAllVms(conn)); + } catch (LibvirtException e) { + s_logger.debug("Failed to get connection: " + e.getMessage()); + } } if (_hypervisorType == HypervisorType.KVM) { - try { - conn = LibvirtConnection.getConnectionByType(HypervisorType.KVM.toString()); - vmStates.putAll(getAllVms(conn)); - } catch (LibvirtException e) { - s_logger.debug("Failed to get connection: " + e.getMessage()); - } + try { + conn = LibvirtConnection.getConnectionByType(HypervisorType.KVM.toString()); + vmStates.putAll(getAllVms(conn)); + } catch (LibvirtException e) { + s_logger.debug("Failed to get connection: " + e.getMessage()); + } } return vmStates; @@ -4396,6 +4329,7 @@ ServerResource { return parser.getEmulator(); } + private String getGuestType(Connect conn, String vmName) { LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); Domain dm = null; @@ -4454,14 +4388,6 @@ ServerResource { } } - private InterfaceDef.nicModel getGuestNicModel(String guestOSType) { - if (isGuestPVEnabled(guestOSType)) { - return InterfaceDef.nicModel.VIRTIO; - } else { - return InterfaceDef.nicModel.E1000; - } - } - private DiskDef.diskBus getGuestDiskModel(String guestOSType) { if (isGuestPVEnabled(guestOSType)) { return DiskDef.diskBus.VIRTIO; @@ -4495,7 +4421,7 @@ ServerResource { } } - private Domain getDomain(Connect conn, String vmName) + public Domain getDomain(Connect conn, String vmName) throws LibvirtException { return conn .domainLookupByName(vmName); @@ -4523,7 +4449,7 @@ ServerResource { } } - protected List getDisks(Connect conn, String vmName) { + public List getDisks(Connect conn, String vmName) { LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); Domain dm = null; try { @@ -4552,38 +4478,7 @@ ServerResource { return command.execute(); } - private String executeBashScript(String script, OutputInterpreter parser) { - Script command = new Script("/bin/bash", _timeout, s_logger); - command.add("-c"); - command.add(script); - return command.execute(parser); - } - private void deletExitingLinkLocalRoutTable(String linkLocalBr) { - Script command = new Script("/bin/bash", _timeout); - command.add("-c"); - command.add("ip route | grep " + NetUtils.getLinkLocalCIDR()); - OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser(); - String result = command.execute(parser); - boolean foundLinkLocalBr = false; - if (result == null && parser.getLines() != null) { - String[] lines = parser.getLines().split("\\n"); - for (String line : lines) { - String[] tokens = line.split(" "); - if (!tokens[2].equalsIgnoreCase(linkLocalBr)) { - Script.runSimpleBashScript("ip route del " - + NetUtils.getLinkLocalCIDR()); - } else { - foundLinkLocalBr = true; - } - } - } - if (!foundLinkLocalBr) { - Script.runSimpleBashScript("ip route add " - + NetUtils.getLinkLocalCIDR() + " dev " + linkLocalBr - + " src " + NetUtils.getLinkLocalGateway()); - } - } private List getVmDiskStat(Connect conn, String vmName) throws LibvirtException { @@ -5002,13 +4897,13 @@ ServerResource { @Override public void setName(String name) { // TODO Auto-generated method stub - + } @Override public void setConfigParams(Map params) { // TODO Auto-generated method stub - + } @Override @@ -5026,7 +4921,7 @@ ServerResource { @Override public void setRunLevel(int level) { // TODO Auto-generated method stub - + } } diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtConnection.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtConnection.java index 2fc54253f57..ea8429e9362 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtConnection.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtConnection.java @@ -16,19 +16,18 @@ // under the License. package com.cloud.hypervisor.kvm.resource; -import com.cloud.hypervisor.Hypervisor; -import com.cloud.hypervisor.Hypervisor.HypervisorType; +import java.util.HashMap; +import java.util.Map; + import org.apache.log4j.Logger; import org.libvirt.Connect; import org.libvirt.LibvirtException; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; +import com.cloud.hypervisor.Hypervisor; +import com.cloud.hypervisor.Hypervisor.HypervisorType; public class LibvirtConnection { - private static final Logger s_logger = Logger - .getLogger(LibvirtConnection.class); + private static final Logger s_logger = Logger.getLogger(LibvirtConnection.class); static private Map _connections = new HashMap(); static private Connect _connection; @@ -48,8 +47,7 @@ public class LibvirtConnection { try { conn.getVersion(); } catch (LibvirtException e) { - s_logger.debug("Connection with libvirtd is broken, due to " - + e.getMessage()); + s_logger.debug("Connection with libvirtd is broken, due to " + e.getMessage()); conn = new Connect(hypervisorURI, false); _connections.put(hypervisorURI, conn); } @@ -59,17 +57,16 @@ public class LibvirtConnection { } static public Connect getConnectionByVmName(String vmName) throws LibvirtException { - HypervisorType[] hypervisors = new HypervisorType[] {HypervisorType.KVM, Hypervisor.HypervisorType.LXC}; + HypervisorType[] hypervisors = new HypervisorType[] { HypervisorType.KVM, Hypervisor.HypervisorType.LXC }; - for (HypervisorType hypervisor : hypervisors) { try { Connect conn = LibvirtConnection.getConnectionByType(hypervisor.toString()); - if (conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName.getBytes())) != null) { + if (conn.domainLookupByName(vmName) != null) { return conn; } } catch (Exception e) { - s_logger.debug("can't find connection: " + hypervisor.toString() + ", for vm: " + vmName + ", continue"); + s_logger.debug("can't find connection: " + hypervisor.toString() + ", for vm: " + vmName + ", continue"); } } diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java index 0aa0e148dd1..93b4dfedb62 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java @@ -358,7 +358,7 @@ public class LibvirtVMDef { } public static class DiskDef { - enum deviceType { + public enum deviceType { FLOPPY("floppy"), DISK("disk"), CDROM("cdrom"); String _type; @@ -400,7 +400,7 @@ public class LibvirtVMDef { } } - enum diskBus { + public enum diskBus { IDE("ide"), SCSI("scsi"), VIRTIO("virtio"), XEN("xen"), USB("usb"), UML( "uml"), FDC("fdc"); String _bus; @@ -415,7 +415,7 @@ public class LibvirtVMDef { } } - enum diskFmtType { + public enum diskFmtType { RAW("raw"), QCOW2("qcow2"); String _fmtType; diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java new file mode 100644 index 00000000000..8dce094f358 --- /dev/null +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java @@ -0,0 +1,862 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.cloud.hypervisor.kvm.storage; + +import java.io.File; +import java.io.FileOutputStream; +import java.net.URISyntaxException; +import java.text.DateFormat; +import java.text.MessageFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.naming.ConfigurationException; + +import org.apache.cloudstack.storage.command.AttachAnswer; +import org.apache.cloudstack.storage.command.AttachCommand; +import org.apache.cloudstack.storage.command.CopyCmdAnswer; +import org.apache.cloudstack.storage.command.CopyCommand; +import org.apache.cloudstack.storage.command.CreateObjectAnswer; +import org.apache.cloudstack.storage.command.CreateObjectCommand; +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.command.DettachAnswer; +import org.apache.cloudstack.storage.command.DettachCommand; +import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; +import org.apache.cloudstack.storage.to.SnapshotObjectTO; +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.cloudstack.utils.qemu.QemuImg; +import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; +import org.apache.cloudstack.utils.qemu.QemuImgException; +import org.apache.cloudstack.utils.qemu.QemuImgFile; +import org.apache.log4j.Logger; +import org.libvirt.Connect; +import org.libvirt.Domain; +import org.libvirt.DomainInfo; +import org.libvirt.DomainSnapshot; +import org.libvirt.LibvirtException; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.DiskTO; +import com.cloud.agent.api.to.NfsTO; +import com.cloud.exception.InternalErrorException; +import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; +import com.cloud.hypervisor.kvm.resource.LibvirtConnection; +import com.cloud.hypervisor.kvm.resource.LibvirtDomainXMLParser; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DiskDef; +import com.cloud.storage.JavaStorageLayer; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.storage.StorageLayer; +import com.cloud.storage.resource.StorageProcessor; +import com.cloud.storage.template.Processor; +import com.cloud.storage.template.Processor.FormatInfo; +import com.cloud.storage.template.QCOW2Processor; +import com.cloud.storage.template.TemplateLocation; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; + +public class KVMStorageProcessor implements StorageProcessor { + private static final Logger s_logger = Logger.getLogger(KVMStorageProcessor.class); + private KVMStoragePoolManager storagePoolMgr; + private LibvirtComputingResource resource; + private StorageLayer storageLayer; + private String _createTmplPath; + private String _manageSnapshotPath; + private int _cmdsTimeout; + + public KVMStorageProcessor(KVMStoragePoolManager storagePoolMgr, LibvirtComputingResource resource) { + this.storagePoolMgr = storagePoolMgr; + this.resource = resource; + } + + protected String getDefaultStorageScriptsDir() { + return "scripts/storage/qcow2"; + } + + public boolean configure(String name, Map params) throws ConfigurationException { + storageLayer = new JavaStorageLayer(); + storageLayer.configure("StorageLayer", params); + + String storageScriptsDir = (String) params.get("storage.scripts.dir"); + if (storageScriptsDir == null) { + storageScriptsDir = getDefaultStorageScriptsDir(); + } + + _createTmplPath = Script.findScript(storageScriptsDir, "createtmplt.sh"); + if (_createTmplPath == null) { + throw new ConfigurationException("Unable to find the createtmplt.sh"); + } + + _manageSnapshotPath = Script.findScript(storageScriptsDir, "managesnapshot.sh"); + if (_manageSnapshotPath == null) { + throw new ConfigurationException("Unable to find the managesnapshot.sh"); + } + + String value = (String) params.get("cmds.timeout"); + _cmdsTimeout = NumbersUtil.parseInt(value, 7200) * 1000; + return true; + } + + @Override + public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) { + DataTO srcData = cmd.getSrcTO(); + DataTO destData = cmd.getDestTO(); + TemplateObjectTO template = (TemplateObjectTO) srcData; + DataStoreTO imageStore = template.getDataStore(); + TemplateObjectTO volume = (TemplateObjectTO) destData; + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) volume.getDataStore(); + + if (!(imageStore instanceof NfsTO)) { + return new CopyCmdAnswer("unsupported protocol"); + } + + NfsTO nfsImageStore = (NfsTO) imageStore; + String tmplturl = nfsImageStore.getUrl() + File.separator + template.getPath(); + int index = tmplturl.lastIndexOf("/"); + String mountpoint = tmplturl.substring(0, index); + String tmpltname = null; + if (index < tmplturl.length() - 1) { + tmpltname = tmplturl.substring(index + 1); + } + + KVMPhysicalDisk tmplVol = null; + KVMStoragePool secondaryPool = null; + try { + secondaryPool = storagePoolMgr.getStoragePoolByURI(mountpoint); + + /* Get template vol */ + if (tmpltname == null) { + secondaryPool.refresh(); + List disks = secondaryPool.listPhysicalDisks(); + if (disks == null || disks.isEmpty()) { + return new PrimaryStorageDownloadAnswer("Failed to get volumes from pool: " + + secondaryPool.getUuid()); + } + for (KVMPhysicalDisk disk : disks) { + if (disk.getName().endsWith("qcow2")) { + tmplVol = disk; + break; + } + } + if (tmplVol == null) { + return new PrimaryStorageDownloadAnswer("Failed to get template from pool: " + + secondaryPool.getUuid()); + } + } else { + tmplVol = secondaryPool.getPhysicalDisk(tmpltname); + } + + /* Copy volume to primary storage */ + KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), + primaryStore.getUuid()); + + KVMPhysicalDisk primaryVol = storagePoolMgr.copyPhysicalDisk(tmplVol, UUID.randomUUID().toString(), + primaryPool); + + TemplateObjectTO newTemplate = new TemplateObjectTO(); + newTemplate.setPath(primaryVol.getName()); + newTemplate.setFormat(ImageFormat.QCOW2); + return new CopyCmdAnswer(newTemplate); + } catch (CloudRuntimeException e) { + return new CopyCmdAnswer(e.toString()); + } finally { + if (secondaryPool != null) { + secondaryPool.delete(); + } + } + } + + // this is much like PrimaryStorageDownloadCommand, but keeping it separate + private KVMPhysicalDisk templateToPrimaryDownload(String templateUrl, KVMStoragePool primaryPool) { + int index = templateUrl.lastIndexOf("/"); + String mountpoint = templateUrl.substring(0, index); + String templateName = null; + if (index < templateUrl.length() - 1) { + templateName = templateUrl.substring(index + 1); + } + + KVMPhysicalDisk templateVol = null; + KVMStoragePool secondaryPool = null; + try { + secondaryPool = storagePoolMgr.getStoragePoolByURI(mountpoint); + /* Get template vol */ + if (templateName == null) { + secondaryPool.refresh(); + List disks = secondaryPool.listPhysicalDisks(); + if (disks == null || disks.isEmpty()) { + s_logger.error("Failed to get volumes from pool: " + secondaryPool.getUuid()); + return null; + } + for (KVMPhysicalDisk disk : disks) { + if (disk.getName().endsWith("qcow2")) { + templateVol = disk; + break; + } + } + if (templateVol == null) { + s_logger.error("Failed to get template from pool: " + secondaryPool.getUuid()); + return null; + } + } else { + templateVol = secondaryPool.getPhysicalDisk(templateName); + } + + /* Copy volume to primary storage */ + + KVMPhysicalDisk primaryVol = storagePoolMgr.copyPhysicalDisk(templateVol, UUID.randomUUID().toString(), + primaryPool); + return primaryVol; + } catch (CloudRuntimeException e) { + s_logger.error("Failed to download template to primary storage", e); + return null; + } finally { + if (secondaryPool != null) { + secondaryPool.delete(); + } + } + } + + @Override + public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd) { + DataTO srcData = cmd.getSrcTO(); + DataTO destData = cmd.getDestTO(); + TemplateObjectTO template = (TemplateObjectTO) srcData; + DataStoreTO imageStore = template.getDataStore(); + VolumeObjectTO volume = (VolumeObjectTO) destData; + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) volume.getDataStore(); + KVMPhysicalDisk BaseVol = null; + KVMStoragePool primaryPool = null; + KVMPhysicalDisk vol = null; + + try { + primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid()); + + String templatePath = template.getPath(); + + if (primaryPool.getType() == StoragePoolType.CLVM) { + vol = templateToPrimaryDownload(templatePath, primaryPool); + } else { + BaseVol = primaryPool.getPhysicalDisk(templatePath); + vol = storagePoolMgr.createDiskFromTemplate(BaseVol, UUID.randomUUID().toString(), primaryPool); + } + if (vol == null) { + return new CopyCmdAnswer(" Can't create storage volume on storage pool"); + } + + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(vol.getName()); + newVol.setSize(vol.getSize()); + + return new CopyCmdAnswer(newVol); + } catch (CloudRuntimeException e) { + s_logger.debug("Failed to create volume: " + e.toString()); + return new CopyCmdAnswer(e.toString()); + } + } + + @Override + public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) { + return null; + } + + @Override + public Answer createTemplateFromVolume(CopyCommand cmd) { + DataTO srcData = cmd.getSrcTO(); + DataTO destData = cmd.getDestTO(); + int wait = cmd.getWait(); + TemplateObjectTO template = (TemplateObjectTO) destData; + DataStoreTO imageStore = template.getDataStore(); + VolumeObjectTO volume = (VolumeObjectTO) srcData; + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) volume.getDataStore(); + + if (!(imageStore instanceof NfsTO)) { + return new CopyCmdAnswer("unsupported protocol"); + } + NfsTO nfsImageStore = (NfsTO) imageStore; + + KVMStoragePool secondaryStorage = null; + KVMStoragePool primary = null; + try { + String templateFolder = template.getPath(); + + secondaryStorage = storagePoolMgr.getStoragePoolByURI(nfsImageStore.getUrl()); + + try { + primary = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid()); + } catch (CloudRuntimeException e) { + if (e.getMessage().contains("not found")) { + primary = storagePoolMgr.createStoragePool(primaryStore.getUuid(), primaryStore.getHost(), + primaryStore.getPort(), primaryStore.getPath(), null, primaryStore.getPoolType()); + } else { + return new CopyCmdAnswer(e.getMessage()); + } + } + + KVMPhysicalDisk disk = primary.getPhysicalDisk(volume.getPath()); + String tmpltPath = secondaryStorage.getLocalPath() + File.separator + templateFolder; + this.storageLayer.mkdirs(tmpltPath); + String templateName = UUID.randomUUID().toString(); + + if (primary.getType() != StoragePoolType.RBD) { + Script command = new Script(_createTmplPath, wait * 1000, s_logger); + command.add("-f", disk.getPath()); + command.add("-t", tmpltPath); + command.add("-n", templateName + ".qcow2"); + + String result = command.execute(); + + if (result != null) { + s_logger.debug("failed to create template: " + result); + return new CopyCmdAnswer(result); + } + } else { + s_logger.debug("Converting RBD disk " + disk.getPath() + " into template " + templateName); + + QemuImgFile srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(primary.getSourceHost(), + primary.getSourcePort(), primary.getAuthUserName(), primary.getAuthSecret(), disk.getPath())); + srcFile.setFormat(PhysicalDiskFormat.RAW); + + QemuImgFile destFile = new QemuImgFile(tmpltPath + "/" + templateName + ".qcow2"); + destFile.setFormat(PhysicalDiskFormat.QCOW2); + + QemuImg q = new QemuImg(); + try { + q.convert(srcFile, destFile); + } catch (QemuImgException e) { + s_logger.error("Failed to create new template while converting " + srcFile.getFileName() + " to " + + destFile.getFileName() + " the error was: " + e.getMessage()); + } + + File templateProp = new File(tmpltPath + "/template.properties"); + if (!templateProp.exists()) { + templateProp.createNewFile(); + } + + String templateContent = "filename=" + templateName + ".qcow2" + System.getProperty("line.separator"); + + DateFormat dateFormat = new SimpleDateFormat("MM_dd_yyyy"); + Date date = new Date(); + templateContent += "snapshot.name=" + dateFormat.format(date) + System.getProperty("line.separator"); + + FileOutputStream templFo = new FileOutputStream(templateProp); + templFo.write(templateContent.getBytes()); + templFo.flush(); + templFo.close(); + } + + Map params = new HashMap(); + params.put(StorageLayer.InstanceConfigKey, this.storageLayer); + Processor qcow2Processor = new QCOW2Processor(); + + qcow2Processor.configure("QCOW2 Processor", params); + + FormatInfo info = qcow2Processor.process(tmpltPath, null, templateName); + + TemplateLocation loc = new TemplateLocation(this.storageLayer, tmpltPath); + loc.create(1, true, templateName); + loc.addFormat(info); + loc.save(); + + TemplateObjectTO newTemplate = new TemplateObjectTO(); + newTemplate.setPath(templateFolder + File.separator + templateName + ".qcow2"); + newTemplate.setSize(info.virtualSize); + newTemplate.setFormat(ImageFormat.QCOW2); + return new CopyCmdAnswer(newTemplate); + } catch (Exception e) { + s_logger.debug("Failed to create template from volume: " + e.toString()); + return new CopyCmdAnswer(e.toString()); + } finally { + if (secondaryStorage != null) { + secondaryStorage.delete(); + } + } + } + + @Override + public Answer backupSnasphot(CopyCommand cmd) { + DataTO srcData = cmd.getSrcTO(); + DataTO destData = cmd.getDestTO(); + SnapshotObjectTO snapshot = (SnapshotObjectTO) srcData; + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) snapshot.getDataStore(); + SnapshotObjectTO destSnapshot = (SnapshotObjectTO) destData; + DataStoreTO imageStore = destData.getDataStore(); + + if (!(imageStore instanceof NfsTO)) { + return new CopyCmdAnswer("unsupported protocol"); + } + NfsTO nfsImageStore = (NfsTO) imageStore; + + String secondaryStoragePoolUrl = nfsImageStore.getUrl(); + // NOTE: snapshot name is encoded in snapshot path + int index = snapshot.getPath().lastIndexOf("/"); + + String snapshotName = snapshot.getPath().substring(index + 1); + String volumePath = snapshot.getVolume().getPath(); + String snapshotDestPath = null; + String snapshotRelPath = null; + String vmName = snapshot.getVmName(); + KVMStoragePool secondaryStoragePool = null; + try { + Connect conn = LibvirtConnection.getConnectionByVmName(vmName); + + secondaryStoragePool = storagePoolMgr.getStoragePoolByURI(secondaryStoragePoolUrl); + + String ssPmountPath = secondaryStoragePool.getLocalPath(); + snapshotRelPath = destSnapshot.getPath(); + + snapshotDestPath = ssPmountPath + File.separator + snapshotRelPath; + KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), + primaryStore.getUuid()); + KVMPhysicalDisk snapshotDisk = primaryPool.getPhysicalDisk(volumePath); + Script command = new Script(_manageSnapshotPath, cmd.getWait() * 1000, s_logger); + command.add("-b", snapshotDisk.getPath()); + command.add("-n", snapshotName); + command.add("-p", snapshotDestPath); + command.add("-t", snapshotName); + String result = command.execute(); + if (result != null) { + s_logger.debug("Failed to backup snaptshot: " + result); + return new CopyCmdAnswer(result); + } + /* Delete the snapshot on primary */ + + DomainInfo.DomainState state = null; + Domain vm = null; + if (vmName != null) { + try { + vm = this.resource.getDomain(conn, vmName); + state = vm.getInfo().state; + } catch (LibvirtException e) { + s_logger.trace("Ignoring libvirt error.", e); + } + } + + KVMStoragePool primaryStorage = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), + primaryStore.getUuid()); + if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING && !primaryStorage.isExternalSnapshot()) { + DomainSnapshot snap = vm.snapshotLookupByName(snapshotName); + snap.delete(0); + + /* + * libvirt on RHEL6 doesn't handle resume event emitted from + * qemu + */ + vm = this.resource.getDomain(conn, vmName); + state = vm.getInfo().state; + if (state == DomainInfo.DomainState.VIR_DOMAIN_PAUSED) { + vm.resume(); + } + } else { + command = new Script(_manageSnapshotPath, _cmdsTimeout, s_logger); + command.add("-d", snapshotDisk.getPath()); + command.add("-n", snapshotName); + result = command.execute(); + if (result != null) { + s_logger.debug("Failed to backup snapshot: " + result); + return new CopyCmdAnswer("Failed to backup snapshot: " + result); + } + } + + SnapshotObjectTO newSnapshot = new SnapshotObjectTO(); + newSnapshot.setPath(snapshotRelPath + File.separator + snapshotName); + return new CopyCmdAnswer(newSnapshot); + } catch (LibvirtException e) { + s_logger.debug("Failed to backup snapshot: " + e.toString()); + return new CopyCmdAnswer(e.toString()); + } catch (CloudRuntimeException e) { + s_logger.debug("Failed to backup snapshot: " + e.toString()); + return new CopyCmdAnswer(e.toString()); + } finally { + if (secondaryStoragePool != null) { + secondaryStoragePool.delete(); + } + } + } + + protected synchronized String attachOrDetachISO(Connect conn, String vmName, String isoPath, boolean isAttach) + throws LibvirtException, URISyntaxException, InternalErrorException { + String isoXml = null; + if (isoPath != null && isAttach) { + int index = isoPath.lastIndexOf("/"); + String path = isoPath.substring(0, index); + String name = isoPath.substring(index + 1); + KVMStoragePool secondaryPool = storagePoolMgr.getStoragePoolByURI(path); + KVMPhysicalDisk isoVol = secondaryPool.getPhysicalDisk(name); + isoPath = isoVol.getPath(); + + DiskDef iso = new DiskDef(); + iso.defISODisk(isoPath); + isoXml = iso.toString(); + } else { + DiskDef iso = new DiskDef(); + iso.defISODisk(null); + isoXml = iso.toString(); + } + + List disks = this.resource.getDisks(conn, vmName); + String result = attachOrDetachDevice(conn, true, vmName, isoXml); + if (result == null && !isAttach) { + for (DiskDef disk : disks) { + if (disk.getDeviceType() == DiskDef.deviceType.CDROM) { + this.resource.cleanupDisk(conn, disk); + } + } + + } + return result; + } + + @Override + public Answer attachIso(AttachCommand cmd) { + DiskTO disk = cmd.getDisk(); + TemplateObjectTO isoTO = (TemplateObjectTO) disk.getData(); + DataStoreTO store = isoTO.getDataStore(); + if (!(store instanceof NfsTO)) { + return new AttachAnswer("unsupported protocol"); + } + NfsTO nfsStore = (NfsTO) store; + try { + Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName()); + attachOrDetachISO(conn, cmd.getVmName(), nfsStore.getUrl() + File.separator + isoTO.getPath(), true); + } catch (LibvirtException e) { + return new Answer(cmd, false, e.toString()); + } catch (URISyntaxException e) { + return new Answer(cmd, false, e.toString()); + } catch (InternalErrorException e) { + return new Answer(cmd, false, e.toString()); + } + + return new Answer(cmd); + } + + @Override + public Answer dettachIso(DettachCommand cmd) { + DiskTO disk = cmd.getDisk(); + TemplateObjectTO isoTO = (TemplateObjectTO) disk.getData(); + DataStoreTO store = isoTO.getDataStore(); + if (!(store instanceof NfsTO)) { + return new AttachAnswer("unsupported protocol"); + } + NfsTO nfsStore = (NfsTO) store; + try { + Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName()); + attachOrDetachISO(conn, cmd.getVmName(), nfsStore.getUrl() + File.separator + isoTO.getPath(), false); + } catch (LibvirtException e) { + return new Answer(cmd, false, e.toString()); + } catch (URISyntaxException e) { + return new Answer(cmd, false, e.toString()); + } catch (InternalErrorException e) { + return new Answer(cmd, false, e.toString()); + } + + return new Answer(cmd); + } + + protected synchronized String attachOrDetachDevice(Connect conn, boolean attach, String vmName, String xml) + throws LibvirtException, InternalErrorException { + Domain dm = null; + try { + dm = conn.domainLookupByName(vmName); + + if (attach) { + s_logger.debug("Attaching device: " + xml); + dm.attachDevice(xml); + } else { + s_logger.debug("Detaching device: " + xml); + dm.detachDevice(xml); + } + } catch (LibvirtException e) { + if (attach) { + s_logger.warn("Failed to attach device to " + vmName + ": " + e.getMessage()); + } else { + s_logger.warn("Failed to detach device from " + vmName + ": " + e.getMessage()); + } + throw e; + } finally { + if (dm != null) { + try { + dm.free(); + } catch (LibvirtException l) { + s_logger.trace("Ignoring libvirt error.", l); + } + } + } + + return null; + } + + protected synchronized String attachOrDetachDisk(Connect conn, boolean attach, String vmName, + KVMPhysicalDisk attachingDisk, int devId) throws LibvirtException, InternalErrorException { + List disks = null; + Domain dm = null; + DiskDef diskdef = null; + try { + if (!attach) { + dm = conn.domainLookupByName(vmName); + LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); + String xml = dm.getXMLDesc(0); + parser.parseDomainXML(xml); + disks = parser.getDisks(); + + for (DiskDef disk : disks) { + String file = disk.getDiskPath(); + if (file != null && file.equalsIgnoreCase(attachingDisk.getPath())) { + diskdef = disk; + break; + } + } + if (diskdef == null) { + throw new InternalErrorException("disk: " + attachingDisk.getPath() + " is not attached before"); + } + } else { + diskdef = new DiskDef(); + if (attachingDisk.getFormat() == PhysicalDiskFormat.QCOW2) { + diskdef.defFileBasedDisk(attachingDisk.getPath(), devId, DiskDef.diskBus.VIRTIO, + DiskDef.diskFmtType.QCOW2); + } else if (attachingDisk.getFormat() == PhysicalDiskFormat.RAW) { + diskdef.defBlockBasedDisk(attachingDisk.getPath(), devId, DiskDef.diskBus.VIRTIO); + } + } + + String xml = diskdef.toString(); + return attachOrDetachDevice(conn, attach, vmName, xml); + } finally { + if (dm != null) { + dm.free(); + } + } + } + + @Override + public Answer attachVolume(AttachCommand cmd) { + DiskTO disk = cmd.getDisk(); + VolumeObjectTO vol = (VolumeObjectTO) disk.getData(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) vol.getDataStore(); + String vmName = cmd.getVmName(); + try { + Connect conn = LibvirtConnection.getConnectionByVmName(vmName); + KVMStoragePool primary = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid()); + + KVMPhysicalDisk phyDisk = primary.getPhysicalDisk(vol.getPath()); + attachOrDetachDisk(conn, true, vmName, phyDisk, disk.getDiskSeq().intValue()); + + return new AttachAnswer(disk); + } catch (LibvirtException e) { + s_logger.debug("Failed to attach volume: " + vol.getPath() + ", due to " + e.toString()); + return new AttachAnswer(e.toString()); + } catch (InternalErrorException e) { + s_logger.debug("Failed to attach volume: " + vol.getPath() + ", due to " + e.toString()); + return new AttachAnswer(e.toString()); + } + } + + @Override + public Answer dettachVolume(DettachCommand cmd) { + DiskTO disk = cmd.getDisk(); + VolumeObjectTO vol = (VolumeObjectTO) disk.getData(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) vol.getDataStore(); + String vmName = cmd.getVmName(); + try { + Connect conn = LibvirtConnection.getConnectionByVmName(vmName); + KVMStoragePool primary = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid()); + + KVMPhysicalDisk phyDisk = primary.getPhysicalDisk(vol.getPath()); + attachOrDetachDisk(conn, false, vmName, phyDisk, disk.getDiskSeq().intValue()); + + return new DettachAnswer(disk); + } catch (LibvirtException e) { + s_logger.debug("Failed to attach volume: " + vol.getPath() + ", due to " + e.toString()); + return new DettachAnswer(e.toString()); + } catch (InternalErrorException e) { + s_logger.debug("Failed to attach volume: " + vol.getPath() + ", due to " + e.toString()); + return new DettachAnswer(e.toString()); + } + } + + @Override + public Answer createVolume(CreateObjectCommand cmd) { + VolumeObjectTO volume = (VolumeObjectTO) cmd.getData(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) volume.getDataStore(); + + KVMStoragePool primaryPool = null; + KVMPhysicalDisk vol = null; + long disksize; + try { + primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid()); + disksize = volume.getSize(); + + vol = primaryPool.createPhysicalDisk(UUID.randomUUID().toString(), disksize); + + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(vol.getName()); + + return new CreateObjectAnswer(newVol); + } catch (Exception e) { + s_logger.debug("Failed to create volume: " + e.toString()); + return new CreateObjectAnswer(e.toString()); + } + } + + protected static MessageFormat SnapshotXML = new MessageFormat(" " + " {0}" + + " " + " {1}" + " " + " "); + + @Override + public Answer createSnapshot(CreateObjectCommand cmd) { + SnapshotObjectTO snapshotTO = (SnapshotObjectTO) cmd.getData(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) snapshotTO.getDataStore(); + VolumeObjectTO volume = snapshotTO.getVolume(); + String snapshotName = UUID.randomUUID().toString(); + String vmName = volume.getVmName(); + try { + Connect conn = LibvirtConnection.getConnectionByVmName(vmName); + DomainInfo.DomainState state = null; + Domain vm = null; + if (vmName != null) { + try { + vm = this.resource.getDomain(conn, vmName); + state = vm.getInfo().state; + } catch (LibvirtException e) { + s_logger.trace("Ignoring libvirt error.", e); + } + } + + KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), + primaryStore.getUuid()); + + if (primaryPool.getType() == StoragePoolType.RBD) { + s_logger.debug("Snapshots are not supported on RBD volumes"); + return new CreateObjectAnswer("Snapshots are not supported on RBD volumes"); + } + + KVMPhysicalDisk disk = primaryPool.getPhysicalDisk(volume.getPath()); + if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING && !primaryPool.isExternalSnapshot()) { + String vmUuid = vm.getUUIDString(); + Object[] args = new Object[] { snapshotName, vmUuid }; + String snapshot = SnapshotXML.format(args); + s_logger.debug(snapshot); + + vm.snapshotCreateXML(snapshot); + /* + * libvirt on RHEL6 doesn't handle resume event emitted from + * qemu + */ + vm = this.resource.getDomain(conn, vmName); + state = vm.getInfo().state; + if (state == DomainInfo.DomainState.VIR_DOMAIN_PAUSED) { + vm.resume(); + } + } else { + + /* VM is not running, create a snapshot by ourself */ + final Script command = new Script(_manageSnapshotPath, this._cmdsTimeout, s_logger); + command.add("-c", disk.getPath()); + command.add("-n", snapshotName); + String result = command.execute(); + if (result != null) { + s_logger.debug("Failed to manage snapshot: " + result); + return new CreateObjectAnswer("Failed to manage snapshot: " + result); + } + } + + SnapshotObjectTO newSnapshot = new SnapshotObjectTO(); + // NOTE: sort of hack, we'd better just put snapshtoName + newSnapshot.setPath(disk.getPath() + File.separator + snapshotName); + return new CreateObjectAnswer(newSnapshot); + } catch (LibvirtException e) { + s_logger.debug("Failed to manage snapshot: " + e.toString()); + return new CreateObjectAnswer("Failed to manage snapshot: " + e.toString()); + } + } + + @Override + public Answer deleteVolume(DeleteCommand cmd) { + VolumeObjectTO vol = (VolumeObjectTO) cmd.getData(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) vol.getDataStore(); + try { + KVMStoragePool pool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid()); + try { + pool.getPhysicalDisk(vol.getPath()); + } catch (Exception e) { + s_logger.debug("can't find volume: " + vol.getPath() + ", return true"); + return new Answer(null); + } + pool.deletePhysicalDisk(vol.getPath()); + return new Answer(null); + } catch (CloudRuntimeException e) { + s_logger.debug("Failed to delete volume: " + e.toString()); + return new Answer(null, false, e.toString()); + } + } + + @Override + public Answer createVolumeFromSnapshot(CopyCommand cmd) { + try { + DataTO srcData = cmd.getSrcTO(); + SnapshotObjectTO snapshot = (SnapshotObjectTO) srcData; + DataTO destData = cmd.getDestTO(); + PrimaryDataStoreTO pool = (PrimaryDataStoreTO) destData.getDataStore(); + DataStoreTO imageStore = srcData.getDataStore(); + + if (!(imageStore instanceof NfsTO)) { + return new CopyCmdAnswer("unsupported protocol"); + } + + NfsTO nfsImageStore = (NfsTO) imageStore; + + String snapshotPath = snapshot.getPath(); + int index = snapshotPath.lastIndexOf("/"); + snapshotPath = snapshotPath.substring(0, index); + String snapshotName = snapshotPath.substring(index + 1); + KVMStoragePool secondaryPool = storagePoolMgr.getStoragePoolByURI(nfsImageStore.getUrl() + File.separator + + snapshotPath); + KVMPhysicalDisk snapshotDisk = secondaryPool.getPhysicalDisk(snapshotName); + + String primaryUuid = pool.getUuid(); + KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(pool.getPoolType(), primaryUuid); + String volUuid = UUID.randomUUID().toString(); + KVMPhysicalDisk disk = storagePoolMgr.copyPhysicalDisk(snapshotDisk, volUuid, primaryPool); + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(disk.getName()); + newVol.setSize(disk.getVirtualSize()); + return new CopyCmdAnswer(newVol); + } catch (CloudRuntimeException e) { + return new CopyCmdAnswer(e.toString()); + } + } + + @Override + public Answer deleteSnapshot(DeleteCommand cmd) { + return new Answer(cmd); + } +} diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageResource.java new file mode 100644 index 00000000000..52e142e4e13 --- /dev/null +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageResource.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.cloud.hypervisor.kvm.storage; + +import org.apache.cloudstack.storage.command.AttachCommand; +import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd; +import org.apache.cloudstack.storage.command.CopyCommand; +import org.apache.cloudstack.storage.command.CreateObjectCommand; +import org.apache.cloudstack.storage.command.CreatePrimaryDataStoreCmd; +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.command.DettachCommand; +import org.apache.cloudstack.storage.command.StorageSubSystemCommand; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; + +public class KVMStorageResource { + private LibvirtComputingResource resource; + public KVMStorageResource(LibvirtComputingResource resource) { + this.resource = resource; + } + + public Answer handleStorageCommands(StorageSubSystemCommand command) { + if (command instanceof CopyCommand) { + return this.execute((CopyCommand)command); + } else if (command instanceof AttachPrimaryDataStoreCmd) { + return this.execute((AttachPrimaryDataStoreCmd)command); + } else if (command instanceof CreatePrimaryDataStoreCmd) { + return execute((CreatePrimaryDataStoreCmd) command); + } else if (command instanceof CreateObjectCommand) { + return execute((CreateObjectCommand) command); + } else if (command instanceof DeleteCommand) { + return execute((DeleteCommand)command); + } else if (command instanceof AttachCommand) { + return execute((AttachCommand)command); + } else if (command instanceof DettachCommand) { + return execute((DettachCommand)command); + } + return new Answer((Command)command, false, "not implemented yet"); + } + + protected Answer execute(CopyCommand cmd) { + return new Answer((Command)cmd, false, "not implemented yet"); + } + + protected Answer execute(AttachPrimaryDataStoreCmd cmd) { + return new Answer((Command)cmd, false, "not implemented yet"); + } + + protected Answer execute(CreatePrimaryDataStoreCmd cmd) { + return new Answer((Command)cmd, false, "not implemented yet"); + } + + protected Answer execute(CreateObjectCommand cmd) { + return new Answer((Command)cmd, false, "not implemented yet"); + } + + protected Answer execute(DeleteCommand cmd) { + return new Answer((Command)cmd, false, "not implemented yet"); + } + + protected Answer execute(AttachCommand cmd) { + return new Answer((Command)cmd, false, "not implemented yet"); + } + + protected Answer execute(DettachCommand cmd) { + return new Answer((Command)cmd, false, "not implemented yet"); + } + +} diff --git a/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java b/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java index a626e31f458..59ba001d04c 100755 --- a/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java +++ b/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java @@ -29,6 +29,8 @@ import java.util.concurrent.ConcurrentHashMap; import javax.naming.ConfigurationException; +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.log4j.Logger; import org.apache.xmlrpc.XmlRpcException; @@ -90,6 +92,10 @@ import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer; import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.DiskTO; +import com.cloud.agent.api.to.NfsTO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.agent.api.to.VirtualMachineTO; @@ -114,7 +120,7 @@ import com.cloud.resource.hypervisor.HypervisorResource; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Volume; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; import com.cloud.template.VirtualMachineTemplate.BootloaderType; import com.cloud.utils.Pair; import com.cloud.utils.Ternary; @@ -125,7 +131,6 @@ import com.cloud.vm.DiskProfile; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; import com.trilead.ssh2.SCPClient; -import com.xensource.xenapi.Types.XenAPIException; public class OvmResourceBase implements ServerResource, HypervisorResource { private static final Logger s_logger = Logger.getLogger(OvmResourceBase.class); @@ -458,7 +463,7 @@ public class OvmResourceBase implements ServerResource, HypervisorResource { setupHeartBeat(pool.getUuid()); OvmStoragePool.Details d = OvmStoragePool.getDetailsByUuid(_conn, pool.getUuid()); - Map tInfo = new HashMap(); + Map tInfo = new HashMap(); ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, d.totalSpace, d.freeSpace, tInfo); return answer; } catch (Exception e) { @@ -527,25 +532,35 @@ public class OvmResourceBase implements ServerResource, HypervisorResource { } protected void createVbds(OvmVm.Details vm, VirtualMachineTO spec) throws URISyntaxException { - for (VolumeTO volume : spec.getDisks()) { + for (DiskTO volume : spec.getDisks()) { if (volume.getType() == Volume.Type.ROOT) { + VolumeObjectTO vol = (VolumeObjectTO)volume.getData(); OvmDisk.Details root = new OvmDisk.Details(); - root.path = volume.getPath(); + root.path = vol.getPath(); root.type = OvmDisk.WRITE; root.isIso = false; vm.rootDisk = root; } else if (volume.getType() == Volume.Type.ISO) { - if (volume.getPath() != null) { + DataTO isoTO = volume.getData(); + if (isoTO.getPath() != null) { + TemplateObjectTO template = (TemplateObjectTO)isoTO; + DataStoreTO store = template.getDataStore(); + if (!(store instanceof NfsTO)) { + throw new CloudRuntimeException("unsupported protocol"); + } + NfsTO nfsStore = (NfsTO)store; + String isoPath = nfsStore.getUrl() + File.separator + template.getPath(); OvmDisk.Details iso = new OvmDisk.Details(); - URI path = new URI(volume.getPath()); + URI path = new URI(isoPath); iso.path = path.getHost() + ":" + path.getPath(); iso.type = OvmDisk.READ; iso.isIso = true; vm.disks.add(iso); } } else if (volume.getType() == Volume.Type.DATADISK){ + OvmDisk.Details data = new OvmDisk.Details(); - data.path = volume.getPath(); + data.path = volume.getData().getPath(); data.type = OvmDisk.SHAREDWRITE; data.isIso = false; vm.disks.add(data); diff --git a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockStorageManager.java b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockStorageManager.java index a90ea9e10eb..80a605537df 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockStorageManager.java +++ b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockStorageManager.java @@ -16,6 +16,10 @@ // under the License. package com.cloud.agent.manager; +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.command.DownloadCommand; +import org.apache.cloudstack.storage.command.DownloadProgressCommand; + import com.cloud.agent.api.Answer; import com.cloud.agent.api.AttachIsoCommand; import com.cloud.agent.api.AttachVolumeAnswer; @@ -26,7 +30,6 @@ import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand; import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand; import com.cloud.agent.api.CreateStoragePoolCommand; import com.cloud.agent.api.CreateVolumeFromSnapshotCommand; -import com.cloud.agent.api.DeleteSnapshotBackupCommand; import com.cloud.agent.api.DeleteStoragePoolCommand; import com.cloud.agent.api.GetStorageStatsAnswer; import com.cloud.agent.api.GetStorageStatsCommand; @@ -39,10 +42,7 @@ import com.cloud.agent.api.storage.CopyVolumeAnswer; import com.cloud.agent.api.storage.CopyVolumeCommand; import com.cloud.agent.api.storage.CreateAnswer; import com.cloud.agent.api.storage.CreateCommand; -import com.cloud.agent.api.storage.DeleteTemplateCommand; import com.cloud.agent.api.storage.DestroyCommand; -import com.cloud.agent.api.storage.DownloadCommand; -import com.cloud.agent.api.storage.DownloadProgressCommand; import com.cloud.agent.api.storage.ListTemplateCommand; import com.cloud.agent.api.storage.ListVolumeCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; @@ -72,9 +72,10 @@ public interface MockStorageManager extends Manager { public GetStorageStatsAnswer GetStorageStats(GetStorageStatsCommand cmd); public Answer ManageSnapshot(ManageSnapshotCommand cmd); public Answer BackupSnapshot(BackupSnapshotCommand cmd, SimulatorInfo info); - public Answer DeleteSnapshotBackup(DeleteSnapshotBackupCommand cmd); + //public Answer DeleteSnapshotBackup(DeleteSnapshotBackupCommand cmd); public Answer CreateVolumeFromSnapshot(CreateVolumeFromSnapshotCommand cmd); - public Answer DeleteTemplate(DeleteTemplateCommand cmd); + //public Answer DeleteTemplate(DeleteTemplateCommand cmd); + public Answer Delete(DeleteCommand cmd); public Answer SecStorageVMSetup(SecStorageVMSetupCommand cmd); public void preinstallTemplates(String url, long zoneId); diff --git a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockStorageManagerImpl.java b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockStorageManagerImpl.java index a50dff6382c..21b81e1d7bb 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockStorageManagerImpl.java +++ b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockStorageManagerImpl.java @@ -28,7 +28,6 @@ import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand; import com.cloud.agent.api.CreateStoragePoolCommand; import com.cloud.agent.api.CreateVolumeFromSnapshotAnswer; import com.cloud.agent.api.CreateVolumeFromSnapshotCommand; -import com.cloud.agent.api.DeleteSnapshotBackupCommand; import com.cloud.agent.api.DeleteStoragePoolCommand; import com.cloud.agent.api.GetStorageStatsAnswer; import com.cloud.agent.api.GetStorageStatsCommand; @@ -45,17 +44,15 @@ import com.cloud.agent.api.storage.CopyVolumeCommand; import com.cloud.agent.api.storage.CreateAnswer; import com.cloud.agent.api.storage.CreateCommand; import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer; -import com.cloud.agent.api.storage.DeleteTemplateCommand; import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.DownloadAnswer; -import com.cloud.agent.api.storage.DownloadCommand; -import com.cloud.agent.api.storage.DownloadProgressCommand; import com.cloud.agent.api.storage.ListTemplateAnswer; import com.cloud.agent.api.storage.ListTemplateCommand; import com.cloud.agent.api.storage.ListVolumeAnswer; import com.cloud.agent.api.storage.ListVolumeCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; +import com.cloud.agent.api.to.DataStoreTO; import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.agent.api.to.VolumeTO; import com.cloud.simulator.MockHost; @@ -74,14 +71,19 @@ import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.DiskProfile; import com.cloud.vm.VirtualMachine.State; + +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.command.DownloadCommand; +import org.apache.cloudstack.storage.command.DownloadProgressCommand; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.agent.api.to.NfsTO; import javax.ejb.Local; import javax.inject.Inject; @@ -357,7 +359,7 @@ public class MockStorageManagerImpl extends ManagerBase implements MockStorageMa txn = Transaction.open(Transaction.CLOUD_DB); txn.close(); } - return new ModifyStoragePoolAnswer(cmd, storagePool.getCapacity(), 0, new HashMap()); + return new ModifyStoragePoolAnswer(cmd, storagePool.getCapacity(), 0, new HashMap()); } @Override @@ -398,7 +400,7 @@ public class MockStorageManagerImpl extends ManagerBase implements MockStorageMa txn = Transaction.open(Transaction.CLOUD_DB); txn.close(); } - return new ModifyStoragePoolAnswer(cmd, storagePool.getCapacity(), 0, new HashMap()); + return new ModifyStoragePoolAnswer(cmd, storagePool.getCapacity(), 0, new HashMap()); } @Override @@ -449,9 +451,9 @@ public class MockStorageManagerImpl extends ManagerBase implements MockStorageMa List volumes = _mockVolumeDao.findByStorageIdAndType(storage.getId(), MockVolumeType.VOLUME); - Map templateInfos = new HashMap(); + Map templateInfos = new HashMap(); for (MockVolumeVO volume : volumes) { - templateInfos.put(volume.getId(), new TemplateInfo(volume.getName(), volume.getPath() + templateInfos.put(volume.getId(), new TemplateProp(volume.getName(), volume.getPath() .replaceAll(storage.getMountPoint(), ""), volume.getSize(), volume.getSize(), true, false)); } txn.commit(); @@ -468,18 +470,23 @@ public class MockStorageManagerImpl extends ManagerBase implements MockStorageMa @Override public Answer ListTemplates(ListTemplateCommand cmd) { + DataStoreTO store = cmd.getDataStore(); + if ( !(store instanceof NfsTO )){ + return new Answer(cmd, false, "Unsupported image data store: " + store); + } Transaction txn = Transaction.open(Transaction.SIMULATOR_DB); MockSecStorageVO storage = null; + String nfsUrl = ((NfsTO)cmd.getDataStore()).getUrl(); try { txn.start(); - storage = _mockSecStorageDao.findByUrl(cmd.getSecUrl()); + storage = _mockSecStorageDao.findByUrl(nfsUrl); if (storage == null) { return new Answer(cmd, false, "Failed to get secondary storage"); } txn.commit(); } catch (Exception ex) { txn.rollback(); - throw new CloudRuntimeException("Error when finding sec storage " + cmd.getSecUrl(), ex); + throw new CloudRuntimeException("Error when finding sec storage " + nfsUrl, ex); } finally { txn.close(); txn = Transaction.open(Transaction.CLOUD_DB); @@ -492,13 +499,13 @@ public class MockStorageManagerImpl extends ManagerBase implements MockStorageMa List templates = _mockVolumeDao.findByStorageIdAndType(storage.getId(), MockVolumeType.TEMPLATE); - Map templateInfos = new HashMap(); + Map templateInfos = new HashMap(); for (MockVolumeVO template : templates) { - templateInfos.put(template.getName(), new TemplateInfo(template.getName(), template.getPath() + templateInfos.put(template.getName(), new TemplateProp(template.getName(), template.getPath() .replaceAll(storage.getMountPoint(), ""), template.getSize(), template.getSize(), true, false)); } txn.commit(); - return new ListTemplateAnswer(cmd.getSecUrl(), templateInfos); + return new ListTemplateAnswer(nfsUrl, templateInfos); } catch (Exception ex) { txn.rollback(); throw new CloudRuntimeException("Error when finding template on sec storage " + storage.getId(), ex); @@ -774,28 +781,6 @@ public class MockStorageManagerImpl extends ManagerBase implements MockStorageMa return new BackupSnapshotAnswer(cmd, true, null, newsnapshot.getName(), true); } - @Override - public Answer DeleteSnapshotBackup(DeleteSnapshotBackupCommand cmd) { - Transaction txn = Transaction.open(Transaction.SIMULATOR_DB); - try { - txn.start(); - MockVolumeVO backSnapshot = _mockVolumeDao.findByName(cmd.getSnapshotUuid()); - if (backSnapshot == null) { - return new Answer(cmd, false, "can't find the backupsnapshot: " + cmd.getSnapshotUuid()); - } - _mockVolumeDao.remove(backSnapshot.getId()); - txn.commit(); - } catch (Exception ex) { - txn.rollback(); - throw new CloudRuntimeException("Error when deleting snapshot"); - } finally { - txn.close(); - txn = Transaction.open(Transaction.CLOUD_DB); - txn.close(); - } - return new Answer(cmd); - } - @Override public CreateVolumeFromSnapshotAnswer CreateVolumeFromSnapshot(CreateVolumeFromSnapshotCommand cmd) { Transaction txn = Transaction.open(Transaction.SIMULATOR_DB); @@ -850,20 +835,21 @@ public class MockStorageManagerImpl extends ManagerBase implements MockStorageMa return new CreateVolumeFromSnapshotAnswer(cmd, true, null, volume.getPath()); } + @Override - public Answer DeleteTemplate(DeleteTemplateCommand cmd) { + public Answer Delete(DeleteCommand cmd) { Transaction txn = Transaction.open(Transaction.SIMULATOR_DB); try { txn.start(); - MockVolumeVO template = _mockVolumeDao.findByStoragePathAndType(cmd.getTemplatePath()); + MockVolumeVO template = _mockVolumeDao.findByStoragePathAndType(cmd.getData().getPath()); if (template == null) { - return new Answer(cmd, false, "can't find template:" + cmd.getTemplatePath()); + return new Answer(cmd, false, "can't find object to delete:" + cmd.getData().getPath()); } _mockVolumeDao.remove(template.getId()); txn.commit(); } catch (Exception ex) { txn.rollback(); - throw new CloudRuntimeException("Error when deleting template"); + throw new CloudRuntimeException("Error when deleting object"); } finally { txn.close(); txn = Transaction.open(Transaction.CLOUD_DB); @@ -872,6 +858,9 @@ public class MockStorageManagerImpl extends ManagerBase implements MockStorageMa return new Answer(cmd); } + + + @Override public Answer SecStorageVMSetup(SecStorageVMSetupCommand cmd) { return new Answer(cmd); diff --git a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java index 1f1f4c53477..c13d37ec4e0 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java +++ b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java @@ -16,6 +16,20 @@ // under the License. package com.cloud.agent.manager; +import java.util.HashMap; +import java.util.Map; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.command.DownloadCommand; +import org.apache.cloudstack.storage.command.DownloadProgressCommand; + import com.cloud.agent.api.Answer; import com.cloud.agent.api.AttachIsoCommand; import com.cloud.agent.api.AttachVolumeCommand; @@ -35,7 +49,6 @@ import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand; import com.cloud.agent.api.CreateStoragePoolCommand; import com.cloud.agent.api.CreateVMSnapshotCommand; import com.cloud.agent.api.CreateVolumeFromSnapshotCommand; -import com.cloud.agent.api.DeleteSnapshotBackupCommand; import com.cloud.agent.api.DeleteStoragePoolCommand; import com.cloud.agent.api.DeleteVMSnapshotCommand; import com.cloud.agent.api.GetDomRVersionCmd; @@ -83,10 +96,7 @@ import com.cloud.agent.api.routing.Site2SiteVpnCfgCommand; import com.cloud.agent.api.routing.VmDataCommand; import com.cloud.agent.api.storage.CopyVolumeCommand; import com.cloud.agent.api.storage.CreateCommand; -import com.cloud.agent.api.storage.DeleteTemplateCommand; import com.cloud.agent.api.storage.DestroyCommand; -import com.cloud.agent.api.storage.DownloadCommand; -import com.cloud.agent.api.storage.DownloadProgressCommand; import com.cloud.agent.api.storage.ListTemplateCommand; import com.cloud.agent.api.storage.ListVolumeCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; @@ -102,14 +112,6 @@ import com.cloud.utils.db.DB; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.VirtualMachine.State; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - -import javax.ejb.Local; -import javax.inject.Inject; -import javax.naming.ConfigurationException; -import java.util.HashMap; -import java.util.Map; @Component @Local(value = { SimulatorManager.class }) @@ -294,12 +296,10 @@ public class SimulatorManagerImpl extends ManagerBase implements SimulatorManage return _mockStorageMgr.ManageSnapshot((ManageSnapshotCommand)cmd); } else if (cmd instanceof BackupSnapshotCommand) { return _mockStorageMgr.BackupSnapshot((BackupSnapshotCommand)cmd, info); - } else if (cmd instanceof DeleteSnapshotBackupCommand) { - return _mockStorageMgr.DeleteSnapshotBackup((DeleteSnapshotBackupCommand)cmd); } else if (cmd instanceof CreateVolumeFromSnapshotCommand) { return _mockStorageMgr.CreateVolumeFromSnapshot((CreateVolumeFromSnapshotCommand)cmd); - } else if (cmd instanceof DeleteTemplateCommand) { - return _mockStorageMgr.DeleteTemplate((DeleteTemplateCommand)cmd); + } else if (cmd instanceof DeleteCommand) { + return _mockStorageMgr.Delete((DeleteCommand)cmd); } else if (cmd instanceof SecStorageVMSetupCommand) { return _mockStorageMgr.SecStorageVMSetup((SecStorageVMSetupCommand)cmd); } else if (cmd instanceof CreatePrivateTemplateFromSnapshotCommand) { diff --git a/plugins/hypervisors/simulator/src/com/cloud/resource/AgentRoutingResource.java b/plugins/hypervisors/simulator/src/com/cloud/resource/AgentRoutingResource.java index 46df50c2133..8a03c4b9598 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/resource/AgentRoutingResource.java +++ b/plugins/hypervisors/simulator/src/com/cloud/resource/AgentRoutingResource.java @@ -51,7 +51,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.Networks.RouterPrivateIpStrategy; import com.cloud.simulator.MockVMVO; import com.cloud.storage.Storage.StorageResourceType; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; import com.cloud.utils.Pair; import com.cloud.vm.VirtualMachine.State; @@ -168,7 +168,7 @@ public class AgentRoutingResource extends AgentStorageResource { } private StartupStorageCommand initializeLocalSR() { - Map tInfo = new HashMap(); + Map tInfo = new HashMap(); StoragePoolInfo poolInfo = _simMgr.getLocalStorage(hostGuid); diff --git a/plugins/hypervisors/simulator/src/com/cloud/resource/AgentStorageResource.java b/plugins/hypervisors/simulator/src/com/cloud/resource/AgentStorageResource.java index a012340d088..3e479aef49a 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/resource/AgentStorageResource.java +++ b/plugins/hypervisors/simulator/src/com/cloud/resource/AgentStorageResource.java @@ -109,7 +109,7 @@ public class AgentStorageResource extends AgentResourceBase implements Secondary } @Override - public String getRootDir(ssCommand cmd) { + public String getRootDir(String url) { // TODO Auto-generated method stub return null; } diff --git a/plugins/hypervisors/simulator/src/com/cloud/resource/SimulatorDiscoverer.java b/plugins/hypervisors/simulator/src/com/cloud/resource/SimulatorDiscoverer.java index 00fe356103b..4f2be7d2d0d 100755 --- a/plugins/hypervisors/simulator/src/com/cloud/resource/SimulatorDiscoverer.java +++ b/plugins/hypervisors/simulator/src/com/cloud/resource/SimulatorDiscoverer.java @@ -44,6 +44,7 @@ import com.cloud.dc.ClusterVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.exception.ConnectionException; import com.cloud.exception.DiscoveryException; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; @@ -51,9 +52,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateZoneVO; import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VMTemplateHostDao; import com.cloud.storage.dao.VMTemplateZoneDao; -import org.springframework.stereotype.Component; @Local(value = Discoverer.class) public class SimulatorDiscoverer extends DiscovererBase implements Discoverer, Listener, ResourceStateAdapter { @@ -62,7 +61,6 @@ public class SimulatorDiscoverer extends DiscovererBase implements Discoverer, L @Inject HostDao _hostDao; @Inject VMTemplateDao _vmTemplateDao; - @Inject VMTemplateHostDao _vmTemplateHostDao; @Inject VMTemplateZoneDao _vmTemplateZoneDao; @Inject ClusterDao _clusterDao; @Inject AgentManager _agentMgr = null; @@ -255,7 +253,7 @@ public class SimulatorDiscoverer extends DiscovererBase implements Discoverer, L } @Override - public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { + public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { /*if(forRebalance) return; diff --git a/plugins/hypervisors/simulator/src/com/cloud/resource/SimulatorSecondaryDiscoverer.java b/plugins/hypervisors/simulator/src/com/cloud/resource/SimulatorSecondaryDiscoverer.java index c121fbac5d9..735bf150224 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/resource/SimulatorSecondaryDiscoverer.java +++ b/plugins/hypervisors/simulator/src/com/cloud/resource/SimulatorSecondaryDiscoverer.java @@ -37,6 +37,7 @@ import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupSecondaryStorageCommand; import com.cloud.agent.manager.MockStorageManager; import com.cloud.exception.ConnectionException; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.storage.SnapshotVO; @@ -113,16 +114,8 @@ public class SimulatorSecondaryDiscoverer extends SecondaryStorageDiscoverer imp @Override public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { - long hostId = host.getId(); - List snapshots = _snapshotDao.listByHostId(hostId); - if (snapshots != null && !snapshots.isEmpty()) { - throw new CloudRuntimeException("Cannot delete this secondary storage because there are still snapshots on it "); - } - _vmTemplateHostDao.deleteByHost(hostId); - host.setGuid(null); - _hostDao.update(hostId, host); - _hostDao.remove(hostId); - return new DeleteHostAnswer(true); + // no need to handle, since secondary storage is no longer a host anymore. + return null; } @Override @@ -157,7 +150,7 @@ public class SimulatorSecondaryDiscoverer extends SecondaryStorageDiscoverer imp } @Override - public void processConnect(HostVO host, StartupCommand cmd, + public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { } diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java index 55bb1e98366..95521e8f83d 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java @@ -28,6 +28,7 @@ import javax.ejb.Local; import javax.inject.Inject; import org.apache.cloudstack.api.ApiConstants.VMDetails; +import org.apache.cloudstack.storage.command.CopyCommand; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -41,6 +42,9 @@ import com.cloud.agent.api.storage.CopyVolumeCommand; import com.cloud.agent.api.storage.CreateVolumeOVACommand; import com.cloud.agent.api.storage.PrepareOVAPackingCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.cluster.ClusterManager; @@ -63,6 +67,7 @@ import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; import com.cloud.secstorage.CommandExecLogDao; import com.cloud.secstorage.CommandExecLogVO; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.GuestOSVO; import com.cloud.storage.dao.GuestOSDao; import com.cloud.storage.secondary.SecondaryStorageVmManager; @@ -286,8 +291,25 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { cmd instanceof CopyVolumeCommand || cmd instanceof CreateVolumeOVACommand || cmd instanceof PrepareOVAPackingCommand || - cmd instanceof CreateVolumeFromSnapshotCommand) { - needDelegation = true; + cmd instanceof CreateVolumeFromSnapshotCommand || + cmd instanceof CopyCommand) { + if (cmd instanceof CopyCommand) { + CopyCommand cpyCommand = (CopyCommand)cmd; + DataTO srcData = cpyCommand.getSrcTO(); + DataStoreTO srcStoreTO = srcData.getDataStore(); + DataTO destData = cpyCommand.getDestTO(); + DataStoreTO destStoreTO = destData.getDataStore(); + + if (destData.getObjectType() == DataObjectType.VOLUME && destStoreTO.getRole() == DataStoreRole.Primary && + srcData.getObjectType() == DataObjectType.TEMPLATE && srcStoreTO.getRole() == DataStoreRole.Primary) { + needDelegation = false; + } else { + needDelegation = true; + } + } else { + needDelegation = true; + } + } /* Fang: remove this before checking in */ // needDelegation = false; diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java index fa873741275..2807da5d887 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java @@ -127,9 +127,9 @@ public class VmwareServerDiscoverer extends DiscovererBase implements public VmwareServerDiscoverer() { s_logger.info("VmwareServerDiscoverer is constructed"); } - + @Override - public Map> find(long dcId, Long podId, Long clusterId, URI url, + public Map> find(long dcId, Long podId, Long clusterId, URI url, String username, String password, List hostTags) throws DiscoveryException { if(s_logger.isInfoEnabled()) @@ -542,7 +542,7 @@ public class VmwareServerDiscoverer extends DiscovererBase implements Long id; if (tmplt == null) { id = _tmpltDao.getNextInSequence(Long.class, "id"); - VMTemplateVO template = new VMTemplateVO(id, isoName, isoName, + VMTemplateVO template = VMTemplateVO.createPreHostIso(id, isoName, isoName, ImageFormat.ISO, true, true, TemplateType.PERHOST, null, null, true, 64, Account.ACCOUNT_ID_SYSTEM, null, "VMware Tools Installer ISO", false, 1, false, @@ -713,7 +713,7 @@ public class VmwareServerDiscoverer extends DiscovererBase implements return VirtualSwitchType.NexusDistributedVirtualSwitch; else if(useDVS) return VirtualSwitchType.VMwareDistributedVirtualSwitch; - else + else return VirtualSwitchType.StandardVirtualSwitch; } diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java index a604392f7a9..68acd9e87ac 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java @@ -36,6 +36,8 @@ 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.DataStoreManager; import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd; import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd; import org.apache.log4j.Logger; @@ -59,10 +61,10 @@ import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.ClusterVSMMapDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.exception.DiscoveredWithErrorException; +import com.cloud.host.Host; import com.cloud.exception.DiscoveryException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.ResourceInUseException; -import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; @@ -113,7 +115,7 @@ import com.cloud.vm.DomainRouterVO; import com.google.gson.Gson; import com.vmware.vim25.AboutInfo; import com.vmware.vim25.HostConnectSpec; -import com.vmware.vim25.ManagedObjectReference; +import com.vmware.vim25.ManagedObjectReference;; @Local(value = {VmwareManager.class, VmwareDatacenterService.class}) @@ -137,6 +139,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw @Inject CommandExecLogDao _cmdExecLogDao; @Inject ClusterManager _clusterMgr; @Inject SecondaryStorageVmManager _ssvmMgr; + @Inject DataStoreManager _dataStoreMgr; @Inject CiscoNexusVSMDeviceDao _nexusDao; @Inject ClusterVSMMapDao _vsmMapDao; @Inject ConfigurationDao _configDao; @@ -446,9 +449,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw @Override public String getSecondaryStorageStoreUrl(long dcId) { - List secStorageHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(dcId); - if(secStorageHosts.size() > 0) - return secStorageHosts.get(0).getStorageUrl(); + DataStore secStore = this._dataStoreMgr.getImageStore(dcId); + if(secStore != null) + return secStore.getUri(); return null; } @@ -517,7 +520,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw _configServer.updateKeyPairs(); s_logger.info("Copy System VM patch ISO file to secondary storage. source ISO: " + srcIso.getAbsolutePath() + - ", destination: " + destIso.getAbsolutePath()); + ", destination: " + destIso.getAbsolutePath()); try { FileUtil.copyfile(srcIso, destIso); } catch(IOException e) { @@ -566,7 +569,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw assert(isoFile != null); if(!isoFile.exists()) { - s_logger.error("Unable to locate systemvm.iso in your setup at " + isoFile.toString()); + s_logger.error("Unable to locate systemvm.iso in your setup at " + isoFile.toString()); } return isoFile; } @@ -583,7 +586,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw } assert(keyFile != null); if(!keyFile.exists()) { - s_logger.error("Unable to locate id_rsa.cloud in your setup at " + keyFile.toString()); + s_logger.error("Unable to locate id_rsa.cloud in your setup at " + keyFile.toString()); } return keyFile; } @@ -731,7 +734,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw } @DB - private void updateClusterNativeHAState(HostVO host, StartupCommand cmd) { + private void updateClusterNativeHAState(Host host, StartupCommand cmd) { ClusterVO cluster = _clusterDao.findById(host.getClusterId()); if(cluster.getClusterType() == ClusterType.ExternalManaged) { if(cmd instanceof StartupRoutingCommand) { @@ -779,7 +782,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw } @Override - public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) { + public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) { if(cmd instanceof StartupCommand) { if(host.getHypervisorType() == HypervisorType.VMware) { updateClusterNativeHAState(host, cmd); diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 1af42390366..c35024c1cf1 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -40,6 +40,11 @@ import java.util.UUID; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.command.StorageSubSystemCommand; +import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.log4j.Logger; import org.apache.log4j.NDC; @@ -179,8 +184,11 @@ import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; import com.cloud.agent.api.storage.ResizeVolumeAnswer; import com.cloud.agent.api.storage.ResizeVolumeCommand; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DiskTO; import com.cloud.agent.api.to.FirewallRuleTO; import com.cloud.agent.api.to.IpAddressTO; +import com.cloud.agent.api.to.NfsTO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.PortForwardingRuleTO; import com.cloud.agent.api.to.StaticNatRuleTO; @@ -194,6 +202,7 @@ import com.cloud.host.Host.Type; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.vmware.manager.VmwareHostService; import com.cloud.hypervisor.vmware.manager.VmwareManager; +import com.cloud.hypervisor.vmware.manager.VmwareStorageMount; import com.cloud.hypervisor.vmware.mo.ClusterMO; import com.cloud.hypervisor.vmware.mo.CustomFieldConstants; import com.cloud.hypervisor.vmware.mo.CustomFieldsManagerMO; @@ -229,8 +238,12 @@ import com.cloud.storage.Volume; import com.cloud.storage.VolumeManager; import com.cloud.storage.VolumeManagerImpl; import com.cloud.storage.resource.StoragePoolResource; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.resource.StorageSubsystemCommandHandler; +import com.cloud.storage.resource.StorageSubsystemCommandHandlerBase; +import com.cloud.storage.resource.VmwareStorageProcessor; +import com.cloud.storage.template.TemplateProp; import com.cloud.utils.DateUtil; +import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; import com.cloud.utils.StringUtils; import com.cloud.utils.component.ComponentContext; @@ -342,6 +355,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa protected volatile long _cmdSequence = 1; + protected StorageSubsystemCommandHandler storageHandler; + protected static HashMap s_statesTable; static { s_statesTable = new HashMap(); @@ -350,6 +365,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa s_statesTable.put(VirtualMachinePowerState.SUSPENDED, State.Stopped); } + public Gson getGson() { + return _gson; + } + public VmwareResource() { _gson = GsonHelper.getGsonLogger(); } @@ -516,6 +535,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa return execute((ResizeVolumeCommand) cmd); } else if (clz == UnregisterVMCommand.class) { return execute((UnregisterVMCommand) cmd); + } else if (cmd instanceof StorageSubSystemCommand) { + return storageHandler.handleStorageCommands((StorageSubSystemCommand)cmd); } else if (clz == ScaleVmCommand.class) { return execute((ScaleVmCommand) cmd); } else if (clz == PvlanSetupCommand.class) { @@ -1429,7 +1450,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa if(!isVMWareToolsInstalled(vmMo)){ String errMsg = "vmware tools is not installed or not running, cannot add nic to vm " + vmName; s_logger.debug(errMsg); - return new PlugNicAnswer(cmd, false, "Unable to execute PlugNicCommand due to " + errMsg); + return new PlugNicAnswer(cmd, false, "Unable to execute PlugNicCommand due to " + errMsg); } // TODO need a way to specify the control of NIC device type @@ -1542,7 +1563,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME); - int ethDeviceNum = this.findRouterEthDeviceIndex(domrName, routerIp, ip.getVifMacAddress()); + int ethDeviceNum = findRouterEthDeviceIndex(domrName, routerIp, ip.getVifMacAddress()); if (ethDeviceNum < 0) { if (ip.isAdd()) { throw new InternalErrorException("Failed to find DomR VIF to associate/disassociate IP with."); @@ -1709,8 +1730,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa vSwitchType = _publicTrafficInfo.getVirtualSwitchType(); } if (VirtualSwitchType.StandardVirtualSwitch == vSwitchType) { - networkInfo = HypervisorHostHelper.prepareNetwork(this._publicTrafficInfo.getVirtualSwitchName(), "cloud.public", - vmMo.getRunningHost(), vlanId, null, null, this._ops_timeout, true); + networkInfo = HypervisorHostHelper.prepareNetwork(_publicTrafficInfo.getVirtualSwitchName(), "cloud.public", + vmMo.getRunningHost(), vlanId, null, null, _ops_timeout, true); } else { networkInfo = HypervisorHostHelper.prepareNetwork(this._publicTrafficInfo.getVirtualSwitchName(), "cloud.public", vmMo.getRunningHost(), vlanId, null, null, null, this._ops_timeout, vSwitchType, _portsPerDvPortGroup, null, false); @@ -1898,11 +1919,11 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa args += " -6 " + cmd.getVmIp6Address(); args += " -u " + cmd.getDuid(); } - + if (!cmd.isDefault()) { args += " -N"; } - + if (s_logger.isDebugEnabled()) { s_logger.debug("Run command on domR " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + ", /root/edithosts.sh " + args); } @@ -2304,14 +2325,21 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa return new CheckSshAnswer(cmd); } - private VolumeTO[] validateDisks(VolumeTO[] disks) { - List validatedDisks = new ArrayList(); + private DiskTO[] validateDisks(DiskTO[] disks) { + List validatedDisks = new ArrayList(); - for (VolumeTO vol : disks) { - if (vol.getPoolUuid() != null && !vol.getPoolUuid().isEmpty()) { - validatedDisks.add(vol); - } else if (vol.getPoolType() == StoragePoolType.ISO && (vol.getPath() != null && !vol.getPath().isEmpty())) { - validatedDisks.add(vol); + for (DiskTO vol : disks) { + if (vol.getType() != Volume.Type.ISO) { + VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore(); + if (primaryStore.getUuid() != null && !primaryStore.getUuid().isEmpty()) { + validatedDisks.add(vol); + } + } else if (vol.getType() == Volume.Type.ISO) { + TemplateObjectTO templateTO = (TemplateObjectTO)vol.getData(); + if (templateTO.getPath() != null && !templateTO.getPath().isEmpty()) { + validatedDisks.add(vol); + } } else { if (s_logger.isDebugEnabled()) { s_logger.debug("Drop invalid disk option, volumeTO: " + _gson.toJson(vol)); @@ -2319,7 +2347,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } - return validatedDisks.toArray(new VolumeTO[0]); + return validatedDisks.toArray(new DiskTO[0]); } protected ScaleVmAnswer execute(ScaleVmCommand cmd) { @@ -2368,7 +2396,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa s_logger.debug("VM " + vmName + " will be started with NIC device type: " + nicDeviceType); VmwareHypervisorHost hyperHost = getHyperHost(context); - VolumeTO[] disks = validateDisks(vmSpec.getDisks()); + DiskTO[] disks = validateDisks(vmSpec.getDisks()); assert (disks.length > 0); NicTO[] nics = vmSpec.getNics(); @@ -2405,9 +2433,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } else { int ramMb = (int) (vmSpec.getMinRam() / (1024 * 1024)); Pair rootDiskDataStoreDetails = null; - for (VolumeTO vol : disks) { + for (DiskTO vol : disks) { if (vol.getType() == Volume.Type.ROOT) { - rootDiskDataStoreDetails = dataStoresDetails.get(vol.getPoolUuid()); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)vol.getData().getDataStore(); + rootDiskDataStoreDetails = dataStoresDetails.get(primaryStore.getUuid()); } } @@ -2426,12 +2455,12 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } int totalChangeDevices = disks.length + nics.length; - VolumeTO volIso = null; + DiskTO volIso = null; if (vmSpec.getType() != VirtualMachine.Type.User) { // system VM needs a patch ISO totalChangeDevices++; } else { - for (VolumeTO vol : disks) { + for (DiskTO vol : disks) { if (vol.getType() == Volume.Type.ISO) { volIso = vol; break; @@ -2455,12 +2484,12 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa s_logger.debug("Nested Virtualization enabled in configuration, checking hypervisor capability"); ManagedObjectReference hostMor = vmMo.getRunningHost().getMor(); ManagedObjectReference computeMor = context.getVimClient().getMoRefProp(hostMor, "parent"); - ManagedObjectReference environmentBrowser = + ManagedObjectReference environmentBrowser = context.getVimClient().getMoRefProp(computeMor, "environmentBrowser"); HostCapability hostCapability = context.getService().queryTargetCapabilities(environmentBrowser, hostMor); if (hostCapability.isNestedHVSupported()) { s_logger.debug("Hypervisor supports nested virtualization, enabling for VM " + vmSpec.getName()); - vmConfigSpec.setNestedHVEnabled(true); + vmConfigSpec.setNestedHVEnabled(true); } else { s_logger.warn("Hypervisor doesn't support nested virtualization, unable to set config for VM " +vmSpec.getName()); @@ -2510,23 +2539,35 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } else { // we will always plugin a CDROM device - if (volIso != null && volIso.getPath() != null && !volIso.getPath().isEmpty()) { - Pair isoDatastoreInfo = getIsoDatastoreInfo(hyperHost, volIso.getPath()); - assert (isoDatastoreInfo != null); - assert (isoDatastoreInfo.second() != null); - deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec(); + if (volIso != null) { + TemplateObjectTO iso = (TemplateObjectTO)volIso.getData(); + + if (iso.getPath() != null && !iso.getPath().isEmpty()) { + DataStoreTO imageStore = iso.getDataStore(); + if (!(imageStore instanceof NfsTO)) { + s_logger.debug("unsupported protocol"); + throw new Exception("unsupported protocol"); + } + NfsTO nfsImageStore = (NfsTO)imageStore; + String isoPath = nfsImageStore.getUrl() + File.separator + iso.getPath(); + Pair isoDatastoreInfo = getIsoDatastoreInfo(hyperHost, isoPath); + assert (isoDatastoreInfo != null); + assert (isoDatastoreInfo.second() != null); + + deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec(); Pair isoInfo = VmwareHelper.prepareIsoDevice(vmMo, isoDatastoreInfo.first(), isoDatastoreInfo.second(), true, true, ideUnitNumber++, i + 1); - deviceConfigSpecArray[i].setDevice(isoInfo.first()); - if (isoInfo.second()) { - if(s_logger.isDebugEnabled()) - s_logger.debug("Prepare ISO volume at new device " + _gson.toJson(isoInfo.first())); - deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD); - } else { - if(s_logger.isDebugEnabled()) - s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first())); - deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.EDIT); - } + deviceConfigSpecArray[i].setDevice(isoInfo.first()); + if (isoInfo.second()) { + if(s_logger.isDebugEnabled()) + s_logger.debug("Prepare ISO volume at new device " + _gson.toJson(isoInfo.first())); + deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD); + } else { + if(s_logger.isDebugEnabled()) + s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first())); + deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.EDIT); + } + } } else { deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec(); Pair isoInfo = VmwareHelper.prepareIsoDevice(vmMo, null, null, true, true, ideUnitNumber++, i + 1); @@ -2545,7 +2586,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } i++; - for (VolumeTO vol : sortVolumesByDeviceId(disks)) { + for (DiskTO vol : sortVolumesByDeviceId(disks)) { deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec(); if (vol.getType() == Volume.Type.ISO) { @@ -2568,19 +2609,19 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } if (vol.getType() != Volume.Type.ISO) { - Pair volumeDsDetails = dataStoresDetails.get(vol.getPoolUuid()); + VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore(); + Pair volumeDsDetails = dataStoresDetails.get(primaryStore.getUuid()); assert (volumeDsDetails != null); VirtualDevice device; - - datastoreDiskPath = volumeDsDetails.second().searchFileInSubFolders(vol.getPath() + ".vmdk", true); - - String chainInfo = vol.getChainInfo(); + datastoreDiskPath = String.format("[%s] %s.vmdk", volumeDsDetails.second().getName(), volumeTO.getPath()); + String chainInfo = volumeTO.getChainInfo(); if (chainInfo != null && !chainInfo.isEmpty()) { String[] diskChain = _gson.fromJson(chainInfo, String[].class); if (diskChain == null || diskChain.length < 1) { s_logger.warn("Empty previously-saved chain info, fall back to the original"); - device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, new String[] { datastoreDiskPath }, volumeDsDetails.first(), + device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, new String[] { datastoreDiskPath }, volumeDsDetails.first(), (controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1); } else { s_logger.info("Attach the disk with stored chain info: " + chainInfo); @@ -2588,7 +2629,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa diskChain[j] = String.format("[%s] %s", volumeDsDetails.second().getName(), diskChain[j]); } - device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, diskChain, volumeDsDetails.first(), + device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, diskChain, volumeDsDetails.first(), (controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1); } } else { @@ -2752,19 +2793,19 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa return listForSort.toArray(new NicTO[0]); } - private VolumeTO[] sortVolumesByDeviceId(VolumeTO[] volumes) { + private DiskTO[] sortVolumesByDeviceId(DiskTO[] volumes) { - List listForSort = new ArrayList(); - for (VolumeTO vol : volumes) { + List listForSort = new ArrayList(); + for (DiskTO vol : volumes) { listForSort.add(vol); } - Collections.sort(listForSort, new Comparator() { + Collections.sort(listForSort, new Comparator() { @Override - public int compare(VolumeTO arg0, VolumeTO arg1) { - if (arg0.getDeviceId() < arg1.getDeviceId()) { + public int compare(DiskTO arg0, DiskTO arg1) { + if (arg0.getDiskSeq() < arg1.getDiskSeq()) { return -1; - } else if (arg0.getDeviceId() == arg1.getDeviceId()) { + } else if (arg0.getDiskSeq() == arg1.getDiskSeq()) { return 0; } @@ -2772,16 +2813,18 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } }); - return listForSort.toArray(new VolumeTO[0]); + return listForSort.toArray(new DiskTO[0]); } - private HashMap> inferDatastoreDetailsFromDiskInfo(VmwareHypervisorHost hyperHost, VmwareContext context, VolumeTO[] disks) throws Exception { + private HashMap> inferDatastoreDetailsFromDiskInfo(VmwareHypervisorHost hyperHost, VmwareContext context, DiskTO[] disks) throws Exception { HashMap> poolMors = new HashMap>(); assert (hyperHost != null) && (context != null); - for (VolumeTO vol : disks) { + for (DiskTO vol : disks) { if (vol.getType() != Volume.Type.ISO) { - String poolUuid = vol.getPoolUuid(); + VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore(); + String poolUuid = primaryStore.getUuid(); if(poolMors.get(poolUuid) == null) { ManagedObjectReference morDataStore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, poolUuid); if (morDataStore == null) { @@ -2789,7 +2832,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa s_logger.error(msg); throw new Exception(msg); } - poolMors.put(vol.getPoolUuid(), new Pair (morDataStore, new DatastoreMO(context, morDataStore))); + poolMors.put(poolUuid, new Pair (morDataStore, new DatastoreMO(context, morDataStore))); } } } @@ -2887,13 +2930,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } if (nicTo.getType() == Networks.TrafficType.Guest) { - return new Pair(this._guestTrafficInfo.getVirtualSwitchName(), Vlan.UNTAGGED); + return new Pair(_guestTrafficInfo.getVirtualSwitchName(), Vlan.UNTAGGED); } else if (nicTo.getType() == Networks.TrafficType.Control || nicTo.getType() == Networks.TrafficType.Management) { - return new Pair(this._privateNetworkVSwitchName, Vlan.UNTAGGED); + return new Pair(_privateNetworkVSwitchName, Vlan.UNTAGGED); } else if (nicTo.getType() == Networks.TrafficType.Public) { - return new Pair(this._publicTrafficInfo.getVirtualSwitchName(), Vlan.UNTAGGED); + return new Pair(_publicTrafficInfo.getVirtualSwitchName(), Vlan.UNTAGGED); } else if (nicTo.getType() == Networks.TrafficType.Storage) { - return new Pair(this._privateNetworkVSwitchName, Vlan.UNTAGGED); + return new Pair(_privateNetworkVSwitchName, Vlan.UNTAGGED); } else if (nicTo.getType() == Networks.TrafficType.Vpn) { throw new Exception("Unsupported traffic type: " + nicTo.getType().toString()); } else { @@ -3580,7 +3623,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } state = State.Stopping; - List volumeToList = null; + List volumeToList = null; return new MigrateWithStorageAnswer(cmd, volumeToList); } catch (Throwable e) { if (e instanceof RemoteException) { @@ -3731,7 +3774,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa DatastoreSummary summary = new DatastoreMO(getServiceContext(), morDatastore).getSummary(); long capacity = summary.getCapacity(); long available = summary.getFreeSpace(); - Map tInfo = new HashMap(); + Map tInfo = new HashMap(); ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, capacity, available, tInfo); return answer; } catch (Throwable e) { @@ -3901,7 +3944,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } - private synchronized ManagedObjectReference prepareSecondaryDatastoreOnHost(String storeUrl) throws Exception { + public synchronized ManagedObjectReference prepareSecondaryDatastoreOnHost(String storeUrl) throws Exception { String storeName = getSecondaryDatastoreUUID(storeUrl); URI uri = new URI(storeUrl); @@ -4310,14 +4353,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } - @Override - public Answer execute(DestroyCommand cmd) { + public Answer execute(DeleteCommand cmd) { if (s_logger.isInfoEnabled()) { s_logger.info("Executing resource DestroyCommand: " + _gson.toJson(cmd)); } /* - * DestroyCommand content example + * DestroyCommand content exafmple * * {"volume": {"id":5,"name":"Volume1", "mountPoint":"/export/home/kelven/vmware-test/primary", * "path":"6bb8762f-c34c-453c-8e03-26cc246ceec4", "size":0,"type":"DATADISK","resourceType": @@ -4331,11 +4373,12 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa try { VmwareContext context = getServiceContext(); VmwareHypervisorHost hyperHost = getHyperHost(context); - VolumeTO vol = cmd.getVolume(); + VolumeObjectTO vol = (VolumeObjectTO)cmd.getData(); + PrimaryDataStoreTO store = (PrimaryDataStoreTO)vol.getDataStore(); - ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, vol.getPoolUuid()); + ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, store.getUuid()); if (morDs == null) { - String msg = "Unable to find datastore based on volume mount point " + cmd.getVolume().getMountPoint(); + String msg = "Unable to find datastore based on volume mount point " + store.getPath(); s_logger.error(msg); throw new Exception(msg); } @@ -4346,8 +4389,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa ManagedObjectReference morCluster = hyperHost.getHyperHostCluster(); ClusterMO clusterMo = new ClusterMO(context, morCluster); - if (cmd.getVolume().getType() == Volume.Type.ROOT) { - String vmName = cmd.getVmName(); + if (vol.getVolumeType() == Volume.Type.ROOT) { + String vmName = vol.getVmName(); if (vmName != null) { VirtualMachineMO vmMo = clusterMo.findVmOnHyperHost(vmName); if (vmMo != null) { @@ -4374,20 +4417,20 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } if (s_logger.isInfoEnabled()) - s_logger.info("Destroy volume by original name: " + cmd.getVolume().getPath() + ".vmdk"); - dsMo.deleteFile(cmd.getVolume().getPath() + ".vmdk", morDc, true); + s_logger.info("Destroy volume by original name: " + vol.getPath() + ".vmdk"); + dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true); // root volume may be created via linked-clone, delete the delta disk as well if (_fullCloneFlag) { if (s_logger.isInfoEnabled()) { - s_logger.info("Destroy volume by derived name: " + cmd.getVolume().getPath() + "-flat.vmdk"); + s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk"); } - dsMo.deleteFile(cmd.getVolume().getPath() + "-flat.vmdk", morDc, true); + dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true); } else { if (s_logger.isInfoEnabled()) { - s_logger.info("Destroy volume by derived name: " + cmd.getVolume().getPath() + "-delta.vmdk"); + s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-delta.vmdk"); } - dsMo.deleteFile(cmd.getVolume().getPath() + "-delta.vmdk", morDc, true); + dsMo.deleteFile(vol.getPath() + "-delta.vmdk", morDc, true); } return new Answer(cmd, true, "Success"); } @@ -4397,17 +4440,17 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } else { // evitTemplate will be converted into DestroyCommand, test if we are running in this case - VirtualMachineMO vmMo = clusterMo.findVmOnHyperHost(cmd.getVolume().getPath()); + VirtualMachineMO vmMo = clusterMo.findVmOnHyperHost(vol.getPath()); if (vmMo != null) { if (s_logger.isInfoEnabled()) - s_logger.info("Destroy template volume " + cmd.getVolume().getPath()); + s_logger.info("Destroy template volume " + vol.getPath()); vmMo.destroy(); return new Answer(cmd, true, "Success"); } } - String chainInfo = cmd.getVolume().getChainInfo(); + String chainInfo = vol.getChainInfo(); if (chainInfo != null && !chainInfo.isEmpty()) { s_logger.info("Destroy volume by chain info: " + chainInfo); String[] diskChain = _gson.fromJson(chainInfo, String[].class); @@ -4423,23 +4466,23 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa if (s_logger.isInfoEnabled()) { s_logger.info("Empty disk chain info, fall back to try to delete by original backing file name"); } - dsMo.deleteFile(cmd.getVolume().getPath() + ".vmdk", morDc, true); + dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true); if (s_logger.isInfoEnabled()) { - s_logger.info("Destroy volume by derived name: " + cmd.getVolume().getPath() + "-flat.vmdk"); + s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk"); } - dsMo.deleteFile(cmd.getVolume().getPath() + "-flat.vmdk", morDc, true); + dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true); } } else { if (s_logger.isInfoEnabled()) { - s_logger.info("Destroy volume by original name: " + cmd.getVolume().getPath() + ".vmdk"); + s_logger.info("Destroy volume by original name: " + vol.getPath() + ".vmdk"); } - dsMo.deleteFile(cmd.getVolume().getPath() + ".vmdk", morDc, true); + dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true); if (s_logger.isInfoEnabled()) { - s_logger.info("Destroy volume by derived name: " + cmd.getVolume().getPath() + "-flat.vmdk"); + s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk"); } - dsMo.deleteFile(cmd.getVolume().getPath() + "-flat.vmdk", morDc, true); + dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true); } return new Answer(cmd, true, "Success"); @@ -4455,7 +4498,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } - private void cleanupNetwork(HostMO hostMo, NetworkDetails netDetails) { + public void cleanupNetwork(HostMO hostMo, NetworkDetails netDetails) { // we will no longer cleanup VLAN networks in order to support native VMware HA /* * assert(netDetails.getName() != null); try { synchronized(this) { NetworkMO networkMo = new @@ -5247,8 +5290,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa if(!"untagged".equalsIgnoreCase(tokens[2])) vlanId = tokens[2]; - HypervisorHostHelper.prepareNetwork(this._privateNetworkVSwitchName, "cloud.private", - hostMo, vlanId, networkRateMbps, null, this._ops_timeout, false); + HypervisorHostHelper.prepareNetwork(_privateNetworkVSwitchName, "cloud.private", + hostMo, vlanId, networkRateMbps, null, _ops_timeout, false); } else { s_logger.info("Skip suspecious cloud network " + networkName); } @@ -5264,7 +5307,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa vlanId = tokens[2]; HypervisorHostHelper.prepareNetwork(_publicTrafficInfo.getVirtualSwitchName(), "cloud.public", - hostMo, vlanId, networkRateMbps, null, this._ops_timeout, false); + hostMo, vlanId, networkRateMbps, null, _ops_timeout, false); } else { s_logger.info("Skip suspecious cloud network " + networkName); } @@ -5281,7 +5324,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa vlanId = tokens[2]; HypervisorHostHelper.prepareNetwork(_guestTrafficInfo.getVirtualSwitchName(), "cloud.guest", - hostMo, vlanId, networkRateMbps, null, this._ops_timeout, false); + hostMo, vlanId, networkRateMbps, null, _ops_timeout, false); } else { s_logger.info("Skip suspecious cloud network " + networkName); } @@ -5538,7 +5581,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa return s_statesTable.get(powerState); } - private static State getVmState(VirtualMachineMO vmMo) throws Exception { + public static State getVmState(VirtualMachineMO vmMo) throws Exception { VirtualMachineRuntimeInfo runtimeInfo = vmMo.getRuntimeInfo(); return convertState(runtimeInfo.getPowerState()); } @@ -5663,9 +5706,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa s_logger.info("VmwareResource network configuration info." + " private traffic over vSwitch: " + _privateNetworkVSwitchName + ", public traffic over " + - this._publicTrafficInfo.getVirtualSwitchType() + " : " + this._publicTrafficInfo.getVirtualSwitchName() + - ", guest traffic over " + this._guestTrafficInfo.getVirtualSwitchType() + " : " + - this._guestTrafficInfo.getVirtualSwitchName()); + _publicTrafficInfo.getVirtualSwitchType() + " : " + _publicTrafficInfo.getVirtualSwitchName() + + ", guest traffic over " + _guestTrafficInfo.getVirtualSwitchType() + " : " + + _guestTrafficInfo.getVirtualSwitchName()); value = params.get("vmware.create.full.clone").toString(); if (value != null && value.equalsIgnoreCase("true")) { @@ -5673,6 +5716,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } else { _fullCloneFlag = false; } + value = (String)params.get("scripts.timeout"); + int timeout = NumbersUtil.parseInt(value, 1440) * 1000; + VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME); + VmwareStorageProcessor storageProcessor = new VmwareStorageProcessor((VmwareHostService)this, _fullCloneFlag, (VmwareStorageMount)mgr, + timeout, this, _shutdown_waitMs + ); + storageHandler = new StorageSubsystemCommandHandlerBase(storageProcessor); return true; } @@ -5692,15 +5742,15 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa return true; } - private VmwareContext getServiceContext() { + public VmwareContext getServiceContext() { return getServiceContext(null); } - private void invalidateServiceContext() { + public void invalidateServiceContext() { invalidateServiceContext(null); } - private VmwareHypervisorHost getHyperHost(VmwareContext context) { + public VmwareHypervisorHost getHyperHost(VmwareContext context) { return getHyperHost(context, null); } @@ -5798,8 +5848,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } + @Override + public Answer execute(DestroyCommand cmd) { + // TODO Auto-generated method stub + return null; + } private boolean isVMWareToolsInstalled(VirtualMachineMO vmMo) throws Exception{ GuestInfo guestInfo = vmMo.getVmGuestInfo(); return (guestInfo != null && guestInfo.getGuestState() != null && guestInfo.getGuestState().equalsIgnoreCase("running")); - } + } } diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java index 95ba317fa2c..22ba59f36ca 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java +++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java @@ -18,6 +18,7 @@ package com.cloud.storage.resource; import java.util.List; +import org.apache.cloudstack.storage.command.StorageSubSystemCommand; import org.apache.cloudstack.storage.resource.SecondaryStorageResourceHandler; import org.apache.log4j.Logger; @@ -48,57 +49,65 @@ import com.cloud.utils.Pair; import com.google.gson.Gson; import com.vmware.vim25.ManagedObjectReference; -public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageResourceHandler, VmwareHostService, VmwareStorageMount { +public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageResourceHandler, VmwareHostService, + VmwareStorageMount { private static final Logger s_logger = Logger.getLogger(VmwareSecondaryStorageResourceHandler.class); private final PremiumSecondaryStorageResource _resource; private final VmwareStorageManager _storageMgr; private final Gson _gson; + private final StorageSubsystemCommandHandler storageSubsystemHandler; /* - private Map _activeHosts = new HashMap(); + * private Map _activeHosts = new HashMap(); */ public VmwareSecondaryStorageResourceHandler(PremiumSecondaryStorageResource resource) { _resource = resource; _storageMgr = new VmwareStorageManagerImpl(this); _gson = GsonHelper.getGsonLogger(); + + VmwareStorageProcessor storageProcessor = new VmwareStorageProcessor(this, true, this, resource.getTimeout(), + null, null); + storageSubsystemHandler = new StorageSubsystemCommandHandlerBase(storageProcessor); } @Override public Answer executeRequest(Command cmd) { Answer answer; if (cmd instanceof PrimaryStorageDownloadCommand) { - answer = execute((PrimaryStorageDownloadCommand)cmd); - } else if(cmd instanceof BackupSnapshotCommand) { - answer = execute((BackupSnapshotCommand)cmd); - } else if(cmd instanceof CreatePrivateTemplateFromVolumeCommand) { - answer = execute((CreatePrivateTemplateFromVolumeCommand)cmd); - } else if(cmd instanceof CreatePrivateTemplateFromSnapshotCommand) { - answer = execute((CreatePrivateTemplateFromSnapshotCommand)cmd); - } else if(cmd instanceof CopyVolumeCommand) { - answer = execute((CopyVolumeCommand)cmd); - } else if(cmd instanceof CreateVolumeOVACommand) { - answer = execute((CreateVolumeOVACommand)cmd); + answer = execute((PrimaryStorageDownloadCommand) cmd); + } else if (cmd instanceof BackupSnapshotCommand) { + answer = execute((BackupSnapshotCommand) cmd); + } else if (cmd instanceof CreatePrivateTemplateFromVolumeCommand) { + answer = execute((CreatePrivateTemplateFromVolumeCommand) cmd); + } else if (cmd instanceof CreatePrivateTemplateFromSnapshotCommand) { + answer = execute((CreatePrivateTemplateFromSnapshotCommand) cmd); + } else if (cmd instanceof CopyVolumeCommand) { + answer = execute((CopyVolumeCommand) cmd); + } else if (cmd instanceof CreateVolumeOVACommand) { + answer = execute((CreateVolumeOVACommand) cmd); } else if (cmd instanceof PrepareOVAPackingCommand) { - answer = execute((PrepareOVAPackingCommand)cmd); - } else if(cmd instanceof CreateVolumeFromSnapshotCommand) { - answer = execute((CreateVolumeFromSnapshotCommand)cmd); + answer = execute((PrepareOVAPackingCommand) cmd); + } else if (cmd instanceof CreateVolumeFromSnapshotCommand) { + answer = execute((CreateVolumeFromSnapshotCommand) cmd); + } else if (cmd instanceof StorageSubSystemCommand) { + answer = storageSubsystemHandler.handleStorageCommands((StorageSubSystemCommand) cmd); } else { - answer = _resource.defaultAction(cmd); + answer = _resource.defaultAction(cmd); } // special handling to pass-back context info for cleanups - if(cmd.getContextParam("execid") != null) { + if (cmd.getContextParam("execid") != null) { answer.setContextParam("execid", cmd.getContextParam("execid")); } - if(cmd.getContextParam("checkpoint") != null) { + if (cmd.getContextParam("checkpoint") != null) { answer.setContextParam("checkpoint", cmd.getContextParam("checkpoint")); } - if(cmd.getContextParam("checkpoint2") != null) { + if (cmd.getContextParam("checkpoint2") != null) { answer.setContextParam("checkpoint2", cmd.getContextParam("checkpoint2")); } @@ -173,13 +182,13 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe @Override public VmwareContext getServiceContext(Command cmd) { String guid = cmd.getContextParam("guid"); - if(guid == null || guid.isEmpty()) { + if (guid == null || guid.isEmpty()) { s_logger.error("Invalid command context parameter guid"); return null; } String username = cmd.getContextParam("username"); - if(username == null || username.isEmpty()) { + if (username == null || username.isEmpty()) { s_logger.error("Invalid command context parameter username"); return null; } @@ -188,14 +197,14 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe // validate command guid parameter String[] tokens = guid.split("@"); - if(tokens == null || tokens.length != 2) { + if (tokens == null || tokens.length != 2) { s_logger.error("Invalid content in command context parameter guid"); return null; } String vCenterAddress = tokens[1]; String[] hostTokens = tokens[0].split(":"); - if(hostTokens == null || hostTokens.length != 2) { + if (hostTokens == null || hostTokens.length != 2) { s_logger.error("Invalid content in command context parameter guid"); return null; } @@ -204,20 +213,21 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe _resource.ensureOutgoingRuleForAddress(vCenterAddress); VmwareContext context = null; - // cached VmwareContext may be timed out in vCenter, give it a chance to reclaim a new context from factory - for(int i = 0; i < 2; i++) { + // cached VmwareContext may be timed out in vCenter, give it a + // chance to reclaim a new context from factory + for (int i = 0; i < 2; i++) { context = VmwareSecondaryStorageContextFactory.create(vCenterAddress, username, password); - if(!validateContext(context, cmd)) { + if (!validateContext(context, cmd)) { invalidateServiceContext(context); } } - if(context != null) { + if (context != null) { context.registerStockObject("serviceconsole", cmd.getContextParam("serviceconsole")); context.registerStockObject("manageportgroup", cmd.getContextParam("manageportgroup")); } return context; - } catch(Exception e) { + } catch (Exception e) { s_logger.error("Unexpected exception " + e.toString(), e); return null; } @@ -231,14 +241,14 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe @Override public VmwareHypervisorHost getHyperHost(VmwareContext context, Command cmd) { String guid = cmd.getContextParam("guid"); - assert(guid != null); + assert (guid != null); String[] tokens = guid.split("@"); - assert(tokens != null && tokens.length == 2); + assert (tokens != null && tokens.length == 2); ManagedObjectReference morHyperHost = new ManagedObjectReference(); String[] hostTokens = tokens[0].split(":"); - if(hostTokens == null || hostTokens.length != 2) { + if (hostTokens == null || hostTokens.length != 2) { s_logger.error("Invalid content in command context parameter guid"); return null; } @@ -246,40 +256,42 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe morHyperHost.setType(hostTokens[0]); morHyperHost.setValue(hostTokens[1]); - if(morHyperHost.getType().equalsIgnoreCase("HostSystem")) { - HostMO hostMo = new HostMO(context, morHyperHost); + if (morHyperHost.getType().equalsIgnoreCase("HostSystem")) { + HostMO hostMo = new HostMO(context, morHyperHost); try { ManagedObjectReference mor = hostMo.getHyperHostCluster(); ClusterMO clusterMo = new ClusterMO(hostMo.getContext(), mor); List> hostsInCluster = clusterMo.getClusterHosts(); - for(Pair hostPair : hostsInCluster) { + for (Pair hostPair : hostsInCluster) { HostMO hostIteratorMo = new HostMO(hostMo.getContext(), hostPair.first()); - VmwareHypervisorHostNetworkSummary netSummary = hostIteratorMo.getHyperHostNetworkSummary( - hostIteratorMo.getHostType() == VmwareHostType.ESXi ? cmd.getContextParam("manageportgroup") : cmd.getContextParam("serviceconsole")); + VmwareHypervisorHostNetworkSummary netSummary = hostIteratorMo + .getHyperHostNetworkSummary(hostIteratorMo.getHostType() == VmwareHostType.ESXi ? cmd + .getContextParam("manageportgroup") : cmd.getContextParam("serviceconsole")); _resource.ensureOutgoingRuleForAddress(netSummary.getHostIp()); s_logger.info("Setup firewall rule for host: " + netSummary.getHostIp()); } - } catch(Throwable e) { - s_logger.warn("Unable to retrive host network information due to exception " + e.toString() + ", host: " + hostTokens[0] + "-" + hostTokens[1]); + } catch (Throwable e) { + s_logger.warn("Unable to retrive host network information due to exception " + e.toString() + + ", host: " + hostTokens[0] + "-" + hostTokens[1]); } return hostMo; } - assert(false); + assert (false); return new ClusterMO(context, morHyperHost); } @Override public String getWorkerName(VmwareContext context, Command cmd, int workerSequence) { - assert(cmd.getContextParam("worker") != null); - assert(workerSequence < 2); + assert (cmd.getContextParam("worker") != null); + assert (workerSequence < 2); - if(workerSequence == 0) + if (workerSequence == 0) return cmd.getContextParam("worker"); return cmd.getContextParam("worker2"); } @@ -291,40 +303,42 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe private boolean validateContext(VmwareContext context, Command cmd) { String guid = cmd.getContextParam("guid"); - assert(guid != null); + assert (guid != null); String[] tokens = guid.split("@"); - assert(tokens != null && tokens.length == 2); + assert (tokens != null && tokens.length == 2); ManagedObjectReference morHyperHost = new ManagedObjectReference(); String[] hostTokens = tokens[0].split(":"); - assert(hostTokens.length == 2); + assert (hostTokens.length == 2); morHyperHost.setType(hostTokens[0]); morHyperHost.setValue(hostTokens[1]); - if(morHyperHost.getType().equalsIgnoreCase("HostSystem")) { - HostMO hostMo = new HostMO(context, morHyperHost); + if (morHyperHost.getType().equalsIgnoreCase("HostSystem")) { + HostMO hostMo = new HostMO(context, morHyperHost); try { - VmwareHypervisorHostNetworkSummary netSummary = hostMo.getHyperHostNetworkSummary( - hostMo.getHostType() == VmwareHostType.ESXi ? cmd.getContextParam("manageportgroup") : cmd.getContextParam("serviceconsole")); - assert(netSummary != null); - if(netSummary.getHostIp() != null && !netSummary.getHostIp().isEmpty()) { - if(s_logger.isDebugEnabled()) { - s_logger.debug("Context validation succeeded. Validated via host: " + netSummary.getHostIp() + ", guid: " + guid); + VmwareHypervisorHostNetworkSummary netSummary = hostMo + .getHyperHostNetworkSummary(hostMo.getHostType() == VmwareHostType.ESXi ? cmd + .getContextParam("manageportgroup") : cmd.getContextParam("serviceconsole")); + assert (netSummary != null); + if (netSummary.getHostIp() != null && !netSummary.getHostIp().isEmpty()) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Context validation succeeded. Validated via host: " + netSummary.getHostIp() + + ", guid: " + guid); } return true; } s_logger.warn("Context validation failed due to invalid host network summary"); return false; - } catch(Throwable e) { + } catch (Throwable e) { s_logger.warn("Context validation failed due to " + VmwareHelper.getExceptionMessage(e)); return false; } } - assert(false); + assert (false); return true; } } diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java new file mode 100644 index 00000000000..d3df0f59ce9 --- /dev/null +++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java @@ -0,0 +1,1288 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.storage.resource; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; +import java.net.URI; +import java.rmi.RemoteException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.cloudstack.storage.command.AttachAnswer; +import org.apache.cloudstack.storage.command.AttachCommand; +import org.apache.cloudstack.storage.command.CopyCmdAnswer; +import org.apache.cloudstack.storage.command.CopyCommand; +import org.apache.cloudstack.storage.command.CreateObjectAnswer; +import org.apache.cloudstack.storage.command.CreateObjectCommand; +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.command.DettachCommand; +import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; +import org.apache.cloudstack.storage.to.SnapshotObjectTO; +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.BackupSnapshotAnswer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.CreateVolumeFromSnapshotAnswer; +import com.cloud.agent.api.ManageSnapshotAnswer; +import com.cloud.agent.api.ManageSnapshotCommand; +import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer; +import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.DiskTO; +import com.cloud.agent.api.to.NfsTO; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.hypervisor.vmware.manager.VmwareHostService; +import com.cloud.hypervisor.vmware.manager.VmwareStorageMount; +import com.cloud.hypervisor.vmware.mo.ClusterMO; +import com.cloud.hypervisor.vmware.mo.CustomFieldConstants; +import com.cloud.hypervisor.vmware.mo.DatacenterMO; +import com.cloud.hypervisor.vmware.mo.DatastoreMO; +import com.cloud.hypervisor.vmware.mo.HostMO; +import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper; +import com.cloud.hypervisor.vmware.mo.NetworkDetails; +import com.cloud.hypervisor.vmware.mo.VirtualMachineMO; +import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost; +import com.cloud.hypervisor.vmware.resource.VmwareResource; +import com.cloud.hypervisor.vmware.util.VmwareContext; +import com.cloud.hypervisor.vmware.util.VmwareHelper; +import com.cloud.serializer.GsonHelper; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.JavaStorageLayer; +import com.cloud.storage.StorageLayer; +import com.cloud.storage.Volume; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.template.VmdkProcessor; +import com.cloud.utils.Pair; +import com.cloud.utils.StringUtils; +import com.cloud.utils.Ternary; +import com.cloud.utils.script.Script; +import com.cloud.vm.VirtualMachine.State; +import com.google.gson.Gson; +import com.vmware.vim25.ManagedObjectReference; +import com.vmware.vim25.VirtualDeviceConfigSpec; +import com.vmware.vim25.VirtualDeviceConfigSpecOperation; +import com.vmware.vim25.VirtualDisk; +import com.vmware.vim25.VirtualEthernetCard; +import com.vmware.vim25.VirtualLsiLogicController; +import com.vmware.vim25.VirtualMachineConfigSpec; +import com.vmware.vim25.VirtualMachineFileInfo; +import com.vmware.vim25.VirtualMachineGuestOsIdentifier; +import com.vmware.vim25.VirtualSCSISharing; + +public class VmwareStorageProcessor implements StorageProcessor { + private static final Logger s_logger = Logger.getLogger(VmwareStorageProcessor.class); + private VmwareHostService hostService; + private boolean _fullCloneFlag; + private VmwareStorageMount mountService; + private VmwareResource resource; + private Integer _timeout; + protected Integer _shutdown_waitMs; + private final Gson _gson; + private final StorageLayer _storage = new JavaStorageLayer(); + public VmwareStorageProcessor(VmwareHostService hostService, boolean fullCloneFlag, VmwareStorageMount mountService, + Integer timeout, + VmwareResource resource, + Integer shutdownWaitMs) { + this.hostService = hostService; + this._fullCloneFlag = fullCloneFlag; + this.mountService = mountService; + this._timeout = timeout; + this.resource = resource; + this._shutdown_waitMs = shutdownWaitMs; + _gson = GsonHelper.getGsonLogger(); + } + + private String getOVFFilePath(String srcOVAFileName) { + File file = new File(srcOVAFileName); + assert(_storage != null); + String[] files = _storage.listFiles(file.getParent()); + if(files != null) { + for(String fileName : files) { + if(fileName.toLowerCase().endsWith(".ovf")) { + File ovfFile = new File(fileName); + return file.getParent() + File.separator + ovfFile.getName(); + } + } + } + return null; + } + private void copyTemplateFromSecondaryToPrimary(VmwareHypervisorHost hyperHost, DatastoreMO datastoreMo, String secondaryStorageUrl, + String templatePathAtSecondaryStorage, String templateName, String templateUuid) throws Exception { + + s_logger.info("Executing copyTemplateFromSecondaryToPrimary. secondaryStorage: " + + secondaryStorageUrl + ", templatePathAtSecondaryStorage: " + templatePathAtSecondaryStorage + + ", templateName: " + templateName); + + String secondaryMountPoint = mountService.getMountPoint(secondaryStorageUrl); + s_logger.info("Secondary storage mount point: " + secondaryMountPoint); + + String srcOVAFileName = secondaryMountPoint + "/" + templatePathAtSecondaryStorage + + templateName + "." + ImageFormat.OVA.getFileExtension(); + + String srcFileName = getOVFFilePath(srcOVAFileName); + if(srcFileName == null) { + Script command = new Script("tar", 0, s_logger); + command.add("--no-same-owner"); + command.add("-xf", srcOVAFileName); + command.setWorkDir(secondaryMountPoint + "/" + templatePathAtSecondaryStorage); + s_logger.info("Executing command: " + command.toString()); + String result = command.execute(); + if(result != null) { + String msg = "Unable to unpack snapshot OVA file at: " + srcOVAFileName; + s_logger.error(msg); + throw new Exception(msg); + } + } + + srcFileName = getOVFFilePath(srcOVAFileName); + if(srcFileName == null) { + String msg = "Unable to locate OVF file in template package directory: " + srcOVAFileName; + s_logger.error(msg); + throw new Exception(msg); + } + + String vmName = templateUuid; + hyperHost.importVmFromOVF(srcFileName, vmName, datastoreMo, "thin"); + + VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName); + if(vmMo == null) { + String msg = "Failed to import OVA template. secondaryStorage: " + + secondaryStorageUrl + ", templatePathAtSecondaryStorage: " + templatePathAtSecondaryStorage + + ", templateName: " + templateName + ", templateUuid: " + templateUuid; + s_logger.error(msg); + throw new Exception(msg); + } + + if(vmMo.createSnapshot("cloud.template.base", "Base snapshot", false, false)) { + vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_UUID, templateUuid); + vmMo.markAsTemplate(); + } else { + vmMo.destroy(); + String msg = "Unable to create base snapshot for template, templateName: " + templateName + ", templateUuid: " + templateUuid; + s_logger.error(msg); + throw new Exception(msg); + } + } + + @Override + public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) { + DataTO srcData = cmd.getSrcTO(); + TemplateObjectTO template = (TemplateObjectTO)srcData; + DataStoreTO srcStore = srcData.getDataStore(); + if (!(srcStore instanceof NfsTO)) { + return new CopyCmdAnswer("unsupported protocol"); + } + NfsTO nfsImageStore = (NfsTO)srcStore; + DataTO destData = cmd.getDestTO(); + DataStoreTO destStore = destData.getDataStore(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)destStore; + String secondaryStorageUrl = nfsImageStore.getUrl(); + assert (secondaryStorageUrl != null); + + String templateUrl = secondaryStorageUrl + File.separator + srcData.getPath(); + + String templateName = null; + String mountPoint = null; + if (templateUrl.endsWith(".ova")) { + int index = templateUrl.lastIndexOf("/"); + mountPoint = templateUrl.substring(0, index); + mountPoint = mountPoint.substring(secondaryStorageUrl.length() + 1); + if (!mountPoint.endsWith("/")) { + mountPoint = mountPoint + "/"; + } + + templateName = templateUrl.substring(index + 1).replace("." + ImageFormat.OVA.getFileExtension(), ""); + + if (templateName == null || templateName.isEmpty()) { + templateName = template.getName(); + } + } else { + mountPoint = templateUrl.substring(secondaryStorageUrl.length() + 1); + if (!mountPoint.endsWith("/")) { + mountPoint = mountPoint + "/"; + } + templateName = template.getName(); + } + + VmwareContext context = hostService.getServiceContext(cmd); + try { + VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd); + + String templateUuidName = UUID.nameUUIDFromBytes((templateName + "@" + primaryStore.getUuid() + "-" + hyperHost.getMor().getValue()).getBytes()).toString(); + // truncate template name to 32 chars to ensure they work well with vSphere API's. + templateUuidName = templateUuidName.replace("-", ""); + + DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter()); + VirtualMachineMO templateMo = VmwareHelper.pickOneVmOnRunningHost(dcMo.findVmByNameAndLabel(templateUuidName), true); + + if (templateMo == null) { + if(s_logger.isInfoEnabled()) + s_logger.info("Template " + templateName + " is not setup yet, setup template from secondary storage with uuid name: " + templateUuidName); + ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid()); + assert (morDs != null); + DatastoreMO primaryStorageDatastoreMo = new DatastoreMO(context, morDs); + + copyTemplateFromSecondaryToPrimary(hyperHost, + primaryStorageDatastoreMo, secondaryStorageUrl, + mountPoint, templateName, templateUuidName); + } else { + s_logger.info("Template " + templateName + " has already been setup, skip the template setup process in primary storage"); + } + + TemplateObjectTO newTemplate = new TemplateObjectTO(); + newTemplate.setPath(templateUuidName); + return new CopyCmdAnswer(newTemplate); + } catch (Throwable e) { + if (e instanceof RemoteException) { + hostService.invalidateServiceContext(context); + } + + String msg = "Unable to execute PrimaryStorageDownloadCommand due to exception"; + s_logger.error(msg, e); + return new CopyCmdAnswer(msg); + } + } + private boolean createVMLinkedClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo, + String vmdkName, ManagedObjectReference morDatastore, ManagedObjectReference morPool) throws Exception { + + ManagedObjectReference morBaseSnapshot = vmTemplate.getSnapshotMor("cloud.template.base"); + if (morBaseSnapshot == null) { + String msg = "Unable to find template base snapshot, invalid template"; + s_logger.error(msg); + throw new Exception(msg); + } + + if(dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmdkName)) + dsMo.deleteFile(String.format("[%s] %s/", dsMo.getName(), vmdkName), dcMo.getMor(), false); + + s_logger.info("creating linked clone from template"); + if (!vmTemplate.createLinkedClone(vmdkName, morBaseSnapshot, dcMo.getVmFolder(), morPool, morDatastore)) { + String msg = "Unable to clone from the template"; + s_logger.error(msg); + throw new Exception(msg); + } + + // we can't rely on un-offical API (VirtualMachineMO.moveAllVmDiskFiles() any more, use hard-coded disk names that we know + // to move files + s_logger.info("Move volume out of volume-wrapper VM "); + dsMo.moveDatastoreFile(String.format("[%s] %s/%s.vmdk", dsMo.getName(), vmdkName, vmdkName), + dcMo.getMor(), dsMo.getMor(), + String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true); + + dsMo.moveDatastoreFile(String.format("[%s] %s/%s-delta.vmdk", dsMo.getName(), vmdkName, vmdkName), + dcMo.getMor(), dsMo.getMor(), + String.format("[%s] %s-delta.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true); + + return true; + } + + private boolean createVMFullClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo, + String vmdkName, ManagedObjectReference morDatastore, ManagedObjectReference morPool) throws Exception { + + if(dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmdkName)) + dsMo.deleteFile(String.format("[%s] %s/", dsMo.getName(), vmdkName), dcMo.getMor(), false); + + s_logger.info("creating full clone from template"); + if (!vmTemplate.createFullClone(vmdkName, dcMo.getVmFolder(), morPool, morDatastore)) { + String msg = "Unable to create full clone from the template"; + s_logger.error(msg); + throw new Exception(msg); + } + + // we can't rely on un-offical API (VirtualMachineMO.moveAllVmDiskFiles() any more, use hard-coded disk names that we know + // to move files + s_logger.info("Move volume out of volume-wrapper VM "); + dsMo.moveDatastoreFile(String.format("[%s] %s/%s.vmdk", dsMo.getName(), vmdkName, vmdkName), + dcMo.getMor(), dsMo.getMor(), + String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true); + + dsMo.moveDatastoreFile(String.format("[%s] %s/%s-flat.vmdk", dsMo.getName(), vmdkName, vmdkName), + dcMo.getMor(), dsMo.getMor(), + String.format("[%s] %s-flat.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true); + + return true; + } + + @Override + public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd) { + DataTO srcData = cmd.getSrcTO(); + TemplateObjectTO template = (TemplateObjectTO)srcData; + DataTO destData = cmd.getDestTO(); + VolumeObjectTO volume = (VolumeObjectTO)destData; + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore(); + PrimaryDataStoreTO srcStore = (PrimaryDataStoreTO)template.getDataStore(); + + + try { + VmwareContext context = this.hostService.getServiceContext(null); + VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(context, null); + DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter()); + VirtualMachineMO vmMo = null; + ManagedObjectReference morDatastore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid()); + if (morDatastore == null) + throw new Exception("Unable to find datastore in vSphere"); + + DatastoreMO dsMo = new DatastoreMO(context, morDatastore); + + + // attach volume id to make the name unique + String vmdkName = volume.getName() + "-" + volume.getId(); + if (srcStore == null) { + // create a root volume for blank VM + String dummyVmName = this.hostService.getWorkerName(context, cmd, 0); + + try { + vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName); + if (vmMo == null) { + throw new Exception("Unable to create a dummy VM for volume creation"); + } + + String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName); + synchronized (this) { + s_logger.info("Delete file if exists in datastore to clear the way for creating the volume. file: " + volumeDatastorePath); + VmwareHelper.deleteVolumeVmdkFiles(dsMo, vmdkName, dcMo); + vmMo.createDisk(volumeDatastorePath, (int) (volume.getSize() / (1024L * 1024L)), morDatastore, -1); + vmMo.detachDisk(volumeDatastorePath, false); + } + + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(vmdkName); + return new CopyCmdAnswer(newVol); + } finally { + vmMo.detachAllDisks(); + + s_logger.info("Destroy dummy VM after volume creation"); + vmMo.destroy(); + } + } else { + String templatePath = template.getPath(); + VirtualMachineMO vmTemplate = VmwareHelper.pickOneVmOnRunningHost(dcMo.findVmByNameAndLabel(templatePath), true); + if (vmTemplate == null) { + s_logger.warn("Template host in vSphere is not in connected state, request template reload"); + return new CopyCmdAnswer("Template host in vSphere is not in connected state, request template reload"); + } + + ManagedObjectReference morPool = hyperHost.getHyperHostOwnerResourcePool(); + ManagedObjectReference morCluster = hyperHost.getHyperHostCluster(); + //createVMLinkedClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool); + if (!_fullCloneFlag) { + createVMLinkedClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool); + } else { + createVMFullClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool); + } + + vmMo = new ClusterMO(context, morCluster).findVmOnHyperHost(vmdkName); + assert (vmMo != null); + + s_logger.info("detach disks from volume-wrapper VM " + vmdkName); + vmMo.detachAllDisks(); + + s_logger.info("destroy volume-wrapper VM " + vmdkName); + vmMo.destroy(); + + String srcFile = String.format("[%s] %s/", dsMo.getName(), vmdkName); + dsMo.deleteFile(srcFile, dcMo.getMor(), true); + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(vmdkName); + return new CopyCmdAnswer(newVol); + } + } catch (Throwable e) { + if (e instanceof RemoteException) { + s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context"); + this.hostService.invalidateServiceContext(null); + } + + String msg = "CreateCommand failed due to " + VmwareHelper.getExceptionMessage(e); + s_logger.error(msg, e); + return new CopyCmdAnswer(e.toString()); + } + } + + + @Override + public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) { + // TODO Auto-generated method stub + return null; + } + + private void postCreatePrivateTemplate(String installFullPath, long templateId, + String templateName, long size, long virtualSize) throws Exception { + + // TODO a bit ugly here + BufferedWriter out = null; + try { + out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(installFullPath + "/template.properties"))); + out.write("filename=" + templateName + ".ova"); + out.newLine(); + out.write("description="); + out.newLine(); + out.write("checksum="); + out.newLine(); + out.write("hvm=false"); + out.newLine(); + out.write("size=" + size); + out.newLine(); + out.write("ova=true"); + out.newLine(); + out.write("id=" + templateId); + out.newLine(); + out.write("public=false"); + out.newLine(); + out.write("ova.filename=" + templateName + ".ova"); + out.newLine(); + out.write("uniquename=" + templateName); + out.newLine(); + out.write("ova.virtualsize=" + virtualSize); + out.newLine(); + out.write("virtualsize=" + virtualSize); + out.newLine(); + out.write("ova.size=" + size); + out.newLine(); + } finally { + if(out != null) + out.close(); + } + } + + private Ternary createTemplateFromVolume(VirtualMachineMO vmMo, String installPath, long templateId, String templateUniqueName, + String secStorageUrl, String volumePath, String workerVmName) throws Exception { + + String secondaryMountPoint = mountService.getMountPoint(secStorageUrl); + String installFullPath = secondaryMountPoint + "/" + installPath; + synchronized(installPath.intern()) { + Script command = new Script(false, "mkdir", _timeout, s_logger); + command.add("-p"); + command.add(installFullPath); + + String result = command.execute(); + if(result != null) { + String msg = "unable to prepare template directory: " + + installPath + ", storage: " + secStorageUrl + ", error msg: " + result; + s_logger.error(msg); + throw new Exception(msg); + } + } + + VirtualMachineMO clonedVm = null; + try { + Pair volumeDeviceInfo = vmMo.getDiskDevice(volumePath, false); + if(volumeDeviceInfo == null) { + String msg = "Unable to find related disk device for volume. volume path: " + volumePath; + s_logger.error(msg); + throw new Exception(msg); + } + + if(!vmMo.createSnapshot(templateUniqueName, "Temporary snapshot for template creation", false, false)) { + String msg = "Unable to take snapshot for creating template from volume. volume path: " + volumePath; + s_logger.error(msg); + throw new Exception(msg); + } + + // 4 MB is the minimum requirement for VM memory in VMware + vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(), + VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first())); + clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName); + if(clonedVm == null) { + String msg = "Unable to create dummy VM to export volume. volume path: " + volumePath; + s_logger.error(msg); + throw new Exception(msg); + } + + clonedVm.exportVm(secondaryMountPoint + "/" + installPath, templateUniqueName, true, false); + + long physicalSize = new File(installFullPath + "/" + templateUniqueName + ".ova").length(); + VmdkProcessor processor = new VmdkProcessor(); + Map params = new HashMap(); + params.put(StorageLayer.InstanceConfigKey, _storage); + processor.configure("VMDK Processor", params); + long virtualSize = processor.getTemplateVirtualSize(installFullPath, templateUniqueName); + + postCreatePrivateTemplate(installFullPath, templateId, templateUniqueName, physicalSize, virtualSize); + return new Ternary(installPath + "/" + templateUniqueName + ".ova", physicalSize, virtualSize); + + } finally { + if(clonedVm != null) { + clonedVm.detachAllDisks(); + clonedVm.destroy(); + } + + vmMo.removeSnapshot(templateUniqueName, false); + } + } + + @Override + public Answer createTemplateFromVolume(CopyCommand cmd) { + VolumeObjectTO volume = (VolumeObjectTO)cmd.getSrcTO(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore(); + TemplateObjectTO template = (TemplateObjectTO)cmd.getDestTO(); + DataStoreTO imageStore = template.getDataStore(); + + if (!(imageStore instanceof NfsTO)) { + return new CopyCmdAnswer("unsupported protocol"); + } + NfsTO nfsImageStore = (NfsTO)imageStore; + String secondaryStoragePoolURL = nfsImageStore.getUrl(); + String volumePath = volume.getPath(); + + String details = null; + + VmwareContext context = hostService.getServiceContext(cmd); + try { + VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd); + + VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(volume.getVmName()); + if (vmMo == null) { + if(s_logger.isDebugEnabled()) + s_logger.debug("Unable to find the owner VM for CreatePrivateTemplateFromVolumeCommand on host " + hyperHost.getHyperHostName() + ", try within datacenter"); + vmMo = hyperHost.findVmOnPeerHyperHost(volume.getVmName()); + + if(vmMo == null) { + String msg = "Unable to find the owner VM for volume operation. vm: " + volume.getVmName(); + s_logger.error(msg); + throw new Exception(msg); + } + } + + Ternary result = createTemplateFromVolume(vmMo, + template.getPath(), template.getId(), template.getName(), + secondaryStoragePoolURL, volumePath, + hostService.getWorkerName(context, cmd, 0)); + + TemplateObjectTO newTemplate = new TemplateObjectTO(); + newTemplate.setPath(template.getName()); + newTemplate.setFormat(ImageFormat.OVA); + newTemplate.setSize(result.third()); + return new CopyCmdAnswer(newTemplate); + + } catch (Throwable e) { + if (e instanceof RemoteException) { + hostService.invalidateServiceContext(context); + } + + s_logger.error("Unexpecpted exception ", e); + + details = "CreatePrivateTemplateFromVolumeCommand exception: " + StringUtils.getExceptionStackInfo(e); + return new CopyCmdAnswer(details); + } + } + + private void exportVolumeToSecondaryStroage(VirtualMachineMO vmMo, String volumePath, + String secStorageUrl, String secStorageDir, String exportName, + String workerVmName) throws Exception { + + String secondaryMountPoint = mountService.getMountPoint(secStorageUrl); + String exportPath = secondaryMountPoint + "/" + secStorageDir + "/" + exportName; + + synchronized(exportPath.intern()) { + if(!new File(exportPath).exists()) { + Script command = new Script(false, "mkdir", _timeout, s_logger); + command.add("-p"); + command.add(exportPath); + if(command.execute() != null) + throw new Exception("unable to prepare snapshot backup directory"); + } + } + + VirtualMachineMO clonedVm = null; + try { + + Pair volumeDeviceInfo = vmMo.getDiskDevice(volumePath, false); + if(volumeDeviceInfo == null) { + String msg = "Unable to find related disk device for volume. volume path: " + volumePath; + s_logger.error(msg); + throw new Exception(msg); + } + + // 4 MB is the minimum requirement for VM memory in VMware + vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(), + VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first())); + clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName); + if(clonedVm == null) { + String msg = "Unable to create dummy VM to export volume. volume path: " + volumePath; + s_logger.error(msg); + throw new Exception(msg); + } + + clonedVm.exportVm(exportPath, exportName, true, true); + } finally { + if(clonedVm != null) { + clonedVm.detachAllDisks(); + clonedVm.destroy(); + } + } + } + + + private String backupSnapshotToSecondaryStorage(VirtualMachineMO vmMo, String installPath, + String volumePath, String snapshotUuid, String secStorageUrl, + String prevSnapshotUuid, String prevBackupUuid, String workerVmName) throws Exception { + + String backupUuid = UUID.randomUUID().toString(); + exportVolumeToSecondaryStroage(vmMo, volumePath, secStorageUrl, + installPath, backupUuid, workerVmName); + return backupUuid + "/" + backupUuid; + } + @Override + public Answer backupSnasphot(CopyCommand cmd) { + SnapshotObjectTO srcSnapshot = (SnapshotObjectTO)cmd.getSrcTO(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)srcSnapshot.getDataStore(); + SnapshotObjectTO destSnapshot = (SnapshotObjectTO)cmd.getDestTO(); + DataStoreTO destStore = destSnapshot.getDataStore(); + if (!(destStore instanceof NfsTO)) { + return new CopyCmdAnswer("unsupported protocol"); + } + + NfsTO destNfsStore = (NfsTO)destStore; + + + String secondaryStorageUrl = destNfsStore.getUrl(); + String snapshotUuid = srcSnapshot.getPath(); + String prevSnapshotUuid = srcSnapshot.getParentSnapshotPath(); + String prevBackupUuid = destSnapshot.getParentSnapshotPath(); + VirtualMachineMO workerVm=null; + String workerVMName = null; + String volumePath = srcSnapshot.getVolume().getPath(); + ManagedObjectReference morDs = null; + DatastoreMO dsMo=null; + + // By default assume failure + String details = null; + boolean success = false; + String snapshotBackupUuid = null; + + VmwareContext context = hostService.getServiceContext(cmd); + VirtualMachineMO vmMo = null; + String vmName = srcSnapshot.getVmName(); + try { + VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd); + morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid()); + + try { + vmMo = hyperHost.findVmOnHyperHost(vmName); + if (vmMo == null) { + if(s_logger.isDebugEnabled()) + s_logger.debug("Unable to find owner VM for BackupSnapshotCommand on host " + hyperHost.getHyperHostName() + ", will try within datacenter"); + + vmMo = hyperHost.findVmOnPeerHyperHost(vmName); + if(vmMo == null) { + dsMo = new DatastoreMO(hyperHost.getContext(), morDs); + + workerVMName = hostService.getWorkerName(context, cmd, 0); + + // attach a volume to dummay wrapper VM for taking snapshot and exporting the VM for backup + if (!hyperHost.createBlankVm(workerVMName, 1, 512, 0, false, 4, 0, VirtualMachineGuestOsIdentifier.OTHER_GUEST.value(), morDs, false)) { + String msg = "Unable to create worker VM to execute BackupSnapshotCommand"; + s_logger.error(msg); + throw new Exception(msg); + } + vmMo = hyperHost.findVmOnHyperHost(workerVMName); + if (vmMo == null) { + throw new Exception("Failed to find the newly create or relocated VM. vmName: " + workerVMName); + } + workerVm = vmMo; + + // attach volume to worker VM + String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumePath); + vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs); + } + } + + if (!vmMo.createSnapshot(snapshotUuid, "Snapshot taken for " + srcSnapshot.getName(), false, false)) { + throw new Exception("Failed to take snapshot " + srcSnapshot.getName() + " on vm: " + vmName); + } + + snapshotBackupUuid = backupSnapshotToSecondaryStorage(vmMo, destSnapshot.getPath(), srcSnapshot.getVolume().getPath(), snapshotUuid, secondaryStorageUrl, prevSnapshotUuid, prevBackupUuid, + hostService.getWorkerName(context, cmd, 1)); + + success = (snapshotBackupUuid != null); + if (success) { + details = "Successfully backedUp the snapshotUuid: " + snapshotUuid + " to secondary storage."; + return new CopyCmdAnswer(details); + } else { + SnapshotObjectTO newSnapshot = new SnapshotObjectTO(); + newSnapshot.setPath(snapshotBackupUuid); + return new CopyCmdAnswer(newSnapshot); + } + } finally { + if(vmMo != null){ + ManagedObjectReference snapshotMor = vmMo.getSnapshotMor(snapshotUuid); + if (snapshotMor != null){ + vmMo.removeSnapshot(snapshotUuid, false); + } + } + + try { + if (workerVm != null) { + // detach volume and destroy worker vm + workerVm.detachAllDisks(); + workerVm.destroy(); + } + } catch (Throwable e) { + s_logger.warn("Failed to destroy worker VM: " + workerVMName); + } + } + } catch (Throwable e) { + if (e instanceof RemoteException) { + hostService.invalidateServiceContext(context); + } + + s_logger.error("Unexpecpted exception ", e); + + details = "BackupSnapshotCommand exception: " + StringUtils.getExceptionStackInfo(e); + return new CopyCmdAnswer(details); + } + } + + @Override + public Answer attachIso(AttachCommand cmd) { + return this.attachIso(cmd.getDisk(), true, cmd.getVmName()); + } + + @Override + public Answer attachVolume(AttachCommand cmd) { + return this.attachVolume(cmd, cmd.getDisk(), true, cmd.getVmName()); + } + + private Answer attachVolume(Command cmd, DiskTO disk, boolean isAttach, String vmName) { + + VolumeObjectTO volumeTO = (VolumeObjectTO)disk.getData(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore(); + try { + VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(this.hostService.getServiceContext(null), null); + VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName); + if (vmMo == null) { + String msg = "Unable to find the VM to execute AttachVolumeCommand, vmName: " + vmName; + s_logger.error(msg); + throw new Exception(msg); + } + + ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid()); + if (morDs == null) { + String msg = "Unable to find the mounted datastore to execute AttachVolumeCommand, vmName: " + vmName; + s_logger.error(msg); + throw new Exception(msg); + } + + DatastoreMO dsMo = new DatastoreMO(this.hostService.getServiceContext(null), morDs); + String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeTO.getPath()); + + AttachAnswer answer = new AttachAnswer(disk); + if (isAttach) { + vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs); + } else { + vmMo.removeAllSnapshots(); + vmMo.detachDisk(datastoreVolumePath, false); + } + + return answer; + } catch (Throwable e) { + if (e instanceof RemoteException) { + s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context"); + this.hostService.invalidateServiceContext(null); + } + + String msg = "AttachVolumeCommand failed due to " + VmwareHelper.getExceptionMessage(e); + s_logger.error(msg, e); + return new AttachAnswer(msg); + } + } + + private static String getSecondaryDatastoreUUID(String storeUrl) { + return UUID.nameUUIDFromBytes(storeUrl.getBytes()).toString(); + } + + public synchronized ManagedObjectReference prepareSecondaryDatastoreOnHost(String storeUrl) throws Exception { + String storeName = getSecondaryDatastoreUUID(storeUrl); + URI uri = new URI(storeUrl); + + VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(this.hostService.getServiceContext(null), null); + ManagedObjectReference morDatastore = hyperHost.mountDatastore(false, uri.getHost(), 0, uri.getPath(), storeName.replace("-", "")); + + if (morDatastore == null) + throw new Exception("Unable to mount secondary storage on host. storeUrl: " + storeUrl); + + return morDatastore; + } + private Answer attachIso(DiskTO disk, boolean isAttach, String vmName) { + + + try { + VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(this.hostService.getServiceContext(null), null); + VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName); + if (vmMo == null) { + String msg = "Unable to find VM in vSphere to execute AttachIsoCommand, vmName: " + vmName; + s_logger.error(msg); + throw new Exception(msg); + } + TemplateObjectTO iso = (TemplateObjectTO)disk.getData(); + NfsTO nfsImageStore = (NfsTO)iso.getDataStore(); + String storeUrl = nfsImageStore.getUrl(); + if (storeUrl == null) { + if (!iso.getName().equalsIgnoreCase("vmware-tools.iso")) { + String msg = "ISO store root url is not found in AttachIsoCommand"; + s_logger.error(msg); + throw new Exception(msg); + } else { + if (isAttach) { + vmMo.mountToolsInstaller(); + } else { + try{ + vmMo.unmountToolsInstaller(); + }catch(Throwable e){ + vmMo.detachIso(null); + } + } + + return new AttachAnswer(disk); + } + } + + ManagedObjectReference morSecondaryDs = prepareSecondaryDatastoreOnHost(storeUrl); + String isoPath = nfsImageStore.getUrl() + File.separator + iso.getPath(); + if (!isoPath.startsWith(storeUrl)) { + assert (false); + String msg = "ISO path does not start with the secondary storage root"; + s_logger.error(msg); + throw new Exception(msg); + } + + int isoNameStartPos = isoPath.lastIndexOf('/'); + String isoFileName = isoPath.substring(isoNameStartPos + 1); + String isoStorePathFromRoot = isoPath.substring(storeUrl.length(), isoNameStartPos); + + // TODO, check if iso is already attached, or if there is a previous + // attachment + DatastoreMO secondaryDsMo = new DatastoreMO(this.hostService.getServiceContext(null), morSecondaryDs); + String storeName = secondaryDsMo.getName(); + String isoDatastorePath = String.format("[%s] %s%s", storeName, isoStorePathFromRoot, isoFileName); + + if (isAttach) { + vmMo.attachIso(isoDatastorePath, morSecondaryDs, true, false); + } else { + vmMo.detachIso(isoDatastorePath); + } + + return new AttachAnswer(disk); + } catch (Throwable e) { + if (e instanceof RemoteException) { + s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context"); + this.hostService.invalidateServiceContext(null); + } + + if(isAttach) { + String msg = "AttachIsoCommand(attach) failed due to " + VmwareHelper.getExceptionMessage(e); + s_logger.error(msg, e); + return new AttachAnswer(msg); + } else { + String msg = "AttachIsoCommand(detach) failed due to " + VmwareHelper.getExceptionMessage(e); + s_logger.warn(msg, e); + return new AttachAnswer(msg); + } + } + } + @Override + public Answer dettachIso(DettachCommand cmd) { + return this.attachIso(cmd.getDisk(), false, cmd.getVmName()); + } + + @Override + public Answer dettachVolume(DettachCommand cmd) { + return this.attachVolume(cmd, cmd.getDisk(), false, cmd.getVmName()); + } + + protected VirtualMachineMO prepareVolumeHostDummyVm(VmwareHypervisorHost hyperHost, DatastoreMO dsMo, String vmName) throws Exception { + assert (hyperHost != null); + + VirtualMachineMO vmMo = null; + VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec(); + vmConfig.setName(vmName); + vmConfig.setMemoryMB((long) 4); // vmware request minimum of 4 MB + vmConfig.setNumCPUs(1); + vmConfig.setGuestId(VirtualMachineGuestOsIdentifier.OTHER_GUEST.value()); + VirtualMachineFileInfo fileInfo = new VirtualMachineFileInfo(); + fileInfo.setVmPathName(String.format("[%s]", dsMo.getName())); + vmConfig.setFiles(fileInfo); + + // Scsi controller + VirtualLsiLogicController scsiController = new VirtualLsiLogicController(); + scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING); + scsiController.setBusNumber(0); + scsiController.setKey(1); + VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec(); + scsiControllerSpec.setDevice(scsiController); + scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD); + + vmConfig.getDeviceChange().add(scsiControllerSpec ); + hyperHost.createVm(vmConfig); + vmMo = hyperHost.findVmOnHyperHost(vmName); + return vmMo; + } + @Override + public Answer createVolume(CreateObjectCommand cmd) { + + VolumeObjectTO volume = (VolumeObjectTO)cmd.getData(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore(); + + try { + VmwareContext context = this.hostService.getServiceContext(null); + VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(context, null); + DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter()); + + ManagedObjectReference morDatastore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid()); + if (morDatastore == null) + throw new Exception("Unable to find datastore in vSphere"); + + DatastoreMO dsMo = new DatastoreMO(context, morDatastore); + // create data volume + VirtualMachineMO vmMo = null; + String volumeUuid = UUID.randomUUID().toString().replace("-", ""); + String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeUuid); + String dummyVmName = this.hostService.getWorkerName(context, cmd, 0); + try { + vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName); + if (vmMo == null) { + throw new Exception("Unable to create a dummy VM for volume creation"); + } + + synchronized (this) { + // s_logger.info("Delete file if exists in datastore to clear the way for creating the volume. file: " + volumeDatastorePath); + VmwareHelper.deleteVolumeVmdkFiles(dsMo, volumeUuid.toString(), dcMo); + + vmMo.createDisk(volumeDatastorePath, (int) (volume.getSize() / (1024L * 1024L)), morDatastore, vmMo.getScsiDeviceControllerKey()); + vmMo.detachDisk(volumeDatastorePath, false); + } + + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(volumeUuid); + newVol.setSize(volume.getSize() / (1024L * 1024L)); + return new CreateObjectAnswer(newVol); + } finally { + s_logger.info("Destroy dummy VM after volume creation"); + vmMo.detachAllDisks(); + vmMo.destroy(); + } + + } catch (Throwable e) { + if (e instanceof RemoteException) { + s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context"); + this.hostService.invalidateServiceContext(null); + } + + String msg = "CreateCommand failed due to " + VmwareHelper.getExceptionMessage(e); + s_logger.error(msg, e); + return new CreateObjectAnswer(e.toString()); + } + } + + @Override + public Answer createSnapshot(CreateObjectCommand cmd) { + // snapshot operation (create or destroy) is handled inside BackupSnapshotCommand(), we just fake + // a success return here + String snapshotUUID = UUID.randomUUID().toString(); + SnapshotObjectTO newSnapshot = new SnapshotObjectTO(); + newSnapshot.setPath(snapshotUUID); + return new CreateObjectAnswer(newSnapshot); + } + + @Override + public Answer deleteVolume(DeleteCommand cmd) { + if (s_logger.isInfoEnabled()) { + s_logger.info("Executing resource DestroyCommand: " + _gson.toJson(cmd)); + } + + /* + * DestroyCommand content example + * + * {"volume": {"id":5,"name":"Volume1", "mountPoint":"/export/home/kelven/vmware-test/primary", + * "path":"6bb8762f-c34c-453c-8e03-26cc246ceec4", "size":0,"type":"DATADISK","resourceType": + * "STORAGE_POOL","storagePoolType":"NetworkFilesystem", "poolId":0,"deviceId":0 } } + * + * {"volume": {"id":1, "name":"i-2-1-KY-ROOT", "mountPoint":"/export/home/kelven/vmware-test/primary", + * "path":"i-2-1-KY-ROOT","size":0,"type":"ROOT", "resourceType":"STORAGE_POOL", "storagePoolType":"NetworkFilesystem", + * "poolId":0,"deviceId":0 } } + */ + + try { + VmwareContext context = this.hostService.getServiceContext(null); + VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(context, null); + VolumeObjectTO vol = (VolumeObjectTO)cmd.getData(); + PrimaryDataStoreTO store = (PrimaryDataStoreTO)vol.getDataStore(); + + ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, store.getUuid()); + if (morDs == null) { + String msg = "Unable to find datastore based on volume mount point " + store.getPath(); + s_logger.error(msg); + throw new Exception(msg); + } + + DatastoreMO dsMo = new DatastoreMO(context, morDs); + + ManagedObjectReference morDc = hyperHost.getHyperHostDatacenter(); + ManagedObjectReference morCluster = hyperHost.getHyperHostCluster(); + ClusterMO clusterMo = new ClusterMO(context, morCluster); + + if (vol.getVolumeType() == Volume.Type.ROOT) { + String vmName = vol.getVmName(); + if (vmName != null) { + VirtualMachineMO vmMo = clusterMo.findVmOnHyperHost(vmName); + if (vmMo != null) { + if (s_logger.isInfoEnabled()) { + s_logger.info("Destroy root volume and VM itself. vmName " + vmName); + } + + HostMO hostMo = vmMo.getRunningHost(); + List networks = vmMo.getNetworksWithDetails(); + + // tear down all devices first before we destroy the VM to avoid accidently delete disk backing files + if (this.resource.getVmState(vmMo) != State.Stopped) + vmMo.safePowerOff(_shutdown_waitMs); + vmMo.tearDownDevices(new Class[] { VirtualDisk.class, VirtualEthernetCard.class }); + vmMo.destroy(); + + for (NetworkDetails netDetails : networks) { + if (netDetails.getGCTag() != null && netDetails.getGCTag().equalsIgnoreCase("true")) { + if (netDetails.getVMMorsOnNetwork() == null || netDetails.getVMMorsOnNetwork().length == 1) { + this.resource.cleanupNetwork(hostMo, netDetails); + } + } + } + } + + if (s_logger.isInfoEnabled()) + s_logger.info("Destroy volume by original name: " + vol.getPath() + ".vmdk"); + dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true); + + // root volume may be created via linked-clone, delete the delta disk as well + if (_fullCloneFlag) { + if (s_logger.isInfoEnabled()) { + s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk"); + } + dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true); + } else { + if (s_logger.isInfoEnabled()) { + s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-delta.vmdk"); + } + dsMo.deleteFile(vol.getPath() + "-delta.vmdk", morDc, true); + } + return new Answer(cmd, true, "Success"); + } + + if (s_logger.isInfoEnabled()) { + s_logger.info("Destroy root volume directly from datastore"); + } + } else { + // evitTemplate will be converted into DestroyCommand, test if we are running in this case + VirtualMachineMO vmMo = clusterMo.findVmOnHyperHost(vol.getPath()); + if (vmMo != null) { + if (s_logger.isInfoEnabled()) + s_logger.info("Destroy template volume " + vol.getPath()); + + vmMo.destroy(); + return new Answer(cmd, true, "Success"); + } + } + + String chainInfo = vol.getChainInfo(); + if (chainInfo != null && !chainInfo.isEmpty()) { + s_logger.info("Destroy volume by chain info: " + chainInfo); + String[] diskChain = _gson.fromJson(chainInfo, String[].class); + + if (diskChain != null && diskChain.length > 0) { + for (String backingName : diskChain) { + if (s_logger.isInfoEnabled()) { + s_logger.info("Delete volume backing file: " + backingName); + } + dsMo.deleteFile(backingName, morDc, true); + } + } else { + if (s_logger.isInfoEnabled()) { + s_logger.info("Empty disk chain info, fall back to try to delete by original backing file name"); + } + dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true); + + if (s_logger.isInfoEnabled()) { + s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk"); + } + dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true); + } + } else { + if (s_logger.isInfoEnabled()) { + s_logger.info("Destroy volume by original name: " + vol.getPath() + ".vmdk"); + } + dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true); + + if (s_logger.isInfoEnabled()) { + s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk"); + } + dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true); + } + + return new Answer(cmd, true, "Success"); + } catch (Throwable e) { + if (e instanceof RemoteException) { + s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context"); + this.hostService.invalidateServiceContext(null); + } + + String msg = "DestroyCommand failed due to " + VmwareHelper.getExceptionMessage(e); + s_logger.error(msg, e); + return new Answer(cmd, false, msg); + } + } + + private Long restoreVolumeFromSecStorage(VmwareHypervisorHost hyperHost, DatastoreMO primaryDsMo, String newVolumeName, + String secStorageUrl, String secStorageDir, String backupName) throws Exception { + + String secondaryMountPoint = mountService.getMountPoint(secStorageUrl); + String srcOVAFileName = secondaryMountPoint + "/" + secStorageDir + "/" + + backupName + "." + ImageFormat.OVA.getFileExtension(); + String snapshotDir = ""; + if (backupName.contains("/")){ + snapshotDir = backupName.split("/")[0]; + } + + File ovafile = new File(srcOVAFileName); + String srcOVFFileName = secondaryMountPoint + "/" + secStorageDir + "/" + + backupName + ".ovf"; + File ovfFile = new File(srcOVFFileName); + // String srcFileName = getOVFFilePath(srcOVAFileName); + if (!ovfFile.exists()) { + srcOVFFileName = getOVFFilePath(srcOVAFileName); + if(srcOVFFileName == null && ovafile.exists() ) { // volss: ova file exists; o/w can't do tar + Script command = new Script("tar", 0, s_logger); + command.add("--no-same-owner"); + command.add("-xf", srcOVAFileName); + command.setWorkDir(secondaryMountPoint + "/" + secStorageDir + "/" + snapshotDir); + s_logger.info("Executing command: " + command.toString()); + String result = command.execute(); + if(result != null) { + String msg = "Unable to unpack snapshot OVA file at: " + srcOVAFileName; + s_logger.error(msg); + throw new Exception(msg); + } + } else { + String msg = "Unable to find snapshot OVA file at: " + srcOVAFileName; + s_logger.error(msg); + throw new Exception(msg); + } + + srcOVFFileName = getOVFFilePath(srcOVAFileName); + } + if(srcOVFFileName == null) { + String msg = "Unable to locate OVF file in template package directory: " + srcOVAFileName; + s_logger.error(msg); + throw new Exception(msg); + } + + VirtualMachineMO clonedVm = null; + try { + hyperHost.importVmFromOVF(srcOVFFileName, newVolumeName, primaryDsMo, "thin"); + clonedVm = hyperHost.findVmOnHyperHost(newVolumeName); + if(clonedVm == null) + throw new Exception("Unable to create container VM for volume creation"); + + clonedVm.moveAllVmDiskFiles(primaryDsMo, "", false); + clonedVm.detachAllDisks(); + return _storage.getSize(srcOVFFileName); + } finally { + if(clonedVm != null) { + clonedVm.detachAllDisks(); + clonedVm.destroy(); + } + } + } + + @Override + public Answer createVolumeFromSnapshot(CopyCommand cmd) { + DataTO srcData = cmd.getSrcTO(); + SnapshotObjectTO snapshot = (SnapshotObjectTO)srcData; + DataTO destData = cmd.getDestTO(); + PrimaryDataStoreTO pool = (PrimaryDataStoreTO)destData.getDataStore(); + DataStoreTO imageStore = srcData.getDataStore(); + + + if (!(imageStore instanceof NfsTO)) { + return new CopyCmdAnswer("unsupported protocol"); + } + + NfsTO nfsImageStore = (NfsTO)imageStore; + String primaryStorageNameLabel = pool.getUuid(); + + String secondaryStorageUrl = nfsImageStore.getUrl(); + String backedUpSnapshotUuid = snapshot.getPath(); + int index = backedUpSnapshotUuid.lastIndexOf(File.separator); + String backupPath = backedUpSnapshotUuid.substring(0, index); + backedUpSnapshotUuid = backedUpSnapshotUuid.substring(index + 1); + String details = null; + String newVolumeName = UUID.randomUUID().toString().replaceAll("-", ""); + + VmwareContext context = hostService.getServiceContext(cmd); + try { + VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd); + ManagedObjectReference morPrimaryDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, + primaryStorageNameLabel); + if (morPrimaryDs == null) { + String msg = "Unable to find datastore: " + primaryStorageNameLabel; + s_logger.error(msg); + throw new Exception(msg); + } + + DatastoreMO primaryDsMo = new DatastoreMO(hyperHost.getContext(), morPrimaryDs); + Long size = restoreVolumeFromSecStorage(hyperHost, primaryDsMo, + newVolumeName, secondaryStorageUrl, backupPath, backedUpSnapshotUuid); + + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(newVolumeName); + newVol.setSize(size); + return new CopyCmdAnswer(newVol); + } catch (Throwable e) { + if (e instanceof RemoteException) { + hostService.invalidateServiceContext(context); + } + + s_logger.error("Unexpecpted exception ", e); + details = "CreateVolumeFromSnapshotCommand exception: " + StringUtils.getExceptionStackInfo(e); + } + return new CopyCmdAnswer(details); + } + + @Override + public Answer deleteSnapshot(DeleteCommand cmd) { + SnapshotObjectTO snapshot = (SnapshotObjectTO)cmd.getData(); + DataStoreTO store = snapshot.getDataStore(); + if (store.getRole() == DataStoreRole.Primary) { + return new Answer(cmd); + } else { + return new Answer(cmd, false, "unsupported command"); + } + } +} diff --git a/plugins/hypervisors/vmware/src/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java b/plugins/hypervisors/vmware/src/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java index 11be609bcf7..bdba61ba028 100644 --- a/plugins/hypervisors/vmware/src/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java +++ b/plugins/hypervisors/vmware/src/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java @@ -21,11 +21,10 @@ package org.apache.cloudstack.storage.motion; import java.util.HashMap; import java.util.Map; -import java.util.List; - import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; @@ -39,12 +38,6 @@ import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.MigrateWithStorageAnswer; import com.cloud.agent.api.MigrateWithStorageCommand; -import com.cloud.agent.api.MigrateWithStorageCompleteAnswer; -import com.cloud.agent.api.MigrateWithStorageCompleteCommand; -import com.cloud.agent.api.MigrateWithStorageReceiveAnswer; -import com.cloud.agent.api.MigrateWithStorageReceiveCommand; -import com.cloud.agent.api.MigrateWithStorageSendAnswer; -import com.cloud.agent.api.MigrateWithStorageSendCommand; import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.api.to.VolumeTO; diff --git a/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/VmwareDatacenterApiUnitTest.java b/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/VmwareDatacenterApiUnitTest.java index de08c93c78a..d79d41e024c 100644 --- a/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/VmwareDatacenterApiUnitTest.java +++ b/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/VmwareDatacenterApiUnitTest.java @@ -32,6 +32,7 @@ import junit.framework.TestCase; import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd; import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.test.utils.SpringUtils; import org.junit.Before; import org.junit.BeforeClass; @@ -414,6 +415,10 @@ public class VmwareDatacenterApiUnitTest { return Mockito.mock(RemoveVmwareDcCmd.class); } + @Bean + public DataStoreManager dataStoreManager() { + return Mockito.mock(DataStoreManager.class); + } public static class Library implements TypeFilter { @Override diff --git a/plugins/hypervisors/vmware/test/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategyTest.java b/plugins/hypervisors/vmware/test/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategyTest.java index ae4f41d55a5..3d2ad57711d 100644 --- a/plugins/hypervisors/vmware/test/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategyTest.java +++ b/plugins/hypervisors/vmware/test/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategyTest.java @@ -30,7 +30,6 @@ import java.util.Map; import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; @@ -39,6 +38,7 @@ import org.apache.cloudstack.framework.async.AsyncCallFuture; import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.framework.async.AsyncRpcConext; +import org.apache.cloudstack.storage.command.CommandResult; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.test.utils.SpringUtils; import org.junit.Before; diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java index 5b6b546b6d4..e360c984619 100755 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java @@ -11,7 +11,7 @@ // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the +// KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package com.cloud.hypervisor.xen.discoverer; @@ -66,7 +66,6 @@ import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VMTemplateHostDao; import com.cloud.user.Account; import com.cloud.utils.NumbersUtil; import com.cloud.utils.db.SearchCriteria.Op; @@ -114,14 +113,13 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L @Inject protected AlertManager _alertMgr; @Inject protected AgentManager _agentMgr; @Inject VMTemplateDao _tmpltDao; - @Inject VMTemplateHostDao _vmTemplateHostDao; @Inject ResourceManager _resourceMgr; @Inject HostPodDao _podDao; @Inject DataCenterDao _dcDao; - + protected XcpServerDiscoverer() { } - + void setClusterGuid(ClusterVO cluster, String guid) { cluster.setGuid(guid); try { @@ -155,43 +153,43 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L String msg = "must specify cluster Id when add host"; s_logger.debug(msg); throw new RuntimeException(msg); - } - + } + if (podId == null) { String msg = "must specify pod Id when add host"; s_logger.debug(msg); throw new RuntimeException(msg); } - + ClusterVO cluster = _clusterDao.findById(clusterId); if(cluster == null || cluster.getHypervisorType() != HypervisorType.XenServer) { if(s_logger.isInfoEnabled()) s_logger.info("invalid cluster id or cluster is not for XenServer hypervisors"); return null; } - + try { List eHosts = _resourceMgr.listAllHostsInCluster(clusterId); if( eHosts.size() > 0 ) { HostVO eHost = eHosts.get(0); _hostDao.loadDetails(eHost); - } + } String hostname = url.getHost(); InetAddress ia = InetAddress.getByName(hostname); - String hostIp = ia.getHostAddress(); + String hostIp = ia.getHostAddress(); Queue pass=new LinkedList(); pass.add(password); - String masterIp = _connPool.getMasterIp(hostIp, username, pass); + String masterIp = _connPool.getMasterIp(hostIp, username, pass); conn = _connPool.masterConnect(masterIp, username, pass); if (conn == null) { String msg = "Unable to get a connection to " + url; s_logger.debug(msg); throw new DiscoveryException(msg); } - + Set pools = Pool.getAll(conn); Pool pool = pools.iterator().next(); - Pool.Record pr = pool.getRecord(conn); + Pool.Record pr = pool.getRecord(conn); String poolUuid = pr.uuid; Map hosts = Host.getAllRecords(conn); @@ -228,22 +226,22 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L conn.dispose(); conn = null; } - + poolUuid = clu.getGuid(); _clusterDao.update(clusterId, clu); - - + + if (_checkHvm) { for (Map.Entry entry : hosts.entrySet()) { Host.Record record = entry.getValue(); - + boolean support_hvm = false; for ( String capability : record.capabilities ) { if(capability.contains("hvm")) { support_hvm = true; break; } - } + } if( !support_hvm ) { String msg = "Unable to add host " + record.address + " because it doesn't support hvm"; _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, dcId, podId, msg, msg); @@ -256,7 +254,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L for (Map.Entry entry : hosts.entrySet()) { Host.Record record = entry.getValue(); String hostAddr = record.address; - + String prodVersion = record.softwareVersion.get("product_version"); if (prodVersion == null) { prodVersion = record.softwareVersion.get("platform_version"); @@ -266,18 +264,18 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L if (hostOS == null) { hostOS = record.softwareVersion.get("platform_name"); } - + String hostOSVer = prodVersion; String hostKernelVer = record.softwareVersion.get("linux"); if (_resourceMgr.findHostByGuid(record.uuid) != null) { s_logger.debug("Skipping " + record.address + " because " + record.uuid + " is already in the database."); continue; - } + } CitrixResourceBase resource = createServerResource(dcId, podId, record); s_logger.info("Found host " + record.hostname + " ip=" + record.address + " product version=" + prodVersion); - + Map details = new HashMap(); Map params = new HashMap(); details.put("url", hostAddr); @@ -291,26 +289,26 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L params.put("cluster", clusterId.toString()); params.put("pool", poolUuid); params.put("ipaddress", record.address); - + details.put(HostInfo.HOST_OS, hostOS); details.put(HostInfo.HOST_OS_VERSION, hostOSVer); details.put(HostInfo.HOST_OS_KERNEL_VERSION, hostKernelVer); details.put(HostInfo.HYPERVISOR_VERSION, xenVersion); - + String privateNetworkLabel = _networkMgr.getDefaultManagementTrafficLabel(dcId, HypervisorType.XenServer); String storageNetworkLabel = _networkMgr.getDefaultStorageTrafficLabel(dcId, HypervisorType.XenServer); - + if (!params.containsKey("private.network.device") && privateNetworkLabel != null) { params.put("private.network.device", privateNetworkLabel); details.put("private.network.device", privateNetworkLabel); } - + if (!params.containsKey("storage.network.device1") && storageNetworkLabel != null) { params.put("storage.network.device1", storageNetworkLabel); details.put("storage.network.device1", storageNetworkLabel); } - + params.put("wait", Integer.toString(_wait)); details.put("wait", Integer.toString(_wait)); params.put("migratewait", _configDao.getValue(Config.MigrateWait.toString())); @@ -327,8 +325,8 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L } resource.start(); resources.put(resource, details); - } - } catch (SessionAuthenticationFailed e) { + } + } catch (SessionAuthenticationFailed e) { throw new DiscoveredWithErrorException("Authentication error"); } catch (XenAPIException e) { s_logger.warn("XenAPI exception", e); @@ -345,27 +343,27 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L } return resources; } - + String getPoolUuid(Connection conn) throws XenAPIException, XmlRpcException { Map pools = Pool.getAllRecords(conn); assert pools.size() == 1 : "Pools size is " + pools.size(); return pools.values().iterator().next().uuid; } - + protected void addSamePool(Connection conn, Map> resources) throws XenAPIException, XmlRpcException { Map hps = Pool.getAllRecords(conn); assert (hps.size() == 1) : "How can it be more than one but it's actually " + hps.size(); - + // This is the pool. String poolUuid = hps.values().iterator().next().uuid; - + for (Map details : resources.values()) { details.put("pool", poolUuid); } } - + protected boolean addHostsToPool(Connection conn, String hostIp, Long clusterId) throws XenAPIException, XmlRpcException, DiscoveryException { - + List hosts; hosts = _resourceMgr.listAllHostsInCluster(clusterId); @@ -400,19 +398,19 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L hostConn = null; } } - + if (masterIp == null) { s_logger.warn("Unable to reach the pool master of the existing cluster"); throw new CloudRuntimeException("Unable to reach the pool master of the existing cluster"); } - + if( !_connPool.joinPool(conn, hostIp, masterIp, username, pass) ){ s_logger.warn("Unable to join the pool"); throw new DiscoveryException("Unable to join the pool"); - } + } return true; } - + protected CitrixResourceBase createServerResource(long dcId, Long podId, Host.Record record) { String prodBrand = record.softwareVersion.get("product_brand"); if (prodBrand == null) { @@ -440,11 +438,11 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L return new XcpServer16Resource(); } // Citrix Xenserver group of hypervisors else if (prodBrand.equals("XenServer") && prodVersion.equals("5.6.0")) - return new XenServer56Resource(); + return new XenServer56Resource(); else if (prodBrand.equals("XenServer") && prodVersion.equals("6.0.0")) - return new XenServer600Resource(); + return new XenServer600Resource(); else if (prodBrand.equals("XenServer") && prodVersion.equals("6.0.2")) - return new XenServer602Resource(); + return new XenServer602Resource(); else if (prodBrand.equals("XenServer") && prodVersion.equals("6.1.0")) return new XenServer610Resource(); else if (prodBrand.equals("XenServer") && prodVersion.equals("6.1.83")) @@ -452,72 +450,72 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L else if (prodBrand.equals("XenServer") && prodVersion.equals("6.2.0")) return new XenServer610Resource(); else if (prodBrand.equals("XenServer") && prodVersion.equals("5.6.100")) { - String prodVersionTextShort = record.softwareVersion.get("product_version_text_short").trim(); + String prodVersionTextShort = record.softwareVersion.get("product_version_text_short").trim(); if ("5.6 SP2".equals(prodVersionTextShort)) { - return new XenServer56SP2Resource(); + return new XenServer56SP2Resource(); } else if ("5.6 FP1".equals(prodVersionTextShort)) { - return new XenServer56FP1Resource(); - } + return new XenServer56FP1Resource(); + } } else if (prodBrand.equals("XCP_Kronos")) { return new XcpOssResource(); } String msg = "Only support XCP 1.0.0, 1.1.0, 1.4.x, 1.5 beta, 1.6.x; XenServer 5.6, XenServer 5.6 FP1, XenServer 5.6 SP2, Xenserver 6.0, 6.0.2, 6.1.0, 6.1.83, 6.2.0 but this one is " + prodBrand + " " + prodVersion; - _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, dcId, podId, msg, msg); + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, dcId, podId, msg, msg); s_logger.debug(msg); throw new RuntimeException(msg); } - - protected void serverConfig() { + + protected void serverConfig() { String value = _params.get(Config.XenSetupMultipath.key()); _setupMultipath = Boolean.parseBoolean(value); } - + @Override public boolean configure(String name, Map params) throws ConfigurationException { super.configure(name, params); serverConfig(); - + _publicNic = _params.get(Config.XenPublicNetwork.key()); _privateNic = _params.get(Config.XenPrivateNetwork.key()); - + _storageNic1 = _params.get(Config.XenStorageNetwork1.key()); _storageNic2 = _params.get(Config.XenStorageNetwork2.key()); - + _guestNic = _params.get(Config.XenGuestNetwork.key()); - + String value = _params.get(Config.XapiWait.toString()); _wait = NumbersUtil.parseInt(value, Integer.parseInt(Config.XapiWait.getDefaultValue())); - + _instance = _params.get(Config.InstanceName.key()); - + value = _params.get(Config.XenSetupMultipath.key()); Boolean.parseBoolean(value); value = _params.get("xen.check.hvm"); _checkHvm = false; _connPool = XenServerConnectionPool.getInstance(); - + _agentMgr.registerForHostEvents(this, true, false, true); - + createXsToolsISO(); _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); return true; } - + @Override public boolean matchHypervisor(String hypervisor) { if(hypervisor == null) return true; return Hypervisor.HypervisorType.XenServer.toString().equalsIgnoreCase(hypervisor); } - + @Override public Hypervisor.HypervisorType getHypervisorType() { return Hypervisor.HypervisorType.XenServer; } - + @Override public void postDiscovery(List hosts, long msId) throws DiscoveryException{ //do nothing @@ -542,14 +540,14 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L public boolean processCommands(long agentId, long seq, Command[] commands) { return false; } - + private void createXsToolsISO() { String isoName = "xs-tools.iso"; VMTemplateVO tmplt = _tmpltDao.findByTemplateName(isoName); Long id; if (tmplt == null) { id = _tmpltDao.getNextInSequence(Long.class, "id"); - VMTemplateVO template = new VMTemplateVO(id, isoName, isoName, ImageFormat.ISO, true, true, + VMTemplateVO template = VMTemplateVO.createPreHostIso(id, isoName, isoName, ImageFormat.ISO, true, true, TemplateType.PERHOST, null, null, true, 64, Account.ACCOUNT_ID_SYSTEM, null, "xen-pv-drv-iso", false, 1, false, HypervisorType.XenServer); _tmpltDao.persist(template); @@ -562,20 +560,20 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L } @Override - public void processConnect(HostVO agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException { + public void processConnect(com.cloud.host.Host agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException { if (!(cmd instanceof StartupRoutingCommand )) { return; - } + } long agentId = agent.getId(); - + StartupRoutingCommand startup = (StartupRoutingCommand)cmd; if (startup.getHypervisorType() != HypervisorType.XenServer) { s_logger.debug("Not XenServer so moving on."); return; } - + HostVO host = _hostDao.findById(agentId); - + ClusterVO cluster = _clusterDao.findById(host.getClusterId()); if ( cluster.getGuid() == null) { cluster.setGuid(startup.getPool()); @@ -614,9 +612,9 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L resource = XenServer56FP1Resource.class.getName(); } } else if (prodBrand.equals("XCP_Kronos")) { - resource = XcpOssResource.class.getName(); + resource = XcpOssResource.class.getName(); } - + if( resource == null ){ String msg = "Only support XCP 1.0.0, 1.1.0, 1.4.x, 1.5 beta, 1.6.x; XenServer 5.6, 5.6 FP1, 5.6 SP2 and Xenserver 6.0 , 6.0.2, 6.1.0, 6.1.83, 6.2.0 but this one is " + prodBrand + " " + prodVersion; s_logger.debug(msg); @@ -630,13 +628,13 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L _hostDao.update(agentId, host); throw new HypervisorVersionChangedException(msg); } - - + + if (s_logger.isDebugEnabled()) { s_logger.debug("Setting up host " + agentId); } HostEnvironment env = new HostEnvironment(); - + SetupCommand setup = new SetupCommand(env); if (_setupMultipath) { setup.setMultipathOn(); @@ -644,7 +642,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L if (!host.isSetup()) { setup.setNeedSetup(true); } - + try { SetupAnswer answer = (SetupAnswer)_agentMgr.send(agentId, setup); if (answer != null && answer.getResult()) { @@ -712,7 +710,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L if (host.getType() != com.cloud.host.Host.Type.Routing || host.getHypervisorType() != HypervisorType.XenServer) { return null; } - + _resourceMgr.deleteRoutingHost(host, isForced, isForceDeleteStorage); if (host.getClusterId() != null) { List hosts = _resourceMgr.listAllUpAndEnabledHosts(com.cloud.host.Host.Type.Routing, host.getClusterId(), host.getPodId(), host.getDataCenterId()); @@ -721,7 +719,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L if (thost.getId() == host.getId()) { continue; } - + long thostId = thost.getId(); PoolEjectCommand eject = new PoolEjectCommand(host.getGuid()); Answer answer = _agentMgr.easySend(thostId, eject); @@ -741,10 +739,10 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, host.getDataCenterId(), host.getPodId(), "Unable to eject host " + host.getGuid(), msg); } } - + return new DeleteHostAnswer(true); } - + @Override public boolean stop() { _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName()); diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 71a38d239db..fa0e1d05030 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -17,6 +17,56 @@ package com.cloud.hypervisor.xen.resource; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.lang.reflect.InvocationTargetException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Queue; +import java.util.Random; +import java.util.Set; +import java.util.UUID; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; +import javax.xml.parsers.DocumentBuilderFactory; + +import com.cloud.agent.api.*; +import com.cloud.agent.api.to.*; +import com.cloud.network.rules.FirewallRule; + +import org.apache.cloudstack.storage.command.StorageSubSystemCommand; +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + import com.cloud.agent.IAgentControl; import com.cloud.agent.api.Answer; import com.cloud.agent.api.AttachIsoCommand; @@ -199,7 +249,9 @@ import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Volume; import com.cloud.storage.VolumeVO; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.resource.StorageSubsystemCommandHandler; +import com.cloud.storage.resource.StorageSubsystemCommandHandlerBase; +import com.cloud.storage.template.TemplateProp; import com.cloud.template.VirtualMachineTemplate.BootloaderType; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; @@ -345,7 +397,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected boolean _canBridgeFirewall = false; protected boolean _isOvs = false; protected List _tmpDom0Vif = new ArrayList(); - protected XenServerStorageResource storageResource; + protected StorageSubsystemCommandHandler storageHandler; protected int _maxNics = 7; public enum SRType { @@ -613,7 +665,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } else if (clazz == CheckS2SVpnConnectionsCommand.class) { return execute((CheckS2SVpnConnectionsCommand) cmd); } else if (cmd instanceof StorageSubSystemCommand) { - return this.storageResource.handleStorageCommands((StorageSubSystemCommand)cmd); + return this.storageHandler.handleStorageCommands((StorageSubSystemCommand)cmd); } else if (clazz == CreateVMSnapshotCommand.class) { return execute((CreateVMSnapshotCommand)cmd); } else if (clazz == DeleteVMSnapshotCommand.class) { @@ -1133,31 +1185,42 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected VDI mount(Connection conn, String vmName, VolumeTO volume) throws XmlRpcException, XenAPIException { - if (volume.getType() == Volume.Type.ISO) { - String isopath = volume.getPath(); - if (isopath == null) { + protected VDI mount(Connection conn, String vmName, DiskTO volume) throws XmlRpcException, XenAPIException { + DataTO data = volume.getData(); + Volume.Type type = volume.getType(); + if (type == Volume.Type.ISO) { + TemplateObjectTO iso = (TemplateObjectTO)data; + DataStoreTO store = iso.getDataStore(); + + if (store == null) { + //It's a fake iso return null; } - if (isopath.startsWith("xs-tools")) { + + //corer case, xenserver pv driver iso + String templateName = iso.getName(); + if (templateName.startsWith("xs-tools")) { try { - Set vdis = VDI.getByNameLabel(conn, isopath); + Set vdis = VDI.getByNameLabel(conn, templateName); if (vdis.isEmpty()) { - throw new CloudRuntimeException("Could not find ISO with URL: " + isopath); + throw new CloudRuntimeException("Could not find ISO with URL: " + templateName); } return vdis.iterator().next(); - } catch (XenAPIException e) { - throw new CloudRuntimeException("Unable to get pv iso: " + isopath + " due to " + e.toString()); + throw new CloudRuntimeException("Unable to get pv iso: " + templateName + " due to " + e.toString()); } catch (Exception e) { - throw new CloudRuntimeException("Unable to get pv iso: " + isopath + " due to " + e.toString()); + throw new CloudRuntimeException("Unable to get pv iso: " + templateName + " due to " + e.toString()); } } + + if (!(store instanceof NfsTO)) { + throw new CloudRuntimeException("only support mount iso on nfs"); + } + NfsTO nfsStore = (NfsTO)store; + String isoPath = nfsStore.getUrl() + File.separator + iso.getPath(); + int index = isoPath.lastIndexOf("/"); - - int index = isopath.lastIndexOf("/"); - - String mountpoint = isopath.substring(0, index); + String mountpoint = isoPath.substring(0, index); URI uri; try { uri = new URI(mountpoint); @@ -1166,20 +1229,21 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } SR isoSr = createIsoSRbyURI(conn, uri, vmName, false); - String isoname = isopath.substring(index + 1); + String isoname = isoPath.substring(index + 1); VDI isoVdi = getVDIbyLocationandSR(conn, isoname, isoSr); if (isoVdi == null) { - throw new CloudRuntimeException("Unable to find ISO " + volume.getPath()); + throw new CloudRuntimeException("Unable to find ISO " + isoPath); } return isoVdi; } else { - return VDI.getByUuid(conn, volume.getPath()); + VolumeObjectTO vol = (VolumeObjectTO)data; + return VDI.getByUuid(conn,vol.getPath()); } } - protected VBD createVbd(Connection conn, VolumeTO volume, String vmName, VM vm, BootloaderType bootLoaderType) throws XmlRpcException, XenAPIException { + protected VBD createVbd(Connection conn, DiskTO volume, String vmName, VM vm, BootloaderType bootLoaderType) throws XmlRpcException, XenAPIException { Volume.Type type = volume.getType(); VDI vdi = mount(conn, vmName, volume); @@ -1197,7 +1261,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe vbdr.bootable = true; } - vbdr.userdevice = Long.toString(volume.getDeviceId()); + vbdr.userdevice = Long.toString(volume.getDiskSeq()); if (volume.getType() == Volume.Type.ISO) { vbdr.mode = Types.VbdMode.RO; vbdr.type = Types.VbdType.CD; @@ -1293,12 +1357,17 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (!(guestOsTypeName.startsWith("Windows") || guestOsTypeName.startsWith("Citrix") || guestOsTypeName.startsWith("Other"))) { if (vmSpec.getBootloader() == BootloaderType.CD) { - VolumeTO [] disks = vmSpec.getDisks(); - for (VolumeTO disk : disks) { - if (disk.getType() == Volume.Type.ISO && disk.getOsType() != null) { - String isoGuestOsName = getGuestOsType(disk.getOsType(), vmSpec.getBootloader() == BootloaderType.CD); - if (!isoGuestOsName.equals(guestOsTypeName)) { - vmSpec.setBootloader(BootloaderType.PyGrub); + DiskTO [] disks = vmSpec.getDisks(); + for (DiskTO disk : disks) { + Volume.Type type = disk.getType(); + if (type == Volume.Type.ISO) { + TemplateObjectTO tmpl = (TemplateObjectTO)disk.getData(); + String osType = tmpl.getGuestOsType(); + if (tmpl.getFormat() == ImageFormat.ISO && osType != null ) { + String isoGuestOsName = getGuestOsType(osType, vmSpec.getBootloader() == BootloaderType.CD); + if (!isoGuestOsName.equals(guestOsTypeName)) { + vmSpec.setBootloader(BootloaderType.PyGrub); + } } } } @@ -1592,7 +1661,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe Host host = Host.getByUuid(conn, _host.uuid); vm = createVmFromTemplate(conn, vmSpec, host); - for (VolumeTO disk : vmSpec.getDisks()) { + for (DiskTO disk : vmSpec.getDisks()) { createVbd(conn, disk, vmName, vm, vmSpec.getBootloader()); } @@ -3912,7 +3981,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return false; } - private void swiftBackupSnapshot(Connection conn, SwiftTO swift, String srUuid, String snapshotUuid, String container, Boolean isISCSI, int wait) { + public void swiftBackupSnapshot(Connection conn, SwiftTO swift, String srUuid, String snapshotUuid, String container, Boolean isISCSI, int wait) { String lfilename; String ldir; if ( isISCSI ) { @@ -5579,7 +5648,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe s_logger.warn(msg); return new Answer(cmd, false, msg); } - Map tInfo = new HashMap(); + Map tInfo = new HashMap(); ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, capacity, available, tInfo); return answer; } catch (XenAPIException e) { @@ -6065,13 +6134,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe CheckXenHostInfo(); - this.storageResource = getStorageResource(); + this.storageHandler = getStorageHandler(); return true; } - protected XenServerStorageResource getStorageResource() { - return new XenServerStorageResource(this); + protected StorageSubsystemCommandHandler getStorageHandler() { + XenServerStorageProcessor processor = new XenServerStorageProcessor(this); + return new StorageSubsystemCommandHandlerBase(processor); } private void CheckXenHostInfo() throws ConfigurationException { diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpOssResource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpOssResource.java index 870049c8111..5261ca046e7 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpOssResource.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpOssResource.java @@ -17,6 +17,17 @@ package com.cloud.hypervisor.xen.resource; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + + import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.NetworkUsageAnswer; @@ -39,14 +50,7 @@ import com.xensource.xenapi.Types.XenAPIException; import com.xensource.xenapi.VBD; import com.xensource.xenapi.VDI; import com.xensource.xenapi.VM; -import org.apache.log4j.Logger; -import org.apache.xmlrpc.XmlRpcException; -import javax.ejb.Local; -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; @Local(value=ServerResource.class) public class XcpOssResource extends CitrixResourceBase { @@ -65,13 +69,13 @@ public class XcpOssResource extends CitrixResourceBase { files.add(file); return files; } - + @Override protected void fillHostInfo(Connection conn, StartupRoutingCommand cmd) { super.fillHostInfo(conn, cmd); cmd.setCaps(cmd.getCapabilities() + " , hvm"); } - + @Override protected String getGuestOsType(String stdType, boolean bootFromCD) { if (stdType.equalsIgnoreCase("Debian GNU/Linux 6(64-bit)")) { @@ -80,7 +84,7 @@ public class XcpOssResource extends CitrixResourceBase { return CitrixHelper.getXcpGuestOsType(stdType); } } - + protected VBD createPatchVbd(Connection conn, String vmName, VM vm) throws XmlRpcException, XenAPIException { if (_host.localSRuuid != null) { //create an iso vdi on it @@ -88,13 +92,13 @@ public class XcpOssResource extends CitrixResourceBase { if (result == null || result.equalsIgnoreCase("Failed")) { throw new CloudRuntimeException("can not create systemvm vdi"); } - + Set vdis = VDI.getByNameLabel(conn, "systemvm-vdi"); if (vdis.size() != 1) { throw new CloudRuntimeException("can not find systemvmiso"); } VDI systemvmVDI = vdis.iterator().next(); - + VBD.Record cdromVBDR = new VBD.Record(); cdromVBDR.VM = vm; cdromVBDR.empty = false; @@ -109,7 +113,7 @@ public class XcpOssResource extends CitrixResourceBase { throw new CloudRuntimeException("can not find local sr"); } } - + protected NetworkUsageAnswer execute(NetworkUsageCommand cmd) { try { @@ -124,10 +128,10 @@ public class XcpOssResource extends CitrixResourceBase { return answer; } catch (Exception ex) { s_logger.warn("Failed to get network usage stats due to ", ex); - return new NetworkUsageAnswer(cmd, ex); + return new NetworkUsageAnswer(cmd, ex); } } - + @Override public Answer executeRequest(Command cmd) { if (cmd instanceof NetworkUsageCommand) { @@ -136,11 +140,11 @@ public class XcpOssResource extends CitrixResourceBase { return super.executeRequest(cmd); } } - + @Override public StartAnswer execute(StartCommand cmd) { StartAnswer answer = super.execute(cmd); - + VirtualMachineTO vmSpec = cmd.getVirtualMachine(); if (vmSpec.getType() == VirtualMachine.Type.ConsoleProxy) { Connection conn = getConnection(); @@ -152,10 +156,10 @@ public class XcpOssResource extends CitrixResourceBase { } callHostPlugin(conn, "vmops", "setDNATRule", "ip", publicIp, "port", "8443", "add", "true"); } - + return answer; } - + @Override public StopAnswer execute(StopCommand cmd) { StopAnswer answer = super.execute(cmd); diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java index f7da000d100..95774bfbca5 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java @@ -11,16 +11,31 @@ // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the +// KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package com.cloud.hypervisor.xen.resource; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.ejb.Local; + +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + import com.cloud.agent.api.FenceAnswer; import com.cloud.agent.api.FenceCommand; +import com.cloud.agent.api.to.DiskTO; import com.cloud.agent.api.to.VirtualMachineTO; -import com.cloud.agent.api.to.VolumeTO; import com.cloud.resource.ServerResource; import com.cloud.storage.Volume; import com.cloud.template.VirtualMachineTemplate.BootloaderType; @@ -33,36 +48,25 @@ import com.xensource.xenapi.Types.XenAPIException; import com.xensource.xenapi.VBD; import com.xensource.xenapi.VDI; import com.xensource.xenapi.VM; -import org.apache.log4j.Logger; -import org.apache.xmlrpc.XmlRpcException; - -import javax.ejb.Local; -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; @Local(value=ServerResource.class) public class XenServer56FP1Resource extends XenServer56Resource { private static final long mem_128m = 134217728L; private static final Logger s_logger = Logger.getLogger(XenServer56FP1Resource.class); - + public XenServer56FP1Resource() { super(); } - + @Override protected String getGuestOsType(String stdType, boolean bootFromCD) { return CitrixHelper.getXenServer56FP1GuestOsType(stdType, bootFromCD); } - + @Override - protected List getPatchFiles() { + protected List getPatchFiles() { List files = new ArrayList(); - String patch = "scripts/vm/hypervisor/xenserver/xenserver56fp1/patch"; + String patch = "scripts/vm/hypervisor/xenserver/xenserver56fp1/patch"; String patchfilePath = Script.findScript("" , patch); if ( patchfilePath == null ) { throw new CloudRuntimeException("Unable to find patch file " + patch); @@ -209,13 +213,17 @@ public class XenServer56FP1Resource extends XenServer56Resource { if (!(guestOsTypeName.startsWith("Windows") || guestOsTypeName.startsWith("Citrix") || guestOsTypeName.startsWith("Other"))) { if (vmSpec.getBootloader() == BootloaderType.CD) { - VolumeTO[] disks = vmSpec.getDisks(); - for (VolumeTO disk : disks) { - if (disk.getType() == Volume.Type.ISO && disk.getOsType() != null) { - String isoGuestOsName = getGuestOsType(disk.getOsType(), vmSpec.getBootloader() == BootloaderType.CD); - if (!isoGuestOsName.equals(guestOsTypeName)) { - vmSpec.setBootloader(BootloaderType.PyGrub); - } + DiskTO[] disks = vmSpec.getDisks(); + for (DiskTO disk : disks) { + if (disk.getType() == Volume.Type.ISO ) { + TemplateObjectTO iso = (TemplateObjectTO)disk.getData(); + String osType = iso.getGuestOsType(); + if (osType != null) { + String isoGuestOsName = getGuestOsType(osType, vmSpec.getBootloader() == BootloaderType.CD); + if (!isoGuestOsName.equals(guestOsTypeName)) { + vmSpec.setBootloader(BootloaderType.PyGrub); + } + } } } } diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer610Resource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer610Resource.java index bb31136f38e..95896611fc1 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer610Resource.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer610Resource.java @@ -26,6 +26,7 @@ import java.util.Set; import javax.ejb.Local; +import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.log4j.Logger; import com.cloud.resource.ServerResource; @@ -46,6 +47,7 @@ import com.cloud.agent.api.MigrateWithStorageCompleteAnswer; import com.cloud.agent.api.MigrateWithStorageCompleteCommand; import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.network.Networks.TrafficType; +import com.cloud.agent.api.to.DiskTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.api.to.VolumeTO; import com.cloud.agent.api.to.NicTO; @@ -103,9 +105,9 @@ public class XenServer610Resource extends XenServer56FP1Resource { } } - private List getUpdatedVolumePathsOfMigratedVm(Connection connection, VM migratedVm, - VolumeTO[] volumes) throws CloudRuntimeException { - List volumeToList = new ArrayList(); + private List getUpdatedVolumePathsOfMigratedVm(Connection connection, VM migratedVm, + DiskTO[] volumes) throws CloudRuntimeException { + List volumeToList = new ArrayList(); try { // Volume paths would have changed. Return that information. @@ -120,11 +122,14 @@ public class XenServer610Resource extends XenServer56FP1Resource { } } - for (VolumeTO volumeTo : volumes) { - Long deviceId = volumeTo.getDeviceId(); + for (DiskTO volumeTo : volumes) { + VolumeObjectTO vol = (VolumeObjectTO)volumeTo.getData(); + Long deviceId = volumeTo.getDiskSeq(); VDI vdi = deviceIdToVdiMap.get(deviceId.toString()); - volumeTo.setPath(vdi.getUuid(connection)); - volumeToList.add(volumeTo); + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(vdi.getUuid(connection)); + newVol.setId(vol.getId()); + volumeToList.add(newVol); } } catch (Exception e) { s_logger.error("Unable to get the updated VDI paths of the migrated vm " + e.toString(), e); @@ -194,7 +199,7 @@ public class XenServer610Resource extends XenServer56FP1Resource { } // Volume paths would have changed. Return that information. - List volumeToList = getUpdatedVolumePathsOfMigratedVm(connection, vmToMigrate, vmSpec.getDisks()); + List volumeToList = getUpdatedVolumePathsOfMigratedVm(connection, vmToMigrate, vmSpec.getDisks()); vmToMigrate.setAffinity(connection, host); state = State.Stopping; @@ -370,7 +375,7 @@ public class XenServer610Resource extends XenServer56FP1Resource { } // Volume paths would have changed. Return that information. - List volumeToSet = getUpdatedVolumePathsOfMigratedVm(connection, migratedVm, vmSpec.getDisks()); + List volumeToSet = getUpdatedVolumePathsOfMigratedVm(connection, migratedVm, vmSpec.getDisks()); migratedVm.setAffinity(connection, host); synchronized (_cluster.intern()) { diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java new file mode 100644 index 00000000000..399e2341b56 --- /dev/null +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java @@ -0,0 +1,1516 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.cloud.hypervisor.xen.resource; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.cloudstack.storage.command.AttachAnswer; +import org.apache.cloudstack.storage.command.AttachCommand; +import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreAnswer; +import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd; +import org.apache.cloudstack.storage.command.CopyCmdAnswer; +import org.apache.cloudstack.storage.command.CopyCommand; +import org.apache.cloudstack.storage.command.CreateObjectAnswer; +import org.apache.cloudstack.storage.command.CreateObjectCommand; +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.command.DettachAnswer; +import org.apache.cloudstack.storage.command.DettachCommand; +import org.apache.cloudstack.storage.datastore.protocol.DataStoreProtocol; +import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; +import org.apache.cloudstack.storage.to.SnapshotObjectTO; +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CreateStoragePoolCommand; +import com.cloud.agent.api.CreateVolumeFromSnapshotAnswer; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.DiskTO; +import com.cloud.agent.api.to.NfsTO; +import com.cloud.agent.api.to.S3TO; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.agent.api.to.SwiftTO; +import com.cloud.exception.InternalErrorException; +import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.storage.resource.StorageProcessor; +import com.cloud.utils.S3Utils; +import com.cloud.utils.StringUtils; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.storage.encoding.DecodedDataObject; +import com.cloud.utils.storage.encoding.DecodedDataStore; +import com.cloud.utils.storage.encoding.Decoder; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.PBD; +import com.xensource.xenapi.Pool; +import com.xensource.xenapi.SR; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.Types.BadServerResponse; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VBD; +import com.xensource.xenapi.VDI; +import com.xensource.xenapi.VM; +import com.xensource.xenapi.VMGuestMetrics; + +public class XenServerStorageProcessor implements StorageProcessor { + private static final Logger s_logger = Logger.getLogger(XenServerStorageProcessor.class); + protected CitrixResourceBase hypervisorResource; + + public XenServerStorageProcessor(CitrixResourceBase resource) { + this.hypervisorResource = resource; + } + + @Override + public AttachAnswer attachIso(AttachCommand cmd) { + DiskTO disk = cmd.getDisk(); + DataTO data = disk.getData(); + DataStoreTO store = data.getDataStore(); + + String isoURL = null; + if (store == null) { + TemplateObjectTO iso = (TemplateObjectTO)disk.getData(); + isoURL = iso.getName(); + } else { + if (!(store instanceof NfsTO)) { + s_logger.debug("Can't attach a iso which is not created on nfs: "); + return new AttachAnswer("Can't attach a iso which is not created on nfs: "); + } + NfsTO nfsStore = (NfsTO)store; + isoURL = nfsStore.getUrl() + File.separator + data.getPath(); + } + + String vmName = cmd.getVmName(); + try { + Connection conn = this.hypervisorResource.getConnection(); + + VBD isoVBD = null; + + // Find the VM + VM vm = this.hypervisorResource.getVM(conn, vmName); + // Find the ISO VDI + VDI isoVDI = this.hypervisorResource.getIsoVDIByURL(conn, vmName, isoURL); + + // Find the VM's CD-ROM VBD + Set vbds = vm.getVBDs(conn); + for (VBD vbd : vbds) { + String userDevice = vbd.getUserdevice(conn); + Types.VbdType type = vbd.getType(conn); + + if (userDevice.equals("3") && type == Types.VbdType.CD) { + isoVBD = vbd; + break; + } + } + + if (isoVBD == null) { + throw new CloudRuntimeException("Unable to find CD-ROM VBD for VM: " + vmName); + } else { + // If an ISO is already inserted, eject it + if (isoVBD.getEmpty(conn) == false) { + isoVBD.eject(conn); + } + + // Insert the new ISO + isoVBD.insert(conn, isoVDI); + } + + return new AttachAnswer(disk); + + } catch (XenAPIException e) { + s_logger.warn("Failed to attach iso" + ": " + e.toString(), e); + return new AttachAnswer(e.toString()); + } catch (Exception e) { + s_logger.warn("Failed to attach iso" + ": " + e.toString(), e); + return new AttachAnswer(e.toString()); + } + } + + @Override + public AttachAnswer attachVolume(AttachCommand cmd) { + String vmName = cmd.getVmName(); + DiskTO disk = cmd.getDisk(); + DataTO data = disk.getData(); + + try { + Connection conn = this.hypervisorResource.getConnection(); + // Look up the VDI + VDI vdi = this.hypervisorResource.mount(conn, null, null, data.getPath()); + // Look up the VM + VM vm = this.hypervisorResource.getVM(conn, vmName); + /* For HVM guest, if no pv driver installed, no attach/detach */ + boolean isHVM; + if (vm.getPVBootloader(conn).equalsIgnoreCase("")) { + isHVM = true; + } else { + isHVM = false; + } + VMGuestMetrics vgm = vm.getGuestMetrics(conn); + boolean pvDrvInstalled = false; + if (!this.hypervisorResource.isRefNull(vgm) && vgm.getPVDriversUpToDate(conn)) { + pvDrvInstalled = true; + } + if (isHVM && !pvDrvInstalled) { + s_logger.warn(": You attempted an operation on a VM which requires PV drivers to be installed but the drivers were not detected"); + return new AttachAnswer("You attempted an operation that requires PV drivers to be installed on the VM. Please install them by inserting xen-pv-drv.iso."); + } + + // Figure out the disk number to attach the VM to + String diskNumber = null; + Long deviceId = disk.getDiskSeq(); + if( deviceId != null ) { + if( deviceId.longValue() == 3 ) { + String msg = "Device 3 is reserved for CD-ROM, choose other device"; + return new AttachAnswer(msg); + } + if(this.hypervisorResource.isDeviceUsed(conn, vm, deviceId)) { + String msg = "Device " + deviceId + " is used in VM " + vmName; + return new AttachAnswer(msg); + } + diskNumber = deviceId.toString(); + } else { + diskNumber = this.hypervisorResource.getUnusedDeviceNum(conn, vm); + } + // Create a new VBD + VBD.Record vbdr = new VBD.Record(); + vbdr.VM = vm; + vbdr.VDI = vdi; + vbdr.bootable = false; + vbdr.userdevice = diskNumber; + vbdr.mode = Types.VbdMode.RW; + vbdr.type = Types.VbdType.DISK; + vbdr.unpluggable = true; + VBD vbd = VBD.create(conn, vbdr); + + // Attach the VBD to the VM + vbd.plug(conn); + + // Update the VDI's label to include the VM name + vdi.setNameLabel(conn, vmName + "-DATA"); + DiskTO newDisk = new DiskTO(disk.getData(), Long.parseLong(diskNumber), disk.getType()); + return new AttachAnswer(newDisk); + + } catch (XenAPIException e) { + String msg = "Failed to attach volume" + " for uuid: " + data.getPath() + " due to " + e.toString(); + s_logger.warn(msg, e); + return new AttachAnswer(msg); + } catch (Exception e) { + String msg = "Failed to attach volume" + " for uuid: " + data.getPath() + " due to " + e.getMessage(); + s_logger.warn(msg, e); + return new AttachAnswer(msg); + } + } + + @Override + public Answer dettachIso(DettachCommand cmd) { + DiskTO disk = cmd.getDisk(); + DataTO data = disk.getData(); + DataStoreTO store = data.getDataStore(); + + String isoURL = null; + if (store == null) { + TemplateObjectTO iso = (TemplateObjectTO)disk.getData(); + isoURL = iso.getName(); + } else { + if (!(store instanceof NfsTO)) { + s_logger.debug("Can't attach a iso which is not created on nfs: "); + return new AttachAnswer("Can't attach a iso which is not created on nfs: "); + } + NfsTO nfsStore = (NfsTO)store; + isoURL = nfsStore.getUrl() + File.separator + data.getPath(); + } + + try { + Connection conn = this.hypervisorResource.getConnection(); + // Find the VM + VM vm = this.hypervisorResource.getVM(conn, cmd.getVmName()); + String vmUUID = vm.getUuid(conn); + + // Find the ISO VDI + VDI isoVDI = this.hypervisorResource.getIsoVDIByURL(conn, cmd.getVmName(), isoURL); + + SR sr = isoVDI.getSR(conn); + + // Look up all VBDs for this VDI + Set vbds = isoVDI.getVBDs(conn); + + // Iterate through VBDs, and if the VBD belongs the VM, eject + // the ISO from it + for (VBD vbd : vbds) { + VM vbdVM = vbd.getVM(conn); + String vbdVmUUID = vbdVM.getUuid(conn); + + if (vbdVmUUID.equals(vmUUID)) { + // If an ISO is already inserted, eject it + if (!vbd.getEmpty(conn)) { + vbd.eject(conn); + } + break; + } + } + + if (!sr.getNameLabel(conn).startsWith("XenServer Tools")) { + this.hypervisorResource.removeSR(conn, sr); + } + + return new DettachAnswer(disk); + } catch (XenAPIException e) { + String msg = "Failed to dettach volume" + " for uuid: " + data.getPath() + " due to " + e.toString(); + s_logger.warn(msg, e); + return new DettachAnswer(msg); + } catch (Exception e) { + String msg = "Failed to dettach volume" + " for uuid: " + data.getPath() + " due to " + e.getMessage(); + s_logger.warn(msg, e); + return new DettachAnswer(msg); + } + } + + + @Override + public Answer dettachVolume(DettachCommand cmd) { + String vmName = cmd.getVmName(); + DiskTO disk = cmd.getDisk(); + DataTO data = disk.getData(); + try { + Connection conn = this.hypervisorResource.getConnection(); + // Look up the VDI + VDI vdi = this.hypervisorResource.mount(conn, null, null, data.getPath()); + // Look up the VM + VM vm = this.hypervisorResource.getVM(conn, vmName); + /* For HVM guest, if no pv driver installed, no attach/detach */ + boolean isHVM; + if (vm.getPVBootloader(conn).equalsIgnoreCase("")) { + isHVM = true; + } else { + isHVM = false; + } + VMGuestMetrics vgm = vm.getGuestMetrics(conn); + boolean pvDrvInstalled = false; + if (!this.hypervisorResource.isRefNull(vgm) && vgm.getPVDriversUpToDate(conn)) { + pvDrvInstalled = true; + } + if (isHVM && !pvDrvInstalled) { + s_logger.warn(": You attempted an operation on a VM which requires PV drivers to be installed but the drivers were not detected"); + return new DettachAnswer("You attempted an operation that requires PV drivers to be installed on the VM. Please install them by inserting xen-pv-drv.iso."); + } + + + // Look up all VBDs for this VDI + Set vbds = vdi.getVBDs(conn); + + // Detach each VBD from its VM, and then destroy it + for (VBD vbd : vbds) { + VBD.Record vbdr = vbd.getRecord(conn); + + if (vbdr.currentlyAttached) { + vbd.unplug(conn); + } + + vbd.destroy(conn); + } + + // Update the VDI's label to be "detached" + vdi.setNameLabel(conn, "detached"); + + this.hypervisorResource.umount(conn, vdi); + + return new DettachAnswer(disk); + } catch(Exception e) { + s_logger.warn("Failed dettach volume: " + data.getPath()); + return new DettachAnswer("Failed dettach volume: " + data.getPath() + ", due to " + e.toString()); + } + } + + + protected SR getSRByNameLabel(Connection conn, String nameLabel) throws BadServerResponse, XenAPIException, XmlRpcException { + Set srs = SR.getByNameLabel(conn, nameLabel); + if (srs.size() != 1) { + throw new CloudRuntimeException("storage uuid: " + nameLabel + " is not unique"); + } + SR poolsr = srs.iterator().next(); + return poolsr; + } + + protected VDI createVdi(Connection conn, String vdiName, SR sr, long size) throws BadServerResponse, XenAPIException, XmlRpcException { + VDI.Record vdir = new VDI.Record(); + vdir.nameLabel = vdiName; + vdir.SR = sr; + vdir.type = Types.VdiType.USER; + + vdir.virtualSize = size; + VDI vdi = VDI.create(conn, vdir); + return vdi; + } + + protected void deleteVDI(Connection conn, VDI vdi) throws BadServerResponse, XenAPIException, XmlRpcException { + vdi.destroy(conn); + } + + @Override + public Answer createSnapshot(CreateObjectCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + SnapshotObjectTO snapshotTO = (SnapshotObjectTO)cmd.getData(); + long snapshotId = snapshotTO.getId(); + String snapshotName = snapshotTO.getName(); + String details = "create snapshot operation Failed for snapshotId: " + snapshotId; + String snapshotUUID = null; + + try { + String volumeUUID = snapshotTO.getVolume().getPath(); + VDI volume = VDI.getByUuid(conn, volumeUUID); + + VDI snapshot = volume.snapshot(conn, new HashMap()); + + if (snapshotName != null) { + snapshot.setNameLabel(conn, snapshotName); + } + + snapshotUUID = snapshot.getUuid(conn); + String preSnapshotUUID = snapshotTO.getParentSnapshotPath(); + //check if it is a empty snapshot + if( preSnapshotUUID != null) { + SR sr = volume.getSR(conn); + String srUUID = sr.getUuid(conn); + String type = sr.getType(conn); + Boolean isISCSI = IsISCSI(type); + String snapshotParentUUID = getVhdParent(conn, srUUID, snapshotUUID, isISCSI); + + String preSnapshotParentUUID = getVhdParent(conn, srUUID, preSnapshotUUID, isISCSI); + if( snapshotParentUUID != null && snapshotParentUUID.equals(preSnapshotParentUUID)) { + // this is empty snapshot, remove it + snapshot.destroy(conn); + snapshotUUID = preSnapshotUUID; + } + } + SnapshotObjectTO newSnapshot = new SnapshotObjectTO(); + newSnapshot.setPath(snapshotUUID); + return new CreateObjectAnswer(newSnapshot); + } catch (XenAPIException e) { + details += ", reason: " + e.toString(); + s_logger.warn(details, e); + } catch (Exception e) { + details += ", reason: " + e.toString(); + s_logger.warn(details, e); + } + + return new CreateObjectAnswer(details); + } + + @Override + public Answer deleteVolume(DeleteCommand cmd) { + DataTO volume = cmd.getData(); + Connection conn = hypervisorResource.getConnection(); + String errorMsg = null; + try { + VDI vdi = VDI.getByUuid(conn, volume.getPath()); + deleteVDI(conn, vdi); + return new Answer(null); + } catch (BadServerResponse e) { + s_logger.debug("Failed to delete volume", e); + errorMsg = e.toString(); + } catch (XenAPIException e) { + s_logger.debug("Failed to delete volume", e); + errorMsg = e.toString(); + } catch (XmlRpcException e) { + s_logger.debug("Failed to delete volume", e); + errorMsg = e.toString(); + } + return new Answer(null, false, errorMsg); + } + + + protected SR getNfsSR(Connection conn, StorageFilerTO pool) { + Map deviceConfig = new HashMap(); + try { + String server = pool.getHost(); + String serverpath = pool.getPath(); + serverpath = serverpath.replace("//", "/"); + Set srs = SR.getAll(conn); + for (SR sr : srs) { + if (!SRType.NFS.equals(sr.getType(conn))) { + continue; + } + + Set pbds = sr.getPBDs(conn); + if (pbds.isEmpty()) { + continue; + } + + PBD pbd = pbds.iterator().next(); + + Map dc = pbd.getDeviceConfig(conn); + + if (dc == null) { + continue; + } + + if (dc.get("server") == null) { + continue; + } + + if (dc.get("serverpath") == null) { + continue; + } + + if (server.equals(dc.get("server")) && serverpath.equals(dc.get("serverpath"))) { + throw new CloudRuntimeException("There is a SR using the same configuration server:" + dc.get("server") + ", serverpath:" + + dc.get("serverpath") + " for pool " + pool.getUuid() + "on host:" + hypervisorResource.getHost().uuid); + } + + } + deviceConfig.put("server", server); + deviceConfig.put("serverpath", serverpath); + Host host = Host.getByUuid(conn, hypervisorResource.getHost().uuid); + SR sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), Long.toString(pool.getId()), SRType.NFS.toString(), "user", true, + new HashMap()); + sr.scan(conn); + return sr; + } catch (XenAPIException e) { + throw new CloudRuntimeException("Unable to create NFS SR " + pool.toString(), e); + } catch (XmlRpcException e) { + throw new CloudRuntimeException("Unable to create NFS SR " + pool.toString(), e); + } + } + + protected SR getIscsiSR(Connection conn, StorageFilerTO pool) { + synchronized (pool.getUuid().intern()) { + Map deviceConfig = new HashMap(); + try { + String target = pool.getHost(); + String path = pool.getPath(); + if (path.endsWith("/")) { + path = path.substring(0, path.length() - 1); + } + + String tmp[] = path.split("/"); + if (tmp.length != 3) { + String msg = "Wrong iscsi path " + pool.getPath() + " it should be /targetIQN/LUN"; + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + String targetiqn = tmp[1].trim(); + String lunid = tmp[2].trim(); + String scsiid = ""; + + Set srs = SR.getByNameLabel(conn, pool.getUuid()); + for (SR sr : srs) { + if (!SRType.LVMOISCSI.equals(sr.getType(conn))) { + continue; + } + Set pbds = sr.getPBDs(conn); + if (pbds.isEmpty()) { + continue; + } + PBD pbd = pbds.iterator().next(); + Map dc = pbd.getDeviceConfig(conn); + if (dc == null) { + continue; + } + if (dc.get("target") == null) { + continue; + } + if (dc.get("targetIQN") == null) { + continue; + } + if (dc.get("lunid") == null) { + continue; + } + if (target.equals(dc.get("target")) && targetiqn.equals(dc.get("targetIQN")) && lunid.equals(dc.get("lunid"))) { + throw new CloudRuntimeException("There is a SR using the same configuration target:" + dc.get("target") + ", targetIQN:" + + dc.get("targetIQN") + ", lunid:" + dc.get("lunid") + " for pool " + pool.getUuid() + "on host:" + this.hypervisorResource.getHost().uuid); + } + } + deviceConfig.put("target", target); + deviceConfig.put("targetIQN", targetiqn); + + Host host = Host.getByUuid(conn, this.hypervisorResource.getHost().uuid); + Map smConfig = new HashMap(); + String type = SRType.LVMOISCSI.toString(); + String poolId = Long.toString(pool.getId()); + SR sr = null; + try { + sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), poolId, type, "user", true, + smConfig); + } catch (XenAPIException e) { + String errmsg = e.toString(); + if (errmsg.contains("SR_BACKEND_FAILURE_107")) { + String lun[] = errmsg.split(""); + boolean found = false; + for (int i = 1; i < lun.length; i++) { + int blunindex = lun[i].indexOf("") + 7; + int elunindex = lun[i].indexOf(""); + String ilun = lun[i].substring(blunindex, elunindex); + ilun = ilun.trim(); + if (ilun.equals(lunid)) { + int bscsiindex = lun[i].indexOf("") + 8; + int escsiindex = lun[i].indexOf(""); + scsiid = lun[i].substring(bscsiindex, escsiindex); + scsiid = scsiid.trim(); + found = true; + break; + } + } + if (!found) { + String msg = "can not find LUN " + lunid + " in " + errmsg; + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + } else { + String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } + } + deviceConfig.put("SCSIid", scsiid); + + String result = SR.probe(conn, host, deviceConfig, type , smConfig); + String pooluuid = null; + if( result.indexOf("") != -1) { + pooluuid = result.substring(result.indexOf("") + 6, result.indexOf("")).trim(); + } + if( pooluuid == null || pooluuid.length() != 36) { + sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), poolId, type, "user", true, + smConfig); + } else { + sr = SR.introduce(conn, pooluuid, pool.getUuid(), poolId, + type, "user", true, smConfig); + Pool.Record pRec = XenServerConnectionPool.getPoolRecord(conn); + PBD.Record rec = new PBD.Record(); + rec.deviceConfig = deviceConfig; + rec.host = pRec.master; + rec.SR = sr; + PBD pbd = PBD.create(conn, rec); + pbd.plug(conn); + } + sr.scan(conn); + return sr; + } catch (XenAPIException e) { + String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } catch (Exception e) { + String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.getMessage(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } + } + } + protected Answer execute(CreateStoragePoolCommand cmd) { + Connection conn = this.hypervisorResource.getConnection(); + StorageFilerTO pool = cmd.getPool(); + try { + if (pool.getType() == StoragePoolType.NetworkFilesystem) { + getNfsSR(conn, pool); + } else if (pool.getType() == StoragePoolType.IscsiLUN) { + getIscsiSR(conn, pool); + } else if (pool.getType() == StoragePoolType.PreSetup) { + } else { + return new Answer(cmd, false, "The pool type: " + pool.getType().name() + " is not supported."); + } + return new Answer(cmd, true, "success"); + } catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + ", create StoragePool failed due to " + e.toString() + " on host:" + this.hypervisorResource.getHost().uuid + " pool: " + pool.getHost() + pool.getPath(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } + + } + + protected Answer directDownloadHttpTemplate(CopyCommand cmd, DecodedDataObject srcObj, DecodedDataObject destObj) { + Connection conn = hypervisorResource.getConnection(); + SR poolsr = null; + VDI vdi = null; + boolean result = false; + try { + if (destObj.getPath() == null) { + //need to create volume at first + + } + vdi = VDI.getByUuid(conn, destObj.getPath()); + if (vdi == null) { + throw new CloudRuntimeException("can't find volume: " + destObj.getPath()); + } + String destStoreUuid = destObj.getStore().getUuid(); + Set srs = SR.getByNameLabel(conn, destStoreUuid); + if (srs.size() != 1) { + throw new CloudRuntimeException("storage uuid: " + destStoreUuid + " is not unique"); + } + poolsr = srs.iterator().next(); + VDI.Record vdir = vdi.getRecord(conn); + String vdiLocation = vdir.location; + String pbdLocation = null; + if (destObj.getStore().getScheme().equalsIgnoreCase(DataStoreProtocol.NFS.toString())) { + pbdLocation = "/run/sr-mount/" + poolsr.getUuid(conn); + } else { + Set pbds = poolsr.getPBDs(conn); + if (pbds.size() != 1) { + throw new CloudRuntimeException("Don't how to handle multiple pbds:" + pbds.size() + " for sr: " + poolsr.getUuid(conn)); + } + PBD pbd = pbds.iterator().next(); + Map deviceCfg = pbd.getDeviceConfig(conn); + pbdLocation = deviceCfg.get("location"); + } + if (pbdLocation == null) { + throw new CloudRuntimeException("Can't get pbd location"); + } + + String vdiPath = pbdLocation + "/" + vdiLocation + ".vhd"; + //download a url into vdipath + //downloadHttpToLocalFile(vdiPath, template.getPath()); + hypervisorResource.callHostPlugin(conn, "storagePlugin", "downloadTemplateFromUrl", "destPath", vdiPath, "srcUrl", srcObj.getPath()); + result = true; + //return new CopyCmdAnswer(cmd, vdi.getUuid(conn)); + } catch (BadServerResponse e) { + s_logger.debug("Failed to download template", e); + } catch (XenAPIException e) { + s_logger.debug("Failed to download template", e); + } catch (XmlRpcException e) { + s_logger.debug("Failed to download template", e); + } catch (Exception e) { + s_logger.debug("Failed to download template", e); + } finally { + if (!result && vdi != null) { + try { + vdi.destroy(conn); + } catch (BadServerResponse e) { + s_logger.debug("Failed to cleanup newly created vdi"); + } catch (XenAPIException e) { + s_logger.debug("Failed to cleanup newly created vdi"); + } catch (XmlRpcException e) { + s_logger.debug("Failed to cleanup newly created vdi"); + } + } + } + return new Answer(cmd, false, "Failed to download template"); + } + + protected Answer execute(AttachPrimaryDataStoreCmd cmd) { + String dataStoreUri = cmd.getDataStore(); + Connection conn = hypervisorResource.getConnection(); + try { + DecodedDataObject obj = Decoder.decode(dataStoreUri); + + DecodedDataStore store = obj.getStore(); + + SR sr = hypervisorResource.getStorageRepository(conn, store.getUuid()); + hypervisorResource.setupHeartbeatSr(conn, sr, false); + long capacity = sr.getPhysicalSize(conn); + long available = capacity - sr.getPhysicalUtilisation(conn); + if (capacity == -1) { + String msg = "Pool capacity is -1! pool: "; + s_logger.warn(msg); + return new Answer(cmd, false, msg); + } + AttachPrimaryDataStoreAnswer answer = new AttachPrimaryDataStoreAnswer(cmd); + answer.setCapacity(capacity); + answer.setUuid(sr.getUuid(conn)); + answer.setAvailable(available); + return answer; + } catch (XenAPIException e) { + String msg = "AttachPrimaryDataStoreCmd add XenAPIException:" + e.toString(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } catch (Exception e) { + String msg = "AttachPrimaryDataStoreCmd failed:" + e.getMessage(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } + } + + private boolean IsISCSI(String type) { + return SRType.LVMOHBA.equals(type) || SRType.LVMOISCSI.equals(type) || SRType.LVM.equals(type) ; + } + + private String copy_vhd_from_secondarystorage(Connection conn, String mountpoint, String sruuid, int wait) { + String nameLabel = "cloud-" + UUID.randomUUID().toString(); + String results = hypervisorResource.callHostPluginAsync(conn, "vmopspremium", "copy_vhd_from_secondarystorage", + wait, "mountpoint", mountpoint, "sruuid", sruuid, "namelabel", nameLabel); + String errMsg = null; + if (results == null || results.isEmpty()) { + errMsg = "copy_vhd_from_secondarystorage return null"; + } else { + String[] tmp = results.split("#"); + String status = tmp[0]; + if (status.equals("0")) { + return tmp[1]; + } else { + errMsg = tmp[1]; + } + } + String source = mountpoint.substring(mountpoint.lastIndexOf('/') + 1); + if( hypervisorResource.killCopyProcess(conn, source) ) { + destroyVDIbyNameLabel(conn, nameLabel); + } + s_logger.warn(errMsg); + throw new CloudRuntimeException(errMsg); + } + + private void destroyVDIbyNameLabel(Connection conn, String nameLabel) { + try { + Set vdis = VDI.getByNameLabel(conn, nameLabel); + if ( vdis.size() != 1 ) { + s_logger.warn("destoryVDIbyNameLabel failed due to there are " + vdis.size() + " VDIs with name " + nameLabel); + return; + } + for (VDI vdi : vdis) { + try { + vdi.destroy(conn); + } catch (Exception e) { + } + } + } catch (Exception e){ + } + } + + protected VDI getVDIbyUuid(Connection conn, String uuid) { + try { + return VDI.getByUuid(conn, uuid); + } catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + " :VDI getByUuid for uuid: " + uuid + " failed due to " + e.toString(); + s_logger.debug(msg); + throw new CloudRuntimeException(msg, e); + } + } + + protected String getVhdParent(Connection conn, String primaryStorageSRUuid, String snapshotUuid, Boolean isISCSI) { + String parentUuid = hypervisorResource.callHostPlugin(conn, "vmopsSnapshot", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid, + "snapshotUuid", snapshotUuid, "isISCSI", isISCSI.toString()); + + if (parentUuid == null || parentUuid.isEmpty() || parentUuid.equalsIgnoreCase("None")) { + s_logger.debug("Unable to get parent of VHD " + snapshotUuid + " in SR " + primaryStorageSRUuid); + // errString is already logged. + return null; + } + return parentUuid; + } + + @Override + public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) { + DataTO srcData = cmd.getSrcTO(); + DataTO destData = cmd.getDestTO(); + int wait = cmd.getWait(); + DataStoreTO srcStore = srcData.getDataStore(); + try { + if ((srcStore instanceof NfsTO) && (srcData.getObjectType() == DataObjectType.TEMPLATE)) { + NfsTO srcImageStore = (NfsTO)srcStore; + TemplateObjectTO srcTemplate = (TemplateObjectTO)srcData; + String storeUrl = srcImageStore.getUrl(); + + URI uri = new URI(storeUrl); + String tmplpath = uri.getHost() + ":" + uri.getPath() + "/" + srcData.getPath(); + PrimaryDataStoreTO destStore = (PrimaryDataStoreTO)destData.getDataStore(); + String poolName = destStore.getUuid(); + Connection conn = hypervisorResource.getConnection(); + + SR poolsr = null; + Set srs = SR.getByNameLabel(conn, poolName); + if (srs.size() != 1) { + String msg = "There are " + srs.size() + " SRs with same name: " + poolName; + s_logger.warn(msg); + return new CopyCmdAnswer(msg); + } else { + poolsr = srs.iterator().next(); + } + String pUuid = poolsr.getUuid(conn); + boolean isISCSI = IsISCSI(poolsr.getType(conn)); + String uuid = copy_vhd_from_secondarystorage(conn, tmplpath, pUuid, wait); + VDI tmpl = getVDIbyUuid(conn, uuid); + VDI snapshotvdi = tmpl.snapshot(conn, new HashMap()); + String snapshotUuid = snapshotvdi.getUuid(conn); + snapshotvdi.setNameLabel(conn, "Template " + srcTemplate.getName()); + String parentuuid = getVhdParent(conn, pUuid, snapshotUuid, isISCSI); + VDI parent = getVDIbyUuid(conn, parentuuid); + Long phySize = parent.getPhysicalUtilisation(conn); + tmpl.destroy(conn); + poolsr.scan(conn); + try{ + Thread.sleep(5000); + } catch (Exception e) { + } + + TemplateObjectTO newVol = new TemplateObjectTO(); + newVol.setUuid(snapshotvdi.getUuid(conn)); + newVol.setPath(newVol.getUuid()); + newVol.setFormat(ImageFormat.VHD); + return new CopyCmdAnswer(newVol); + } + }catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + " for template + " + " due to " + e.toString(); + s_logger.warn(msg, e); + return new CopyCmdAnswer(msg); + } + return new CopyCmdAnswer("not implemented yet"); + } + + @Override + public Answer createVolume(CreateObjectCommand cmd) { + DataTO data = cmd.getData(); + VolumeObjectTO volume = (VolumeObjectTO)data; + + try { + Connection conn = hypervisorResource.getConnection(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)data.getDataStore(); + SR poolSr = hypervisorResource.getStorageRepository(conn, primaryStore.getUuid()); + VDI.Record vdir = new VDI.Record(); + vdir.nameLabel = volume.getName(); + vdir.SR = poolSr; + vdir.type = Types.VdiType.USER; + + vdir.virtualSize = volume.getSize(); + VDI vdi; + + vdi = VDI.create(conn, vdir); + vdir = vdi.getRecord(conn); + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setName(vdir.nameLabel); + newVol.setSize(vdir.virtualSize); + newVol.setPath(vdir.uuid); + + return new CreateObjectAnswer(newVol); + } catch (Exception e) { + s_logger.debug("create volume failed: " + e.toString()); + return new CreateObjectAnswer(e.toString()); + } + } + + @Override + public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + DataTO srcData = cmd.getSrcTO(); + DataTO destData = cmd.getDestTO(); + PrimaryDataStoreTO pool = (PrimaryDataStoreTO)destData.getDataStore(); + VolumeObjectTO volume = (VolumeObjectTO)destData; + VDI vdi = null; + try { + VDI tmpltvdi = null; + + tmpltvdi = getVDIbyUuid(conn, srcData.getPath()); + vdi = tmpltvdi.createClone(conn, new HashMap()); + vdi.setNameLabel(conn, volume.getName()); + + + VDI.Record vdir; + vdir = vdi.getRecord(conn); + s_logger.debug("Succesfully created VDI: Uuid = " + vdir.uuid); + + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setName(vdir.nameLabel); + newVol.setSize(vdir.virtualSize); + newVol.setPath(vdir.uuid); + + return new CopyCmdAnswer(newVol); + } catch (Exception e) { + s_logger.warn("Unable to create volume; Pool=" + pool + "; Disk: ", e); + return new CopyCmdAnswer(e.toString()); + } + } + + @Override + public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + DataTO srcData = cmd.getSrcTO(); + DataTO destData = cmd.getDestTO(); + int wait = cmd.getWait(); + VolumeObjectTO srcVolume = (VolumeObjectTO)srcData; + VolumeObjectTO destVolume = (VolumeObjectTO)destData; + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)destVolume.getDataStore(); + DataStoreTO srcStore = srcVolume.getDataStore(); + + if (srcStore instanceof NfsTO) { + NfsTO nfsStore = (NfsTO)srcStore; + try { + SR primaryStoragePool = hypervisorResource.getStorageRepository(conn, primaryStore.getUuid()); + String srUuid = primaryStoragePool.getUuid(conn); + URI uri = new URI(nfsStore.getUrl()); + String volumePath = uri.getHost() + ":" + uri.getPath() + File.separator + srcVolume.getPath(); + String uuid = copy_vhd_from_secondarystorage(conn, volumePath, srUuid, wait ); + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(uuid); + newVol.setSize(srcVolume.getSize()); + + return new CopyCmdAnswer(newVol); + } catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString(); + s_logger.warn(msg, e); + return new CopyCmdAnswer(e.toString()); + } + } + + s_logger.debug("unsupported protocol"); + return new CopyCmdAnswer("unsupported protocol"); + } + + @Override + public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + VolumeObjectTO srcVolume = (VolumeObjectTO)cmd.getSrcTO(); + VolumeObjectTO destVolume = (VolumeObjectTO)cmd.getDestTO(); + int wait = cmd.getWait(); + DataStoreTO destStore = destVolume.getDataStore(); + + if (destStore instanceof NfsTO) { + SR secondaryStorage = null; + try { + NfsTO nfsStore = (NfsTO)destStore; + URI uri = new URI(nfsStore.getUrl()); + // Create the volume folder + if (!hypervisorResource.createSecondaryStorageFolder(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath())) { + throw new InternalErrorException("Failed to create the volume folder."); + } + + // Create a SR for the volume UUID folder + secondaryStorage = hypervisorResource.createNfsSRbyURI(conn, new URI(nfsStore.getUrl() + File.separator + destVolume.getPath()), false); + // Look up the volume on the source primary storage pool + VDI srcVdi = getVDIbyUuid(conn, srcVolume.getPath()); + // Copy the volume to secondary storage + VDI destVdi = hypervisorResource.cloudVDIcopy(conn, srcVdi, secondaryStorage, wait); + String destVolumeUUID = destVdi.getUuid(conn); + + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(destVolume.getPath() + File.separator + destVolumeUUID + ".vhd"); + newVol.setSize(srcVolume.getSize()); + return new CopyCmdAnswer(newVol); + } catch (Exception e) { + s_logger.debug("Failed to copy volume to secondary: " + e.toString()); + return new CopyCmdAnswer("Failed to copy volume to secondary: " + e.toString()); + } finally { + hypervisorResource.removeSR(conn, secondaryStorage); + } + } + return new CopyCmdAnswer("unsupported protocol"); + } + + boolean swiftUpload(Connection conn, SwiftTO swift, String container, String ldir, String lfilename, Boolean isISCSI, int wait) { + String result = null; + try { + result = hypervisorResource.callHostPluginAsync(conn, "swiftxen", "swift", wait, + "op", "upload", "url", swift.getUrl(), "account", swift.getAccount(), + "username", swift.getUserName(), "key", swift.getKey(), "container", container, + "ldir", ldir, "lfilename", lfilename, "isISCSI", isISCSI.toString()); + if( result != null && result.equals("true")) { + return true; + } + } catch (Exception e) { + s_logger.warn("swift upload failed due to " + e.toString(), e); + } + return false; + } + + protected String deleteSnapshotBackup(Connection conn, String path, String secondaryStorageMountPath, String backupUUID) { + + // If anybody modifies the formatting below again, I'll skin them + String result = hypervisorResource.callHostPlugin(conn, "vmopsSnapshot", "deleteSnapshotBackup", "backupUUID", backupUUID, "path", path, "secondaryStorageMountPath", secondaryStorageMountPath); + + return result; + } + + public void swiftBackupSnapshot(Connection conn, SwiftTO swift, String srUuid, String snapshotUuid, String container, Boolean isISCSI, int wait) { + String lfilename; + String ldir; + if ( isISCSI ) { + ldir = "/dev/VG_XenStorage-" + srUuid; + lfilename = "VHD-" + snapshotUuid; + } else { + ldir = "/var/run/sr-mount/" + srUuid; + lfilename = snapshotUuid + ".vhd"; + } + swiftUpload(conn, swift, container, ldir, lfilename, isISCSI, wait); + } + + private static List serializeProperties(final Object object, + final Class propertySet) { + + assert object != null; + assert propertySet != null; + assert propertySet.isAssignableFrom(object.getClass()); + + try { + + final BeanInfo beanInfo = Introspector.getBeanInfo(propertySet); + final PropertyDescriptor[] descriptors = beanInfo + .getPropertyDescriptors(); + + final List serializedProperties = new ArrayList(); + for (final PropertyDescriptor descriptor : descriptors) { + + serializedProperties.add(descriptor.getName()); + final Object value = descriptor.getReadMethod().invoke(object); + serializedProperties.add(value != null ? value.toString() + : "null"); + + } + + return Collections.unmodifiableList(serializedProperties); + + } catch (IntrospectionException e) { + s_logger.warn( + "Ignored IntrospectionException when serializing class " + + object.getClass().getCanonicalName(), e); + } catch (IllegalArgumentException e) { + s_logger.warn( + "Ignored IllegalArgumentException when serializing class " + + object.getClass().getCanonicalName(), e); + } catch (IllegalAccessException e) { + s_logger.warn( + "Ignored IllegalAccessException when serializing class " + + object.getClass().getCanonicalName(), e); + } catch (InvocationTargetException e) { + s_logger.warn( + "Ignored InvocationTargetException when serializing class " + + object.getClass().getCanonicalName(), e); + } + + return Collections.emptyList(); + + } + + private boolean backupSnapshotToS3(final Connection connection, + final S3TO s3, final String srUuid, final String snapshotUuid, + final Boolean iSCSIFlag, final int wait) { + + final String filename = iSCSIFlag ? "VHD-" + snapshotUuid + : snapshotUuid + ".vhd"; + final String dir = (iSCSIFlag ? "/dev/VG_XenStorage-" + : "/var/run/sr-mount/") + srUuid; + final String key = StringUtils.join("/", "snapshots", snapshotUuid); + + try { + + final List parameters = new ArrayList( + serializeProperties(s3, S3Utils.ClientOptions.class)); + parameters.addAll(Arrays.asList("operation", "put", "directory", + dir, "filename", filename, "iSCSIFlag", + iSCSIFlag.toString(), "key", key)); + final String result = hypervisorResource.callHostPluginAsync(connection, "s3xen", + "s3", wait, + parameters.toArray(new String[parameters.size()])); + + if (result != null && result.equals("true")) { + return true; + } + + } catch (Exception e) { + s_logger.error(String.format( + "S3 upload failed of snapshot %1$s due to %2$s.", + snapshotUuid, e.toString()), e); + } + + return false; + + } + + protected String backupSnapshot(Connection conn, String primaryStorageSRUuid, String path, String secondaryStorageMountPath, String snapshotUuid, String prevBackupUuid, Boolean isISCSI, int wait) { + String backupSnapshotUuid = null; + + if (prevBackupUuid == null) { + prevBackupUuid = ""; + } + + // Each argument is put in a separate line for readability. + // Using more lines does not harm the environment. + String backupUuid = UUID.randomUUID().toString(); + String results = hypervisorResource.callHostPluginAsync(conn, "vmopsSnapshot", "backupSnapshot", wait, + "primaryStorageSRUuid", primaryStorageSRUuid, "path", path, "secondaryStorageMountPath", secondaryStorageMountPath, + "snapshotUuid", snapshotUuid, "prevBackupUuid", prevBackupUuid, "backupUuid", backupUuid, "isISCSI", isISCSI.toString()); + String errMsg = null; + if (results == null || results.isEmpty()) { + errMsg = "Could not copy backupUuid: " + backupSnapshotUuid + + " from primary storage " + primaryStorageSRUuid + " to secondary storage " + + secondaryStorageMountPath + " due to null"; + } else { + + String[] tmp = results.split("#"); + String status = tmp[0]; + backupSnapshotUuid = tmp[1]; + // status == "1" if and only if backupSnapshotUuid != null + // So we don't rely on status value but return backupSnapshotUuid as an + // indicator of success. + if (status != null && status.equalsIgnoreCase("1") && backupSnapshotUuid != null) { + s_logger.debug("Successfully copied backupUuid: " + backupSnapshotUuid + + " to secondary storage"); + return backupSnapshotUuid; + } else { + errMsg = "Could not copy backupUuid: " + backupSnapshotUuid + + " from primary storage " + primaryStorageSRUuid + " to secondary storage " + + secondaryStorageMountPath + " due to " + tmp[1]; + } + } + String source = backupUuid + ".vhd"; + hypervisorResource.killCopyProcess(conn, source); + s_logger.warn(errMsg); + return null; + + } + + private boolean destroySnapshotOnPrimaryStorageExceptThis(Connection conn, String volumeUuid, String avoidSnapshotUuid){ + try { + VDI volume = getVDIbyUuid(conn, volumeUuid); + if (volume == null) { + throw new InternalErrorException("Could not destroy snapshot on volume " + volumeUuid + " due to can not find it"); + } + Set snapshots = volume.getSnapshots(conn); + for( VDI snapshot : snapshots ) { + try { + if(! snapshot.getUuid(conn).equals(avoidSnapshotUuid)) { + snapshot.destroy(conn); + } + } catch (Exception e) { + String msg = "Destroying snapshot: " + snapshot+ " on primary storage failed due to " + e.toString(); + s_logger.warn(msg, e); + } + } + s_logger.debug("Successfully destroyed snapshot on volume: " + volumeUuid + " execept this current snapshot "+ avoidSnapshotUuid ); + return true; + } catch (XenAPIException e) { + String msg = "Destroying snapshot on volume: " + volumeUuid + " execept this current snapshot "+ avoidSnapshotUuid + " failed due to " + e.toString(); + s_logger.error(msg, e); + } catch (Exception e) { + String msg = "Destroying snapshot on volume: " + volumeUuid + " execept this current snapshot "+ avoidSnapshotUuid + " failed due to " + e.toString(); + s_logger.warn(msg, e); + } + + return false; + } + + @Override + public Answer backupSnasphot(CopyCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + DataTO srcData = cmd.getSrcTO(); + DataTO cacheData = cmd.getCacheTO(); + DataTO destData = cmd.getDestTO(); + int wait = cmd.getWait(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)srcData.getDataStore(); + String primaryStorageNameLabel = primaryStore.getUuid(); + String secondaryStorageUrl = null; + NfsTO cacheStore = null; + String destPath = null; + if (cacheData != null) { + cacheStore = (NfsTO)cacheData.getDataStore(); + secondaryStorageUrl = cacheStore.getUrl(); + destPath = cacheData.getPath(); + } else { + cacheStore = (NfsTO)destData.getDataStore(); + secondaryStorageUrl = cacheStore.getUrl(); + destPath = destData.getPath(); + } + + SnapshotObjectTO snapshotTO = (SnapshotObjectTO)srcData; + SnapshotObjectTO snapshotOnImage = (SnapshotObjectTO)destData; + String snapshotUuid = snapshotTO.getPath(); + + String prevBackupUuid = snapshotOnImage.getParentSnapshotPath(); + String prevSnapshotUuid = snapshotTO.getParentSnapshotPath(); + + // By default assume failure + String details = null; + String snapshotBackupUuid = null; + boolean fullbackup = true; + try { + SR primaryStorageSR = hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel); + if (primaryStorageSR == null) { + throw new InternalErrorException("Could not backup snapshot because the primary Storage SR could not be created from the name label: " + primaryStorageNameLabel); + } + String psUuid = primaryStorageSR.getUuid(conn); + Boolean isISCSI = IsISCSI(primaryStorageSR.getType(conn)); + + VDI snapshotVdi = getVDIbyUuid(conn, snapshotUuid); + String snapshotPaUuid = null; + if ( prevBackupUuid != null ) { + try { + snapshotPaUuid = getVhdParent(conn, psUuid, snapshotUuid, isISCSI); + if( snapshotPaUuid != null ) { + String snashotPaPaPaUuid = getVhdParent(conn, psUuid, snapshotPaUuid, isISCSI); + String prevSnashotPaUuid = getVhdParent(conn, psUuid, prevSnapshotUuid, isISCSI); + if (snashotPaPaPaUuid != null && prevSnashotPaUuid!= null && prevSnashotPaUuid.equals(snashotPaPaPaUuid)) { + fullbackup = false; + } + } + } catch (Exception e) { + } + } + + URI uri = new URI(secondaryStorageUrl); + String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); + DataStoreTO destStore = destData.getDataStore(); + String folder = destPath; + if (fullbackup) { + // the first snapshot is always a full snapshot + + if( !hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, folder)) { + details = " Filed to create folder " + folder + " in secondary storage"; + s_logger.warn(details); + return new CopyCmdAnswer(details); + } + String snapshotMountpoint = secondaryStorageUrl + "/" + folder; + SR snapshotSr = null; + try { + snapshotSr = hypervisorResource.createNfsSRbyURI(conn, new URI(snapshotMountpoint), false); + VDI backedVdi = hypervisorResource.cloudVDIcopy(conn, snapshotVdi, snapshotSr, wait); + snapshotBackupUuid = backedVdi.getUuid(conn); + + if( destStore instanceof SwiftTO) { + try { + hypervisorResource.swiftBackupSnapshot(conn, (SwiftTO)destStore, snapshotSr.getUuid(conn), snapshotBackupUuid, "S-" + snapshotTO.getVolume().getVolumeId().toString(), false, wait); + snapshotBackupUuid = snapshotBackupUuid + ".vhd"; + } finally { + deleteSnapshotBackup(conn, folder, secondaryStorageMountPath, snapshotBackupUuid); + } + } else if (destStore instanceof S3TO) { + try { + backupSnapshotToS3(conn, (S3TO)destStore, snapshotSr.getUuid(conn), snapshotBackupUuid, isISCSI, wait); + snapshotBackupUuid = snapshotBackupUuid + ".vhd"; + } finally { + deleteSnapshotBackup(conn, folder, secondaryStorageMountPath, snapshotBackupUuid); + } + } + + } finally { + if( snapshotSr != null) { + hypervisorResource.removeSR(conn, snapshotSr); + } + } + } else { + String primaryStorageSRUuid = primaryStorageSR.getUuid(conn); + if( destStore instanceof SwiftTO ) { + swiftBackupSnapshot(conn, (SwiftTO)destStore, primaryStorageSRUuid, snapshotPaUuid, "S-" + snapshotTO.getVolume().getVolumeId().toString(), isISCSI, wait); + if ( isISCSI ) { + snapshotBackupUuid = "VHD-" + snapshotPaUuid; + } else { + snapshotBackupUuid = snapshotPaUuid + ".vhd"; + } + + } else if (destStore instanceof S3TO ) { + backupSnapshotToS3(conn, (S3TO)destStore, primaryStorageSRUuid, snapshotPaUuid, isISCSI, wait); + } else { + snapshotBackupUuid = backupSnapshot(conn, primaryStorageSRUuid, folder + File.separator + UUID.nameUUIDFromBytes(secondaryStorageMountPath.getBytes()) + , secondaryStorageMountPath, snapshotUuid, prevBackupUuid, isISCSI, wait); + + } + } + String volumeUuid = snapshotTO.getVolume().getPath(); + destroySnapshotOnPrimaryStorageExceptThis(conn, volumeUuid, snapshotUuid); + + SnapshotObjectTO newSnapshot = new SnapshotObjectTO(); + newSnapshot.setPath(folder + File.separator + snapshotBackupUuid); + if (fullbackup) { + newSnapshot.setParentSnapshotPath(null); + } else { + newSnapshot.setParentSnapshotPath(prevBackupUuid); + } + return new CopyCmdAnswer(newSnapshot); + } catch (XenAPIException e) { + details = "BackupSnapshot Failed due to " + e.toString(); + s_logger.warn(details, e); + } catch (Exception e) { + details = "BackupSnapshot Failed due to " + e.getMessage(); + s_logger.warn(details, e); + } + + return new CopyCmdAnswer(details); + } + + @Override + public Answer createTemplateFromVolume(CopyCommand cmd) { + Connection conn = this.hypervisorResource.getConnection(); + VolumeObjectTO volume = (VolumeObjectTO)cmd.getSrcTO(); + TemplateObjectTO template = (TemplateObjectTO)cmd.getDestTO(); + NfsTO destStore = (NfsTO)cmd.getDestTO().getDataStore(); + int wait = cmd.getWait(); + + String secondaryStoragePoolURL = destStore.getUrl(); + String volumeUUID = volume.getPath(); + + String userSpecifiedName = template.getName(); + + + String details = null; + SR tmpltSR = null; + boolean result = false; + String secondaryStorageMountPath = null; + String installPath = null; + try { + URI uri = new URI(secondaryStoragePoolURL); + secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); + installPath = template.getPath(); + if( !this.hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath)) { + details = " Filed to create folder " + installPath + " in secondary storage"; + s_logger.warn(details); + return new CopyCmdAnswer(details); + } + + VDI vol = getVDIbyUuid(conn, volumeUUID); + // create template SR + URI tmpltURI = new URI(secondaryStoragePoolURL + "/" + installPath); + tmpltSR = this.hypervisorResource.createNfsSRbyURI(conn, tmpltURI, false); + + // copy volume to template SR + VDI tmpltVDI = this.hypervisorResource.cloudVDIcopy(conn, vol, tmpltSR, wait); + // scan makes XenServer pick up VDI physicalSize + tmpltSR.scan(conn); + if (userSpecifiedName != null) { + tmpltVDI.setNameLabel(conn, userSpecifiedName); + } + + String tmpltUUID = tmpltVDI.getUuid(conn); + String tmpltFilename = tmpltUUID + ".vhd"; + long virtualSize = tmpltVDI.getVirtualSize(conn); + long physicalSize = tmpltVDI.getPhysicalUtilisation(conn); + // create the template.properties file + String templatePath = secondaryStorageMountPath + "/" + installPath; + result = this.hypervisorResource.postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUUID, userSpecifiedName, null, physicalSize, virtualSize, template.getId()); + if (!result) { + throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir: " + tmpltURI); + } + installPath = installPath + "/" + tmpltFilename; + this.hypervisorResource.removeSR(conn, tmpltSR); + tmpltSR = null; + TemplateObjectTO newTemplate = new TemplateObjectTO(); + newTemplate.setPath(installPath); + newTemplate.setFormat(ImageFormat.VHD); + newTemplate.setSize(virtualSize); + CopyCmdAnswer answer = new CopyCmdAnswer(newTemplate); + return answer; + } catch (Exception e) { + if (tmpltSR != null) { + this.hypervisorResource.removeSR(conn, tmpltSR); + } + if ( secondaryStorageMountPath != null) { + this.hypervisorResource.deleteSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath); + } + details = "Creating template from volume " + volumeUUID + " failed due to " + e.toString(); + s_logger.error(details, e); + } + return new CopyCmdAnswer(details); + } + + @Override + public Answer createVolumeFromSnapshot(CopyCommand cmd) { + Connection conn = this.hypervisorResource.getConnection(); + DataTO srcData = cmd.getSrcTO(); + SnapshotObjectTO snapshot = (SnapshotObjectTO)srcData; + DataTO destData = cmd.getDestTO(); + PrimaryDataStoreTO pool = (PrimaryDataStoreTO)destData.getDataStore(); + DataStoreTO imageStore = srcData.getDataStore(); + + if (!(imageStore instanceof NfsTO)) { + return new CopyCmdAnswer("unsupported protocol"); + } + + NfsTO nfsImageStore = (NfsTO)imageStore; + String primaryStorageNameLabel = pool.getUuid(); + String secondaryStorageUrl = nfsImageStore.getUrl(); + int wait = cmd.getWait(); + boolean result = false; + // Generic error message. + String details = null; + String volumeUUID = null; + + if (secondaryStorageUrl == null) { + details += " because the URL passed: " + secondaryStorageUrl + " is invalid."; + return new CopyCmdAnswer(details); + } + try { + SR primaryStorageSR = this.hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel); + if (primaryStorageSR == null) { + throw new InternalErrorException("Could not create volume from snapshot because the primary Storage SR could not be created from the name label: " + + primaryStorageNameLabel); + } + // Get the absolute path of the snapshot on the secondary storage. + String snapshotInstallPath = snapshot.getPath(); + int index = snapshotInstallPath.lastIndexOf(File.separator); + String snapshotName = snapshotInstallPath.substring(index + 1); + + if (!snapshotName.startsWith("VHD-") && !snapshotName.endsWith(".vhd")) { + snapshotInstallPath = snapshotInstallPath + ".vhd"; + } + URI snapshotURI = new URI(secondaryStorageUrl + File.separator + snapshotInstallPath); + String snapshotPath = snapshotURI.getHost() + ":" + snapshotURI.getPath(); + String srUuid = primaryStorageSR.getUuid(conn); + volumeUUID = copy_vhd_from_secondarystorage(conn, snapshotPath, srUuid, wait); + result = true; + VDI volume = VDI.getByUuid(conn, volumeUUID); + VDI.Record vdir = volume.getRecord(conn); + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(volumeUUID); + newVol.setSize(vdir.virtualSize); + return new CopyCmdAnswer(newVol); + } catch (XenAPIException e) { + details += " due to " + e.toString(); + s_logger.warn(details, e); + } catch (Exception e) { + details += " due to " + e.getMessage(); + s_logger.warn(details, e); + } + if (!result) { + // Is this logged at a higher level? + s_logger.error(details); + } + + // In all cases return something. + return new CopyCmdAnswer(details); + } + + @Override + public Answer deleteSnapshot(DeleteCommand cmd) { + SnapshotObjectTO snapshot = (SnapshotObjectTO)cmd.getData(); + DataStoreTO store = snapshot.getDataStore(); + if (store.getRole() == DataStoreRole.Primary) { + Connection conn = this.hypervisorResource.getConnection(); + VDI snapshotVdi = getVDIbyUuid(conn, snapshot.getPath()); + if (snapshotVdi == null) { + return new Answer(null); + } + String errMsg = null; + try { + this.deleteVDI(conn, snapshotVdi); + } catch (BadServerResponse e) { + s_logger.debug("delete snapshot failed:" + e.toString()); + errMsg = e.toString(); + } catch (XenAPIException e) { + s_logger.debug("delete snapshot failed:" + e.toString()); + errMsg = e.toString(); + } catch (XmlRpcException e) { + s_logger.debug("delete snapshot failed:" + e.toString()); + errMsg = e.toString(); + } + return new Answer(cmd, false, errMsg); + } + return new Answer(cmd, false, "unsupported storage type"); + } +} diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java deleted file mode 100644 index 7e0ccbed39c..00000000000 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java +++ /dev/null @@ -1,662 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * 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, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package com.cloud.hypervisor.xen.resource; - -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreAnswer; -import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd; -import org.apache.cloudstack.storage.command.CopyCmd; -import org.apache.cloudstack.storage.command.CopyCmdAnswer; -import org.apache.cloudstack.storage.command.CreateObjectAnswer; -import org.apache.cloudstack.storage.command.CreateObjectCommand; -import org.apache.cloudstack.storage.command.CreatePrimaryDataStoreCmd; -import org.apache.cloudstack.storage.command.CreateVolumeFromBaseImageCommand; -import org.apache.cloudstack.storage.command.StorageSubSystemCommand; -import org.apache.cloudstack.storage.datastore.protocol.DataStoreProtocol; -import org.apache.cloudstack.storage.to.ImageOnPrimaryDataStoreTO; -import org.apache.cloudstack.storage.to.VolumeTO; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.log4j.Logger; -import org.apache.xmlrpc.XmlRpcException; - -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.Command; -import com.cloud.agent.api.storage.DeleteVolumeCommand; -import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.storage.encoding.DecodedDataObject; -import com.cloud.utils.storage.encoding.DecodedDataStore; -import com.cloud.utils.storage.encoding.Decoder; -import com.xensource.xenapi.Connection; -import com.xensource.xenapi.Host; -import com.xensource.xenapi.PBD; -import com.xensource.xenapi.SR; -import com.xensource.xenapi.Types; -import com.xensource.xenapi.Types.BadServerResponse; -import com.xensource.xenapi.Types.XenAPIException; -import com.xensource.xenapi.VDI; - -import edu.emory.mathcs.backport.java.util.Arrays; - -public class XenServerStorageResource { - private static final Logger s_logger = Logger.getLogger(XenServerStorageResource.class); - protected CitrixResourceBase hypervisorResource; - - public XenServerStorageResource(CitrixResourceBase resource) { - this.hypervisorResource = resource; - } - - public Answer handleStorageCommands(StorageSubSystemCommand command) { - if (command instanceof CopyCmd) { - return this.execute((CopyCmd)command); - } else if (command instanceof AttachPrimaryDataStoreCmd) { - return this.execute((AttachPrimaryDataStoreCmd)command); - } else if (command instanceof CreatePrimaryDataStoreCmd) { - return execute((CreatePrimaryDataStoreCmd) command); - } else if (command instanceof CreateVolumeFromBaseImageCommand) { - return execute((CreateVolumeFromBaseImageCommand)command); - } else if (command instanceof CreateObjectCommand) { - return execute((CreateObjectCommand) command); - } else if (command instanceof DeleteVolumeCommand) { - return execute((DeleteVolumeCommand)command); - } - return new Answer((Command)command, false, "not implemented yet"); - } - - protected SR getSRByNameLabel(Connection conn, String nameLabel) throws BadServerResponse, XenAPIException, XmlRpcException { - Set srs = SR.getByNameLabel(conn, nameLabel); - if (srs.size() != 1) { - throw new CloudRuntimeException("storage uuid: " + nameLabel + " is not unique"); - } - SR poolsr = srs.iterator().next(); - return poolsr; - } - - protected VDI createVdi(Connection conn, String vdiName, SR sr, long size) throws BadServerResponse, XenAPIException, XmlRpcException { - VDI.Record vdir = new VDI.Record(); - vdir.nameLabel = vdiName; - vdir.SR = sr; - vdir.type = Types.VdiType.USER; - - vdir.virtualSize = size; - VDI vdi = VDI.create(conn, vdir); - return vdi; - } - - protected void deleteVDI(Connection conn, VDI vdi) throws BadServerResponse, XenAPIException, XmlRpcException { - vdi.destroy(conn); - } - - private Map getParameters(URI uri) { - String parameters = uri.getQuery(); - Map params = new HashMap(); - List paraLists = Arrays.asList(parameters.split("&")); - for (String para : paraLists) { - String[] pair = para.split("="); - params.put(pair[0], pair[1]); - } - return params; - } - - protected CreateObjectAnswer getTemplateSize(CreateObjectCommand cmd, String templateUrl) { - Connection conn = hypervisorResource.getConnection(); - long size = this.getTemplateSize(conn, templateUrl); - return new CreateObjectAnswer(cmd, templateUrl, size); - } - protected CreateObjectAnswer execute(CreateObjectCommand cmd) { - String uriString = cmd.getObjectUri(); - DecodedDataObject obj = null; - - Connection conn = hypervisorResource.getConnection(); - VDI vdi = null; - boolean result = false; - String errorMsg = null; - - try { - obj = Decoder.decode(uriString); - - DecodedDataStore store = obj.getStore(); - if (obj.getObjType().equalsIgnoreCase("template") && store.getRole().equalsIgnoreCase("image")) { - return getTemplateSize(cmd, obj.getPath()); - } - - long size = obj.getSize(); - String name = obj.getName(); - String storeUuid = store.getUuid(); - SR primaryDataStoreSR = getSRByNameLabel(conn, storeUuid); - vdi = createVdi(conn, name, primaryDataStoreSR, size); - VDI.Record record = vdi.getRecord(conn); - result = true; - return new CreateObjectAnswer(cmd, record.uuid, record.virtualSize); - } catch (BadServerResponse e) { - s_logger.debug("Failed to create volume", e); - errorMsg = e.toString(); - } catch (XenAPIException e) { - s_logger.debug("Failed to create volume", e); - errorMsg = e.toString(); - } catch (XmlRpcException e) { - s_logger.debug("Failed to create volume", e); - errorMsg = e.toString(); - } catch (URISyntaxException e) { - s_logger.debug("Failed to create volume", e); - errorMsg = e.toString(); - } finally { - if (!result && vdi != null) { - try { - deleteVDI(conn, vdi); - } catch (Exception e) { - s_logger.debug("Faled to delete vdi: " + vdi.toString()); - } - } - } - - return new CreateObjectAnswer(cmd, false, errorMsg); - } - - protected Answer execute(DeleteVolumeCommand cmd) { - VolumeTO volume = null; - Connection conn = hypervisorResource.getConnection(); - String errorMsg = null; - try { - VDI vdi = VDI.getByUuid(conn, volume.getUuid()); - deleteVDI(conn, vdi); - return new Answer(cmd); - } catch (BadServerResponse e) { - s_logger.debug("Failed to delete volume", e); - errorMsg = e.toString(); - } catch (XenAPIException e) { - s_logger.debug("Failed to delete volume", e); - errorMsg = e.toString(); - } catch (XmlRpcException e) { - s_logger.debug("Failed to delete volume", e); - errorMsg = e.toString(); - } - - return new Answer(cmd, false, errorMsg); - } - - protected Answer execute(CreateVolumeFromBaseImageCommand cmd) { - VolumeTO volume = cmd.getVolume(); - ImageOnPrimaryDataStoreTO baseImage = cmd.getImage(); - Connection conn = hypervisorResource.getConnection(); - - try { - VDI baseVdi = VDI.getByUuid(conn, baseImage.getPathOnPrimaryDataStore()); - VDI newVol = baseVdi.createClone(conn, new HashMap()); - newVol.setNameLabel(conn, volume.getName()); - return new CreateObjectAnswer(cmd, newVol.getUuid(conn), newVol.getVirtualSize(conn)); - } catch (BadServerResponse e) { - return new Answer(cmd, false, e.toString()); - } catch (XenAPIException e) { - return new Answer(cmd, false, e.toString()); - } catch (XmlRpcException e) { - return new Answer(cmd, false, e.toString()); - } - } - - protected SR getNfsSR(Connection conn, DecodedDataStore store) { - - Map deviceConfig = new HashMap(); - - String uuid = store.getUuid(); - try { - String server = store.getServer(); - String serverpath = store.getPath(); - - serverpath = serverpath.replace("//", "/"); - Set srs = SR.getAll(conn); - for (SR sr : srs) { - if (!SRType.NFS.equals(sr.getType(conn))) { - continue; - } - - Set pbds = sr.getPBDs(conn); - if (pbds.isEmpty()) { - continue; - } - - PBD pbd = pbds.iterator().next(); - - Map dc = pbd.getDeviceConfig(conn); - - if (dc == null) { - continue; - } - - if (dc.get("server") == null) { - continue; - } - - if (dc.get("serverpath") == null) { - continue; - } - - if (server.equals(dc.get("server")) && serverpath.equals(dc.get("serverpath"))) { - throw new CloudRuntimeException("There is a SR using the same configuration server:" + dc.get("server") + ", serverpath:" - + dc.get("serverpath") + " for pool " + uuid + "on host:" + hypervisorResource.getHost().uuid); - } - - } - deviceConfig.put("server", server); - deviceConfig.put("serverpath", serverpath); - Host host = Host.getByUuid(conn, hypervisorResource.getHost().uuid); - SR sr = SR.create(conn, host, deviceConfig, new Long(0), uuid, uuid, SRType.NFS.toString(), "user", true, - new HashMap()); - sr.scan(conn); - return sr; - } catch (XenAPIException e) { - throw new CloudRuntimeException("Unable to create NFS SR " + uuid, e); - } catch (XmlRpcException e) { - throw new CloudRuntimeException("Unable to create NFS SR " + uuid, e); - } - } - /* - protected SR getIscsiSR(Connection conn, PrimaryDataStoreTO pool) { - synchronized (pool.getUuid().intern()) { - Map deviceConfig = new HashMap(); - try { - String target = pool.getHost(); - String path = pool.getPath(); - if (path.endsWith("/")) { - path = path.substring(0, path.length() - 1); - } - - String tmp[] = path.split("/"); - if (tmp.length != 3) { - String msg = "Wrong iscsi path " + pool.getPath() + " it should be /targetIQN/LUN"; - s_logger.warn(msg); - throw new CloudRuntimeException(msg); - } - String targetiqn = tmp[1].trim(); - String lunid = tmp[2].trim(); - String scsiid = ""; - - Set srs = SR.getByNameLabel(conn, pool.getUuid()); - for (SR sr : srs) { - if (!SRType.LVMOISCSI.equals(sr.getType(conn))) { - continue; - } - Set pbds = sr.getPBDs(conn); - if (pbds.isEmpty()) { - continue; - } - PBD pbd = pbds.iterator().next(); - Map dc = pbd.getDeviceConfig(conn); - if (dc == null) { - continue; - } - if (dc.get("target") == null) { - continue; - } - if (dc.get("targetIQN") == null) { - continue; - } - if (dc.get("lunid") == null) { - continue; - } - if (target.equals(dc.get("target")) && targetiqn.equals(dc.get("targetIQN")) && lunid.equals(dc.get("lunid"))) { - throw new CloudRuntimeException("There is a SR using the same configuration target:" + dc.get("target") + ", targetIQN:" - + dc.get("targetIQN") + ", lunid:" + dc.get("lunid") + " for pool " + pool.getUuid() + "on host:" + _host.uuid); - } - } - deviceConfig.put("target", target); - deviceConfig.put("targetIQN", targetiqn); - - Host host = Host.getByUuid(conn, _host.uuid); - Map smConfig = new HashMap(); - String type = SRType.LVMOISCSI.toString(); - String poolId = Long.toString(pool.getId()); - SR sr = null; - try { - sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), poolId, type, "user", true, - smConfig); - } catch (XenAPIException e) { - String errmsg = e.toString(); - if (errmsg.contains("SR_BACKEND_FAILURE_107")) { - String lun[] = errmsg.split(""); - boolean found = false; - for (int i = 1; i < lun.length; i++) { - int blunindex = lun[i].indexOf("") + 7; - int elunindex = lun[i].indexOf(""); - String ilun = lun[i].substring(blunindex, elunindex); - ilun = ilun.trim(); - if (ilun.equals(lunid)) { - int bscsiindex = lun[i].indexOf("") + 8; - int escsiindex = lun[i].indexOf(""); - scsiid = lun[i].substring(bscsiindex, escsiindex); - scsiid = scsiid.trim(); - found = true; - break; - } - } - if (!found) { - String msg = "can not find LUN " + lunid + " in " + errmsg; - s_logger.warn(msg); - throw new CloudRuntimeException(msg); - } - } else { - String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.toString(); - s_logger.warn(msg, e); - throw new CloudRuntimeException(msg, e); - } - } - deviceConfig.put("SCSIid", scsiid); - - String result = SR.probe(conn, host, deviceConfig, type , smConfig); - String pooluuid = null; - if( result.indexOf("") != -1) { - pooluuid = result.substring(result.indexOf("") + 6, result.indexOf("")).trim(); - } - if( pooluuid == null || pooluuid.length() != 36) { - sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), poolId, type, "user", true, - smConfig); - } else { - sr = SR.introduce(conn, pooluuid, pool.getUuid(), poolId, - type, "user", true, smConfig); - Pool.Record pRec = XenServerConnectionPool.getPoolRecord(conn); - PBD.Record rec = new PBD.Record(); - rec.deviceConfig = deviceConfig; - rec.host = pRec.master; - rec.SR = sr; - PBD pbd = PBD.create(conn, rec); - pbd.plug(conn); - } - sr.scan(conn); - return sr; - } catch (XenAPIException e) { - String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.toString(); - s_logger.warn(msg, e); - throw new CloudRuntimeException(msg, e); - } catch (Exception e) { - String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.getMessage(); - s_logger.warn(msg, e); - throw new CloudRuntimeException(msg, e); - } - } - }*/ - - protected Answer execute(CreatePrimaryDataStoreCmd cmd) { - Connection conn = hypervisorResource.getConnection(); - String storeUrl = cmd.getDataStore(); - - try { - DecodedDataObject obj = Decoder.decode(storeUrl); - DecodedDataStore store = obj.getStore(); - - if (store.getScheme().equalsIgnoreCase("nfs")) { - SR sr = getNfsSR(conn, store); - } else if (store.getScheme().equalsIgnoreCase("iscsi")) { - //getIscsiSR(conn, dataStore); - } else if (store.getScheme().equalsIgnoreCase("presetup")) { - } else { - return new Answer(cmd, false, "The pool type: " + store.getScheme() + " is not supported."); - } - return new Answer(cmd, true, "success"); - } catch (Exception e) { - // String msg = "Catch Exception " + e.getClass().getName() + ", create StoragePool failed due to " + e.toString() + " on host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath(); - //s_logger.warn(msg, e); - return new Answer(cmd, false, null); - } - } - - private long getTemplateSize(Connection conn, String url) { - String size = hypervisorResource.callHostPlugin(conn, "storagePlugin", "getTemplateSize", "srcUrl", url); - if (size.equalsIgnoreCase("") || size == null) { - throw new CloudRuntimeException("Can't get template size"); - } - - try { - return Long.parseLong(size); - } catch (NumberFormatException e) { - throw new CloudRuntimeException("Failed to get template lenght", e); - } - - /* - HttpHead method = new HttpHead(url); - DefaultHttpClient client = new DefaultHttpClient(); - try { - HttpResponse response = client.execute(method); - Header header = response.getFirstHeader("Content-Length"); - if (header == null) { - throw new CloudRuntimeException("Can't get content-lenght header from :" + url); - } - Long length = Long.parseLong(header.getValue()); - return length; - } catch (HttpException e) { - throw new CloudRuntimeException("Failed to get template lenght", e); - } catch (IOException e) { - throw new CloudRuntimeException("Failed to get template lenght", e); - } catch (NumberFormatException e) { - throw new CloudRuntimeException("Failed to get template lenght", e); - }*/ - } - - private void downloadHttpToLocalFile(String destFilePath, String url) { - File destFile = new File(destFilePath); - if (!destFile.exists()) { - throw new CloudRuntimeException("dest file doesn't exist: " + destFilePath); - } - - DefaultHttpClient client = new DefaultHttpClient(); - HttpGet getMethod = new HttpGet(url); - HttpResponse response; - BufferedOutputStream output = null; - long length = 0; - try { - response = client.execute(getMethod); - HttpEntity entity = response.getEntity(); - length = entity.getContentLength(); - output = new BufferedOutputStream(new FileOutputStream(destFile)); - entity.writeTo(output); - } catch (ClientProtocolException e) { - throw new CloudRuntimeException("Failed to download template", e); - } catch (IOException e) { - throw new CloudRuntimeException("Failed to download template", e); - } finally { - if (output != null) { - try { - output.close(); - } catch (IOException e) { - throw new CloudRuntimeException("Failed to download template", e); - } - } - } - - //double check the length - destFile = new File(destFilePath); - if (destFile.length() != length) { - throw new CloudRuntimeException("Download file length doesn't match: expected: " + length + ", actual: " + destFile.length()); - } - - } - - protected Answer directDownloadHttpTemplate(CopyCmd cmd, DecodedDataObject srcObj, DecodedDataObject destObj) { - Connection conn = hypervisorResource.getConnection(); - SR poolsr = null; - VDI vdi = null; - boolean result = false; - try { - if (destObj.getPath() == null) { - //need to create volume at first - - } - vdi = VDI.getByUuid(conn, destObj.getPath()); - if (vdi == null) { - throw new CloudRuntimeException("can't find volume: " + destObj.getPath()); - } - String destStoreUuid = destObj.getStore().getUuid(); - Set srs = SR.getByNameLabel(conn, destStoreUuid); - if (srs.size() != 1) { - throw new CloudRuntimeException("storage uuid: " + destStoreUuid + " is not unique"); - } - poolsr = srs.iterator().next(); - VDI.Record vdir = vdi.getRecord(conn); - String vdiLocation = vdir.location; - String pbdLocation = null; - if (destObj.getStore().getScheme().equalsIgnoreCase(DataStoreProtocol.NFS.toString())) { - pbdLocation = "/run/sr-mount/" + poolsr.getUuid(conn); - } else { - Set pbds = poolsr.getPBDs(conn); - if (pbds.size() != 1) { - throw new CloudRuntimeException("Don't how to handle multiple pbds:" + pbds.size() + " for sr: " + poolsr.getUuid(conn)); - } - PBD pbd = pbds.iterator().next(); - Map deviceCfg = pbd.getDeviceConfig(conn); - pbdLocation = deviceCfg.get("location"); - } - if (pbdLocation == null) { - throw new CloudRuntimeException("Can't get pbd location"); - } - - String vdiPath = pbdLocation + "/" + vdiLocation + ".vhd"; - //download a url into vdipath - //downloadHttpToLocalFile(vdiPath, template.getPath()); - hypervisorResource.callHostPlugin(conn, "storagePlugin", "downloadTemplateFromUrl", "destPath", vdiPath, "srcUrl", srcObj.getPath()); - result = true; - return new CopyCmdAnswer(cmd, vdi.getUuid(conn)); - } catch (BadServerResponse e) { - s_logger.debug("Failed to download template", e); - } catch (XenAPIException e) { - s_logger.debug("Failed to download template", e); - } catch (XmlRpcException e) { - s_logger.debug("Failed to download template", e); - } catch (Exception e) { - s_logger.debug("Failed to download template", e); - } finally { - if (!result && vdi != null) { - try { - vdi.destroy(conn); - } catch (BadServerResponse e) { - s_logger.debug("Failed to cleanup newly created vdi"); - } catch (XenAPIException e) { - s_logger.debug("Failed to cleanup newly created vdi"); - } catch (XmlRpcException e) { - s_logger.debug("Failed to cleanup newly created vdi"); - } - } - } - return new Answer(cmd, false, "Failed to download template"); - } - - protected Answer execute(AttachPrimaryDataStoreCmd cmd) { - String dataStoreUri = cmd.getDataStore(); - Connection conn = hypervisorResource.getConnection(); - try { - DecodedDataObject obj = Decoder.decode(dataStoreUri); - - DecodedDataStore store = obj.getStore(); - - SR sr = hypervisorResource.getStorageRepository(conn, store.getUuid()); - hypervisorResource.setupHeartbeatSr(conn, sr, false); - long capacity = sr.getPhysicalSize(conn); - long available = capacity - sr.getPhysicalUtilisation(conn); - if (capacity == -1) { - String msg = "Pool capacity is -1! pool: "; - s_logger.warn(msg); - return new Answer(cmd, false, msg); - } - AttachPrimaryDataStoreAnswer answer = new AttachPrimaryDataStoreAnswer(cmd); - answer.setCapacity(capacity); - answer.setUuid(sr.getUuid(conn)); - answer.setAvailable(available); - return answer; - } catch (XenAPIException e) { - String msg = "AttachPrimaryDataStoreCmd add XenAPIException:" + e.toString(); - s_logger.warn(msg, e); - return new Answer(cmd, false, msg); - } catch (Exception e) { - String msg = "AttachPrimaryDataStoreCmd failed:" + e.getMessage(); - s_logger.warn(msg, e); - return new Answer(cmd, false, msg); - } - } - - protected Answer execute(CopyCmd cmd) { - DecodedDataObject srcObj = null; - DecodedDataObject destObj = null; - try { - srcObj = Decoder.decode(cmd.getSrcUri()); - destObj = Decoder.decode(cmd.getDestUri()); - } catch (URISyntaxException e) { - return new Answer(cmd, false, e.toString()); - } - - - if (srcObj.getPath().startsWith("http")) { - return directDownloadHttpTemplate(cmd, srcObj, destObj); - } else { - return new Answer(cmd, false, "not implemented yet"); - /* - String tmplturl = cmd.getUrl(); - String poolName = cmd.getPoolUuid(); - int wait = cmd.getWait(); - try { - URI uri = new URI(tmplturl); - String tmplpath = uri.getHost() + ":" + uri.getPath(); - Connection conn = hypervisorResource.getConnection(); - SR poolsr = null; - Set srs = SR.getByNameLabel(conn, poolName); - if (srs.size() != 1) { - String msg = "There are " + srs.size() + " SRs with same name: " + poolName; - s_logger.warn(msg); - return new PrimaryStorageDownloadAnswer(msg); - } else { - poolsr = srs.iterator().next(); - } - String pUuid = poolsr.getUuid(conn); - boolean isISCSI = IsISCSI(poolsr.getType(conn)); - String uuid = copy_vhd_from_secondarystorage(conn, tmplpath, pUuid, wait); - VDI tmpl = getVDIbyUuid(conn, uuid); - VDI snapshotvdi = tmpl.snapshot(conn, new HashMap()); - String snapshotUuid = snapshotvdi.getUuid(conn); - snapshotvdi.setNameLabel(conn, "Template " + cmd.getName()); - String parentuuid = getVhdParent(conn, pUuid, snapshotUuid, isISCSI); - VDI parent = getVDIbyUuid(conn, parentuuid); - Long phySize = parent.getPhysicalUtilisation(conn); - tmpl.destroy(conn); - poolsr.scan(conn); - try{ - Thread.sleep(5000); - } catch (Exception e) { - } - return new PrimaryStorageDownloadAnswer(snapshotvdi.getUuid(conn), phySize); - } catch (Exception e) { - String msg = "Catch Exception " + e.getClass().getName() + " on host:" + _host.uuid + " for template: " - + tmplturl + " due to " + e.toString(); - s_logger.warn(msg, e); - return new PrimaryStorageDownloadAnswer(msg); - }*/ - } - - } -} diff --git a/plugins/hypervisors/xen/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java b/plugins/hypervisors/xen/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java index 42cb68d1213..c796b691d8d 100644 --- a/plugins/hypervisors/xen/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java +++ b/plugins/hypervisors/xen/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java @@ -24,15 +24,18 @@ import java.util.Map; import javax.inject.Inject; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; +import org.apache.cloudstack.storage.to.VolumeObjectTO; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; @@ -217,12 +220,12 @@ public class XenServerStorageMotionStrategy implements DataMotionStrategy { } } - private void updateVolumePathsAfterMigration(Map volumeToPool, List volumeTos) { + private void updateVolumePathsAfterMigration(Map volumeToPool, List volumeTos) { for (Map.Entry entry : volumeToPool.entrySet()) { boolean updated = false; VolumeInfo volume = entry.getKey(); StoragePool pool = (StoragePool)entry.getValue(); - for (VolumeTO volumeTo : volumeTos) { + for (VolumeObjectTO volumeTo : volumeTos) { if (volume.getId() == volumeTo.getId()) { VolumeVO volumeVO = volDao.findById(volume.getId()); Long oldPoolId = volumeVO.getPoolId(); diff --git a/plugins/pom.xml b/plugins/pom.xml index eab47554e6b..d8ae97af2ca 100755 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -35,7 +35,7 @@ api/rate-limit api/discovery acl/static-role-based - affinity-group-processors/host-anti-affinity + affinity-group-processors/host-anti-affinity affinity-group-processors/explicit-dedication deployment-planners/user-concentrated-pod deployment-planners/user-dispersing @@ -61,8 +61,12 @@ user-authenticators/sha256salted network-elements/dns-notifier storage/image/s3 + storage/image/swift + storage/image/default + storage/image/sample storage/volume/solidfire storage/volume/default + storage/volume/sample alert-handlers/snmp-alerts alert-handlers/syslog-alerts network-elements/internal-loadbalancer diff --git a/plugins/storage-allocators/random/src/org/apache/cloudstack/storage/allocator/RandomStoragePoolAllocator.java b/plugins/storage-allocators/random/src/org/apache/cloudstack/storage/allocator/RandomStoragePoolAllocator.java index cbe6647ded8..76ce6631c74 100644 --- a/plugins/storage-allocators/random/src/org/apache/cloudstack/storage/allocator/RandomStoragePoolAllocator.java +++ b/plugins/storage-allocators/random/src/org/apache/cloudstack/storage/allocator/RandomStoragePoolAllocator.java @@ -21,56 +21,57 @@ import java.util.List; import javax.ejb.Local; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.log4j.Logger; import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner.ExcludeList; +import com.cloud.storage.ScopeType; import com.cloud.storage.StoragePool; import com.cloud.vm.DiskProfile; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; -@Local(value=StoragePoolAllocator.class) +@Local(value = StoragePoolAllocator.class) public class RandomStoragePoolAllocator extends AbstractStoragePoolAllocator { private static final Logger s_logger = Logger.getLogger(RandomStoragePoolAllocator.class); - - @Override - public List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { - List suitablePools = new ArrayList(); - - long dcId = plan.getDataCenterId(); - Long podId = plan.getPodId(); - Long clusterId = plan.getClusterId(); + @Override + public List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, + DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + + List suitablePools = new ArrayList(); + + long dcId = plan.getDataCenterId(); + Long podId = plan.getPodId(); + Long clusterId = plan.getClusterId(); s_logger.debug("Looking for pools in dc: " + dcId + " pod:" + podId + " cluster:" + clusterId); - List pools = _storagePoolDao.listBy(dcId, podId, clusterId, ScopeType.CLUSTER); + List pools = _storagePoolDao.listBy(dcId, podId, clusterId, ScopeType.CLUSTER); if (pools.size() == 0) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("No storage pools available for allocation, returning"); - } + if (s_logger.isDebugEnabled()) { + s_logger.debug("No storage pools available for allocation, returning"); + } return suitablePools; } - + Collections.shuffle(pools); - if (s_logger.isDebugEnabled()) { + if (s_logger.isDebugEnabled()) { s_logger.debug("RandomStoragePoolAllocator has " + pools.size() + " pools to check for allocation"); } - for (StoragePoolVO pool: pools) { - if(suitablePools.size() == returnUpTo){ - break; - } - StoragePool pol = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(pool.getId()); - - if (filter(avoid, pol, dskCh, plan)) { - suitablePools.add(pol); - } + for (StoragePoolVO pool : pools) { + if (suitablePools.size() == returnUpTo) { + break; + } + StoragePool pol = (StoragePool) this.dataStoreMgr.getPrimaryDataStore(pool.getId()); + + if (filter(avoid, pol, dskCh, plan)) { + suitablePools.add(pol); + } } if (s_logger.isDebugEnabled()) { - s_logger.debug("RandomStoragePoolAllocator returning "+suitablePools.size() +" suitable storage pools"); + s_logger.debug("RandomStoragePoolAllocator returning " + suitablePools.size() + " suitable storage pools"); } return suitablePools; diff --git a/plugins/storage/image/default/pom.xml b/plugins/storage/image/default/pom.xml new file mode 100644 index 00000000000..f51d8f55a1d --- /dev/null +++ b/plugins/storage/image/default/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + cloud-plugin-storage-image-default + Apache CloudStack Plugin - Storage Image default provider + + org.apache.cloudstack + cloudstack-plugins + 4.2.0-SNAPSHOT + ../../../pom.xml + + + + org.apache.cloudstack + cloud-engine-storage + ${project.version} + + + org.apache.cloudstack + cloud-engine-storage-image + ${project.version} + + + org.apache.cloudstack + cloud-engine-storage-volume + ${project.version} + + + org.apache.cloudstack + cloud-engine-storage-snapshot + ${project.version} + + + mysql + mysql-connector-java + ${cs.mysql.version} + provided + + + + install + src + test + + + maven-surefire-plugin + + true + + + + integration-test + + test + + + + + + + diff --git a/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java b/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java new file mode 100644 index 00000000000..aa2d533c255 --- /dev/null +++ b/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.datastore.driver; + +import java.util.UUID; + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity; +import org.apache.cloudstack.storage.image.store.ImageStoreImpl; +import org.apache.log4j.Logger; +import org.apache.cloudstack.storage.image.BaseImageStoreDriverImpl; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.storage.CreateEntityDownloadURLCommand; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.NfsTO; +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.utils.exception.CloudRuntimeException; + +public class CloudStackImageStoreDriverImpl extends BaseImageStoreDriverImpl { + private static final Logger s_logger = Logger.getLogger(CloudStackImageStoreDriverImpl.class); + + @Inject + ConfigurationDao _configDao; + @Inject + EndPointSelector _epSelector; + + + @Override + public DataStoreTO getStoreTO(DataStore store) { + ImageStoreImpl nfsStore = (ImageStoreImpl) store; + NfsTO nfsTO = new NfsTO(); + nfsTO.setRole(store.getRole()); + nfsTO.setUrl(nfsStore.getUri()); + return nfsTO; + } + + @Override + public String createEntityExtractUrl(DataStore store, String installPath, ImageFormat format) { + // find an endpoint to send command + EndPoint ep = _epSelector.select(store); + // Create Symlink at ssvm + String path = installPath; + String uuid = UUID.randomUUID().toString() + "." + format.getFileExtension(); + CreateEntityDownloadURLCommand cmd = new CreateEntityDownloadURLCommand(((ImageStoreEntity) store).getMountPoint(), path, uuid); + Answer ans = ep.sendMessage(cmd); + if (ans == null || !ans.getResult()) { + String errorString = "Unable to create a link for entity at " + installPath + " on ssvm," + ans.getDetails(); + s_logger.error(errorString); + throw new CloudRuntimeException(errorString); + } + // Construct actual URL locally now that the symlink exists at SSVM + return generateCopyUrl(ep.getPublicAddr(), uuid); + } + + private String generateCopyUrl(String ipAddress, String uuid){ + + String hostname = ipAddress; + String scheme = "http"; + boolean _sslCopy = false; + String sslCfg = _configDao.getValue(Config.SecStorageEncryptCopy.toString()); + if ( sslCfg != null ){ + _sslCopy = Boolean.parseBoolean(sslCfg); + } + if (_sslCopy) { + hostname = ipAddress.replace(".", "-"); + hostname = hostname + ".realhostip.com"; + scheme = "https"; + } + return scheme + "://" + hostname + "/userdata/" + uuid; + } + +} diff --git a/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackImageStoreLifeCycleImpl.java b/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackImageStoreLifeCycleImpl.java new file mode 100644 index 00000000000..7b30575c8d1 --- /dev/null +++ b/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackImageStoreLifeCycleImpl.java @@ -0,0 +1,155 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.datastore.lifecycle; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; +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.datastore.ImageStoreHelper; +import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager; +import org.apache.cloudstack.storage.image.store.lifecycle.ImageStoreLifeCycle; +import org.apache.log4j.Logger; + +import com.cloud.agent.api.StoragePoolInfo; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.resource.Discoverer; +import com.cloud.resource.ResourceManager; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ScopeType; +import com.cloud.utils.UriUtils; + +public class CloudStackImageStoreLifeCycleImpl implements ImageStoreLifeCycle { + + private static final Logger s_logger = Logger.getLogger(CloudStackImageStoreLifeCycleImpl.class); + @Inject + protected ResourceManager _resourceMgr; + @Inject + protected ImageStoreDao imageStoreDao; + @Inject + ImageStoreHelper imageStoreHelper; + @Inject + ImageStoreProviderManager imageStoreMgr; + + protected List _discoverers; + + public List getDiscoverers() { + return _discoverers; + } + + public void setDiscoverers(List _discoverers) { + this._discoverers = _discoverers; + } + + public CloudStackImageStoreLifeCycleImpl() { + } + + @SuppressWarnings("unchecked") + @Override + public DataStore initialize(Map dsInfos) { + + Long dcId = (Long) dsInfos.get("zoneId"); + String url = (String) dsInfos.get("url"); + String name = (String) dsInfos.get("name"); + if (name == null) { + name = url; + } + String providerName = (String) dsInfos.get("providerName"); + DataStoreRole role = (DataStoreRole) dsInfos.get("role"); + Map details = (Map) dsInfos.get("details"); + + s_logger.info("Trying to add a new host at " + url + " in data center " + dcId); + + URI uri = null; + try { + uri = new URI(UriUtils.encodeURIComponent(url)); + if (uri.getScheme() == null) { + throw new InvalidParameterValueException("uri.scheme is null " + url + ", add nfs:// as a prefix"); + } else if (uri.getScheme().equalsIgnoreCase("nfs")) { + if (uri.getHost() == null || uri.getHost().equalsIgnoreCase("") || uri.getPath() == null + || uri.getPath().equalsIgnoreCase("")) { + throw new InvalidParameterValueException( + "Your host and/or path is wrong. Make sure it's of the format nfs://hostname/path"); + } + } + } catch (URISyntaxException e) { + throw new InvalidParameterValueException(url + " is not a valid uri"); + } + + if (dcId == null) { + throw new InvalidParameterValueException( + "DataCenter id is null, and cloudstack default image storehas to be associated with a data center"); + } + + Map imageStoreParameters = new HashMap(); + imageStoreParameters.put("name", name); + imageStoreParameters.put("zoneId", dcId); + imageStoreParameters.put("url", url); + imageStoreParameters.put("protocol", uri.getScheme().toLowerCase()); + imageStoreParameters.put("scope", ScopeType.ZONE); // default cloudstack + // provider only + // supports zone-wide + // image store + imageStoreParameters.put("providerName", providerName); + imageStoreParameters.put("role", role); + + ImageStoreVO ids = imageStoreHelper.createImageStore(imageStoreParameters, details); + return imageStoreMgr.getImageStore(ids.getId()); + } + + @Override + public boolean attachCluster(DataStore store, ClusterScope scope) { + return false; + } + + @Override + public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo) { + return false; + } + + + @Override + public boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisorType) { + return false; + } + + @Override + public boolean maintain(DataStore store) { + return false; + } + + @Override + public boolean cancelMaintain(DataStore store) { + return false; + } + + @Override + public boolean deleteDataStore(DataStore store) { + return false; + } +} diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/AncientImageDataStoreProvider.java b/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/provider/CloudStackImageStoreProviderImpl.java similarity index 53% rename from engine/storage/image/src/org/apache/cloudstack/storage/image/store/AncientImageDataStoreProvider.java rename to plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/provider/CloudStackImageStoreProviderImpl.java index 2715dc7e0e9..23de36fb952 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/AncientImageDataStoreProvider.java +++ b/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/provider/CloudStackImageStoreProviderImpl.java @@ -16,41 +16,39 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.storage.image.store; +package org.apache.cloudstack.storage.datastore.provider; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.UUID; - import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider; import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; -import org.apache.cloudstack.engine.subsystem.api.storage.ImageDataStoreProvider; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; -import org.apache.cloudstack.storage.image.ImageDataStoreDriver; -import org.apache.cloudstack.storage.image.datastore.ImageDataStoreHelper; -import org.apache.cloudstack.storage.image.datastore.ImageDataStoreManager; -import org.apache.cloudstack.storage.image.driver.AncientImageDataStoreDriverImpl; -import org.apache.cloudstack.storage.image.store.lifecycle.DefaultImageDataStoreLifeCycle; -import org.apache.cloudstack.storage.image.store.lifecycle.ImageDataStoreLifeCycle; +import org.apache.cloudstack.engine.subsystem.api.storage.ImageStoreProvider; +import org.apache.cloudstack.storage.datastore.driver.CloudStackImageStoreDriverImpl; +import org.apache.cloudstack.storage.datastore.lifecycle.CloudStackImageStoreLifeCycleImpl; +import org.apache.cloudstack.storage.image.ImageStoreDriver; +import org.apache.cloudstack.storage.image.datastore.ImageStoreHelper; +import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager; +import org.apache.cloudstack.storage.image.store.lifecycle.ImageStoreLifeCycle; import org.springframework.stereotype.Component; +import com.cloud.storage.ScopeType; import com.cloud.utils.component.ComponentContext; @Component -public class AncientImageDataStoreProvider implements ImageDataStoreProvider { +public class CloudStackImageStoreProviderImpl implements ImageStoreProvider { - private final String name = "ancient image data store"; - protected ImageDataStoreLifeCycle lifeCycle; - protected ImageDataStoreDriver driver; + private final String providerName = DataStoreProvider.NFS_IMAGE; + protected ImageStoreLifeCycle lifeCycle; + protected ImageStoreDriver driver; @Inject - ImageDataStoreManager storeMgr; + ImageStoreProviderManager storeMgr; @Inject - ImageDataStoreHelper helper; + ImageStoreHelper helper; @Override public DataStoreLifeCycle getDataStoreLifeCycle() { @@ -59,25 +57,16 @@ public class AncientImageDataStoreProvider implements ImageDataStoreProvider { @Override public String getName() { - return this.name; + return this.providerName; } @Override public boolean configure(Map params) { - lifeCycle = ComponentContext.inject(DefaultImageDataStoreLifeCycle.class); - driver = ComponentContext.inject(AncientImageDataStoreDriverImpl.class); + lifeCycle = ComponentContext.inject(CloudStackImageStoreLifeCycleImpl.class); + driver = ComponentContext.inject(CloudStackImageStoreDriverImpl.class); storeMgr.registerDriver(this.getName(), driver); - - Map infos = new HashMap(); - String dataStoreName = UUID.nameUUIDFromBytes(this.name.getBytes()).toString(); - infos.put("name", dataStoreName); - infos.put("uuid", dataStoreName); - infos.put("protocol", "http"); - infos.put("scope", ScopeType.GLOBAL); - infos.put("providerName", this.getName()); - DataStoreLifeCycle lifeCycle = this.getDataStoreLifeCycle(); - lifeCycle.initialize(infos); + return true; } @@ -93,9 +82,22 @@ public class AncientImageDataStoreProvider implements ImageDataStoreProvider { @Override public Set getTypes() { - Set types = new HashSet(); + Set types = new HashSet(); types.add(DataStoreProviderType.IMAGE); + types.add(DataStoreProviderType.ImageCache); return types; } + @Override + public boolean isScopeSupported(ScopeType scope) { + if (scope == ScopeType.ZONE) + return true; + return false; + } + + @Override + public boolean needDownloadSysTemplate() { + return false; + } + } diff --git a/plugins/storage/image/s3/pom.xml b/plugins/storage/image/s3/pom.xml index 7ab0d3e9301..ad42e6fa376 100644 --- a/plugins/storage/image/s3/pom.xml +++ b/plugins/storage/image/s3/pom.xml @@ -27,11 +27,26 @@ ../../../pom.xml + + org.apache.cloudstack + cloud-engine-storage + ${project.version} + org.apache.cloudstack cloud-engine-storage-image ${project.version} + + org.apache.cloudstack + cloud-engine-storage-volume + ${project.version} + + + org.apache.cloudstack + cloud-engine-storage-snapshot + ${project.version} + install diff --git a/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/driver/S3ImageStoreDriverImpl.java b/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/driver/S3ImageStoreDriverImpl.java new file mode 100644 index 00000000000..85547ff2e6f --- /dev/null +++ b/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/driver/S3ImageStoreDriverImpl.java @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.datastore.driver; + +import java.net.URL; +import java.util.Date; +import java.util.Map; +import javax.inject.Inject; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao; +import org.apache.cloudstack.storage.image.BaseImageStoreDriverImpl; +import org.apache.cloudstack.storage.image.store.ImageStoreImpl; +import org.apache.log4j.Logger; + +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.S3TO; +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.utils.S3Utils; + +public class S3ImageStoreDriverImpl extends BaseImageStoreDriverImpl { + private static final Logger s_logger = Logger.getLogger(S3ImageStoreDriverImpl.class); + + @Inject + ImageStoreDetailsDao _imageStoreDetailsDao; + + @Inject + ConfigurationDao _configDao; + + + @Override + public DataStoreTO getStoreTO(DataStore store) { + ImageStoreImpl imgStore = (ImageStoreImpl) store; + Map details = _imageStoreDetailsDao.getDetails(imgStore.getId()); + return new S3TO(imgStore.getId(), imgStore.getUuid(), details.get(ApiConstants.S3_ACCESS_KEY), + details.get(ApiConstants.S3_SECRET_KEY), details.get(ApiConstants.S3_END_POINT), + details.get(ApiConstants.S3_BUCKET_NAME), details.get(ApiConstants.S3_HTTPS_FLAG) == null ? false + : Boolean.parseBoolean(details.get(ApiConstants.S3_HTTPS_FLAG)), + details.get(ApiConstants.S3_CONNECTION_TIMEOUT) == null ? null : Integer.valueOf(details + .get(ApiConstants.S3_CONNECTION_TIMEOUT)), + details.get(ApiConstants.S3_MAX_ERROR_RETRY) == null ? null : Integer.valueOf(details + .get(ApiConstants.S3_MAX_ERROR_RETRY)), + details.get(ApiConstants.S3_SOCKET_TIMEOUT) == null ? null : Integer.valueOf(details + .get(ApiConstants.S3_SOCKET_TIMEOUT)), imgStore.getCreated(), + _configDao.getValue(Config.S3EnableRRS.toString()) == null ? false : Boolean.parseBoolean(_configDao + .getValue(Config.S3EnableRRS.toString()))); + + } + + + @Override + public String createEntityExtractUrl(DataStore store, String installPath, ImageFormat format) { + // for S3, no need to do anything, just return template url for + // extract template. but we need to set object acl as public_read to + // make the url accessible + S3TO s3 = (S3TO)getStoreTO(store); + String key = installPath; + + s_logger.info("Generating pre-signed s3 entity extraction URL."); + Date expiration = new Date(); + long milliSeconds = expiration.getTime(); + milliSeconds += 1000 * 60 * 60; // expired after one hour. + expiration.setTime(milliSeconds); + + URL s3url = S3Utils.generatePresignedUrl(s3, s3.getBucketName(), key, expiration); + + s_logger.info("Pre-Signed URL = " + s3url.toString()); + + return s3url.toString(); + } + + +} diff --git a/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/lifecycle/S3ImageStoreLifeCycleImpl.java b/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/lifecycle/S3ImageStoreLifeCycleImpl.java new file mode 100644 index 00000000000..2630d137863 --- /dev/null +++ b/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/lifecycle/S3ImageStoreLifeCycleImpl.java @@ -0,0 +1,135 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.datastore.lifecycle; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; +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.datastore.ImageStoreHelper; +import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager; +import org.apache.cloudstack.storage.image.store.lifecycle.ImageStoreLifeCycle; +import org.apache.log4j.Logger; + +import com.cloud.agent.api.StoragePoolInfo; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.resource.Discoverer; +import com.cloud.resource.ResourceManager; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ScopeType; +import com.cloud.storage.s3.S3Manager; + +public class S3ImageStoreLifeCycleImpl implements ImageStoreLifeCycle { + + private static final Logger s_logger = Logger.getLogger(S3ImageStoreLifeCycleImpl.class); + @Inject + protected ResourceManager _resourceMgr; + @Inject + protected ImageStoreDao imageStoreDao; + @Inject + ImageStoreHelper imageStoreHelper; + @Inject + ImageStoreProviderManager imageStoreMgr; + + protected List _discoverers; + + public List getDiscoverers() { + return _discoverers; + } + + public void setDiscoverers(List _discoverers) { + this._discoverers = _discoverers; + } + + public S3ImageStoreLifeCycleImpl() { + } + + @SuppressWarnings("unchecked") + @Override + public DataStore initialize(Map dsInfos) { + + Long dcId = (Long) dsInfos.get("zoneId"); + String url = (String) dsInfos.get("url"); + String name = (String) dsInfos.get("name"); + String providerName = (String) dsInfos.get("providerName"); + ScopeType scope = (ScopeType) dsInfos.get("scope"); + DataStoreRole role = (DataStoreRole) dsInfos.get("role"); + Map details = (Map) dsInfos.get("details"); + + s_logger.info("Trying to add a S3 store in data center " + dcId); + + Map imageStoreParameters = new HashMap(); + imageStoreParameters.put("name", name); + imageStoreParameters.put("zoneId", dcId); + imageStoreParameters.put("url", url); + String protocol = "http"; + String useHttps = details.get(ApiConstants.S3_HTTPS_FLAG); + if (useHttps != null && Boolean.parseBoolean(useHttps)) { + protocol = "https"; + } + imageStoreParameters.put("protocol", protocol); + if (scope != null) { + imageStoreParameters.put("scope", scope); + } else { + imageStoreParameters.put("scope", ScopeType.REGION); + } + imageStoreParameters.put("providerName", providerName); + imageStoreParameters.put("role", role); + + ImageStoreVO ids = imageStoreHelper.createImageStore(imageStoreParameters, details); + return imageStoreMgr.getImageStore(ids.getId()); + } + + @Override + public boolean attachCluster(DataStore store, ClusterScope scope) { + return false; + } + + @Override + public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo) { + return false; + } + + @Override + public boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisorType) { + return false; + } + + @Override + public boolean maintain(DataStore store) { + return false; + } + + @Override + public boolean cancelMaintain(DataStore store) { + return false; + } + + @Override + public boolean deleteDataStore(DataStore store) { + return false; + } +} diff --git a/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/provider/S3ImageStoreProviderImpl.java b/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/provider/S3ImageStoreProviderImpl.java new file mode 100644 index 00000000000..8bcdb44f9c0 --- /dev/null +++ b/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/provider/S3ImageStoreProviderImpl.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.datastore.provider; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider; +import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; +import org.apache.cloudstack.engine.subsystem.api.storage.ImageStoreProvider; +import org.apache.cloudstack.storage.datastore.driver.S3ImageStoreDriverImpl; +import org.apache.cloudstack.storage.datastore.lifecycle.S3ImageStoreLifeCycleImpl; +import org.apache.cloudstack.storage.image.ImageStoreDriver; +import org.apache.cloudstack.storage.image.datastore.ImageStoreHelper; +import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager; +import org.apache.cloudstack.storage.image.store.lifecycle.ImageStoreLifeCycle; +import org.springframework.stereotype.Component; + +import com.cloud.storage.ScopeType; +import com.cloud.utils.component.ComponentContext; + +@Component +public class S3ImageStoreProviderImpl implements ImageStoreProvider { + + private final String providerName = DataStoreProvider.S3_IMAGE; + protected ImageStoreLifeCycle lifeCycle; + protected ImageStoreDriver driver; + @Inject + ImageStoreProviderManager storeMgr; + @Inject + ImageStoreHelper helper; + + @Override + public DataStoreLifeCycle getDataStoreLifeCycle() { + return lifeCycle; + } + + @Override + public String getName() { + return this.providerName; + } + + @Override + public boolean configure(Map params) { + lifeCycle = ComponentContext.inject(S3ImageStoreLifeCycleImpl.class); + driver = ComponentContext.inject(S3ImageStoreDriverImpl.class); + storeMgr.registerDriver(this.getName(), driver); + return true; + } + + @Override + public DataStoreDriver getDataStoreDriver() { + return this.driver; + } + + @Override + public HypervisorHostListener getHostListener() { + return null; + } + + @Override + public Set getTypes() { + Set types = new HashSet(); + types.add(DataStoreProviderType.IMAGE); + return types; + } + + @Override + public boolean isScopeSupported(ScopeType scope) { + if (scope == ScopeType.REGION) + return true; + return false; + } + + @Override + public boolean needDownloadSysTemplate() { + return true; + } + +} diff --git a/plugins/storage/image/sample/pom.xml b/plugins/storage/image/sample/pom.xml new file mode 100644 index 00000000000..44b50b09220 --- /dev/null +++ b/plugins/storage/image/sample/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + cloud-plugin-storage-image-sample + Apache CloudStack Plugin - Storage Image sample provider + + org.apache.cloudstack + cloudstack-plugins + 4.2.0-SNAPSHOT + ../../../pom.xml + + + + org.apache.cloudstack + cloud-engine-storage + ${project.version} + + + org.apache.cloudstack + cloud-engine-storage-image + ${project.version} + + + org.apache.cloudstack + cloud-engine-storage-volume + ${project.version} + + + org.apache.cloudstack + cloud-engine-storage-snapshot + ${project.version} + + + mysql + mysql-connector-java + ${cs.mysql.version} + provided + + + + install + src + test + + + maven-surefire-plugin + + true + + + + integration-test + + test + + + + + + + diff --git a/engine/storage/src/org/apache/cloudstack/storage/endpoint/EndPointSelector.java b/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/driver/SampleImageStoreDriverImpl.java similarity index 52% rename from engine/storage/src/org/apache/cloudstack/storage/endpoint/EndPointSelector.java rename to plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/driver/SampleImageStoreDriverImpl.java index 6910eb6a401..44f94f39ee4 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/endpoint/EndPointSelector.java +++ b/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/driver/SampleImageStoreDriverImpl.java @@ -16,25 +16,38 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.storage.endpoint; +package org.apache.cloudstack.storage.datastore.driver; -import java.util.List; +import javax.inject.Inject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.storage.image.BaseImageStoreDriverImpl; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.dao.VMTemplateDao; + +//http-read-only based image store +public class SampleImageStoreDriverImpl extends BaseImageStoreDriverImpl { + @Inject + EndPointSelector selector; + @Inject + VMTemplateDao imageDataDao; + + public SampleImageStoreDriverImpl() { + } + + @Override + public DataStoreTO getStoreTO(DataStore store) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String createEntityExtractUrl(DataStore store, String installPath, ImageFormat format) { + // TODO Auto-generated method stub + return null; + } -public interface EndPointSelector { - public EndPoint select(DataObject srcData, DataObject destData); - /** - * @param object - * @return - */ - EndPoint select(DataObject object); - /** - * @param store - * @return - */ - List selectAll(DataStore store); } diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/lifecycle/DefaultImageDataStoreLifeCycle.java b/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/lifecycle/SampleImageStoreLifeCycleImpl.java similarity index 58% rename from engine/storage/image/src/org/apache/cloudstack/storage/image/store/lifecycle/DefaultImageDataStoreLifeCycle.java rename to plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/lifecycle/SampleImageStoreLifeCycleImpl.java index fef97671961..e4df6f55f3a 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/lifecycle/DefaultImageDataStoreLifeCycle.java +++ b/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/lifecycle/SampleImageStoreLifeCycleImpl.java @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package org.apache.cloudstack.storage.image.store.lifecycle; +package org.apache.cloudstack.storage.datastore.lifecycle; import java.util.Map; @@ -24,85 +24,59 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; -import org.apache.cloudstack.storage.image.datastore.ImageDataStoreHelper; -import org.apache.cloudstack.storage.image.datastore.ImageDataStoreManager; -import org.apache.cloudstack.storage.image.db.ImageDataStoreDao; -import org.apache.cloudstack.storage.image.db.ImageDataStoreVO; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; +import org.apache.cloudstack.storage.image.datastore.ImageStoreHelper; +import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager; +import org.apache.cloudstack.storage.image.store.lifecycle.ImageStoreLifeCycle; import com.cloud.agent.api.StoragePoolInfo; import com.cloud.hypervisor.Hypervisor.HypervisorType; -public class DefaultImageDataStoreLifeCycle implements ImageDataStoreLifeCycle { +public class SampleImageStoreLifeCycleImpl implements ImageStoreLifeCycle { @Inject - protected ImageDataStoreDao imageStoreDao; - @Inject - ImageDataStoreHelper imageStoreHelper; - @Inject - ImageDataStoreManager imageStoreMgr; - public DefaultImageDataStoreLifeCycle() { - } + protected ImageStoreDao imageStoreDao; + @Inject + ImageStoreHelper imageStoreHelper; + @Inject + ImageStoreProviderManager imageStoreMgr; + public SampleImageStoreLifeCycleImpl() { + } @Override public DataStore initialize(Map dsInfos) { - ImageDataStoreVO ids = imageStoreHelper.createImageDataStore(dsInfos); - return imageStoreMgr.getImageDataStore(ids.getId()); + ImageStoreVO ids = imageStoreHelper.createImageStore(dsInfos); + return imageStoreMgr.getImageStore(ids.getId()); } - @Override public boolean attachCluster(DataStore store, ClusterScope scope) { - // TODO Auto-generated method stub return false; } - @Override - public boolean attachHost(DataStore store, HostScope scope, - StoragePoolInfo existingInfo) { - // TODO Auto-generated method stub + public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo) { return false; } - @Override public boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisor) { - // TODO Auto-generated method stub return false; } - - @Override - public boolean dettach() { - // TODO Auto-generated method stub - return false; - } - - - @Override - public boolean unmanaged() { - // TODO Auto-generated method stub - return false; - } - - @Override public boolean maintain(DataStore store) { - // TODO Auto-generated method stub return false; } - @Override public boolean cancelMaintain(DataStore store) { - // TODO Auto-generated method stub return false; } - @Override public boolean deleteDataStore(DataStore store) { - // TODO Auto-generated method stub return false; } } diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/DefaultImageDataStoreProvider.java b/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/provider/SampleImageStoreProviderImpl.java similarity index 59% rename from engine/storage/image/src/org/apache/cloudstack/storage/image/store/DefaultImageDataStoreProvider.java rename to plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/provider/SampleImageStoreProviderImpl.java index 0b5de858819..c52e96e0c93 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/DefaultImageDataStoreProvider.java +++ b/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/provider/SampleImageStoreProviderImpl.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.storage.image.store; +package org.apache.cloudstack.storage.datastore.provider; import java.util.HashSet; import java.util.Map; @@ -26,24 +26,25 @@ import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider; import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; -import org.apache.cloudstack.engine.subsystem.api.storage.ImageDataStoreProvider; -import org.apache.cloudstack.storage.image.ImageDataStoreDriver; -import org.apache.cloudstack.storage.image.datastore.ImageDataStoreManager; -import org.apache.cloudstack.storage.image.driver.DefaultImageDataStoreDriverImpl; -import org.apache.cloudstack.storage.image.store.lifecycle.DefaultImageDataStoreLifeCycle; -import org.apache.cloudstack.storage.image.store.lifecycle.ImageDataStoreLifeCycle; +import org.apache.cloudstack.engine.subsystem.api.storage.ImageStoreProvider; +import org.apache.cloudstack.storage.datastore.driver.SampleImageStoreDriverImpl; +import org.apache.cloudstack.storage.datastore.lifecycle.SampleImageStoreLifeCycleImpl; +import org.apache.cloudstack.storage.image.ImageStoreDriver; +import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager; +import org.apache.cloudstack.storage.image.store.lifecycle.ImageStoreLifeCycle; +import com.cloud.storage.ScopeType; import com.cloud.utils.component.ComponentContext; -public class DefaultImageDataStoreProvider implements ImageDataStoreProvider { - private final String name = "default image data store"; - protected ImageDataStoreLifeCycle lifeCycle; - protected ImageDataStoreDriver driver; +public class SampleImageStoreProviderImpl implements ImageStoreProvider { + private final String name = DataStoreProvider.SAMPLE_IMAGE; + protected ImageStoreLifeCycle lifeCycle; + protected ImageStoreDriver driver; @Inject - ImageDataStoreManager storeMgr; - long id; - String uuid; + ImageStoreProviderManager storeMgr; + @Override public DataStoreLifeCycle getDataStoreLifeCycle() { return lifeCycle; @@ -56,8 +57,8 @@ public class DefaultImageDataStoreProvider implements ImageDataStoreProvider { @Override public boolean configure(Map params) { - lifeCycle = ComponentContext.inject(DefaultImageDataStoreLifeCycle.class); - driver = ComponentContext.inject(DefaultImageDataStoreDriverImpl.class); + lifeCycle = ComponentContext.inject(SampleImageStoreLifeCycleImpl.class); + driver = ComponentContext.inject(SampleImageStoreDriverImpl.class); storeMgr.registerDriver(this.getName(), driver); return true; @@ -65,7 +66,7 @@ public class DefaultImageDataStoreProvider implements ImageDataStoreProvider { @Override public Set getTypes() { - Set types = new HashSet(); + Set types = new HashSet(); types.add(DataStoreProviderType.IMAGE); return types; } @@ -79,4 +80,17 @@ public class DefaultImageDataStoreProvider implements ImageDataStoreProvider { public HypervisorHostListener getHostListener() { return null; } + + @Override + public boolean isScopeSupported(ScopeType scope) { + if (scope == ScopeType.ZONE) + return true; + return false; + } + + @Override + public boolean needDownloadSysTemplate() { + return false; + } + } diff --git a/plugins/storage/image/swift/pom.xml b/plugins/storage/image/swift/pom.xml new file mode 100644 index 00000000000..4e3907fd808 --- /dev/null +++ b/plugins/storage/image/swift/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + cloud-plugin-storage-image-swift + Apache CloudStack Plugin - Storage Image Swift provider + + org.apache.cloudstack + cloudstack-plugins + 4.2.0-SNAPSHOT + ../../../pom.xml + + + + org.apache.cloudstack + cloud-engine-storage + ${project.version} + + + org.apache.cloudstack + cloud-engine-storage-image + ${project.version} + + + org.apache.cloudstack + cloud-engine-storage-volume + ${project.version} + + + org.apache.cloudstack + cloud-engine-storage-snapshot + ${project.version} + + + mysql + mysql-connector-java + ${cs.mysql.version} + provided + + + + install + src + test + + + maven-surefire-plugin + + true + + + + integration-test + + test + + + + + + + diff --git a/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/driver/SwiftImageStoreDriverImpl.java b/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/driver/SwiftImageStoreDriverImpl.java new file mode 100644 index 00000000000..d6d6cd283f1 --- /dev/null +++ b/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/driver/SwiftImageStoreDriverImpl.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.datastore.driver; + +import java.util.Map; +import javax.inject.Inject; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao; +import org.apache.cloudstack.storage.image.BaseImageStoreDriverImpl; +import org.apache.cloudstack.storage.image.store.ImageStoreImpl; +import org.apache.log4j.Logger; + +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.SwiftTO; +import com.cloud.exception.UnsupportedServiceException; +import com.cloud.storage.Storage.ImageFormat; + +public class SwiftImageStoreDriverImpl extends BaseImageStoreDriverImpl { + private static final Logger s_logger = Logger.getLogger(SwiftImageStoreDriverImpl.class); + + @Inject + ImageStoreDetailsDao _imageStoreDetailsDao; + + @Override + public DataStoreTO getStoreTO(DataStore store) { + ImageStoreImpl imgStore = (ImageStoreImpl) store; + Map details = _imageStoreDetailsDao.getDetails(imgStore.getId()); + return new SwiftTO(imgStore.getId(), imgStore.getUri(), details.get(ApiConstants.ACCOUNT), + details.get(ApiConstants.USERNAME), details.get(ApiConstants.KEY)); + } + + @Override + public String createEntityExtractUrl(DataStore store, String installPath, ImageFormat format) { + throw new UnsupportedServiceException("Extract entity url is not yet supported for Swift image store provider"); + } + +} diff --git a/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/lifecycle/SwiftImageStoreLifeCycleImpl.java b/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/lifecycle/SwiftImageStoreLifeCycleImpl.java new file mode 100644 index 00000000000..4256cc2cc7b --- /dev/null +++ b/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/lifecycle/SwiftImageStoreLifeCycleImpl.java @@ -0,0 +1,116 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.datastore.lifecycle; + +import com.cloud.agent.api.StoragePoolInfo; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.resource.ResourceManager; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ScopeType; +import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; +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.datastore.ImageStoreHelper; +import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager; +import org.apache.cloudstack.storage.image.store.lifecycle.ImageStoreLifeCycle; +import org.apache.log4j.Logger; + +import javax.inject.Inject; +import java.util.HashMap; +import java.util.Map; + +public class SwiftImageStoreLifeCycleImpl implements ImageStoreLifeCycle { + + private static final Logger s_logger = Logger.getLogger(SwiftImageStoreLifeCycleImpl.class); + @Inject + protected ResourceManager _resourceMgr; + @Inject + protected ImageStoreDao imageStoreDao; + @Inject + ImageStoreHelper imageStoreHelper; + @Inject + ImageStoreProviderManager imageStoreMgr; + + public SwiftImageStoreLifeCycleImpl() { + } + + @Override + public DataStore initialize(Map dsInfos) { + + Long dcId = (Long) dsInfos.get("zoneId"); + String url = (String) dsInfos.get("url"); + String name = (String) dsInfos.get("name"); + ScopeType scope = (ScopeType) dsInfos.get("scope"); + String providerName = (String) dsInfos.get("providerName"); + DataStoreRole role = (DataStoreRole) dsInfos.get("role"); + + Map details = (Map) dsInfos.get("details"); + + s_logger.info("Trying to add a swift store at " + url + " in data center " + dcId); + + // just need to insert an entry in DB + Map imageStoreParameters = new HashMap(); + imageStoreParameters.put("name", name); + imageStoreParameters.put("zoneId", dcId); + imageStoreParameters.put("url", url); + imageStoreParameters.put("protocol", "http"); + if (scope != null) { + imageStoreParameters.put("scope", scope); + } else { + imageStoreParameters.put("scope", ScopeType.REGION); + } + imageStoreParameters.put("providerName", providerName); + imageStoreParameters.put("role", role); + + ImageStoreVO ids = imageStoreHelper.createImageStore(imageStoreParameters, details); + return imageStoreMgr.getImageStore(ids.getId()); + } + + @Override + public boolean attachCluster(DataStore store, ClusterScope scope) { + return false; + } + + @Override + public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo) { + return false; + } + + + @Override + public boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisorType) { + return false; + } + + @Override + public boolean maintain(DataStore store) { + return false; + } + + @Override + public boolean cancelMaintain(DataStore store) { + return false; + } + + @Override + public boolean deleteDataStore(DataStore store) { + return false; + } +} diff --git a/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/provider/SwiftImageStoreProviderImpl.java b/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/provider/SwiftImageStoreProviderImpl.java new file mode 100644 index 00000000000..788eebcd145 --- /dev/null +++ b/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/provider/SwiftImageStoreProviderImpl.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.datastore.provider; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider; +import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; +import org.apache.cloudstack.engine.subsystem.api.storage.ImageStoreProvider; +import org.apache.cloudstack.storage.datastore.driver.SwiftImageStoreDriverImpl; +import org.apache.cloudstack.storage.datastore.lifecycle.SwiftImageStoreLifeCycleImpl; +import org.apache.cloudstack.storage.image.ImageStoreDriver; +import org.apache.cloudstack.storage.image.datastore.ImageStoreHelper; +import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager; +import org.apache.cloudstack.storage.image.store.lifecycle.ImageStoreLifeCycle; +import org.springframework.stereotype.Component; + +import com.cloud.storage.ScopeType; +import com.cloud.utils.component.ComponentContext; + +@Component +public class SwiftImageStoreProviderImpl implements ImageStoreProvider { + + private final String providerName = DataStoreProvider.SWIFT_IMAGE; + protected ImageStoreLifeCycle lifeCycle; + protected ImageStoreDriver driver; + @Inject + ImageStoreProviderManager storeMgr; + @Inject + ImageStoreHelper helper; + + @Override + public DataStoreLifeCycle getDataStoreLifeCycle() { + return lifeCycle; + } + + @Override + public String getName() { + return this.providerName; + } + + @Override + public boolean configure(Map params) { + lifeCycle = ComponentContext.inject(SwiftImageStoreLifeCycleImpl.class); + driver = ComponentContext.inject(SwiftImageStoreDriverImpl.class); + + storeMgr.registerDriver(this.getName(), driver); + + return true; + } + + @Override + public DataStoreDriver getDataStoreDriver() { + return this.driver; + } + + @Override + public HypervisorHostListener getHostListener() { + return null; + } + + @Override + public Set getTypes() { + Set types = new HashSet(); + types.add(DataStoreProviderType.IMAGE); + return types; + } + + @Override + public boolean isScopeSupported(ScopeType scope) { + if (scope == ScopeType.REGION) + return true; + return false; + } + + @Override + public boolean needDownloadSysTemplate() { + return true; + } + +} diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java index fa099d31b9f..8d7c965ee07 100644 --- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java +++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java @@ -18,347 +18,192 @@ */ package org.apache.cloudstack.storage.datastore.driver; -import java.util.Set; - -import javax.inject.Inject; - -import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; -import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; -import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; -import org.apache.cloudstack.framework.async.AsyncCompletionCallback; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.volume.VolumeObject; -import org.apache.log4j.Logger; - import com.cloud.agent.api.Answer; -import com.cloud.agent.api.ManageSnapshotAnswer; -import com.cloud.agent.api.ManageSnapshotCommand; -import com.cloud.agent.api.storage.CreateAnswer; -import com.cloud.agent.api.storage.CreateCommand; -import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.ResizeVolumeAnswer; import com.cloud.agent.api.storage.ResizeVolumeCommand; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.exception.StorageUnavailableException; -import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; -import com.cloud.server.ManagementServer; -import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.ResizeVolumePayload; -import com.cloud.storage.SnapshotVO; -import com.cloud.storage.Storage; -import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; -import com.cloud.storage.VMTemplateHostVO; -import com.cloud.storage.VMTemplateStoragePoolVO; -import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VolumeManager; -import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.snapshot.SnapshotManager; -import com.cloud.template.TemplateManager; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.vm.DiskProfile; import com.cloud.vm.dao.VMInstanceDao; +import org.apache.cloudstack.engine.subsystem.api.storage.*; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.storage.command.CommandResult; +import org.apache.cloudstack.storage.command.CreateObjectCommand; +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.volume.VolumeObject; +import org.apache.log4j.Logger; + +import javax.inject.Inject; public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver { - private static final Logger s_logger = Logger - .getLogger(CloudStackPrimaryDataStoreDriverImpl.class); - @Inject DiskOfferingDao diskOfferingDao; - @Inject VMTemplateDao templateDao; - @Inject VolumeDao volumeDao; - @Inject TemplateManager templateMgr; - @Inject HostDao hostDao; - @Inject StorageManager storageMgr; - @Inject VolumeManager volumeMgr; - @Inject VMInstanceDao vmDao; - @Inject SnapshotDao snapshotDao; - @Inject PrimaryDataStoreDao primaryStoreDao; - @Inject SnapshotManager snapshotMgr; - @Inject ManagementServer _mgmtSrvr; - @Override - public String grantAccess(DataObject data, EndPoint ep) { - // TODO Auto-generated method stub - return null; - } + private static final Logger s_logger = Logger.getLogger(CloudStackPrimaryDataStoreDriverImpl.class); + @Inject + DiskOfferingDao diskOfferingDao; + @Inject + VMTemplateDao templateDao; + @Inject + VolumeDao volumeDao; + @Inject + HostDao hostDao; + @Inject + StorageManager storageMgr; + @Inject + VolumeManager volumeMgr; + @Inject + VMInstanceDao vmDao; + @Inject + SnapshotDao snapshotDao; + @Inject + PrimaryDataStoreDao primaryStoreDao; + @Inject + SnapshotManager snapshotMgr; + @Inject + EndPointSelector epSelector; - @Override - public boolean revokeAccess(DataObject data, EndPoint ep) { - // TODO Auto-generated method stub - return false; - } + @Override + public DataTO getTO(DataObject data) { + return null; + } - @Override - public Set listObjects(DataStore store) { - // TODO Auto-generated method stub - return null; - } + @Override + public DataStoreTO getStoreTO(DataStore store) { + return null; + } - public boolean createVolume( - VolumeInfo volume) throws StorageUnavailableException { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Creating volume: " + volume); - } + public Answer createVolume(VolumeInfo volume) throws StorageUnavailableException { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Creating volume: " + volume); + } - DiskOfferingVO offering = diskOfferingDao.findById(volume.getDiskOfferingId()); - DiskProfile diskProfile = new DiskProfile(volume, offering, - null); + CreateObjectCommand cmd = new CreateObjectCommand(volume.getTO()); + EndPoint ep = epSelector.select(volume); + Answer answer = ep.sendMessage(cmd); + return answer; + } - VMTemplateVO template = null; - if (volume.getTemplateId() != null) { - template = templateDao.findById(volume.getTemplateId()); - } + @Override + public void createAsync(DataObject data, AsyncCompletionCallback callback) { + String errMsg = null; + Answer answer = null; + if (data.getType() == DataObjectType.VOLUME) { + try { + answer = createVolume((VolumeInfo) data); + } catch (StorageUnavailableException e) { + s_logger.debug("failed to create volume", e); + errMsg = e.toString(); + } catch (Exception e) { + s_logger.debug("failed to create volume", e); + errMsg = e.toString(); + } + } + CreateCmdResult result = new CreateCmdResult(null, answer); + if (errMsg != null) { + result.setResult(errMsg); + } - StoragePool pool = (StoragePool)volume.getDataStore(); - VolumeVO vol = volumeDao.findById(volume.getId()); - if (pool != null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Trying to create in " + pool); - } - vol.setPoolId(pool.getId()); - - CreateCommand cmd = null; - VMTemplateStoragePoolVO tmpltStoredOn = null; - - for (int i = 0; i < 2; i++) { - if (template != null - && template.getFormat() != Storage.ImageFormat.ISO) { - if (pool.getPoolType() == StoragePoolType.CLVM) { - // prepareISOForCreate does what we need, which is to - // tell us where the template is - VMTemplateHostVO tmpltHostOn = templateMgr - .prepareISOForCreate(template, pool); - if (tmpltHostOn == null) { - s_logger.debug("cannot find template " - + template.getId() + " " - + template.getName()); - throw new CloudRuntimeException("cannot find template" - + template.getId() - + template.getName()); - } - HostVO secondaryStorageHost = hostDao - .findById(tmpltHostOn.getHostId()); - String tmpltHostUrl = secondaryStorageHost - .getStorageUrl(); - String fullTmpltUrl = tmpltHostUrl + "/" - + tmpltHostOn.getInstallPath(); - cmd = new CreateCommand(diskProfile, fullTmpltUrl, - new StorageFilerTO(pool), _mgmtSrvr.getExecuteInSequence()); - } else { - tmpltStoredOn = templateMgr.prepareTemplateForCreate( - template, pool); - if (tmpltStoredOn == null) { - s_logger.debug("Cannot use this pool " + pool - + " because we can't propagate template " - + template); - throw new CloudRuntimeException("Cannot use this pool " + pool - + " because we can't propagate template " - + template); - } - cmd = new CreateCommand(diskProfile, - tmpltStoredOn.getLocalDownloadPath(), - new StorageFilerTO(pool), _mgmtSrvr.getExecuteInSequence()); - } - } else { - if (template != null - && Storage.ImageFormat.ISO == template.getFormat()) { - VMTemplateHostVO tmpltHostOn = templateMgr - .prepareISOForCreate(template, pool); - if (tmpltHostOn == null) { - throw new CloudRuntimeException( - "Did not find ISO in secondry storage in zone " - + pool.getDataCenterId()); - } - } - cmd = new CreateCommand(diskProfile, new StorageFilerTO( - pool), _mgmtSrvr.getExecuteInSequence()); - } - - Answer answer = storageMgr.sendToPool(pool, null, cmd); - if (answer.getResult()) { - CreateAnswer createAnswer = (CreateAnswer) answer; - vol.setFolder(pool.getPath()); - vol.setPath(createAnswer.getVolume().getPath()); - vol.setSize(createAnswer.getVolume().getSize()); - vol.setPoolType(pool.getPoolType()); - vol.setPoolId(pool.getId()); - vol.setPodId(pool.getPodId()); - this.volumeDao.update(vol.getId(), vol); - return true; - } else { - if (tmpltStoredOn != null - && (answer instanceof CreateAnswer) - && ((CreateAnswer) answer) - .templateReloadRequested()) { - if (!templateMgr - .resetTemplateDownloadStateOnPool(tmpltStoredOn - .getId())) { - break; // break out of template-redeploy retry loop - } - } else { - break; - } - } - } - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Unable to create volume " + volume.getId()); - } - return false; - } - - @Override - public void createAsync(DataObject data, - AsyncCompletionCallback callback) { - // TODO Auto-generated method stub - String errMsg = null; - if (data.getType() == DataObjectType.VOLUME) { - try { - createVolume((VolumeInfo)data); - } catch (StorageUnavailableException e) { - s_logger.debug("failed to create volume", e); - errMsg = e.toString(); - } catch (Exception e) { - s_logger.debug("failed to create volume", e); - errMsg = e.toString(); - } - } - CreateCmdResult result = new CreateCmdResult(null, null); - if (errMsg != null) { - result.setResult(errMsg); - } - - callback.complete(result); - - } - - @Override - public void deleteAsync(DataObject data, - AsyncCompletionCallback callback) { - - String vmName = null; - VolumeVO vol = this.volumeDao.findById(data.getId()); - - - StoragePool pool = (StoragePool)data.getDataStore(); - - DestroyCommand cmd = new DestroyCommand(pool, vol, vmName); - - CommandResult result = new CommandResult(); - try { - Answer answer = this.storageMgr.sendToPool(pool, cmd); - if (answer != null && !answer.getResult()) { - result.setResult(answer.getDetails()); - s_logger.info("Will retry delete of " + vol + " from " + pool.getId()); - } - } catch (StorageUnavailableException e) { - s_logger.error("Storage is unavailable currently. Will retry delete of " - + vol + " from " + pool.getId(), e); - result.setResult(e.toString()); - } catch (Exception ex) { - s_logger.debug("Unable to destoy volume" + vol + " from " + pool.getId(), ex); - result.setResult(ex.toString()); - } - callback.complete(result); - } - - @Override - public void copyAsync(DataObject srcdata, DataObject destData, - AsyncCompletionCallback callback) { - // TODO Auto-generated method stub - - } - - @Override - public boolean canCopy(DataObject srcData, DataObject destData) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void takeSnapshot(SnapshotInfo snapshot, - AsyncCompletionCallback callback) { - CreateCmdResult result = null; - try { - VolumeInfo volume = snapshot.getBaseVolume(); - String vmName = this.volumeMgr.getVmNameOnVolume(volume); - SnapshotVO preSnapshotVO = this.snapshotMgr.getParentSnapshot(volume, snapshot); - String parentSnapshotPath = null; - if (preSnapshotVO != null) { - parentSnapshotPath = preSnapshotVO.getPath(); - } - StoragePool srcPool = (StoragePool)volume.getDataStore(); - - ManageSnapshotCommand cmd = new ManageSnapshotCommand(snapshot.getId(), volume.getPath(), srcPool, parentSnapshotPath, snapshot.getName(), vmName); - - ManageSnapshotAnswer answer = (ManageSnapshotAnswer) this.snapshotMgr.sendToPool(volume, cmd); - - if ((answer != null) && answer.getResult()) { - result = new CreateCmdResult(answer.getSnapshotPath(), null); - } else { - result = new CreateCmdResult(null, null); - } - } catch (Exception e) { - s_logger.debug("Failed to take snapshot: " + snapshot.getId(), e); - result = new CreateCmdResult(null, null); - result.setResult(e.toString()); - } callback.complete(result); - } + } - @Override - public void revertSnapshot(SnapshotInfo snapshot, - AsyncCompletionCallback callback) { - // TODO Auto-generated method stub + @Override + public void deleteAsync(DataObject data, AsyncCompletionCallback callback) { + DeleteCommand cmd = new DeleteCommand(data.getTO()); - } + CommandResult result = new CommandResult(); + try { + EndPoint ep = epSelector.select(data); + Answer answer = ep.sendMessage(cmd); + if (answer != null && !answer.getResult()) { + result.setResult(answer.getDetails()); + } + } catch (Exception ex) { + s_logger.debug("Unable to destoy volume" + data.getId(), ex); + result.setResult(ex.toString()); + } + callback.complete(result); + } - @Override - public void resize(DataObject data, - AsyncCompletionCallback callback) { - VolumeObject vol = (VolumeObject)data; - StoragePool pool = (StoragePool)data.getDataStore(); - ResizeVolumePayload resizeParameter = (ResizeVolumePayload)vol.getpayload(); + @Override + public void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback callback) { + } - ResizeVolumeCommand resizeCmd = new ResizeVolumeCommand( - vol.getPath(), new StorageFilerTO(pool), vol.getSize(), - resizeParameter.newSize, resizeParameter.shrinkOk, resizeParameter.instanceName); - CreateCmdResult result = new CreateCmdResult(null, null); - try { - ResizeVolumeAnswer answer = (ResizeVolumeAnswer) this.storageMgr.sendToPool(pool, - resizeParameter.hosts, resizeCmd); - if (answer != null && answer.getResult()) { - long finalSize = answer.getNewSize(); - s_logger.debug("Resize: volume started at size " + vol.getSize() - + " and ended at size " + finalSize); + @Override + public boolean canCopy(DataObject srcData, DataObject destData) { + return false; + } - vol.setSize(finalSize); - vol.update(); - } else if (answer != null) { - result.setResult(answer.getDetails()); - } else { - s_logger.debug("return a null answer, mark it as failed for unknown reason"); - result.setResult("return a null answer, mark it as failed for unknown reason"); - } + @Override + public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback) { + CreateCmdResult result = null; + try { + DataTO snapshotTO = snapshot.getTO(); - } catch (Exception e) { - s_logger.debug("sending resize command failed", e); - result.setResult(e.toString()); - } + CreateObjectCommand cmd = new CreateObjectCommand(snapshotTO); + EndPoint ep = this.epSelector.select(snapshot); + Answer answer = ep.sendMessage(cmd); - callback.complete(result); - } + result = new CreateCmdResult(null, answer); + if (answer != null && !answer.getResult()) { + result.setResult(answer.getDetails()); + } + + callback.complete(result); + return; + } catch (Exception e) { + s_logger.debug("Failed to take snapshot: " + snapshot.getId(), e); + result = new CreateCmdResult(null, null); + result.setResult(e.toString()); + } + callback.complete(result); + } + + @Override + public void revertSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback) { + } + + @Override + public void resize(DataObject data, AsyncCompletionCallback callback) { + VolumeObject vol = (VolumeObject) data; + StoragePool pool = (StoragePool) data.getDataStore(); + ResizeVolumePayload resizeParameter = (ResizeVolumePayload) vol.getpayload(); + + ResizeVolumeCommand resizeCmd = new ResizeVolumeCommand(vol.getPath(), new StorageFilerTO(pool), vol.getSize(), + resizeParameter.newSize, resizeParameter.shrinkOk, resizeParameter.instanceName); + CreateCmdResult result = new CreateCmdResult(null, null); + try { + ResizeVolumeAnswer answer = (ResizeVolumeAnswer) this.storageMgr.sendToPool(pool, resizeParameter.hosts, + resizeCmd); + if (answer != null && answer.getResult()) { + long finalSize = answer.getNewSize(); + s_logger.debug("Resize: volume started at size " + vol.getSize() + " and ended at size " + finalSize); + + vol.setSize(finalSize); + vol.update(); + } else if (answer != null) { + result.setResult(answer.getDetails()); + } else { + s_logger.debug("return a null answer, mark it as failed for unknown reason"); + result.setResult("return a null answer, mark it as failed for unknown reason"); + } + + } catch (Exception e) { + s_logger.debug("sending resize command failed", e); + result.setResult(e.toString()); + } + + callback.complete(result); + } } diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java index fb37e8f4b10..2e0ff66baa1 100644 --- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java +++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java @@ -75,10 +75,8 @@ import com.cloud.vm.dao.SecondaryStorageVmDao; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; -public class CloudStackPrimaryDataStoreLifeCycleImpl implements - PrimaryDataStoreLifeCycle { - private static final Logger s_logger = Logger - .getLogger(CloudStackPrimaryDataStoreLifeCycleImpl.class); +public class CloudStackPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLifeCycle { + private static final Logger s_logger = Logger.getLogger(CloudStackPrimaryDataStoreLifeCycleImpl.class); @Inject protected ResourceManager _resourceMgr; protected List _discoverers; @@ -93,7 +91,6 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements @Inject StorageManager storageMgr; - @Inject VolumeDao volumeDao; @Inject @@ -124,16 +121,16 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements @Inject StoragePoolAutomation storagePoolAutmation; + @SuppressWarnings("unchecked") @Override public DataStore initialize(Map dsInfos) { Long clusterId = (Long) dsInfos.get("clusterId"); Long podId = (Long) dsInfos.get("podId"); Long zoneId = (Long) dsInfos.get("zoneId"); String url = (String) dsInfos.get("url"); - String providerName = (String)dsInfos.get("providerName"); + String providerName = (String) dsInfos.get("providerName"); if (clusterId != null && podId == null) { - throw new InvalidParameterValueException( - "Cluster id requires pod id"); + throw new InvalidParameterValueException("Cluster id requires pod id"); } PrimaryDataStoreParameters parameters = new PrimaryDataStoreParameters(); @@ -142,15 +139,12 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements try { uri = new URI(UriUtils.encodeURIComponent(url)); if (uri.getScheme() == null) { - throw new InvalidParameterValueException("scheme is null " - + url + ", add nfs:// as a prefix"); + throw new InvalidParameterValueException("scheme is null " + url + ", add nfs:// as a prefix"); } else if (uri.getScheme().equalsIgnoreCase("nfs")) { String uriHost = uri.getHost(); String uriPath = uri.getPath(); - if (uriHost == null || uriPath == null - || uriHost.trim().isEmpty() || uriPath.trim().isEmpty()) { - throw new InvalidParameterValueException( - "host or path is null, should be nfs://hostname/path"); + if (uriHost == null || uriPath == null || uriHost.trim().isEmpty() || uriPath.trim().isEmpty()) { + throw new InvalidParameterValueException("host or path is null, should be nfs://hostname/path"); } } else if (uri.getScheme().equalsIgnoreCase("sharedMountPoint")) { String uriPath = uri.getPath(); @@ -161,18 +155,15 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements } else if (uri.getScheme().equalsIgnoreCase("rbd")) { String uriPath = uri.getPath(); if (uriPath == null) { - throw new InvalidParameterValueException( - "host or path is null, should be rbd://hostname/pool"); + throw new InvalidParameterValueException("host or path is null, should be rbd://hostname/pool"); } } } catch (URISyntaxException e) { - throw new InvalidParameterValueException(url - + " is not a valid uri"); + throw new InvalidParameterValueException(url + " is not a valid uri"); } String tags = (String) dsInfos.get("tags"); - Map details = (Map) dsInfos - .get("details"); + Map details = (Map) dsInfos.get("details"); parameters.setTags(tags); parameters.setDetails(details); @@ -186,10 +177,8 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements } String userInfo = uri.getUserInfo(); int port = uri.getPort(); - StoragePool pool = null; if (s_logger.isDebugEnabled()) { - s_logger.debug("createPool Params @ scheme - " + scheme - + " storageHost - " + storageHost + " hostPath - " + s_logger.debug("createPool Params @ scheme - " + scheme + " storageHost - " + storageHost + " hostPath - " + hostPath + " port - " + port); } if (scheme.equalsIgnoreCase("nfs")) { @@ -240,8 +229,7 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements } if (lun != -1) { if (clusterId == null) { - throw new IllegalArgumentException( - "IscsiLUN need to have clusters specified"); + throw new IllegalArgumentException("IscsiLUN need to have clusters specified"); } hostPath.replaceFirst("/", ""); parameters.setType(StoragePoolType.IscsiLUN); @@ -254,14 +242,11 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements try { pools = discoverer.find(zoneId, podId, uri, details); } catch (DiscoveryException e) { - throw new IllegalArgumentException( - "Not enough information for discovery " + uri, - e); + throw new IllegalArgumentException("Not enough information for discovery " + uri, e); } if (pools != null) { - Map.Entry> entry = pools - .entrySet().iterator().next(); - pool = entry.getKey(); + Map.Entry> entry = pools.entrySet().iterator() + .next(); details = entry.getValue(); break; } @@ -295,19 +280,17 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements parameters.setPort(0); parameters.setPath(hostPath); } else { - s_logger.warn("Unable to figure out the scheme for URI: " + uri); - throw new IllegalArgumentException( - "Unable to figure out the scheme for URI: " + uri); + s_logger.warn("Unable to figure out the scheme for URI: " + uri); + throw new IllegalArgumentException("Unable to figure out the scheme for URI: " + uri); } } if (localStorage == null) { - List pools = primaryDataStoreDao - .listPoolByHostPath(storageHost, hostPath); + List pools = primaryDataStoreDao.listPoolByHostPath(storageHost, hostPath); if (!pools.isEmpty() && !scheme.equalsIgnoreCase("sharedmountpoint")) { Long oldPodId = pools.get(0).getPodId(); - throw new CloudRuntimeException("Storage pool " + uri - + " already in use by another pod (id=" + oldPodId + ")"); + throw new CloudRuntimeException("Storage pool " + uri + " already in use by another pod (id=" + + oldPodId + ")"); } } @@ -315,29 +298,23 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements String uuid = null; if (existingUuid != null) { - uuid = (String)existingUuid; - } else if (scheme.equalsIgnoreCase("sharedmountpoint") - || scheme.equalsIgnoreCase("clvm")) { + uuid = (String) existingUuid; + } else if (scheme.equalsIgnoreCase("sharedmountpoint") || scheme.equalsIgnoreCase("clvm")) { uuid = UUID.randomUUID().toString(); } else if (scheme.equalsIgnoreCase("PreSetup")) { uuid = hostPath.replace("/", ""); } else { - uuid = UUID.nameUUIDFromBytes( - new String(storageHost + hostPath).getBytes()).toString(); + uuid = UUID.nameUUIDFromBytes(new String(storageHost + hostPath).getBytes()).toString(); } - - List spHandles = primaryDataStoreDao - .findIfDuplicatePoolsExistByUUID(uuid); + List spHandles = primaryDataStoreDao.findIfDuplicatePoolsExistByUUID(uuid); if ((spHandles != null) && (spHandles.size() > 0)) { if (s_logger.isDebugEnabled()) { s_logger.debug("Another active pool with the same uuid already exists"); } - throw new CloudRuntimeException( - "Another active pool with the same uuid already exists"); + throw new CloudRuntimeException("Another active pool with the same uuid already exists"); } - String poolName = (String) dsInfos.get("name"); parameters.setUuid(uuid); @@ -351,20 +328,13 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements } protected boolean createStoragePool(long hostId, StoragePool pool) { - s_logger.debug("creating pool " + pool.getName() + " on host " - + hostId); - if (pool.getPoolType() != StoragePoolType.NetworkFilesystem - && pool.getPoolType() != StoragePoolType.Filesystem - && pool.getPoolType() != StoragePoolType.IscsiLUN - && pool.getPoolType() != StoragePoolType.Iscsi - && pool.getPoolType() != StoragePoolType.VMFS - && pool.getPoolType() != StoragePoolType.SharedMountPoint - && pool.getPoolType() != StoragePoolType.PreSetup - && pool.getPoolType() != StoragePoolType.OCFS2 - && pool.getPoolType() != StoragePoolType.RBD - && pool.getPoolType() != StoragePoolType.CLVM) { - s_logger.warn(" Doesn't support storage pool type " - + pool.getPoolType()); + s_logger.debug("creating pool " + pool.getName() + " on host " + hostId); + if (pool.getPoolType() != StoragePoolType.NetworkFilesystem && pool.getPoolType() != StoragePoolType.Filesystem + && pool.getPoolType() != StoragePoolType.IscsiLUN && pool.getPoolType() != StoragePoolType.Iscsi + && pool.getPoolType() != StoragePoolType.VMFS && pool.getPoolType() != StoragePoolType.SharedMountPoint + && pool.getPoolType() != StoragePoolType.PreSetup && pool.getPoolType() != StoragePoolType.OCFS2 + && pool.getPoolType() != StoragePoolType.RBD && pool.getPoolType() != StoragePoolType.CLVM) { + s_logger.warn(" Doesn't support storage pool type " + pool.getPoolType()); return false; } CreateStoragePoolCommand cmd = new CreateStoragePoolCommand(true, pool); @@ -375,8 +345,7 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements primaryDataStoreDao.expunge(pool.getId()); String msg = ""; if (answer != null) { - msg = "Can not create storage pool through host " + hostId - + " due to " + answer.getDetails(); + msg = "Can not create storage pool through host " + hostId + " due to " + answer.getDetails(); s_logger.warn(msg); } else { msg = "Can not create storage pool through host " + hostId @@ -391,19 +360,15 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements public boolean attachCluster(DataStore store, ClusterScope scope) { PrimaryDataStoreInfo primarystore = (PrimaryDataStoreInfo) store; // Check if there is host up in this cluster - List allHosts = _resourceMgr.listAllUpAndEnabledHosts( - Host.Type.Routing, primarystore.getClusterId(), + List allHosts = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.Routing, primarystore.getClusterId(), primarystore.getPodId(), primarystore.getDataCenterId()); if (allHosts.isEmpty()) { - throw new CloudRuntimeException( - "No host up to associate a storage pool with in cluster " - + primarystore.getClusterId()); + throw new CloudRuntimeException("No host up to associate a storage pool with in cluster " + + primarystore.getClusterId()); } - if (primarystore.getPoolType() == StoragePoolType.OCFS2 - && !_ocfs2Mgr.prepareNodes(allHosts, primarystore)) { - s_logger.warn("Can not create storage pool " + primarystore - + " on cluster " + primarystore.getClusterId()); + if (primarystore.getPoolType() == StoragePoolType.OCFS2 && !_ocfs2Mgr.prepareNodes(allHosts, primarystore)) { + s_logger.warn("Can not create storage pool " + primarystore + " on cluster " + primarystore.getClusterId()); primaryDataStoreDao.expunge(primarystore.getId()); return false; } @@ -420,18 +385,16 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements List poolHosts = new ArrayList(); for (HostVO h : allHosts) { try { - this.storageMgr.connectHostToSharedPool(h.getId(), - primarystore.getId()); + this.storageMgr.connectHostToSharedPool(h.getId(), primarystore.getId()); poolHosts.add(h); } catch (Exception e) { - s_logger.warn("Unable to establish a connection between " + h - + " and " + primarystore, e); + s_logger.warn("Unable to establish a connection between " + h + " and " + primarystore, e); } } if (poolHosts.isEmpty()) { - s_logger.warn("No host can access storage pool " + primarystore - + " on cluster " + primarystore.getClusterId()); + s_logger.warn("No host can access storage pool " + primarystore + " on cluster " + + primarystore.getClusterId()); primaryDataStoreDao.expunge(primarystore.getId()); return false; } @@ -445,29 +408,15 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements List hosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor(hypervisorType, scope.getScopeId()); for (HostVO host : hosts) { try { - this.storageMgr.connectHostToSharedPool(host.getId(), - dataStore.getId()); + this.storageMgr.connectHostToSharedPool(host.getId(), dataStore.getId()); } catch (Exception e) { - s_logger.warn("Unable to establish a connection between " + host - + " and " + dataStore, e); + s_logger.warn("Unable to establish a connection between " + host + " and " + dataStore, e); } } this.dataStoreHelper.attachZone(dataStore, hypervisorType); return true; } - @Override - public boolean dettach() { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean unmanaged() { - // TODO Auto-generated method stub - return false; - } - @Override public boolean maintain(DataStore dataStore) { storagePoolAutmation.maintain(dataStore); @@ -485,16 +434,13 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements @DB @Override public boolean deleteDataStore(DataStore store) { - List hostPoolRecords = this._storagePoolHostDao - .listByPoolId(store.getId()); - StoragePool pool = (StoragePool)store; + List hostPoolRecords = this._storagePoolHostDao.listByPoolId(store.getId()); + StoragePool pool = (StoragePool) store; boolean deleteFlag = false; // Remove the SR associated with the Xenserver for (StoragePoolHostVO host : hostPoolRecords) { - DeleteStoragePoolCommand deleteCmd = new DeleteStoragePoolCommand( - pool); - final Answer answer = agentMgr.easySend(host.getHostId(), - deleteCmd); + DeleteStoragePoolCommand deleteCmd = new DeleteStoragePoolCommand(pool); + final Answer answer = agentMgr.easySend(host.getHostId(), deleteCmd); if (answer != null && answer.getResult()) { deleteFlag = true; diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/provider/CloudStackPrimaryDataStoreProviderImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/provider/CloudStackPrimaryDataStoreProviderImpl.java index 826f07ae07e..410416c4499 100644 --- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/provider/CloudStackPrimaryDataStoreProviderImpl.java +++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/provider/CloudStackPrimaryDataStoreProviderImpl.java @@ -23,6 +23,7 @@ import java.util.Map; import java.util.Set; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider; import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreProvider; @@ -31,18 +32,17 @@ import org.apache.cloudstack.storage.datastore.lifecycle.CloudStackPrimaryDataSt import com.cloud.utils.component.ComponentContext; -public class CloudStackPrimaryDataStoreProviderImpl implements - PrimaryDataStoreProvider { +public class CloudStackPrimaryDataStoreProviderImpl implements PrimaryDataStoreProvider { - private final String providerName = "ancient primary data store provider"; + private final String providerName = DataStoreProvider.DEFAULT_PRIMARY; protected PrimaryDataStoreDriver driver; protected HypervisorHostListener listener; protected DataStoreLifeCycle lifecycle; CloudStackPrimaryDataStoreProviderImpl() { - + } - + @Override public String getName() { return providerName; @@ -70,10 +70,10 @@ public class CloudStackPrimaryDataStoreProviderImpl implements public HypervisorHostListener getHostListener() { return this.listener; } - + @Override public Set getTypes() { - Set types = new HashSet(); + Set types = new HashSet(); types.add(DataStoreProviderType.PRIMARY); return types; } diff --git a/plugins/storage/volume/sample/pom.xml b/plugins/storage/volume/sample/pom.xml new file mode 100644 index 00000000000..2e2fdb51806 --- /dev/null +++ b/plugins/storage/volume/sample/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + cloud-plugin-storage-volume-sample + Apache CloudStack Plugin - Storage Volume sample provider + + org.apache.cloudstack + cloudstack-plugins + 4.2.0-SNAPSHOT + ../../../pom.xml + + + + org.apache.cloudstack + cloud-engine-storage-volume + ${project.version} + + + mysql + mysql-connector-java + ${cs.mysql.version} + provided + + + + install + src + test + + + maven-surefire-plugin + + true + + + + integration-test + + test + + + + + + + diff --git a/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java b/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java new file mode 100644 index 00000000000..643c9334964 --- /dev/null +++ b/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java @@ -0,0 +1,181 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.datastore.driver; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.storage.dao.StoragePoolHostDao; +import org.apache.cloudstack.engine.subsystem.api.storage.*; +import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.framework.async.AsyncRpcConext; +import org.apache.cloudstack.storage.command.CommandResult; +import org.apache.cloudstack.storage.command.CreateObjectCommand; +import org.apache.cloudstack.storage.datastore.DataObjectManager; +import org.apache.log4j.Logger; + +import javax.inject.Inject; + +public class SamplePrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver { + private static final Logger s_logger = Logger.getLogger(SamplePrimaryDataStoreDriverImpl.class); + @Inject + EndPointSelector selector; + @Inject + StoragePoolHostDao storeHostDao; + @Inject + DataObjectManager dataObjMgr; + + public SamplePrimaryDataStoreDriverImpl() { + + } + + @Override + public DataTO getTO(DataObject data) { + return null; + } + + @Override + public DataStoreTO getStoreTO(DataStore store) { + return null; + } + + private class CreateVolumeContext extends AsyncRpcConext { + private final DataObject volume; + public CreateVolumeContext(AsyncCompletionCallback callback, DataObject volume) { + super(callback); + this.volume = volume; + } + } + + public Void createAsyncCallback(AsyncCallbackDispatcher callback, + CreateVolumeContext context) { + /* + * CreateCmdResult result = null; CreateObjectAnswer volAnswer = + * (CreateObjectAnswer) callback.getResult(); if (volAnswer.getResult()) + * { result = new CreateCmdResult(volAnswer.getPath(), volAnswer); } + * else { result = new CreateCmdResult("", null); + * result.setResult(volAnswer.getDetails()); } + * + * context.getParentCallback().complete(result); + */ + return null; + } + + @Override + public void deleteAsync(DataObject vo, AsyncCompletionCallback callback) { + /* + * DeleteCommand cmd = new DeleteCommand(vo.getUri()); + * + * EndPoint ep = selector.select(vo); AsyncRpcConext + * context = new AsyncRpcConext(callback); + * AsyncCallbackDispatcher + * caller = AsyncCallbackDispatcher.create(this); + * caller.setCallback(caller.getTarget().deleteCallback(null, null)) + * .setContext(context); ep.sendMessageAsync(cmd, caller); + */ + } + + public Void deleteCallback(AsyncCallbackDispatcher callback, + AsyncRpcConext context) { + CommandResult result = new CommandResult(); + Answer answer = callback.getResult(); + if (!answer.getResult()) { + result.setResult(answer.getDetails()); + } + context.getParentCallback().complete(result); + return null; + } + + /* + * private class CreateVolumeFromBaseImageContext extends + * AsyncRpcConext { private final VolumeObject volume; + * + * public CreateVolumeFromBaseImageContext(AsyncCompletionCallback + * callback, VolumeObject volume) { super(callback); this.volume = volume; } + * + * public VolumeObject getVolume() { return this.volume; } + * + * } + * + * @Override public void createVolumeFromBaseImageAsync(VolumeObject volume, + * TemplateInfo template, AsyncCompletionCallback callback) { + * VolumeTO vol = this.dataStore.getVolumeTO(volume); List + * endPoints = this.dataStore.getEndPoints(); EndPoint ep = + * endPoints.get(0); String templateUri = + * template.getDataStore().grantAccess(template, ep); + * CreateVolumeFromBaseImageCommand cmd = new + * CreateVolumeFromBaseImageCommand(vol, templateUri); + * + * CreateVolumeFromBaseImageContext context = new + * CreateVolumeFromBaseImageContext(callback, volume); + * AsyncCallbackDispatcher caller + * = AsyncCallbackDispatcher.create(this); caller.setContext(context) + * .setCallback + * (caller.getTarget().createVolumeFromBaseImageAsyncCallback(null, null)); + * + * ep.sendMessageAsync(cmd, caller); } + */ + /* + * public Object + * createVolumeFromBaseImageAsyncCallback(AsyncCallbackDispatcher + * callback, + * CreateVolumeFromBaseImageContext context) { + * CreateVolumeAnswer answer = (CreateVolumeAnswer)callback.getResult(); + * CommandResult result = new CommandResult(); if (answer == null || + * answer.getDetails() != null) { result.setSuccess(false); if (answer != + * null) { result.setResult(answer.getDetails()); } } else { + * result.setSuccess(true); VolumeObject volume = context.getVolume(); + * volume.setPath(answer.getVolumeUuid()); } + * AsyncCompletionCallback parentCall = + * context.getParentCallback(); parentCall.complete(result); return null; } + */ + + @Override + public void createAsync(DataObject vol, AsyncCompletionCallback callback) { + EndPoint ep = selector.select(vol); + CreateObjectCommand createCmd = new CreateObjectCommand(null); + + CreateVolumeContext context = new CreateVolumeContext(callback, vol); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setContext(context).setCallback(caller.getTarget().createAsyncCallback(null, null)); + + ep.sendMessageAsync(createCmd, caller); + } + + @Override + public void revertSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback) { + } + + @Override + public boolean canCopy(DataObject srcData, DataObject destData) { + return false; + } + + @Override + public void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback callback) { + } + + @Override + public void resize(DataObject data, AsyncCompletionCallback callback) { + } + + @Override + public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback) { + } + +} diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java b/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/lifecycle/SamplePrimaryDataStoreLifeCycleImpl.java similarity index 74% rename from engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java rename to plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/lifecycle/SamplePrimaryDataStoreLifeCycleImpl.java index cffa1cee4dc..92538ad5f4b 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java +++ b/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/lifecycle/SamplePrimaryDataStoreLifeCycleImpl.java @@ -18,32 +18,24 @@ */ package org.apache.cloudstack.storage.datastore.lifecycle; -import java.util.List; -import java.util.Map; - -import javax.inject.Inject; - -import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; -import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; -import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle; -import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; -import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd; -import org.apache.cloudstack.storage.command.CreatePrimaryDataStoreCmd; -import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.cloudstack.storage.endpoint.EndPointSelector; -import org.apache.cloudstack.storage.volume.datastore.PrimaryDataStoreHelper; - import com.cloud.agent.api.StoragePoolInfo; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.StoragePoolStatus; +import org.apache.cloudstack.engine.subsystem.api.storage.*; +import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd; +import org.apache.cloudstack.storage.command.CreatePrimaryDataStoreCmd; +import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.storage.volume.datastore.PrimaryDataStoreHelper; -public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLifeCycle { +import javax.inject.Inject; +import java.util.List; +import java.util.Map; + +public class SamplePrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLifeCycle { @Inject EndPointSelector selector; @Inject @@ -54,18 +46,20 @@ public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLif PrimaryDataStoreHelper primaryStoreHelper; @Inject PrimaryDataStoreProviderManager providerMgr; - public DefaultPrimaryDataStoreLifeCycleImpl() { + + public SamplePrimaryDataStoreLifeCycleImpl() { } - + @Override public DataStore initialize(Map dsInfos) { - - DataStore store = primaryStoreHelper.createPrimaryDataStore(null); + + DataStore store = primaryStoreHelper.createPrimaryDataStore(null); return providerMgr.getPrimaryDataStore(store.getId()); } protected void attachCluster(DataStore store) { - //send down AttachPrimaryDataStoreCmd command to all the hosts in the cluster + // send down AttachPrimaryDataStoreCmd command to all the hosts in the + // cluster List endPoints = selector.selectAll(store); CreatePrimaryDataStoreCmd createCmd = new CreatePrimaryDataStoreCmd(store.getUri()); EndPoint ep = endPoints.get(0); @@ -73,14 +67,14 @@ public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLif if (host.getHypervisorType() == HypervisorType.XenServer) { ep.sendMessage(createCmd); } - + endPoints.get(0).sendMessage(createCmd); AttachPrimaryDataStoreCmd cmd = new AttachPrimaryDataStoreCmd(store.getUri()); for (EndPoint endp : endPoints) { endp.sendMessage(cmd); } } - + @Override public boolean attachCluster(DataStore dataStore, ClusterScope scope) { StoragePoolVO dataStoreVO = dataStoreDao.findById(dataStore.getId()); @@ -90,57 +84,38 @@ public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLif dataStoreVO.setStatus(StoragePoolStatus.Attaching); dataStoreVO.setScope(scope.getScopeType()); dataStoreDao.update(dataStoreVO.getId(), dataStoreVO); - - + attachCluster(dataStore); - + dataStoreVO = dataStoreDao.findById(dataStore.getId()); dataStoreVO.setStatus(StoragePoolStatus.Up); dataStoreDao.update(dataStoreVO.getId(), dataStoreVO); - + return true; } - @Override - public boolean dettach() { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean unmanaged() { - // TODO Auto-generated method stub - return false; - } - @Override public boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisorType) { - // TODO Auto-generated method stub return false; } @Override - public boolean attachHost(DataStore store, HostScope scope, - StoragePoolInfo existingInfo) { - // TODO Auto-generated method stub + public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo) { return false; } @Override public boolean maintain(DataStore store) { - // TODO Auto-generated method stub return false; } @Override public boolean cancelMaintain(DataStore store) { - // TODO Auto-generated method stub return false; } @Override public boolean deleteDataStore(DataStore store) { - // TODO Auto-generated method stub return false; } diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/provider/DefaultPrimaryDatastoreProviderImpl.java b/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/provider/SamplePrimaryDatastoreProviderImpl.java similarity index 73% rename from engine/storage/volume/src/org/apache/cloudstack/storage/datastore/provider/DefaultPrimaryDatastoreProviderImpl.java rename to plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/provider/SamplePrimaryDatastoreProviderImpl.java index 8c674dc0444..79ffc8fe4a1 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/provider/DefaultPrimaryDatastoreProviderImpl.java +++ b/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/provider/SamplePrimaryDatastoreProviderImpl.java @@ -23,28 +23,24 @@ import java.util.Set; import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider; import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreProvider; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider.DataStoreProviderType; import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager; -import org.apache.cloudstack.storage.datastore.driver.DefaultPrimaryDataStoreDriverImpl; -import org.apache.cloudstack.storage.datastore.lifecycle.DefaultPrimaryDataStoreLifeCycleImpl; +import org.apache.cloudstack.storage.datastore.driver.SamplePrimaryDataStoreDriverImpl; +import org.apache.cloudstack.storage.datastore.lifecycle.SamplePrimaryDataStoreLifeCycleImpl; import com.cloud.utils.component.ComponentContext; - -public class DefaultPrimaryDatastoreProviderImpl implements PrimaryDataStoreProvider { - private final String providerName = "default primary data store provider"; +public class SamplePrimaryDatastoreProviderImpl implements PrimaryDataStoreProvider { + private final String providerName = "sample primary data store provider"; protected PrimaryDataStoreDriver driver; protected HypervisorHostListener listener; @Inject PrimaryDataStoreProviderManager storeMgr; protected DataStoreLifeCycle lifecycle; - protected String uuid; - protected long id; + @Override public String getName() { return providerName; @@ -57,8 +53,8 @@ public class DefaultPrimaryDatastoreProviderImpl implements PrimaryDataStoreProv @Override public boolean configure(Map params) { - lifecycle = ComponentContext.inject(DefaultPrimaryDataStoreLifeCycleImpl.class); - driver = ComponentContext.inject(DefaultPrimaryDataStoreDriverImpl.class); + lifecycle = ComponentContext.inject(SamplePrimaryDataStoreLifeCycleImpl.class); + driver = ComponentContext.inject(SamplePrimaryDataStoreDriverImpl.class); listener = ComponentContext.inject(DefaultHostListener.class); return true; } @@ -72,10 +68,10 @@ public class DefaultPrimaryDatastoreProviderImpl implements PrimaryDataStoreProv public HypervisorHostListener getHostListener() { return this.listener; } - + @Override public Set getTypes() { - Set types = new HashSet(); + Set types = new HashSet(); types.add(DataStoreProviderType.PRIMARY); return types; } diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java index f31126c2aeb..960378c2821 100644 --- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java +++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java @@ -16,81 +16,51 @@ // under the License. package org.apache.cloudstack.storage.datastore.driver; -import java.util.Set; - -import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; -import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; -import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import org.apache.cloudstack.engine.subsystem.api.storage.*; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.storage.command.CommandResult; public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver { @Override - public String grantAccess(DataObject data, EndPoint ep) { - // TODO Auto-generated method stub + public DataTO getTO(DataObject data) { return null; } @Override - public boolean revokeAccess(DataObject data, EndPoint ep) { - // TODO Auto-generated method stub - return false; - } - - @Override - public Set listObjects(DataStore store) { - // TODO Auto-generated method stub + public DataStoreTO getStoreTO(DataStore store) { return null; } @Override public void createAsync(DataObject data, AsyncCompletionCallback callback) { - // TODO Auto-generated method stub - } @Override public void deleteAsync(DataObject data, AsyncCompletionCallback callback) { - // TODO Auto-generated method stub - } @Override public void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback callback) { - // TODO Auto-generated method stub - } @Override public boolean canCopy(DataObject srcData, DataObject destData) { - // TODO Auto-generated method stub return false; } @Override public void revertSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback) { - // TODO Auto-generated method stub - } - @Override - public void resize(DataObject data, - AsyncCompletionCallback callback) { - // TODO Auto-generated method stub - - } - - @Override - public void takeSnapshot(SnapshotInfo snapshot, - AsyncCompletionCallback callback) { - // TODO Auto-generated method stub - - } + @Override + public void resize(DataObject data, AsyncCompletionCallback callback) { + } + @Override + public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback) { + } } diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/provider/SolidfirePrimaryDataStoreProvider.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/provider/SolidfirePrimaryDataStoreProvider.java index 650cac8518d..2965e8ff58e 100644 --- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/provider/SolidfirePrimaryDataStoreProvider.java +++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/provider/SolidfirePrimaryDataStoreProvider.java @@ -16,24 +16,47 @@ // under the License. package org.apache.cloudstack.storage.datastore.provider; +import java.util.Map; +import java.util.Set; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle; +import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreProvider; import org.springframework.stereotype.Component; @Component -public class SolidfirePrimaryDataStoreProvider extends - DefaultPrimaryDatastoreProviderImpl { - private final String name = "Solidfre Primary Data Store Provider"; +public class SolidfirePrimaryDataStoreProvider implements PrimaryDataStoreProvider { + private final String name = "Solidfire Primary Data Store Provider"; + @Override + public String getName() { + return name; + } + + @Override + public DataStoreLifeCycle getDataStoreLifeCycle() { + return null; + } + + @Override + public DataStoreDriver getDataStoreDriver() { + return null; + } + + @Override + public HypervisorHostListener getHostListener() { + return null; + } + + @Override + public boolean configure(Map params) { + return false; + } + + @Override + public Set getTypes() { + return null; + } - public SolidfirePrimaryDataStoreProvider() { - - - // TODO Auto-generated constructor stub - } - - @Override - public String getName() { - return name; - } - - } diff --git a/plugins/storage/volume/solidfire/test/org/apache/cloudstack/storage/test/AopTestAdvice.java b/plugins/storage/volume/solidfire/test/org/apache/cloudstack/storage/test/AopTestAdvice.java index 63669c453d7..902f5953eb1 100644 --- a/plugins/storage/volume/solidfire/test/org/apache/cloudstack/storage/test/AopTestAdvice.java +++ b/plugins/storage/volume/solidfire/test/org/apache/cloudstack/storage/test/AopTestAdvice.java @@ -21,14 +21,14 @@ import org.aspectj.lang.ProceedingJoinPoint; import com.cloud.utils.db.Transaction; public class AopTestAdvice { - public Object AopTestMethod(ProceedingJoinPoint call) throws Throwable { - Transaction txn = Transaction.open(call.getSignature().getName()); - Object ret = null; - try { - ret = call.proceed(); - } finally { - txn.close(); - } - return ret; - } + public Object AopTestMethod(ProceedingJoinPoint call) throws Throwable { + Transaction txn = Transaction.open(call.getSignature().getName()); + Object ret = null; + try { + ret = call.proceed(); + } finally { + txn.close(); + } + return ret; + } } diff --git a/plugins/storage/volume/solidfire/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java b/plugins/storage/volume/solidfire/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java index eb6fe453886..79215618914 100644 --- a/plugins/storage/volume/solidfire/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java +++ b/plugins/storage/volume/solidfire/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java @@ -24,28 +24,29 @@ import com.cloud.agent.AgentManager; import com.cloud.host.dao.HostDao; public class ChildTestConfiguration extends TestConfiguration { - - @Override - @Bean - public HostDao hostDao() { - HostDao dao = super.hostDao(); - HostDao nDao = Mockito.spy(dao); - return nDao; - } - - @Bean - public AgentManager agentMgr() { - return Mockito.mock(AgentManager.class); - } - - @Bean - public ImageMotionService imageMotion() { - return Mockito.mock(ImageMotionService.class); - } -/* @Override - @Bean - public PrimaryDataStoreDao primaryDataStoreDao() { - return Mockito.mock(PrimaryDataStoreDaoImpl.class); - }*/ + @Override + @Bean + public HostDao hostDao() { + HostDao dao = super.hostDao(); + HostDao nDao = Mockito.spy(dao); + return nDao; + } + + @Bean + public AgentManager agentMgr() { + return Mockito.mock(AgentManager.class); + } + + @Bean + public ImageMotionService imageMotion() { + return Mockito.mock(ImageMotionService.class); + } + + /* + * @Override + * + * @Bean public PrimaryDataStoreDao primaryDataStoreDao() { return + * Mockito.mock(PrimaryDataStoreDaoImpl.class); } + */ } diff --git a/plugins/storage/volume/solidfire/test/org/apache/cloudstack/storage/test/TestConfiguration.java b/plugins/storage/volume/solidfire/test/org/apache/cloudstack/storage/test/TestConfiguration.java index 2c6092d7408..8e98771feab 100644 --- a/plugins/storage/volume/solidfire/test/org/apache/cloudstack/storage/test/TestConfiguration.java +++ b/plugins/storage/volume/solidfire/test/org/apache/cloudstack/storage/test/TestConfiguration.java @@ -26,12 +26,13 @@ import com.cloud.host.dao.HostDaoImpl; @Configuration public class TestConfiguration { - @Bean - public HostDao hostDao() { - return new HostDaoImpl(); - } - @Bean - public PrimaryDataStoreDao primaryDataStoreDao() { - return new PrimaryDataStoreDaoImpl(); - } + @Bean + public HostDao hostDao() { + return new HostDaoImpl(); + } + + @Bean + public PrimaryDataStoreDao primaryDataStoreDao() { + return new PrimaryDataStoreDaoImpl(); + } } diff --git a/plugins/storage/volume/solidfire/test/org/apache/cloudstack/storage/test/VolumeTest.java b/plugins/storage/volume/solidfire/test/org/apache/cloudstack/storage/test/VolumeTest.java index dc29fb835d2..a745dafbc2f 100644 --- a/plugins/storage/volume/solidfire/test/org/apache/cloudstack/storage/test/VolumeTest.java +++ b/plugins/storage/volume/solidfire/test/org/apache/cloudstack/storage/test/VolumeTest.java @@ -23,16 +23,13 @@ import java.util.Map; import java.util.UUID; import javax.inject.Inject; -import javax.naming.ConfigurationException; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreProvider; -import org.apache.cloudstack.storage.command.CreateObjectAnswer; -import org.apache.cloudstack.storage.command.CreateVolumeFromBaseImageCommand; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Matchers; import org.mockito.Mockito; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -45,8 +42,6 @@ import com.cloud.dc.HostPodVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.HostPodDao; -import com.cloud.exception.AgentUnavailableException; -import com.cloud.exception.OperationTimedoutException; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; @@ -55,97 +50,91 @@ import com.cloud.org.Cluster.ClusterType; import com.cloud.org.Managed.ManagedState; import com.cloud.resource.ResourceState; - @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations="classpath:/resource/storageContext.xml") +@ContextConfiguration(locations = "classpath:/resource/storageContext.xml") public class VolumeTest { - @Inject - HostDao hostDao; - @Inject - HostPodDao podDao; - @Inject - ClusterDao clusterDao; - @Inject - DataCenterDao dcDao; - @Inject - PrimaryDataStoreDao primaryStoreDao; - //@Inject - //PrimaryDataStoreProviderManager primaryDataStoreProviderMgr; - @Inject - AgentManager agentMgr; - Long dcId; - Long clusterId; - @Before - public void setUp() { - //create data center - DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24", - null, null, NetworkType.Basic, null, null, true, true, null, null); - dc = dcDao.persist(dc); - dcId = dc.getId(); - //create pod + @Inject + HostDao hostDao; + @Inject + HostPodDao podDao; + @Inject + ClusterDao clusterDao; + @Inject + DataCenterDao dcDao; + @Inject + PrimaryDataStoreDao primaryStoreDao; + // @Inject + // PrimaryDataStoreProviderManager primaryDataStoreProviderMgr; + @Inject + AgentManager agentMgr; + Long dcId; + Long clusterId; - HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), "192.168.56.1", "192.168.56.0/24", 8, "test"); - pod = podDao.persist(pod); - //create xen cluster - ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster"); - cluster.setHypervisorType(HypervisorType.XenServer.toString()); - cluster.setClusterType(ClusterType.CloudManaged); - cluster.setManagedState(ManagedState.Managed); - cluster = clusterDao.persist(cluster); - clusterId = cluster.getId(); - //create xen host + @Before + public void setUp() { + // create data center + DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, + "10.0.0.1/24", null, null, NetworkType.Basic, null, null, true, true, null, null); + dc = dcDao.persist(dc); + dcId = dc.getId(); + // create pod - HostVO host = new HostVO(UUID.randomUUID().toString()); - host.setName("devcloud xen host"); - host.setType(Host.Type.Routing); - host.setPrivateIpAddress("192.168.56.2"); - host.setDataCenterId(dc.getId()); - host.setVersion("6.0.1"); - host.setAvailable(true); - host.setSetup(true); - host.setLastPinged(0); - host.setResourceState(ResourceState.Enabled); - host.setClusterId(cluster.getId()); + HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), "192.168.56.1", "192.168.56.0/24", 8, + "test"); + pod = podDao.persist(pod); + // create xen cluster + ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster"); + cluster.setHypervisorType(HypervisorType.XenServer.toString()); + cluster.setClusterType(ClusterType.CloudManaged); + cluster.setManagedState(ManagedState.Managed); + cluster = clusterDao.persist(cluster); + clusterId = cluster.getId(); + // create xen host - host = hostDao.persist(host); - List results = new ArrayList(); - results.add(host); - Mockito.when(hostDao.listAll()).thenReturn(results); - Mockito.when(hostDao.findHypervisorHostInCluster(Mockito.anyLong())).thenReturn(results); - CreateObjectAnswer createVolumeFromImageAnswer = new CreateObjectAnswer(null,UUID.randomUUID().toString(), null); + HostVO host = new HostVO(UUID.randomUUID().toString()); + host.setName("devcloud xen host"); + host.setType(Host.Type.Routing); + host.setPrivateIpAddress("192.168.56.2"); + host.setDataCenterId(dc.getId()); + host.setVersion("6.0.1"); + host.setAvailable(true); + host.setSetup(true); + host.setLastPinged(0); + host.setResourceState(ResourceState.Enabled); + host.setClusterId(cluster.getId()); - try { - Mockito.when(agentMgr.send(Mockito.anyLong(), Mockito.any(CreateVolumeFromBaseImageCommand.class))).thenReturn(createVolumeFromImageAnswer); - } catch (AgentUnavailableException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (OperationTimedoutException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + host = hostDao.persist(host); + List results = new ArrayList(); + results.add(host); + Mockito.when(hostDao.listAll()).thenReturn(results); + Mockito.when(hostDao.findHypervisorHostInCluster(Matchers.anyLong())).thenReturn(results); + // CreateObjectAnswer createVolumeFromImageAnswer = new + // CreateObjectAnswer(null,UUID.randomUUID().toString(), null); + // Mockito.when(primaryStoreDao.findById(Mockito.anyLong())).thenReturn(primaryStore); + } - //Mockito.when(primaryStoreDao.findById(Mockito.anyLong())).thenReturn(primaryStore); - } + private PrimaryDataStoreInfo createPrimaryDataStore() { + try { + // primaryDataStoreProviderMgr.configure("primary data store mgr", + // new HashMap()); + // PrimaryDataStoreProvider provider = + // primaryDataStoreProviderMgr.getDataStoreProvider("Solidfre Primary Data Store Provider"); + Map params = new HashMap(); + params.put("url", "nfs://test/test"); + params.put("dcId", dcId.toString()); + params.put("clusterId", clusterId.toString()); + params.put("name", "my primary data store"); + // PrimaryDataStoreInfo primaryDataStoreInfo = + // provider.registerDataStore(params); + return null; + } catch (Exception e) { + return null; + } + } - private PrimaryDataStoreInfo createPrimaryDataStore() { - try { - //primaryDataStoreProviderMgr.configure("primary data store mgr", new HashMap()); - //PrimaryDataStoreProvider provider = primaryDataStoreProviderMgr.getDataStoreProvider("Solidfre Primary Data Store Provider"); - Map params = new HashMap(); - params.put("url", "nfs://test/test"); - params.put("dcId", dcId.toString()); - params.put("clusterId", clusterId.toString()); - params.put("name", "my primary data store"); - //PrimaryDataStoreInfo primaryDataStoreInfo = provider.registerDataStore(params); - return null; - } catch (Exception e) { - return null; - } - } - - @Test - public void createPrimaryDataStoreTest() { - createPrimaryDataStore(); - } + @Test + public void createPrimaryDataStoreTest() { + createPrimaryDataStore(); + } } diff --git a/scripts/storage/qcow2/createtmplt.sh b/scripts/storage/qcow2/createtmplt.sh index 152268f651a..8d6dd0d4849 100755 --- a/scripts/storage/qcow2/createtmplt.sh +++ b/scripts/storage/qcow2/createtmplt.sh @@ -27,10 +27,10 @@ usage() { #set -x qemu_img="cloud-qemu-img" -which $qemu_img +which $qemu_img >& /dev/null if [ $? -gt 0 ] then - which qemu-img + which qemu-img >& /dev/null if [ $? -eq 0 ] then qemu_img="qemu-img" diff --git a/scripts/storage/qcow2/managesnapshot.sh b/scripts/storage/qcow2/managesnapshot.sh index 29b7081290d..30148de66e7 100755 --- a/scripts/storage/qcow2/managesnapshot.sh +++ b/scripts/storage/qcow2/managesnapshot.sh @@ -48,7 +48,7 @@ is_lv() { # And a logical volume lvm lvs "${1}" > /dev/null 2>&1 && return 0 fi - return 1 + return 0 } get_vg() { diff --git a/scripts/storage/secondary/create_privatetemplate_from_snapshot_xen.sh b/scripts/storage/secondary/create_privatetemplate_from_snapshot_xen.sh new file mode 100755 index 00000000000..309bcbdb683 --- /dev/null +++ b/scripts/storage/secondary/create_privatetemplate_from_snapshot_xen.sh @@ -0,0 +1,98 @@ +#!/bin/bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# 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, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +#set -x + +usage() { + printf "Usage: %s -t [template path] -n [template name] -s [snapshot name] -p [snapshot path] \n" $(basename $0) +} + +snapshotPath= +snapshotName= +templatePath= +templateName= +while getopts ':s:n:t:p:' OPTION +do + case $OPTION in + t) tflag=1 + templatePath="$OPTARG" + ;; + n) nflag=1 + templateName="$OPTARG" + ;; + s) sflag=1 + snapshotName="$OPTARG" + ;; + p) pflag=1 + snapshotPath="$OPTARG" + ;; + ?) usage + exit 2 + ;; + esac +done + +if [ "$sflag$nflag$tflag$pflag" != "1111" ] +then + usage + exit 1 +fi + +VHDUTIL="/bin/vhd-util" +desvhd=$templatePath/$templateName +srcvhd=$snapshotPath/$snapshotName + +copyvhd() +{ + local desvhd=$1 + local srcvhd=$2 + local parent= + parent=`$VHDUTIL query -p -n $srcvhd` + if [ $? -ne 0 ]; then + echo "30#failed to query $srcvhd" + exit 2 + fi + if [[ "${parent}" =~ " no parent" ]]; then + dd if=$srcvhd of=$desvhd bs=2M + if [ $? -ne 0 ]; then + echo "31#failed to dd $srcvhd to $desvhd" + rm -rf $desvhd > /dev/null + exit 0 + fi + else + copyvhd $desvhd $parent + $VHDUTIL coalesce -p $desvhd -n $srcvhd + if [ $? -ne 0 ]; then + echo "32#failed to coalesce $desvhd to $srcvhd" + rm -rf $desvhd > /dev/null + exit 0 + fi + fi +} + +copyvhd $desvhd $srcvhd +imgsize=$(ls -l $desvhd| awk -F" " '{print $5}') +propertyFile=/$templatePath/template.properties +touch $propertyFile +echo -n "" > $propertyFile + +echo "filename=$templateName" > $propertyFile +echo "hvm=$hvm" >> $propertyFile +echo "size=$imgsize" >> $propertyFile + +exit 0 diff --git a/server/src/com/cloud/agent/AgentManager.java b/server/src/com/cloud/agent/AgentManager.java index 6c300ea76fa..02dd10d810f 100755 --- a/server/src/com/cloud/agent/AgentManager.java +++ b/server/src/com/cloud/agent/AgentManager.java @@ -16,6 +16,8 @@ // under the License. package com.cloud.agent; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; + import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.StartupCommand; @@ -44,10 +46,10 @@ public interface AgentManager extends Manager { Del, Contains, } - + /** * easy send method that returns null if there's any errors. It handles all exceptions. - * + * * @param hostId * host id * @param cmd @@ -58,7 +60,7 @@ public interface AgentManager extends Manager { /** * Synchronous sending a command to the agent. - * + * * @param hostId * id of the agent on host * @param cmd @@ -70,7 +72,7 @@ public interface AgentManager extends Manager { /** * Synchronous sending a list of commands to the agent. - * + * * @param hostId * id of the agent on host * @param cmds @@ -87,7 +89,7 @@ public interface AgentManager extends Manager { /** * Asynchronous sending of a command to the agent. - * + * * @param hostId * id of the agent on the host. * @param cmds @@ -102,7 +104,7 @@ public interface AgentManager extends Manager { /** * Register to listen for host events. These are mostly connection and disconnection events. - * + * * @param listener * @param connections * listen for connections @@ -125,7 +127,7 @@ public interface AgentManager extends Manager { /** * Unregister for listening to host events. - * + * * @param id * returned from registerForHostEvents */ @@ -135,23 +137,20 @@ public interface AgentManager extends Manager { Answer sendTo(Long dcId, HypervisorType type, Command cmd); - void sendToSecStorage(HostVO ssHost, Command cmd, Listener listener) throws AgentUnavailableException; - Answer sendToSecStorage(HostVO ssHost, Command cmd); - /* working as a lock while agent is being loaded */ public boolean tapLoadingAgents(Long hostId, TapAgentsAction action); - + public AgentAttache handleDirectConnectAgent(HostVO host, StartupCommand[] cmds, ServerResource resource, boolean forRebalance) throws ConnectionException; - + public boolean agentStatusTransitTo(HostVO host, Status.Event e, long msId); - + public AgentAttache findAttache(long hostId); - + void disconnectWithoutInvestigation(long hostId, Status.Event event); - + public void pullAgentToMaintenance(long hostId); - + public void pullAgentOutMaintenance(long hostId); boolean reconnect(long hostId); diff --git a/server/src/com/cloud/agent/manager/AgentManagerImpl.java b/server/src/com/cloud/agent/manager/AgentManagerImpl.java index 6baeecf382a..fb857a707c8 100755 --- a/server/src/com/cloud/agent/manager/AgentManagerImpl.java +++ b/server/src/com/cloud/agent/manager/AgentManagerImpl.java @@ -41,8 +41,6 @@ import javax.naming.ConfigurationException; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; import com.cloud.agent.StartupCommandProcessor; @@ -98,7 +96,6 @@ import com.cloud.resource.Discoverer; import com.cloud.resource.ResourceManager; import com.cloud.resource.ResourceState; import com.cloud.resource.ServerResource; -import com.cloud.server.ManagementService; import com.cloud.storage.StorageManager; import com.cloud.storage.StorageService; import com.cloud.storage.dao.StoragePoolHostDao; @@ -109,7 +106,6 @@ import com.cloud.user.AccountManager; import com.cloud.utils.ActionDelegate; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; -import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; @@ -380,31 +376,7 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl return attache; } - @Override - public Answer sendToSecStorage(HostVO ssHost, Command cmd) { - if( ssHost.getType() == Host.Type.LocalSecondaryStorage ) { - return easySend(ssHost.getId(), cmd); - } else if ( ssHost.getType() == Host.Type.SecondaryStorage) { - return sendToSSVM(ssHost.getDataCenterId(), cmd); - } else { - String msg = "do not support Secondary Storage type " + ssHost.getType(); - s_logger.warn(msg); - return new Answer(cmd, false, msg); - } - } - @Override - public void sendToSecStorage(HostVO ssHost, Command cmd, Listener listener) throws AgentUnavailableException { - if( ssHost.getType() == Host.Type.LocalSecondaryStorage ) { - send(ssHost.getId(), new Commands(cmd), listener); - } else if ( ssHost.getType() == Host.Type.SecondaryStorage) { - sendToSSVM(ssHost.getDataCenterId(), cmd, listener); - } else { - String err = "do not support Secondary Storage type " + ssHost.getType(); - s_logger.warn(err); - throw new CloudRuntimeException(err); - } - } private void sendToSSVM(final long dcId, final Command cmd, final Listener listener) throws AgentUnavailableException { List ssAHosts = _ssvmMgr.listUpAndConnectingSecondaryStorageVmHost(dcId); @@ -1482,6 +1454,7 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl } } + @Override public void disconnectWithInvestigation(final long hostId, final Status.Event event) { disconnectInternal(hostId, event, true); } diff --git a/server/src/com/cloud/agent/manager/AgentMonitor.java b/server/src/com/cloud/agent/manager/AgentMonitor.java index f3f6669dae6..2c0266e6689 100755 --- a/server/src/com/cloud/agent/manager/AgentMonitor.java +++ b/server/src/com/cloud/agent/manager/AgentMonitor.java @@ -248,7 +248,7 @@ public class AgentMonitor extends Thread implements AgentMonitorService { } @Override - public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) { + public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) { if (host.getType().equals(Host.Type.TrafficMonitor) || host.getType().equals(Host.Type.SecondaryStorage)) { return; diff --git a/server/src/com/cloud/agent/manager/SynchronousListener.java b/server/src/com/cloud/agent/manager/SynchronousListener.java index 074f5a84820..36987053a0f 100755 --- a/server/src/com/cloud/agent/manager/SynchronousListener.java +++ b/server/src/com/cloud/agent/manager/SynchronousListener.java @@ -24,7 +24,7 @@ import com.cloud.agent.api.AgentControlCommand; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.StartupCommand; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.host.Status; import com.cloud.utils.Profiler; @@ -79,7 +79,7 @@ public class SynchronousListener implements Listener { } @Override - public void processConnect(HostVO agent, StartupCommand cmd, boolean forRebalance) { + public void processConnect(Host agent, StartupCommand cmd, boolean forRebalance) { } @Override diff --git a/server/src/com/cloud/agent/manager/allocator/impl/UserConcentratedAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/UserConcentratedAllocator.java index 29e1be9547c..af4e4110913 100755 --- a/server/src/com/cloud/agent/manager/allocator/impl/UserConcentratedAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/impl/UserConcentratedAllocator.java @@ -70,8 +70,6 @@ public class UserConcentratedAllocator extends AdapterBase implements PodAllocat @Inject HostPodDao _podDao; @Inject - VMTemplateHostDao _templateHostDao; - @Inject VMTemplatePoolDao _templatePoolDao; @Inject ServiceOfferingDao _offeringDao; @@ -87,7 +85,8 @@ public class UserConcentratedAllocator extends AdapterBase implements PodAllocat private int _secondsToSkipDestroyedVMs = 0; @Override - public Pair allocateTo(VirtualMachineTemplate template, ServiceOfferingVO offering, DataCenterVO zone, long accountId, Set avoids) { + public Pair allocateTo(VirtualMachineTemplate template, ServiceOfferingVO offering, DataCenterVO zone, long accountId, + Set avoids) { long zoneId = zone.getId(); List podsInZone = _podDao.listByDataCenterId(zoneId); @@ -107,23 +106,28 @@ public class UserConcentratedAllocator extends AdapterBase implements PodAllocat } if (offering != null) { - // test for enough memory in the pod (make sure to check for enough memory for the service offering, plus + // test for enough memory in the pod (make sure to check for + // enough memory for the service offering, plus // some extra padding for xen overhead long[] hostCandiates = new long[1]; - boolean enoughCapacity = dataCenterAndPodHasEnoughCapacity(zoneId, podId, (offering.getRamSize()) * 1024L * 1024L, CapacityVO.CAPACITY_TYPE_MEMORY, hostCandiates); + boolean enoughCapacity = dataCenterAndPodHasEnoughCapacity(zoneId, podId, (offering.getRamSize()) * 1024L * 1024L, + CapacityVO.CAPACITY_TYPE_MEMORY, hostCandiates); if (!enoughCapacity) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Not enough RAM available in zone/pod to allocate storage for user VM (zone: " + zoneId + ", pod: " + podId + ")"); + s_logger.debug("Not enough RAM available in zone/pod to allocate storage for user VM (zone: " + zoneId + ", pod: " + + podId + ")"); } continue; } // test for enough CPU in the pod - enoughCapacity = dataCenterAndPodHasEnoughCapacity(zoneId, podId, (offering.getCpu() * offering.getSpeed()), CapacityVO.CAPACITY_TYPE_CPU, hostCandiates); + enoughCapacity = dataCenterAndPodHasEnoughCapacity(zoneId, podId, (offering.getCpu() * offering.getSpeed()), + CapacityVO.CAPACITY_TYPE_CPU, hostCandiates); if (!enoughCapacity) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Not enough cpu available in zone/pod to allocate storage for user VM (zone: " + zoneId + ", pod: " + podId + ")"); + s_logger.debug("Not enough cpu available in zone/pod to allocate storage for user VM (zone: " + zoneId + ", pod: " + + podId + ")"); } continue; } @@ -207,7 +211,8 @@ public class UserConcentratedAllocator extends AdapterBase implements PodAllocat } if (vm.getState() == State.Stopped || vm.getState() == State.Destroyed) { - // for Stopped/Destroyed VMs, we will skip counting it if it hasn't been used for a while + // for Stopped/Destroyed VMs, we will skip counting it if it hasn't + // been used for a while int secondsToSkipVMs = _secondsToSkipStoppedVMs; if (vm.getState() == State.Destroyed) { @@ -217,8 +222,9 @@ public class UserConcentratedAllocator extends AdapterBase implements PodAllocat long millisecondsSinceLastUpdate = DateUtil.currentGMTTime().getTime() - vm.getUpdateTime().getTime(); if (millisecondsSinceLastUpdate > secondsToSkipVMs * 1000L) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Skip counting " + vm.getState().toString() + " vm " + vm.getInstanceName() + " in capacity allocation as it has been " + vm.getState().toString().toLowerCase() - + " for " + millisecondsSinceLastUpdate / 60000 + " minutes"); + s_logger.debug("Skip counting " + vm.getState().toString() + " vm " + vm.getInstanceName() + + " in capacity allocation as it has been " + vm.getState().toString().toLowerCase() + " for " + + millisecondsSinceLastUpdate / 60000 + " minutes"); } return true; } @@ -228,11 +234,12 @@ public class UserConcentratedAllocator extends AdapterBase implements PodAllocat } /** - * + * * @param hostId * Host id to calculate against * @param capacityType - * CapacityVO.CAPACITY_TYPE_MEMORY or CapacityVO.CAPACITY_TYPE_CPU + * CapacityVO.CAPACITY_TYPE_MEMORY or + * CapacityVO.CAPACITY_TYPE_CPU * @return */ private long calcHostAllocatedCpuMemoryCapacity(long hostId, short capacityType) { @@ -253,21 +260,23 @@ public class UserConcentratedAllocator extends AdapterBase implements PodAllocat if (userVm == null) { continue; } - } - + } + so = _offeringDao.findById(vm.getServiceOfferingId()); if (capacityType == CapacityVO.CAPACITY_TYPE_MEMORY) { usedCapacity += so.getRamSize() * 1024L * 1024L; if (s_logger.isDebugEnabled()) { - s_logger.debug("Counting memory capacity used by vm: " + vm.getId() + ", size: " + so.getRamSize() + "MB, host: " + hostId + ", currently counted: " + usedCapacity + " Bytes"); + s_logger.debug("Counting memory capacity used by vm: " + vm.getId() + ", size: " + so.getRamSize() + "MB, host: " + hostId + + ", currently counted: " + usedCapacity + " Bytes"); } } else if (capacityType == CapacityVO.CAPACITY_TYPE_CPU) { usedCapacity += so.getCpu() * so.getSpeed(); if (s_logger.isDebugEnabled()) { - s_logger.debug("Counting cpu capacity used by vm: " + vm.getId() + ", cpu: " + so.getCpu() + ", speed: " + so.getSpeed() + ", currently counted: " + usedCapacity + " Bytes"); + s_logger.debug("Counting cpu capacity used by vm: " + vm.getId() + ", cpu: " + so.getCpu() + ", speed: " + so.getSpeed() + + ", currently counted: " + usedCapacity + " Bytes"); } } } @@ -281,7 +290,7 @@ public class UserConcentratedAllocator extends AdapterBase implements PodAllocat * List thvoList = _templateHostDao.listByTemplateStatus(templateId, dcId, podId, Status.DOWNLOADED); * List tpvoList = _templatePoolDao.listByTemplateStatus(templateId, dcId, podId, * Status.DOWNLOADED); - * + * * if (thvoList != null && thvoList.size() > 0) { if (s_logger.isDebugEnabled()) { s_logger.debug("Found " + * thvoList.size() + " storage hosts in pod " + podId + " with template " + templateId); } return true; } else if * (tpvoList != null && tpvoList.size() > 0) { if (s_logger.isDebugEnabled()) { s_logger.debug("Found " + @@ -304,7 +313,8 @@ public class UserConcentratedAllocator extends AdapterBase implements PodAllocat public boolean configure(String name, Map params) throws ConfigurationException { Map configs = _configDao.getConfiguration("management-server", params); String stoppedValue = configs.get("vm.resource.release.interval"); - // String destroyedValue = configs.get("capacity.skipcounting.destroyed.hours"); + // String destroyedValue = + // configs.get("capacity.skipcounting.destroyed.hours"); String destroyedValue = null; _secondsToSkipStoppedVMs = NumbersUtil.parseInt(stoppedValue, 86400); _secondsToSkipDestroyedVMs = NumbersUtil.parseInt(destroyedValue, 0); @@ -312,19 +322,19 @@ public class UserConcentratedAllocator extends AdapterBase implements PodAllocat /* * ComponentLocator locator = ComponentLocator.getCurrentLocator(); _vmDao = locator.getDao(UserVmDao.class); if (_vmDao * == null) { throw new ConfigurationException("Unable to find UserVMDao."); } - * + * * _volumeDao = locator.getDao(VolumeDao.class); if (_volumeDao == null) { throw new * ConfigurationException("Unable to find VolumeDao."); } - * + * * _templateHostDao = locator.getDao(VMTemplateHostDao.class); if (_templateHostDao == null) { throw new * ConfigurationException("Unable to get template host dao."); } - * + * * _templatePoolDao = locator.getDao(VMTemplatePoolDao.class); if (_templatePoolDao == null) { throw new * ConfigurationException("Unable to get template pool dao."); } - * + * * _podDao = locator.getDao(HostPodDao.class); if (_podDao == null) { throw new * ConfigurationException("Unable to find HostPodDao."); } - * + * * _capacityDao = locator.getDao(CapacityDao.class); if (_capacityDao == null) { throw new * ConfigurationException("Unable to retrieve " + CapacityDao.class); } */ diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index e5fa2e19757..073e4c27618 100755 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -53,6 +53,7 @@ import org.apache.cloudstack.api.response.EventResponse; import org.apache.cloudstack.api.response.HostForMigrationResponse; import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.InstanceGroupResponse; +import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.cloudstack.api.response.ProjectAccountResponse; import org.apache.cloudstack.api.response.ProjectInvitationResponse; import org.apache.cloudstack.api.response.ProjectResponse; @@ -60,6 +61,7 @@ import org.apache.cloudstack.api.response.ResourceTagResponse; import org.apache.cloudstack.api.response.SecurityGroupResponse; import org.apache.cloudstack.api.response.ServiceOfferingResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; +import org.apache.cloudstack.api.response.TemplateResponse; import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.api.response.VolumeResponse; @@ -76,6 +78,7 @@ import com.cloud.api.query.dao.DataCenterJoinDao; import com.cloud.api.query.dao.DiskOfferingJoinDao; import com.cloud.api.query.dao.DomainRouterJoinDao; import com.cloud.api.query.dao.HostJoinDao; +import com.cloud.api.query.dao.ImageStoreJoinDao; import com.cloud.api.query.dao.InstanceGroupJoinDao; import com.cloud.api.query.dao.ProjectAccountJoinDao; import com.cloud.api.query.dao.ProjectInvitationJoinDao; @@ -84,6 +87,7 @@ import com.cloud.api.query.dao.ResourceTagJoinDao; import com.cloud.api.query.dao.SecurityGroupJoinDao; import com.cloud.api.query.dao.ServiceOfferingJoinDao; import com.cloud.api.query.dao.StoragePoolJoinDao; +import com.cloud.api.query.dao.TemplateJoinDao; import com.cloud.api.query.dao.UserAccountJoinDao; import com.cloud.api.query.dao.UserVmJoinDao; import com.cloud.api.query.dao.VolumeJoinDao; @@ -95,6 +99,7 @@ import com.cloud.api.query.vo.DiskOfferingJoinVO; import com.cloud.api.query.vo.DomainRouterJoinVO; import com.cloud.api.query.vo.EventJoinVO; import com.cloud.api.query.vo.HostJoinVO; +import com.cloud.api.query.vo.ImageStoreJoinVO; import com.cloud.api.query.vo.InstanceGroupJoinVO; import com.cloud.api.query.vo.ProjectAccountJoinVO; import com.cloud.api.query.vo.ProjectInvitationJoinVO; @@ -103,6 +108,7 @@ import com.cloud.api.query.vo.ResourceTagJoinVO; import com.cloud.api.query.vo.SecurityGroupJoinVO; import com.cloud.api.query.vo.ServiceOfferingJoinVO; import com.cloud.api.query.vo.StoragePoolJoinVO; +import com.cloud.api.query.vo.TemplateJoinVO; import com.cloud.api.query.vo.UserAccountJoinVO; import com.cloud.api.query.vo.UserVmJoinVO; import com.cloud.api.query.vo.VolumeJoinVO; @@ -219,6 +225,7 @@ import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.GuestOS; import com.cloud.storage.GuestOSCategoryVO; +import com.cloud.storage.ImageStore; import com.cloud.storage.Snapshot; import com.cloud.storage.SnapshotVO; import com.cloud.storage.Storage.ImageFormat; @@ -250,6 +257,7 @@ import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.dao.VolumeHostDao; import com.cloud.storage.snapshot.SnapshotPolicy; import com.cloud.template.TemplateManager; +import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; import com.cloud.user.AccountDetailsDao; import com.cloud.user.AccountVO; @@ -327,7 +335,6 @@ public class ApiDBUtils { static PrimaryDataStoreDao _storagePoolDao; static VMTemplateDao _templateDao; static VMTemplateDetailsDao _templateDetailsDao; - static VMTemplateHostDao _templateHostDao; static VMTemplateSwiftDao _templateSwiftDao; static VMTemplateS3Dao _templateS3Dao; static UploadDao _uploadDao; @@ -339,7 +346,6 @@ public class ApiDBUtils { static VolumeDao _volumeDao; static Site2SiteVpnGatewayDao _site2SiteVpnGatewayDao; static Site2SiteCustomerGatewayDao _site2SiteCustomerGatewayDao; - static VolumeHostDao _volumeHostDao; static DataCenterDao _zoneDao; static NetworkOfferingDao _networkOfferingDao; static NetworkDao _networkDao; @@ -377,8 +383,10 @@ public class ApiDBUtils { static HostJoinDao _hostJoinDao; static VolumeJoinDao _volJoinDao; static StoragePoolJoinDao _poolJoinDao; + static ImageStoreJoinDao _imageStoreJoinDao; static AccountJoinDao _accountJoinDao; static AsyncJobJoinDao _jobJoinDao; + static TemplateJoinDao _templateJoinDao; static PhysicalNetworkTrafficTypeDao _physicalNetworkTrafficTypeDao; static PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao; @@ -436,7 +444,6 @@ public class ApiDBUtils { @Inject private PrimaryDataStoreDao storagePoolDao; @Inject private VMTemplateDao templateDao; @Inject private VMTemplateDetailsDao templateDetailsDao; - @Inject private VMTemplateHostDao templateHostDao; @Inject private VMTemplateSwiftDao templateSwiftDao; @Inject private VMTemplateS3Dao templateS3Dao; @Inject private UploadDao uploadDao; @@ -448,7 +455,6 @@ public class ApiDBUtils { @Inject private VolumeDao volumeDao; @Inject private Site2SiteVpnGatewayDao site2SiteVpnGatewayDao; @Inject private Site2SiteCustomerGatewayDao site2SiteCustomerGatewayDao; - @Inject private VolumeHostDao volumeHostDao; @Inject private DataCenterDao zoneDao; @Inject private NetworkOfferingDao networkOfferingDao; @Inject private NetworkDao networkDao; @@ -486,8 +492,10 @@ public class ApiDBUtils { @Inject private HostJoinDao hostJoinDao; @Inject private VolumeJoinDao volJoinDao; @Inject private StoragePoolJoinDao poolJoinDao; + @Inject private ImageStoreJoinDao imageStoreJoinDao; @Inject private AccountJoinDao accountJoinDao; @Inject private AsyncJobJoinDao jobJoinDao; + @Inject private TemplateJoinDao templateJoinDao; @Inject private PhysicalNetworkTrafficTypeDao physicalNetworkTrafficTypeDao; @Inject private PhysicalNetworkServiceProviderDao physicalNetworkServiceProviderDao; @@ -545,7 +553,6 @@ public class ApiDBUtils { _storagePoolDao = storagePoolDao; _templateDao = templateDao; _templateDetailsDao = templateDetailsDao; - _templateHostDao = templateHostDao; _templateSwiftDao = templateSwiftDao; _templateS3Dao = templateS3Dao; _uploadDao = uploadDao; @@ -557,7 +564,6 @@ public class ApiDBUtils { _volumeDao = volumeDao; _site2SiteVpnGatewayDao = site2SiteVpnGatewayDao; _site2SiteCustomerGatewayDao = site2SiteCustomerGatewayDao; - _volumeHostDao = volumeHostDao; _zoneDao = zoneDao; _securityGroupDao = securityGroupDao; _securityGroupJoinDao = securityGroupJoinDao; @@ -593,8 +599,10 @@ public class ApiDBUtils { _hostJoinDao = hostJoinDao; _volJoinDao = volJoinDao; _poolJoinDao = poolJoinDao; + _imageStoreJoinDao = imageStoreJoinDao; _accountJoinDao = accountJoinDao; _jobJoinDao = jobJoinDao; + _templateJoinDao = templateJoinDao; _physicalNetworkTrafficTypeDao = physicalNetworkTrafficTypeDao; _physicalNetworkServiceProviderDao = physicalNetworkServiceProviderDao; @@ -885,25 +893,6 @@ public class ApiDBUtils { return template; } - public static VMTemplateHostVO findTemplateHostRef(long templateId, long zoneId) { - return findTemplateHostRef(templateId, zoneId, false); - } - - public static VMTemplateHostVO findTemplateHostRef(long templateId, long zoneId, boolean readyOnly) { - VMTemplateVO vmTemplate = findTemplateById(templateId); - if (vmTemplate.getHypervisorType() == HypervisorType.BareMetal) { - List res = _templateHostDao.listByTemplateId(templateId); - return res.size() == 0 ? null : res.get(0); - } else { - return _templateMgr.getTemplateHostRef(zoneId, templateId, readyOnly); - } - } - - - public static VolumeHostVO findVolumeHostRef(long volumeId, long zoneId) { - return _volumeHostDao.findVolumeByZone(volumeId, zoneId); - } - public static VMTemplateSwiftVO findTemplateSwiftRef(long templateId) { return _templateSwiftDao.findOneByTemplateId(templateId); } @@ -974,18 +963,6 @@ public class ApiDBUtils { return _storageMgr.getHypervisorTypeFromFormat(format); } - public static List listTemplateHostBy(long templateId, Long zoneId, boolean readyOnly) { - if (zoneId != null) { - VMTemplateVO vmTemplate = findTemplateById(templateId); - if (vmTemplate.getHypervisorType() == HypervisorType.BareMetal) { - return _templateHostDao.listByTemplateId(templateId); - } else { - return _templateHostDao.listByZoneTemplate(zoneId, templateId, readyOnly); - } - } else { - return _templateHostDao.listByOnlyTemplateId(templateId); - } - } public static List listUserStatsBy(Long accountId) { return _userStatsDao.listBy(accountId); @@ -1595,6 +1572,18 @@ public class ApiDBUtils { return _poolJoinDao.newStoragePoolView(vr); } + public static ImageStoreResponse newImageStoreResponse(ImageStoreJoinVO vr) { + return _imageStoreJoinDao.newImageStoreResponse(vr); + } + + public static ImageStoreResponse fillImageStoreDetails(ImageStoreResponse vrData, ImageStoreJoinVO vr){ + return _imageStoreJoinDao.setImageStoreResponse(vrData, vr); + } + + public static List newImageStoreView(ImageStore vr){ + return _imageStoreJoinDao.newImageStoreView(vr); + } + public static AccountResponse newAccountResponse(AccountJoinVO ve) { return _accountJoinDao.newAccountResponse(ve); @@ -1648,6 +1637,33 @@ public class ApiDBUtils { return _nicSecondaryIpDao.listByNicId(nicId); } + public static TemplateResponse newTemplateUpdateResponse(TemplateJoinVO vr) { + return _templateJoinDao.newUpdateResponse(vr); + } + + + public static TemplateResponse newTemplateResponse(TemplateJoinVO vr) { + return _templateJoinDao.newTemplateResponse(vr); + } + + + public static TemplateResponse newIsoResponse(TemplateJoinVO vr) { + return _templateJoinDao.newIsoResponse(vr); + } + + public static TemplateResponse fillTemplateDetails(TemplateResponse vrData, TemplateJoinVO vr){ + return _templateJoinDao.setTemplateResponse(vrData, vr); + } + + public static List newTemplateView(VirtualMachineTemplate vr){ + return _templateJoinDao.newTemplateView(vr); + } + + + public static List newTemplateView(VirtualMachineTemplate vr, long zoneId, boolean readyOnly){ + return _templateJoinDao.newTemplateView(vr, zoneId, readyOnly); + } + public static AffinityGroup getAffinityGroup(String groupName, long accountId) { return _affinityGroupDao.findByAccountAndName(accountId, groupName); } diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 17cad7ed550..7d91e95bc9a 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -16,15 +16,9 @@ // under the License. package com.cloud.api; -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonList; - import java.text.DecimalFormat; import java.util.ArrayList; -import java.util.Arrays; import java.util.Calendar; -import java.util.Collections; -import java.util.Comparator; import java.util.Date; import java.util.EnumSet; import java.util.HashMap; @@ -32,6 +26,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.StringTokenizer; import java.util.TimeZone; import javax.inject.Inject; @@ -42,7 +37,6 @@ import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.ApiConstants.HostDetails; import org.apache.cloudstack.api.ApiConstants.VMDetails; -import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.ResponseGenerator; import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd; import org.apache.cloudstack.api.response.AccountResponse; @@ -92,6 +86,7 @@ import org.apache.cloudstack.api.response.NetworkOfferingResponse; import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.NicResponse; import org.apache.cloudstack.api.response.NicSecondaryIpResponse; +import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.cloudstack.api.response.PhysicalNetworkResponse; import org.apache.cloudstack.api.response.PodResponse; import org.apache.cloudstack.api.response.PortableIpRangeResponse; @@ -142,6 +137,7 @@ import org.apache.cloudstack.network.lb.ApplicationLoadBalancerRule; import org.apache.cloudstack.region.PortableIp; import org.apache.cloudstack.region.PortableIpRange; import org.apache.cloudstack.region.Region; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.usage.Usage; import org.apache.cloudstack.usage.UsageService; import org.apache.cloudstack.usage.UsageTypes; @@ -157,6 +153,7 @@ import com.cloud.api.query.vo.DiskOfferingJoinVO; import com.cloud.api.query.vo.DomainRouterJoinVO; import com.cloud.api.query.vo.EventJoinVO; import com.cloud.api.query.vo.HostJoinVO; +import com.cloud.api.query.vo.ImageStoreJoinVO; import com.cloud.api.query.vo.InstanceGroupJoinVO; import com.cloud.api.query.vo.ProjectAccountJoinVO; import com.cloud.api.query.vo.ProjectInvitationJoinVO; @@ -165,6 +162,7 @@ import com.cloud.api.query.vo.ResourceTagJoinVO; import com.cloud.api.query.vo.SecurityGroupJoinVO; import com.cloud.api.query.vo.ServiceOfferingJoinVO; import com.cloud.api.query.vo.StoragePoolJoinVO; +import com.cloud.api.query.vo.TemplateJoinVO; import com.cloud.api.query.vo.UserAccountJoinVO; import com.cloud.api.query.vo.UserVmJoinVO; import com.cloud.api.query.vo.VolumeJoinVO; @@ -181,7 +179,6 @@ import com.cloud.configuration.ResourceLimit; import com.cloud.dao.EntityManager; import com.cloud.dc.ClusterVO; import com.cloud.dc.DataCenter; -import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; import com.cloud.dc.Pod; import com.cloud.dc.StorageNetworkIpRange; @@ -254,24 +251,22 @@ import com.cloud.projects.Project; import com.cloud.projects.ProjectAccount; import com.cloud.projects.ProjectInvitation; import com.cloud.region.ha.GlobalLoadBalancerRule; +import com.cloud.server.Criteria; import com.cloud.server.ResourceTag; import com.cloud.server.ResourceTag.TaggedResourceType; import com.cloud.service.ServiceOfferingVO; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.GuestOS; import com.cloud.storage.GuestOSCategoryVO; +import com.cloud.storage.ImageStore; import com.cloud.storage.S3; import com.cloud.storage.Snapshot; import com.cloud.storage.SnapshotVO; -import com.cloud.storage.Storage.ImageFormat; -import com.cloud.storage.Storage.TemplateType; +import com.cloud.storage.Upload; +import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.StoragePool; import com.cloud.storage.Swift; import com.cloud.storage.UploadVO; -import com.cloud.storage.VMTemplateHostVO; -import com.cloud.storage.VMTemplateS3VO; -import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; -import com.cloud.storage.VMTemplateSwiftVO; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.Volume; import com.cloud.storage.VolumeVO; @@ -304,8 +299,10 @@ public class ApiResponseHelper implements ResponseGenerator { public final Logger s_logger = Logger.getLogger(ApiResponseHelper.class); private static final DecimalFormat s_percentFormat = new DecimalFormat("##.##"); - @Inject private EntityManager _entityMgr = null; - @Inject private UsageService _usageSvc = null; + @Inject + private EntityManager _entityMgr = null; + @Inject + private UsageService _usageSvc = null; @Inject NetworkModel _ntwkModel; @Override @@ -314,9 +311,8 @@ public class ApiResponseHelper implements ResponseGenerator { return ApiDBUtils.newUserResponse(vUser); } - - - // this method is used for response generation via createAccount (which creates an account + user) + // this method is used for response generation via createAccount (which + // creates an account + user) @Override public AccountResponse createUserAccountResponse(UserAccount user) { return ApiDBUtils.newAccountResponse(ApiDBUtils.findAccountViewById(user.getAccountId())); @@ -328,7 +324,6 @@ public class ApiResponseHelper implements ResponseGenerator { return ApiDBUtils.newAccountResponse(vUser); } - @Override public UserResponse createUserResponse(UserAccount user) { UserAccountJoinVO vUser = ApiDBUtils.newUserView(user); @@ -444,7 +439,7 @@ public class ApiResponseHelper implements ResponseGenerator { snapshotResponse.setIntervalType(ApiDBUtils.getSnapshotIntervalTypes(snapshot.getId())); snapshotResponse.setState(snapshot.getState()); - //set tag information + // set tag information List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Snapshot, snapshot.getId()); List tagResponses = new ArrayList(); for (ResourceTag tag : tags) { @@ -467,9 +462,9 @@ public class ApiResponseHelper implements ResponseGenerator { vmSnapshotResponse.setDescription(vmSnapshot.getDescription()); vmSnapshotResponse.setDisplayName(vmSnapshot.getDisplayName()); UserVm vm = ApiDBUtils.findUserVmById(vmSnapshot.getVmId()); - if(vm!=null) + if (vm != null) vmSnapshotResponse.setVirtualMachineid(vm.getUuid()); - if(vmSnapshot.getParent() != null) + if (vmSnapshot.getParent() != null) vmSnapshotResponse.setParentName(ApiDBUtils.getVMSnapshotById(vmSnapshot.getParent()).getDisplayName()); vmSnapshotResponse.setCurrent(vmSnapshot.getCurrent()); vmSnapshotResponse.setType(vmSnapshot.getType().toString()); @@ -580,9 +575,9 @@ public class ApiResponseHelper implements ResponseGenerator { // get start ip and end ip of corresponding vlan String ipRange = vlan.getIpRange(); if (ipRange != null) { - String[] range = ipRange.split("-"); - vlanResponse.setStartIp(range[0]); - vlanResponse.setEndIp(range[1]); + String[] range = ipRange.split("-"); + vlanResponse.setStartIp(range[0]); + vlanResponse.setEndIp(range[1]); } vlanResponse.setIp6Gateway(vlan.getIp6Gateway()); @@ -590,9 +585,9 @@ public class ApiResponseHelper implements ResponseGenerator { String ip6Range = vlan.getIp6Range(); if (ip6Range != null) { - String[] range = ip6Range.split("-"); - vlanResponse.setStartIpv6(range[0]); - vlanResponse.setEndIpv6(range[1]); + String[] range = ip6Range.split("-"); + vlanResponse.setStartIpv6(range[0]); + vlanResponse.setEndIpv6(range[1]); } if (vlan.getNetworkId() != null) { @@ -721,6 +716,7 @@ public class ApiResponseHelper implements ResponseGenerator { } } + ipResponse.setPortable(ipAddr.isPortable()); //set tag information @@ -771,7 +767,7 @@ public class ApiResponseHelper implements ResponseGenerator { tagResponses.add(tagResponse); } lbResponse.setTags(tagResponses); - + Network ntwk = ApiDBUtils.findNetworkById(loadBalancer.getNetworkId()); lbResponse.setNetworkId(ntwk.getUuid()); @@ -843,7 +839,8 @@ public class ApiResponseHelper implements ResponseGenerator { capacityResponse.setCapacityTotal(capacity.getTotalCapacity()); } if (capacityResponse.getCapacityTotal() != 0) { - capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() / (float) capacityResponse.getCapacityTotal() * 100f)); + capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() + / (float) capacityResponse.getCapacityTotal() * 100f)); } else { capacityResponse.setPercentUsed(s_percentFormat.format(0L)); } @@ -863,7 +860,7 @@ public class ApiResponseHelper implements ResponseGenerator { return ApiDBUtils.newDataCenterResponse(vOffering, showCapacities); } - public static List getDataCenterCapacityResponse(Long zoneId){ + public static List getDataCenterCapacityResponse(Long zoneId) { List capacities = ApiDBUtils.getCapacityByClusterPodZone(zoneId, null, null); Set capacityResponses = new HashSet(); float cpuOverprovisioningFactor = ApiDBUtils.getCpuOverprovisioningFactor(); @@ -882,7 +879,8 @@ public class ApiResponseHelper implements ResponseGenerator { capacityResponse.setCapacityTotal(capacity.getTotalCapacity()); } if (capacityResponse.getCapacityTotal() != 0) { - capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() / (float) capacityResponse.getCapacityTotal() * 100f)); + capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() + / (float) capacityResponse.getCapacityTotal() * 100f)); } else { capacityResponse.setPercentUsed(s_percentFormat.format(0L)); } @@ -908,7 +906,8 @@ public class ApiResponseHelper implements ResponseGenerator { capacityResponse.setCapacityUsed(capacity.getUsedCapacity()); capacityResponse.setCapacityTotal(capacity.getTotalCapacity()); if (capacityResponse.getCapacityTotal() != 0) { - capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() / (float) capacityResponse.getCapacityTotal() * 100f)); + capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() + / (float) capacityResponse.getCapacityTotal() * 100f)); } else { capacityResponse.setPercentUsed(s_percentFormat.format(0L)); } @@ -936,11 +935,21 @@ public class ApiResponseHelper implements ResponseGenerator { @Override public StoragePoolResponse createStoragePoolResponse(StoragePool pool) { List viewPools = ApiDBUtils.newStoragePoolView(pool); - List listPools = ViewResponseHelper.createStoragePoolResponse(viewPools.toArray(new StoragePoolJoinVO[viewPools.size()])); + List listPools = ViewResponseHelper + .createStoragePoolResponse(viewPools.toArray(new StoragePoolJoinVO[viewPools.size()])); assert listPools != null && listPools.size() == 1 : "There should be one storage pool returned"; return listPools.get(0); } + @Override + public ImageStoreResponse createImageStoreResponse(ImageStore os) { + List viewStores = ApiDBUtils.newImageStoreView(os); + List listStores = ViewResponseHelper + .createImageStoreResponse(viewStores.toArray(new ImageStoreJoinVO[viewStores.size()])); + assert listStores != null && listStores.size() == 1 : "There should be one image data store returned"; + return listStores.get(0); + } + @Override public StoragePoolResponse createStoragePoolForMigrationResponse(StoragePool pool) { List viewPools = ApiDBUtils.newStoragePoolView(pool); @@ -974,7 +983,6 @@ public class ApiResponseHelper implements ResponseGenerator { clusterResponse.setCpuOvercommitRatio(cpuOvercommitRatio); clusterResponse.setMemoryOvercommitRatio(memoryOvercommitRatio); - if (showCapacities != null && showCapacities) { List capacities = ApiDBUtils.getCapacityByClusterPodZone(null, null, cluster.getId()); Set capacityResponses = new HashSet(); @@ -986,10 +994,9 @@ public class ApiResponseHelper implements ResponseGenerator { if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_CPU) { capacityResponse.setCapacityTotal(new Long((long) (capacity.getTotalCapacity() * Float.parseFloat(cpuOvercommitRatio)))); - }else if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_MEMORY){ + } else if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_MEMORY) { capacityResponse.setCapacityTotal(new Long((long) (capacity.getTotalCapacity() * Float.parseFloat(memoryOvercommitRatio)))); - } - else if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED) { + } else if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED) { List c = ApiDBUtils.findNonSharedStorageForClusterPodZone(null, null, cluster.getId()); capacityResponse.setCapacityTotal(capacity.getTotalCapacity() - c.get(0).getTotalCapacity()); capacityResponse.setCapacityUsed(capacity.getUsedCapacity() - c.get(0).getUsedCapacity()); @@ -997,7 +1004,8 @@ public class ApiResponseHelper implements ResponseGenerator { capacityResponse.setCapacityTotal(capacity.getTotalCapacity()); } if (capacityResponse.getCapacityTotal() != 0) { - capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() / (float) capacityResponse.getCapacityTotal() * 100f)); + capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() + / (float) capacityResponse.getCapacityTotal() * 100f)); } else { capacityResponse.setPercentUsed(s_percentFormat.format(0L)); } @@ -1047,7 +1055,7 @@ public class ApiResponseHelper implements ResponseGenerator { stateToSet = "Deleting"; } - //set tag information + // set tag information List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.PortForwardingRule, fwRule.getId()); List tagResponses = new ArrayList(); for (ResourceTag tag : tags) { @@ -1110,8 +1118,6 @@ public class ApiResponseHelper implements ResponseGenerator { return ViewResponseHelper.createUserVmResponse(objectName, viewVms.toArray(new UserVmJoinVO[viewVms.size()])); } - - @Override public DomainRouterResponse createDomainRouterResponse(VirtualRouter router) { List viewVrs = ApiDBUtils.newDomainRouterView(router); @@ -1120,26 +1126,25 @@ public class ApiResponseHelper implements ResponseGenerator { return listVrs.get(0); } - @Override public SystemVmResponse createSystemVmResponse(VirtualMachine vm) { SystemVmResponse vmResponse = new SystemVmResponse(); if (vm.getType() == Type.SecondaryStorageVm || vm.getType() == Type.ConsoleProxy) { // SystemVm vm = (SystemVm) systemVM; vmResponse.setId(vm.getUuid()); - //vmResponse.setObjectId(vm.getId()); + // vmResponse.setObjectId(vm.getId()); vmResponse.setSystemVmType(vm.getType().toString().toLowerCase()); vmResponse.setName(vm.getHostName()); - if ( vm.getPodIdToDeployIn() != null ){ + if (vm.getPodIdToDeployIn() != null) { HostPodVO pod = ApiDBUtils.findPodById(vm.getPodIdToDeployIn()); - if ( pod != null ){ - vmResponse.setPodId(pod.getUuid()); + if (pod != null) { + vmResponse.setPodId(pod.getUuid()); } } VMTemplateVO template = ApiDBUtils.findTemplateById(vm.getTemplateId()); - if (template != null){ - vmResponse.setTemplateId(template.getUuid()); + if (template != null) { + vmResponse.setTemplateId(template.getUuid()); } vmResponse.setCreated(vm.getCreated()); @@ -1263,269 +1268,45 @@ public class ApiResponseHelper implements ResponseGenerator { } @Override - public TemplateResponse createIsoResponse(VirtualMachineTemplate result) { - TemplateResponse response = new TemplateResponse(); - response.setId(result.getUuid()); - response.setName(result.getName()); - response.setDisplayText(result.getDisplayText()); - response.setPublic(result.isPublicTemplate()); - response.setCreated(result.getCreated()); - response.setFormat(result.getFormat()); - GuestOS os = ApiDBUtils.findGuestOSById(result.getGuestOSId()); - if (os != null) { - response.setOsTypeId(os.getUuid()); - response.setOsTypeName(os.getDisplayName()); - } - response.setDetails(result.getDetails()); - Account caller = UserContext.current().getCaller(); + public TemplateResponse createTemplateUpdateResponse(VirtualMachineTemplate result) { + List tvo = ApiDBUtils.newTemplateView(result); + List listVrs = ViewResponseHelper.createTemplateUpdateResponse(tvo.toArray(new TemplateJoinVO[tvo.size()])); + assert listVrs != null && listVrs.size() == 1 : "There should be one template returned"; + return listVrs.get(0); + } - if (result.getFormat() == ImageFormat.ISO) { // Templates are always bootable - response.setBootable(result.isBootable()); + @Override + public List createTemplateResponses(VirtualMachineTemplate result, Long zoneId, boolean readyOnly) { + List tvo = null; + if (zoneId == null || zoneId == -1) { + tvo = ApiDBUtils.newTemplateView(result); } else { - response.setHypervisor(result.getHypervisorType().toString());// hypervisors are associated with templates + tvo = ApiDBUtils.newTemplateView(result, zoneId, readyOnly); + } - - // add account ID and name - Account owner = ApiDBUtils.findAccountById(result.getAccountId()); - populateAccount(response, owner.getId()); - populateDomain(response, owner.getDomainId()); - - //set tag information - List tags = null; - if (result.getFormat() == ImageFormat.ISO) { - tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, result.getId()); - } else { - tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Template, result.getId()); - } - - List tagResponses = new ArrayList(); - for (ResourceTag tag : tags) { - ResourceTagResponse tagResponse = createResourceTagResponse(tag, true); - tagResponses.add(tagResponse); - } - response.setTags(tagResponses); - - response.setObjectName("iso"); - response.setDynamicallyScalable(result.isDynamicallyScalable()); - return response; + return ViewResponseHelper.createTemplateResponse(tvo.toArray(new TemplateJoinVO[tvo.size()])); } @Override public List createTemplateResponses(long templateId, Long zoneId, boolean readyOnly) { - if (zoneId == null || zoneId == -1) { - List responses = new ArrayList(); - List dcs = new ArrayList(); - responses = createSwiftTemplateResponses(templateId); - if (!responses.isEmpty()) { - return responses; - } - dcs.addAll(ApiDBUtils.listZones()); - for (DataCenterVO dc : dcs) { - responses.addAll(createTemplateResponses(templateId, dc.getId(), readyOnly)); - } - return responses; - } else { - return createTemplateResponses(templateId, zoneId.longValue(), readyOnly); - } - } - - private List createSwiftTemplateResponses(long templateId) { VirtualMachineTemplate template = findTemplateById(templateId); - List responses = new ArrayList(); - VMTemplateSwiftVO templateSwiftRef = ApiDBUtils.findTemplateSwiftRef(templateId); - if (templateSwiftRef == null) { - return responses; - } - - TemplateResponse templateResponse = new TemplateResponse(); - templateResponse.setId(template.getUuid()); - templateResponse.setName(template.getName()); - templateResponse.setDisplayText(template.getDisplayText()); - templateResponse.setPublic(template.isPublicTemplate()); - templateResponse.setCreated(templateSwiftRef.getCreated()); - - templateResponse.setReady(true); - templateResponse.setFeatured(template.isFeatured()); - templateResponse.setExtractable(template.isExtractable() && !(template.getTemplateType() == TemplateType.SYSTEM)); - templateResponse.setPasswordEnabled(template.getEnablePassword()); - templateResponse.setSshKeyEnabled(template.getEnableSshKey()); - templateResponse.setCrossZones(template.isCrossZones()); - templateResponse.setFormat(template.getFormat()); - templateResponse.setDetails(template.getDetails()); - if (template.getTemplateType() != null) { - templateResponse.setTemplateType(template.getTemplateType().toString()); - } - - templateResponse.setHypervisor(template.getHypervisorType().toString()); - - GuestOS os = ApiDBUtils.findGuestOSById(template.getGuestOSId()); - if (os != null) { - templateResponse.setOsTypeId(os.getUuid()); - templateResponse.setOsTypeName(os.getDisplayName()); - } else { - templateResponse.setOsTypeId("-1"); - templateResponse.setOsTypeName(""); - } - - Account account = ApiDBUtils.findAccountByIdIncludingRemoved(template.getAccountId()); - populateAccount(templateResponse, account.getId()); - populateDomain(templateResponse, account.getDomainId()); - - Account caller = UserContext.current().getCaller(); - boolean isAdmin = false; - if (BaseCmd.isAdmin(caller.getType())) { - isAdmin = true; - } - - // If the user is an Admin, add the template download status - if (isAdmin || caller.getId() == template.getAccountId()) { - // add download status - templateResponse.setStatus("Successfully Installed"); - } - - Long templateSize = templateSwiftRef.getSize(); - if (templateSize > 0) { - templateResponse.setSize(templateSize); - } - - templateResponse.setChecksum(template.getChecksum()); - if (template.getSourceTemplateId() != null) { - VirtualMachineTemplate tmpl = ApiDBUtils.findTemplateById(template.getSourceTemplateId()); - if (tmpl != null) { - templateResponse.setSourceTemplateId(tmpl.getUuid()); - } - } - - templateResponse.setChecksum(template.getChecksum()); - - templateResponse.setTemplateTag(template.getTemplateTag()); - - templateResponse.setObjectName("template"); - responses.add(templateResponse); - return responses; + return createTemplateResponses(template, zoneId, readyOnly); } + @Override - public List createTemplateResponses(long templateId, long zoneId, boolean readyOnly) { - VirtualMachineTemplate template = findTemplateById(templateId); - List responses = new ArrayList(); - VMTemplateHostVO templateHostRef = ApiDBUtils.findTemplateHostRef(templateId, zoneId, readyOnly); - if (templateHostRef == null) { - return responses; - } - - HostVO host = ApiDBUtils.findHostById(templateHostRef.getHostId()); - if (host.getType() == Host.Type.LocalSecondaryStorage && host.getStatus() != com.cloud.host.Status.Up) { - return responses; - } - - TemplateResponse templateResponse = new TemplateResponse(); - templateResponse.setId(template.getUuid()); - templateResponse.setName(template.getName()); - templateResponse.setDisplayText(template.getDisplayText()); - templateResponse.setPublic(template.isPublicTemplate()); - templateResponse.setCreated(templateHostRef.getCreated()); - - templateResponse.setReady(templateHostRef.getDownloadState() == Status.DOWNLOADED); - templateResponse.setFeatured(template.isFeatured()); - templateResponse.setExtractable(template.isExtractable() && !(template.getTemplateType() == TemplateType.SYSTEM)); - templateResponse.setPasswordEnabled(template.getEnablePassword()); - templateResponse.setSshKeyEnabled(template.getEnableSshKey()); - templateResponse.setCrossZones(template.isCrossZones()); - templateResponse.setFormat(template.getFormat()); - if (template.getTemplateType() != null) { - templateResponse.setTemplateType(template.getTemplateType().toString()); - } - - templateResponse.setHypervisor(template.getHypervisorType().toString()); - templateResponse.setDetails(template.getDetails()); - - GuestOS os = ApiDBUtils.findGuestOSById(template.getGuestOSId()); - if (os != null) { - templateResponse.setOsTypeId(os.getUuid()); - templateResponse.setOsTypeName(os.getDisplayName()); + public List createIsoResponses(VirtualMachineTemplate result, Long zoneId, boolean readyOnly) { + List tvo = null; + if (zoneId == null || zoneId == -1) { + tvo = ApiDBUtils.newTemplateView(result); } else { - templateResponse.setOsTypeId("-1"); - templateResponse.setOsTypeName(""); + tvo = ApiDBUtils.newTemplateView(result, zoneId, readyOnly); } - Account account = ApiDBUtils.findAccountByIdIncludingRemoved(template.getAccountId()); - populateAccount(templateResponse, account.getId()); - populateDomain(templateResponse, account.getDomainId()); - - DataCenter datacenter = ApiDBUtils.findZoneById(zoneId); - - if (datacenter != null) { - // Add the zone ID - templateResponse.setZoneId(datacenter.getUuid()); - templateResponse.setZoneName(datacenter.getName()); - } - - boolean isAdmin = false; - Account caller = UserContext.current().getCaller(); - if ((caller == null) || BaseCmd.isAdmin(caller.getType())) { - isAdmin = true; - } - - // If the user is an Admin, add the template download status - if (isAdmin || caller.getId() == template.getAccountId()) { - // add download status - if (templateHostRef.getDownloadState() != Status.DOWNLOADED) { - String templateStatus = "Processing"; - if (templateHostRef.getDownloadState() == VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS) { - if (templateHostRef.getDownloadPercent() == 100) { - templateStatus = "Installing Template"; - } else { - templateStatus = templateHostRef.getDownloadPercent() + "% Downloaded"; - } - } else { - templateStatus = templateHostRef.getErrorString(); - } - templateResponse.setStatus(templateStatus); - } else if (templateHostRef.getDownloadState() == VMTemplateHostVO.Status.DOWNLOADED) { - templateResponse.setStatus("Download Complete"); - } else { - templateResponse.setStatus("Successfully Installed"); - } - } - - Long templateSize = templateHostRef.getSize(); - if (templateSize > 0) { - templateResponse.setSize(templateSize); - } - - templateResponse.setChecksum(template.getChecksum()); - if (template.getSourceTemplateId() != null) { - VirtualMachineTemplate tmpl = ApiDBUtils.findTemplateById(template.getSourceTemplateId()); - if (tmpl != null) { - templateResponse.setSourceTemplateId(tmpl.getUuid()); - } - } - - templateResponse.setChecksum(template.getChecksum()); - - templateResponse.setTemplateTag(template.getTemplateTag()); - - //set tag information - List tags = null; - if (template.getFormat() == ImageFormat.ISO) { - tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, template.getId()); - } else { - tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Template, template.getId()); - } - List tagResponses = new ArrayList(); - for (ResourceTag tag : tags) { - ResourceTagResponse tagResponse = createResourceTagResponse(tag, true); - tagResponses.add(tagResponse); - } - templateResponse.setTags(tagResponses); - - templateResponse.setObjectName("template"); - templateResponse.setDynamicallyScalable(template.isDynamicallyScalable()); - responses.add(templateResponse); - return responses; + return ViewResponseHelper.createIsoResponse(tvo.toArray(new TemplateJoinVO[tvo.size()])); } + /* @Override public List createIsoResponses(long isoId, Long zoneId, boolean readyOnly) { @@ -1547,15 +1328,14 @@ public class ApiResponseHelper implements ResponseGenerator { isoResponse.setChecksum(iso.getChecksum()); isoResponse.setPasswordEnabled(false); isoResponse.setDetails(iso.getDetails()); - isoResponse.setDynamicallyScalable(iso.isDynamicallyScalable()); // add account ID and name Account owner = ApiDBUtils.findAccountById(iso.getAccountId()); populateAccount(isoResponse, owner.getId()); populateDomain(isoResponse, owner.getDomainId()); - //set tag information - List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, iso.getId()); + // set tag information + List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, iso.getId()); List tagResponses = new ArrayList(); for (ResourceTag tag : tags) { ResourceTagResponse tagResponse = createResourceTagResponse(tag, true); @@ -1724,7 +1504,6 @@ public class ApiResponseHelper implements ResponseGenerator { isoResponse.setPublic(iso.isPublicTemplate()); isoResponse.setChecksum(iso.getChecksum()); isoResponse.setDetails(iso.getDetails()); - isoResponse.setDynamicallyScalable(iso.isDynamicallyScalable()); // TODO: implement GuestOS os = ApiDBUtils.findGuestOSById(iso.getGuestOSId()); @@ -1779,8 +1558,8 @@ public class ApiResponseHelper implements ResponseGenerator { isoResponse.setSize(isoSize); } - //set tag information - List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, iso.getId()); + // set tag information + List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, iso.getId()); List tagResponses = new ArrayList(); for (ResourceTag tag : tags) { @@ -1793,8 +1572,7 @@ public class ApiResponseHelper implements ResponseGenerator { isoResponses.add(isoResponse); return isoResponses; } - - +*/ @Override public SecurityGroupResponse createSecurityGroupResponse(SecurityGroup group) { @@ -1804,9 +1582,10 @@ public class ApiResponseHelper implements ResponseGenerator { return listSgs.get(0); } + //TODO: we need to deprecate uploadVO, since extract is done in a synchronous fashion @Override - public ExtractResponse createExtractResponse(Long uploadId, Long id, Long zoneId, Long accountId, String mode) { - UploadVO uploadInfo = ApiDBUtils.findUploadById(uploadId); + public ExtractResponse createExtractResponse(Long id, Long zoneId, Long accountId, String mode, String url) { + ExtractResponse response = new ExtractResponse(); response.setObjectName("template"); VMTemplateVO template = ApiDBUtils.findTemplateById(id); @@ -1818,11 +1597,41 @@ public class ApiResponseHelper implements ResponseGenerator { response.setZoneName(zone.getName()); } response.setMode(mode); - response.setUploadId(uploadInfo.getUuid()); - response.setState(uploadInfo.getUploadState().toString()); + response.setUrl(url); + response.setState(Upload.Status.DOWNLOAD_URL_CREATED.toString()); Account account = ApiDBUtils.findAccountById(accountId); response.setAccountId(account.getUuid()); - response.setUrl(uploadInfo.getUploadUrl()); + + return response; + } + + @Override + public ExtractResponse createExtractResponse(Long uploadId, Long id, Long zoneId, Long accountId, String mode, String url) { + + ExtractResponse response = new ExtractResponse(); + response.setObjectName("template"); + VMTemplateVO template = ApiDBUtils.findTemplateById(id); + response.setId(template.getUuid()); + response.setName(template.getName()); + if (zoneId != null) { + DataCenter zone = ApiDBUtils.findZoneById(zoneId); + response.setZoneId(zone.getUuid()); + response.setZoneName(zone.getName()); + } + response.setMode(mode); + if (uploadId == null) { + // region-wide image store + response.setUrl(url); + response.setState(Upload.Status.DOWNLOAD_URL_CREATED.toString()); + } else { + UploadVO uploadInfo = ApiDBUtils.findUploadById(uploadId); + response.setUploadId(uploadInfo.getUuid()); + response.setState(uploadInfo.getUploadState().toString()); + response.setUrl(uploadInfo.getUploadUrl()); + } + Account account = ApiDBUtils.findAccountById(accountId); + response.setAccountId(account.getUuid()); + return response; } @@ -1858,8 +1667,6 @@ public class ApiResponseHelper implements ResponseGenerator { return createTemplateResponses(templateId, host.getDataCenterId(), true); } - - @Override public EventResponse createEventResponse(Event event) { EventJoinVO vEvent = ApiDBUtils.newEventView(event); @@ -1867,6 +1674,153 @@ public class ApiResponseHelper implements ResponseGenerator { } + private List sumCapacities(List hostCapacities) { + Map totalCapacityMap = new HashMap(); + Map usedCapacityMap = new HashMap(); + + Set poolIdsToIgnore = new HashSet(); + Criteria c = new Criteria(); + // TODO: implement + List allStoragePools = ApiDBUtils.searchForStoragePools(c); + for (StoragePoolVO pool : allStoragePools) { + StoragePoolType poolType = pool.getPoolType(); + if (!(poolType.isShared())) {// All the non shared storages + // shouldn't show up in the capacity + // calculation + poolIdsToIgnore.add(pool.getId()); + } + } + + float cpuOverprovisioningFactor = ApiDBUtils.getCpuOverprovisioningFactor(); + + // collect all the capacity types, sum allocated/used and sum + // total...get one capacity number for each + for (Capacity capacity : hostCapacities) { + + // check if zone exist + DataCenter zone = ApiDBUtils.findZoneById(capacity.getDataCenterId()); + if (zone == null) { + continue; + } + + short capacityType = capacity.getCapacityType(); + + // If local storage then ignore + if ((capacityType == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED || capacityType == Capacity.CAPACITY_TYPE_STORAGE) + && poolIdsToIgnore.contains(capacity.getHostOrPoolId())) { + continue; + } + + String key = capacity.getCapacityType() + "_" + capacity.getDataCenterId(); + String keyForPodTotal = key + "_-1"; + + boolean sumPodCapacity = false; + if (capacity.getPodId() != null) { + key += "_" + capacity.getPodId(); + sumPodCapacity = true; + } + + Long totalCapacity = totalCapacityMap.get(key); + Long usedCapacity = usedCapacityMap.get(key); + + // reset overprovisioning factor to 1 + float overprovisioningFactor = 1; + if (capacityType == Capacity.CAPACITY_TYPE_CPU) { + overprovisioningFactor = cpuOverprovisioningFactor; + } + + if (totalCapacity == null) { + totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor)); + } else { + totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor)) + totalCapacity; + } + + if (usedCapacity == null) { + usedCapacity = new Long(capacity.getUsedCapacity()); + } else { + usedCapacity = new Long(capacity.getUsedCapacity() + usedCapacity); + } + + if (capacityType == Capacity.CAPACITY_TYPE_CPU || capacityType == Capacity.CAPACITY_TYPE_MEMORY) { // Reserved + // Capacity + // accounts + // for + // stopped + // vms + // that + // have been + // stopped + // within + // an + // interval + usedCapacity += capacity.getReservedCapacity(); + } + + totalCapacityMap.put(key, totalCapacity); + usedCapacityMap.put(key, usedCapacity); + + if (sumPodCapacity) { + totalCapacity = totalCapacityMap.get(keyForPodTotal); + usedCapacity = usedCapacityMap.get(keyForPodTotal); + + overprovisioningFactor = 1; + if (capacityType == Capacity.CAPACITY_TYPE_CPU) { + overprovisioningFactor = cpuOverprovisioningFactor; + } + + if (totalCapacity == null) { + totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor)); + } else { + totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor)) + totalCapacity; + } + + if (usedCapacity == null) { + usedCapacity = new Long(capacity.getUsedCapacity()); + } else { + usedCapacity = new Long(capacity.getUsedCapacity() + usedCapacity); + } + + if (capacityType == Capacity.CAPACITY_TYPE_CPU || capacityType == Capacity.CAPACITY_TYPE_MEMORY) { // Reserved + // Capacity + // accounts + // for + // stopped + // vms + // that + // have + // been + // stopped + // within + // an + // interval + usedCapacity += capacity.getReservedCapacity(); + } + + totalCapacityMap.put(keyForPodTotal, totalCapacity); + usedCapacityMap.put(keyForPodTotal, usedCapacity); + } + } + + List summedCapacities = new ArrayList(); + for (String key : totalCapacityMap.keySet()) { + CapacityVO summedCapacity = new CapacityVO(); + + StringTokenizer st = new StringTokenizer(key, "_"); + summedCapacity.setCapacityType(Short.parseShort(st.nextToken())); + summedCapacity.setDataCenterId(Long.parseLong(st.nextToken())); + if (st.hasMoreTokens()) { + summedCapacity.setPodId(Long.parseLong(st.nextToken())); + } + + summedCapacity.setTotalCapacity(totalCapacityMap.get(key)); + summedCapacity.setUsedCapacity(usedCapacityMap.get(key)); + + summedCapacities.add(summedCapacity); + } + return summedCapacities; + } + + @Override public List createCapacityResponse(List result, DecimalFormat format) { List capacityResponses = new ArrayList(); @@ -1901,10 +1855,11 @@ public class ApiResponseHelper implements ResponseGenerator { capacityResponse.setZoneId(zone.getUuid()); capacityResponse.setZoneName(zone.getName()); } - if (summedCapacity.getUsedPercentage() != null){ + if (summedCapacity.getUsedPercentage() != null) { capacityResponse.setPercentUsed(format.format(summedCapacity.getUsedPercentage() * 100f)); } else if (summedCapacity.getTotalCapacity() != 0) { - capacityResponse.setPercentUsed(format.format((float) summedCapacity.getUsedCapacity() / (float) summedCapacity.getTotalCapacity() * 100f)); + capacityResponse.setPercentUsed(format.format((float) summedCapacity.getUsedCapacity() / (float) summedCapacity.getTotalCapacity() + * 100f)); } else { capacityResponse.setPercentUsed(format.format(0L)); } @@ -1922,7 +1877,8 @@ public class ApiResponseHelper implements ResponseGenerator { VirtualMachineTemplate template = ApiDBUtils.findTemplateById(id); Account templateOwner = ApiDBUtils.findAccountById(template.getAccountId()); if (isAdmin) { - // FIXME: we have just template id and need to get template owner from that + // FIXME: we have just template id and need to get template owner + // from that if (templateOwner != null) { templateOwnerDomain = templateOwner.getDomainId(); } @@ -2103,10 +2059,10 @@ public class ApiResponseHelper implements ResponseGenerator { eLb.setValue(offering.getElasticLb() ? "true" : "false"); lbCapResponse.add(eLb); - CapabilityResponse inline = new CapabilityResponse(); - inline.setName(Capability.InlineMode.getName()); - inline.setValue(offering.isInline() ? "true" : "false"); - lbCapResponse.add(inline); + CapabilityResponse inline = new CapabilityResponse(); + inline.setName(Capability.InlineMode.getName()); + inline.setValue(offering.isInline() ? "true" : "false"); + lbCapResponse.add(inline); svcRsp.setCapabilities(lbCapResponse); } else if (Service.SourceNat == service) { @@ -2143,20 +2099,21 @@ public class ApiResponseHelper implements ResponseGenerator { response.setForVpc(ApiDBUtils.isOfferingForVpc(offering)); response.setServices(serviceResponses); - + //set network offering details Map details = _ntwkModel.getNtwkOffDetails(offering.getId()); if (details != null && !details.isEmpty()) { response.setDetails(details); } - + response.setObjectName("networkoffering"); return response; } @Override public NetworkResponse createNetworkResponse(Network network) { - // need to get network profile in order to retrieve dns information from there + // need to get network profile in order to retrieve dns information from + // there NetworkProfile profile = ApiDBUtils.getNetworkProfile(network.getId()); NetworkResponse response = new NetworkResponse(); response.setId(network.getUuid()); @@ -2179,8 +2136,10 @@ public class ApiResponseHelper implements ResponseGenerator { // FIXME - either set netmask or cidr response.setCidr(network.getCidr()); response.setNetworkCidr((network.getNetworkCidr())); - // If network has reservation its entire network cidr is defined by getNetworkCidr() - // if no reservation is present then getCidr() will define the entire network cidr + // If network has reservation its entire network cidr is defined by + // getNetworkCidr() + // if no reservation is present then getCidr() will define the entire + // network cidr if (network.getNetworkCidr() != null) { response.setNetmask(NetUtils.cidr2Netmask(network.getNetworkCidr())); } @@ -2191,44 +2150,45 @@ public class ApiResponseHelper implements ResponseGenerator { response.setIp6Gateway(network.getIp6Gateway()); response.setIp6Cidr(network.getIp6Cidr()); - // create response for reserved IP ranges that can be used for non-cloudstack purposes - String reservation = null; + // create response for reserved IP ranges that can be used for + // non-cloudstack purposes + String reservation = null; if ((network.getCidr() != null) && (NetUtils.isNetworkAWithinNetworkB(network.getCidr(), network.getNetworkCidr()))) { - String[] guestVmCidrPair = network.getCidr().split("\\/"); - String[] guestCidrPair = network.getNetworkCidr().split("\\/"); + String[] guestVmCidrPair = network.getCidr().split("\\/"); + String[] guestCidrPair = network.getNetworkCidr().split("\\/"); - Long guestVmCidrSize = Long.valueOf(guestVmCidrPair[1]); - Long guestCidrSize = Long.valueOf(guestCidrPair[1]); + Long guestVmCidrSize = Long.valueOf(guestVmCidrPair[1]); + Long guestCidrSize = Long.valueOf(guestCidrPair[1]); - String[] guestVmIpRange = NetUtils.getIpRangeFromCidr(guestVmCidrPair[0], guestVmCidrSize); - String[] guestIpRange = NetUtils.getIpRangeFromCidr(guestCidrPair[0], guestCidrSize); - long startGuestIp = NetUtils.ip2Long(guestIpRange[0]); - long endGuestIp = NetUtils.ip2Long(guestIpRange[1]); - long startVmIp = NetUtils.ip2Long(guestVmIpRange[0]); - long endVmIp = NetUtils.ip2Long(guestVmIpRange[1]); + String[] guestVmIpRange = NetUtils.getIpRangeFromCidr(guestVmCidrPair[0], guestVmCidrSize); + String[] guestIpRange = NetUtils.getIpRangeFromCidr(guestCidrPair[0], guestCidrSize); + long startGuestIp = NetUtils.ip2Long(guestIpRange[0]); + long endGuestIp = NetUtils.ip2Long(guestIpRange[1]); + long startVmIp = NetUtils.ip2Long(guestVmIpRange[0]); + long endVmIp = NetUtils.ip2Long(guestVmIpRange[1]); - if (startVmIp == startGuestIp && endVmIp < endGuestIp -1) { - reservation = (NetUtils.long2Ip(endVmIp + 1) + "-" + NetUtils.long2Ip(endGuestIp)); - } - if (endVmIp == endGuestIp && startVmIp > startGuestIp + 1) { - reservation = (NetUtils.long2Ip(startGuestIp) + "-" + NetUtils.long2Ip(startVmIp-1)); - } - if(startVmIp > startGuestIp + 1 && endVmIp < endGuestIp - 1) { - reservation = (NetUtils.long2Ip(startGuestIp) + "-" + NetUtils.long2Ip(startVmIp-1) + " , " + - NetUtils.long2Ip(endVmIp + 1) + "-"+ NetUtils.long2Ip(endGuestIp)); + if (startVmIp == startGuestIp && endVmIp < endGuestIp - 1) { + reservation = (NetUtils.long2Ip(endVmIp + 1) + "-" + NetUtils.long2Ip(endGuestIp)); + } + if (endVmIp == endGuestIp && startVmIp > startGuestIp + 1) { + reservation = (NetUtils.long2Ip(startGuestIp) + "-" + NetUtils.long2Ip(startVmIp - 1)); + } + if (startVmIp > startGuestIp + 1 && endVmIp < endGuestIp - 1) { + reservation = (NetUtils.long2Ip(startGuestIp) + "-" + NetUtils.long2Ip(startVmIp - 1) + " , " + NetUtils.long2Ip(endVmIp + 1) + "-" + NetUtils + .long2Ip(endGuestIp)); } } response.setReservedIpRange(reservation); - //return vlan information only to Root admin + // return vlan information only to Root admin if (network.getBroadcastUri() != null && UserContext.current().getCaller().getType() == Account.ACCOUNT_TYPE_ADMIN) { String broadcastUri = network.getBroadcastUri().toString(); response.setBroadcastUri(broadcastUri); - String vlan="N/A"; + String vlan = "N/A"; if (broadcastUri.startsWith("vlan")) { vlan = broadcastUri.substring("vlan://".length(), broadcastUri.length()); } - //return vlan information only to Root admin + // return vlan information only to Root admin response.setVlan(vlan); } @@ -2333,7 +2293,7 @@ public class ApiResponseHelper implements ResponseGenerator { } response.setCanUseForDeploy(ApiDBUtils.canUseForDeploy(network)); - //set tag information + // set tag information List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Network, network.getId()); List tagResponses = new ArrayList(); for (ResourceTag tag : tags) { @@ -2371,9 +2331,6 @@ public class ApiResponseHelper implements ResponseGenerator { return listPrjs.get(0); } - - - @Override public FirewallResponse createFirewallResponse(FirewallRule fwRule) { FirewallResponse response = new FirewallResponse(); @@ -2410,7 +2367,7 @@ public class ApiResponseHelper implements ResponseGenerator { response.setIcmpCode(fwRule.getIcmpCode()); response.setIcmpType(fwRule.getIcmpType()); - //set tag information + // set tag information List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.FirewallRule, fwRule.getId()); List tagResponses = new ArrayList(); for (ResourceTag tag : tags) { @@ -2487,7 +2444,8 @@ public class ApiResponseHelper implements ResponseGenerator { return hpvCapabilitiesResponse; } - // TODO: we may need to refactor once ControlledEntityResponse and ControlledEntity id to uuid conversion are all done. + // TODO: we may need to refactor once ControlledEntityResponse and + // ControlledEntity id to uuid conversion are all done. // currently code is scattered in private void populateOwner(ControlledEntityResponse response, ControlledEntity object) { Account account = ApiDBUtils.findAccountByIdIncludingRemoved(object.getAccountId()); @@ -2546,16 +2504,12 @@ public class ApiResponseHelper implements ResponseGenerator { return listProjs.get(0); } - - - @Override public ProjectInvitationResponse createProjectInvitationResponse(ProjectInvitation invite) { ProjectInvitationJoinVO vInvite = ApiDBUtils.newProjectInvitationView(invite); return ApiDBUtils.newProjectInvitationResponse(vInvite); } - @Override public SystemVmInstanceResponse createSystemVmInstanceResponse(VirtualMachine vm) { SystemVmInstanceResponse vmResponse = new SystemVmInstanceResponse(); @@ -2590,25 +2544,7 @@ public class ApiResponseHelper implements ResponseGenerator { response.setZoneId(zone.getUuid()); } response.setNetworkSpeed(result.getSpeed()); - //Create vlan ranges response - String vlanRanges = null; - vlanRanges = result.getVnetString(); - if(vlanRanges != null) { - String [] vlan = vlanRanges.split(";"); - - //Sort the vlan ranges - Arrays.sort(vlan, new Comparator() { - public int compare (String first, String second) { - return Integer.valueOf(first.split("-")[0]).compareTo(Integer.valueOf(second.split("-")[0])); - } - }); - List vlanList = new ArrayList(); - Collections.addAll(vlanList, vlan); - vlanRanges = StringUtils.join(vlanList,";"); - } - //Set the final String response - response.setVlan(vlanRanges); - + response.setVlan(result.getVnetString()); if (result.getDomainId() != null) { Domain domain = ApiDBUtils.findDomainById(result.getDomainId()); if (domain != null) { @@ -2662,9 +2598,8 @@ public class ApiResponseHelper implements ResponseGenerator { CapabilityResponse capabilityResponse = new CapabilityResponse(); capabilityResponse.setName(cap.getName()); capabilityResponse.setObjectName("capability"); - if (cap.getName().equals(Capability.SupportedLBIsolation.getName()) || - cap.getName().equals(Capability.SupportedSourceNatTypes.getName()) || - cap.getName().equals(Capability.RedundantRouter.getName())) { + if (cap.getName().equals(Capability.SupportedLBIsolation.getName()) || cap.getName().equals(Capability.SupportedSourceNatTypes.getName()) + || cap.getName().equals(Capability.RedundantRouter.getName())) { capabilityResponse.setCanChoose(true); } else { capabilityResponse.setCanChoose(false); @@ -2766,8 +2701,7 @@ public class ApiResponseHelper implements ResponseGenerator { } @Override - public LBStickinessResponse createLBStickinessPolicyResponse( - StickinessPolicy stickinessPolicy, LoadBalancer lb) { + public LBStickinessResponse createLBStickinessPolicyResponse(StickinessPolicy stickinessPolicy, LoadBalancer lb) { LBStickinessResponse spResponse = new LBStickinessResponse(); spResponse.setlbRuleId(lb.getUuid()); @@ -2782,8 +2716,7 @@ public class ApiResponseHelper implements ResponseGenerator { } List responses = new ArrayList(); - LBStickinessPolicyResponse ruleResponse = new LBStickinessPolicyResponse( - stickinessPolicy); + LBStickinessPolicyResponse ruleResponse = new LBStickinessPolicyResponse(stickinessPolicy); responses.add(ruleResponse); spResponse.setRules(responses); @@ -2793,8 +2726,7 @@ public class ApiResponseHelper implements ResponseGenerator { } @Override - public LBStickinessResponse createLBStickinessPolicyResponse( - List stickinessPolicies, LoadBalancer lb) { + public LBStickinessResponse createLBStickinessPolicyResponse(List stickinessPolicies, LoadBalancer lb) { LBStickinessResponse spResponse = new LBStickinessResponse(); if (lb == null) @@ -2822,8 +2754,7 @@ public class ApiResponseHelper implements ResponseGenerator { } @Override - public LBHealthCheckResponse createLBHealthCheckPolicyResponse( - List healthcheckPolicies, LoadBalancer lb) { + public LBHealthCheckResponse createLBHealthCheckPolicyResponse(List healthcheckPolicies, LoadBalancer lb) { LBHealthCheckResponse hcResponse = new LBHealthCheckResponse(); if (lb == null) @@ -2874,9 +2805,8 @@ public class ApiResponseHelper implements ResponseGenerator { } @Override - public LDAPConfigResponse createLDAPConfigResponse(String hostname, - Integer port, Boolean useSSL, String queryFilter, - String searchBase, String bindDN) { + public LDAPConfigResponse createLDAPConfigResponse(String hostname, Integer port, Boolean useSSL, String queryFilter, String searchBase, + String bindDN) { LDAPConfigResponse lr = new LDAPConfigResponse(); lr.setHostname(hostname); lr.setPort(port.toString()); @@ -2904,15 +2834,15 @@ public class ApiResponseHelper implements ResponseGenerator { return response; } - @Override - public RegionResponse createRegionResponse(Region region) { - RegionResponse response = new RegionResponse(); - response.setId(region.getId()); - response.setName(region.getName()); - response.setEndPoint(region.getEndPoint()); - response.setObjectName("region"); - return response; - } + @Override + public RegionResponse createRegionResponse(Region region) { + RegionResponse response = new RegionResponse(); + response.setId(region.getId()); + response.setName(region.getName()); + response.setEndPoint(region.getEndPoint()); + response.setObjectName("region"); + return response; + } @Override public ResourceTagResponse createResourceTagResponse(ResourceTag resourceTag, boolean keyValueOnly) { @@ -2920,8 +2850,6 @@ public class ApiResponseHelper implements ResponseGenerator { return ApiDBUtils.newResourceTagResponse(rto, keyValueOnly); } - - @Override public VpcOfferingResponse createVpcOfferingResponse(VpcOffering offering) { VpcOfferingResponse response = new VpcOfferingResponse(); @@ -2957,7 +2885,6 @@ public class ApiResponseHelper implements ResponseGenerator { return response; } - @Override public VpcResponse createVpcResponse(Vpc vpc) { VpcResponse response = new VpcResponse(); @@ -3012,7 +2939,7 @@ public class ApiResponseHelper implements ResponseGenerator { response.setServices(serviceResponses); populateOwner(response, vpc); - //set tag information + // set tag information List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Vpc, vpc.getId()); List tagResponses = new ArrayList(); for (ResourceTag tag : tags) { @@ -3059,7 +2986,6 @@ public class ApiResponseHelper implements ResponseGenerator { response.setObjectName("privategateway"); - return response; } @@ -3204,7 +3130,7 @@ public class ApiResponseHelper implements ResponseGenerator { populateAccount(response, result.getAccountId()); populateDomain(response, result.getDomainId()); - //set tag information + // set tag information List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.StaticRoute, result.getId()); List tagResponses = new ArrayList(); for (ResourceTag tag : tags) { @@ -3263,7 +3189,7 @@ public class ApiResponseHelper implements ResponseGenerator { response.setId(result.getUuid()); Long vpnGatewayId = result.getVpnGatewayId(); - if(vpnGatewayId != null) { + if (vpnGatewayId != null) { Site2SiteVpnGateway vpnGateway = ApiDBUtils.findVpnGatewayById(vpnGatewayId); if (vpnGateway != null) { response.setVpnGatewayId(vpnGateway.getUuid()); @@ -3274,7 +3200,7 @@ public class ApiResponseHelper implements ResponseGenerator { } Long customerGatewayId = result.getCustomerGatewayId(); - if(customerGatewayId != null) { + if (customerGatewayId != null) { Site2SiteCustomerGateway customerGateway = ApiDBUtils.findCustomerGatewayById(customerGatewayId); if (customerGateway != null) { response.setCustomerGatewayId(customerGateway.getUuid()); @@ -3298,13 +3224,14 @@ public class ApiResponseHelper implements ResponseGenerator { response.setObjectName("vpnconnection"); return response; } + @Override public GuestOSResponse createGuestOSResponse(GuestOS guestOS) { GuestOSResponse response = new GuestOSResponse(); response.setDescription(guestOS.getDisplayName()); response.setId(guestOS.getUuid()); GuestOSCategoryVO category = ApiDBUtils.findGuestOsCategoryById(guestOS.getCategoryId()); - if ( category != null ){ + if (category != null) { response.setOsCategoryId(category.getUuid()); } @@ -3312,8 +3239,6 @@ public class ApiResponseHelper implements ResponseGenerator { return response; } - - @Override public SnapshotScheduleResponse createSnapshotScheduleResponse(SnapshotSchedule snapshotSchedule) { SnapshotScheduleResponse response = new SnapshotScheduleResponse(); @@ -3336,82 +3261,81 @@ public class ApiResponseHelper implements ResponseGenerator { return response; } + @Override + public UsageRecordResponse createUsageResponse(Usage usageRecord) { + UsageRecordResponse usageRecResponse = new UsageRecordResponse(); - @Override - public UsageRecordResponse createUsageResponse(Usage usageRecord) { - UsageRecordResponse usageRecResponse = new UsageRecordResponse(); + Account account = ApiDBUtils.findAccountByIdIncludingRemoved(usageRecord.getAccountId()); + if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { + //find the project + Project project = ApiDBUtils.findProjectByProjectAccountIdIncludingRemoved(account.getId()); + usageRecResponse.setProjectId(project.getUuid()); + usageRecResponse.setProjectName(project.getName()); + } else { + usageRecResponse.setAccountId(account.getUuid()); + usageRecResponse.setAccountName(account.getAccountName()); + } - Account account = ApiDBUtils.findAccountByIdIncludingRemoved(usageRecord.getAccountId()); - if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { - //find the project - Project project = ApiDBUtils.findProjectByProjectAccountIdIncludingRemoved(account.getId()); - usageRecResponse.setProjectId(project.getUuid()); - usageRecResponse.setProjectName(project.getName()); - } else { - usageRecResponse.setAccountId(account.getUuid()); - usageRecResponse.setAccountName(account.getAccountName()); - } + Domain domain = ApiDBUtils.findDomainById(usageRecord.getDomainId()); + if (domain != null) { + usageRecResponse.setDomainId(domain.getUuid()); + } - Domain domain = ApiDBUtils.findDomainById(usageRecord.getDomainId()); - if (domain != null) { - usageRecResponse.setDomainId(domain.getUuid()); - } + if (usageRecord.getZoneId() != null) { + DataCenter zone = ApiDBUtils.findZoneById(usageRecord.getZoneId()); + if (zone != null) { + usageRecResponse.setZoneId(zone.getUuid()); + } + } + usageRecResponse.setDescription(usageRecord.getDescription()); + usageRecResponse.setUsage(usageRecord.getUsageDisplay()); + usageRecResponse.setUsageType(usageRecord.getUsageType()); + if (usageRecord.getVmInstanceId() != null) { + VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getVmInstanceId()); + usageRecResponse.setVirtualMachineId(vm.getUuid()); + } + usageRecResponse.setVmName(usageRecord.getVmName()); + if (usageRecord.getTemplateId() != null) { + VMTemplateVO template = ApiDBUtils.findTemplateById(usageRecord.getTemplateId()); + if (template != null) { + usageRecResponse.setTemplateId(template.getUuid()); + } + } - if (usageRecord.getZoneId() != null) { - DataCenter zone = ApiDBUtils.findZoneById(usageRecord.getZoneId()); - if (zone != null) { - usageRecResponse.setZoneId(zone.getUuid()); - } - } - usageRecResponse.setDescription(usageRecord.getDescription()); - usageRecResponse.setUsage(usageRecord.getUsageDisplay()); - usageRecResponse.setUsageType(usageRecord.getUsageType()); - if (usageRecord.getVmInstanceId() != null) { - VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getVmInstanceId()); - usageRecResponse.setVirtualMachineId(vm.getUuid()); - } - usageRecResponse.setVmName(usageRecord.getVmName()); - if (usageRecord.getTemplateId() != null) { - VMTemplateVO template = ApiDBUtils.findTemplateById(usageRecord.getTemplateId()); - if (template != null) { - usageRecResponse.setTemplateId(template.getUuid()); - } - } + if(usageRecord.getUsageType() == UsageTypes.RUNNING_VM || usageRecord.getUsageType() == UsageTypes.ALLOCATED_VM){ + ServiceOfferingVO svcOffering = _entityMgr.findByIdIncludingRemoved(ServiceOfferingVO.class, usageRecord.getOfferingId().toString()); + //Service Offering Id + usageRecResponse.setOfferingId(svcOffering.getUuid()); + //VM Instance ID + VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(vm.getUuid()); + //Hypervisor Type + usageRecResponse.setType(usageRecord.getType()); - if(usageRecord.getUsageType() == UsageTypes.RUNNING_VM || usageRecord.getUsageType() == UsageTypes.ALLOCATED_VM){ - ServiceOfferingVO svcOffering = _entityMgr.findByIdIncludingRemoved(ServiceOfferingVO.class, usageRecord.getOfferingId().toString()); - //Service Offering Id - usageRecResponse.setOfferingId(svcOffering.getUuid()); - //VM Instance ID - VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(vm.getUuid()); - //Hypervisor Type - usageRecResponse.setType(usageRecord.getType()); + } else if(usageRecord.getUsageType() == UsageTypes.IP_ADDRESS){ + //isSourceNAT + usageRecResponse.setSourceNat((usageRecord.getType().equals("SourceNat"))?true:false); + //isSystem + usageRecResponse.setSystem((usageRecord.getSize() == 1)?true:false); + //IP Address ID + IPAddressVO ip = _entityMgr.findByIdIncludingRemoved(IPAddressVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(ip.getUuid()); - } else if(usageRecord.getUsageType() == UsageTypes.IP_ADDRESS){ - //isSourceNAT - usageRecResponse.setSourceNat((usageRecord.getType().equals("SourceNat"))?true:false); - //isSystem - usageRecResponse.setSystem((usageRecord.getSize() == 1)?true:false); - //IP Address ID - IPAddressVO ip = _entityMgr.findByIdIncludingRemoved(IPAddressVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(ip.getUuid()); - - } else if(usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_SENT || usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_RECEIVED){ - //Device Type - usageRecResponse.setType(usageRecord.getType()); - if(usageRecord.getType().equals("DomainRouter")){ - //Domain Router Id - VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(vm.getUuid()); - } else { - //External Device Host Id - HostVO host = _entityMgr.findByIdIncludingRemoved(HostVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(host.getUuid()); - } - //Network ID - NetworkVO network = _entityMgr.findByIdIncludingRemoved(NetworkVO.class, usageRecord.getNetworkId().toString()); - usageRecResponse.setNetworkId(network.getUuid()); + } else if(usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_SENT || usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_RECEIVED){ + //Device Type + usageRecResponse.setType(usageRecord.getType()); + if(usageRecord.getType().equals("DomainRouter")){ + //Domain Router Id + VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(vm.getUuid()); + } else { + //External Device Host Id + HostVO host = _entityMgr.findByIdIncludingRemoved(HostVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(host.getUuid()); + } + //Network ID + NetworkVO network = _entityMgr.findByIdIncludingRemoved(NetworkVO.class, usageRecord.getNetworkId().toString()); + usageRecResponse.setNetworkId(network.getUuid()); } else if(usageRecord.getUsageType() == UsageTypes.VM_DISK_IO_READ || usageRecord.getUsageType() == UsageTypes.VM_DISK_IO_WRITE || usageRecord.getUsageType() == UsageTypes.VM_DISK_BYTES_READ || usageRecord.getUsageType() == UsageTypes.VM_DISK_BYTES_WRITE){ @@ -3424,97 +3348,97 @@ public class ApiResponseHelper implements ResponseGenerator { VolumeVO volume = _entityMgr.findByIdIncludingRemoved(VolumeVO.class, usageRecord.getUsageId().toString()); usageRecResponse.setUsageId(volume.getUuid()); - } else if(usageRecord.getUsageType() == UsageTypes.VOLUME){ - //Volume ID - VolumeVO volume = _entityMgr.findByIdIncludingRemoved(VolumeVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(volume.getUuid()); - //Volume Size - usageRecResponse.setSize(usageRecord.getSize()); - //Disk Offering Id - if(usageRecord.getOfferingId() != null){ - DiskOfferingVO diskOff = _entityMgr.findByIdIncludingRemoved(DiskOfferingVO.class, usageRecord.getOfferingId().toString()); - usageRecResponse.setOfferingId(diskOff.getUuid()); - } + } else if(usageRecord.getUsageType() == UsageTypes.VOLUME){ + //Volume ID + VolumeVO volume = _entityMgr.findByIdIncludingRemoved(VolumeVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(volume.getUuid()); + //Volume Size + usageRecResponse.setSize(usageRecord.getSize()); + //Disk Offering Id + if(usageRecord.getOfferingId() != null){ + DiskOfferingVO diskOff = _entityMgr.findByIdIncludingRemoved(DiskOfferingVO.class, usageRecord.getOfferingId().toString()); + usageRecResponse.setOfferingId(diskOff.getUuid()); + } - } else if(usageRecord.getUsageType() == UsageTypes.TEMPLATE || usageRecord.getUsageType() == UsageTypes.ISO){ - //Template/ISO ID - VMTemplateVO tmpl = _entityMgr.findByIdIncludingRemoved(VMTemplateVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(tmpl.getUuid()); - //Template/ISO Size - usageRecResponse.setSize(usageRecord.getSize()); + } else if(usageRecord.getUsageType() == UsageTypes.TEMPLATE || usageRecord.getUsageType() == UsageTypes.ISO){ + //Template/ISO ID + VMTemplateVO tmpl = _entityMgr.findByIdIncludingRemoved(VMTemplateVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(tmpl.getUuid()); + //Template/ISO Size + usageRecResponse.setSize(usageRecord.getSize()); - } else if(usageRecord.getUsageType() == UsageTypes.SNAPSHOT){ - //Snapshot ID - SnapshotVO snap = _entityMgr.findByIdIncludingRemoved(SnapshotVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(snap.getUuid()); - //Snapshot Size - usageRecResponse.setSize(usageRecord.getSize()); + } else if(usageRecord.getUsageType() == UsageTypes.SNAPSHOT){ + //Snapshot ID + SnapshotVO snap = _entityMgr.findByIdIncludingRemoved(SnapshotVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(snap.getUuid()); + //Snapshot Size + usageRecResponse.setSize(usageRecord.getSize()); - } else if(usageRecord.getUsageType() == UsageTypes.LOAD_BALANCER_POLICY){ - //Load Balancer Policy ID + } else if(usageRecord.getUsageType() == UsageTypes.LOAD_BALANCER_POLICY){ + //Load Balancer Policy ID LoadBalancerVO lb = _entityMgr.findByIdIncludingRemoved(LoadBalancerVO.class, usageRecord.getUsageId().toString()); usageRecResponse.setUsageId(lb.getUuid()); - } else if(usageRecord.getUsageType() == UsageTypes.PORT_FORWARDING_RULE){ - //Port Forwarding Rule ID + } else if(usageRecord.getUsageType() == UsageTypes.PORT_FORWARDING_RULE){ + //Port Forwarding Rule ID PortForwardingRuleVO pf = _entityMgr.findByIdIncludingRemoved(PortForwardingRuleVO.class, usageRecord.getUsageId().toString()); usageRecResponse.setUsageId(pf.getUuid()); - } else if(usageRecord.getUsageType() == UsageTypes.NETWORK_OFFERING){ - //Network Offering Id - NetworkOfferingVO netOff = _entityMgr.findByIdIncludingRemoved(NetworkOfferingVO.class, usageRecord.getOfferingId().toString()); - usageRecResponse.setOfferingId(netOff.getUuid()); - //is Default - usageRecResponse.setDefault((usageRecord.getUsageId() == 1)? true:false); + } else if(usageRecord.getUsageType() == UsageTypes.NETWORK_OFFERING){ + //Network Offering Id + NetworkOfferingVO netOff = _entityMgr.findByIdIncludingRemoved(NetworkOfferingVO.class, usageRecord.getOfferingId().toString()); + usageRecResponse.setOfferingId(netOff.getUuid()); + //is Default + usageRecResponse.setDefault((usageRecord.getUsageId() == 1)? true:false); - } else if(usageRecord.getUsageType() == UsageTypes.VPN_USERS){ - //VPN User ID + } else if(usageRecord.getUsageType() == UsageTypes.VPN_USERS){ + //VPN User ID VpnUserVO vpnUser = _entityMgr.findByIdIncludingRemoved(VpnUserVO.class, usageRecord.getUsageId().toString()); usageRecResponse.setUsageId(vpnUser.getUuid()); - } else if(usageRecord.getUsageType() == UsageTypes.SECURITY_GROUP){ - //Security Group Id - SecurityGroupVO sg = _entityMgr.findByIdIncludingRemoved(SecurityGroupVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(sg.getUuid()); - } + } else if(usageRecord.getUsageType() == UsageTypes.SECURITY_GROUP){ + //Security Group Id + SecurityGroupVO sg = _entityMgr.findByIdIncludingRemoved(SecurityGroupVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(sg.getUuid()); + } - if (usageRecord.getRawUsage() != null) { - DecimalFormat decimalFormat = new DecimalFormat("###########.######"); - usageRecResponse.setRawUsage(decimalFormat.format(usageRecord.getRawUsage())); - } + if (usageRecord.getRawUsage() != null) { + DecimalFormat decimalFormat = new DecimalFormat("###########.######"); + usageRecResponse.setRawUsage(decimalFormat.format(usageRecord.getRawUsage())); + } - if (usageRecord.getStartDate() != null) { - usageRecResponse.setStartDate(getDateStringInternal(usageRecord.getStartDate())); - } - if (usageRecord.getEndDate() != null) { - usageRecResponse.setEndDate(getDateStringInternal(usageRecord.getEndDate())); - } - - return usageRecResponse; - } + if (usageRecord.getStartDate() != null) { + usageRecResponse.setStartDate(getDateStringInternal(usageRecord.getStartDate())); + } + if (usageRecord.getEndDate() != null) { + usageRecResponse.setEndDate(getDateStringInternal(usageRecord.getEndDate())); + } + return usageRecResponse; + } public String getDateStringInternal(Date inputDate) { - if (inputDate == null) return null; + if (inputDate == null) + return null; TimeZone tz = _usageSvc.getUsageTimezone(); Calendar cal = Calendar.getInstance(tz); cal.setTime(inputDate); StringBuffer sb = new StringBuffer(); - sb.append(cal.get(Calendar.YEAR)+"-"); + sb.append(cal.get(Calendar.YEAR) + "-"); int month = cal.get(Calendar.MONTH) + 1; if (month < 10) { sb.append("0" + month + "-"); } else { - sb.append(month+"-"); + sb.append(month + "-"); } int day = cal.get(Calendar.DAY_OF_MONTH); if (day < 10) { sb.append("0" + day); } else { - sb.append(""+day); + sb.append("" + day); } sb.append("'T'"); @@ -3523,38 +3447,40 @@ public class ApiResponseHelper implements ResponseGenerator { if (hour < 10) { sb.append("0" + hour + ":"); } else { - sb.append(hour+":"); + sb.append(hour + ":"); } int minute = cal.get(Calendar.MINUTE); if (minute < 10) { sb.append("0" + minute + ":"); } else { - sb.append(minute+":"); + sb.append(minute + ":"); } int seconds = cal.get(Calendar.SECOND); if (seconds < 10) { sb.append("0" + seconds); } else { - sb.append(""+seconds); + sb.append("" + seconds); } double offset = cal.get(Calendar.ZONE_OFFSET); if (tz.inDaylightTime(inputDate)) { - offset += (1.0*tz.getDSTSavings()); // add the timezone's DST value (typically 1 hour expressed in milliseconds) + offset += (1.0 * tz.getDSTSavings()); // add the timezone's DST + // value (typically 1 hour + // expressed in milliseconds) } - offset = offset / (1000d*60d*60d); - int hourOffset = (int)offset; + offset = offset / (1000d * 60d * 60d); + int hourOffset = (int) offset; double decimalVal = Math.abs(offset) - Math.abs(hourOffset); - int minuteOffset = (int)(decimalVal * 60); + int minuteOffset = (int) (decimalVal * 60); if (hourOffset < 0) { if (hourOffset > -10) { - sb.append("-0"+Math.abs(hourOffset)); + sb.append("-0" + Math.abs(hourOffset)); } else { - sb.append("-"+Math.abs(hourOffset)); + sb.append("-" + Math.abs(hourOffset)); } } else { if (hourOffset < 10) { @@ -3588,6 +3514,7 @@ public class ApiResponseHelper implements ResponseGenerator { return response; } + @Override public NicSecondaryIpResponse createSecondaryIPToNicResponse(NicSecondaryIp result) { NicSecondaryIpResponse response = new NicSecondaryIpResponse(); NicVO nic = _entityMgr.findById(NicVO.class, result.getNicId()); @@ -3600,6 +3527,7 @@ public class ApiResponseHelper implements ResponseGenerator { return response; } + @Override public NicResponse createNicResponse(Nic result) { NicResponse response = new NicResponse(); NetworkVO network = _entityMgr.findById(NetworkVO.class, result.getNetworkId()); @@ -3612,7 +3540,7 @@ public class ApiResponseHelper implements ResponseGenerator { List secondaryIps = ApiDBUtils.findNicSecondaryIps(result.getId()); if (secondaryIps != null) { List ipList = new ArrayList(); - for (NicSecondaryIpVO ip: secondaryIps) { + for (NicSecondaryIpVO ip : secondaryIps) { NicSecondaryIpResponse ipRes = new NicSecondaryIpResponse(); ipRes.setId(ip.getUuid()); ipRes.setIpAddr(ip.getIp4Address()); @@ -3634,7 +3562,7 @@ public class ApiResponseHelper implements ResponseGenerator { return response; } - + @Override public ApplicationLoadBalancerResponse createLoadBalancerContainerReponse(ApplicationLoadBalancerRule lb, Map lbInstances) { @@ -3646,7 +3574,7 @@ public class ApiResponseHelper implements ResponseGenerator { Network nw = ApiDBUtils.findNetworkById(lb.getNetworkId()); lbResponse.setNetworkId(nw.getUuid()); populateOwner(lbResponse, lb); - + if (lb.getScheme() == Scheme.Internal) { lbResponse.setSourceIp(lb.getSourceIp().addr()); //TODO - create the view for the load balancer rule to reflect the network uuid @@ -3659,7 +3587,7 @@ public class ApiResponseHelper implements ResponseGenerator { Network ntwk = ApiDBUtils.findNetworkById(publicIp.getNetworkId()); lbResponse.setSourceIpNetworkId(ntwk.getUuid()); } - + //set load balancer rules information (only one rule per load balancer in this release) List ruleResponses = new ArrayList(); ApplicationLoadBalancerRuleResponse ruleResponse = new ApplicationLoadBalancerRuleResponse(); @@ -3673,7 +3601,7 @@ public class ApiResponseHelper implements ResponseGenerator { ruleResponse.setObjectName("loadbalancerrule"); ruleResponses.add(ruleResponse); lbResponse.setLbRules(ruleResponses); - + //set Lb instances information List instanceResponses = new ArrayList(); for (Ip ip : lbInstances.keySet()) { @@ -3685,7 +3613,7 @@ public class ApiResponseHelper implements ResponseGenerator { instanceResponse.setObjectName("loadbalancerinstance"); instanceResponses.add(instanceResponse); } - + lbResponse.setLbInstances(instanceResponses); //set tag information @@ -3821,6 +3749,7 @@ public class ApiResponseHelper implements ResponseGenerator { } + @Override public NetworkACLResponse createNetworkACLResponse(NetworkACL networkACL) { NetworkACLResponse response = new NetworkACLResponse(); response.setId(networkACL.getUuid()); diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index c851e3bcf8c..9bd8f2a063b 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -16,32 +16,32 @@ // under the License. package com.cloud.api.query; -import java.util.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; import javax.ejb.Local; import javax.inject.Inject; -import com.cloud.api.ApiDBUtils; -import com.cloud.server.ResourceMetaDataService; -import com.cloud.server.ResourceTag; -import com.cloud.server.TaggedResourceService; -import com.cloud.vm.NicDetailVO; -import com.cloud.vm.dao.NicDetailDao; +import com.cloud.storage.*; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.affinity.AffinityGroupVMMapVO; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; -import com.cloud.storage.VolumeDetailVO; -import com.cloud.storage.dao.VolumeDetailsDao; - import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; import org.apache.cloudstack.api.command.admin.host.ListHostsCmd; import org.apache.cloudstack.api.command.admin.internallb.ListInternalLBVMsCmd; import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd; +import org.apache.cloudstack.api.command.admin.storage.ListImageStoresCmd; import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd; import org.apache.cloudstack.api.command.admin.user.ListUsersCmd; import org.apache.cloudstack.api.command.user.account.ListAccountsCmd; import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd; import org.apache.cloudstack.api.command.user.event.ListEventsCmd; +import org.apache.cloudstack.api.command.user.iso.ListIsosCmd; import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd; import org.apache.cloudstack.api.command.user.offering.ListDiskOfferingsCmd; import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd; @@ -49,13 +49,14 @@ import org.apache.cloudstack.api.command.user.project.ListProjectInvitationsCmd; import org.apache.cloudstack.api.command.user.project.ListProjectsCmd; import org.apache.cloudstack.api.command.user.securitygroup.ListSecurityGroupsCmd; import org.apache.cloudstack.api.command.user.tag.ListTagsCmd; +import org.apache.cloudstack.api.command.user.template.ListTemplatesCmd; import org.apache.cloudstack.api.command.user.vm.ListVMsCmd; import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd; import org.apache.cloudstack.api.command.user.volume.ListResourceDetailsCmd; import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd; import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd; import org.apache.cloudstack.api.response.*; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateState; import org.apache.cloudstack.query.QueryService; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -67,6 +68,7 @@ import com.cloud.api.query.dao.DataCenterJoinDao; import com.cloud.api.query.dao.DiskOfferingJoinDao; import com.cloud.api.query.dao.DomainRouterJoinDao; import com.cloud.api.query.dao.HostJoinDao; +import com.cloud.api.query.dao.ImageStoreJoinDao; import com.cloud.api.query.dao.InstanceGroupJoinDao; import com.cloud.api.query.dao.ProjectAccountJoinDao; import com.cloud.api.query.dao.ProjectInvitationJoinDao; @@ -75,6 +77,7 @@ import com.cloud.api.query.dao.ResourceTagJoinDao; import com.cloud.api.query.dao.SecurityGroupJoinDao; import com.cloud.api.query.dao.ServiceOfferingJoinDao; import com.cloud.api.query.dao.StoragePoolJoinDao; +import com.cloud.api.query.dao.TemplateJoinDao; import com.cloud.api.query.dao.UserAccountJoinDao; import com.cloud.api.query.dao.UserVmJoinDao; import com.cloud.api.query.dao.VolumeJoinDao; @@ -86,6 +89,7 @@ import com.cloud.api.query.vo.DiskOfferingJoinVO; import com.cloud.api.query.vo.DomainRouterJoinVO; import com.cloud.api.query.vo.EventJoinVO; import com.cloud.api.query.vo.HostJoinVO; +import com.cloud.api.query.vo.ImageStoreJoinVO; import com.cloud.api.query.vo.InstanceGroupJoinVO; import com.cloud.api.query.vo.ProjectAccountJoinVO; import com.cloud.api.query.vo.ProjectInvitationJoinVO; @@ -94,6 +98,7 @@ import com.cloud.api.query.vo.ResourceTagJoinVO; import com.cloud.api.query.vo.SecurityGroupJoinVO; import com.cloud.api.query.vo.ServiceOfferingJoinVO; import com.cloud.api.query.vo.StoragePoolJoinVO; +import com.cloud.api.query.vo.TemplateJoinVO; import com.cloud.api.query.vo.UserAccountJoinVO; import com.cloud.api.query.vo.UserVmJoinVO; import com.cloud.api.query.vo.VolumeJoinVO; @@ -118,10 +123,18 @@ import com.cloud.projects.ProjectInvitation; import com.cloud.projects.ProjectManager; import com.cloud.projects.dao.ProjectAccountDao; import com.cloud.projects.dao.ProjectDao; +import com.cloud.resource.ResourceManager; import com.cloud.server.Criteria; +import com.cloud.server.ResourceMetaDataService; +import com.cloud.server.ResourceTag; +import com.cloud.server.ResourceTag.TaggedResourceType; +import com.cloud.server.TaggedResourceService; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; -import com.cloud.storage.Volume; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VolumeDetailsDao; +import com.cloud.template.VirtualMachineTemplate.TemplateFilter; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.AccountVO; @@ -137,13 +150,15 @@ import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria.Func; import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.vm.DomainRouterVO; +import com.cloud.vm.NicDetailVO; import com.cloud.vm.UserVmVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.dao.DomainRouterDao; +import com.cloud.vm.dao.NicDetailDao; import com.cloud.vm.dao.UserVmDao; @Component -@Local(value = {QueryService.class }) +@Local(value = { QueryService.class }) public class QueryManagerImpl extends ManagerBase implements QueryService { public static final Logger s_logger = Logger.getLogger(QueryManagerImpl.class); @@ -222,6 +237,9 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { @Inject private StoragePoolJoinDao _poolJoinDao; + @Inject + private ImageStoreJoinDao _imageStoreJoinDao; + @Inject private DiskOfferingJoinDao _diskOfferingJoinDao; @@ -246,6 +264,14 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { @Inject private HighAvailabilityManager _haMgr; + @Inject + private VMTemplateDao _templateDao; + + @Inject + private TemplateJoinDao _templateJoinDao; + + @Inject + ResourceManager _resourceMgr; @Inject private ResourceMetaDataService _resourceMetaDataMgr; @@ -260,22 +286,29 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { @Inject private DedicatedResourceDao _dedicatedDao; - /* (non-Javadoc) - * @see com.cloud.api.query.QueryService#searchForUsers(org.apache.cloudstack.api.command.admin.user.ListUsersCmd) + + /* + * (non-Javadoc) + * + * @see + * com.cloud.api.query.QueryService#searchForUsers(org.apache.cloudstack + * .api.command.admin.user.ListUsersCmd) */ @Override public ListResponse searchForUsers(ListUsersCmd cmd) throws PermissionDeniedException { Pair, Integer> result = searchForUsersInternal(cmd); ListResponse response = new ListResponse(); - List userResponses = ViewResponseHelper.createUserResponse(result.first().toArray(new UserAccountJoinVO[result.first().size()])); + List userResponses = ViewResponseHelper.createUserResponse(result.first().toArray( + new UserAccountJoinVO[result.first().size()])); response.setResponses(userResponses, result.second()); return response; } - private Pair, Integer> searchForUsersInternal(ListUsersCmd cmd) throws PermissionDeniedException { + private Pair, Integer> searchForUsersInternal(ListUsersCmd cmd) + throws PermissionDeniedException { Account caller = UserContext.current().getCaller(); - //TODO: Integrate with ACL checkAccess refactoring + // TODO: Integrate with ACL checkAccess refactoring Long domainId = cmd.getDomainId(); if (domainId != null) { Domain domain = _domainDao.findById(domainId); @@ -307,7 +340,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } else if (id != null) { sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); } else { - // this condition is used to exclude system user from the search results + // this condition is used to exclude system user from the search + // results sb.and("id", sb.entity().getId(), SearchCriteria.Op.NEQ); } @@ -371,7 +405,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { public ListResponse searchForEvents(ListEventsCmd cmd) { Pair, Integer> result = searchForEventsInternal(cmd); ListResponse response = new ListResponse(); - List eventResponses = ViewResponseHelper.createEventResponse(result.first().toArray(new EventJoinVO[result.first().size()])); + List eventResponses = ViewResponseHelper.createEventResponse(result.first().toArray( + new EventJoinVO[result.first().size()])); response.setResponses(eventResponses, result.second()); return response; } @@ -391,15 +426,17 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { Ternary domainIdRecursiveListProject = new Ternary( cmd.getDomainId(), cmd.isRecursive(), null); - _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, - cmd.listAll(), false); + _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, + domainIdRecursiveListProject, cmd.listAll(), false); Long domainId = domainIdRecursiveListProject.first(); Boolean isRecursive = domainIdRecursiveListProject.second(); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); - Filter searchFilter = new Filter(EventJoinVO.class, "createDate", false, cmd.getStartIndex(), cmd.getPageSizeVal()); + Filter searchFilter = new Filter(EventJoinVO.class, "createDate", false, cmd.getStartIndex(), + cmd.getPageSizeVal()); SearchBuilder sb = _eventJoinDao.createSearchBuilder(); - _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); sb.and("levelL", sb.entity().getLevel(), SearchCriteria.Op.LIKE); @@ -415,7 +452,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { SearchCriteria sc = sb.create(); // building ACL condition - _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); if (id != null) { sc.setParameters("id", id); @@ -448,7 +486,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sc.setParameters("archived", false); Pair, Integer> eventPair = null; - // event_view will not have duplicate rows for each event, so searchAndCount should be good enough. + // event_view will not have duplicate rows for each event, so + // searchAndCount should be good enough. if ((entryTime != null) && (duration != null)) { // TODO: waiting for response from dev list, logic is mystery to // me!! @@ -460,7 +499,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { * calMin.add(Calendar.SECOND, -entryTime); * calMax.add(Calendar.SECOND, -duration); Date minTime = * calMin.getTime(); Date maxTime = calMax.getTime(); - * + * * sc.setParameters("state", com.cloud.event.Event.State.Completed); * sc.setParameters("startId", 0); sc.setParameters("createDate", * minTime, maxTime); List startedEvents = @@ -481,7 +520,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { public ListResponse listTags(ListTagsCmd cmd) { Pair, Integer> tags = listTagsInternal(cmd); ListResponse response = new ListResponse(); - List tagResponses = ViewResponseHelper.createResourceTagResponse(false, tags.first().toArray(new ResourceTagJoinVO[tags.first().size()])); + List tagResponses = ViewResponseHelper.createResourceTagResponse(false, tags.first() + .toArray(new ResourceTagJoinVO[tags.first().size()])); response.setResponses(tagResponses, tags.second()); return response; } @@ -496,18 +536,20 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { String customerName = cmd.getCustomer(); boolean listAll = cmd.listAll(); - Ternary domainIdRecursiveListProject = - new Ternary(cmd.getDomainId(), cmd.isRecursive(), null); + Ternary domainIdRecursiveListProject = new Ternary( + cmd.getDomainId(), cmd.isRecursive(), null); - _accountMgr.buildACLSearchParameters(caller, null, cmd.getAccountName(), - cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, listAll, false); + _accountMgr.buildACLSearchParameters(caller, null, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, + domainIdRecursiveListProject, listAll, false); Long domainId = domainIdRecursiveListProject.first(); Boolean isRecursive = domainIdRecursiveListProject.second(); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); - Filter searchFilter = new Filter(ResourceTagJoinVO.class, "resourceType", false, cmd.getStartIndex(), cmd.getPageSizeVal()); + Filter searchFilter = new Filter(ResourceTagJoinVO.class, "resourceType", false, cmd.getStartIndex(), + cmd.getPageSizeVal()); SearchBuilder sb = _resourceTagJoinDao.createSearchBuilder(); - _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); sb.and("key", sb.entity().getKey(), SearchCriteria.Op.EQ); sb.and("value", sb.entity().getValue(), SearchCriteria.Op.EQ); @@ -523,7 +565,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { // now set the SC criteria... SearchCriteria sc = sb.create(); - _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); if (key != null) { sc.setParameters("key", key); @@ -550,13 +593,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { return result; } - - @Override public ListResponse searchForVmGroups(ListVMGroupsCmd cmd) { Pair, Integer> groups = searchForVmGroupsInternal(cmd); ListResponse response = new ListResponse(); - List grpResponses = ViewResponseHelper.createInstanceGroupResponse(groups.first().toArray(new InstanceGroupJoinVO[groups.first().size()])); + List grpResponses = ViewResponseHelper.createInstanceGroupResponse(groups.first() + .toArray(new InstanceGroupJoinVO[groups.first().size()])); response.setResponses(grpResponses, groups.second()); return response; } @@ -571,24 +613,25 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { Ternary domainIdRecursiveListProject = new Ternary( cmd.getDomainId(), cmd.isRecursive(), null); - _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, - cmd.listAll(), false); + _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, + domainIdRecursiveListProject, cmd.listAll(), false); Long domainId = domainIdRecursiveListProject.first(); Boolean isRecursive = domainIdRecursiveListProject.second(); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); - Filter searchFilter = new Filter(InstanceGroupJoinVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); + Filter searchFilter = new Filter(InstanceGroupJoinVO.class, "id", true, cmd.getStartIndex(), + cmd.getPageSizeVal()); SearchBuilder sb = _vmGroupJoinDao.createSearchBuilder(); - _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); - + _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); - SearchCriteria sc = sb.create(); - _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); if (keyword != null) { SearchCriteria ssc = _vmGroupJoinDao.createSearchCriteria(); @@ -596,7 +639,6 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sc.addAnd("name", SearchCriteria.Op.SC, ssc); } - if (id != null) { sc.setParameters("id", id); } @@ -612,7 +654,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { public ListResponse searchForUserVMs(ListVMsCmd cmd) { Pair, Integer> result = searchForUserVMsInternal(cmd); ListResponse response = new ListResponse(); - List vmResponses = ViewResponseHelper.createUserVmResponse("virtualmachine", cmd.getDetails(), result.first().toArray(new UserVmJoinVO[result.first().size()])); + List vmResponses = ViewResponseHelper.createUserVmResponse("virtualmachine", cmd.getDetails(), + result.first().toArray(new UserVmJoinVO[result.first().size()])); response.setResponses(vmResponses, result.second()); return response; } @@ -625,19 +668,22 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { Long id = cmd.getId(); Map tags = cmd.getTags(); - Ternary domainIdRecursiveListProject = new Ternary(cmd.getDomainId(), cmd.isRecursive(), null); - _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, listAll, false); + Ternary domainIdRecursiveListProject = new Ternary( + cmd.getDomainId(), cmd.isRecursive(), null); + _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, + domainIdRecursiveListProject, listAll, false); Long domainId = domainIdRecursiveListProject.first(); Boolean isRecursive = domainIdRecursiveListProject.second(); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal()); - //Criteria c = new Criteria(null, Boolean.FALSE, cmd.getStartIndex(), cmd.getPageSizeVal()); //version without default sorting + // Criteria c = new Criteria(null, Boolean.FALSE, cmd.getStartIndex(), + // cmd.getPageSizeVal()); //version without default sorting c.addCriteria(Criteria.KEYWORD, cmd.getKeyword()); c.addCriteria(Criteria.ID, cmd.getId()); c.addCriteria(Criteria.NAME, cmd.getInstanceName()); c.addCriteria(Criteria.STATE, cmd.getState()); - c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId()); + c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId()); c.addCriteria(Criteria.GROUPID, cmd.getGroupId()); c.addCriteria(Criteria.FOR_VIRTUAL_NETWORK, cmd.getForVirtualNetwork()); c.addCriteria(Criteria.NETWORKID, cmd.getNetworkId()); @@ -668,25 +714,28 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } c.addCriteria(Criteria.ISADMIN, _accountMgr.isAdmin(caller.getType())); - return searchForUserVMsByCriteria(c, caller, domainId, isRecursive, - permittedAccounts, listAll, listProjectResourcesCriteria, tags); + return searchForUserVMsByCriteria(c, caller, domainId, isRecursive, permittedAccounts, listAll, + listProjectResourcesCriteria, tags); } + private Pair, Integer> searchForUserVMsByCriteria(Criteria c, Account caller, Long domainId, + boolean isRecursive, List permittedAccounts, boolean listAll, + ListProjectResourcesCriteria listProjectResourcesCriteria, Map tags) { + Filter searchFilter = new Filter(UserVmJoinVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), + c.getLimit()); - private Pair, Integer> searchForUserVMsByCriteria(Criteria c, Account caller, Long domainId, boolean isRecursive, - List permittedAccounts, boolean listAll, ListProjectResourcesCriteria listProjectResourcesCriteria, Map tags) { - Filter searchFilter = new Filter(UserVmJoinVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit()); - - //first search distinct vm id by using query criteria and pagination + // first search distinct vm id by using query criteria and pagination SearchBuilder sb = _userVmJoinDao.createSearchBuilder(); - sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct ids - _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct + // ids + _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); Object id = c.getCriteria(Criteria.ID); Object name = c.getCriteria(Criteria.NAME); Object state = c.getCriteria(Criteria.STATE); Object notState = c.getCriteria(Criteria.NOTSTATE); - Object zoneId = c.getCriteria(Criteria.DATACENTERID); + Object zoneId = c.getCriteria(Criteria.DATACENTERID); Object pod = c.getCriteria(Criteria.PODID); Object hostId = c.getCriteria(Criteria.HOSTID); Object hostName = c.getCriteria(Criteria.HOSTNAME); @@ -708,7 +757,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sb.and("stateEQ", sb.entity().getState(), SearchCriteria.Op.EQ); sb.and("stateNEQ", sb.entity().getState(), SearchCriteria.Op.NEQ); sb.and("stateNIN", sb.entity().getState(), SearchCriteria.Op.NIN); - sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); + sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ); sb.and("hypervisorType", sb.entity().getHypervisorType(), SearchCriteria.Op.EQ); sb.and("hostIdEQ", sb.entity().getHostId(), SearchCriteria.Op.EQ); @@ -722,7 +771,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } if (tags != null && !tags.isEmpty()) { - for (int count=0; count < tags.size(); count++) { + for (int count = 0; count < tags.size(); count++) { sb.or().op("key" + String.valueOf(count), sb.entity().getTagKey(), SearchCriteria.Op.EQ); sb.and("value" + String.valueOf(count), sb.entity().getTagValue(), SearchCriteria.Op.EQ); sb.cp(); @@ -733,7 +782,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sb.and("networkId", sb.entity().getNetworkId(), SearchCriteria.Op.EQ); } - if(vpcId != null && networkId == null){ + if (vpcId != null && networkId == null) { sb.and("vpcId", sb.entity().getVpcId(), SearchCriteria.Op.EQ); } @@ -749,7 +798,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { SearchCriteria sc = sb.create(); // building ACL condition - _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); if (tags != null && !tags.isEmpty()) { int count = 0; @@ -760,7 +810,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } } - if (groupId != null && (Long)groupId != -1) { + if (groupId != null && (Long) groupId != -1) { sc.setParameters("instanceGroupId", groupId); } @@ -790,7 +840,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sc.setParameters("networkId", networkId); } - if(vpcId != null && networkId == null){ + if (vpcId != null && networkId == null) { sc.setParameters("vpcId", vpcId); } @@ -822,7 +872,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sc.setParameters("stateNEQ", "Destroyed"); } } - + if (pod != null) { sc.setParameters("podId", pod); @@ -848,23 +898,22 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } // search vm details by ids - Pair, Integer> uniqueVmPair = _userVmJoinDao.searchAndCount(sc, searchFilter); + Pair, Integer> uniqueVmPair = _userVmJoinDao.searchAndCount(sc, searchFilter); Integer count = uniqueVmPair.second(); - if ( count.intValue() == 0 ){ + if (count.intValue() == 0) { // handle empty result cases return uniqueVmPair; } List uniqueVms = uniqueVmPair.first(); Long[] vmIds = new Long[uniqueVms.size()]; int i = 0; - for (UserVmJoinVO v : uniqueVms ){ + for (UserVmJoinVO v : uniqueVms) { vmIds[i++] = v.getId(); } List vms = _userVmJoinDao.searchByIds(vmIds); return new Pair, Integer>(vms, count); } - @Override public ListResponse searchForSecurityGroups(ListSecurityGroupsCmd cmd) { Pair, Integer> result = searchForSecurityGroupsInternal(cmd); @@ -874,7 +923,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { return response; } - private Pair, Integer> searchForSecurityGroupsInternal(ListSecurityGroupsCmd cmd) throws PermissionDeniedException, InvalidParameterValueException { + private Pair, Integer> searchForSecurityGroupsInternal(ListSecurityGroupsCmd cmd) + throws PermissionDeniedException, InvalidParameterValueException { Account caller = UserContext.current().getCaller(); Long instanceId = cmd.getVirtualMachineId(); String securityGroup = cmd.getSecurityGroupName(); @@ -886,28 +936,34 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { if (instanceId != null) { UserVmVO userVM = _userVmDao.findById(instanceId); if (userVM == null) { - throw new InvalidParameterValueException("Unable to list network groups for virtual machine instance " + instanceId + "; instance not found."); + throw new InvalidParameterValueException("Unable to list network groups for virtual machine instance " + + instanceId + "; instance not found."); } _accountMgr.checkAccess(caller, null, true, userVM); return listSecurityGroupRulesByVM(instanceId.longValue(), cmd.getStartIndex(), cmd.getPageSizeVal()); } - Ternary domainIdRecursiveListProject = new Ternary(cmd.getDomainId(), cmd.isRecursive(), null); - _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false); + Ternary domainIdRecursiveListProject = new Ternary( + cmd.getDomainId(), cmd.isRecursive(), null); + _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, + domainIdRecursiveListProject, cmd.listAll(), false); Long domainId = domainIdRecursiveListProject.first(); Boolean isRecursive = domainIdRecursiveListProject.second(); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); - Filter searchFilter = new Filter(SecurityGroupJoinVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); + Filter searchFilter = new Filter(SecurityGroupJoinVO.class, "id", true, cmd.getStartIndex(), + cmd.getPageSizeVal()); SearchBuilder sb = _securityGroupJoinDao.createSearchBuilder(); - sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct ids - _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct + // ids + _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); if (tags != null && !tags.isEmpty()) { - for (int count=0; count < tags.size(); count++) { + for (int count = 0; count < tags.size(); count++) { sb.or().op("key" + String.valueOf(count), sb.entity().getTagKey(), SearchCriteria.Op.EQ); sb.and("value" + String.valueOf(count), sb.entity().getTagValue(), SearchCriteria.Op.EQ); sb.cp(); @@ -915,7 +971,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } SearchCriteria sc = sb.create(); - _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); if (id != null) { sc.setParameters("id", id); @@ -942,9 +999,9 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } // search security group together with rules - Pair, Integer> uniqueSgPair = _securityGroupJoinDao.searchAndCount(sc, searchFilter); + Pair, Integer> uniqueSgPair = _securityGroupJoinDao.searchAndCount(sc, searchFilter); Integer count = uniqueSgPair.second(); - if ( count.intValue() == 0 ){ + if (count.intValue() == 0) { // handle empty result cases return uniqueSgPair; } @@ -952,7 +1009,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { List uniqueSgs = uniqueSgPair.first(); Long[] sgIds = new Long[uniqueSgs.size()]; int i = 0; - for (SecurityGroupJoinVO v : uniqueSgs ){ + for (SecurityGroupJoinVO v : uniqueSgs) { sgIds[i++] = v.getId(); } List sgs = _securityGroupJoinDao.searchByIds(sgIds); @@ -977,7 +1034,6 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { return new Pair, Integer>(sgs, count); } - @Override public ListResponse searchForRouters(ListRoutersCmd cmd) { Pair, Integer> result = searchForRoutersInternal(cmd, cmd.getId(), cmd.getRouterName(), @@ -985,12 +1041,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { cmd.getVpcId(), cmd.getForVpc(), cmd.getRole()); ListResponse response = new ListResponse(); - List routerResponses = ViewResponseHelper.createDomainRouterResponse(result.first().toArray(new DomainRouterJoinVO[result.first().size()])); + List routerResponses = ViewResponseHelper.createDomainRouterResponse(result.first() + .toArray(new DomainRouterJoinVO[result.first().size()])); response.setResponses(routerResponses, result.second()); return response; } - @Override public ListResponse searchForInternalLbVms(ListInternalLBVMsCmd cmd) { Pair, Integer> result = searchForRoutersInternal(cmd, cmd.getId(), cmd.getRouterName(), @@ -998,35 +1054,37 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { cmd.getVpcId(), cmd.getForVpc(), cmd.getRole()); ListResponse response = new ListResponse(); - List routerResponses = ViewResponseHelper.createDomainRouterResponse(result.first().toArray(new DomainRouterJoinVO[result.first().size()])); + List routerResponses = ViewResponseHelper.createDomainRouterResponse(result.first() + .toArray(new DomainRouterJoinVO[result.first().size()])); response.setResponses(routerResponses, result.second()); return response; } - private Pair, Integer> searchForRoutersInternal(BaseListProjectAndAccountResourcesCmd cmd, Long id, String name, String state, Long zoneId, Long podId, Long hostId, String keyword, Long networkId, Long vpcId, Boolean forVpc, String role) { - Account caller = UserContext.current().getCaller(); List permittedAccounts = new ArrayList(); Ternary domainIdRecursiveListProject = new Ternary( cmd.getDomainId(), cmd.isRecursive(), null); - _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, - cmd.listAll(), false); + _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, + domainIdRecursiveListProject, cmd.listAll(), false); Long domainId = domainIdRecursiveListProject.first(); Boolean isRecursive = domainIdRecursiveListProject.second(); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); - Filter searchFilter = new Filter(DomainRouterJoinVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); - //Filter searchFilter = new Filter(DomainRouterJoinVO.class, null, true, cmd.getStartIndex(), cmd.getPageSizeVal()); + Filter searchFilter = new Filter(DomainRouterJoinVO.class, "id", true, cmd.getStartIndex(), + cmd.getPageSizeVal()); + // Filter searchFilter = new Filter(DomainRouterJoinVO.class, null, + // true, cmd.getStartIndex(), cmd.getPageSizeVal()); SearchBuilder sb = _routerJoinDao.createSearchBuilder(); sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct // ids to get // number of // records with // pagination - _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); sb.and("name", sb.entity().getHostName(), SearchCriteria.Op.LIKE); sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); @@ -1051,7 +1109,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } SearchCriteria sc = sb.create(); - _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); if (keyword != null) { SearchCriteria ssc = _routerJoinDao.createSearchCriteria(); @@ -1093,7 +1152,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { if (vpcId != null) { sc.setParameters("vpcId", vpcId); } - + if (role != null) { sc.setParameters("role", role); } @@ -1115,13 +1174,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { return new Pair, Integer>(vrs, count); } - - @Override public ListResponse listProjects(ListProjectsCmd cmd) { Pair, Integer> projects = listProjectsInternal(cmd); ListResponse response = new ListResponse(); - List projectResponses = ViewResponseHelper.createProjectResponse(projects.first().toArray(new ProjectJoinVO[projects.first().size()])); + List projectResponses = ViewResponseHelper.createProjectResponse(projects.first().toArray( + new ProjectJoinVO[projects.first().size()])); response.setResponses(projectResponses, projects.second()); return response; } @@ -1162,13 +1220,15 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { if (accountName != null) { Account owner = _accountMgr.getActiveAccountByName(accountName, domainId); if (owner == null) { - throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId); + throw new InvalidParameterValueException("Unable to find account " + accountName + + " in domain " + domainId); } accountId = owner.getId(); } } else { // domainId == null if (accountName != null) { - throw new InvalidParameterValueException("could not find account " + accountName + " because domain is not specified"); + throw new InvalidParameterValueException("could not find account " + accountName + + " because domain is not specified"); } } @@ -1270,19 +1330,19 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { return new Pair, Integer>(prjs, count); } - @Override public ListResponse listProjectInvitations(ListProjectInvitationsCmd cmd) { Pair, Integer> invites = listProjectInvitationsInternal(cmd); ListResponse response = new ListResponse(); - List projectInvitationResponses = - ViewResponseHelper.createProjectInvitationResponse(invites.first().toArray(new ProjectInvitationJoinVO[invites.first().size()])); + List projectInvitationResponses = ViewResponseHelper + .createProjectInvitationResponse(invites.first().toArray( + new ProjectInvitationJoinVO[invites.first().size()])); response.setResponses(projectInvitationResponses, invites.second()); return response; } - public Pair, Integer> listProjectInvitationsInternal(ListProjectInvitationsCmd cmd){ + public Pair, Integer> listProjectInvitationsInternal(ListProjectInvitationsCmd cmd) { Long id = cmd.getId(); Long projectId = cmd.getProjectId(); String accountName = cmd.getAccountName(); @@ -1297,15 +1357,18 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { Account caller = UserContext.current().getCaller(); List permittedAccounts = new ArrayList(); - Ternary domainIdRecursiveListProject = new Ternary(domainId, isRecursive, null); - _accountMgr.buildACLSearchParameters(caller, id, accountName, projectId, permittedAccounts, domainIdRecursiveListProject, listAll, true); + Ternary domainIdRecursiveListProject = new Ternary( + domainId, isRecursive, null); + _accountMgr.buildACLSearchParameters(caller, id, accountName, projectId, permittedAccounts, + domainIdRecursiveListProject, listAll, true); domainId = domainIdRecursiveListProject.first(); isRecursive = domainIdRecursiveListProject.second(); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); Filter searchFilter = new Filter(ProjectInvitationJoinVO.class, "id", true, startIndex, pageSizeVal); SearchBuilder sb = _projectInvitationJoinDao.createSearchBuilder(); - _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); sb.and("projectId", sb.entity().getProjectId(), SearchCriteria.Op.EQ); sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ); @@ -1313,10 +1376,10 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); SearchCriteria sc = sb.create(); - _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); - - if (projectId != null){ + if (projectId != null) { sc.setParameters("projectId", projectId); } @@ -1330,24 +1393,24 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { if (activeOnly) { sc.setParameters("state", ProjectInvitation.State.Pending); - sc.setParameters("created", new Date((DateUtil.currentGMTTime().getTime()) - _projectMgr.getInvitationTimeout())); + sc.setParameters("created", + new Date((DateUtil.currentGMTTime().getTime()) - _projectMgr.getInvitationTimeout())); } return _projectInvitationJoinDao.searchAndCount(sc, searchFilter); } - @Override public ListResponse listProjectAccounts(ListProjectAccountsCmd cmd) { Pair, Integer> projectAccounts = listProjectAccountsInternal(cmd); ListResponse response = new ListResponse(); - List projectResponses = ViewResponseHelper.createProjectAccountResponse(projectAccounts.first().toArray(new ProjectAccountJoinVO[projectAccounts.first().size()])); + List projectResponses = ViewResponseHelper.createProjectAccountResponse(projectAccounts + .first().toArray(new ProjectAccountJoinVO[projectAccounts.first().size()])); response.setResponses(projectResponses, projectAccounts.second()); return response; } - public Pair, Integer> listProjectAccountsInternal(ListProjectAccountsCmd cmd) { long projectId = cmd.getProjectId(); String accountName = cmd.getAccountName(); @@ -1355,19 +1418,23 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { Long startIndex = cmd.getStartIndex(); Long pageSizeVal = cmd.getPageSizeVal(); - //long projectId, String accountName, String role, Long startIndex, Long pageSizeVal) { + // long projectId, String accountName, String role, Long startIndex, + // Long pageSizeVal) { Account caller = UserContext.current().getCaller(); - //check that the project exists + // check that the project exists Project project = _projectDao.findById(projectId); if (project == null) { throw new InvalidParameterValueException("Unable to find the project id=" + projectId); } - //verify permissions - only accounts belonging to the project can list project's account - if (!_accountMgr.isAdmin(caller.getType()) && _projectAccountDao.findByProjectIdAccountId(projectId, caller.getAccountId()) == null) { - throw new PermissionDeniedException("Account " + caller + " is not authorized to list users of the project id=" + projectId); + // verify permissions - only accounts belonging to the project can list + // project's account + if (!_accountMgr.isAdmin(caller.getType()) + && _projectAccountDao.findByProjectIdAccountId(projectId, caller.getAccountId()) == null) { + throw new PermissionDeniedException("Account " + caller + + " is not authorized to list users of the project id=" + projectId); } Filter searchFilter = new Filter(ProjectAccountJoinVO.class, "id", false, startIndex, pageSizeVal); @@ -1392,25 +1459,27 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sc.setParameters("accountName", accountName); } - return _projectAccountJoinDao.searchAndCount(sc, searchFilter); + return _projectAccountJoinDao.searchAndCount(sc, searchFilter); } @Override public ListResponse searchForServers(ListHostsCmd cmd) { - //FIXME: do we need to support list hosts with VmId, maybe we should create another command just for this + // FIXME: do we need to support list hosts with VmId, maybe we should + // create another command just for this // Right now it is handled separately outside this QueryService s_logger.debug(">>>Searching for hosts>>>"); Pair, Integer> hosts = searchForServersInternal(cmd); ListResponse response = new ListResponse(); s_logger.debug(">>>Generating Response>>>"); - List hostResponses = ViewResponseHelper.createHostResponse(cmd.getDetails(), hosts.first().toArray(new HostJoinVO[hosts.first().size()])); + List hostResponses = ViewResponseHelper.createHostResponse(cmd.getDetails(), hosts.first() + .toArray(new HostJoinVO[hosts.first().size()])); response.setResponses(hostResponses, hosts.second()); return response; } public Pair, Integer> searchForServersInternal(ListHostsCmd cmd) { - Long zoneId = _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), cmd.getZoneId()); + Long zoneId = _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), cmd.getZoneId()); Object name = cmd.getHostName(); Object type = cmd.getType(); Object state = cmd.getState(); @@ -1426,12 +1495,13 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { Filter searchFilter = new Filter(HostJoinVO.class, "id", Boolean.TRUE, startIndex, pageSize); SearchBuilder sb = _hostJoinDao.createSearchBuilder(); - sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct ids + sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct + // ids sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); sb.and("type", sb.entity().getType(), SearchCriteria.Op.LIKE); sb.and("status", sb.entity().getStatus(), SearchCriteria.Op.EQ); - sb.and("dataCenterId", sb.entity().getZoneId(), SearchCriteria.Op.EQ); + sb.and("dataCenterId", sb.entity().getZoneId(), SearchCriteria.Op.EQ); sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ); sb.and("clusterId", sb.entity().getClusterId(), SearchCriteria.Op.EQ); sb.and("resourceState", sb.entity().getResourceState(), SearchCriteria.Op.EQ); @@ -1448,7 +1518,6 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } - SearchCriteria sc = sb.create(); if (keyword != null) { @@ -1475,7 +1544,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } if (zoneId != null) { sc.setParameters("dataCenterId", zoneId); - } + } if (pod != null) { sc.setParameters("podId", pod); } @@ -1492,16 +1561,16 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } // search host details by ids - Pair, Integer> uniqueHostPair = _hostJoinDao.searchAndCount(sc, searchFilter); + Pair, Integer> uniqueHostPair = _hostJoinDao.searchAndCount(sc, searchFilter); Integer count = uniqueHostPair.second(); - if ( count.intValue() == 0 ){ + if (count.intValue() == 0) { // handle empty result cases return uniqueHostPair; } List uniqueHosts = uniqueHostPair.first(); Long[] hostIds = new Long[uniqueHosts.size()]; int i = 0; - for (HostJoinVO v : uniqueHosts ){ + for (HostJoinVO v : uniqueHosts) { hostIds[i++] = v.getId(); } List hosts = _hostJoinDao.searchByIds(hostIds); @@ -1514,12 +1583,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { Pair, Integer> result = searchForVolumesInternal(cmd); ListResponse response = new ListResponse(); - List volumeResponses = ViewResponseHelper.createVolumeResponse(result.first().toArray(new VolumeJoinVO[result.first().size()])); + List volumeResponses = ViewResponseHelper.createVolumeResponse(result.first().toArray( + new VolumeJoinVO[result.first().size()])); response.setResponses(volumeResponses, result.second()); return response; } - private Pair, Integer> searchForVolumesInternal(ListVolumesCmd cmd) { Account caller = UserContext.current().getCaller(); @@ -1532,20 +1601,24 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { String type = cmd.getType(); Map tags = cmd.getTags(); - Long zoneId = cmd.getZoneId(); + Long zoneId = cmd.getZoneId(); Long podId = null; if (_accountMgr.isAdmin(caller.getType())) { podId = cmd.getPodId(); } - Ternary domainIdRecursiveListProject = new Ternary(cmd.getDomainId(), cmd.isRecursive(), null); - _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false); + Ternary domainIdRecursiveListProject = new Ternary( + cmd.getDomainId(), cmd.isRecursive(), null); + _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, + domainIdRecursiveListProject, cmd.listAll(), false); Long domainId = domainIdRecursiveListProject.first(); Boolean isRecursive = domainIdRecursiveListProject.second(); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); - Filter searchFilter = new Filter(VolumeJoinVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal()); + Filter searchFilter = new Filter(VolumeJoinVO.class, "created", false, cmd.getStartIndex(), + cmd.getPageSizeVal()); - // hack for now, this should be done better but due to needing a join I opted to + // hack for now, this should be done better but due to needing a join I + // opted to // do this quickly and worry about making it pretty later SearchBuilder sb = _volumeJoinDao.createSearchBuilder(); sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct @@ -1553,13 +1626,14 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { // number of // records with // pagination - _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); sb.and("volumeType", sb.entity().getVolumeType(), SearchCriteria.Op.LIKE); sb.and("instanceId", sb.entity().getVmId(), SearchCriteria.Op.EQ); - sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); + sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ); // Only return volumes that are not destroyed sb.and("state", sb.entity().getState(), SearchCriteria.Op.NEQ); @@ -1570,18 +1644,17 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sb.cp(); if (tags != null && !tags.isEmpty()) { - for (int count=0; count < tags.size(); count++) { + for (int count = 0; count < tags.size(); count++) { sb.or().op("key" + String.valueOf(count), sb.entity().getTagKey(), SearchCriteria.Op.EQ); sb.and("value" + String.valueOf(count), sb.entity().getTagValue(), SearchCriteria.Op.EQ); sb.cp(); } } - - // now set the SC criteria... SearchCriteria sc = sb.create(); - _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); if (keyword != null) { SearchCriteria ssc = _volumeJoinDao.createSearchCriteria(); @@ -1618,13 +1691,14 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } if (zoneId != null) { sc.setParameters("dataCenterId", zoneId); - } + } if (podId != null) { sc.setParameters("podId", podId); } // Don't return DomR and ConsoleProxy volumes - sc.setParameters("type", VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm, VirtualMachine.Type.DomainRouter); + sc.setParameters("type", VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm, + VirtualMachine.Type.DomainRouter); // Only return volumes that are not destroyed sc.setParameters("state", Volume.State.Destroy); @@ -1650,12 +1724,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { public ListResponse searchForAccounts(ListAccountsCmd cmd) { Pair, Integer> result = searchForAccountsInternal(cmd); ListResponse response = new ListResponse(); - List accountResponses = ViewResponseHelper.createAccountResponse(result.first().toArray(new AccountJoinVO[result.first().size()])); + List accountResponses = ViewResponseHelper.createAccountResponse(result.first().toArray( + new AccountJoinVO[result.first().size()])); response.setResponses(accountResponses, result.second()); return response; } - private Pair, Integer> searchForAccountsInternal(ListAccountsCmd cmd) { Account caller = UserContext.current().getCaller(); Long domainId = cmd.getDomainId(); @@ -1685,7 +1759,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { if (accountName != null) { Account account = _accountDao.findActiveAccount(accountName, domainId); if (account == null || account.getId() == Account.ACCOUNT_ID_SYSTEM) { - throw new InvalidParameterValueException("Unable to find account by name " + accountName + " in domain " + domainId); + throw new InvalidParameterValueException("Unable to find account by name " + accountName + + " in domain " + domainId); } _accountMgr.checkAccess(caller, null, true, account); } @@ -1722,7 +1797,6 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sb.and("typeNEQ", sb.entity().getType(), SearchCriteria.Op.NEQ); sb.and("idNEQ", sb.entity().getId(), SearchCriteria.Op.NEQ); - if (listForDomain && isRecursive) { sb.and("path", sb.entity().getDomainPath(), SearchCriteria.Op.LIKE); } @@ -1777,12 +1851,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { public ListResponse searchForAsyncJobs(ListAsyncJobsCmd cmd) { Pair, Integer> result = searchForAsyncJobsInternal(cmd); ListResponse response = new ListResponse(); - List jobResponses = ViewResponseHelper.createAsyncJobResponse(result.first().toArray(new AsyncJobJoinVO[result.first().size()])); + List jobResponses = ViewResponseHelper.createAsyncJobResponse(result.first().toArray( + new AsyncJobJoinVO[result.first().size()])); response.setResponses(jobResponses, result.second()); return response; } - private Pair, Integer> searchForAsyncJobsInternal(ListAsyncJobsCmd cmd) { Account caller = UserContext.current().getCaller(); @@ -1791,8 +1865,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { Ternary domainIdRecursiveListProject = new Ternary( cmd.getDomainId(), cmd.isRecursive(), null); - _accountMgr.buildACLSearchParameters(caller, null, cmd.getAccountName(), null, permittedAccounts, domainIdRecursiveListProject, - cmd.listAll(), false); + _accountMgr.buildACLSearchParameters(caller, null, cmd.getAccountName(), null, permittedAccounts, + domainIdRecursiveListProject, cmd.listAll(), false); Long domainId = domainIdRecursiveListProject.first(); Boolean isRecursive = domainIdRecursiveListProject.second(); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); @@ -1857,7 +1931,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { Pair, Integer> result = searchForStoragePoolsInternal(cmd); ListResponse response = new ListResponse(); - List poolResponses = ViewResponseHelper.createStoragePoolResponse(result.first().toArray(new StoragePoolJoinVO[result.first().size()])); + List poolResponses = ViewResponseHelper.createStoragePoolResponse(result.first().toArray( + new StoragePoolJoinVO[result.first().size()])); response.setResponses(poolResponses, result.second()); return response; } @@ -1872,7 +1947,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } } - Long zoneId = _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), cmd.getZoneId()); + Long zoneId = _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), cmd.getZoneId()); Object id = cmd.getId(); Object name = cmd.getStoragePoolName(); Object path = cmd.getPath(); @@ -1883,23 +1958,21 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { Long startIndex = cmd.getStartIndex(); Long pageSize = cmd.getPageSizeVal(); - Filter searchFilter = new Filter(StoragePoolJoinVO.class, "id", Boolean.TRUE, startIndex, pageSize); SearchBuilder sb = _poolJoinDao.createSearchBuilder(); - sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct ids + sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct + // ids sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); - sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); + sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); sb.and("path", sb.entity().getPath(), SearchCriteria.Op.EQ); - sb.and("dataCenterId", sb.entity().getZoneId(), SearchCriteria.Op.EQ); + sb.and("dataCenterId", sb.entity().getZoneId(), SearchCriteria.Op.EQ); sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ); sb.and("clusterId", sb.entity().getClusterId(), SearchCriteria.Op.EQ); sb.and("hostAddress", sb.entity().getHostAddress(), SearchCriteria.Op.EQ); - SearchCriteria sc = sb.create(); - if (keyword != null) { SearchCriteria ssc = _poolJoinDao.createSearchCriteria(); ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); @@ -1913,7 +1986,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } if (name != null) { - sc.setParameters("name", "%" + name + "%"); + sc.setParameters("name", name); } if (path != null) { @@ -1921,7 +1994,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } if (zoneId != null) { sc.setParameters("dataCenterId", zoneId); - } + } if (pod != null) { sc.setParameters("podId", pod); } @@ -1953,11 +2026,92 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } + @Override + public ListResponse searchForImageStores(ListImageStoresCmd cmd) { + Pair, Integer> result = searchForImageStoresInternal(cmd); + ListResponse response = new ListResponse(); + + List poolResponses = ViewResponseHelper.createImageStoreResponse(result.first().toArray( + new ImageStoreJoinVO[result.first().size()])); + response.setResponses(poolResponses, result.second()); + return response; + } + + private Pair, Integer> searchForImageStoresInternal(ListImageStoresCmd cmd) { + + Long zoneId = _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), cmd.getZoneId()); + Object id = cmd.getId(); + Object name = cmd.getStoreName(); + String provider = cmd.getProvider(); + String protocol = cmd.getProtocol(); + Object keyword = cmd.getKeyword(); + Long startIndex = cmd.getStartIndex(); + Long pageSize = cmd.getPageSizeVal(); + + Filter searchFilter = new Filter(ImageStoreJoinVO.class, "id", Boolean.TRUE, startIndex, pageSize); + + SearchBuilder sb = _imageStoreJoinDao.createSearchBuilder(); + sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct + // ids + sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); + sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); + sb.and("dataCenterId", sb.entity().getZoneId(), SearchCriteria.Op.EQ); + sb.and("protocol", sb.entity().getProtocol(), SearchCriteria.Op.EQ); + sb.and("provider", sb.entity().getProviderName(), SearchCriteria.Op.EQ); + sb.and("role", sb.entity().getRole(), SearchCriteria.Op.EQ); + + SearchCriteria sc = sb.create(); + sc.setParameters("role", DataStoreRole.Image); + + if (keyword != null) { + SearchCriteria ssc = _imageStoreJoinDao.createSearchCriteria(); + ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); + ssc.addOr("provider", SearchCriteria.Op.LIKE, "%" + keyword + "%"); + sc.addAnd("name", SearchCriteria.Op.SC, ssc); + } + + if (id != null) { + sc.setParameters("id", id); + } + + if (name != null) { + sc.setParameters("name", name); + } + + if (zoneId != null) { + sc.setParameters("dataCenterId", zoneId); + } + if (provider != null) { + sc.setParameters("provider", provider); + } + if (protocol != null) { + sc.setParameters("protocol", protocol); + } + + // search Store details by ids + Pair, Integer> uniqueStorePair = _imageStoreJoinDao.searchAndCount(sc, searchFilter); + Integer count = uniqueStorePair.second(); + if (count.intValue() == 0) { + // empty result + return uniqueStorePair; + } + List uniqueStores = uniqueStorePair.first(); + Long[] vrIds = new Long[uniqueStores.size()]; + int i = 0; + for (ImageStoreJoinVO v : uniqueStores) { + vrIds[i++] = v.getId(); + } + List vrs = _imageStoreJoinDao.searchByIds(vrIds); + return new Pair, Integer>(vrs, count); + + } + @Override public ListResponse searchForDiskOfferings(ListDiskOfferingsCmd cmd) { Pair, Integer> result = searchForDiskOfferingsInternal(cmd); ListResponse response = new ListResponse(); - List offeringResponses = ViewResponseHelper.createDiskOfferingResponse(result.first().toArray(new DiskOfferingJoinVO[result.first().size()])); + List offeringResponses = ViewResponseHelper.createDiskOfferingResponse(result.first() + .toArray(new DiskOfferingJoinVO[result.first().size()])); response.setResponses(offeringResponses, result.second()); return response; } @@ -1975,10 +2129,10 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { Boolean isAscending = Boolean.parseBoolean(_configDao.getValue("sortkey.algorithm")); isAscending = (isAscending == null ? true : isAscending); - Filter searchFilter = new Filter(DiskOfferingJoinVO.class, "sortKey", isAscending, cmd.getStartIndex(), cmd.getPageSizeVal()); + Filter searchFilter = new Filter(DiskOfferingJoinVO.class, "sortKey", isAscending, cmd.getStartIndex(), + cmd.getPageSizeVal()); SearchCriteria sc = _diskOfferingJoinDao.createSearchCriteria(); - Account account = UserContext.current().getCaller(); Object name = cmd.getDiskOfferingName(); Object id = cmd.getId(); @@ -1988,31 +2142,32 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { // if a domainId is provided, we just return the disk offering // associated with this domain if (domainId != null) { - if (account.getType() == Account.ACCOUNT_TYPE_ADMIN || isPermissible(account.getDomainId(), domainId) ) { + if (account.getType() == Account.ACCOUNT_TYPE_ADMIN || isPermissible(account.getDomainId(), domainId)) { // check if the user's domain == do's domain || user's domain is // a child of so's domain for non-root users sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId); return _diskOfferingJoinDao.searchAndCount(sc, searchFilter); } else { - throw new PermissionDeniedException("The account:" + account.getAccountName() - + " does not fall in the same domain hierarchy as the disk offering"); + throw new PermissionDeniedException("The account:" + account.getAccountName() + + " does not fall in the same domain hierarchy as the disk offering"); } } - List domainIds = null; - // For non-root users, only return all offerings for the user's domain, and everything above till root + // For non-root users, only return all offerings for the user's domain, + // and everything above till root if ((account.getType() == Account.ACCOUNT_TYPE_NORMAL || account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || account.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { // find all domain Id up to root domain for this account domainIds = new ArrayList(); DomainVO domainRecord = _domainDao.findById(account.getDomainId()); - if ( domainRecord == null ){ + if (domainRecord == null) { s_logger.error("Could not find the domainId for account:" + account.getAccountName()); - throw new CloudAuthenticationException("Could not find the domainId for account:" + account.getAccountName()); + throw new CloudAuthenticationException("Could not find the domainId for account:" + + account.getAccountName()); } domainIds.add(domainRecord.getId()); - while (domainRecord.getParent() != null ){ + while (domainRecord.getParent() != null) { domainRecord = _domainDao.findById(domainRecord.getParent()); domainIds.add(domainRecord.getId()); } @@ -2020,13 +2175,19 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { SearchCriteria spc = _diskOfferingJoinDao.createSearchCriteria(); spc.addOr("domainId", SearchCriteria.Op.IN, domainIds.toArray()); - spc.addOr("domainId", SearchCriteria.Op.NULL); // include public offering as where + spc.addOr("domainId", SearchCriteria.Op.NULL); // include public + // offering as where sc.addAnd("domainId", SearchCriteria.Op.SC, spc); - sc.addAnd("systemUse", SearchCriteria.Op.EQ, false); // non-root users should not see system offering at all + sc.addAnd("systemUse", SearchCriteria.Op.EQ, false); // non-root + // users should + // not see + // system + // offering at + // all } - if (keyword != null) { + if (keyword != null) { SearchCriteria ssc = _diskOfferingJoinDao.createSearchCriteria(); ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%"); ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); @@ -2067,13 +2228,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { return _diskOfferingJoinDao.searchAndCount(sc, searchFilter); } - - @Override public ListResponse searchForServiceOfferings(ListServiceOfferingsCmd cmd) { Pair, Integer> result = searchForServiceOfferingsInternal(cmd); ListResponse response = new ListResponse(); - List offeringResponses = ViewResponseHelper.createServiceOfferingResponse(result.first().toArray(new ServiceOfferingJoinVO[result.first().size()])); + List offeringResponses = ViewResponseHelper.createServiceOfferingResponse(result + .first().toArray(new ServiceOfferingJoinVO[result.first().size()])); response.setResponses(offeringResponses, result.second()); return response; } @@ -2090,7 +2250,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { // root Boolean isAscending = Boolean.parseBoolean(_configDao.getValue("sortkey.algorithm")); isAscending = (isAscending == null ? true : isAscending); - Filter searchFilter = new Filter(ServiceOfferingJoinVO.class, "sortKey", isAscending, cmd.getStartIndex(), cmd.getPageSizeVal()); + Filter searchFilter = new Filter(ServiceOfferingJoinVO.class, "sortKey", isAscending, cmd.getStartIndex(), + cmd.getPageSizeVal()); SearchCriteria sc = _srvOfferingJoinDao.createSearchCriteria(); Account caller = UserContext.current().getCaller(); @@ -2118,7 +2279,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } } - // boolean includePublicOfferings = false; + // boolean includePublicOfferings = false; if ((caller.getType() == Account.ACCOUNT_TYPE_NORMAL || caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { // For non-root users. @@ -2128,23 +2289,24 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { // find all domain Id up to root domain for this account List domainIds = new ArrayList(); DomainVO domainRecord = _domainDao.findById(caller.getDomainId()); - if ( domainRecord == null ){ + if (domainRecord == null) { s_logger.error("Could not find the domainId for account:" + caller.getAccountName()); - throw new CloudAuthenticationException("Could not find the domainId for account:" + caller.getAccountName()); + throw new CloudAuthenticationException("Could not find the domainId for account:" + + caller.getAccountName()); } domainIds.add(domainRecord.getId()); - while (domainRecord.getParent() != null ){ + while (domainRecord.getParent() != null) { domainRecord = _domainDao.findById(domainRecord.getParent()); domainIds.add(domainRecord.getId()); } SearchCriteria spc = _srvOfferingJoinDao.createSearchCriteria(); spc.addOr("domainId", SearchCriteria.Op.IN, domainIds.toArray()); - spc.addOr("domainId", SearchCriteria.Op.NULL); // include public offering as where + spc.addOr("domainId", SearchCriteria.Op.NULL); // include public + // offering as where sc.addAnd("domainId", SearchCriteria.Op.SC, spc); - } - else { + } else { // for root users if (caller.getDomainId() != 1 && isSystem) { // NON ROOT admin throw new InvalidParameterValueException("Non ROOT admins cannot access system's offering"); @@ -2163,7 +2325,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } else if (vmId != null) { UserVmVO vmInstance = _userVmDao.findById(vmId); if ((vmInstance == null) || (vmInstance.getRemoved() != null)) { - InvalidParameterValueException ex = new InvalidParameterValueException("unable to find a virtual machine with specified id"); + InvalidParameterValueException ex = new InvalidParameterValueException( + "unable to find a virtual machine with specified id"); ex.addProxyObject(vmId.toString(), "vmId"); throw ex; } @@ -2185,7 +2348,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } if (isSystem != null) { - // note that for non-root users, isSystem is always false when control comes to here + // note that for non-root users, isSystem is always false when + // control comes to here sc.addAnd("systemUse", SearchCriteria.Op.EQ, isSystem); } @@ -2201,19 +2365,16 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } - - - @Override public ListResponse listDataCenters(ListZonesByCmd cmd) { Pair, Integer> result = listDataCentersInternal(cmd); ListResponse response = new ListResponse(); - List dcResponses = ViewResponseHelper.createDataCenterResponse(cmd.getShowCapacities(), result.first().toArray(new DataCenterJoinVO[result.first().size()])); + List dcResponses = ViewResponseHelper.createDataCenterResponse(cmd.getShowCapacities(), result + .first().toArray(new DataCenterJoinVO[result.first().size()])); response.setResponses(dcResponses, result.second()); return response; } - private Pair, Integer> listDataCentersInternal(ListZonesByCmd cmd) { Account account = UserContext.current().getCaller(); Long domainId = cmd.getDomainId(); @@ -2225,9 +2386,9 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { Filter searchFilter = new Filter(DataCenterJoinVO.class, null, false, cmd.getStartIndex(), cmd.getPageSizeVal()); SearchCriteria sc = _dcJoinDao.createSearchCriteria(); - if(networkType != null) - sc.addAnd("networkType", SearchCriteria.Op.EQ, networkType); - + if (networkType != null) + sc.addAnd("networkType", SearchCriteria.Op.EQ, networkType); + if (id != null) { sc.addAnd("id", SearchCriteria.Op.EQ, id); } else if (name != null) { @@ -2240,13 +2401,13 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sc.addAnd("name", SearchCriteria.Op.SC, ssc); } - /*List all resources due to Explicit Dedication except the dedicated resources of other account - * if (domainId != null) { - // for domainId != null - // right now, we made the decision to only list zones associated - // with this domain, private zone - sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId); - } else */ + /* + * List all resources due to Explicit Dedication except the + * dedicated resources of other account if (domainId != null) { // + * for domainId != null // right now, we made the decision to only + * list zones associated // with this domain, private zone + * sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId); } else + */ if (account.getType() == Account.ACCOUNT_TYPE_NORMAL) { // it was decided to return all zones for the user's domain, and // everything above till root @@ -2255,20 +2416,21 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { // check the parent, if not null, add zones for that parent to // list - // find all domain Id up to root domain for this account List domainIds = new ArrayList(); DomainVO domainRecord = _domainDao.findById(account.getDomainId()); - if ( domainRecord == null ){ + if (domainRecord == null) { s_logger.error("Could not find the domainId for account:" + account.getAccountName()); - throw new CloudAuthenticationException("Could not find the domainId for account:" + account.getAccountName()); + throw new CloudAuthenticationException("Could not find the domainId for account:" + + account.getAccountName()); } domainIds.add(domainRecord.getId()); - while (domainRecord.getParent() != null ){ + while (domainRecord.getParent() != null) { domainRecord = _domainDao.findById(domainRecord.getParent()); domainIds.add(domainRecord.getId()); } - // domainId == null (public zones) or domainId IN [all domain id up to root domain] + // domainId == null (public zones) or domainId IN [all domain id + // up to root domain] SearchCriteria sdc = _dcJoinDao.createSearchCriteria(); sdc.addOr("domainId", SearchCriteria.Op.IN, domainIds.toArray()); sdc.addOr("domainId", SearchCriteria.Op.NULL); @@ -2277,34 +2439,41 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { // remove disabled zones sc.addAnd("allocationState", SearchCriteria.Op.NEQ, Grouping.AllocationState.Disabled); - //remove Dedicated zones not dedicated to this domainId or subdomainId + // remove Dedicated zones not dedicated to this domainId or + // subdomainId List dedicatedZoneIds = removeDedicatedZoneNotSuitabe(domainIds); - if(!dedicatedZoneIds.isEmpty()){ - sdc.addAnd("id", SearchCriteria.Op.NIN, dedicatedZoneIds.toArray(new Object[dedicatedZoneIds.size()])); + if (!dedicatedZoneIds.isEmpty()) { + sdc.addAnd("id", SearchCriteria.Op.NIN, + dedicatedZoneIds.toArray(new Object[dedicatedZoneIds.size()])); } - } else if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || account.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { + } else if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN + || account.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { // it was decided to return all zones for the domain admin, and - // everything above till root, as well as zones till the domain leaf + // everything above till root, as well as zones till the domain + // leaf List domainIds = new ArrayList(); DomainVO domainRecord = _domainDao.findById(account.getDomainId()); - if ( domainRecord == null ){ + if (domainRecord == null) { s_logger.error("Could not find the domainId for account:" + account.getAccountName()); - throw new CloudAuthenticationException("Could not find the domainId for account:" + account.getAccountName()); + throw new CloudAuthenticationException("Could not find the domainId for account:" + + account.getAccountName()); } domainIds.add(domainRecord.getId()); // find all domain Ids till leaf - List allChildDomains = _domainDao.findAllChildren(domainRecord.getPath(), domainRecord.getId()); + List allChildDomains = _domainDao.findAllChildren(domainRecord.getPath(), + domainRecord.getId()); for (DomainVO domain : allChildDomains) { domainIds.add(domain.getId()); } // then find all domain Id up to root domain for this account - while (domainRecord.getParent() != null ){ + while (domainRecord.getParent() != null) { domainRecord = _domainDao.findById(domainRecord.getParent()); domainIds.add(domainRecord.getId()); } - // domainId == null (public zones) or domainId IN [all domain id up to root domain] + // domainId == null (public zones) or domainId IN [all domain id + // up to root domain] SearchCriteria sdc = _dcJoinDao.createSearchCriteria(); sdc.addOr("domainId", SearchCriteria.Op.IN, domainIds.toArray()); sdc.addOr("domainId", SearchCriteria.Op.NULL); @@ -2313,26 +2482,30 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { // remove disabled zones sc.addAnd("allocationState", SearchCriteria.Op.NEQ, Grouping.AllocationState.Disabled); - //remove Dedicated zones not dedicated to this domainId or subdomainId + // remove Dedicated zones not dedicated to this domainId or + // subdomainId List dedicatedZoneIds = removeDedicatedZoneNotSuitabe(domainIds); - if(!dedicatedZoneIds.isEmpty()){ - sdc.addAnd("id", SearchCriteria.Op.NIN, dedicatedZoneIds.toArray(new Object[dedicatedZoneIds.size()])); + if (!dedicatedZoneIds.isEmpty()) { + sdc.addAnd("id", SearchCriteria.Op.NIN, + dedicatedZoneIds.toArray(new Object[dedicatedZoneIds.size()])); } } - // handle available=FALSE option, only return zones with at least one VM running there + // handle available=FALSE option, only return zones with at least + // one VM running there Boolean available = cmd.isAvailable(); if (account != null) { if ((available != null) && Boolean.FALSE.equals(available)) { - Set dcIds = new HashSet(); //data centers with at least one VM running + Set dcIds = new HashSet(); // data centers with + // at least one VM + // running List routers = _routerDao.listBy(account.getId()); - for (DomainRouterVO router : routers){ + for (DomainRouterVO router : routers) { dcIds.add(router.getDataCenterId()); } - if ( dcIds.size() == 0) { + if (dcIds.size() == 0) { return new Pair, Integer>(new ArrayList(), 0); - } - else{ + } else { sc.addAnd("idIn", SearchCriteria.Op.IN, dcIds.toArray()); } @@ -2344,11 +2517,11 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } private List removeDedicatedZoneNotSuitabe(List domainIds) { - //remove dedicated zone of other domain + // remove dedicated zone of other domain List dedicatedZoneIds = new ArrayList(); List dedicatedResources = _dedicatedDao.listZonesNotInDomainIds(domainIds); for (DedicatedResourceVO dr : dedicatedResources) { - if(dr != null) { + if (dr != null) { dedicatedZoneIds.add(dr.getDataCenterId()); } } @@ -2384,18 +2557,327 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } @Override + public ListResponse listTemplates(ListTemplatesCmd cmd) { + Pair, Integer> result = searchForTemplatesInternal(cmd); + ListResponse response = new ListResponse(); + + List templateResponses = ViewResponseHelper.createTemplateResponse(result.first().toArray( + new TemplateJoinVO[result.first().size()])); + response.setResponses(templateResponses, result.second()); + return response; + } + + private Pair, Integer> searchForTemplatesInternal(ListTemplatesCmd cmd) { + TemplateFilter templateFilter = TemplateFilter.valueOf(cmd.getTemplateFilter()); + Long id = cmd.getId(); + Map tags = cmd.getTags(); + Account caller = UserContext.current().getCaller(); + + boolean listAll = false; + if (templateFilter != null && templateFilter == TemplateFilter.all) { + if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { + throw new InvalidParameterValueException("Filter " + TemplateFilter.all + + " can be specified by admin only"); + } + listAll = true; + } + + List permittedAccountIds = new ArrayList(); + Ternary domainIdRecursiveListProject = new Ternary( + cmd.getDomainId(), cmd.isRecursive(), null); + _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccountIds, + domainIdRecursiveListProject, listAll, false); + ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); + List permittedAccounts = new ArrayList(); + for (Long accountId : permittedAccountIds) { + permittedAccounts.add(_accountMgr.getAccount(accountId)); + } + + boolean showDomr = ((templateFilter != TemplateFilter.selfexecutable) && (templateFilter != TemplateFilter.featured)); + HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor()); + + return searchForTemplatesInternal(id, cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, + cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType, showDomr, + cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags); + } + + private Pair, Integer> searchForTemplatesInternal(Long templateId, String name, + String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long pageSize, + Long startIndex, Long zoneId, HypervisorType hyperType, boolean showDomr, boolean onlyReady, + List permittedAccounts, Account caller, ListProjectResourcesCriteria listProjectResourcesCriteria, + Map tags) { + VMTemplateVO template = null; + + Boolean isAscending = Boolean.parseBoolean(_configDao.getValue("sortkey.algorithm")); + isAscending = (isAscending == null ? true : isAscending); + Filter searchFilter = new Filter(TemplateJoinVO.class, "sortKey", isAscending, startIndex, pageSize); + SearchCriteria sc = _templateJoinDao.createSearchCriteria(); + + // verify templateId parameter and specially handle it + if (templateId != null) { + template = _templateDao.findById(templateId); + if (template == null) { + throw new InvalidParameterValueException("Please specify a valid template ID."); + }// If ISO requested then it should be ISO. + if (isIso && template.getFormat() != ImageFormat.ISO) { + s_logger.error("Template Id " + templateId + " is not an ISO"); + InvalidParameterValueException ex = new InvalidParameterValueException( + "Specified Template Id is not an ISO"); + ex.addProxyObject(template.getUuid(), "templateId"); + throw ex; + }// If ISO not requested then it shouldn't be an ISO. + if (!isIso && template.getFormat() == ImageFormat.ISO) { + s_logger.error("Incorrect format of the template id " + templateId); + InvalidParameterValueException ex = new InvalidParameterValueException("Incorrect format " + + template.getFormat() + " of the specified template id"); + ex.addProxyObject(template.getUuid(), "templateId"); + throw ex; + } + + // if template is not public, perform permission check here + if (!template.isPublicTemplate() && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + Account owner = _accountMgr.getAccount(template.getAccountId()); + _accountMgr.checkAccess(caller, null, true, owner); + } + + // if templateId is specified, then we will just use the id to + // search and ignore other query parameters + sc.addAnd("id", SearchCriteria.Op.EQ, templateId); + } else { + + DomainVO domain = null; + if (!permittedAccounts.isEmpty()) { + domain = _domainDao.findById(permittedAccounts.get(0).getDomainId()); + } else { + domain = _domainDao.findById(DomainVO.ROOT_DOMAIN); + } + + List hypers = null; + if (!isIso) { + hypers = _resourceMgr.listAvailHypervisorInZone(null, null); + } + + // add criteria for project or not + if (listProjectResourcesCriteria == ListProjectResourcesCriteria.SkipProjectResources) { + sc.addAnd("accountType", SearchCriteria.Op.NEQ, Account.ACCOUNT_TYPE_PROJECT); + } else if (listProjectResourcesCriteria == ListProjectResourcesCriteria.ListProjectResourcesOnly) { + sc.addAnd("accountType", SearchCriteria.Op.EQ, Account.ACCOUNT_TYPE_PROJECT); + } + + // add criteria for domain path in case of domain admin + if ((templateFilter == TemplateFilter.self || templateFilter == TemplateFilter.selfexecutable) + && (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN)) { + sc.addAnd("domainPath", SearchCriteria.Op.LIKE, domain.getPath() + "%"); + } + + List relatedDomainIds = new ArrayList(); + List permittedAccountIds = new ArrayList(); + if (!permittedAccounts.isEmpty()) { + for (Account account : permittedAccounts) { + permittedAccountIds.add(account.getId()); + DomainVO accountDomain = _domainDao.findById(account.getDomainId()); + + // get all parent domain ID's all the way till root domain + DomainVO domainTreeNode = accountDomain; + relatedDomainIds.add(domainTreeNode.getId()); + while (domainTreeNode.getParent() != null) { + domainTreeNode = _domainDao.findById(domainTreeNode.getParent()); + relatedDomainIds.add(domainTreeNode.getId()); + } + + // get all child domain ID's + if (_accountMgr.isAdmin(account.getType())) { + List allChildDomains = _domainDao.findAllChildren(accountDomain.getPath(), + accountDomain.getId()); + for (DomainVO childDomain : allChildDomains) { + relatedDomainIds.add(childDomain.getId()); + } + } + } + } + + if (!isIso) { + // add hypervisor criteria for template case + if (hypers != null && !hypers.isEmpty()) { + String[] relatedHypers = new String[hypers.size()]; + for (int i = 0; i < hypers.size(); i++) { + relatedHypers[i] = hypers.get(i).toString(); + } + sc.addAnd("hypervisorType", SearchCriteria.Op.IN, relatedHypers); + } + } + + // control different template filters + if (templateFilter == TemplateFilter.featured || templateFilter == TemplateFilter.community) { + sc.addAnd("publicTemplate", SearchCriteria.Op.EQ, true); + if (templateFilter == TemplateFilter.featured) { + sc.addAnd("featured", SearchCriteria.Op.EQ, true); + } else { + sc.addAnd("featured", SearchCriteria.Op.EQ, false); + } + if (!permittedAccounts.isEmpty()) { + SearchCriteria scc = _templateJoinDao.createSearchCriteria(); + scc.addOr("domainId", SearchCriteria.Op.IN, relatedDomainIds.toArray()); + scc.addOr("domainId", SearchCriteria.Op.NULL); + sc.addAnd("domainId", SearchCriteria.Op.SC, scc); + } + } else if (templateFilter == TemplateFilter.self || templateFilter == TemplateFilter.selfexecutable) { + if (!permittedAccounts.isEmpty()) { + sc.addAnd("accountId", SearchCriteria.Op.IN, permittedAccountIds.toArray()); + } + } else if (templateFilter == TemplateFilter.sharedexecutable || templateFilter == TemplateFilter.shared) { + SearchCriteria scc = _templateJoinDao.createSearchCriteria(); + scc.addOr("accountId", SearchCriteria.Op.IN, permittedAccountIds.toArray()); + scc.addOr("sharedAccountId", SearchCriteria.Op.IN, permittedAccountIds.toArray()); + sc.addAnd("accountId", SearchCriteria.Op.SC, scc); + } else if (templateFilter == TemplateFilter.executable) { + SearchCriteria scc = _templateJoinDao.createSearchCriteria(); + scc.addOr("publicTemplate", SearchCriteria.Op.EQ, true); + if (!permittedAccounts.isEmpty()) { + scc.addOr("accountId", SearchCriteria.Op.IN, permittedAccountIds.toArray()); + } + sc.addAnd("publicTemplate", SearchCriteria.Op.SC, scc); + } + + // add tags criteria + if (tags != null && !tags.isEmpty()) { + SearchCriteria scc = _templateJoinDao.createSearchCriteria(); + int count = 0; + for (String key : tags.keySet()) { + SearchCriteria scTag = _templateJoinDao.createSearchCriteria(); + scTag.addAnd("tagKey", SearchCriteria.Op.EQ, key); + scTag.addAnd("tagValue", SearchCriteria.Op.EQ, tags.get(key)); + if (isIso) { + scTag.addAnd("tagResourceType", SearchCriteria.Op.EQ, TaggedResourceType.ISO); + } else { + scTag.addAnd("tagResourceType", SearchCriteria.Op.EQ, TaggedResourceType.Template); + } + scc.addOr("tagKey", SearchCriteria.Op.SC, scTag); + count++; + } + sc.addAnd("tagKey", SearchCriteria.Op.SC, scc); + } + + // other criteria + + if (keyword != null) { + sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); + } else if (name != null) { + sc.addAnd("name", SearchCriteria.Op.EQ, name); + } + + if (isIso) { + sc.addAnd("format", SearchCriteria.Op.EQ, "ISO"); + + } else { + sc.addAnd("format", SearchCriteria.Op.NEQ, "ISO"); + } + + if (!hyperType.equals(HypervisorType.None)) { + sc.addAnd("hypervisorType", SearchCriteria.Op.EQ, hyperType); + } + + if (bootable != null) { + sc.addAnd("bootable", SearchCriteria.Op.EQ, bootable); + } + + if (onlyReady) { + sc.addAnd("state", SearchCriteria.Op.EQ, TemplateState.Ready); + } + + if (zoneId != null) { + sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId); + } + + if (!showDomr) { + // excluding system template + sc.addAnd("templateType", SearchCriteria.Op.NEQ, Storage.TemplateType.SYSTEM); + } + } + + // don't return removed template, this should not be needed since we + // changed annotation for removed field in TemplateJoinVO. + // sc.addAnd("removed", SearchCriteria.Op.NULL); + + // search unique templates and find details by Ids + Pair, Integer> uniqueTmplPair = _templateJoinDao.searchAndCount(sc, searchFilter); + Integer count = uniqueTmplPair.second(); + if (count.intValue() == 0) { + // empty result + return uniqueTmplPair; + } + List uniqueTmpls = uniqueTmplPair.first(); + Long[] vrIds = new Long[uniqueTmpls.size()]; + int i = 0; + for (TemplateJoinVO v : uniqueTmpls) { + vrIds[i++] = v.getId(); + } + List vrs = _templateJoinDao.searchByIds(vrIds); + return new Pair, Integer>(vrs, count); + + // TODO: revisit the special logic for iso search in + // VMTemplateDaoImpl.searchForTemplates and understand why we need to + // specially handle ISO. The original logic is very twisted and no idea + // about what the code was doing. + + } + + @Override + public ListResponse listIsos(ListIsosCmd cmd) { + Pair, Integer> result = searchForIsosInternal(cmd); + ListResponse response = new ListResponse(); + + List templateResponses = ViewResponseHelper.createIsoResponse(result.first().toArray( + new TemplateJoinVO[result.first().size()])); + response.setResponses(templateResponses, result.second()); + return response; + } + + private Pair, Integer> searchForIsosInternal(ListIsosCmd cmd) { + TemplateFilter isoFilter = TemplateFilter.valueOf(cmd.getIsoFilter()); + Long id = cmd.getId(); + Map tags = cmd.getTags(); + Account caller = UserContext.current().getCaller(); + + boolean listAll = false; + if (isoFilter != null && isoFilter == TemplateFilter.all) { + if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { + throw new InvalidParameterValueException("Filter " + TemplateFilter.all + + " can be specified by admin only"); + } + listAll = true; + } + + List permittedAccountIds = new ArrayList(); + Ternary domainIdRecursiveListProject = new Ternary( + cmd.getDomainId(), cmd.isRecursive(), null); + _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccountIds, + domainIdRecursiveListProject, listAll, false); + ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); + List permittedAccounts = new ArrayList(); + for (Long accountId : permittedAccountIds) { + permittedAccounts.add(_accountMgr.getAccount(accountId)); + } + + HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor()); + + return searchForTemplatesInternal(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true, + cmd.isBootable(), cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType, true, + cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags); + } + public ListResponse listAffinityGroups(Long affinityGroupId, String affinityGroupName, String affinityGroupType, Long vmId, String accountName, Long domainId, boolean isRecursive, boolean listAll, Long startIndex, Long pageSize) { Pair, Integer> result = listAffinityGroupsInternal(affinityGroupId, - affinityGroupName, affinityGroupType, vmId, accountName, domainId, isRecursive, listAll, startIndex, pageSize); + affinityGroupName, affinityGroupType, vmId, accountName, domainId, isRecursive, listAll, startIndex, + pageSize); ListResponse response = new ListResponse(); List agResponses = ViewResponseHelper.createAffinityGroupResponses(result.first()); response.setResponses(agResponses, result.second()); return response; } - public Pair, Integer> listAffinityGroupsInternal(Long affinityGroupId, String affinityGroupName, String affinityGroupType, Long vmId, String accountName, Long domainId, boolean isRecursive, boolean listAll, Long startIndex, Long pageSize) { @@ -2406,7 +2888,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { if (vmId != null) { UserVmVO userVM = _userVmDao.findById(vmId); - if (userVM == null){ + if (userVM == null) { throw new InvalidParameterValueException("Unable to list affinity groups for virtual machine instance " + vmId + "; instance not found."); } @@ -2432,7 +2914,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { // distinct SearchCriteria sc = groupSearch.create(); - _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); if (affinityGroupId != null) { sc.addAnd("id", SearchCriteria.Op.EQ, affinityGroupId); @@ -2446,8 +2929,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sc.addAnd("type", SearchCriteria.Op.EQ, affinityGroupType); } - - Pair, Integer> uniqueGroupsPair = _affinityGroupJoinDao.searchAndCount(sc, searchFilter); + Pair, Integer> uniqueGroupsPair = _affinityGroupJoinDao.searchAndCount(sc, + searchFilter); // search group details by ids Integer count = uniqueGroupsPair.second(); if (count.intValue() == 0) { @@ -2483,27 +2966,26 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { return new Pair, Integer>(ags, count); } - - public List listResource(ListResourceDetailsCmd cmd){ + public List listResource(ListResourceDetailsCmd cmd) { String key = cmd.getKey(); ResourceTag.TaggedResourceType resourceType = cmd.getResourceType(); String resourceId = cmd.getResourceId(); Long id = _taggedResourceMgr.getResourceId(resourceId, resourceType); - if(resourceType == ResourceTag.TaggedResourceType.Volume){ + if (resourceType == ResourceTag.TaggedResourceType.Volume) { List volumeDetailList; - if(key == null){ + if (key == null) { volumeDetailList = _volumeDetailDao.findDetails(id); - }else{ + } else { VolumeDetailVO volumeDetail = _volumeDetailDao.findDetail(id, key); volumeDetailList = new LinkedList(); volumeDetailList.add(volumeDetail); } List volumeDetailResponseList = new ArrayList(); - for (VolumeDetailVO volumeDetail : volumeDetailList ){ + for (VolumeDetailVO volumeDetail : volumeDetailList) { ResourceDetailResponse volumeDetailResponse = new ResourceDetailResponse(); volumeDetailResponse.setResourceId(id.toString()); volumeDetailResponse.setName(volumeDetail.getName()); @@ -2515,22 +2997,21 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { return volumeDetailResponseList; - } else { - + } else { List nicDetailList; - if(key == null){ + if (key == null) { nicDetailList = _nicDetailDao.findDetails(id); - }else { + } else { NicDetailVO nicDetail = _nicDetailDao.findDetail(id, key); nicDetailList = new LinkedList(); nicDetailList.add(nicDetail); } List nicDetailResponseList = new ArrayList(); - for(NicDetailVO nicDetail : nicDetailList){ + for (NicDetailVO nicDetail : nicDetailList) { ResourceDetailResponse nicDetailResponse = new ResourceDetailResponse(); - //String uuid = ApiDBUtils.findN + // String uuid = ApiDBUtils.findN nicDetailResponse.setName(nicDetail.getName()); nicDetailResponse.setValue(nicDetail.getValue()); nicDetailResponse.setResourceType(ResourceTag.TaggedResourceType.Nic.toString()); diff --git a/server/src/com/cloud/api/query/ViewResponseHelper.java b/server/src/com/cloud/api/query/ViewResponseHelper.java index a61da69b2e8..b98cea3f778 100644 --- a/server/src/com/cloud/api/query/ViewResponseHelper.java +++ b/server/src/com/cloud/api/query/ViewResponseHelper.java @@ -49,6 +49,7 @@ import org.apache.cloudstack.api.response.EventResponse; import org.apache.cloudstack.api.response.HostForMigrationResponse; import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.InstanceGroupResponse; +import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.cloudstack.api.response.ProjectAccountResponse; import org.apache.cloudstack.api.response.ProjectInvitationResponse; import org.apache.cloudstack.api.response.ProjectResponse; @@ -56,12 +57,16 @@ import org.apache.cloudstack.api.response.ResourceTagResponse; import org.apache.cloudstack.api.response.SecurityGroupResponse; import org.apache.cloudstack.api.response.ServiceOfferingResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; +import org.apache.cloudstack.api.response.TemplateResponse; import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.api.response.VolumeResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.log4j.Logger; + +import com.cloud.api.query.vo.ImageStoreJoinVO; +import com.cloud.api.query.vo.TemplateJoinVO; import java.util.ArrayList; import java.util.EnumSet; import java.util.Hashtable; @@ -283,6 +288,25 @@ public class ViewResponseHelper { return new ArrayList(vrDataList.values()); } + + public static List createImageStoreResponse(ImageStoreJoinVO... stores) { + Hashtable vrDataList = new Hashtable(); + // Initialise the vrdatalist with the input data + for (ImageStoreJoinVO vr : stores) { + ImageStoreResponse vrData = vrDataList.get(vr.getId()); + if ( vrData == null ){ + // first time encountering this vm + vrData = ApiDBUtils.newImageStoreResponse(vr); + } + else{ + // update tags + vrData = ApiDBUtils.fillImageStoreDetails(vrData, vr); + } + vrDataList.put(vr.getId(), vrData); + } + return new ArrayList(vrDataList.values()); + } + public static List createStoragePoolForMigrationResponse(StoragePoolJoinVO... pools) { Hashtable vrDataList = new Hashtable(); // Initialise the vrdatalist with the input data @@ -341,6 +365,57 @@ public class ViewResponseHelper { return respList; } + public static List createTemplateResponse(TemplateJoinVO... templates) { + Hashtable vrDataList = new Hashtable(); + for (TemplateJoinVO vr : templates) { + TemplateResponse vrData = vrDataList.get(vr.getId()); + if ( vrData == null ){ + // first time encountering this volume + vrData = ApiDBUtils.newTemplateResponse(vr); + } + else{ + // update tags + vrData = ApiDBUtils.fillTemplateDetails(vrData, vr); + } + vrDataList.put(vr.getId(), vrData); + } + return new ArrayList(vrDataList.values()); + } + + public static List createTemplateUpdateResponse(TemplateJoinVO... templates) { + Hashtable vrDataList = new Hashtable(); + for (TemplateJoinVO vr : templates) { + TemplateResponse vrData = vrDataList.get(vr.getId()); + if ( vrData == null ){ + // first time encountering this volume + vrData = ApiDBUtils.newTemplateUpdateResponse(vr); + } + else{ + // update tags + vrData = ApiDBUtils.fillTemplateDetails(vrData, vr); + } + vrDataList.put(vr.getId(), vrData); + } + return new ArrayList(vrDataList.values()); + } + + public static List createIsoResponse(TemplateJoinVO... templates) { + Hashtable vrDataList = new Hashtable(); + for (TemplateJoinVO vr : templates) { + TemplateResponse vrData = vrDataList.get(vr.getId()); + if ( vrData == null ){ + // first time encountering this volume + vrData = ApiDBUtils.newIsoResponse(vr); + } + else{ + // update tags + vrData = ApiDBUtils.fillTemplateDetails(vrData, vr); + } + vrDataList.put(vr.getId(), vrData); + } + return new ArrayList(vrDataList.values()); + } + public static List createAffinityGroupResponses(List groups) { Hashtable vrDataList = new Hashtable(); for (AffinityGroupJoinVO vr : groups) { diff --git a/server/src/com/cloud/api/query/dao/ImageStoreJoinDao.java b/server/src/com/cloud/api/query/dao/ImageStoreJoinDao.java new file mode 100644 index 00000000000..c1f6325c19b --- /dev/null +++ b/server/src/com/cloud/api/query/dao/ImageStoreJoinDao.java @@ -0,0 +1,36 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.api.query.dao; + +import java.util.List; + +import org.apache.cloudstack.api.response.ImageStoreResponse; +import com.cloud.api.query.vo.ImageStoreJoinVO; +import com.cloud.storage.ImageStore; +import com.cloud.utils.db.GenericDao; + +public interface ImageStoreJoinDao extends GenericDao { + + ImageStoreResponse newImageStoreResponse(ImageStoreJoinVO os); + + ImageStoreResponse setImageStoreResponse(ImageStoreResponse response, ImageStoreJoinVO os); + + List newImageStoreView(ImageStore os); + + List searchByIds(Long... spIds); + +} diff --git a/server/src/com/cloud/api/query/dao/ImageStoreJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/ImageStoreJoinDaoImpl.java new file mode 100644 index 00000000000..7810ffc16ae --- /dev/null +++ b/server/src/com/cloud/api/query/dao/ImageStoreJoinDaoImpl.java @@ -0,0 +1,162 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.api.query.dao; + +import java.util.ArrayList; +import java.util.List; + +import javax.ejb.Local; +import javax.inject.Inject; + +import org.apache.cloudstack.api.response.ImageStoreDetailResponse; +import org.apache.cloudstack.api.response.ImageStoreResponse; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.api.query.vo.ImageStoreJoinVO; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.storage.ImageStore; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + + +@Component +@Local(value={ImageStoreJoinDao.class}) +public class ImageStoreJoinDaoImpl extends GenericDaoBase implements ImageStoreJoinDao { + public static final Logger s_logger = Logger.getLogger(ImageStoreJoinDaoImpl.class); + + @Inject + private ConfigurationDao _configDao; + + private final SearchBuilder dsSearch; + + private final SearchBuilder dsIdSearch; + + + protected ImageStoreJoinDaoImpl() { + + dsSearch = createSearchBuilder(); + dsSearch.and("idIN", dsSearch.entity().getId(), SearchCriteria.Op.IN); + dsSearch.done(); + + dsIdSearch = createSearchBuilder(); + dsIdSearch.and("id", dsIdSearch.entity().getId(), SearchCriteria.Op.EQ); + dsIdSearch.done(); + + this._count = "select count(distinct id) from image_store_view WHERE "; + } + + + + + + @Override + public ImageStoreResponse newImageStoreResponse(ImageStoreJoinVO ids) { + ImageStoreResponse osResponse = new ImageStoreResponse(); + osResponse.setId(ids.getUuid()); + osResponse.setName(ids.getName()); + osResponse.setProviderName(ids.getProviderName()); + osResponse.setProtocol(ids.getProtocol()); + osResponse.setUrl(ids.getUrl()); + osResponse.setScope(ids.getScope()); + osResponse.setZoneId(ids.getZoneUuid()); + osResponse.setZoneName(ids.getZoneName()); + + String detailName = ids.getDetailName(); + if ( detailName != null && detailName.length() > 0 ){ + ImageStoreDetailResponse osdResponse = new ImageStoreDetailResponse(detailName, ids.getDetailValue()); + osResponse.addDetail(osdResponse); + } + osResponse.setObjectName("imagestore"); + return osResponse; + } + + + + + + @Override + public ImageStoreResponse setImageStoreResponse(ImageStoreResponse response, ImageStoreJoinVO ids) { + String detailName = ids.getDetailName(); + if ( detailName != null && detailName.length() > 0 ){ + ImageStoreDetailResponse osdResponse = new ImageStoreDetailResponse(detailName, ids.getDetailValue()); + response.addDetail(osdResponse); + } + return response; + } + + + + @Override + public List newImageStoreView(ImageStore os) { + SearchCriteria sc = dsIdSearch.create(); + sc.setParameters("id", os.getId()); + return searchIncludingRemoved(sc, null, null, false); + + } + + + + @Override + public List searchByIds(Long... spIds) { + // set detail batch query size + int DETAILS_BATCH_SIZE = 2000; + String batchCfg = _configDao.getValue("detail.batch.query.size"); + if ( batchCfg != null ){ + DETAILS_BATCH_SIZE = Integer.parseInt(batchCfg); + } + // query details by batches + List uvList = new ArrayList(); + // query details by batches + int curr_index = 0; + if ( spIds.length > DETAILS_BATCH_SIZE ){ + while ( (curr_index + DETAILS_BATCH_SIZE ) <= spIds.length ) { + Long[] ids = new Long[DETAILS_BATCH_SIZE]; + for (int k = 0, j = curr_index; j < curr_index + DETAILS_BATCH_SIZE; j++, k++) { + ids[k] = spIds[j]; + } + SearchCriteria sc = dsSearch.create(); + sc.setParameters("idIN", ids); + List vms = searchIncludingRemoved(sc, null, null, false); + if (vms != null) { + uvList.addAll(vms); + } + curr_index += DETAILS_BATCH_SIZE; + } + } + if (curr_index < spIds.length) { + int batch_size = (spIds.length - curr_index); + // set the ids value + Long[] ids = new Long[batch_size]; + for (int k = 0, j = curr_index; j < curr_index + batch_size; j++, k++) { + ids[k] = spIds[j]; + } + SearchCriteria sc = dsSearch.create(); + sc.setParameters("idIN", ids); + List vms = searchIncludingRemoved(sc, null, null, false); + if (vms != null) { + uvList.addAll(vms); + } + } + return uvList; + } + + + + +} diff --git a/server/src/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java index 4254a7cb825..68d9113cc17 100644 --- a/server/src/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java @@ -21,37 +21,33 @@ import java.util.List; import javax.ejb.Local; import javax.inject.Inject; - -import com.cloud.capacity.Capacity; import org.apache.cloudstack.api.response.StoragePoolResponse; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; -import org.apache.commons.lang.ObjectUtils; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import com.cloud.api.ApiDBUtils; import com.cloud.api.query.vo.StoragePoolJoinVO; +import com.cloud.capacity.Capacity; import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.storage.ScopeType; import com.cloud.storage.StoragePool; import com.cloud.storage.StorageStats; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; - @Component -@Local(value={StoragePoolJoinDao.class}) +@Local(value = { StoragePoolJoinDao.class }) public class StoragePoolJoinDaoImpl extends GenericDaoBase implements StoragePoolJoinDao { public static final Logger s_logger = Logger.getLogger(StoragePoolJoinDaoImpl.class); @Inject - private ConfigurationDao _configDao; + private ConfigurationDao _configDao; private final SearchBuilder spSearch; private final SearchBuilder spIdSearch; - protected StoragePoolJoinDaoImpl() { spSearch = createSearchBuilder(); @@ -65,10 +61,6 @@ public class StoragePoolJoinDaoImpl extends GenericDaoBase 0){ + if (response.getTags() != null && response.getTags().length() > 0) { response.setTags(response.getTags() + "," + tag); - } - else{ + } else { response.setTags(tag); } } @@ -146,13 +139,13 @@ public class StoragePoolJoinDaoImpl extends GenericDaoBase 0){ + if (response.getTags() != null && response.getTags().length() > 0) { response.setTags(response.getTags() + "," + tag); } else { response.setTags(tag); @@ -193,22 +185,20 @@ public class StoragePoolJoinDaoImpl extends GenericDaoBase searchByIds(Long... spIds) { // set detail batch query size int DETAILS_BATCH_SIZE = 2000; String batchCfg = _configDao.getValue("detail.batch.query.size"); - if ( batchCfg != null ){ + if (batchCfg != null) { DETAILS_BATCH_SIZE = Integer.parseInt(batchCfg); } // query details by batches List uvList = new ArrayList(); // query details by batches int curr_index = 0; - if ( spIds.length > DETAILS_BATCH_SIZE ){ - while ( (curr_index + DETAILS_BATCH_SIZE ) <= spIds.length ) { + if (spIds.length > DETAILS_BATCH_SIZE) { + while ((curr_index + DETAILS_BATCH_SIZE) <= spIds.length) { Long[] ids = new Long[DETAILS_BATCH_SIZE]; for (int k = 0, j = curr_index; j < curr_index + DETAILS_BATCH_SIZE; j++, k++) { ids[k] = spIds[j]; @@ -239,7 +229,4 @@ public class StoragePoolJoinDaoImpl extends GenericDaoBase { + + TemplateResponse newTemplateResponse(TemplateJoinVO tmpl); + + TemplateResponse newIsoResponse(TemplateJoinVO tmpl); + + TemplateResponse newUpdateResponse(TemplateJoinVO tmpl); + + TemplateResponse setTemplateResponse(TemplateResponse tmplData, TemplateJoinVO tmpl); + + List newTemplateView(VirtualMachineTemplate tmpl); + + List newTemplateView(VirtualMachineTemplate tmpl, long zoneId, boolean readyOnly); + + List searchByIds(Long... ids); + + List listActiveTemplates(long storeId); + + } diff --git a/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java new file mode 100644 index 00000000000..07930936b44 --- /dev/null +++ b/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java @@ -0,0 +1,455 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.api.query.dao; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.ejb.Local; +import javax.inject.Inject; + +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.response.TemplateResponse; +import org.apache.cloudstack.api.response.TemplateZoneResponse; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateState; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.api.ApiDBUtils; +import com.cloud.api.ApiResponseHelper; +import com.cloud.api.query.vo.ResourceTagJoinVO; +import com.cloud.api.query.vo.TemplateJoinVO; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.storage.VMTemplateHostVO; +import com.cloud.storage.Storage.TemplateType; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.template.VirtualMachineTemplate; +import com.cloud.user.Account; +import com.cloud.user.UserContext; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + + +@Component +@Local(value={TemplateJoinDao.class}) +public class TemplateJoinDaoImpl extends GenericDaoBase implements TemplateJoinDao { + + + + public static final Logger s_logger = Logger.getLogger(TemplateJoinDaoImpl.class); + + @Inject + private ConfigurationDao _configDao; + + private final SearchBuilder tmpltSearch; + + private final SearchBuilder tmpltIdSearch; + + private final SearchBuilder tmpltZoneSearch; + + private final SearchBuilder activeTmpltSearch; + + + protected TemplateJoinDaoImpl() { + + tmpltSearch = createSearchBuilder(); + tmpltSearch.and("idIN", tmpltSearch.entity().getId(), SearchCriteria.Op.IN); + tmpltSearch.done(); + + tmpltIdSearch = createSearchBuilder(); + tmpltIdSearch.and("id", tmpltIdSearch.entity().getId(), SearchCriteria.Op.EQ); + tmpltIdSearch.done(); + + tmpltZoneSearch = createSearchBuilder(); + tmpltZoneSearch.and("id", tmpltZoneSearch.entity().getId(), SearchCriteria.Op.EQ); + tmpltZoneSearch.and("dataCenterId", tmpltZoneSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); + tmpltZoneSearch.and("state", tmpltZoneSearch.entity().getState(), SearchCriteria.Op.EQ); + tmpltZoneSearch.done(); + + activeTmpltSearch = createSearchBuilder(); + activeTmpltSearch.and("store_id", activeTmpltSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ); + activeTmpltSearch.and("type", activeTmpltSearch.entity().getTemplateType(), SearchCriteria.Op.EQ); + activeTmpltSearch.done(); + + // select distinct pair (template_id, zone_id) + this._count = "select count(distinct id) from template_view WHERE "; + } + + + + + @Override + public TemplateResponse newTemplateResponse(TemplateJoinVO template) { + TemplateResponse templateResponse = new TemplateResponse(); + templateResponse.setId(template.getUuid()); + templateResponse.setName(template.getName()); + templateResponse.setDisplayText(template.getDisplayText()); + templateResponse.setPublic(template.isPublicTemplate()); + templateResponse.setCreated(template.getCreatedOnStore()); + templateResponse.setReady(template.getState() == ObjectInDataStoreStateMachine.State.Ready); + templateResponse.setFeatured(template.isFeatured()); + templateResponse.setExtractable(template.isExtractable() && !(template.getTemplateType() == TemplateType.SYSTEM)); + templateResponse.setPasswordEnabled(template.isEnablePassword()); + templateResponse.setSshKeyEnabled(template.isEnableSshKey()); + templateResponse.setCrossZones(template.isCrossZones()); + templateResponse.setFormat(template.getFormat()); + if (template.getTemplateType() != null) { + templateResponse.setTemplateType(template.getTemplateType().toString()); + } + + templateResponse.setHypervisor(template.getHypervisorType().toString()); + + + templateResponse.setOsTypeId(template.getGuestOSUuid()); + templateResponse.setOsTypeName(template.getGuestOSName()); + + // populate owner. + ApiResponseHelper.populateOwner(templateResponse, template); + + // populate domain + templateResponse.setDomainId(template.getDomainUuid()); + templateResponse.setDomainName(template.getDomainName()); + + + + boolean isAdmin = false; + Account caller = UserContext.current().getCaller(); + if ((caller == null) || BaseCmd.isAdmin(caller.getType())) { + isAdmin = true; + } + + // If the user is an Admin, add the template download status + if (isAdmin || caller.getId() == template.getAccountId()) { + // add download status + if (template.getDownloadState() != Status.DOWNLOADED) { + String templateStatus = "Processing"; + if (template.getDownloadState() == VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS) { + if (template.getDownloadPercent() == 100) { + templateStatus = "Installing Template"; + } else { + templateStatus = template.getDownloadPercent() + "% Downloaded"; + } + } else { + templateStatus = template.getErrorString(); + } + templateResponse.setStatus(templateStatus); + } else if (template.getDownloadState() == VMTemplateHostVO.Status.DOWNLOADED) { + templateResponse.setStatus("Download Complete"); + } else { + templateResponse.setStatus("Successfully Installed"); + } + } + + Long templateSize = template.getSize(); + if (templateSize > 0) { + templateResponse.setSize(templateSize); + } + + templateResponse.setChecksum(template.getChecksum()); + if (template.getSourceTemplateId() != null) { + templateResponse.setSourceTemplateId(template.getSourceTemplateUuid()); + } + templateResponse.setTemplateTag(template.getTemplateTag()); + + // set template zone information + if (template.getDataCenterId() > 0 ){ + TemplateZoneResponse tmplZoneResp = new TemplateZoneResponse(template.getDataCenterUuid(), template.getDataCenterName()); + templateResponse.addZone(tmplZoneResp); + // set the first found associated zone directly in TemplateResponse + templateResponse.setZoneId(template.getDataCenterUuid()); + templateResponse.setZoneName(template.getDataCenterName()); + } + + // set details map + if (template.getDetailName() != null){ + Map details = new HashMap(); + details.put(template.getDetailName(), template.getDetailValue()); + templateResponse.setDetails(details); + } + + // update tag information + long tag_id = template.getTagId(); + if (tag_id > 0) { + ResourceTagJoinVO vtag = ApiDBUtils.findResourceTagViewById(tag_id); + if ( vtag != null ){ + templateResponse.addTag(ApiDBUtils.newResourceTagResponse(vtag, false)); + } + } + + + templateResponse.setObjectName("template"); + return templateResponse; + } + + + //TODO: This is to keep compatibility with 4.1 API, where updateTemplateCmd and updateIsoCmd will return a simpler TemplateResponse + // compared to listTemplates and listIsos. + @Override + public TemplateResponse newUpdateResponse(TemplateJoinVO result) { + TemplateResponse response = new TemplateResponse(); + response.setId(result.getUuid()); + response.setName(result.getName()); + response.setDisplayText(result.getDisplayText()); + response.setPublic(result.isPublicTemplate()); + response.setCreated(result.getCreated()); + response.setFormat(result.getFormat()); + response.setOsTypeId(result.getGuestOSUuid()); + response.setOsTypeName(result.getGuestOSName()); + response.setBootable(result.isBootable()); + response.setHypervisor(result.getHypervisorType().toString()); + + // populate owner. + ApiResponseHelper.populateOwner(response, result); + + // populate domain + response.setDomainId(result.getDomainUuid()); + response.setDomainName(result.getDomainName()); + + // set details map + if (result.getDetailName() != null) { + Map details = new HashMap(); + details.put(result.getDetailName(), result.getDetailValue()); + response.setDetails(details); + } + + // update tag information + long tag_id = result.getTagId(); + if (tag_id > 0) { + ResourceTagJoinVO vtag = ApiDBUtils.findResourceTagViewById(tag_id); + if (vtag != null) { + response.addTag(ApiDBUtils.newResourceTagResponse(vtag, false)); + } + } + + response.setObjectName("iso"); + return response; + } + + + + + @Override + public TemplateResponse setTemplateResponse(TemplateResponse templateResponse, TemplateJoinVO template) { + + // update template zone information + if (template.getDataCenterId() > 0 ){ + TemplateZoneResponse tmplZoneResp = new TemplateZoneResponse(template.getDataCenterUuid(), template.getDataCenterName()); + templateResponse.addZone(tmplZoneResp); + if (templateResponse.getZoneId() == null) { + // set the first found associated zone directly in + // TemplateResponse + templateResponse.setZoneId(template.getDataCenterUuid()); + templateResponse.setZoneName(template.getDataCenterName()); + } + } + + // update details map + if (template.getDetailName() != null){ + Map details = templateResponse.getDetails(); + if ( details == null ){ + details = new HashMap(); + } + details.put(template.getDetailName(), template.getDetailValue()); + templateResponse.setDetails(details); + } + + // update tag information + long tag_id = template.getTagId(); + if (tag_id > 0) { + ResourceTagJoinVO vtag = ApiDBUtils.findResourceTagViewById(tag_id); + if ( vtag != null ){ + templateResponse.addTag(ApiDBUtils.newResourceTagResponse(vtag, false)); + } + } + + return templateResponse; + } + + + @Override + public TemplateResponse newIsoResponse(TemplateJoinVO iso) { + + TemplateResponse isoResponse = new TemplateResponse(); + isoResponse.setId(iso.getUuid()); + isoResponse.setName(iso.getName()); + isoResponse.setDisplayText(iso.getDisplayText()); + isoResponse.setPublic(iso.isPublicTemplate()); + isoResponse.setExtractable(iso.isExtractable() && !(iso.getTemplateType() == TemplateType.PERHOST)); + isoResponse.setCreated(iso.getCreatedOnStore()); + if ( iso.getTemplateType() == TemplateType.PERHOST ){ + // for xs-tools.iso and vmware-tools.iso, we didn't download, but is ready to use. + isoResponse.setReady(true); + } + else{ + isoResponse.setReady(iso.getState() == ObjectInDataStoreStateMachine.State.Ready); + } + isoResponse.setBootable(iso.isBootable()); + isoResponse.setFeatured(iso.isFeatured()); + isoResponse.setCrossZones(iso.isCrossZones()); + isoResponse.setPublic(iso.isPublicTemplate()); + isoResponse.setChecksum(iso.getChecksum()); + + isoResponse.setOsTypeId(iso.getGuestOSUuid()); + isoResponse.setOsTypeName(iso.getGuestOSName()); + + // populate owner. + ApiResponseHelper.populateOwner(isoResponse, iso); + + // populate domain + isoResponse.setDomainId(iso.getDomainUuid()); + isoResponse.setDomainName(iso.getDomainName()); + + // set template zone information + if (iso.getDataCenterId() > 0 ){ + TemplateZoneResponse tmplZoneResp = new TemplateZoneResponse(iso.getDataCenterUuid(), iso.getDataCenterName()); + isoResponse.addZone(tmplZoneResp); + // set the first found associated zone directly in TemplateResponse + isoResponse.setZoneId(iso.getDataCenterUuid()); + isoResponse.setZoneName(iso.getDataCenterName()); + } + + + Account caller = UserContext.current().getCaller(); + boolean isAdmin = false; + if ((caller == null) || BaseCmd.isAdmin(caller.getType())) { + isAdmin = true; + } + + + // If the user is an admin, add the template download status + if (isAdmin || caller.getId() == iso.getAccountId()) { + // add download status + if (iso.getDownloadState() != Status.DOWNLOADED) { + String isoStatus = "Processing"; + if (iso.getDownloadState() == VMTemplateHostVO.Status.DOWNLOADED) { + isoStatus = "Download Complete"; + } else if (iso.getDownloadState() == VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS) { + if (iso.getDownloadPercent() == 100) { + isoStatus = "Installing ISO"; + } else { + isoStatus = iso.getDownloadPercent() + "% Downloaded"; + } + } else { + isoStatus = iso.getErrorString(); + } + isoResponse.setStatus(isoStatus); + } else { + isoResponse.setStatus("Successfully Installed"); + } + } + + Long isoSize = iso.getSize(); + if (isoSize > 0) { + isoResponse.setSize(isoSize); + } + + // update tag information + long tag_id = iso.getTagId(); + if (tag_id > 0) { + ResourceTagJoinVO vtag = ApiDBUtils.findResourceTagViewById(tag_id); + if ( vtag != null ){ + isoResponse.addTag(ApiDBUtils.newResourceTagResponse(vtag, false)); + } + } + + isoResponse.setObjectName("iso"); + return isoResponse; + + } + + @Override + public List newTemplateView(VirtualMachineTemplate template) { + SearchCriteria sc = tmpltIdSearch.create(); + sc.setParameters("id", template.getId()); + return searchIncludingRemoved(sc, null, null, false); + } + + @Override + public List newTemplateView(VirtualMachineTemplate template, long zoneId, boolean readyOnly) { + SearchCriteria sc = tmpltZoneSearch.create(); + sc.setParameters("id", template.getId()); + sc.setParameters("dataCenterId", zoneId); + if ( readyOnly ){ + sc.setParameters("state", TemplateState.Ready); + } + return searchIncludingRemoved(sc, null, null, false); + } + + + + @Override + public List searchByIds(Long... tmplIds) { + // set detail batch query size + int DETAILS_BATCH_SIZE = 2000; + String batchCfg = _configDao.getValue("detail.batch.query.size"); + if ( batchCfg != null ){ + DETAILS_BATCH_SIZE = Integer.parseInt(batchCfg); + } + // query details by batches + List uvList = new ArrayList(); + // query details by batches + int curr_index = 0; + if ( tmplIds.length > DETAILS_BATCH_SIZE ){ + while ( (curr_index + DETAILS_BATCH_SIZE ) <= tmplIds.length ) { + Long[] ids = new Long[DETAILS_BATCH_SIZE]; + for (int k = 0, j = curr_index; j < curr_index + DETAILS_BATCH_SIZE; j++, k++) { + ids[k] = tmplIds[j]; + } + SearchCriteria sc = tmpltSearch.create(); + sc.setParameters("idIN", ids); + List vms = searchIncludingRemoved(sc, null, null, false); + if (vms != null) { + uvList.addAll(vms); + } + curr_index += DETAILS_BATCH_SIZE; + } + } + if (curr_index < tmplIds.length) { + int batch_size = (tmplIds.length - curr_index); + // set the ids value + Long[] ids = new Long[batch_size]; + for (int k = 0, j = curr_index; j < curr_index + batch_size; j++, k++) { + ids[k] = tmplIds[j]; + } + SearchCriteria sc = tmpltSearch.create(); + sc.setParameters("idIN", ids); + List vms = searchIncludingRemoved(sc, null, null, false); + if (vms != null) { + uvList.addAll(vms); + } + } + return uvList; + } + + + + + @Override + public List listActiveTemplates(long storeId) { + SearchCriteria sc = activeTmpltSearch.create(); + sc.setParameters("store_id", storeId); + sc.setParameters("type", TemplateType.USER); + return searchIncludingRemoved(sc, null, null, false); + } + + + +} diff --git a/server/src/com/cloud/api/query/dao/UserVmJoinDao.java b/server/src/com/cloud/api/query/dao/UserVmJoinDao.java index 2617a7475ef..bfff83982b4 100644 --- a/server/src/com/cloud/api/query/dao/UserVmJoinDao.java +++ b/server/src/com/cloud/api/query/dao/UserVmJoinDao.java @@ -36,4 +36,6 @@ public interface UserVmJoinDao extends GenericDao { List newUserVmView(UserVm... userVms); List searchByIds(Long... ids); + + List listActiveByIsoId(Long isoId); } diff --git a/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java index 64c4b207b3a..028083406fd 100644 --- a/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java @@ -43,7 +43,9 @@ import com.cloud.uservm.UserVm; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; +import com.cloud.vm.UserVmVO; import com.cloud.vm.VmStats; +import com.cloud.vm.VirtualMachine.State; @Component @@ -55,6 +57,7 @@ public class UserVmJoinDaoImpl extends GenericDaoBase implem private ConfigurationDao _configDao; private final SearchBuilder VmDetailSearch; + private final SearchBuilder activeVmByIsoSearch; protected UserVmJoinDaoImpl() { @@ -64,9 +67,24 @@ public class UserVmJoinDaoImpl extends GenericDaoBase implem this._count = "select count(distinct id) from user_vm_view WHERE "; - + activeVmByIsoSearch = createSearchBuilder(); + activeVmByIsoSearch.and("isoId", activeVmByIsoSearch.entity().getIsoId(), SearchCriteria.Op.EQ); + activeVmByIsoSearch.and("stateNotIn", activeVmByIsoSearch.entity().getState(), SearchCriteria.Op.NIN); + activeVmByIsoSearch.done(); } + + @Override + public List listActiveByIsoId(Long isoId) { + SearchCriteria sc = activeVmByIsoSearch.create(); + sc.setParameters("isoId", isoId); + State[] states = new State[2]; + states[0] = State.Error; + states[1] = State.Expunging; + return listBy(sc); + } + + @Override public UserVmResponse newUserVmResponse(String objectName, UserVmJoinVO userVm, EnumSet details, Account caller) { UserVmResponse userVmResponse = new UserVmResponse(); diff --git a/server/src/com/cloud/api/query/vo/ImageStoreJoinVO.java b/server/src/com/cloud/api/query/vo/ImageStoreJoinVO.java new file mode 100644 index 00000000000..ac161afe47d --- /dev/null +++ b/server/src/com/cloud/api/query/vo/ImageStoreJoinVO.java @@ -0,0 +1,207 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.api.query.vo; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.Id; +import javax.persistence.Table; + +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ImageStore; +import com.cloud.storage.ScopeType; +import com.cloud.utils.db.GenericDao; + +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +/** + * Image Data Store DB view. + * + */ +@Entity +@Table(name="image_store_view") +public class ImageStoreJoinVO extends BaseViewVO implements InternalIdentity, Identity { + + @Id + @Column(name="id") + private long id; + + @Column(name="uuid") + private String uuid; + + @Column(name="name") + private String name; + + @Column(name="url") + private String url; + + @Column(name = "protocol") + private String protocol; + + @Column(name = "image_provider_name", nullable = false) + private String providerName; + + @Column(name="scope") + @Enumerated(value = EnumType.STRING) + private ScopeType scope; + + @Column(name = "role") + @Enumerated(value = EnumType.STRING) + private DataStoreRole role; + + @Column(name="data_center_id") + private long zoneId; + + @Column(name="data_center_uuid") + private String zoneUuid; + + @Column(name="data_center_name") + private String zoneName; + + @Column(name="detail_name") + private String detailName; + + @Column(name="detail_value") + private String detailValue; + + @Column(name=GenericDao.REMOVED_COLUMN) + private Date removed; + + @Override + public long getId() { + return id; + } + + @Override + public void setId(long id) { + this.id = id; + } + + @Override + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getName() { + return name; + } + + + + public long getZoneId() { + return zoneId; + } + + public void setZoneId(long zoneId) { + this.zoneId = zoneId; + } + + public String getZoneUuid() { + return zoneUuid; + } + + public void setZoneUuid(String zoneUuid) { + this.zoneUuid = zoneUuid; + } + + public String getZoneName() { + return zoneName; + } + + public void setZoneName(String zoneName) { + this.zoneName = zoneName; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public String getProviderName() { + return providerName; + } + + public void setProviderName(String providerName) { + this.providerName = providerName; + } + + public ScopeType getScope() { + return scope; + } + + public void setScope(ScopeType scope) { + this.scope = scope; + } + + public void setName(String name) { + this.name = name; + } + + public String getDetailName() { + return detailName; + } + + public void setDetailName(String detailName) { + this.detailName = detailName; + } + + public String getDetailValue() { + return detailValue; + } + + public void setDetailValue(String detailValue) { + this.detailValue = detailValue; + } + + public DataStoreRole getRole() { + return role; + } + + public void setRole(DataStoreRole role) { + this.role = role; + } + + public Date getRemoved() { + return removed; + } + + public void setRemoved(Date removed) { + this.removed = removed; + } + + +} diff --git a/server/src/com/cloud/api/query/vo/StoragePoolJoinVO.java b/server/src/com/cloud/api/query/vo/StoragePoolJoinVO.java index f35096a5219..c0d5ee990a5 100644 --- a/server/src/com/cloud/api/query/vo/StoragePoolJoinVO.java +++ b/server/src/com/cloud/api/query/vo/StoragePoolJoinVO.java @@ -24,16 +24,17 @@ import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.Id; import javax.persistence.Table; +import com.cloud.org.Cluster; +import com.cloud.storage.ScopeType; +import com.cloud.storage.StoragePoolStatus; +import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.utils.db.GenericDao; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; + import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.org.Cluster; -import com.cloud.storage.Storage.StoragePoolType; -import com.cloud.storage.StoragePoolStatus; -import com.cloud.utils.db.GenericDao; /** * Storage Pool DB view. diff --git a/server/src/com/cloud/api/query/vo/TemplateJoinVO.java b/server/src/com/cloud/api/query/vo/TemplateJoinVO.java new file mode 100644 index 00000000000..03dce9943b5 --- /dev/null +++ b/server/src/com/cloud/api/query/vo/TemplateJoinVO.java @@ -0,0 +1,1030 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.api.query.vo; + +import java.util.Date; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.server.ResourceTag.TaggedResourceType; +import com.cloud.storage.Storage; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.utils.db.GenericDao; + +@Entity +@Table(name="template_view") +public class TemplateJoinVO extends BaseViewVO implements ControlledViewEntity { + + @Id + @Column(name="id") + private long id; + + @Column(name="uuid") + private String uuid; + + @Column(name="unique_name") + private String uniqueName; + + @Column(name="name") + private String name; + + @Column(name="format") + private Storage.ImageFormat format; + + @Column(name="public") + private boolean publicTemplate = true; + + @Column(name="featured") + private boolean featured; + + @Column(name="type") + private Storage.TemplateType templateType; + + @Column(name="url") + private String url = null; + + @Column(name="hvm") + private boolean requiresHvm; + + @Column(name="bits") + private int bits; + + @Temporal(value=TemporalType.TIMESTAMP) + @Column(name=GenericDao.CREATED_COLUMN) + private Date created = null; + + @Temporal(value=TemporalType.TIMESTAMP) + @Column(name="created_on_store") + private Date createdOnStore = null; + + @Column(name=GenericDao.REMOVED_COLUMN) + @Temporal(TemporalType.TIMESTAMP) + private Date removed; + + @Column(name="checksum") + private String checksum; + + @Column(name="display_text", length=4096) + private String displayText; + + @Column(name="enable_password") + private boolean enablePassword; + + @Column(name="guest_os_id") + private long guestOSId; + + @Column(name="guest_os_uuid") + private String guestOSUuid; + + @Column(name="guest_os_name") + private String guestOSName; + + @Column(name="bootable") + private boolean bootable = true; + + @Column(name="prepopulate") + private boolean prepopulate = false; + + @Column(name="cross_zones") + private boolean crossZones = false; + + @Column(name="hypervisor_type") + @Enumerated(value=EnumType.STRING) + private HypervisorType hypervisorType; + + @Column(name="extractable") + private boolean extractable = true; + + @Column(name="source_template_id") + private Long sourceTemplateId; + + @Column(name="source_template_uuid") + private String sourceTemplateUuid; + + + @Column(name="template_tag") + private String templateTag; + + @Column(name="sort_key") + private int sortKey; + + @Column(name="enable_sshkey") + private boolean enableSshKey; + + @Column(name="account_id") + private long accountId; + + @Column(name="account_uuid") + private String accountUuid; + + @Column(name="account_name") + private String accountName = null; + + @Column(name="account_type") + private short accountType; + + @Column(name="domain_id") + private long domainId; + + @Column(name="domain_uuid") + private String domainUuid; + + @Column(name="domain_name") + private String domainName = null; + + @Column(name="domain_path") + private String domainPath = null; + + @Column(name="project_id") + private long projectId; + + @Column(name="project_uuid") + private String projectUuid; + + @Column(name="project_name") + private String projectName; + + @Column(name="data_center_id") + private long dataCenterId; + + @Column(name="data_center_uuid") + private String dataCenterUuid; + + @Column(name="data_center_name") + private String dataCenterName; + + @Column(name="store_id") + private Long dataStoreId; // this can be null for baremetal templates + + @Column (name="download_state") + @Enumerated(EnumType.STRING) + private Status downloadState; + + @Column (name="download_pct") + private int downloadPercent; + + @Column (name="error_str") + private String errorString; + + @Column (name="size") + private long size; + + @Column(name="destroyed") + boolean destroyed = false; + + @Column(name="lp_account_id") + private Long sharedAccountId; + + @Column(name="detail_name") + private String detailName; + + @Column(name="detail_value") + private String detailValue; + + + @Column(name="tag_id") + private long tagId; + + @Column(name="tag_uuid") + private String tagUuid; + + @Column(name="tag_key") + private String tagKey; + + @Column(name="tag_value") + private String tagValue; + + @Column(name="tag_domain_id") + private long tagDomainId; + + @Column(name="tag_account_id") + private long tagAccountId; + + @Column(name="tag_resource_id") + private long tagResourceId; + + @Column(name="tag_resource_uuid") + private String tagResourceUuid; + + @Column(name="tag_resource_type") + @Enumerated(value=EnumType.STRING) + private TaggedResourceType tagResourceType; + + @Column(name="tag_customer") + private String tagCustomer; + + @Column(name = "state") + @Enumerated(EnumType.STRING) + ObjectInDataStoreStateMachine.State state; + + public TemplateJoinVO() { + } + + + + @Override + public long getId() { + return id; + } + + + + @Override + public void setId(long id) { + this.id = id; + } + + + + @Override + public String getUuid() { + return uuid; + } + + + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + + + public String getName() { + return name; + } + + + + public void setName(String name) { + this.name = name; + } + + + public Date getCreated() { + return created; + } + + + + public void setCreated(Date created) { + this.created = created; + } + + + + public Date getRemoved() { + return removed; + } + + + + public void setRemoved(Date removed) { + this.removed = removed; + } + + + + @Override + public long getAccountId() { + return accountId; + } + + + + public void setAccountId(long accountId) { + this.accountId = accountId; + } + + + + @Override + public String getAccountUuid() { + return accountUuid; + } + + + + public void setAccountUuid(String accountUuid) { + this.accountUuid = accountUuid; + } + + + + @Override + public String getAccountName() { + return accountName; + } + + + + public void setAccountName(String accountName) { + this.accountName = accountName; + } + + + + @Override + public short getAccountType() { + return accountType; + } + + + + public void setAccountType(short accountType) { + this.accountType = accountType; + } + + + + @Override + public long getDomainId() { + return domainId; + } + + + + public void setDomainId(long domainId) { + this.domainId = domainId; + } + + + + @Override + public String getDomainUuid() { + return domainUuid; + } + + + + public void setDomainUuid(String domainUuid) { + this.domainUuid = domainUuid; + } + + + + @Override + public String getDomainName() { + return domainName; + } + + + + public void setDomainName(String domainName) { + this.domainName = domainName; + } + + + + @Override + public String getDomainPath() { + return domainPath; + } + + + + public void setDomainPath(String domainPath) { + this.domainPath = domainPath; + } + + + + public long getProjectId() { + return projectId; + } + + + + public void setProjectId(long projectId) { + this.projectId = projectId; + } + + + + @Override + public String getProjectUuid() { + return projectUuid; + } + + + + public void setProjectUuid(String projectUuid) { + this.projectUuid = projectUuid; + } + + + + @Override + public String getProjectName() { + return projectName; + } + + + + public void setProjectName(String projectName) { + this.projectName = projectName; + } + + + + + public boolean isExtractable() { + return extractable; + } + + + + public void setExtractable(boolean extractable) { + this.extractable = extractable; + } + + + + public Storage.TemplateType getTemplateType() { + return templateType; + } + + + + public void setTemplateType(Storage.TemplateType templateType) { + this.templateType = templateType; + } + + + + + + + public long getTagId() { + return tagId; + } + + + + public void setTagId(long tagId) { + this.tagId = tagId; + } + + + + public String getTagUuid() { + return tagUuid; + } + + + + public void setTagUuid(String tagUuid) { + this.tagUuid = tagUuid; + } + + + + public String getTagKey() { + return tagKey; + } + + + + public void setTagKey(String tagKey) { + this.tagKey = tagKey; + } + + + + public String getTagValue() { + return tagValue; + } + + + + public void setTagValue(String tagValue) { + this.tagValue = tagValue; + } + + + + public long getTagDomainId() { + return tagDomainId; + } + + + + public void setTagDomainId(long tagDomainId) { + this.tagDomainId = tagDomainId; + } + + + + public long getTagAccountId() { + return tagAccountId; + } + + + + public void setTagAccountId(long tagAccountId) { + this.tagAccountId = tagAccountId; + } + + + + public long getTagResourceId() { + return tagResourceId; + } + + + + public void setTagResourceId(long tagResourceId) { + this.tagResourceId = tagResourceId; + } + + + + public String getTagResourceUuid() { + return tagResourceUuid; + } + + + + public void setTagResourceUuid(String tagResourceUuid) { + this.tagResourceUuid = tagResourceUuid; + } + + + + public TaggedResourceType getTagResourceType() { + return tagResourceType; + } + + + + public void setTagResourceType(TaggedResourceType tagResourceType) { + this.tagResourceType = tagResourceType; + } + + + + public String getTagCustomer() { + return tagCustomer; + } + + + + public void setTagCustomer(String tagCustomer) { + this.tagCustomer = tagCustomer; + } + + + + public long getDataCenterId() { + return dataCenterId; + } + + + + public void setDataCenterId(long dataCenterId) { + this.dataCenterId = dataCenterId; + } + + + + public String getDataCenterUuid() { + return dataCenterUuid; + } + + + + public void setDataCenterUuid(String dataCenterUuid) { + this.dataCenterUuid = dataCenterUuid; + } + + + + public String getDataCenterName() { + return dataCenterName; + } + + + + public void setDataCenterName(String dataCenterName) { + this.dataCenterName = dataCenterName; + } + + + + public String getUniqueName() { + return uniqueName; + } + + + + public void setUniqueName(String uniqueName) { + this.uniqueName = uniqueName; + } + + + + public boolean isPublicTemplate() { + return publicTemplate; + } + + + + public void setPublicTemplate(boolean publicTemplate) { + this.publicTemplate = publicTemplate; + } + + + + public boolean isFeatured() { + return featured; + } + + + + public void setFeatured(boolean featured) { + this.featured = featured; + } + + + + public String getUrl() { + return url; + } + + + + public void setUrl(String url) { + this.url = url; + } + + + + public boolean isRequiresHvm() { + return requiresHvm; + } + + + + public void setRequiresHvm(boolean requiresHvm) { + this.requiresHvm = requiresHvm; + } + + + + public int getBits() { + return bits; + } + + + + public void setBits(int bits) { + this.bits = bits; + } + + + + public String getChecksum() { + return checksum; + } + + + + public void setChecksum(String checksum) { + this.checksum = checksum; + } + + + + public String getDisplayText() { + return displayText; + } + + + + public void setDisplayText(String displayText) { + this.displayText = displayText; + } + + + + public boolean isEnablePassword() { + return enablePassword; + } + + + + public void setEnablePassword(boolean enablePassword) { + this.enablePassword = enablePassword; + } + + + + public long getGuestOSId() { + return guestOSId; + } + + + + public void setGuestOSId(long guestOSId) { + this.guestOSId = guestOSId; + } + + + + public String getGuestOSUuid() { + return guestOSUuid; + } + + + + public void setGuestOSUuid(String guestOSUuid) { + this.guestOSUuid = guestOSUuid; + } + + + + public String getGuestOSName() { + return guestOSName; + } + + + + public void setGuestOSName(String guestOSName) { + this.guestOSName = guestOSName; + } + + + + public boolean isBootable() { + return bootable; + } + + + + public void setBootable(boolean bootable) { + this.bootable = bootable; + } + + + + public boolean isPrepopulate() { + return prepopulate; + } + + + + public void setPrepopulate(boolean prepopulate) { + this.prepopulate = prepopulate; + } + + + + public boolean isCrossZones() { + return crossZones; + } + + + + public void setCrossZones(boolean crossZones) { + this.crossZones = crossZones; + } + + + + public HypervisorType getHypervisorType() { + return hypervisorType; + } + + + + public void setHypervisorType(HypervisorType hypervisorType) { + this.hypervisorType = hypervisorType; + } + + + + public Long getSourceTemplateId() { + return sourceTemplateId; + } + + + + public void setSourceTemplateId(Long sourceTemplateId) { + this.sourceTemplateId = sourceTemplateId; + } + + + + public String getSourceTemplateUuid() { + return sourceTemplateUuid; + } + + + + public void setSourceTemplateUuid(String sourceTemplateUuid) { + this.sourceTemplateUuid = sourceTemplateUuid; + } + + + + public String getTemplateTag() { + return templateTag; + } + + + + public void setTemplateTag(String templateTag) { + this.templateTag = templateTag; + } + + + + public int getSortKey() { + return sortKey; + } + + + + public void setSortKey(int sortKey) { + this.sortKey = sortKey; + } + + + + public boolean isEnableSshKey() { + return enableSshKey; + } + + + + public void setEnableSshKey(boolean enableSshKey) { + this.enableSshKey = enableSshKey; + } + + + + public Status getDownloadState() { + return downloadState; + } + + + + public void setDownloadState(Status downloadState) { + this.downloadState = downloadState; + } + + + + public long getSize() { + return size; + } + + + + public void setSize(long size) { + this.size = size; + } + + + + public boolean isDestroyed() { + return destroyed; + } + + + + public void setDestroyed(boolean destroyed) { + this.destroyed = destroyed; + } + + + + public Long getSharedAccountId() { + return sharedAccountId; + } + + + + public void setSharedAccountId(Long sharedAccountId) { + this.sharedAccountId = sharedAccountId; + } + + + + public String getDetailName() { + return detailName; + } + + + + public void setDetailName(String detailName) { + this.detailName = detailName; + } + + + + public String getDetailValue() { + return detailValue; + } + + + + public void setDetailValue(String detailValue) { + this.detailValue = detailValue; + } + + + + public Date getCreatedOnStore() { + return createdOnStore; + } + + + + public void setCreatedOnStore(Date createdOnStore) { + this.createdOnStore = createdOnStore; + } + + + + public Storage.ImageFormat getFormat() { + return format; + } + + + + public void setFormat(Storage.ImageFormat format) { + this.format = format; + } + + + + public int getDownloadPercent() { + return downloadPercent; + } + + + + public void setDownloadPercent(int downloadPercent) { + this.downloadPercent = downloadPercent; + } + + + + public String getErrorString() { + return errorString; + } + + + + public void setErrorString(String errorString) { + this.errorString = errorString; + } + + + + public Long getDataStoreId() { + return dataStoreId; + } + + + + public void setDataStoreId(Long dataStoreId) { + this.dataStoreId = dataStoreId; + } + + + + public ObjectInDataStoreStateMachine.State getState() { + return state; + } + + + + public void setState(ObjectInDataStoreStateMachine.State state) { + this.state = state; + } + + +} diff --git a/server/src/com/cloud/capacity/CapacityManager.java b/server/src/com/cloud/capacity/CapacityManager.java index bdd9ccd155b..ab02e77ac19 100755 --- a/server/src/com/cloud/capacity/CapacityManager.java +++ b/server/src/com/cloud/capacity/CapacityManager.java @@ -18,6 +18,7 @@ package com.cloud.capacity; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.storage.VMTemplateVO; import com.cloud.utils.component.Manager; @@ -41,7 +42,7 @@ public interface CapacityManager extends Manager { */ boolean checkIfHostHasCapacity(long hostId, Integer cpu, long ram, boolean checkFromReservedCapacity, float cpuOverprovisioningFactor, float memoryOvercommitRatio, boolean considerReservedCapacity); - void updateCapacityForHost(HostVO host); + void updateCapacityForHost(Host host); /** * @param pool storage pool diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java index e58ae4079bc..7a94c780706 100755 --- a/server/src/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java @@ -179,7 +179,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, CapacityVO capacityMemory = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_MEMORY); Long clusterId = null; if (hostId != null) { - HostVO host = _hostDao.findById(hostId); + HostVO host = _hostDao.findById(hostId); clusterId = host.getClusterId(); } if (capacityCpu == null || capacityMemory == null || svo == null) { @@ -530,7 +530,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, @DB @Override - public void updateCapacityForHost(HostVO host){ + public void updateCapacityForHost(Host host){ // prepare the service offerings List offerings = _offeringsDao.listAllIncludingRemoved(); Map offeringsMap = new HashMap(); @@ -819,7 +819,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, } @Override - public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { + public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { // TODO Auto-generated method stub } diff --git a/server/src/com/cloud/capacity/ComputeCapacityListener.java b/server/src/com/cloud/capacity/ComputeCapacityListener.java index 16e154a80a6..7ca8fd74409 100755 --- a/server/src/com/cloud/capacity/ComputeCapacityListener.java +++ b/server/src/com/cloud/capacity/ComputeCapacityListener.java @@ -29,7 +29,7 @@ import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; import com.cloud.capacity.dao.CapacityDao; import com.cloud.exception.ConnectionException; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.host.Status; import com.cloud.utils.db.SearchCriteria; @@ -71,7 +71,7 @@ public class ComputeCapacityListener implements Listener { @Override - public void processConnect(HostVO server, StartupCommand startup, boolean forRebalance) throws ConnectionException { + public void processConnect(Host server, StartupCommand startup, boolean forRebalance) throws ConnectionException { if (!(startup instanceof StartupRoutingCommand)) { return; } diff --git a/server/src/com/cloud/capacity/StorageCapacityListener.java b/server/src/com/cloud/capacity/StorageCapacityListener.java index bc03f725e78..2d63a269053 100755 --- a/server/src/com/cloud/capacity/StorageCapacityListener.java +++ b/server/src/com/cloud/capacity/StorageCapacityListener.java @@ -32,7 +32,7 @@ import com.cloud.agent.api.StartupStorageCommand; import com.cloud.capacity.dao.CapacityDao; import com.cloud.capacity.dao.CapacityDaoImpl; import com.cloud.exception.ConnectionException; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.host.Status; import com.cloud.storage.Storage; import com.cloud.utils.db.SearchCriteria; @@ -70,7 +70,7 @@ public class StorageCapacityListener implements Listener { @Override - public void processConnect(HostVO server, StartupCommand startup, boolean forRebalance) throws ConnectionException { + public void processConnect(Host server, StartupCommand startup, boolean forRebalance) throws ConnectionException { if (!(startup instanceof StartupStorageCommand)) { return; diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index 3c73783792c..f14a76cb111 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -72,7 +72,10 @@ public enum Config { StorageOverprovisioningFactor("Storage", StoragePoolAllocator.class, String.class, "storage.overprovisioning.factor", "2", "Used for storage overprovisioning calculation; available storage will be (actualStorageSize * storage.overprovisioning.factor)", null, ConfigurationParameterScope.zone.toString()), StorageStatsInterval("Storage", ManagementServer.class, String.class, "storage.stats.interval", "60000", "The interval (in milliseconds) when storage stats (per host) are retrieved from agents.", null), MaxVolumeSize("Storage", ManagementServer.class, Integer.class, "storage.max.volume.size", "2000", "The maximum size for a volume (in GB).", null), - MaxUploadVolumeSize("Storage", ManagementServer.class, Integer.class, "storage.max.volume.upload.size", "500", "The maximum size for a uploaded volume(in GB).", null), + StorageCacheReplacementLRUTimeInterval("Storage", ManagementServer.class, Integer.class, "storage.cache.replacement.lru.interval", "30", "time interval for unsed data on cache storage (in days).", null), + StorageCacheReplacementEnabled("Storage", ManagementServer.class, Boolean.class, "storage.cache.replacement.enabled", "true", "enable or disable cache storage replacement algorithm.", null), + StorageCacheReplacementInterval("Storage", ManagementServer.class, Integer.class, "storage.cache.replacement.interval", "86400", "time interval between cache replacement threads (in seconds).", null), + MaxUploadVolumeSize("Storage", ManagementServer.class, Integer.class, "storage.max.volume.upload.size", "500", "The maximum size for a uploaded volume(in GB).", null), TotalRetries("Storage", AgentManager.class, Integer.class, "total.retries", "4", "The number of times each command sent to a host should be retried in case of failure.", null), StoragePoolMaxWaitSeconds("Storage", ManagementServer.class, Integer.class, "storage.pool.max.waitseconds", "3600", "Timeout (in seconds) to synchronize storage pool operations.", null), StorageTemplateCleanupEnabled("Storage", ManagementServer.class, Boolean.class, "storage.template.cleanup.enabled", "true", "Enable/disable template cleanup activity, only take effect when overall storage cleanup is enabled", null), @@ -141,7 +144,7 @@ public enum Config { SnapshotPollInterval("Snapshots", SnapshotManager.class, Integer.class, "snapshot.poll.interval", "300", "The time interval in seconds when the management server polls for snapshots to be scheduled.", null), SnapshotDeltaMax("Snapshots", SnapshotManager.class, Integer.class, "snapshot.delta.max", "16", "max delta snapshots between two full snapshots.", null), BackupSnapshotAferTakingSnapshot("Snapshots", SnapshotManager.class, Boolean.class, "snapshot.backup.rightafter", "true", "backup snapshot right after snapshot is taken", null), - + // Advanced JobExpireMinutes("Advanced", ManagementServer.class, String.class, "job.expire.minutes", "1440", "Time (in minutes) for async-jobs to be kept in system", null), JobCancelThresholdMinutes("Advanced", ManagementServer.class, String.class, "job.cancel.threshold.minutes", "60", "Time (in minutes) for async-jobs to be forcely cancelled if it has been in process for long", null), @@ -416,13 +419,15 @@ public enum Config { ApiLimitMax("Advanced", ManagementServer.class, Integer.class, "api.throttling.max", "25", "Max allowed number of APIs within fixed interval", null), ApiLimitCacheSize("Advanced", ManagementServer.class, Integer.class, "api.throttling.cachesize", "50000", "Account based API count cache size", null), - + // object store + S3EnableRRS("Advanced", ManagementServer.class, Boolean.class, "s3.rrs.enabled", "false", "enable s3 reduced redundancy storage", null), + // VMSnapshots VMSnapshotMax("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.max", "10", "Maximum vm snapshots for a vm", null), VMSnapshotCreateWait("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.create.wait", "1800", "In second, timeout for create vm snapshot", null), CloudDnsName("Advanced", ManagementServer.class, String.class, "cloud.dns.name", null, "DNS name of the cloud for the GSLB service", null), - + BlacklistedRoutes("Advanced", VpcManager.class, String.class, "blacklisted.routes", null, "Routes that are blacklisted, can not be used for Static Routes creation for the VPC Private Gateway", "routes", ConfigurationParameterScope.zone.toString()), diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 13c821e216d..f7440c0e715 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -66,6 +66,8 @@ import org.apache.cloudstack.api.command.admin.zone.CreateZoneCmd; import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd; import org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd; import org.apache.cloudstack.api.command.user.network.ListNetworkOfferingsCmd; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.region.PortableIp; import org.apache.cloudstack.region.PortableIpDao; import org.apache.cloudstack.region.PortableIpRange; @@ -127,7 +129,6 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; -import com.cloud.host.HostVO; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.IpAddress; import com.cloud.network.Network; @@ -178,7 +179,6 @@ import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.S3Dao; import com.cloud.storage.dao.SwiftDao; import com.cloud.storage.s3.S3Manager; -import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.storage.swift.SwiftManager; import com.cloud.test.IPRangeConfig; import com.cloud.user.Account; @@ -273,7 +273,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Inject ProjectManager _projectMgr; @Inject - SecondaryStorageVmManager _ssvmMgr; + DataStoreManager _dataStoreMgr; @Inject NetworkOfferingServiceMapDao _ntwkOffServiceMapDao; @Inject @@ -318,7 +318,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati DedicatedResourceDao _dedicatedDao; // FIXME - why don't we have interface for DataCenterLinkLocalIpAddressDao? - @Inject protected DataCenterLinkLocalIpAddressDao _LinkLocalIpAllocDao; + @Inject + protected DataCenterLinkLocalIpAddressDao _LinkLocalIpAllocDao; private int _maxVolumeSizeInGb = Integer.parseInt(Config.MaxVolumeSize.getDefaultValue()); private long _defaultPageSize = Long.parseLong(Config.DefaultPageSize.getDefaultValue()); @@ -328,11 +329,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati public boolean configure(final String name, final Map params) throws ConfigurationException { String maxVolumeSizeInGbString = _configDao.getValue(Config.MaxVolumeSize.key()); _maxVolumeSizeInGb = NumbersUtil.parseInt(maxVolumeSizeInGbString, - Integer.parseInt(Config.MaxVolumeSize.getDefaultValue())); + Integer.parseInt(Config.MaxVolumeSize.getDefaultValue())); String defaultPageSizeString = _configDao.getValue(Config.DefaultPageSize.key()); _defaultPageSize = NumbersUtil.parseLong(defaultPageSizeString, - Long.parseLong(Config.DefaultPageSize.getDefaultValue())); + Long.parseLong(Config.DefaultPageSize.getDefaultValue())); populateConfigValuesForValidationSet(); return true; @@ -374,13 +375,22 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (mgtCidr == null || mgtCidr.trim().isEmpty()) { String[] localCidrs = NetUtils.getLocalCidrs(); if (localCidrs.length > 0) { - s_logger.warn("Management network CIDR is not configured originally. Set it default to " + localCidrs[0]); + s_logger.warn("Management network CIDR is not configured originally. Set it default to " + + localCidrs[0]); - _alertMgr.sendAlert(AlertManager.ALERT_TYPE_MANAGMENT_NODE, 0, new Long(0), "Management network CIDR is not configured originally. Set it default to " + localCidrs[0], ""); - _configDao.update(Config.ManagementNetwork.key(), Config.ManagementNetwork.getCategory(), localCidrs[0]); + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_MANAGMENT_NODE, 0, new Long(0), + "Management network CIDR is not configured originally. Set it default to " + localCidrs[0], ""); + _configDao + .update(Config.ManagementNetwork.key(), Config.ManagementNetwork.getCategory(), localCidrs[0]); } else { s_logger.warn("Management network CIDR is not properly configured and we are not able to find a default setting"); - _alertMgr.sendAlert(AlertManager.ALERT_TYPE_MANAGMENT_NODE, 0, new Long(0), "Management network CIDR is not properly configured and we are not able to find a default setting", ""); + _alertMgr + .sendAlert( + AlertManager.ALERT_TYPE_MANAGMENT_NODE, + 0, + new Long(0), + "Management network CIDR is not properly configured and we are not able to find a default setting", + ""); } } @@ -394,7 +404,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Override @DB - public String updateConfiguration(long userId, String name, String category, String value, String scope, Long resourceId) { + public String updateConfiguration(long userId, String name, String category, String value, String scope, + Long resourceId) { String validationMsg = validateConfigurationValue(name, value, scope); @@ -403,62 +414,74 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new InvalidParameterValueException(validationMsg); } - // If scope of the parameter is given then it needs to be updated in the corresponding details table, - // if scope is mentioned as global or not mentioned then it is normal global parameter updation - if (scope != null && !scope.isEmpty() && !Config.ConfigurationParameterScope.global.toString().equalsIgnoreCase(scope)) { + // If scope of the parameter is given then it needs to be updated in the + // corresponding details table, + // if scope is mentioned as global or not mentioned then it is normal + // global parameter updation + if (scope != null && !scope.isEmpty() + && !Config.ConfigurationParameterScope.global.toString().equalsIgnoreCase(scope)) { switch (Config.ConfigurationParameterScope.valueOf(scope)) { - case zone: DataCenterVO zone = _zoneDao.findById(resourceId); - if (zone == null) { - throw new InvalidParameterValueException("unable to find zone by id " + resourceId); - } - DcDetailVO dcDetailVO = _dcDetailsDao.findDetail(resourceId, name.toLowerCase()); - if (dcDetailVO == null) { - dcDetailVO = new DcDetailVO(resourceId, name, value); - _dcDetailsDao.persist(dcDetailVO); - } else { - dcDetailVO.setValue(value); - _dcDetailsDao.update(dcDetailVO.getId(), dcDetailVO); - } break; - case cluster: ClusterVO cluster = _clusterDao.findById(resourceId); - if (cluster == null) { - throw new InvalidParameterValueException("unable to find cluster by id " + resourceId); - } - ClusterDetailsVO clusterDetailsVO = _clusterDetailsDao.findDetail(resourceId, name); - if (clusterDetailsVO == null) { - clusterDetailsVO = new ClusterDetailsVO(resourceId, name, value); - _clusterDetailsDao.persist(clusterDetailsVO); - } else { - clusterDetailsVO.setValue(value); - _clusterDetailsDao.update(clusterDetailsVO.getId(), clusterDetailsVO); - } break; + case zone: + DataCenterVO zone = _zoneDao.findById(resourceId); + if (zone == null) { + throw new InvalidParameterValueException("unable to find zone by id " + resourceId); + } + DcDetailVO dcDetailVO = _dcDetailsDao.findDetail(resourceId, name.toLowerCase()); + if (dcDetailVO == null) { + dcDetailVO = new DcDetailVO(resourceId, name, value); + _dcDetailsDao.persist(dcDetailVO); + } else { + dcDetailVO.setValue(value); + _dcDetailsDao.update(dcDetailVO.getId(), dcDetailVO); + } + break; + case cluster: + ClusterVO cluster = _clusterDao.findById(resourceId); + if (cluster == null) { + throw new InvalidParameterValueException("unable to find cluster by id " + resourceId); + } + ClusterDetailsVO clusterDetailsVO = _clusterDetailsDao.findDetail(resourceId, name); + if (clusterDetailsVO == null) { + clusterDetailsVO = new ClusterDetailsVO(resourceId, name, value); + _clusterDetailsDao.persist(clusterDetailsVO); + } else { + clusterDetailsVO.setValue(value); + _clusterDetailsDao.update(clusterDetailsVO.getId(), clusterDetailsVO); + } + break; - case storagepool: StoragePoolVO pool = _storagePoolDao.findById(resourceId); - if (pool == null) { - throw new InvalidParameterValueException("unable to find storage pool by id " + resourceId); - } - StoragePoolDetailVO storagePoolDetailVO = _storagePoolDetailsDao.findDetail(resourceId, name); - if (storagePoolDetailVO == null) { - storagePoolDetailVO = new StoragePoolDetailVO(resourceId, name, value); - _storagePoolDetailsDao.persist(storagePoolDetailVO); + case storagepool: + StoragePoolVO pool = _storagePoolDao.findById(resourceId); + if (pool == null) { + throw new InvalidParameterValueException("unable to find storage pool by id " + resourceId); + } + StoragePoolDetailVO storagePoolDetailVO = _storagePoolDetailsDao.findDetail(resourceId, name); + if (storagePoolDetailVO == null) { + storagePoolDetailVO = new StoragePoolDetailVO(resourceId, name, value); + _storagePoolDetailsDao.persist(storagePoolDetailVO); - } else { - storagePoolDetailVO.setValue(value); - _storagePoolDetailsDao.update(storagePoolDetailVO.getId(), storagePoolDetailVO); - } break; + } else { + storagePoolDetailVO.setValue(value); + _storagePoolDetailsDao.update(storagePoolDetailVO.getId(), storagePoolDetailVO); + } + break; - case account: AccountVO account = _accountDao.findById(resourceId); - if (account == null) { - throw new InvalidParameterValueException("unable to find account by id " + resourceId); - } - AccountDetailVO accountDetailVO = _accountDetailsDao.findDetail(resourceId, name); - if (accountDetailVO == null) { - accountDetailVO = new AccountDetailVO(resourceId, name, value); - _accountDetailsDao.persist(accountDetailVO); - } else { - accountDetailVO.setValue(value); - _accountDetailsDao.update(accountDetailVO.getId(), accountDetailVO); - } break; - default: throw new InvalidParameterValueException("Scope provided is invalid"); + case account: + AccountVO account = _accountDao.findById(resourceId); + if (account == null) { + throw new InvalidParameterValueException("unable to find account by id " + resourceId); + } + AccountDetailVO accountDetailVO = _accountDetailsDao.findDetail(resourceId, name); + if (accountDetailVO == null) { + accountDetailVO = new AccountDetailVO(resourceId, name, value); + _accountDetailsDao.persist(accountDetailVO); + } else { + accountDetailVO.setValue(value); + _accountDetailsDao.update(accountDetailVO.getId(), accountDetailVO); + } + break; + default: + throw new InvalidParameterValueException("Scope provided is invalid"); } return value; } @@ -482,7 +505,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati pstmt.executeUpdate(); } catch (Throwable e) { - throw new CloudRuntimeException("Failed to update guest.network.device in host_details due to exception ", e); + throw new CloudRuntimeException( + "Failed to update guest.network.device in host_details due to exception ", e); } } else if (Config.XenPrivateNetwork.key().equalsIgnoreCase(name)) { String sql = "update host_details set value=? where name=?"; @@ -493,7 +517,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati pstmt.executeUpdate(); } catch (Throwable e) { - throw new CloudRuntimeException("Failed to update private.network.device in host_details due to exception ", e); + throw new CloudRuntimeException( + "Failed to update private.network.device in host_details due to exception ", e); } } else if (Config.XenPublicNetwork.key().equalsIgnoreCase(name)) { String sql = "update host_details set value=? where name=?"; @@ -504,7 +529,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati pstmt.executeUpdate(); } catch (Throwable e) { - throw new CloudRuntimeException("Failed to update public.network.device in host_details due to exception ", e); + throw new CloudRuntimeException( + "Failed to update public.network.device in host_details due to exception ", e); } } else if (Config.XenStorageNetwork1.key().equalsIgnoreCase(name)) { String sql = "update host_details set value=? where name=?"; @@ -515,7 +541,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati pstmt.executeUpdate(); } catch (Throwable e) { - throw new CloudRuntimeException("Failed to update storage.network.device1 in host_details due to exception ", e); + throw new CloudRuntimeException( + "Failed to update storage.network.device1 in host_details due to exception ", e); } } else if (Config.XenStorageNetwork2.key().equals(name)) { String sql = "update host_details set value=? where name=?"; @@ -526,18 +553,23 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati pstmt.executeUpdate(); } catch (Throwable e) { - throw new CloudRuntimeException("Failed to update storage.network.device2 in host_details due to exception ", e); + throw new CloudRuntimeException( + "Failed to update storage.network.device2 in host_details due to exception ", e); } } else if (Config.SystemVMUseLocalStorage.key().equalsIgnoreCase(name)) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Config 'system.vm.use.local.storage' changed to value:" + value + ", need to update System VM offerings"); + s_logger.debug("Config 'system.vm.use.local.storage' changed to value:" + value + + ", need to update System VM offerings"); } boolean useLocalStorage = Boolean.parseBoolean(_configDao.getValue(Config.SystemVMUseLocalStorage.key())); - ServiceOfferingVO serviceOffering = _serviceOfferingDao.findByName(ServiceOffering.consoleProxyDefaultOffUniqueName); + ServiceOfferingVO serviceOffering = _serviceOfferingDao + .findByName(ServiceOffering.consoleProxyDefaultOffUniqueName); if (serviceOffering != null) { serviceOffering.setUseLocalStorage(useLocalStorage); if (!_serviceOfferingDao.update(serviceOffering.getId(), serviceOffering)) { - throw new CloudRuntimeException("Failed to update ConsoleProxy offering's use_local_storage option to value:" + useLocalStorage); + throw new CloudRuntimeException( + "Failed to update ConsoleProxy offering's use_local_storage option to value:" + + useLocalStorage); } } @@ -545,7 +577,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (serviceOffering != null) { serviceOffering.setUseLocalStorage(useLocalStorage); if (!_serviceOfferingDao.update(serviceOffering.getId(), serviceOffering)) { - throw new CloudRuntimeException("Failed to update SoftwareRouter offering's use_local_storage option to value:" + useLocalStorage); + throw new CloudRuntimeException( + "Failed to update SoftwareRouter offering's use_local_storage option to value:" + + useLocalStorage); } } @@ -553,7 +587,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (serviceOffering != null) { serviceOffering.setUseLocalStorage(useLocalStorage); if (!_serviceOfferingDao.update(serviceOffering.getId(), serviceOffering)) { - throw new CloudRuntimeException("Failed to update SecondaryStorage offering's use_local_storage option to value:" + useLocalStorage); + throw new CloudRuntimeException( + "Failed to update SecondaryStorage offering's use_local_storage option to value:" + + useLocalStorage); } } } @@ -572,8 +608,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati Long clusterId = cmd.getClusterId(); Long storagepoolId = cmd.getStoragepoolId(); Long accountId = cmd.getAccountId(); - UserContext.current().setEventDetails(" Name: " + name + " New Value: " + (((name.toLowerCase()).contains("password")) ? "*****" : - (((value == null) ? "" : value)))); + UserContext.current().setEventDetails( + " Name: " + name + " New Value: " + + (((name.toLowerCase()).contains("password")) ? "*****" : (((value == null) ? "" : value)))); // check if config value exists ConfigurationVO config = _configDao.findByName(name); if (config == null) { @@ -614,7 +651,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } if (paramCountCheck > 1) { - throw new InvalidParameterValueException("cannot handle multiple IDs, provide only one ID corresponding to the scope"); + throw new InvalidParameterValueException( + "cannot handle multiple IDs, provide only one ID corresponding to the scope"); } String updatedValue = updateConfiguration(userId, name, config.getCategory(), value, scope, id); @@ -638,7 +676,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati s_logger.error("Invalid scope id provided for the parameter " + name); return "Invalid scope id provided for the parameter " + name; } - if ((name.equalsIgnoreCase("cpu.overprovisioning.factor") || name.equalsIgnoreCase("mem.overprovisioning.factor")) && value == null) { + if ((name.equalsIgnoreCase("cpu.overprovisioning.factor") || name + .equalsIgnoreCase("mem.overprovisioning.factor")) && value == null) { s_logger.error("value cannot be null for cpu.overprovisioning.factor/mem.overprovisioning.factor"); return "value cannot be null for cpu.overprovisioning.factor/mem.overprovisioning.factor"; } @@ -660,8 +699,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati return "Please enter either 'true' or 'false'."; } if (Config.SwiftEnable.key().equals(name)) { - List hosts = _ssvmMgr.listSecondaryStorageHostsInAllZones(); - if (hosts != null && hosts.size() > 0) { + List stores = this._dataStoreMgr.listImageStores(); + if (stores != null && stores.size() > 0) { return " can not change " + Config.SwiftEnable.key() + " after you have added secondary storage"; } SwiftVO swift = _swiftDao.findById(1L); @@ -684,11 +723,13 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati try { int val = Integer.parseInt(value); if (val <= 0) { - throw new InvalidParameterValueException("Please enter a positive value for the configuration parameter:" + name); + throw new InvalidParameterValueException( + "Please enter a positive value for the configuration parameter:" + name); } } catch (NumberFormatException e) { s_logger.error("There was an error trying to parse the integer value for:" + name); - throw new InvalidParameterValueException("There was an error trying to parse the integer value for:" + name); + throw new InvalidParameterValueException("There was an error trying to parse the integer value for:" + + name); } } @@ -701,7 +742,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (range.equals("privateip")) { try { if (!NetUtils.isSiteLocalAddress(value)) { - s_logger.error("privateip range " + value + " is not a site local address for configuration variable " + name); + s_logger.error("privateip range " + value + + " is not a site local address for configuration variable " + name); return "Please enter a site local IP address."; } } catch (NullPointerException e) { @@ -719,7 +761,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati return "Please enter hypervisor list, seperated by comma"; } for (String hypervisor : hypervisors) { - if (HypervisorType.getType(hypervisor) == HypervisorType.Any || HypervisorType.getType(hypervisor) == HypervisorType.None) { + if (HypervisorType.getType(hypervisor) == HypervisorType.Any + || HypervisorType.getType(hypervisor) == HypervisorType.None) { return "Please enter valid hypervisor type"; } } @@ -733,8 +776,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (route != null) { String routeToVerify = route.trim(); if (!NetUtils.isValidCIDR(routeToVerify)) { - throw new InvalidParameterValueException("Invalid value for blacklisted route: " + route + ". Valid format is list" + - " of cidrs separated by coma. Example: 10.1.1.0/24,192.168.0.0/24"); + throw new InvalidParameterValueException("Invalid value for blacklisted route: " + route + + ". Valid format is list" + + " of cidrs separated by coma. Example: 10.1.1.0/24,192.168.0.0/24"); } } } @@ -814,8 +858,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati String errorMsg = table.get(2); String dbName; - if (tableName.equals("event") || tableName.equals("cloud_usage") || tableName.equals("usage_vm_instance") || tableName.equals("usage_ip_address") || tableName.equals("usage_network") - || tableName.equals("usage_job") || tableName.equals("account") || tableName.equals("user_statistics")) { + if (tableName.equals("event") || tableName.equals("cloud_usage") || tableName.equals("usage_vm_instance") + || tableName.equals("usage_ip_address") || tableName.equals("usage_network") + || tableName.equals("usage_job") || tableName.equals("account") + || tableName.equals("user_statistics")) { dbName = "cloud_usage"; } else { dbName = "cloud"; @@ -823,7 +869,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati String selectSql = "SELECT * FROM `" + dbName + "`.`" + tableName + "` WHERE " + column + " = ?"; - if (tableName.equals("host") || tableName.equals("cluster") || tableName.equals("volumes") || tableName.equals("vm_instance")) { + if (tableName.equals("host") || tableName.equals("cluster") || tableName.equals("volumes") + || tableName.equals("vm_instance")) { selectSql += " and removed IS NULL"; } @@ -836,17 +883,20 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new CloudRuntimeException("The pod cannot be deleted because " + errorMsg); } } catch (SQLException ex) { - throw new CloudRuntimeException("The Management Server failed to detect if pod is deletable. Please contact Cloud Support."); + throw new CloudRuntimeException( + "The Management Server failed to detect if pod is deletable. Please contact Cloud Support."); } } } - private void checkPodAttributes(long podId, String podName, long zoneId, String gateway, String cidr, String startIp, String endIp, String allocationStateStr, boolean checkForDuplicates, + private void checkPodAttributes(long podId, String podName, long zoneId, String gateway, String cidr, + String startIp, String endIp, String allocationStateStr, boolean checkForDuplicates, boolean skipGatewayOverlapCheck) { if (checkForDuplicates) { // Check if the pod already exists if (validPod(podName, zoneId)) { - throw new InvalidParameterValueException("A pod with name: " + podName + " already exists in zone " + zoneId + ". Please specify a different pod name. "); + throw new InvalidParameterValueException("A pod with name: " + podName + " already exists in zone " + + zoneId + ". Please specify a different pod name. "); } } @@ -890,8 +940,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (checkPodCIDRs == null || checkPodCIDRs.trim().isEmpty() || Boolean.parseBoolean(checkPodCIDRs)) { checkPodCidrSubnets(zoneId, podId, cidr); /* - * Commenting out due to Bug 11593 - CIDR conflicts with zone when extending pod but not when creating it - * + * Commenting out due to Bug 11593 - CIDR conflicts with zone when + * extending pod but not when creating it + * * checkCidrVlanOverlap(zoneId, cidr); */ } @@ -900,7 +951,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati try { Grouping.AllocationState.valueOf(allocationStateStr); } catch (IllegalArgumentException ex) { - throw new InvalidParameterValueException("Unable to resolve Allocation State '" + allocationStateStr + "' to a supported state"); + throw new InvalidParameterValueException("Unable to resolve Allocation State '" + allocationStateStr + + "' to a supported state"); } } } @@ -924,7 +976,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati txn.start(); // Delete private ip addresses for the pod if there are any - List privateIps = _privateIpAddressDao.listByPodIdDcId(Long.valueOf(podId), pod.getDataCenterId()); + List privateIps = _privateIpAddressDao.listByPodIdDcId(Long.valueOf(podId), + pod.getDataCenterId()); if (!privateIps.isEmpty()) { if (!(_privateIpAddressDao.deleteIpAddressByPod(podId))) { throw new CloudRuntimeException("Failed to cleanup private ip addresses for pod " + podId); @@ -932,7 +985,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } // Delete link local ip addresses for the pod - List localIps = _LinkLocalIpAllocDao.listByPodIdDcId(podId, pod.getDataCenterId()); + List localIps = _LinkLocalIpAllocDao.listByPodIdDcId(podId, + pod.getDataCenterId()); if (!localIps.isEmpty()) { if (!(_LinkLocalIpAllocDao.deleteIpAddressByPod(podId))) { throw new CloudRuntimeException("Failed to cleanup private ip addresses for pod " + podId); @@ -967,12 +1021,14 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Override public Pod editPod(UpdatePodCmd cmd) { - return editPod(cmd.getId(), cmd.getPodName(), cmd.getStartIp(), cmd.getEndIp(), cmd.getGateway(), cmd.getNetmask(), cmd.getAllocationState()); + return editPod(cmd.getId(), cmd.getPodName(), cmd.getStartIp(), cmd.getEndIp(), cmd.getGateway(), + cmd.getNetmask(), cmd.getAllocationState()); } @Override @DB - public Pod editPod(long id, String name, String startIp, String endIp, String gateway, String netmask, String allocationStateStr) { + public Pod editPod(long id, String name, String startIp, String endIp, String gateway, String netmask, + String allocationStateStr) { // verify parameters HostPodVO pod = _podDao.findById(id); @@ -995,13 +1051,15 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati long oldCidr = pod.getCidrSize(); if (newCidr > oldCidr) { - throw new CloudRuntimeException("The specified pod has allocated private IP addresses, so its IP address range can be extended only"); + throw new CloudRuntimeException( + "The specified pod has allocated private IP addresses, so its IP address range can be extended only"); } } if (startIp != null && !startIp.equals(existingPodIpRange[0])) { if (NetUtils.ipRangesOverlap(startIp, null, existingPodIpRange[0], existingPodIpRange[1])) { - throw new CloudRuntimeException("The specified pod has allocated private IP addresses, so its IP address range can be extended only"); + throw new CloudRuntimeException( + "The specified pod has allocated private IP addresses, so its IP address range can be extended only"); } else { leftRangeToAdd = new String[2]; long endIpForUpdate = NetUtils.ip2Long(existingPodIpRange[0]) - 1; @@ -1012,7 +1070,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (endIp != null && !endIp.equals(existingPodIpRange[1])) { if (NetUtils.ipRangesOverlap(endIp, endIp, existingPodIpRange[0], existingPodIpRange[1])) { - throw new CloudRuntimeException("The specified pod has allocated private IP addresses, so its IP address range can be extended only"); + throw new CloudRuntimeException( + "The specified pod has allocated private IP addresses, so its IP address range can be extended only"); } else { rightRangeToAdd = new String[2]; long startIpForUpdate = NetUtils.ip2Long(existingPodIpRange[1]) + 1; @@ -1057,7 +1116,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // Verify pod's attributes String cidr = NetUtils.ipAndNetMaskToCidr(gateway, netmask); boolean checkForDuplicates = !oldPodName.equals(name); - checkPodAttributes(id, name, pod.getDataCenterId(), gateway, cidr, startIp, endIp, allocationStateStr, checkForDuplicates, false); + checkPodAttributes(id, name, pod.getDataCenterId(), gateway, cidr, startIp, endIp, allocationStateStr, + checkForDuplicates, false); Transaction txn = Transaction.currentTxn(); try { @@ -1116,7 +1176,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } @Override - public Pod createPod(long zoneId, String name, String startIp, String endIp, String gateway, String netmask, String allocationState) { + public Pod createPod(long zoneId, String name, String startIp, String endIp, String gateway, String netmask, + String allocationState) { String cidr = NetUtils.ipAndNetMaskToCidr(gateway, netmask); Long userId = UserContext.current().getCallerUserId(); @@ -1128,7 +1189,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Override @DB - public HostPodVO createPod(long userId, String podName, long zoneId, String gateway, String cidr, String startIp, String endIp, String allocationStateStr, boolean skipGatewayOverlapCheck) { + public HostPodVO createPod(long userId, String podName, long zoneId, String gateway, String cidr, String startIp, + String endIp, String allocationStateStr, boolean skipGatewayOverlapCheck) { // Check if the zone is valid if (!validZone(zoneId)) { @@ -1138,7 +1200,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // Check if zone is disabled DataCenterVO zone = _zoneDao.findById(zoneId); Account account = UserContext.current().getCaller(); - if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(account.getType())) { + if (Grouping.AllocationState.Disabled == zone.getAllocationState() + && !_accountMgr.isRootAdmin(account.getType())) { throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: " + zoneId); } @@ -1154,7 +1217,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } // Validate new pod settings - checkPodAttributes(-1, podName, zoneId, gateway, cidr, startIp, endIp, allocationStateStr, true, skipGatewayOverlapCheck); + checkPodAttributes(-1, podName, zoneId, gateway, cidr, startIp, endIp, allocationStateStr, true, + skipGatewayOverlapCheck); // Create the new pod in the database String ipRange; @@ -1258,7 +1322,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati selectSql += " AND taken IS NOT NULL"; } - if (tableName.equals("host_pod_ref") || tableName.equals("host") || tableName.equals("volumes") || tableName.equals("physical_network")) { + if (tableName.equals("host_pod_ref") || tableName.equals("host") || tableName.equals("volumes") + || tableName.equals("physical_network")) { selectSql += " AND removed is NULL"; } @@ -1275,18 +1340,21 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new CloudRuntimeException("The zone is not deletable because " + errorMsg); } } catch (SQLException ex) { - throw new CloudRuntimeException("The Management Server failed to detect if zone is deletable. Please contact Cloud Support."); + throw new CloudRuntimeException( + "The Management Server failed to detect if zone is deletable. Please contact Cloud Support."); } } } - private void checkZoneParameters(String zoneName, String dns1, String dns2, String internalDns1, String internalDns2, boolean checkForDuplicates, Long domainId, String allocationStateStr, - String ip6Dns1, String ip6Dns2) { + private void checkZoneParameters(String zoneName, String dns1, String dns2, String internalDns1, + String internalDns2, boolean checkForDuplicates, Long domainId, String allocationStateStr, String ip6Dns1, + String ip6Dns2) { if (checkForDuplicates) { // Check if a zone with the specified name already exists if (validZone(zoneName)) { - throw new InvalidParameterValueException("A zone with that name already exists. Please specify a unique zone name."); + throw new InvalidParameterValueException( + "A zone with that name already exists. Please specify a unique zone name."); } } @@ -1329,7 +1397,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati try { Grouping.AllocationState.valueOf(allocationStateStr); } catch (IllegalArgumentException ex) { - throw new InvalidParameterValueException("Unable to resolve Allocation State '" + allocationStateStr + "' to a supported state"); + throw new InvalidParameterValueException("Unable to resolve Allocation State '" + allocationStateStr + + "' to a supported state"); } } } @@ -1347,12 +1416,15 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new InvalidParameterValueException("The start address of the IP range is not in the CIDR subnet."); } - if (endIp != null && !NetUtils.getCidrSubNet(endIp, cidrSize).equalsIgnoreCase(NetUtils.getCidrSubNet(cidrAddress, cidrSize))) { + if (endIp != null + && !NetUtils.getCidrSubNet(endIp, cidrSize).equalsIgnoreCase( + NetUtils.getCidrSubNet(cidrAddress, cidrSize))) { throw new InvalidParameterValueException("The end address of the IP range is not in the CIDR subnet."); } if (endIp != null && NetUtils.ip2Long(startIp) > NetUtils.ip2Long(endIp)) { - throw new InvalidParameterValueException("The start IP address must have a lower value than the end IP address."); + throw new InvalidParameterValueException( + "The start IP address must have a lower value than the end IP address."); } } @@ -1365,7 +1437,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati for (IPAddressVO publicIPVO : existingPublicIPs) { long publicIP = NetUtils.ip2Long(publicIPVO.getAddress().addr()); if ((publicIP >= privateStartIp) && (publicIP <= privateEndIp)) { - throw new InvalidParameterValueException("The Start IP and endIP address range overlap with Public IP :" + publicIPVO.getAddress().addr()); + throw new InvalidParameterValueException( + "The Start IP and endIP address range overlap with Public IP :" + + publicIPVO.getAddress().addr()); } } } @@ -1380,7 +1454,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (!NetUtils.isValidIp(IpRange[0]) || !NetUtils.isValidIp(IpRange[1])) continue; if (NetUtils.ipRangesOverlap(startIp, endIp, IpRange[0], IpRange[1])) { - throw new InvalidParameterValueException("The Start IP and endIP address range overlap with private IP :" + IpRange[0] + ":" + IpRange[1]); + throw new InvalidParameterValueException( + "The Start IP and endIP address range overlap with private IP :" + IpRange[0] + ":" + + IpRange[1]); } } } @@ -1448,7 +1524,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati return true; } - @Override @DB public LDAPConfigCmd listLDAPConfig(LDAPConfigCmd cmd) { @@ -1458,13 +1533,13 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati cmd.setPort(port == null ? 0 : Integer.valueOf(port)); String queryFilter = _configDao.getValue(LDAPParams.queryfilter.toString()); cmd.setQueryFilter(queryFilter == null ? "" : queryFilter); - String searchBase = _configDao.getValue(LDAPParams.searchbase.toString()); + String searchBase = _configDao.getValue(LDAPParams.searchbase.toString()); cmd.setSearchBase(searchBase == null ? "" : searchBase); - String useSSL = _configDao.getValue(LDAPParams.usessl.toString()); + String useSSL = _configDao.getValue(LDAPParams.usessl.toString()); cmd.setUseSSL(useSSL == null ? Boolean.FALSE : Boolean.valueOf(useSSL)); - String binddn = _configDao.getValue(LDAPParams.dn.toString()); + String binddn = _configDao.getValue(LDAPParams.dn.toString()); cmd.setBindDN(binddn == null ? "" : binddn); - String truststore = _configDao.getValue(LDAPParams.truststore.toString()); + String truststore = _configDao.getValue(LDAPParams.truststore.toString()); cmd.setTrustStore(truststore == null ? "" : truststore); return cmd; } @@ -1473,7 +1548,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @DB public boolean updateLDAP(LDAPConfigCmd cmd) { try { - // set the ldap details in the zone details table with a zone id of -12 + // set the ldap details in the zone details table with a zone id of + // -12 String hostname = cmd.getHostname(); Integer port = cmd.getPort(); String queryFilter = cmd.getQueryFilter(); @@ -1485,12 +1561,14 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati String trustStorePassword = cmd.getTrustStorePassword(); if (bindDN != null && bindPasswd == null) { - throw new InvalidParameterValueException("If you specify a bind name then you need to provide bind password too."); + throw new InvalidParameterValueException( + "If you specify a bind name then you need to provide bind password too."); } // check query filter if it contains valid substitution - if (!queryFilter.contains("%u") && !queryFilter.contains("%n") && !queryFilter.contains("%e")){ - throw new InvalidParameterValueException("QueryFilter should contain at least one of the substitutions: %u, %n or %e: " + queryFilter); + if (!queryFilter.contains("%u") && !queryFilter.contains("%n") && !queryFilter.contains("%e")) { + throw new InvalidParameterValueException( + "QueryFilter should contain at least one of the substitutions: %u, %n or %e: " + queryFilter); } // check if the info is correct @@ -1501,7 +1579,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati env.put(Context.SECURITY_PROTOCOL, "ssl"); protocol = "ldaps://"; if (trustStore == null || trustStorePassword == null) { - throw new InvalidParameterValueException("If you plan to use SSL then you need to configure the trust store."); + throw new InvalidParameterValueException( + "If you plan to use SSL then you need to configure the trust store."); } System.setProperty("javax.net.ssl.trustStore", trustStore); System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword); @@ -1519,21 +1598,24 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // store the result in DB Configuration ConfigurationVO cvo = _configDao.findByName(LDAPParams.hostname.toString()); if (cvo == null) { - cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.hostname.toString(), null, "Hostname or ip address of the ldap server eg: my.ldap.com"); + cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.hostname.toString(), + null, "Hostname or ip address of the ldap server eg: my.ldap.com"); } cvo.setValue(DBEncryptionUtil.encrypt(hostname)); _configDao.persist(cvo); cvo = _configDao.findByName(LDAPParams.port.toString()); if (cvo == null) { - cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.port.toString(), null, "Specify the LDAP port if required, default is 389"); + cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.port.toString(), null, + "Specify the LDAP port if required, default is 389"); } cvo.setValue(DBEncryptionUtil.encrypt(port.toString())); _configDao.persist(cvo); cvo = _configDao.findByName(LDAPParams.queryfilter.toString()); if (cvo == null) { - cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.queryfilter.toString(), null, + cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.queryfilter.toString(), + null, "You specify a query filter here, which narrows down the users, who can be part of this domain"); } cvo.setValue(DBEncryptionUtil.encrypt(queryFilter)); @@ -1541,7 +1623,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati cvo = _configDao.findByName(LDAPParams.searchbase.toString()); if (cvo == null) { - cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.searchbase.toString(), null, + cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.searchbase.toString(), + null, "The search base defines the starting point for the search in the directory tree Example: dc=cloud,dc=com."); } cvo.setValue(DBEncryptionUtil.encrypt(searchBase)); @@ -1549,42 +1632,48 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati cvo = _configDao.findByName(LDAPParams.usessl.toString()); if (cvo == null) { - cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.usessl.toString(), null, "Check Use SSL if the external LDAP server is configured for LDAP over SSL."); + cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.usessl.toString(), null, + "Check Use SSL if the external LDAP server is configured for LDAP over SSL."); } cvo.setValue(DBEncryptionUtil.encrypt(useSSL.toString())); _configDao.persist(cvo); cvo = _configDao.findByName(LDAPParams.dn.toString()); if (cvo == null) { - cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.dn.toString(), null, "Specify the distinguished name of a user with the search permission on the directory"); + cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.dn.toString(), null, + "Specify the distinguished name of a user with the search permission on the directory"); } cvo.setValue(DBEncryptionUtil.encrypt(bindDN)); _configDao.persist(cvo); cvo = _configDao.findByName(LDAPParams.passwd.toString()); if (cvo == null) { - cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.passwd.toString(), null, "Enter the password"); + cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.passwd.toString(), null, + "Enter the password"); } cvo.setValue(DBEncryptionUtil.encrypt(bindPasswd)); _configDao.persist(cvo); cvo = _configDao.findByName(LDAPParams.truststore.toString()); if (cvo == null) { - cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.truststore.toString(), null, "Enter the path to trusted keystore"); + cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.truststore.toString(), + null, "Enter the path to trusted keystore"); } cvo.setValue(DBEncryptionUtil.encrypt(trustStore)); _configDao.persist(cvo); cvo = _configDao.findByName(LDAPParams.truststorepass.toString()); if (cvo == null) { - cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.truststorepass.toString(), null, "Enter the password for trusted keystore"); + cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", + LDAPParams.truststorepass.toString(), null, "Enter the password for trusted keystore"); } cvo.setValue(DBEncryptionUtil.encrypt(trustStorePassword)); _configDao.persist(cvo); s_logger.debug("The ldap server is configured: " + hostname); } catch (NamingException ne) { - throw new InvalidParameterValueException("Naming Exception, check you ldap data ! " + ne.getMessage() + (ne.getCause() != null ? ("; Caused by:" + ne.getCause().getMessage()) : "")); + throw new InvalidParameterValueException("Naming Exception, check you ldap data ! " + ne.getMessage() + + (ne.getCause() != null ? ("; Caused by:" + ne.getCause().getMessage()) : "")); } return true; } @@ -1690,7 +1779,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } if (internalDns2 == null) { - internalDns2 = zone.getInternalDns2(); + internalDns2 = zone.getInternalDns2(); } if (guestCidr == null) { @@ -1707,7 +1796,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } boolean checkForDuplicates = !zoneName.equals(oldZoneName); - checkZoneParameters(zoneName, dns1, dns2, internalDns1, internalDns2, checkForDuplicates, null, allocationStateStr, ip6Dns1, ip6Dns2);// not allowing updating domain associated with a zone, once created + checkZoneParameters(zoneName, dns1, dns2, internalDns1, internalDns2, checkForDuplicates, null, + allocationStateStr, ip6Dns1, ip6Dns2);// not allowing updating + // domain associated with + // a zone, once created zone.setName(zoneName); zone.setDns1(dns1); @@ -1753,20 +1845,27 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // check if zone has necessary trafficTypes before enabling try { PhysicalNetwork mgmtPhyNetwork; - // zone should have a physical network with management traffiType - mgmtPhyNetwork = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Management); - if (NetworkType.Advanced == zone.getNetworkType() && ! zone.isSecurityGroupEnabled() ) { - // advanced zone without SG should have a physical network with public Thpe + // zone should have a physical network with management + // traffiType + mgmtPhyNetwork = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, + TrafficType.Management); + if (NetworkType.Advanced == zone.getNetworkType() && !zone.isSecurityGroupEnabled()) { + // advanced zone without SG should have a physical + // network with public Thpe _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Public); } try { _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Storage); } catch (InvalidParameterValueException noStorage) { - PhysicalNetworkTrafficTypeVO mgmtTraffic = _trafficTypeDao.findBy(mgmtPhyNetwork.getId(), TrafficType.Management); - _networkSvc.addTrafficTypeToPhysicalNetwork(mgmtPhyNetwork.getId(), TrafficType.Storage.toString(), mgmtTraffic.getXenNetworkLabel(), mgmtTraffic.getKvmNetworkLabel(), - mgmtTraffic.getVmwareNetworkLabel(), mgmtTraffic.getSimulatorNetworkLabel(), mgmtTraffic.getVlan()); - s_logger.info("No storage traffic type was specified by admin, create default storage traffic on physical network " + mgmtPhyNetwork.getId() + " with same configure of management traffic type"); + PhysicalNetworkTrafficTypeVO mgmtTraffic = _trafficTypeDao.findBy(mgmtPhyNetwork.getId(), + TrafficType.Management); + _networkSvc.addTrafficTypeToPhysicalNetwork(mgmtPhyNetwork.getId(), + TrafficType.Storage.toString(), mgmtTraffic.getXenNetworkLabel(), + mgmtTraffic.getKvmNetworkLabel(), mgmtTraffic.getVmwareNetworkLabel(), + mgmtTraffic.getSimulatorNetworkLabel(), mgmtTraffic.getVlan()); + s_logger.info("No storage traffic type was specified by admin, create default storage traffic on physical network " + + mgmtPhyNetwork.getId() + " with same configure of management traffic type"); } } catch (InvalidParameterValueException ex) { throw new InvalidParameterValueException("Cannot enable this Zone since: " + ex.getMessage()); @@ -1790,8 +1889,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Override @DB - public DataCenterVO createZone(long userId, String zoneName, String dns1, String dns2, String internalDns1, String internalDns2, String guestCidr, String domain, Long domainId, - NetworkType zoneType, String allocationStateStr, String networkDomain, boolean isSecurityGroupEnabled, boolean isLocalStorageEnabled, String ip6Dns1, String ip6Dns2) { + public DataCenterVO createZone(long userId, String zoneName, String dns1, String dns2, String internalDns1, + String internalDns2, String guestCidr, String domain, Long domainId, NetworkType zoneType, + String allocationStateStr, String networkDomain, boolean isSecurityGroupEnabled, + boolean isLocalStorageEnabled, String ip6Dns1, String ip6Dns2) { // checking the following params outside checkzoneparams method as we do // not use these params for updatezone @@ -1809,7 +1910,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } - checkZoneParameters(zoneName, dns1, dns2, internalDns1, internalDns2, true, domainId, allocationStateStr, ip6Dns1, ip6Dns2); + checkZoneParameters(zoneName, dns1, dns2, internalDns1, internalDns2, true, domainId, allocationStateStr, + ip6Dns1, ip6Dns2); byte[] bytes = (zoneName + System.currentTimeMillis()).getBytes(); String zoneToken = UUID.nameUUIDFromBytes(bytes).toString(); @@ -1817,18 +1919,22 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati try { txn.start(); // Create the new zone in the database - DataCenterVO zone = new DataCenterVO(zoneName, null, dns1, dns2, internalDns1, internalDns2, guestCidr, null, null, zoneType, zoneToken, networkDomain, isSecurityGroupEnabled, isLocalStorageEnabled, ip6Dns1, ip6Dns2); + DataCenterVO zone = new DataCenterVO(zoneName, null, dns1, dns2, internalDns1, internalDns2, guestCidr, + null, null, zoneType, zoneToken, networkDomain, isSecurityGroupEnabled, isLocalStorageEnabled, + ip6Dns1, ip6Dns2); if (allocationStateStr != null && !allocationStateStr.isEmpty()) { Grouping.AllocationState allocationState = Grouping.AllocationState.valueOf(allocationStateStr); zone.setAllocationState(allocationState); } else { - // Zone will be disabled since 3.0. Admin should enable it after physical network and providers setup. + // Zone will be disabled since 3.0. Admin should enable it after + // physical network and providers setup. zone.setAllocationState(Grouping.AllocationState.Disabled); } zone = _zoneDao.persist(zone); if (domainId != null) { - //zone is explicitly dedicated to this domain - DedicatedResourceVO dedicatedResource = new DedicatedResourceVO(zone.getId(), null, null, null, domainId, null); + // zone is explicitly dedicated to this domain + DedicatedResourceVO dedicatedResource = new DedicatedResourceVO(zone.getId(), null, null, null, + domainId, null); _dedicatedDao.persist(dedicatedResource); } @@ -1869,7 +1975,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } else if (offering.getTrafficType() == TrafficType.Control) { broadcastDomainType = BroadcastDomainType.LinkLocal; } else if (offering.getTrafficType() == TrafficType.Public) { - if ((zone.getNetworkType() == NetworkType.Advanced && !zone.isSecurityGroupEnabled()) || zone.getNetworkType() == NetworkType.Basic) { + if ((zone.getNetworkType() == NetworkType.Advanced && !zone.isSecurityGroupEnabled()) + || zone.getNetworkType() == NetworkType.Basic) { broadcastDomainType = BroadcastDomainType.Vlan; } else { continue; @@ -1880,7 +1987,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati userNetwork.setBroadcastDomainType(broadcastDomainType); userNetwork.setNetworkDomain(networkDomain); - _networkMgr.setupNetwork(systemAccount, offering, userNetwork, plan, null, null, false, + _networkMgr.setupNetwork(systemAccount, offering, userNetwork, plan, null, null, false, Domain.ROOT_DOMAIN, null, null, null, true); } } @@ -1911,7 +2018,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati allocationState = Grouping.AllocationState.Disabled.toString(); } - if (!(type.equalsIgnoreCase(NetworkType.Basic.toString())) && !(type.equalsIgnoreCase(NetworkType.Advanced.toString()))) { + if (!(type.equalsIgnoreCase(NetworkType.Basic.toString())) + && !(type.equalsIgnoreCase(NetworkType.Advanced.toString()))) { throw new InvalidParameterValueException("Invalid zone type; only Advanced and Basic values are supported"); } else if (type.equalsIgnoreCase(NetworkType.Basic.toString())) { isBasic = true; @@ -1938,7 +2046,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati isSecurityGroupEnabled = true; } - return createZone(userId, zoneName, dns1, dns2, internalDns1, internalDns2, guestCidr, domainVO != null ? domainVO.getName() : null, domainId, zoneType, allocationState, networkDomain, + return createZone(userId, zoneName, dns1, dns2, internalDns1, internalDns2, guestCidr, + domainVO != null ? domainVO.getName() : null, domainId, zoneType, allocationState, networkDomain, isSecurityGroupEnabled, isLocalStorageEnabled, ip6Dns1, ip6Dns2); } @@ -1948,27 +2057,32 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati String name = cmd.getServiceOfferingName(); if ((name == null) || (name.length() == 0)) { - throw new InvalidParameterValueException("Failed to create service offering: specify the name that has non-zero length"); + throw new InvalidParameterValueException( + "Failed to create service offering: specify the name that has non-zero length"); } String displayText = cmd.getDisplayText(); if ((displayText == null) || (displayText.length() == 0)) { - throw new InvalidParameterValueException("Failed to create service offering " + name + ": specify the display text that has non-zero length"); + throw new InvalidParameterValueException("Failed to create service offering " + name + + ": specify the display text that has non-zero length"); } Long cpuNumber = cmd.getCpuNumber(); if ((cpuNumber == null) || (cpuNumber.intValue() <= 0) || (cpuNumber.intValue() > 2147483647)) { - throw new InvalidParameterValueException("Failed to create service offering " + name + ": specify the cpu number value between 1 and 2147483647"); + throw new InvalidParameterValueException("Failed to create service offering " + name + + ": specify the cpu number value between 1 and 2147483647"); } Long cpuSpeed = cmd.getCpuSpeed(); if ((cpuSpeed == null) || (cpuSpeed.intValue() <= 0) || (cpuSpeed.intValue() > 2147483647)) { - throw new InvalidParameterValueException("Failed to create service offering " + name + ": specify the cpu speed value between 1 and 2147483647"); + throw new InvalidParameterValueException("Failed to create service offering " + name + + ": specify the cpu speed value between 1 and 2147483647"); } Long memory = cmd.getMemory(); if ((memory == null) || (memory.intValue() < 32) || (memory.intValue() > 2147483647)) { - throw new InvalidParameterValueException("Failed to create service offering " + name + ": specify the memory value between 32 and 2147483647 MB"); + throw new InvalidParameterValueException("Failed to create service offering " + name + + ": specify the memory value between 32 and 2147483647 MB"); } // check if valid domain @@ -1982,7 +2096,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (storageType.equalsIgnoreCase(ServiceOffering.StorageType.local.toString())) { localStorageRequired = true; } else if (!storageType.equalsIgnoreCase(ServiceOffering.StorageType.shared.toString())) { - throw new InvalidParameterValueException("Invalid storage type " + storageType + " specified, valid types are: 'local' and 'shared'"); + throw new InvalidParameterValueException("Invalid storage type " + storageType + + " specified, valid types are: 'local' and 'shared'"); } } @@ -2004,7 +2119,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } else if (VirtualMachine.Type.InternalLoadBalancerVm.toString().toLowerCase().equals(vmTypeString)) { vmType = VirtualMachine.Type.InternalLoadBalancerVm; } else { - throw new InvalidParameterValueException("Invalid systemVmType. Supported types are: " + VirtualMachine.Type.DomainRouter + ", " + VirtualMachine.Type.ConsoleProxy + ", " + throw new InvalidParameterValueException("Invalid systemVmType. Supported types are: " + + VirtualMachine.Type.DomainRouter + ", " + VirtualMachine.Type.ConsoleProxy + ", " + VirtualMachine.Type.SecondaryStorageVm); } } else { @@ -2013,7 +2129,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } if (cmd.getNetworkRate() != null && !allowNetworkRate) { - throw new InvalidParameterValueException("Network rate can be specified only for non-System offering and system offerings having \"domainrouter\" systemvmtype"); + throw new InvalidParameterValueException( + "Network rate can be specified only for non-System offering and system offerings having \"domainrouter\" systemvmtype"); } if (cmd.getDeploymentPlanner() != null) { @@ -2042,7 +2159,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate, String deploymentPlanner, Map details, Long bytesReadRate, Long bytesWriteRate, Long iopsReadRate, Long iopsWriteRate) { tags = cleanupTags(tags); - ServiceOfferingVO offering = new ServiceOfferingVO(name, cpu, ramSize, speed, networkRate, null, offerHA, limitResourceUse, volatileVm, displayText, localStorageRequired, false, tags, isSystem, vm_type, + ServiceOfferingVO offering = new ServiceOfferingVO(name, cpu, ramSize, speed, networkRate, null, offerHA, + limitResourceUse, volatileVm, displayText, localStorageRequired, false, tags, isSystem, vm_type, domainId, hostTag, deploymentPlanner); if ((bytesReadRate != null) && (bytesReadRate > 0)) @@ -2206,7 +2324,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (storageType.equalsIgnoreCase(ServiceOffering.StorageType.local.toString())) { localStorageRequired = true; } else if (!storageType.equalsIgnoreCase(ServiceOffering.StorageType.shared.toString())) { - throw new InvalidParameterValueException("Invalid storage type " + storageType + " specified, valid types are: 'local' and 'shared'"); + throw new InvalidParameterValueException("Invalid storage type " + storageType + + " specified, valid types are: 'local' and 'shared'"); } } @@ -2334,8 +2453,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Override @DB - @ActionEvent(eventType = EventTypes.EVENT_VLAN_IP_RANGE_CREATE, eventDescription = "creating vlan ip range", async = false) - public Vlan createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, ResourceAllocationException { + @ActionEvent(eventType = EventTypes.EVENT_VLAN_IP_RANGE_CREATE, eventDescription = "creating vlan ip range", + async = false) + public Vlan createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws InsufficientCapacityException, + ConcurrentOperationException, ResourceUnavailableException, ResourceAllocationException { Long zoneId = cmd.getZoneId(); Long podId = cmd.getPodId(); String startIP = cmd.getStartIp(); @@ -2410,7 +2531,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati physicalNetworkId = network.getPhysicalNetworkId(); } } else if (ipv6) { - throw new InvalidParameterValueException("Only support IPv6 on extending existed network"); + throw new InvalidParameterValueException("Only support IPv6 on extending existed network"); } // Verify that zone exists @@ -2420,9 +2541,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } if (ipv6) { - if (network.getGuestType() != GuestType.Shared || zone.isSecurityGroupEnabled()) { - throw new InvalidParameterValueException("Only support IPv6 on extending existed share network without SG"); - } + if (network.getGuestType() != GuestType.Shared || zone.isSecurityGroupEnabled()) { + throw new InvalidParameterValueException( + "Only support IPv6 on extending existed share network without SG"); + } } // verify that physical network exists PhysicalNetworkVO pNtwk = null; @@ -2444,34 +2566,41 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } else { if (forVirtualNetwork) { // default physical network with public traffic in the zone - physicalNetworkId = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Public).getId(); + physicalNetworkId = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, + TrafficType.Public).getId(); } else { if (zone.getNetworkType() == DataCenter.NetworkType.Basic) { - // default physical network with guest traffic in the zone - physicalNetworkId = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Guest).getId(); + // default physical network with guest traffic in the + // zone + physicalNetworkId = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, + TrafficType.Guest).getId(); } else if (zone.getNetworkType() == DataCenter.NetworkType.Advanced) { if (zone.isSecurityGroupEnabled()) { - physicalNetworkId = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Guest).getId(); + physicalNetworkId = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, + TrafficType.Guest).getId(); } else { - throw new InvalidParameterValueException("Physical Network Id is null, please provide the Network id for Direct vlan creation "); + throw new InvalidParameterValueException( + "Physical Network Id is null, please provide the Network id for Direct vlan creation "); } } } } } - // Check if zone is enabled Account caller = UserContext.current().getCaller(); - if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) { + if (Grouping.AllocationState.Disabled == zone.getAllocationState() + && !_accountMgr.isRootAdmin(caller.getType())) { throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: " + zoneId); } if (zone.isSecurityGroupEnabled() && zone.getNetworkType() != DataCenter.NetworkType.Basic && forVirtualNetwork) { - throw new InvalidParameterValueException("Can't add virtual ip range into a zone with security group enabled"); + throw new InvalidParameterValueException( + "Can't add virtual ip range into a zone with security group enabled"); } - // If networkId is not specified, and vlan is Virtual or Direct Untagged, try to locate default networks + // If networkId is not specified, and vlan is Virtual or Direct + // Untagged, try to locate default networks if (forVirtualNetwork) { if (network == null) { // find default public network in the zone @@ -2494,47 +2623,51 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati zoneId = network.getDataCenterId(); } } else if (network.getGuestType() == null || network.getGuestType() == Network.GuestType.Isolated) { - throw new InvalidParameterValueException("Can't create direct vlan for network id=" + networkId + " with type: " + network.getGuestType()); + throw new InvalidParameterValueException("Can't create direct vlan for network id=" + networkId + + " with type: " + network.getGuestType()); } } - Pair> sameSubnet= null; + Pair> sameSubnet = null; // Can add vlan range only to the network which allows it if (!network.getSpecifyIpRanges()) { throw new InvalidParameterValueException("Network " + network + " doesn't support adding ip ranges"); } - if ( zone.getNetworkType() == DataCenter.NetworkType.Advanced ) { + if (zone.getNetworkType() == DataCenter.NetworkType.Advanced) { if (network.getTrafficType() == TrafficType.Guest) { if (network.getGuestType() != GuestType.Shared) { - throw new InvalidParameterValueException("Can execute createVLANIpRanges on shared guest network, but type of this guest network " - + network.getId() + " is " + network.getGuestType()); + throw new InvalidParameterValueException( + "Can execute createVLANIpRanges on shared guest network, but type of this guest network " + + network.getId() + " is " + network.getGuestType()); } List vlans = _vlanDao.listVlansByNetworkId(network.getId()); VlanVO vlan = vlans.get(0); - if ( vlans != null && vlans.size() > 0 ) { - if ( vlanId == null ) { + if (vlans != null && vlans.size() > 0) { + if (vlanId == null) { vlanId = vlan.getVlanTag(); } else if (!vlan.getVlanTag().equals(vlanId)) { - throw new InvalidParameterValueException("there is already one vlan " + vlan.getVlanTag() + " on network :" + - + network.getId() + ", only one vlan is allowed on guest network"); + throw new InvalidParameterValueException("there is already one vlan " + vlan.getVlanTag() + + " on network :" + +network.getId() + ", only one vlan is allowed on guest network"); } } - sameSubnet=validateIpRange(startIP, endIP, newVlanGateway, newVlanNetmask, vlans, ipv4, ipv6, ip6Gateway, ip6Cidr,startIPv6, endIPv6, network); + sameSubnet = validateIpRange(startIP, endIP, newVlanGateway, newVlanNetmask, vlans, ipv4, ipv6, + ip6Gateway, ip6Cidr, startIPv6, endIPv6, network); } } else if (network.getTrafficType() == TrafficType.Management) { - throw new InvalidParameterValueException("Cannot execute createVLANIpRanges on management network"); - } - else if (zone.getNetworkType() == NetworkType.Basic){ - List vlans = _vlanDao.listVlansByNetworkId(network.getId()); - sameSubnet=validateIpRange(startIP,endIP,newVlanGateway, newVlanNetmask, vlans, ipv4, ipv6, ip6Gateway, ip6Cidr, startIPv6, endIPv6, network); + throw new InvalidParameterValueException("Cannot execute createVLANIpRanges on management network"); + } else if (zone.getNetworkType() == NetworkType.Basic) { + List vlans = _vlanDao.listVlansByNetworkId(network.getId()); + sameSubnet = validateIpRange(startIP, endIP, newVlanGateway, newVlanNetmask, vlans, ipv4, ipv6, ip6Gateway, + ip6Cidr, startIPv6, endIPv6, network); } - if (zoneId == null || (ipv6 && (ip6Gateway == null || ip6Cidr == null))) { - throw new InvalidParameterValueException("Gateway, netmask and zoneId have to be passed in for virtual and direct untagged networks"); + if (zoneId == null || (ipv6 && (ip6Gateway == null || ip6Cidr == null))) { + throw new InvalidParameterValueException( + "Gateway, netmask and zoneId have to be passed in for virtual and direct untagged networks"); } if (forVirtualNetwork) { @@ -2542,51 +2675,52 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati long accountIpRange = NetUtils.ip2Long(endIP) - NetUtils.ip2Long(startIP) + 1; - //check resource limits + // check resource limits _resourceLimitMgr.checkResourceLimit(vlanOwner, ResourceType.public_ip, accountIpRange); } } // Check if the IP range overlaps with the private ip if (ipv4) { - checkOverlapPrivateIpRange(zoneId, startIP, endIP); + checkOverlapPrivateIpRange(zoneId, startIP, endIP); } Transaction txn = Transaction.currentTxn(); txn.start(); + if (sameSubnet == null || sameSubnet.first() == false) { - s_logger.info("adding a new subnet to the network "+network.getId()); - } - else { - // if it is same subnet the user might not send the vlan and the netmask details. so we are - //figuring out while validation and setting them here. + s_logger.info("adding a new subnet to the network " + network.getId()); + } else { + // if it is same subnet the user might not send the vlan and the + // netmask details. so we are + // figuring out while validation and setting them here. newVlanGateway = sameSubnet.second().first(); newVlanNetmask = sameSubnet.second().second(); } - Vlan vlan = createVlanAndPublicIpRange(zoneId, networkId, physicalNetworkId, forVirtualNetwork, podId, startIP, + Vlan vlan = createVlanAndPublicIpRange(zoneId, networkId, physicalNetworkId, forVirtualNetwork, podId, startIP, endIP, newVlanGateway, newVlanNetmask, vlanId, vlanOwner, startIPv6, endIPv6, ip6Gateway, ip6Cidr); - //create an entry in the nic_secondary table. This will be the new gateway that will be configured on the corresponding routervm. - + // create an entry in the nic_secondary table. This will be the new + // gateway that will be configured on the corresponding routervm. txn.commit(); return vlan; } - public int checkIfSubsetOrSuperset(String newVlanGateway, String newVlanNetmask, VlanVO vlan, String startIP, String endIP) { - if (newVlanGateway == null && newVlanNetmask==null) { + public int checkIfSubsetOrSuperset(String newVlanGateway, String newVlanNetmask, VlanVO vlan, String startIP, + String endIP) { + if (newVlanGateway == null && newVlanNetmask == null) { newVlanGateway = vlan.getVlanGateway(); newVlanNetmask = vlan.getVlanNetmask(); - //this means he is trying to add to the existing subnet. + // this means he is trying to add to the existing subnet. if (NetUtils.sameSubnet(startIP, newVlanGateway, newVlanNetmask)) { - if (NetUtils.sameSubnet(endIP, newVlanGateway, newVlanNetmask)){ + if (NetUtils.sameSubnet(endIP, newVlanGateway, newVlanNetmask)) { return 3; } } return 0; - } - else if (newVlanGateway == null || newVlanGateway ==null){ - throw new InvalidParameterValueException("either both netmask and gateway should be passed or both should me omited."); - } - else { + } else if (newVlanGateway == null || newVlanGateway == null) { + throw new InvalidParameterValueException( + "either both netmask and gateway should be passed or both should me omited."); + } else { if (!NetUtils.sameSubnet(startIP, newVlanGateway, newVlanNetmask)) { throw new InvalidParameterValueException("The start ip and gateway do not belong to the same subnet"); } @@ -2597,43 +2731,50 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati String cidrnew = NetUtils.getCidrFromGatewayAndNetmask(newVlanGateway, newVlanNetmask); String existing_cidr = NetUtils.getCidrFromGatewayAndNetmask(vlan.getVlanGateway(), vlan.getVlanNetmask()); - return (NetUtils.isNetowrkASubsetOrSupersetOfNetworkB(cidrnew, existing_cidr)); + return (NetUtils.isNetowrkASubsetOrSupersetOfNetworkB(cidrnew, existing_cidr)); } - public Pair> validateIpRange(String startIP, String endIP, String newVlanGateway, String newVlanNetmask, List vlans, boolean ipv4, boolean ipv6, String ip6Gateway, String ip6Cidr, String startIPv6, String endIPv6, Network network) { - String vlanGateway=null; - String vlanNetmask=null; + public Pair> validateIpRange(String startIP, String endIP, String newVlanGateway, + String newVlanNetmask, List vlans, boolean ipv4, boolean ipv6, String ip6Gateway, String ip6Cidr, + String startIPv6, String endIPv6, Network network) { + String vlanGateway = null; + String vlanNetmask = null; boolean sameSubnet = false; - if ( vlans != null && vlans.size() > 0 ) { + if (vlans != null && vlans.size() > 0) { for (VlanVO vlan : vlans) { if (ipv4) { vlanGateway = vlan.getVlanGateway(); vlanNetmask = vlan.getVlanNetmask(); - //check if subset or super set or neither. + // check if subset or super set or neither. int val = checkIfSubsetOrSuperset(newVlanGateway, newVlanNetmask, vlan, startIP, endIP); if (val == 1) { - // this means that new cidr is a superset of the existing subnet. - throw new InvalidParameterValueException("The subnet you are trying to add is a superset of the existing subnet having gateway"+vlan.getVlanGateway()+" and netmask "+vlan.getVlanNetmask()); - } - else if (val == 0) { - //this implies the user is trying to add a new subnet which is not a superset or subset of this subnet. - //checking with the other subnets. + // this means that new cidr is a superset of the + // existing subnet. + throw new InvalidParameterValueException( + "The subnet you are trying to add is a superset of the existing subnet having gateway" + + vlan.getVlanGateway() + " and netmask " + vlan.getVlanNetmask()); + } else if (val == 0) { + // this implies the user is trying to add a new subnet + // which is not a superset or subset of this subnet. + // checking with the other subnets. continue; - } - else if (val == 2) { - //this means he is trying to add to the same subnet. - throw new InvalidParameterValueException("The subnet you are trying to add is a subset of the existing subnet having gateway"+vlan.getVlanGateway()+" and netmask "+vlan.getVlanNetmask()); - } - else if (val == 3) { - sameSubnet =true; + } else if (val == 2) { + // this means he is trying to add to the same subnet. + throw new InvalidParameterValueException( + "The subnet you are trying to add is a subset of the existing subnet having gateway" + + vlan.getVlanGateway() + " and netmask " + vlan.getVlanNetmask()); + } else if (val == 3) { + sameSubnet = true; } } if (ipv6) { if (ip6Gateway != null && !ip6Gateway.equals(network.getIp6Gateway())) { - throw new InvalidParameterValueException("The input gateway " + ip6Gateway + " is not same as network gateway " + network.getIp6Gateway()); + throw new InvalidParameterValueException("The input gateway " + ip6Gateway + + " is not same as network gateway " + network.getIp6Gateway()); } if (ip6Cidr != null && !ip6Cidr.equals(network.getIp6Cidr())) { - throw new InvalidParameterValueException("The input cidr " + ip6Cidr + " is not same as network ciddr " + network.getIp6Cidr()); + throw new InvalidParameterValueException("The input cidr " + ip6Cidr + + " is not same as network ciddr " + network.getIp6Cidr()); } ip6Gateway = network.getIp6Gateway(); ip6Cidr = network.getIp6Cidr(); @@ -2641,48 +2782,50 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } } - if (newVlanGateway==null && newVlanNetmask ==null && sameSubnet == false) { - throw new InvalidParameterValueException("The ip range dose not belong to any of the existing subnets, Provide the netmask and gateway if you want to add new subnet"); + if (newVlanGateway == null && newVlanNetmask == null && sameSubnet == false) { + throw new InvalidParameterValueException( + "The ip range dose not belong to any of the existing subnets, Provide the netmask and gateway if you want to add new subnet"); } - Pair vlanDetails=null; + Pair vlanDetails = null; - if (sameSubnet){ - vlanDetails = new Pair(vlanGateway, vlanNetmask); + if (sameSubnet) { + vlanDetails = new Pair(vlanGateway, vlanNetmask); + } else { + vlanDetails = new Pair(newVlanGateway, newVlanNetmask); } - else { - vlanDetails = new Pair(newVlanGateway, newVlanNetmask); - } - //check if the gatewayip is the part of the ip range being added. + // check if the gatewayip is the part of the ip range being added. if (NetUtils.ipRangesOverlap(startIP, endIP, vlanDetails.first(), vlanDetails.first())) { - throw new InvalidParameterValueException("The gateway ip should not be the part of the ip range being added."); + throw new InvalidParameterValueException( + "The gateway ip should not be the part of the ip range being added."); } - Pair> result = new Pair>(sameSubnet, vlanDetails); - return result; + Pair> result = new Pair>(sameSubnet, vlanDetails); + return result; } @Override @DB - public Vlan createVlanAndPublicIpRange(long zoneId, long networkId, long physicalNetworkId, boolean forVirtualNetwork, Long podId, - String startIP, String endIP, String vlanGateway, String vlanNetmask, - String vlanId, Account vlanOwner, String startIPv6, String endIPv6, String vlanIp6Gateway, String vlanIp6Cidr) { + public Vlan createVlanAndPublicIpRange(long zoneId, long networkId, long physicalNetworkId, + boolean forVirtualNetwork, Long podId, String startIP, String endIP, String vlanGateway, + String vlanNetmask, String vlanId, Account vlanOwner, String startIPv6, String endIPv6, + String vlanIp6Gateway, String vlanIp6Cidr) { Network network = _networkModel.getNetwork(networkId); boolean ipv4 = false, ipv6 = false; if (startIP != null) { - ipv4 = true; + ipv4 = true; } if (startIPv6 != null) { - ipv6 = true; + ipv6 = true; } if (!ipv4 && !ipv6) { throw new InvalidParameterValueException("Please specify IPv4 or IPv6 address."); } - //Validate the zone + // Validate the zone DataCenterVO zone = _zoneDao.findById(zoneId); if (zone == null) { throw new InvalidParameterValueException("Please specify a valid zone."); @@ -2691,12 +2834,12 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // ACL check checkZoneAccess(UserContext.current().getCaller(), zone); - //Validate the physical network + // Validate the physical network if (_physicalNetworkDao.findById(physicalNetworkId) == null) { throw new InvalidParameterValueException("Please specify a valid physical network id"); } - //Validate the pod + // Validate the pod if (podId != null) { Pod pod = _podDao.findById(podId); if (pod == null) { @@ -2705,27 +2848,29 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (pod.getDataCenterId() != zoneId) { throw new InvalidParameterValueException("Pod id=" + podId + " doesn't belong to zone id=" + zoneId); } - //pod vlans can be created in basic zone only + // pod vlans can be created in basic zone only if (zone.getNetworkType() != NetworkType.Basic || network.getTrafficType() != TrafficType.Guest) { throw new InvalidParameterValueException("Pod id can be specified only for the networks of type " - + TrafficType.Guest + " in zone of type " + NetworkType.Basic); + + TrafficType.Guest + " in zone of type " + NetworkType.Basic); } } - //1) if vlan is specified for the guest network range, it should be the same as network's vlan - //2) if vlan is missing, default it to the guest network's vlan + // 1) if vlan is specified for the guest network range, it should be the + // same as network's vlan + // 2) if vlan is missing, default it to the guest network's vlan if (network.getTrafficType() == TrafficType.Guest) { String networkVlanId = null; URI uri = network.getBroadcastUri(); if (uri != null) { String[] vlan = uri.toString().split("vlan:\\/\\/"); networkVlanId = vlan[1]; - //For pvlan + // For pvlan networkVlanId = networkVlanId.split("-")[0]; } if (vlanId != null) { - // if vlan is specified, throw an error if it's not equal to network's vlanId + // if vlan is specified, throw an error if it's not equal to + // network's vlanId if (networkVlanId != null && !networkVlanId.equalsIgnoreCase(vlanId)) { throw new InvalidParameterValueException("Vlan doesn't match vlan of the network"); } @@ -2733,7 +2878,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati vlanId = networkVlanId; } } else if (network.getTrafficType() == TrafficType.Public && vlanId == null) { - //vlan id is required for public network + // vlan id is required for public network throw new InvalidParameterValueException("Vlan id is required when add ip range to the public network"); } @@ -2743,180 +2888,200 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati VlanType vlanType = forVirtualNetwork ? VlanType.VirtualNetwork : VlanType.DirectAttached; - if (vlanOwner != null && zone.getNetworkType() != NetworkType.Advanced) { - throw new InvalidParameterValueException("Vlan owner can be defined only in the zone of type " + NetworkType.Advanced); + throw new InvalidParameterValueException("Vlan owner can be defined only in the zone of type " + + NetworkType.Advanced); } if (ipv4) { - // Make sure the gateway is valid - if (!NetUtils.isValidIp(vlanGateway)) { - throw new InvalidParameterValueException("Please specify a valid gateway"); - } + // Make sure the gateway is valid + if (!NetUtils.isValidIp(vlanGateway)) { + throw new InvalidParameterValueException("Please specify a valid gateway"); + } - // Make sure the netmask is valid - if (!NetUtils.isValidIp(vlanNetmask)) { - throw new InvalidParameterValueException("Please specify a valid netmask"); - } + // Make sure the netmask is valid + if (!NetUtils.isValidIp(vlanNetmask)) { + throw new InvalidParameterValueException("Please specify a valid netmask"); + } } if (ipv6) { - if (!NetUtils.isValidIpv6(vlanIp6Gateway)) { - throw new InvalidParameterValueException("Please specify a valid IPv6 gateway"); - } - if (!NetUtils.isValidIp6Cidr(vlanIp6Cidr)) { - throw new InvalidParameterValueException("Please specify a valid IPv6 CIDR"); - } + if (!NetUtils.isValidIpv6(vlanIp6Gateway)) { + throw new InvalidParameterValueException("Please specify a valid IPv6 gateway"); + } + if (!NetUtils.isValidIp6Cidr(vlanIp6Cidr)) { + throw new InvalidParameterValueException("Please specify a valid IPv6 CIDR"); + } } if (ipv4) { - String newVlanSubnet = NetUtils.getSubNet(vlanGateway, vlanNetmask); + String newVlanSubnet = NetUtils.getSubNet(vlanGateway, vlanNetmask); - // Check if the new VLAN's subnet conflicts with the guest network in - // the specified zone (guestCidr is null for basic zone) - String guestNetworkCidr = zone.getGuestNetworkCidr(); - if (guestNetworkCidr != null) { - String[] cidrPair = guestNetworkCidr.split("\\/"); - String guestIpNetwork = NetUtils.getIpRangeStartIpFromCidr(cidrPair[0], Long.parseLong(cidrPair[1])); - long guestCidrSize = Long.parseLong(cidrPair[1]); - long vlanCidrSize = NetUtils.getCidrSize(vlanNetmask); + // Check if the new VLAN's subnet conflicts with the guest network + // in + // the specified zone (guestCidr is null for basic zone) + String guestNetworkCidr = zone.getGuestNetworkCidr(); + if (guestNetworkCidr != null) { + String[] cidrPair = guestNetworkCidr.split("\\/"); + String guestIpNetwork = NetUtils.getIpRangeStartIpFromCidr(cidrPair[0], Long.parseLong(cidrPair[1])); + long guestCidrSize = Long.parseLong(cidrPair[1]); + long vlanCidrSize = NetUtils.getCidrSize(vlanNetmask); - long cidrSizeToUse = -1; - if (vlanCidrSize < guestCidrSize) { - cidrSizeToUse = vlanCidrSize; - } else { - cidrSizeToUse = guestCidrSize; - } + long cidrSizeToUse = -1; + if (vlanCidrSize < guestCidrSize) { + cidrSizeToUse = vlanCidrSize; + } else { + cidrSizeToUse = guestCidrSize; + } - String guestSubnet = NetUtils.getCidrSubNet(guestIpNetwork, cidrSizeToUse); + String guestSubnet = NetUtils.getCidrSubNet(guestIpNetwork, cidrSizeToUse); - if (newVlanSubnet.equals(guestSubnet)) { - throw new InvalidParameterValueException("The new IP range you have specified has the same subnet as the guest network in zone: " + zone.getName() - + ". Please specify a different gateway/netmask."); - } - } + if (newVlanSubnet.equals(guestSubnet)) { + throw new InvalidParameterValueException( + "The new IP range you have specified has the same subnet as the guest network in zone: " + + zone.getName() + ". Please specify a different gateway/netmask."); + } + } - // Check if there are any errors with the IP range - checkPublicIpRangeErrors(zoneId, vlanId, vlanGateway, vlanNetmask, startIP, endIP); + // Check if there are any errors with the IP range + checkPublicIpRangeErrors(zoneId, vlanId, vlanGateway, vlanNetmask, startIP, endIP); - // Throw an exception if any of the following is true: - // 1. Another VLAN in the same zone has a different tag but the same - // subnet as the new VLAN. Make an exception for the - // case when both vlans are Direct. - // 2. Another VLAN in the same zone that has the same tag and subnet as - // the new VLAN has IPs that overlap with the IPs - // being added - // 3. Another VLAN in the same zone that has the same tag and subnet as - // the new VLAN has a different gateway than the - // new VLAN - // 4. If VLAN is untagged and Virtual, and there is existing UNTAGGED - // vlan with different subnet - List vlans = _vlanDao.listByZone(zone.getId()); - for (VlanVO vlan : vlans) { - String otherVlanGateway = vlan.getVlanGateway(); - // Continue if it's not IPv4 - if (otherVlanGateway == null) { - continue; - } - String otherVlanSubnet = NetUtils.getSubNet(vlan.getVlanGateway(), vlan.getVlanNetmask()); - String[] otherVlanIpRange = vlan.getIpRange().split("\\-"); - String otherVlanStartIP = otherVlanIpRange[0]; - String otherVlanEndIP = null; - if (otherVlanIpRange.length > 1) { - otherVlanEndIP = otherVlanIpRange[1]; - } + // Throw an exception if any of the following is true: + // 1. Another VLAN in the same zone has a different tag but the same + // subnet as the new VLAN. Make an exception for the + // case when both vlans are Direct. + // 2. Another VLAN in the same zone that has the same tag and subnet + // as + // the new VLAN has IPs that overlap with the IPs + // being added + // 3. Another VLAN in the same zone that has the same tag and subnet + // as + // the new VLAN has a different gateway than the + // new VLAN + // 4. If VLAN is untagged and Virtual, and there is existing + // UNTAGGED + // vlan with different subnet + List vlans = _vlanDao.listByZone(zone.getId()); + for (VlanVO vlan : vlans) { + String otherVlanGateway = vlan.getVlanGateway(); + // Continue if it's not IPv4 + if (otherVlanGateway == null) { + continue; + } + String otherVlanSubnet = NetUtils.getSubNet(vlan.getVlanGateway(), vlan.getVlanNetmask()); + String[] otherVlanIpRange = vlan.getIpRange().split("\\-"); + String otherVlanStartIP = otherVlanIpRange[0]; + String otherVlanEndIP = null; + if (otherVlanIpRange.length > 1) { + otherVlanEndIP = otherVlanIpRange[1]; + } - if (forVirtualNetwork && !vlanId.equals(vlan.getVlanTag()) && newVlanSubnet.equals(otherVlanSubnet) && !allowIpRangeOverlap(vlan, forVirtualNetwork, networkId)) { - throw new InvalidParameterValueException("The IP range with tag: " + vlan.getVlanTag() + " in zone " + zone.getName() - + " has the same subnet. Please specify a different gateway/netmask."); - } + if (forVirtualNetwork && !vlanId.equals(vlan.getVlanTag()) && newVlanSubnet.equals(otherVlanSubnet) + && !allowIpRangeOverlap(vlan, forVirtualNetwork, networkId)) { + throw new InvalidParameterValueException("The IP range with tag: " + vlan.getVlanTag() + + " in zone " + zone.getName() + + " has the same subnet. Please specify a different gateway/netmask."); + } - boolean vlansUntaggedAndVirtual = (vlanId.equals(Vlan.UNTAGGED) && vlanId.equals(vlan.getVlanTag()) && forVirtualNetwork && vlan.getVlanType() == VlanType.VirtualNetwork); + boolean vlansUntaggedAndVirtual = (vlanId.equals(Vlan.UNTAGGED) && vlanId.equals(vlan.getVlanTag()) + && forVirtualNetwork && vlan.getVlanType() == VlanType.VirtualNetwork); - if (vlansUntaggedAndVirtual && !newVlanSubnet.equals(otherVlanSubnet)) { - throw new InvalidParameterValueException("The Untagged ip range with different subnet already exists in zone " + zone.getId()); - } + if (vlansUntaggedAndVirtual && !newVlanSubnet.equals(otherVlanSubnet)) { + throw new InvalidParameterValueException( + "The Untagged ip range with different subnet already exists in zone " + zone.getId()); + } - if (vlanId.equals(vlan.getVlanTag()) && newVlanSubnet.equals(otherVlanSubnet)) { - if (NetUtils.ipRangesOverlap(startIP, endIP, otherVlanStartIP, otherVlanEndIP)) { - throw new InvalidParameterValueException("The IP range with tag: " + vlan.getVlanTag() - + " already has IPs that overlap with the new range. Please specify a different start IP/end IP."); - } + if (vlanId.equals(vlan.getVlanTag()) && newVlanSubnet.equals(otherVlanSubnet)) { + if (NetUtils.ipRangesOverlap(startIP, endIP, otherVlanStartIP, otherVlanEndIP)) { + throw new InvalidParameterValueException( + "The IP range with tag: " + + vlan.getVlanTag() + + " already has IPs that overlap with the new range. Please specify a different start IP/end IP."); + } - if (!vlanGateway.equals(otherVlanGateway)) { - throw new InvalidParameterValueException("The IP range with tag: " + vlan.getVlanTag() + " has already been added with gateway " + otherVlanGateway - + ". Please specify a different tag."); - } - } - } + if (!vlanGateway.equals(otherVlanGateway)) { + throw new InvalidParameterValueException("The IP range with tag: " + vlan.getVlanTag() + + " has already been added with gateway " + otherVlanGateway + + ". Please specify a different tag."); + } + } + } } String ipv6Range = null; if (ipv6) { - ipv6Range = startIPv6; - if (endIPv6 != null) { - ipv6Range += "-" + endIPv6; - } + ipv6Range = startIPv6; + if (endIPv6 != null) { + ipv6Range += "-" + endIPv6; + } - List vlans = _vlanDao.listByZone(zone.getId()); - for (VlanVO vlan : vlans) { - if (vlan.getIp6Gateway() == null) { - continue; - } - if (vlanId.equals(vlan.getVlanTag())) { - if (NetUtils.isIp6RangeOverlap(ipv6Range, vlan.getIp6Range())) { - throw new InvalidParameterValueException("The IPv6 range with tag: " + vlan.getVlanTag() - + " already has IPs that overlap with the new range. Please specify a different start IP/end IP."); - } + List vlans = _vlanDao.listByZone(zone.getId()); + for (VlanVO vlan : vlans) { + if (vlan.getIp6Gateway() == null) { + continue; + } + if (vlanId.equals(vlan.getVlanTag())) { + if (NetUtils.isIp6RangeOverlap(ipv6Range, vlan.getIp6Range())) { + throw new InvalidParameterValueException( + "The IPv6 range with tag: " + + vlan.getVlanTag() + + " already has IPs that overlap with the new range. Please specify a different start IP/end IP."); + } - if (!vlanIp6Gateway.equals(vlan.getIp6Gateway())) { - throw new InvalidParameterValueException("The IP range with tag: " + vlan.getVlanTag() + " has already been added with gateway " + vlan.getIp6Gateway() - + ". Please specify a different tag."); - } - } - } + if (!vlanIp6Gateway.equals(vlan.getIp6Gateway())) { + throw new InvalidParameterValueException("The IP range with tag: " + vlan.getVlanTag() + + " has already been added with gateway " + vlan.getIp6Gateway() + + ". Please specify a different tag."); + } + } + } } // Check if a guest VLAN is using the same tag if (_zoneDao.findVnet(zoneId, physicalNetworkId, vlanId).size() > 0) { - throw new InvalidParameterValueException("The VLAN tag " + vlanId + " is already being used for the guest network in zone " + zone.getName()); + throw new InvalidParameterValueException("The VLAN tag " + vlanId + + " is already being used for the guest network in zone " + zone.getName()); } String ipRange = null; if (ipv4) { - ipRange = startIP; - if (endIP != null) { - ipRange += "-" + endIP; - } + ipRange = startIP; + if (endIP != null) { + ipRange += "-" + endIP; + } } // Everything was fine, so persist the VLAN Transaction txn = Transaction.currentTxn(); txn.start(); - VlanVO vlan = new VlanVO(vlanType, vlanId, vlanGateway, vlanNetmask, zone.getId(), ipRange, networkId, physicalNetworkId, vlanIp6Gateway, vlanIp6Cidr, ipv6Range); + VlanVO vlan = new VlanVO(vlanType, vlanId, vlanGateway, vlanNetmask, zone.getId(), ipRange, networkId, + physicalNetworkId, vlanIp6Gateway, vlanIp6Cidr, ipv6Range); s_logger.debug("Saving vlan range " + vlan); vlan = _vlanDao.persist(vlan); - // IPv6 use a used ip map, is different from ipv4, no need to save public ip range + // IPv6 use a used ip map, is different from ipv4, no need to save + // public ip range if (ipv4) { - if (!savePublicIPRange(startIP, endIP, zoneId, vlan.getId(), networkId, physicalNetworkId)) { - throw new CloudRuntimeException("Failed to save IPv4 range. Please contact Cloud Support."); - } + if (!savePublicIPRange(startIP, endIP, zoneId, vlan.getId(), networkId, physicalNetworkId)) { + throw new CloudRuntimeException("Failed to save IPv4 range. Please contact Cloud Support."); + } } if (vlanOwner != null) { - // This VLAN is account-specific, so create an AccountVlanMapVO entry + // This VLAN is account-specific, so create an AccountVlanMapVO + // entry AccountVlanMapVO accountVlanMapVO = new AccountVlanMapVO(vlanOwner.getId(), vlan.getId()); _accountVlanMapDao.persist(accountVlanMapVO); - // generate usage event for dedication of every ip address in the range + // generate usage event for dedication of every ip address in the + // range List ips = _publicIpAddressDao.listByVlanId(vlan.getId()); for (IPAddressVO ip : ips) { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_IP_ASSIGN, vlanOwner.getId(), - ip.getDataCenterId(), ip.getId(), ip.getAddress().toString(), ip.isSourceNat(), vlan.getVlanType().toString(), - ip.getSystem(), ip.getClass().getName(), ip.getUuid()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_IP_ASSIGN, vlanOwner.getId(), ip + .getDataCenterId(), ip.getId(), ip.getAddress().toString(), ip.isSourceNat(), vlan + .getVlanType().toString(), ip.getSystem(), ip.getClass().getName(), ip.getUuid()); } // increment resource count for dedicated public ip's _resourceLimitMgr.incrementResourceCount(vlanOwner.getId(), ResourceType.public_ip, new Long(ips.size())); @@ -2940,7 +3105,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Override @DB - public boolean deleteVlanAndPublicIpRange(long userId, long vlanDbId, Account caller) { + public boolean deleteVlanAndPublicIpRange(long userId, long vlanDbId, Account caller) { VlanVO vlanRange = _vlanDao.findById(vlanDbId); if (vlanRange == null) { throw new InvalidParameterValueException("Please specify a valid IP range id."); @@ -2948,7 +3113,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati boolean isAccountSpecific = false; List acctVln = _accountVlanMapDao.listAccountVlanMapsByVlan(vlanRange.getId()); - // Check for account wide pool. It will have an entry for account_vlan_map. + // Check for account wide pool. It will have an entry for + // account_vlan_map. if (acctVln != null && !acctVln.isEmpty()) { isAccountSpecific = true; } @@ -2968,43 +3134,54 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (s_logger.isDebugEnabled()) { s_logger.debug("lock vlan " + vlanDbId + " is acquired"); } - for (IPAddressVO ip : ips) { if (ip.isOneToOneNat()) { - throw new InvalidParameterValueException("Can't delete account specific vlan " + vlanDbId + - " as ip " + ip + " belonging to the range is used for static nat purposes. Cleanup the rules first"); + throw new InvalidParameterValueException( + "Can't delete account specific vlan " + + vlanDbId + + " as ip " + + ip + + " belonging to the range is used for static nat purposes. Cleanup the rules first"); } - + if (ip.isSourceNat()) { - throw new InvalidParameterValueException("Can't delete account specific vlan " + vlanDbId + - " as ip " + ip + " belonging to the range is a source nat ip for the network id=" + ip.getSourceNetworkId() + - ". IP range with the source nat ip address can be removed either as a part of Network, or account removal"); + throw new InvalidParameterValueException( + "Can't delete account specific vlan " + + vlanDbId + + " as ip " + + ip + + " belonging to the range is a source nat ip for the network id=" + + ip.getSourceNetworkId() + + ". IP range with the source nat ip address can be removed either as a part of Network, or account removal"); } if (_firewallDao.countRulesByIpId(ip.getId()) > 0) { - throw new InvalidParameterValueException("Can't delete account specific vlan " + vlanDbId + - " as ip " + ip + " belonging to the range has firewall rules applied. Cleanup the rules first"); + throw new InvalidParameterValueException("Can't delete account specific vlan " + vlanDbId + + " as ip " + ip + + " belonging to the range has firewall rules applied. Cleanup the rules first"); } - //release public ip address here + // release public ip address here success = success && _networkMgr.disassociatePublicIpAddress(ip.getId(), userId, caller); } if (!success) { - s_logger.warn("Some ip addresses failed to be released as a part of vlan " + vlanDbId + " removal"); + s_logger.warn("Some ip addresses failed to be released as a part of vlan " + vlanDbId + + " removal"); } } finally { _vlanDao.releaseFromLockTable(vlanDbId); - } + } } } if (success) { // Delete all public IPs in the VLAN - // if ip range is dedicated to an account generate usage events for release of every ip in the range - if(isAccountSpecific) { + // if ip range is dedicated to an account generate usage events for + // release of every ip in the range + if (isAccountSpecific) { for (IPAddressVO ip : ips) { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_IP_RELEASE, acctVln.get(0).getId(), - ip.getDataCenterId(), ip.getId(), ip.getAddress().toString(), ip.isSourceNat(), vlanRange.getVlanType().toString(), - ip.getSystem(), ip.getClass().getName(), ip.getUuid()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_IP_RELEASE, acctVln.get(0).getId(), ip + .getDataCenterId(), ip.getId(), ip.getAddress().toString(), ip.isSourceNat(), vlanRange + .getVlanType().toString(), ip.getSystem(), ip.getClass().getName(), ip.getUuid()); } } if (_networkModel.areServicesSupportedInNetwork(vlanRange.getNetworkId(), Service.Dhcp)) { @@ -3018,11 +3195,13 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati txn.close(); return false; } + else { txn.commit(); } txn.close(); } + else { return handleIpAliasDeletion(vlanRange, vlanDbId, dhcpServiceProvider, network); } @@ -3062,22 +3241,25 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (result == false) { result_final = false; s_logger.debug("Failed to delete the vlan range as we could not free the ip used to provide the dhcp service."); - } - else { + } else { _publicIpAddressDao.unassignIpAddress(ip.getId()); result_final = true; } } else { - // if there are more vlans in the subnet check if there are free ips. + // if there are more vlans in the subnet check if there + // are free ips. List vlanDbIdList = new ArrayList(); for (VlanVO vlanrange : vlanRanges) { if (vlanrange.getId() != vlanDbId) { vlanDbIdList.add(vlanrange.getId()); } } - s_logger.info("vlan Range"+vlanRange.getId()+" id being deleted, one of the Ips in this range is used to provide the dhcp service, trying to free this ip and allocate a new one."); + s_logger.info("vlan Range" + + vlanRange.getId() + + " id being deleted, one of the Ips in this range is used to provide the dhcp service, trying to free this ip and allocate a new one."); for (VlanVO vlanrange : vlanRanges) { if (vlanrange.getId() != vlanDbId) { + long freeIpsInsubnet = _publicIpAddressDao.countFreeIpsInVlan(vlanrange.getId()); if (freeIpsInsubnet > 0){ //assign one free ip to the router for creating ip Alias. The ipalias is system managed ip so we are using the system account to allocate the ip not the caller. @@ -3124,7 +3306,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Override @DB - @ActionEvent(eventType = EventTypes.EVENT_VLAN_IP_RANGE_DEDICATE, eventDescription = "dedicating vlan ip range", async = false) + @ActionEvent(eventType = EventTypes.EVENT_VLAN_IP_RANGE_DEDICATE, eventDescription = "dedicating vlan ip range", + async = false) public Vlan dedicatePublicIpRange(DedicatePublicIpRangeCmd cmd) throws ResourceAllocationException { Long vlanDbId = cmd.getId(); String accountName = cmd.getAccountName(); @@ -3149,7 +3332,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (vlanOwner == null) { throw new InvalidParameterValueException("Unable to find account by name " + accountName); } else if (vlanOwner.getId() == Account.ACCOUNT_ID_SYSTEM) { - throw new InvalidParameterValueException("Please specify a valid account. Cannot dedicate IP range to system account"); + throw new InvalidParameterValueException( + "Please specify a valid account. Cannot dedicate IP range to system account"); } } @@ -3172,21 +3356,24 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new InvalidParameterValueException("Unable to find zone by id " + zoneId); } if (zone.getNetworkType() == NetworkType.Basic) { - throw new InvalidParameterValueException("Public IP range can be dedicated to an account only in the zone of type " + NetworkType.Advanced); + throw new InvalidParameterValueException( + "Public IP range can be dedicated to an account only in the zone of type " + NetworkType.Advanced); } // Check Public IP resource limits int accountPublicIpRange = _publicIpAddressDao.countIPs(zoneId, vlanDbId, false); _resourceLimitMgr.checkResourceLimit(vlanOwner, ResourceType.public_ip, accountPublicIpRange); - // Check if any of the Public IP addresses is allocated to another account + // Check if any of the Public IP addresses is allocated to another + // account List ips = _publicIpAddressDao.listByVlanId(vlanDbId); for (IPAddressVO ip : ips) { Long allocatedToAccountId = ip.getAllocatedToAccountId(); if (allocatedToAccountId != null) { Account accountAllocatedTo = _accountMgr.getActiveAccountById(allocatedToAccountId); if (!accountAllocatedTo.getAccountName().equalsIgnoreCase(accountName)) - throw new InvalidParameterValueException(ip.getAddress() + " Public IP address in range is allocated to another account "); + throw new InvalidParameterValueException(ip.getAddress() + + " Public IP address in range is allocated to another account "); } } @@ -3201,8 +3388,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // generate usage event for dedication of every ip address in the range for (IPAddressVO ip : ips) { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_IP_ASSIGN, vlanOwner.getId(), - ip.getDataCenterId(), ip.getId(), ip.getAddress().toString(), ip.isSourceNat(), vlan.getVlanType().toString(), + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_IP_ASSIGN, vlanOwner.getId(), ip.getDataCenterId(), + ip.getId(), ip.getAddress().toString(), ip.isSourceNat(), vlan.getVlanType().toString(), ip.getSystem(), ip.getClass().getName(), ip.getUuid()); } @@ -3213,7 +3400,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } @Override - @ActionEvent(eventType = EventTypes.EVENT_VLAN_IP_RANGE_RELEASE, eventDescription = "releasing a public ip range", async = false) + @ActionEvent(eventType = EventTypes.EVENT_VLAN_IP_RANGE_RELEASE, eventDescription = "releasing a public ip range", + async = false) public boolean releasePublicIpRange(ReleasePublicIpRangeCmd cmd) { Long vlanDbId = cmd.getId(); @@ -3222,10 +3410,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new InvalidParameterValueException("Please specify a valid IP range id."); } - return releasePublicIpRange(vlanDbId, UserContext.current().getCallerUserId(), UserContext.current().getCaller()); + return releasePublicIpRange(vlanDbId, UserContext.current().getCallerUserId(), UserContext.current() + .getCaller()); } - @DB public boolean releasePublicIpRange(long vlanDbId, long userId, Account caller) { VlanVO vlan = _vlanDao.findById(vlanDbId); @@ -3233,7 +3421,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati List acctVln = _accountVlanMapDao.listAccountVlanMapsByVlan(vlanDbId); // Verify range is dedicated if (acctVln == null || acctVln.isEmpty()) { - throw new InvalidParameterValueException("Can't release Public IP range " + vlanDbId + " as it not dedicated to any account"); + throw new InvalidParameterValueException("Can't release Public IP range " + vlanDbId + + " as it not dedicated to any account"); } // Check if range has any allocated public IPs @@ -3251,17 +3440,17 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } for (IPAddressVO ip : ips) { // Disassociate allocated IP's that are not in use - if ( !ip.isOneToOneNat() && !ip.isSourceNat() && !(_firewallDao.countRulesByIpId(ip.getId()) > 0) ) { + if (!ip.isOneToOneNat() && !ip.isSourceNat() && !(_firewallDao.countRulesByIpId(ip.getId()) > 0)) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Releasing Public IP addresses" + ip +" of vlan " + vlanDbId + " as part of Public IP" + - " range release to the system pool"); + s_logger.debug("Releasing Public IP addresses" + ip + " of vlan " + vlanDbId + + " as part of Public IP" + " range release to the system pool"); } success = success && _networkMgr.disassociatePublicIpAddress(ip.getId(), userId, caller); } } if (!success) { - s_logger.warn("Some Public IP addresses that were not in use failed to be released as a part of" + - " vlan " + vlanDbId + "release to the system pool"); + s_logger.warn("Some Public IP addresses that were not in use failed to be released as a part of" + + " vlan " + vlanDbId + "release to the system pool"); } } finally { _vlanDao.releaseFromLockTable(vlanDbId); @@ -3270,14 +3459,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // A Public IP range can only be dedicated to one account at a time if (_accountVlanMapDao.remove(acctVln.get(0).getId())) { - // generate usage events to remove dedication for every ip in the range + // generate usage events to remove dedication for every ip in the + // range for (IPAddressVO ip : ips) { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_IP_RELEASE, acctVln.get(0).getAccountId(), - ip.getDataCenterId(), ip.getId(), ip.getAddress().toString(), ip.isSourceNat(), vlan.getVlanType().toString(), - ip.getSystem(), ip.getClass().getName(), ip.getUuid()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_IP_RELEASE, acctVln.get(0).getAccountId(), ip + .getDataCenterId(), ip.getId(), ip.getAddress().toString(), ip.isSourceNat(), vlan + .getVlanType().toString(), ip.getSystem(), ip.getClass().getName(), ip.getUuid()); } // decrement resource count for dedicated public ip's - _resourceLimitMgr.decrementResourceCount(acctVln.get(0).getAccountId(), ResourceType.public_ip, new Long(ips.size())); + _resourceLimitMgr.decrementResourceCount(acctVln.get(0).getAccountId(), ResourceType.public_ip, new Long( + ips.size())); return true; } else { return false; @@ -3347,20 +3538,22 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati return true; } - @DB - protected boolean savePublicIPRange(String startIP, String endIP, long zoneId, long vlanDbId, long sourceNetworkid, long physicalNetworkId) { + protected boolean savePublicIPRange(String startIP, String endIP, long zoneId, long vlanDbId, long sourceNetworkid, + long physicalNetworkId) { long startIPLong = NetUtils.ip2Long(startIP); long endIPLong = NetUtils.ip2Long(endIP); Transaction txn = Transaction.currentTxn(); txn.start(); IPRangeConfig config = new IPRangeConfig(); - List problemIps = config.savePublicIPRange(txn, startIPLong, endIPLong, zoneId, vlanDbId, sourceNetworkid, physicalNetworkId); + List problemIps = config.savePublicIPRange(txn, startIPLong, endIPLong, zoneId, vlanDbId, + sourceNetworkid, physicalNetworkId); txn.commit(); return problemIps != null && problemIps.size() == 0; } - private void checkPublicIpRangeErrors(long zoneId, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP) { + private void checkPublicIpRangeErrors(long zoneId, String vlanId, String vlanGateway, String vlanNetmask, + String startIP, String endIP) { // Check that the start and end IPs are valid if (!NetUtils.isValidIp(startIP)) { throw new InvalidParameterValueException("Please specify a valid start IP"); @@ -3381,18 +3574,20 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } if (endIP != null && !NetUtils.sameSubnet(startIP, endIP, vlanNetmask)) { - throw new InvalidParameterValueException("Please ensure that your start IP and end IP are in the same subnet, as per the IP range's netmask."); + throw new InvalidParameterValueException( + "Please ensure that your start IP and end IP are in the same subnet, as per the IP range's netmask."); } if (!NetUtils.sameSubnet(startIP, vlanGateway, vlanNetmask)) { - throw new InvalidParameterValueException("Please ensure that your start IP is in the same subnet as your IP range's gateway, as per the IP range's netmask."); + throw new InvalidParameterValueException( + "Please ensure that your start IP is in the same subnet as your IP range's gateway, as per the IP range's netmask."); } if (endIP != null && !NetUtils.sameSubnet(endIP, vlanGateway, vlanNetmask)) { - throw new InvalidParameterValueException("Please ensure that your end IP is in the same subnet as your IP range's gateway, as per the IP range's netmask."); + throw new InvalidParameterValueException( + "Please ensure that your end IP is in the same subnet as your IP range's gateway, as per the IP range's netmask."); } } - private String getCidrAddress(String cidr) { String[] cidrPair = cidr.split("\\/"); @@ -3404,7 +3599,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati return Integer.parseInt(cidrPair[1]); } - @Override public void checkPodCidrSubnets(long dcId, Long podIdToBeSkipped, String cidr) { // For each pod, return an error if any of the following is true: @@ -3462,10 +3656,15 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // Check that cidrSubnet does not equal guestSubnet if (cidrSubnet.equals(guestSubnet)) { if (podName.equals("newPod")) { - throw new InvalidParameterValueException("The subnet of the pod you are adding conflicts with the subnet of the Guest IP Network. Please specify a different CIDR."); + throw new InvalidParameterValueException( + "The subnet of the pod you are adding conflicts with the subnet of the Guest IP Network. Please specify a different CIDR."); } else { - throw new InvalidParameterValueException("Warning: The subnet of pod " + podName + " in zone " + zoneName - + " conflicts with the subnet of the Guest IP Network. Please change either the pod's CIDR or the Guest IP Network's subnet, and re-run install-vmops-management."); + throw new InvalidParameterValueException( + "Warning: The subnet of pod " + + podName + + " in zone " + + zoneName + + " conflicts with the subnet of the Guest IP Network. Please change either the pod's CIDR or the Guest IP Network's subnet, and re-run install-vmops-management."); } } } @@ -3493,10 +3692,12 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (cidrSubnet.equals(otherCidrSubnet)) { String otherPodName = getPodName(otherPodId.longValue()); if (podName.equals("newPod")) { - throw new InvalidParameterValueException("The subnet of the pod you are adding conflicts with the subnet of pod " + otherPodName + " in zone " + zoneName - + ". Please specify a different CIDR."); + throw new InvalidParameterValueException( + "The subnet of the pod you are adding conflicts with the subnet of pod " + otherPodName + + " in zone " + zoneName + ". Please specify a different CIDR."); } else { - throw new InvalidParameterValueException("Warning: The pods " + podName + " and " + otherPodName + " in zone " + zoneName + throw new InvalidParameterValueException("Warning: The pods " + podName + " and " + + otherPodName + " in zone " + zoneName + " have conflicting CIDR subnets. Please change the CIDR of one of these pods."); } } @@ -3553,8 +3754,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } @Override - @ActionEvent(eventType = EventTypes.EVENT_VLAN_IP_RANGE_DELETE, eventDescription = "deleting vlan ip range", async = false) - public boolean deleteVlanIpRange(DeleteVlanIpRangeCmd cmd) { + @ActionEvent(eventType = EventTypes.EVENT_VLAN_IP_RANGE_DELETE, eventDescription = "deleting vlan ip range", + async = false) + public boolean deleteVlanIpRange(DeleteVlanIpRangeCmd cmd) { Long vlanDbId = cmd.getId(); VlanVO vlan = _vlanDao.findById(vlanDbId); @@ -3562,15 +3764,17 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new InvalidParameterValueException("Please specify a valid IP range id."); } - return deleteVlanAndPublicIpRange(UserContext.current().getCallerUserId(), vlanDbId, UserContext.current().getCaller()); + return deleteVlanAndPublicIpRange(UserContext.current().getCallerUserId(), vlanDbId, UserContext.current() + .getCaller()); } @Override - public void checkDiskOfferingAccess(Account caller, DiskOffering dof){ + public void checkDiskOfferingAccess(Account caller, DiskOffering dof) { for (SecurityChecker checker : _secChecker) { if (checker.checkAccess(caller, dof)) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Access granted to " + caller + " to disk offering:" + dof.getId() + " by " + checker.getName()); + s_logger.debug("Access granted to " + caller + " to disk offering:" + dof.getId() + " by " + + checker.getName()); } return; } else { @@ -3579,24 +3783,28 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } assert false : "How can all of the security checkers pass on checking this caller?"; - throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to disk offering:" + dof.getId()); + throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to disk offering:" + + dof.getId()); } @Override - public void checkZoneAccess(Account caller, DataCenter zone){ + public void checkZoneAccess(Account caller, DataCenter zone) { for (SecurityChecker checker : _secChecker) { if (checker.checkAccess(caller, zone)) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Access granted to " + caller + " to zone:" + zone.getId() + " by " + checker.getName()); + s_logger.debug("Access granted to " + caller + " to zone:" + zone.getId() + " by " + + checker.getName()); } return; } else { - throw new PermissionDeniedException("Access denied to " + caller + " by " + checker.getName() + " for zone " + zone.getId()); + throw new PermissionDeniedException("Access denied to " + caller + " by " + checker.getName() + + " for zone " + zone.getId()); } } assert false : "How can all of the security checkers pass on checking this caller?"; - throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to zone:" + zone.getId()); + throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to zone:" + + zone.getId()); } @Override @@ -3625,12 +3833,14 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } if (trafficType == null) { - throw new InvalidParameterValueException("Invalid value for traffictype. Supported traffic types: Public, Management, Control, Guest, Vlan or Storage"); + throw new InvalidParameterValueException( + "Invalid value for traffictype. Supported traffic types: Public, Management, Control, Guest, Vlan or Storage"); } // Only GUEST traffic type is supported in Acton if (trafficType != TrafficType.Guest) { - throw new InvalidParameterValueException("Only traffic type " + TrafficType.Guest + " is supported in the current release"); + throw new InvalidParameterValueException("Only traffic type " + TrafficType.Guest + + " is supported in the current release"); } // Verify offering type @@ -3642,7 +3852,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } if (guestType == null) { - throw new InvalidParameterValueException("Invalid \"type\" parameter is given; can have Shared and Isolated values"); + throw new InvalidParameterValueException( + "Invalid \"type\" parameter is given; can have Shared and Isolated values"); } // Verify availability @@ -3653,7 +3864,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } if (availability == null) { - throw new InvalidParameterValueException("Invalid value for Availability. Supported types: " + Availability.Required + ", " + Availability.Optional); + throw new InvalidParameterValueException("Invalid value for Availability. Supported types: " + + Availability.Required + ", " + Availability.Optional); } Long serviceOfferingId = cmd.getServiceOfferingId(); @@ -3664,7 +3876,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new InvalidParameterValueException("Cannot find specified service offering: " + serviceOfferingId); } if (!VirtualMachine.Type.DomainRouter.toString().equalsIgnoreCase(offering.getSystemVmType())) { - throw new InvalidParameterValueException("The specified service offering " + serviceOfferingId + " cannot be used by virtual router!"); + throw new InvalidParameterValueException("The specified service offering " + serviceOfferingId + + " cannot be used by virtual router!"); } } @@ -3683,7 +3896,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (service == Service.SecurityGroup) { // allow security group service for Shared networks only if (guestType != GuestType.Shared) { - throw new InvalidParameterValueException("Secrity group service is supported for network offerings with guest ip type " + GuestType.Shared); + throw new InvalidParameterValueException( + "Secrity group service is supported for network offerings with guest ip type " + + GuestType.Shared); } Set sgProviders = new HashSet(); sgProviders.add(Provider.SecurityGroupProvider); @@ -3708,10 +3923,12 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati Network.Service service = Network.Service.getService(serviceStr); if (serviceProviderMap.containsKey(service)) { Set providers = new HashSet(); - // Allow to specify more than 1 provider per service only if the service is LB - if (!serviceStr.equalsIgnoreCase(Service.Lb.getName()) && svcPrv.get(serviceStr) != null && svcPrv.get(serviceStr).size() > 1) { - throw new InvalidParameterValueException("In the current release only one provider can be " + - "specified for the service if the service is not LB"); + // Allow to specify more than 1 provider per service only if + // the service is LB + if (!serviceStr.equalsIgnoreCase(Service.Lb.getName()) && svcPrv.get(serviceStr) != null + && svcPrv.get(serviceStr).size() > 1) { + throw new InvalidParameterValueException("In the current release only one provider can be " + + "specified for the service if the service is not LB"); } for (String prvNameStr : svcPrv.get(serviceStr)) { // check if provider is supported @@ -3724,7 +3941,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati firewallProvider = provider; } - if ((service == Service.PortForwarding || service == Service.StaticNat) && provider == Provider.VirtualRouter){ + if ((service == Service.PortForwarding || service == Service.StaticNat) + && provider == Provider.VirtualRouter) { firewallProvider = Provider.VirtualRouter; } @@ -3742,8 +3960,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } serviceProviderMap.put(service, providers); } else { - throw new InvalidParameterValueException("Service " + serviceStr + " is not enabled for the network " + - "offering, can't add a provider to it"); + throw new InvalidParameterValueException("Service " + serviceStr + + " is not enabled for the network " + "offering, can't add a provider to it"); } } } @@ -3751,24 +3969,33 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // validate providers combination here _networkModel.canProviderSupportServices(providerCombinationToVerify); - // validate the LB service capabilities specified in the network offering + // validate the LB service capabilities specified in the network + // offering Map lbServiceCapabilityMap = cmd.getServiceCapabilities(Service.Lb); - if (!serviceProviderMap.containsKey(Service.Lb) && lbServiceCapabilityMap != null && !lbServiceCapabilityMap.isEmpty()) { - throw new InvalidParameterValueException("Capabilities for LB service can be specifed only when LB service is enabled for network offering."); + if (!serviceProviderMap.containsKey(Service.Lb) && lbServiceCapabilityMap != null + && !lbServiceCapabilityMap.isEmpty()) { + throw new InvalidParameterValueException( + "Capabilities for LB service can be specifed only when LB service is enabled for network offering."); } validateLoadBalancerServiceCapabilities(lbServiceCapabilityMap); - // validate the Source NAT service capabilities specified in the network offering + // validate the Source NAT service capabilities specified in the network + // offering Map sourceNatServiceCapabilityMap = cmd.getServiceCapabilities(Service.SourceNat); - if (!serviceProviderMap.containsKey(Service.SourceNat) && sourceNatServiceCapabilityMap != null && !sourceNatServiceCapabilityMap.isEmpty()) { - throw new InvalidParameterValueException("Capabilities for source NAT service can be specifed only when source NAT service is enabled for network offering."); + if (!serviceProviderMap.containsKey(Service.SourceNat) && sourceNatServiceCapabilityMap != null + && !sourceNatServiceCapabilityMap.isEmpty()) { + throw new InvalidParameterValueException( + "Capabilities for source NAT service can be specifed only when source NAT service is enabled for network offering."); } validateSourceNatServiceCapablities(sourceNatServiceCapabilityMap); - // validate the Static Nat service capabilities specified in the network offering + // validate the Static Nat service capabilities specified in the network + // offering Map staticNatServiceCapabilityMap = cmd.getServiceCapabilities(Service.StaticNat); - if (!serviceProviderMap.containsKey(Service.StaticNat) && sourceNatServiceCapabilityMap != null && !staticNatServiceCapabilityMap.isEmpty()) { - throw new InvalidParameterValueException("Capabilities for static NAT service can be specifed only when static NAT service is enabled for network offering."); + if (!serviceProviderMap.containsKey(Service.StaticNat) && sourceNatServiceCapabilityMap != null + && !staticNatServiceCapabilityMap.isEmpty()) { + throw new InvalidParameterValueException( + "Capabilities for static NAT service can be specifed only when static NAT service is enabled for network offering."); } validateStaticNatServiceCapablities(staticNatServiceCapabilityMap); @@ -3777,19 +4004,20 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati serviceCapabilityMap.put(Service.SourceNat, sourceNatServiceCapabilityMap); serviceCapabilityMap.put(Service.StaticNat, staticNatServiceCapabilityMap); - // if Firewall service is missing, add Firewall service/provider combination + // if Firewall service is missing, add Firewall service/provider + // combination if (firewallProvider != null) { s_logger.debug("Adding Firewall service with provider " + firewallProvider.getName()); Set firewallProviderSet = new HashSet(); firewallProviderSet.add(firewallProvider); serviceProviderMap.put(Service.Firewall, firewallProviderSet); } - + Map details = new HashMap(); if (detailsStr != null) { for (String detailStr : detailsStr.keySet()) { NetworkOffering.Detail offDetail = null; - for (NetworkOffering.Detail supportedDetail: NetworkOffering.Detail.values()) { + for (NetworkOffering.Detail supportedDetail : NetworkOffering.Detail.values()) { if (detailStr.equalsIgnoreCase(supportedDetail.toString())) { offDetail = supportedDetail; break; @@ -3802,14 +4030,18 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } - return createNetworkOffering(name, displayText, trafficType, tags, specifyVlan, availability, networkRate, serviceProviderMap, false, guestType, false, - serviceOfferingId, conserveMode, serviceCapabilityMap, specifyIpRanges, isPersistent, details); + return createNetworkOffering(name, displayText, trafficType, tags, specifyVlan, availability, networkRate, + serviceProviderMap, false, guestType, false, serviceOfferingId, conserveMode, serviceCapabilityMap, + specifyIpRanges, isPersistent, details); } void validateLoadBalancerServiceCapabilities(Map lbServiceCapabilityMap) { if (lbServiceCapabilityMap != null && !lbServiceCapabilityMap.isEmpty()) { - if (lbServiceCapabilityMap.keySet().size() > 3 || !lbServiceCapabilityMap.containsKey(Capability.SupportedLBIsolation)) { - throw new InvalidParameterValueException("Only " + Capability.SupportedLBIsolation.getName() + ", " + Capability.ElasticLb.getName() + ", " + Capability.InlineMode.getName() + " capabilities can be sepcified for LB service"); + if (lbServiceCapabilityMap.keySet().size() > 3 + || !lbServiceCapabilityMap.containsKey(Capability.SupportedLBIsolation)) { + throw new InvalidParameterValueException("Only " + Capability.SupportedLBIsolation.getName() + ", " + + Capability.ElasticLb.getName() + ", " + Capability.InlineMode.getName() + + " capabilities can be sepcified for LB service"); } for (Capability cap : lbServiceCapabilityMap.keySet()) { @@ -3818,30 +4050,35 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati boolean dedicatedLb = value.contains("dedicated"); boolean sharedLB = value.contains("shared"); if ((dedicatedLb && sharedLB) || (!dedicatedLb && !sharedLB)) { - throw new InvalidParameterValueException("Either dedicated or shared isolation can be specified for " + Capability.SupportedLBIsolation.getName()); + throw new InvalidParameterValueException( + "Either dedicated or shared isolation can be specified for " + + Capability.SupportedLBIsolation.getName()); } } else if (cap == Capability.ElasticLb) { boolean enabled = value.contains("true"); boolean disabled = value.contains("false"); if (!enabled && !disabled) { - throw new InvalidParameterValueException("Unknown specified value for " + Capability.ElasticLb.getName()); + throw new InvalidParameterValueException("Unknown specified value for " + + Capability.ElasticLb.getName()); } } else if (cap == Capability.InlineMode) { boolean enabled = value.contains("true"); boolean disabled = value.contains("false"); if (!enabled && !disabled) { - throw new InvalidParameterValueException("Unknown specified value for " + Capability.InlineMode.getName()); + throw new InvalidParameterValueException("Unknown specified value for " + + Capability.InlineMode.getName()); } } else if (cap == Capability.LbSchemes) { boolean internalLb = value.contains("internal"); boolean publicLb = value.contains("public"); if (!internalLb && !publicLb) { - throw new InvalidParameterValueException("Unknown specified value for " + Capability.LbSchemes.getName()); + throw new InvalidParameterValueException("Unknown specified value for " + + Capability.LbSchemes.getName()); } } else { - throw new InvalidParameterValueException("Only " + Capability.SupportedLBIsolation.getName() + - ", " + Capability.ElasticLb.getName() + ", " + Capability.InlineMode.getName() - + ", " + Capability.LbSchemes.getName() + " capabilities can be sepcified for LB service"); + throw new InvalidParameterValueException("Only " + Capability.SupportedLBIsolation.getName() + ", " + + Capability.ElasticLb.getName() + ", " + Capability.InlineMode.getName() + ", " + + Capability.LbSchemes.getName() + " capabilities can be sepcified for LB service"); } } } @@ -3850,7 +4087,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati void validateSourceNatServiceCapablities(Map sourceNatServiceCapabilityMap) { if (sourceNatServiceCapabilityMap != null && !sourceNatServiceCapabilityMap.isEmpty()) { if (sourceNatServiceCapabilityMap.keySet().size() > 2) { - throw new InvalidParameterValueException("Only " + Capability.SupportedSourceNatTypes.getName() + " and " + Capability.RedundantRouter + " capabilities can be sepcified for source nat service"); + throw new InvalidParameterValueException("Only " + Capability.SupportedSourceNatTypes.getName() + + " and " + Capability.RedundantRouter + + " capabilities can be sepcified for source nat service"); } for (Capability capability : sourceNatServiceCapabilityMap.keySet()) { @@ -3859,16 +4098,21 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati boolean perAccount = value.contains("peraccount"); boolean perZone = value.contains("perzone"); if ((perAccount && perZone) || (!perAccount && !perZone)) { - throw new InvalidParameterValueException("Either peraccount or perzone source NAT type can be specified for " + Capability.SupportedSourceNatTypes.getName()); + throw new InvalidParameterValueException( + "Either peraccount or perzone source NAT type can be specified for " + + Capability.SupportedSourceNatTypes.getName()); } } else if (capability == Capability.RedundantRouter) { boolean enabled = value.contains("true"); boolean disabled = value.contains("false"); if (!enabled && !disabled) { - throw new InvalidParameterValueException("Unknown specified value for " + Capability.RedundantRouter.getName()); + throw new InvalidParameterValueException("Unknown specified value for " + + Capability.RedundantRouter.getName()); } } else { - throw new InvalidParameterValueException("Only " + Capability.SupportedSourceNatTypes.getName() + " and " + Capability.RedundantRouter + " capabilities can be sepcified for source nat service"); + throw new InvalidParameterValueException("Only " + Capability.SupportedSourceNatTypes.getName() + + " and " + Capability.RedundantRouter + + " capabilities can be sepcified for source nat service"); } } } @@ -3877,7 +4121,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati void validateStaticNatServiceCapablities(Map staticNatServiceCapabilityMap) { if (staticNatServiceCapabilityMap != null && !staticNatServiceCapabilityMap.isEmpty()) { if (staticNatServiceCapabilityMap.keySet().size() > 2) { - throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " and " + Capability.AssociatePublicIP.getName() + " capabilitiy can be sepcified for static nat service"); + throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " and " + + Capability.AssociatePublicIP.getName() + + " capabilitiy can be sepcified for static nat service"); } boolean eipEnabled = false; @@ -3889,7 +4135,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati eipEnabled = value.contains("true"); eipDisabled = value.contains("false"); if (!eipEnabled && !eipDisabled) { - throw new InvalidParameterValueException("Unknown specified value for " + Capability.ElasticIp.getName()); + throw new InvalidParameterValueException("Unknown specified value for " + + Capability.ElasticIp.getName()); } } else if (capability == Capability.AssociatePublicIP) { if (value.contains("true")) { @@ -3897,13 +4144,17 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } else if (value.contains("false")) { associatePublicIP = false; } else { - throw new InvalidParameterValueException("Unknown specified value for " + Capability.AssociatePublicIP.getName()); + throw new InvalidParameterValueException("Unknown specified value for " + + Capability.AssociatePublicIP.getName()); } } else { - throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " and " + Capability.AssociatePublicIP.getName() + " capabilitiy can be sepcified for static nat service"); + throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " and " + + Capability.AssociatePublicIP.getName() + + " capabilitiy can be sepcified for static nat service"); } if (eipDisabled && associatePublicIP) { - throw new InvalidParameterValueException("Capability " + Capability.AssociatePublicIP.getName() + " can only be set when capability " + Capability.ElasticIp.getName() + " is true"); + throw new InvalidParameterValueException("Capability " + Capability.AssociatePublicIP.getName() + + " can only be set when capability " + Capability.ElasticIp.getName() + " is true"); } } } @@ -3911,9 +4162,12 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Override @DB - public NetworkOfferingVO createNetworkOffering(String name, String displayText, TrafficType trafficType, String tags, boolean specifyVlan, Availability availability, Integer networkRate, - Map> serviceProviderMap, boolean isDefault, Network.GuestType type, boolean systemOnly, Long serviceOfferingId, - boolean conserveMode, Map> serviceCapabilityMap, boolean specifyIpRanges, boolean isPersistent, Map details) { + public NetworkOfferingVO createNetworkOffering(String name, String displayText, TrafficType trafficType, + String tags, boolean specifyVlan, Availability availability, Integer networkRate, + Map> serviceProviderMap, boolean isDefault, Network.GuestType type, + boolean systemOnly, Long serviceOfferingId, boolean conserveMode, + Map> serviceCapabilityMap, boolean specifyIpRanges, boolean isPersistent, + Map details) { String multicastRateStr = _configDao.getValue("multicast.throttling.rate"); int multicastRate = ((multicastRateStr == null) ? 10 : Integer.parseInt(multicastRateStr)); @@ -3924,23 +4178,27 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new InvalidParameterValueException("SpecifyVlan should be true if network offering's type is " + type); } - //specifyIpRanges should always be true for Shared networks - //specifyIpRanges can only be true for Isolated networks with no Source Nat service + // specifyIpRanges should always be true for Shared networks + // specifyIpRanges can only be true for Isolated networks with no Source + // Nat service if (specifyIpRanges) { if (type == GuestType.Isolated) { if (serviceProviderMap.containsKey(Service.SourceNat)) { - throw new InvalidParameterValueException("SpecifyIpRanges can only be true for Shared network offerings and Isolated with no SourceNat service"); + throw new InvalidParameterValueException( + "SpecifyIpRanges can only be true for Shared network offerings and Isolated with no SourceNat service"); } } } else { if (type == GuestType.Shared) { - throw new InvalidParameterValueException("SpecifyIpRanges should always be true for Shared network offerings"); + throw new InvalidParameterValueException( + "SpecifyIpRanges should always be true for Shared network offerings"); } } // isPersistent should always be false for Shared network Offerings if (isPersistent && type == GuestType.Shared) { - throw new InvalidParameterValueException("isPersistent should be false if network offering's type is " + type); + throw new InvalidParameterValueException("isPersistent should be false if network offering's type is " + + type); } // validate availability value @@ -3955,8 +4213,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // only one network offering in the system can be Required List offerings = _networkOfferingDao.listByAvailability(Availability.Required, false); if (!offerings.isEmpty()) { - throw new InvalidParameterValueException("System already has network offering id=" + offerings.get(0).getId() - + " with availability " + Availability.Required); + throw new InvalidParameterValueException("System already has network offering id=" + + offerings.get(0).getId() + " with availability " + Availability.Required); } } @@ -3975,7 +4233,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if ((lbServiceCapabilityMap != null) && (!lbServiceCapabilityMap.isEmpty())) { String isolationCapability = lbServiceCapabilityMap.get(Capability.SupportedLBIsolation); if (isolationCapability != null) { - _networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.Lb), Service.Lb, Capability.SupportedLBIsolation, isolationCapability); + _networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.Lb), Service.Lb, + Capability.SupportedLBIsolation, isolationCapability); dedicatedLb = isolationCapability.contains("dedicated"); } else { dedicatedLb = true; @@ -3988,40 +4247,44 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati String inlineMode = lbServiceCapabilityMap.get(Capability.InlineMode); if (inlineMode != null) { - _networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.Lb), Service.Lb, Capability.InlineMode, inlineMode); + _networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.Lb), Service.Lb, + Capability.InlineMode, inlineMode); inline = inlineMode.contains("true"); } else { inline = false; } - + String publicLbStr = lbServiceCapabilityMap.get(Capability.LbSchemes); if (serviceProviderMap.containsKey(Service.Lb)) { if (publicLbStr != null) { - _networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.Lb), Service.Lb, Capability.LbSchemes, publicLbStr); + _networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.Lb), Service.Lb, + Capability.LbSchemes, publicLbStr); internalLb = publicLbStr.contains("internal"); publicLb = publicLbStr.contains("public"); } } } - - //in the current version of the code, publicLb and specificLb can't both be set to true for the same network offering + + // in the current version of the code, publicLb and specificLb can't + // both be set to true for the same network offering if (publicLb && internalLb) { - throw new InvalidParameterValueException("Public lb and internal lb can't be enabled at the same time on the offering"); + throw new InvalidParameterValueException( + "Public lb and internal lb can't be enabled at the same time on the offering"); } Map sourceNatServiceCapabilityMap = serviceCapabilityMap.get(Service.SourceNat); if ((sourceNatServiceCapabilityMap != null) && (!sourceNatServiceCapabilityMap.isEmpty())) { String sourceNatType = sourceNatServiceCapabilityMap.get(Capability.SupportedSourceNatTypes); if (sourceNatType != null) { - _networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.SourceNat), Service.SourceNat, - Capability.SupportedSourceNatTypes, sourceNatType); + _networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.SourceNat), + Service.SourceNat, Capability.SupportedSourceNatTypes, sourceNatType); sharedSourceNat = sourceNatType.contains("perzone"); } String param = sourceNatServiceCapabilityMap.get(Capability.RedundantRouter); if (param != null) { - _networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.SourceNat), Service.SourceNat, - Capability.RedundantRouter, param); + _networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.SourceNat), + Service.SourceNat, Capability.RedundantRouter, param); redundantRouter = param.contains("true"); } } @@ -4046,23 +4309,24 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati NetworkOfferingVO offering = new NetworkOfferingVO(name, displayText, trafficType, systemOnly, specifyVlan, networkRate, multicastRate, isDefault, availability, tags, type, conserveMode, dedicatedLb, - sharedSourceNat, redundantRouter, elasticIp, elasticLb, specifyIpRanges, inline, isPersistent, associatePublicIp, publicLb, internalLb); + sharedSourceNat, redundantRouter, elasticIp, elasticLb, specifyIpRanges, inline, isPersistent, + associatePublicIp, publicLb, internalLb); if (serviceOfferingId != null) { offering.setServiceOfferingId(serviceOfferingId); } - - //validate the details + + // validate the details if (details != null) { validateNtwkOffDetails(details, serviceProviderMap); } Transaction txn = Transaction.currentTxn(); txn.start(); - //1) create network offering object + // 1) create network offering object s_logger.debug("Adding network offering " + offering); offering = _networkOfferingDao.persist(offering, details); - //2) populate services and providers + // 2) populate services and providers if (serviceProviderMap != null) { for (Network.Service service : serviceProviderMap.keySet()) { Set providers = serviceProviderMap.get(service); @@ -4072,9 +4336,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (provider == Provider.VPCVirtualRouter) { vpcOff = true; } - NetworkOfferingServiceMapVO offService = new NetworkOfferingServiceMapVO(offering.getId(), service, provider); + NetworkOfferingServiceMapVO offService = new NetworkOfferingServiceMapVO(offering.getId(), + service, provider); _ntwkOffServiceMapDao.persist(offService); - s_logger.trace("Added service for the network offering: " + offService + " with provider " + provider.getName()); + s_logger.trace("Added service for the network offering: " + offService + " with provider " + + provider.getName()); } if (vpcOff) { @@ -4083,7 +4349,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati _vpcMgr.validateNtwkOffForVpc(offering, supportedSvcs); } } else { - NetworkOfferingServiceMapVO offService = new NetworkOfferingServiceMapVO(offering.getId(), service, null); + NetworkOfferingServiceMapVO offService = new NetworkOfferingServiceMapVO(offering.getId(), service, + null); _ntwkOffServiceMapDao.persist(offService); s_logger.trace("Added service for the network offering: " + offService + " with null provider"); } @@ -4098,13 +4365,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati protected void validateNtwkOffDetails(Map details, Map> serviceProviderMap) { for (Detail detail : details.keySet()) { - + Provider lbProvider = null; - if (detail == NetworkOffering.Detail.InternalLbProvider || detail == NetworkOffering.Detail.PublicLbProvider) { - //1) Vaidate the detail values - have to match the lb provider name + if (detail == NetworkOffering.Detail.InternalLbProvider + || detail == NetworkOffering.Detail.PublicLbProvider) { + // 1) Vaidate the detail values - have to match the lb provider + // name String providerStr = details.get(detail); if (Network.Provider.getProvider(providerStr) == null) { - throw new InvalidParameterValueException("Invalid value " + providerStr + " for the detail " + detail); + throw new InvalidParameterValueException("Invalid value " + providerStr + " for the detail " + + detail); } if (serviceProviderMap.get(Service.Lb) != null) { for (Provider provider : serviceProviderMap.get(Service.Lb)) { @@ -4113,31 +4383,33 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati break; } } - } - + } + if (lbProvider == null) { throw new InvalidParameterValueException("Invalid value " + details.get(detail) + " for the detail " + detail + ". The provider is not supported by the network offering"); } - - //2) validate if the provider supports the scheme + + // 2) validate if the provider supports the scheme Set lbProviders = new HashSet(); lbProviders.add(lbProvider); if (detail == NetworkOffering.Detail.InternalLbProvider) { - _networkModel.checkCapabilityForProvider(lbProviders, Service.Lb, Capability.LbSchemes, Scheme.Internal.toString()); - } else if (detail == NetworkOffering.Detail.PublicLbProvider){ - _networkModel.checkCapabilityForProvider(lbProviders, Service.Lb, Capability.LbSchemes, Scheme.Public.toString()); + _networkModel.checkCapabilityForProvider(lbProviders, Service.Lb, Capability.LbSchemes, + Scheme.Internal.toString()); + } else if (detail == NetworkOffering.Detail.PublicLbProvider) { + _networkModel.checkCapabilityForProvider(lbProviders, Service.Lb, Capability.LbSchemes, + Scheme.Public.toString()); } } } } - @Override public List searchForNetworkOfferings(ListNetworkOfferingsCmd cmd) { Boolean isAscending = Boolean.parseBoolean(_configDao.getValue("sortkey.algorithm")); isAscending = (isAscending == null ? true : isAscending); - Filter searchFilter = new Filter(NetworkOfferingVO.class, "sortKey", isAscending, cmd.getStartIndex(), cmd.getPageSizeVal()); + Filter searchFilter = new Filter(NetworkOfferingVO.class, "sortKey", isAscending, cmd.getStartIndex(), + cmd.getPageSizeVal()); Account caller = UserContext.current().getCaller(); SearchCriteria sc = _networkOfferingDao.createSearchCriteria(); @@ -4199,7 +4471,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // only root admin can list network offering with specifyVlan = true if (specifyVlan != null && caller.getType() == Account.ACCOUNT_TYPE_ADMIN) { sc.addAnd("specifyVlan", SearchCriteria.Op.EQ, specifyVlan); - }else{ + } else { specifyVlan = false; } @@ -4226,7 +4498,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // Don't return system network offerings to the user sc.addAnd("systemOnly", SearchCriteria.Op.EQ, false); - // if networkId is specified, list offerings available for upgrade only (for this network) + // if networkId is specified, list offerings available for upgrade only + // (for this network) Network network = null; if (networkId != null) { // check if network exists and the caller can operate with it @@ -4279,7 +4552,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati for (PhysicalNetworkVO pNtwk : pNtwks) { List pNtwkTag = pNtwk.getTags(); if (pNtwkTag == null || pNtwkTag.isEmpty()) { - throw new CloudRuntimeException("Tags are not defined for physical network in the zone id=" + zoneId); + throw new CloudRuntimeException("Tags are not defined for physical network in the zone id=" + + zoneId); } pNtwkTags.addAll(pNtwkTag); } @@ -4287,7 +4561,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } // filter by supported services - boolean listBySupportedServices = (supportedServicesStr != null && !supportedServicesStr.isEmpty() && !offerings.isEmpty()); + boolean listBySupportedServices = (supportedServicesStr != null && !supportedServicesStr.isEmpty() && !offerings + .isEmpty()); boolean checkIfProvidersAreEnabled = (zoneId != null); boolean parseOfferings = (listBySupportedServices || sourceNatSupported != null || checkIfProvidersAreEnabled || forVpc != null || network != null); @@ -4321,7 +4596,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } if (listBySupportedServices) { - addOffering = addOffering && _networkModel.areServicesSupportedByNetworkOffering(offering.getId(), supportedServices); + addOffering = addOffering + && _networkModel.areServicesSupportedByNetworkOffering(offering.getId(), supportedServices); } if (checkIfProvidersAreEnabled) { @@ -4331,16 +4607,19 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati checkForProviders = _networkModel.listNetworkOfferingServices(offering.getId()); } - addOffering = addOffering && _networkModel.areServicesEnabledInZone(zoneId, offering, checkForProviders); + addOffering = addOffering + && _networkModel.areServicesEnabledInZone(zoneId, offering, checkForProviders); } if (sourceNatSupported != null) { - addOffering = addOffering && (_networkModel.areServicesSupportedByNetworkOffering(offering.getId(), Network.Service.SourceNat) == sourceNatSupported); + addOffering = addOffering + && (_networkModel.areServicesSupportedByNetworkOffering(offering.getId(), + Network.Service.SourceNat) == sourceNatSupported); } if (forVpc != null) { addOffering = addOffering && (isOfferingForVpc(offering) == forVpc.booleanValue()); - } else if (network != null){ + } else if (network != null) { addOffering = addOffering && (isOfferingForVpc(offering) == (network.getVpcId() != null)); } @@ -4382,12 +4661,13 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new InvalidParameterValueException("Default network offering can't be deleted"); } - // don't allow to delete network offering if it's in use by existing networks (the offering can be disabled + // don't allow to delete network offering if it's in use by existing + // networks (the offering can be disabled // though) int networkCount = _networkDao.getNetworkCountByNetworkOffId(offeringId); if (networkCount > 0) { - throw new InvalidParameterValueException("Can't delete network offering " + offeringId + " as its used by " + networkCount + " networks. " + - "To make the network offering unavaiable, disable it"); + throw new InvalidParameterValueException("Can't delete network offering " + offeringId + " as its used by " + + networkCount + " networks. " + "To make the network offering unavaiable, disable it"); } if (_networkOfferingDao.remove(offeringId)) { @@ -4456,22 +4736,23 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } if (availability == null) { throw new InvalidParameterValueException("Invalid value for Availability. Supported types: " - + Availability.Required + ", " + Availability.Optional); + + Availability.Required + ", " + Availability.Optional); } else { if (availability == NetworkOffering.Availability.Required) { - boolean canOffBeRequired = (offeringToUpdate.getGuestType() == GuestType.Isolated - && _networkModel.areServicesSupportedByNetworkOffering(offeringToUpdate.getId(), Service.SourceNat)); + boolean canOffBeRequired = (offeringToUpdate.getGuestType() == GuestType.Isolated && _networkModel + .areServicesSupportedByNetworkOffering(offeringToUpdate.getId(), Service.SourceNat)); if (!canOffBeRequired) { - throw new InvalidParameterValueException("Availability can be " + - NetworkOffering.Availability.Required + " only for networkOfferings of type " + GuestType.Isolated + " and with " - + Service.SourceNat.getName() + " enabled"); + throw new InvalidParameterValueException("Availability can be " + + NetworkOffering.Availability.Required + " only for networkOfferings of type " + + GuestType.Isolated + " and with " + Service.SourceNat.getName() + " enabled"); } // only one network offering in the system can be Required - List offerings = _networkOfferingDao.listByAvailability(Availability.Required, false); + List offerings = _networkOfferingDao.listByAvailability(Availability.Required, + false); if (!offerings.isEmpty() && offerings.get(0).getId() != offeringToUpdate.getId()) { - throw new InvalidParameterValueException("System already has network offering id=" + - offerings.get(0).getId() + " with availability " + Availability.Required); + throw new InvalidParameterValueException("System already has network offering id=" + + offerings.get(0).getId() + " with availability " + Availability.Required); } } offering.setAvailability(availability); @@ -4486,32 +4767,33 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } @Override - @ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_MARK_DEFAULT_ZONE, eventDescription = "Marking account with the " + - "default zone", async=true) + @ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_MARK_DEFAULT_ZONE, eventDescription = "Marking account with the " + + "default zone", async = true) public AccountVO markDefaultZone(String accountName, long domainId, long defaultZoneId) { - // Check if the account exists - Account account = _accountDao.findEnabledAccount(accountName, domainId); - if (account == null) { + // Check if the account exists + Account account = _accountDao.findEnabledAccount(accountName, domainId); + if (account == null) { s_logger.error("Unable to find account by name: " + accountName + " in domain " + domainId); - throw new InvalidParameterValueException("Account by name: " + accountName + " doesn't exist in domain " + domainId); + throw new InvalidParameterValueException("Account by name: " + accountName + " doesn't exist in domain " + + domainId); } // Don't allow modification of system account if (account.getId() == Account.ACCOUNT_ID_SYSTEM) { throw new InvalidParameterValueException("Can not modify system account"); - } + } - AccountVO acctForUpdate = _accountDao.findById(account.getId()); + AccountVO acctForUpdate = _accountDao.findById(account.getId()); - acctForUpdate.setDefaultZoneId(defaultZoneId); + acctForUpdate.setDefaultZoneId(defaultZoneId); - if (_accountDao.update(account.getId(), acctForUpdate)) { - UserContext.current().setEventDetails("Default zone id= " + defaultZoneId); - return _accountDao.findById(account.getId()); - } else { - return null; - } + if (_accountDao.update(account.getId(), acctForUpdate)) { + UserContext.current().setEventDetails("Default zone id= " + defaultZoneId); + return _accountDao.findById(account.getId()); + } else { + return null; + } } // Note: This method will be used for entity name validations in the coming @@ -4527,7 +4809,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati char ch = str.charAt(i); for (int j = 0; j < searchChars.length; j++) { if (searchChars[j] == ch) { - throw new InvalidParameterValueException("Name cannot contain any of the following special characters:" + forbidden); + throw new InvalidParameterValueException( + "Name cannot contain any of the following special characters:" + forbidden); } } } @@ -4556,7 +4839,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (no.getRateMbps() != null) { networkRate = no.getRateMbps(); } else { - networkRate = Integer.parseInt(_configServer.getConfigValue(Config.NetworkThrottlingRate.key(), Config.ConfigurationParameterScope.zone.toString(), dataCenterId)); + networkRate = Integer.parseInt(_configServer.getConfigValue(Config.NetworkThrottlingRate.key(), + Config.ConfigurationParameterScope.zone.toString(), dataCenterId)); } // networkRate is unsigned int in netowrkOfferings table, and can't be @@ -4644,27 +4928,27 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } @Override - public AllocationState findClusterAllocationState(ClusterVO cluster){ + public AllocationState findClusterAllocationState(ClusterVO cluster) { - if(cluster.getAllocationState() == AllocationState.Disabled){ - return AllocationState.Disabled; - }else if(ApiDBUtils.findPodById(cluster.getPodId()).getAllocationState() == AllocationState.Disabled){ - return AllocationState.Disabled; - }else { - DataCenterVO zone = ApiDBUtils.findZoneById(cluster.getDataCenterId()); - return zone.getAllocationState(); - } + if (cluster.getAllocationState() == AllocationState.Disabled) { + return AllocationState.Disabled; + } else if (ApiDBUtils.findPodById(cluster.getPodId()).getAllocationState() == AllocationState.Disabled) { + return AllocationState.Disabled; + } else { + DataCenterVO zone = ApiDBUtils.findZoneById(cluster.getDataCenterId()); + return zone.getAllocationState(); + } } @Override - public AllocationState findPodAllocationState(HostPodVO pod){ + public AllocationState findPodAllocationState(HostPodVO pod) { - if(pod.getAllocationState() == AllocationState.Disabled){ - return AllocationState.Disabled; - }else { - DataCenterVO zone = ApiDBUtils.findZoneById(pod.getDataCenterId()); - return zone.getAllocationState(); - } + if (pod.getAllocationState() == AllocationState.Disabled) { + return AllocationState.Disabled; + } else { + DataCenterVO zone = ApiDBUtils.findZoneById(pod.getDataCenterId()); + return zone.getAllocationState(); + } } private boolean allowIpRangeOverlap(VlanVO vlan, boolean forVirtualNetwork, long networkId) { @@ -4705,8 +4989,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati networkRate = offering.getRateMbps(); } else { // for domain router service offering, get network rate from - if (offering.getSystemVmType() != null && offering.getSystemVmType().equalsIgnoreCase(VirtualMachine.Type.DomainRouter.toString())) { - networkRate = Integer.parseInt(_configServer.getConfigValue(Config.NetworkThrottlingRate.key(), Config.ConfigurationParameterScope.zone.toString(), dataCenterId)); + if (offering.getSystemVmType() != null + && offering.getSystemVmType().equalsIgnoreCase(VirtualMachine.Type.DomainRouter.toString())) { + networkRate = Integer.parseInt(_configServer.getConfigValue(Config.NetworkThrottlingRate.key(), + Config.ConfigurationParameterScope.zone.toString(), dataCenterId)); } else { networkRate = Integer.parseInt(_configDao.getValue(Config.VmNetworkThrottlingRate.key())); } @@ -4735,7 +5021,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Override @DB - @ActionEvent(eventType = EventTypes.EVENT_PORTABLE_IP_RANGE_CREATE, eventDescription = "creating portable ip range", async = false) + @ActionEvent(eventType = EventTypes.EVENT_PORTABLE_IP_RANGE_CREATE, + eventDescription = "creating portable ip range", async = false) public PortableIpRange createPortableIpRange(CreatePortableIpRangeCmd cmd) throws ConcurrentOperationException { Integer regionId = cmd.getRegionId(); String startIP = cmd.getStartIp(); @@ -4754,18 +5041,18 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } if (!NetUtils.sameSubnet(startIP, gateway, netmask)) { - throw new InvalidParameterValueException("Please ensure that your start IP is in the same subnet as " + - "your portable IP range's gateway and as per the IP range's netmask."); + throw new InvalidParameterValueException("Please ensure that your start IP is in the same subnet as " + + "your portable IP range's gateway and as per the IP range's netmask."); } if (!NetUtils.sameSubnet(endIP, gateway, netmask)) { - throw new InvalidParameterValueException("Please ensure that your end IP is in the same subnet as " + - "your portable IP range's gateway and as per the IP range's netmask."); + throw new InvalidParameterValueException("Please ensure that your end IP is in the same subnet as " + + "your portable IP range's gateway and as per the IP range's netmask."); } if (checkOverlapPortableIpRange(regionId, startIP, endIP)) { - throw new InvalidParameterValueException("Ip range: " + startIP + "-" + endIP + " overlaps with a portable" + - " IP range already configured in the region " + regionId); + throw new InvalidParameterValueException("Ip range: " + startIP + "-" + endIP + + " overlaps with a portable" + " IP range already configured in the region " + regionId); } if (vlanId == null) { @@ -4783,11 +5070,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati PortableIpRangeVO portableIpRange = new PortableIpRangeVO(regionId, vlanId, gateway, netmask, startIP, endIP); portableIpRange = _portableIpRangeDao.persist(portableIpRange); - long startIpLong = NetUtils.ip2Long(startIP); + long startIpLong = NetUtils.ip2Long(startIP); long endIpLong = NetUtils.ip2Long(endIP); - while(startIpLong <= endIpLong) { - PortableIpVO portableIP = new PortableIpVO(regionId, portableIpRange.getId(), vlanId, - gateway, netmask,NetUtils.long2Ip(startIpLong)); + while (startIpLong <= endIpLong) { + PortableIpVO portableIP = new PortableIpVO(regionId, portableIpRange.getId(), vlanId, gateway, netmask, + NetUtils.long2Ip(startIpLong)); _portableIpDao.persist(portableIP); startIpLong++; } @@ -4799,7 +5086,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Override @DB - @ActionEvent(eventType = EventTypes.EVENT_PORTABLE_IP_RANGE_DELETE, eventDescription = "deleting portable ip range", async = false) + @ActionEvent(eventType = EventTypes.EVENT_PORTABLE_IP_RANGE_DELETE, + eventDescription = "deleting portable ip range", async = false) public boolean deletePortableIpRange(DeletePortableIpRangeCmd cmd) { long rangeId = cmd.getId(); PortableIpRangeVO portableIpRange = _portableIpRangeDao.findById(rangeId); @@ -4808,7 +5096,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } List fullIpRange = _portableIpDao.listByRangeId(portableIpRange.getId()); - List freeIpRange = _portableIpDao.listByRangeIdAndState(portableIpRange.getId(), PortableIp.State.Free); + List freeIpRange = _portableIpDao.listByRangeIdAndState(portableIpRange.getId(), + PortableIp.State.Free); if (fullIpRange != null && freeIpRange != null) { if (fullIpRange.size() == freeIpRange.size()) { @@ -4827,17 +5116,17 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati Integer regionId = cmd.getRegionIdId(); Long rangeId = cmd.getPortableIpRangeId(); - List ranges = new ArrayList(); + List ranges = new ArrayList(); if (regionId != null) { Region region = _regionDao.findById(regionId); if (region == null) { throw new InvalidParameterValueException("Invalid region ID: " + regionId); } - return _portableIpRangeDao.listByRegionId(regionId); + return _portableIpRangeDao.listByRegionId(regionId); } if (rangeId != null) { - PortableIpRangeVO range = _portableIpRangeDao.findById(rangeId); + PortableIpRangeVO range = _portableIpRangeDao.findById(rangeId); if (range == null) { throw new InvalidParameterValueException("Invalid portable IP range ID: " + regionId); } diff --git a/server/src/com/cloud/consoleproxy/AgentHook.java b/server/src/com/cloud/consoleproxy/AgentHook.java index 5b6d585680c..b17bd18bd9d 100644 --- a/server/src/com/cloud/consoleproxy/AgentHook.java +++ b/server/src/com/cloud/consoleproxy/AgentHook.java @@ -21,14 +21,15 @@ import com.cloud.agent.api.ConsoleAccessAuthenticationCommand; import com.cloud.agent.api.ConsoleProxyLoadReportCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupProxyCommand; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.host.Status; public interface AgentHook { void onLoadReport(ConsoleProxyLoadReportCommand cmd); AgentControlAnswer onConsoleAccessAuthentication(ConsoleAccessAuthenticationCommand cmd); - void onAgentConnect(HostVO host, StartupCommand cmd); - + + void onAgentConnect(Host host, StartupCommand cmd); + public void onAgentDisconnect(long agentId, Status state); - public void startAgentHttpHandlerInVM(StartupProxyCommand startupCmd); + public void startAgentHttpHandlerInVM(StartupProxyCommand startupCmd); } diff --git a/server/src/com/cloud/consoleproxy/AgentHookBase.java b/server/src/com/cloud/consoleproxy/AgentHookBase.java index 2748a8cb68c..160810d1da3 100644 --- a/server/src/com/cloud/consoleproxy/AgentHookBase.java +++ b/server/src/com/cloud/consoleproxy/AgentHookBase.java @@ -19,7 +19,6 @@ package com.cloud.consoleproxy; import java.util.Date; import java.util.Random; -import java.util.UUID; import org.apache.log4j.Logger; @@ -34,10 +33,10 @@ import com.cloud.agent.api.GetVncPortCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupProxyCommand; import com.cloud.agent.api.proxy.StartConsoleProxyAgentHttpHandlerCommand; -import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.OperationTimedoutException; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; @@ -79,6 +78,7 @@ public abstract class AgentHookBase implements AgentHook { this._ms = ms; } + @Override public AgentControlAnswer onConsoleAccessAuthentication(ConsoleAccessAuthenticationCommand cmd) { Long vmId = null; @@ -194,6 +194,7 @@ public abstract class AgentHookBase implements AgentHook { return new ConsoleAccessAuthenticationAnswer(cmd, true); } + @Override public void startAgentHttpHandlerInVM(StartupProxyCommand startupCmd) { StartConsoleProxyAgentHttpHandlerCommand cmd = null; if (_configDao.isPremium()) { @@ -241,33 +242,33 @@ public abstract class AgentHookBase implements AgentHook { + startupCmd.getProxyVmId(), e); } } - + private String getEncryptorPassword() { String key; String iv; ConsoleProxyPasswordBasedEncryptor.KeyIVPair keyIvPair = null; - + // if we failed after reset, something is definitely wrong for(int i = 0; i < 2; i++) { key = _ms.getEncryptionKey(); iv = _ms.getEncryptionIV(); - + keyIvPair = new ConsoleProxyPasswordBasedEncryptor.KeyIVPair(key, iv); - + if(keyIvPair.getIvBytes() == null || keyIvPair.getIvBytes().length != 16 || keyIvPair.getKeyBytes() == null || keyIvPair.getKeyBytes().length != 16) { - + s_logger.warn("Console access AES KeyIV sanity check failed, reset and regenerate"); _ms.resetEncryptionKeyIV(); } else { break; } } - + Gson gson = new GsonBuilder().create(); return gson.toJson(keyIvPair); } - + protected abstract HostVO findConsoleProxyHost(StartupProxyCommand cmd); @@ -277,7 +278,7 @@ public abstract class AgentHookBase implements AgentHook { } @Override - public void onAgentConnect(HostVO host, StartupCommand cmd) { + public void onAgentConnect(Host host, StartupCommand cmd) { // no-op } diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyListener.java b/server/src/com/cloud/consoleproxy/ConsoleProxyListener.java index a3b72645794..2190dffe8c3 100755 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyListener.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyListener.java @@ -25,7 +25,7 @@ import com.cloud.agent.api.ConsoleAccessAuthenticationCommand; import com.cloud.agent.api.ConsoleProxyLoadReportCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupProxyCommand; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.host.Status; public class ConsoleProxyListener implements Listener { @@ -64,7 +64,7 @@ public class ConsoleProxyListener implements Listener { } @Override - public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) { + public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) { _proxyMgr.onAgentConnect(host, cmd); if (cmd instanceof StartupProxyCommand) { diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManager.java index faec51307b5..4b57d5f6c1a 100755 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManager.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManager.java @@ -41,5 +41,4 @@ public interface ConsoleProxyManager extends Manager, ConsoleProxyService { public boolean stopProxy(long proxyVmId); public boolean rebootProxy(long proxyVmId); public boolean destroyProxy(long proxyVmId); - } diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 7362cf1e227..5983aa7ad7c 100755 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -30,6 +30,8 @@ import javax.naming.ConfigurationException; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -99,12 +101,10 @@ import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePoolStatus; -import com.cloud.storage.VMTemplateHostVO; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VMTemplateHostDao; import com.cloud.template.TemplateManager; import com.cloud.user.Account; import com.cloud.user.AccountManager; @@ -189,7 +189,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy @Inject private VMInstanceDao _instanceDao; @Inject - private VMTemplateHostDao _vmTemplateHostDao; + private TemplateDataStoreDao _vmTemplateStoreDao; @Inject private AgentManager _agentMgr; @Inject @@ -309,11 +309,6 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } } - @Override - public void onAgentConnect(HostVO host, StartupCommand cmd) { - // no-op - } - @Override public void onAgentDisconnect(long agentId, com.cloud.host.Status state) { @@ -695,14 +690,14 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } defaultNetwork = networks.get(0); } else { - TrafficType defaultTrafficType = TrafficType.Public; - if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) { - defaultTrafficType = TrafficType.Guest; - } - List defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType); + 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) { + if (defaultNetworks.size() != 1) { throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + defaultTrafficType + " when expect to find 1"); } @@ -943,22 +938,10 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenterId); if (zoneHostInfo != null && isZoneHostReady(zoneHostInfo)) { VMTemplateVO template = _templateDao.findSystemVMTemplate(dataCenterId); - HostVO secondaryStorageHost = this.templateMgr.getSecondaryStorageHost(dataCenterId); - boolean templateReady = false; - - if (secondaryStorageHost == null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("No secondary storage available in zone " + dataCenterId + ", wait until it is ready to launch secondary storage vm"); - } - return false; - } + TemplateDataStoreVO templateHostRef = this._vmTemplateStoreDao.findByTemplateZoneDownloadStatus(template.getId(), dataCenterId, + Status.DOWNLOADED); - if (template != null && secondaryStorageHost != null) { - VMTemplateHostVO templateHostRef = _vmTemplateHostDao.findByHostTemplate(secondaryStorageHost.getId(), template.getId()); - templateReady = (templateHostRef != null) && (templateHostRef.getDownloadState() == Status.DOWNLOADED); - } - - if (templateReady) { + if (templateHostRef != null) { List> l = _consoleProxyDao.getDatacenterStoragePoolHostInfo(dataCenterId, _use_lvm); if (l != null && l.size() > 0 && l.get(0).second().intValue() > 0) { return true; @@ -971,11 +954,9 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy if (s_logger.isDebugEnabled()) { if (template == null) { s_logger.debug("Zone host is ready, but console proxy template is null"); - } else if (secondaryStorageHost != null) { - s_logger.debug("Zone host is ready, but console proxy template: " + template.getId() + " is not ready on secondary storage: " + secondaryStorageHost.getId()); - } else { - s_logger.debug("Zone host is ready, but console proxy template: " + template.getId() + " is not ready on secondary storage."); - } + } else { + s_logger.debug("Zone host is ready, but console proxy template: " + template.getId() + " is not ready on secondary storage."); + } } } } diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java index eb895e53b04..4ef2152dd7b 100644 --- a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java +++ b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java @@ -711,7 +711,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy } @Override - public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { + public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { if (!(cmd instanceof StartupRoutingCommand)) { return; } diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java index be36b8d22d2..50bfb3068d0 100644 --- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java +++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java @@ -22,6 +22,8 @@ import java.util.Map; import javax.inject.Inject; import com.cloud.agent.api.Command; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.DiskTO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.api.to.VolumeTO; @@ -94,7 +96,7 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis VirtualMachine vm = vmProfile.getVirtualMachine(); Long minMemory = (long) (offering.getRamSize() / vmProfile.getMemoryOvercommitRatio()); int minspeed = (int) (offering.getSpeed() / vmProfile.getCpuOvercommitRatio()); - int maxspeed = (offering.getSpeed()); + int maxspeed = (offering.getSpeed()); VirtualMachineTO to = new VirtualMachineTO(vm.getId(), vm.getInstanceName(), vm.getType(), offering.getCpu(), minspeed, maxspeed, minMemory * 1024l * 1024l, offering.getRamSize() * 1024l * 1024l, null, null, vm.isHaEnabled(), vm.limitCpuUse(), vm.getVncPassword()); to.setBootArgs(vmProfile.getBootArgs()); @@ -107,7 +109,7 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis } to.setNics(nics); - to.setDisks(vmProfile.getDisks().toArray(new VolumeTO[vmProfile.getDisks().size()])); + to.setDisks(vmProfile.getDisks().toArray(new DiskTO[vmProfile.getDisks().size()])); if(vmProfile.getTemplate().getBits() == 32) { to.setArch("i686"); @@ -132,7 +134,7 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis // Workaround to make sure the TO has the UUID we need for Niciri integration VMInstanceVO vmInstance = _virtualMachineDao.findById(to.getId()); to.setUuid(vmInstance.getUuid()); - + // return to; } diff --git a/server/src/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java b/server/src/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java index 75b007c87d2..f59bdf370aa 100644 --- a/server/src/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java +++ b/server/src/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java @@ -23,7 +23,6 @@ import java.util.List; import java.util.Map; import java.util.UUID; -import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; @@ -62,20 +61,26 @@ import com.cloud.resource.ServerResource; import com.cloud.resource.UnableDeleteHostException; import com.cloud.utils.ssh.SSHCmdHelper; -public abstract class LibvirtServerDiscoverer extends DiscovererBase implements Discoverer, -Listener, ResourceStateAdapter { +public abstract class LibvirtServerDiscoverer extends DiscovererBase implements Discoverer, Listener, + ResourceStateAdapter { private static final Logger s_logger = Logger.getLogger(LibvirtServerDiscoverer.class); private String _hostIp; - private final int _waitTime = 5; /*wait for 5 minutes*/ + private final int _waitTime = 5; /* wait for 5 minutes */ private String _kvmPrivateNic; private String _kvmPublicNic; private String _kvmGuestNic; - @Inject HostDao _hostDao = null; - @Inject ClusterDao _clusterDao; - @Inject ResourceManager _resourceMgr; - @Inject AgentManager _agentMgr; - @Inject ConfigurationDao _configDao; - @Inject NetworkModel _networkMgr; + @Inject + HostDao _hostDao = null; + @Inject + ClusterDao _clusterDao; + @Inject + ResourceManager _resourceMgr; + @Inject + AgentManager _agentMgr; + @Inject + ConfigurationDao _configDao; + @Inject + NetworkModel _networkMgr; public abstract Hypervisor.HypervisorType getHypervisorType(); @@ -92,14 +97,13 @@ Listener, ResourceStateAdapter { } @Override - public AgentControlAnswer processControlCommand(long agentId, - AgentControlCommand cmd) { + public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) { // TODO Auto-generated method stub return null; } @Override - public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) { + public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) { } @Override @@ -127,14 +131,13 @@ Listener, ResourceStateAdapter { } @Override - public Map> find(long dcId, - Long podId, Long clusterId, URI uri, String username, - String password, List hostTags) throws DiscoveryException { + public Map> find(long dcId, Long podId, Long clusterId, URI uri, + String username, String password, List hostTags) throws DiscoveryException { ClusterVO cluster = _clusterDao.findById(clusterId); - if(cluster == null || cluster.getHypervisorType() != getHypervisorType()) { - if(s_logger.isInfoEnabled()) - s_logger.info("invalid cluster id or cluster is not for " + getHypervisorType() + " hypervisors"); + if (cluster == null || cluster.getHypervisorType() != getHypervisorType()) { + if (s_logger.isInfoEnabled()) + s_logger.info("invalid cluster id or cluster is not for " + getHypervisorType() + " hypervisors"); return null; } @@ -153,11 +156,16 @@ Listener, ResourceStateAdapter { InetAddress ia = InetAddress.getByName(hostname); agentIp = ia.getHostAddress(); String guid = UUID.nameUUIDFromBytes(agentIp.getBytes()).toString(); - String guidWithTail = guid + "-LibvirtComputingResource";/*tail added by agent.java*/ + String guidWithTail = guid + "-LibvirtComputingResource";/* + * tail + * added by + * agent + * .java + */ if (_resourceMgr.findHostByGuid(guidWithTail) != null) { s_logger.debug("Skipping " + agentIp + " because " + guidWithTail + " is already in the database."); return null; - } + } sshConnection = new com.trilead.ssh2.Connection(agentIp, 22); @@ -172,7 +180,7 @@ Listener, ResourceStateAdapter { return null; } - List netInfos = _networkMgr.getPhysicalNetworkInfo(dcId, getHypervisorType()); + List netInfos = _networkMgr.getPhysicalNetworkInfo(dcId, getHypervisorType()); String kvmPrivateNic = null; String kvmPublicNic = null; String kvmGuestNic = null; @@ -193,7 +201,7 @@ Listener, ResourceStateAdapter { kvmPrivateNic = _kvmPrivateNic; kvmPublicNic = _kvmPublicNic; kvmGuestNic = _kvmGuestNic; - } + } if (kvmPublicNic == null) { kvmPublicNic = (kvmGuestNic != null) ? kvmGuestNic : kvmPrivateNic; @@ -207,7 +215,8 @@ Listener, ResourceStateAdapter { kvmGuestNic = (kvmPublicNic != null) ? kvmPublicNic : kvmPrivateNic; } - String parameters = " -m " + _hostIp + " -z " + dcId + " -p " + podId + " -c " + clusterId + " -g " + guid + " -a"; + String parameters = " -m " + _hostIp + " -z " + dcId + " -p " + podId + " -c " + clusterId + " -g " + guid + + " -a"; parameters += " --pubNic=" + kvmPublicNic; parameters += " --prvNic=" + kvmPrivateNic; @@ -220,8 +229,8 @@ Listener, ResourceStateAdapter { params.put("zone", Long.toString(dcId)); params.put("pod", Long.toString(podId)); - params.put("cluster", Long.toString(clusterId)); - params.put("guid", guid); + params.put("cluster", Long.toString(clusterId)); + params.put("guid", guid); params.put("agentIp", agentIp); kvmResource.configure("kvm agent", params); resources.put(kvmResource, details); @@ -238,16 +247,16 @@ Listener, ResourceStateAdapter { _clusterDao.update(clusterId, cluster); } - //save user name and password + // save user name and password _hostDao.loadDetails(connectedHost); Map hostDetails = connectedHost.getDetails(); hostDetails.put("password", password); hostDetails.put("username", username); _hostDao.saveDetails(connectedHost); return resources; - } catch (DiscoveredWithErrorException e){ + } catch (DiscoveredWithErrorException e) { throw e; - }catch (Exception e) { + } catch (Exception e) { String msg = " can't setup agent, due to " + e.toString() + " - " + e.getMessage(); s_logger.warn(msg); } finally { @@ -259,7 +268,7 @@ Listener, ResourceStateAdapter { } private HostVO waitForHostConnect(long dcId, long podId, long clusterId, String guid) { - for (int i = 0; i < _waitTime *2; i++) { + for (int i = 0; i < _waitTime * 2; i++) { List hosts = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.Routing, clusterId, podId, dcId); for (HostVO host : hosts) { if (host.getGuid().equalsIgnoreCase(guid)) { @@ -283,7 +292,8 @@ Listener, ResourceStateAdapter { @Override public boolean configure(String name, Map params) throws ConfigurationException { -// _setupAgentPath = Script.findScript(getPatchPath(), "setup_agent.sh"); + // _setupAgentPath = Script.findScript(getPatchPath(), + // "setup_agent.sh"); _kvmPrivateNic = _configDao.getValue(Config.KvmPrivateNetwork.key()); if (_kvmPrivateNic == null) { _kvmPrivateNic = "cloudbr0"; @@ -312,15 +322,14 @@ Listener, ResourceStateAdapter { } @Override - public void postDiscovery(List hosts, long msId) - throws DiscoveryException { + public void postDiscovery(List hosts, long msId) throws DiscoveryException { // TODO Auto-generated method stub } @Override public boolean matchHypervisor(String hypervisor) { // for backwards compatibility, if not supplied, always let to try it - if(hypervisor == null) + if (hypervisor == null) return true; return getHypervisorType().toString().equalsIgnoreCase(hypervisor); @@ -340,6 +349,11 @@ Listener, ResourceStateAdapter { /* KVM requires host are the same in cluster */ ClusterVO clusterVO = _clusterDao.findById(host.getClusterId()); + if (clusterVO == null) { + s_logger.debug("cannot find cluster: " + host.getClusterId()); + throw new IllegalArgumentException("cannot add host, due to can't find cluster: " + host.getClusterId()); + } + List hostsInCluster = _resourceMgr.listAllHostsInCluster(clusterVO.getId()); if (!hostsInCluster.isEmpty()) { HostVO oneHost = hostsInCluster.get(0); @@ -347,8 +361,9 @@ Listener, ResourceStateAdapter { String hostOsInCluster = oneHost.getDetail("Host.OS"); String hostOs = ssCmd.getHostDetails().get("Host.OS"); if (!hostOsInCluster.equalsIgnoreCase(hostOs)) { - throw new IllegalArgumentException("Can't add host: " + firstCmd.getPrivateIpAddress() + " with hostOS: " + hostOs + " into a cluster," - + "in which there are " + hostOsInCluster + " hosts added"); + throw new IllegalArgumentException("Can't add host: " + firstCmd.getPrivateIpAddress() + + " with hostOS: " + hostOs + " into a cluster," + "in which there are " + hostOsInCluster + + " hosts added"); } } @@ -358,17 +373,17 @@ Listener, ResourceStateAdapter { } @Override - public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map details, - List hostTags) { + public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, + Map details, List hostTags) { // TODO Auto-generated method stub return null; } @Override - public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { - if (host.getType() != Host.Type.Routing || - (host.getHypervisorType() != HypervisorType.KVM && - host.getHypervisorType() != HypervisorType.LXC)) { + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) + throws UnableDeleteHostException { + if (host.getType() != Host.Type.Routing + || (host.getHypervisorType() != HypervisorType.KVM && host.getHypervisorType() != HypervisorType.LXC)) { return null; } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 61c5639eb91..283212280e4 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -99,7 +99,6 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.UnsupportedServiceException; import com.cloud.host.Host; -import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; @@ -888,12 +887,12 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L DataCenter zone = _configMgr.getZone(network.getDataCenterId()); if (zone.getNetworkType() == NetworkType.Advanced) { if (network.getGuestType() == Network.GuestType.Shared) { - if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) { - _accountMgr.checkAccess(UserContext.current().getCaller(), AccessType.UseNetwork, false, network); - } else { - throw new InvalidParameterValueException("IP can be associated with guest network of 'shared' type only if " + - "network services Source Nat, Static Nat, Port Forwarding, Load balancing, firewall are enabled in the network"); - } + if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) { + _accountMgr.checkAccess(UserContext.current().getCaller(), AccessType.UseNetwork, false, network); + } else { + throw new InvalidParameterValueException("IP can be associated with guest network of 'shared' type only if " + + "network services Source Nat, Static Nat, Port Forwarding, Load balancing, firewall are enabled in the network"); + } } } else { _accountMgr.checkAccess(caller, null, true, ipToAssoc); @@ -3634,9 +3633,9 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L for (IPAddressVO ipToRelease : ipsToRelease) { if (ipToRelease.getVpcId() == null) { if (!ipToRelease.isPortable()) { - IPAddressVO ip = markIpAsUnavailable(ipToRelease.getId()); - assert (ip != null) : "Unable to mark the ip address id=" + ipToRelease.getId() + " as unavailable."; - } else { + IPAddressVO ip = markIpAsUnavailable(ipToRelease.getId()); + assert (ip != null) : "Unable to mark the ip address id=" + ipToRelease.getId() + " as unavailable."; + } else { // portable IP address are associated with owner, until explicitly requested to be disassociated // so as part of network clean up just break IP association with guest network ipToRelease.setAssociatedWithNetworkId(null); @@ -3843,7 +3842,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } @Override - public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { + public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { if (!(cmd instanceof StartupRoutingCommand)) { return; } @@ -4150,38 +4149,38 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L public NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context, VirtualMachineProfile vmProfile, boolean prepare) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { - - VirtualMachine vm = vmProfile.getVirtualMachine(); - DataCenter dc = _configMgr.getZone(network.getDataCenterId()); - Host host = _hostDao.findById(vm.getHostId()); - DeployDestination dest = new DeployDestination(dc, null, null, host); - - NicProfile nic = getNicProfileForVm(network, requested, vm); - - //1) allocate nic (if needed) Always allocate if it is a user vm - if (nic == null || (vmProfile.getType() == VirtualMachine.Type.User)) { - int deviceId = _nicDao.countNics(vm.getId()); - - nic = allocateNic(requested, network, false, - deviceId, vmProfile).first(); - - if (nic == null) { - throw new CloudRuntimeException("Failed to allocate nic for vm " + vm + " in network " + network); + + VirtualMachine vm = vmProfile.getVirtualMachine(); + DataCenter dc = _configMgr.getZone(network.getDataCenterId()); + Host host = _hostDao.findById(vm.getHostId()); + DeployDestination dest = new DeployDestination(dc, null, null, host); + + NicProfile nic = getNicProfileForVm(network, requested, vm); + + //1) allocate nic (if needed) Always allocate if it is a user vm + if (nic == null || (vmProfile.getType() == VirtualMachine.Type.User)) { + int deviceId = _nicDao.countNics(vm.getId()); + + nic = allocateNic(requested, network, false, + deviceId, vmProfile).first(); + + if (nic == null) { + throw new CloudRuntimeException("Failed to allocate nic for vm " + vm + " in network " + network); + } + + s_logger.debug("Nic is allocated successfully for vm " + vm + " in network " + network); + } + + //2) prepare nic + if (prepare) { + Pair implemented = implementNetwork(nic.getNetworkId(), dest, context); + nic = prepareNic(vmProfile, dest, context, nic.getId(), implemented.second()); + s_logger.debug("Nic is prepared successfully for vm " + vm + " in network " + network); + } + + return nic; } - s_logger.debug("Nic is allocated successfully for vm " + vm + " in network " + network); - } - - //2) prepare nic - if (prepare) { - Pair implemented = implementNetwork(nic.getNetworkId(), dest, context); - nic = prepareNic(vmProfile, dest, context, nic.getId(), implemented.second()); - s_logger.debug("Nic is prepared successfully for vm " + vm + " in network " + network); - } - - return nic; - } - @Override public List getNicProfiles(VirtualMachine vm) { @@ -4265,7 +4264,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } return elements; } - + @Override public StaticNatServiceProvider getStaticNatProviderForNetwork(Network network) { @@ -4301,7 +4300,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L assert lbElement instanceof LoadBalancingServiceProvider; return (LoadBalancingServiceProvider)lbElement; } - + @Override public boolean isNetworkInlineMode(Network network) { @@ -4319,7 +4318,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } - @Override + @Override public boolean isSecondaryIpSetForNic(long nicId) { NicVO nic = _nicDao.findById(nicId); return nic.getSecondaryIp(); @@ -4327,42 +4326,41 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L private boolean removeVmSecondaryIpsOfNic(long nicId) { - Transaction txn = Transaction.currentTxn(); - txn.start(); - List ipList = _nicSecondaryIpDao.listByNicId(nicId); - if (ipList != null) { - for (NicSecondaryIpVO ip: ipList) { - _nicSecondaryIpDao.remove(ip.getId()); + Transaction txn = Transaction.currentTxn(); + txn.start(); + List ipList = _nicSecondaryIpDao.listByNicId(nicId); + if (ipList != null) { + for (NicSecondaryIpVO ip: ipList) { + _nicSecondaryIpDao.remove(ip.getId()); + } + s_logger.debug("Revoving nic secondary ip entry ..."); } - s_logger.debug("Revoving nic secondary ip entry ..."); - } - txn.commit(); - return true; - } - - - @Override - public String allocatePublicIpForGuestNic(Long networkId, DataCenter dc, Pod pod,Account owner, - String requestedIp) throws InsufficientAddressCapacityException { - PublicIp ip = assignPublicIpAddress(dc.getId(), null, owner, VlanType.DirectAttached, networkId, requestedIp, false); - if (ip == null) { - s_logger.debug("There is no free public ip address"); - return null; + txn.commit(); + return true; } - Ip ipAddr = ip.getAddress(); - return ipAddr.addr(); - } - @Override + @Override + public String allocatePublicIpForGuestNic(Long networkId, DataCenter dc, Pod pod,Account owner, + String requestedIp) throws InsufficientAddressCapacityException { + PublicIp ip = assignPublicIpAddress(dc.getId(), null, owner, VlanType.DirectAttached, networkId, requestedIp, false); + if (ip == null) { + s_logger.debug("There is no free public ip address"); + return null; + } + Ip ipAddr = ip.getAddress(); + return ipAddr.addr(); + } + + + @Override public NicVO savePlaceholderNic(Network network, String ip4Address, String ip6Address, Type vmType) { - NicVO nic = new NicVO(null, null, network.getId(), null); - nic.setIp4Address(ip4Address); + NicVO nic = new NicVO(null, null, network.getId(), null); + nic.setIp4Address(ip4Address); nic.setIp6Address(ip6Address); nic.setReservationStrategy(ReservationStrategy.PlaceHolder); nic.setState(Nic.State.Reserved); nic.setVmType(vmType); return _nicDao.persist(nic); } - } diff --git a/server/src/com/cloud/network/NetworkUsageManagerImpl.java b/server/src/com/cloud/network/NetworkUsageManagerImpl.java index 80f898b0d7a..3ac77f98cfd 100755 --- a/server/src/com/cloud/network/NetworkUsageManagerImpl.java +++ b/server/src/com/cloud/network/NetworkUsageManagerImpl.java @@ -481,7 +481,7 @@ public class NetworkUsageManagerImpl extends ManagerBase implements NetworkUsage } @Override - public void processConnect(HostVO agent, StartupCommand cmd, boolean forRebalance) { + public void processConnect(Host agent, StartupCommand cmd, boolean forRebalance) { if (cmd instanceof StartupTrafficMonitorCommand) { long agentId = agent.getId(); s_logger.debug("Sending RecurringNetworkUsageCommand to " + agentId); diff --git a/server/src/com/cloud/network/SshKeysDistriMonitor.java b/server/src/com/cloud/network/SshKeysDistriMonitor.java index 82f72de8c3b..cd92ae66377 100755 --- a/server/src/com/cloud/network/SshKeysDistriMonitor.java +++ b/server/src/com/cloud/network/SshKeysDistriMonitor.java @@ -31,7 +31,7 @@ import com.cloud.agent.manager.Commands; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConnectionException; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; @@ -69,7 +69,7 @@ public class SshKeysDistriMonitor implements Listener { } @Override - public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { + public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { if (cmd instanceof StartupRoutingCommand) { if (((StartupRoutingCommand) cmd).getHypervisorType() == HypervisorType.KVM || ((StartupRoutingCommand) cmd).getHypervisorType() == HypervisorType.XenServer || diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index c9dee9c933e..3489dbfb34c 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -101,6 +101,7 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.StorageUnavailableException; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; @@ -1741,37 +1742,37 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V s_logger.debug("Adding nic for Virtual Router in Guest network " + guestNetwork); String defaultNetworkStartIp = null, defaultNetworkStartIpv6 = null; if (!setupPublicNetwork) { - Nic placeholder = _networkModel.getPlaceholderNicForRouter(guestNetwork, plan.getPodId()); + Nic placeholder = _networkModel.getPlaceholderNicForRouter(guestNetwork, plan.getPodId()); if (guestNetwork.getCidr() != null) { if (placeholder != null && placeholder.getIp4Address() != null) { s_logger.debug("Requesting ipv4 address " + placeholder.getIp4Address() + " stored in placeholder nic for the network " + guestNetwork); - defaultNetworkStartIp = placeholder.getIp4Address(); - } else { - String startIp = _networkModel.getStartIpAddress(guestNetwork.getId()); - if (startIp != null && _ipAddressDao.findByIpAndSourceNetworkId(guestNetwork.getId(), startIp).getAllocatedTime() == null) { - defaultNetworkStartIp = startIp; - } else if (s_logger.isDebugEnabled()){ + defaultNetworkStartIp = placeholder.getIp4Address(); + } else { + String startIp = _networkModel.getStartIpAddress(guestNetwork.getId()); + if (startIp != null && _ipAddressDao.findByIpAndSourceNetworkId(guestNetwork.getId(), startIp).getAllocatedTime() == null) { + defaultNetworkStartIp = startIp; + } else if (s_logger.isDebugEnabled()){ s_logger.debug("First ipv4 " + startIp + " in network id=" + guestNetwork.getId() + - " is already allocated, can't use it for domain router; will get random ip address from the range"); - } - } + " is already allocated, can't use it for domain router; will get random ip address from the range"); + } + } } - + if (guestNetwork.getIp6Cidr() != null) { if (placeholder != null && placeholder.getIp6Address() != null) { s_logger.debug("Requesting ipv6 address " + placeholder.getIp6Address() + " stored in placeholder nic for the network " + guestNetwork); defaultNetworkStartIpv6 = placeholder.getIp6Address(); } else { - String startIpv6 = _networkModel.getStartIpv6Address(guestNetwork.getId()); - if (startIpv6 != null && _ipv6Dao.findByNetworkIdAndIp(guestNetwork.getId(), startIpv6) == null) { - defaultNetworkStartIpv6 = startIpv6; - } else if (s_logger.isDebugEnabled()){ - s_logger.debug("First ipv6 " + startIpv6 + " in network id=" + guestNetwork.getId() + - " is already allocated, can't use it for domain router; will get random ipv6 address from the range"); - } + String startIpv6 = _networkModel.getStartIpv6Address(guestNetwork.getId()); + if (startIpv6 != null && _ipv6Dao.findByNetworkIdAndIp(guestNetwork.getId(), startIpv6) == null) { + defaultNetworkStartIpv6 = startIpv6; + } else if (s_logger.isDebugEnabled()){ + s_logger.debug("First ipv6 " + startIpv6 + " in network id=" + guestNetwork.getId() + + " is already allocated, can't use it for domain router; will get random ipv6 address from the range"); } } } + } NicProfile gatewayNic = new NicProfile(defaultNetworkStartIp, defaultNetworkStartIpv6); if (setupPublicNetwork) { @@ -2240,15 +2241,15 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V PvlanSetupCommand cmd = PvlanSetupCommand.createDhcpSetup(op, nic.getBroadCastUri(), networkTag, router.getInstanceName(), nic.getMacAddress(), nic.getIp4Address()); // In fact we send command to the host of router, we're not programming router but the host Answer answer = null; - try { + try { answer = _agentMgr.send(hostId, cmd); } catch (OperationTimedoutException e) { s_logger.warn("Timed Out", e); return false; - } catch (AgentUnavailableException e) { + } catch (AgentUnavailableException e) { s_logger.warn("Agent Unavailable ", e); - return false; - } + return false; + } if (answer == null || !answer.getResult()) { return false; @@ -2491,7 +2492,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V activeIpAliasTOs.add(new IpAliasTO(aliasVO.getIp4Address(), aliasVO.getNetmask(), aliasVO.getAliasCount().toString())); } if (revokedIpAliasTOs.size() != 0 || activeIpAliasTOs.size() != 0){ - createDeleteIpAliasCommand(router, revokedIpAliasTOs, activeIpAliasTOs, guestNetworkId, cmds); + createDeleteIpAliasCommand(router, revokedIpAliasTOs, activeIpAliasTOs, guestNetworkId, cmds); configDnsMasq(router, _networkDao.findById(guestNetworkId), cmds); } @@ -2803,7 +2804,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V vlanDbIdList.add(vlan.getId()); } if (dc.getNetworkType() == NetworkType.Basic) { - routerPublicIP = _networkMgr.assignPublicIpAddressFromVlans(router.getDataCenterId(), vm.getPodIdToDeployIn(), caller, Vlan.VlanType.DirectAttached, vlanDbIdList, nic.getNetworkId(), null, false); + routerPublicIP = _networkMgr.assignPublicIpAddressFromVlans(router.getDataCenterId(), vm.getPodIdToDeployIn(), caller, Vlan.VlanType.DirectAttached, vlanDbIdList, nic.getNetworkId(), null, false); } else { routerPublicIP = _networkMgr.assignPublicIpAddressFromVlans(router.getDataCenterId(), null, caller, Vlan.VlanType.DirectAttached, vlanDbIdList, nic.getNetworkId(), null, false); @@ -3872,7 +3873,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } @Override - public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { + public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { UserContext context = UserContext.current(); context.setAccountId(1); List routers = _routerDao.listIsolatedByHostId(host.getId()); diff --git a/server/src/com/cloud/network/security/SecurityGroupListener.java b/server/src/com/cloud/network/security/SecurityGroupListener.java index 32452532f55..0c101f257d4 100755 --- a/server/src/com/cloud/network/security/SecurityGroupListener.java +++ b/server/src/com/cloud/network/security/SecurityGroupListener.java @@ -38,7 +38,7 @@ import com.cloud.agent.api.StartupRoutingCommand; import com.cloud.agent.api.SecurityGroupRuleAnswer.FailureReason; import com.cloud.agent.manager.Commands; import com.cloud.exception.AgentUnavailableException; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.host.Status; import com.cloud.network.security.SecurityGroupWork.Step; import com.cloud.network.security.dao.SecurityGroupWorkDao; @@ -157,7 +157,7 @@ public class SecurityGroupListener implements Listener { @Override - public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) { + public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) { if(s_logger.isInfoEnabled()) s_logger.info("Received a host startup notification"); diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index c6e8d7d7729..fe91cb337d0 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -45,6 +45,7 @@ import org.apache.cloudstack.api.command.admin.storage.AddS3Cmd; import org.apache.cloudstack.api.command.admin.storage.ListS3sCmd; import org.apache.cloudstack.api.command.admin.swift.AddSwiftCmd; import org.apache.cloudstack.api.command.admin.swift.ListSwiftsCmd; +import org.apache.cloudstack.region.dao.RegionDao; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.log4j.Logger; @@ -167,92 +168,95 @@ import com.cloud.dc.DataCenter.NetworkType; @Component @Local({ ResourceManager.class, ResourceService.class }) -public class ResourceManagerImpl extends ManagerBase implements ResourceManager, ResourceService, - Manager { - private static final Logger s_logger = Logger - .getLogger(ResourceManagerImpl.class); +public class ResourceManagerImpl extends ManagerBase implements ResourceManager, ResourceService, Manager { + private static final Logger s_logger = Logger.getLogger(ResourceManagerImpl.class); @Inject - AccountManager _accountMgr; + AccountManager _accountMgr; @Inject - AgentManager _agentMgr; + AgentManager _agentMgr; @Inject - StorageManager _storageMgr; + StorageManager _storageMgr; @Inject - protected SecondaryStorageVmManager _secondaryStorageMgr; - + protected SecondaryStorageVmManager _secondaryStorageMgr; @Inject - protected DataCenterDao _dcDao; + protected RegionDao _regionDao; @Inject - protected HostPodDao _podDao; + protected DataCenterDao _dcDao; @Inject - protected ClusterDetailsDao _clusterDetailsDao; + protected HostPodDao _podDao; @Inject - protected ClusterDao _clusterDao; + protected ClusterDetailsDao _clusterDetailsDao; @Inject - protected CapacityDao _capacityDao; + protected ClusterDao _clusterDao; @Inject - protected HostDao _hostDao; + protected CapacityDao _capacityDao; + @Inject + protected HostDao _hostDao; @Inject protected SwiftManager _swiftMgr; @Inject - protected S3Manager _s3Mgr; + protected S3Manager _s3Mgr; @Inject - protected HostDetailsDao _hostDetailsDao; + protected HostDetailsDao _hostDetailsDao; @Inject protected ConfigurationDao _configDao; @Inject - protected HostTagsDao _hostTagsDao; + protected HostTagsDao _hostTagsDao; @Inject - protected GuestOSCategoryDao _guestOSCategoryDao; + protected GuestOSCategoryDao _guestOSCategoryDao; @Inject - protected PrimaryDataStoreDao _storagePoolDao; + protected PrimaryDataStoreDao _storagePoolDao; @Inject - protected DataCenterIpAddressDao _privateIPAddressDao; + protected DataCenterIpAddressDao _privateIPAddressDao; @Inject - protected IPAddressDao _publicIPAddressDao; + protected IPAddressDao _publicIPAddressDao; @Inject - protected VirtualMachineManager _vmMgr; + protected VirtualMachineManager _vmMgr; @Inject - protected VMInstanceDao _vmDao; + protected VMInstanceDao _vmDao; @Inject - protected HighAvailabilityManager _haMgr; + protected HighAvailabilityManager _haMgr; @Inject - protected StorageService _storageSvr; + protected StorageService _storageSvr; @Inject PlannerHostReservationDao _plannerHostReserveDao; @Inject protected DedicatedResourceDao _dedicatedDao; protected List _discoverers; + public List getDiscoverers() { - return _discoverers; - } - public void setDiscoverers(List _discoverers) { - this._discoverers = _discoverers; - } + return _discoverers; + } + + public void setDiscoverers(List _discoverers) { + this._discoverers = _discoverers; + } - @Inject - protected ClusterManager _clusterMgr; @Inject - protected StoragePoolHostDao _storagePoolHostDao; + protected ClusterManager _clusterMgr; + @Inject + protected StoragePoolHostDao _storagePoolHostDao; + + protected List _podAllocators; - protected List _podAllocators; public List getPodAllocators() { - return _podAllocators; - } - public void setPodAllocators(List _podAllocators) { - this._podAllocators = _podAllocators; - } + return _podAllocators; + } - @Inject - protected VMTemplateDao _templateDao; - @Inject - protected ConfigurationManager _configMgr; - @Inject - protected ClusterVSMMapDao _clusterVSMMapDao; + public void setPodAllocators(List _podAllocators) { + this._podAllocators = _podAllocators; + } - protected long _nodeId = ManagementServerNode.getManagementServerId(); + @Inject + protected VMTemplateDao _templateDao; + @Inject + protected ConfigurationManager _configMgr; + @Inject + protected ClusterVSMMapDao _clusterVSMMapDao; + + protected long _nodeId = ManagementServerNode.getManagementServerId(); protected HashMap _resourceStateAdapters = new HashMap(); @@ -269,8 +273,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } if (lst.contains(listener)) { - throw new CloudRuntimeException("Duplicate resource lisener:" - + listener.getClass().getSimpleName()); + throw new CloudRuntimeException("Duplicate resource lisener:" + listener.getClass().getSimpleName()); } lst.add(listener); @@ -286,31 +289,22 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, insertListener(ResourceListener.EVENT_DISCOVER_AFTER, listener); } if ((event & ResourceListener.EVENT_DELETE_HOST_BEFORE) != 0) { - insertListener(ResourceListener.EVENT_DELETE_HOST_BEFORE, - listener); + insertListener(ResourceListener.EVENT_DELETE_HOST_BEFORE, listener); } if ((event & ResourceListener.EVENT_DELETE_HOST_AFTER) != 0) { - insertListener(ResourceListener.EVENT_DELETE_HOST_AFTER, - listener); + insertListener(ResourceListener.EVENT_DELETE_HOST_AFTER, listener); } if ((event & ResourceListener.EVENT_CANCEL_MAINTENANCE_BEFORE) != 0) { - insertListener( - ResourceListener.EVENT_CANCEL_MAINTENANCE_BEFORE, - listener); + insertListener(ResourceListener.EVENT_CANCEL_MAINTENANCE_BEFORE, listener); } if ((event & ResourceListener.EVENT_CANCEL_MAINTENANCE_AFTER) != 0) { - insertListener(ResourceListener.EVENT_CANCEL_MAINTENANCE_AFTER, - listener); + insertListener(ResourceListener.EVENT_CANCEL_MAINTENANCE_AFTER, listener); } if ((event & ResourceListener.EVENT_PREPARE_MAINTENANCE_BEFORE) != 0) { - insertListener( - ResourceListener.EVENT_PREPARE_MAINTENANCE_BEFORE, - listener); + insertListener(ResourceListener.EVENT_PREPARE_MAINTENANCE_BEFORE, listener); } if ((event & ResourceListener.EVENT_PREPARE_MAINTENANCE_AFTER) != 0) { - insertListener( - ResourceListener.EVENT_PREPARE_MAINTENANCE_AFTER, - listener); + insertListener(ResourceListener.EVENT_PREPARE_MAINTENANCE_AFTER, listener); } } } @@ -320,15 +314,14 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, synchronized (_lifeCycleListeners) { Iterator it = _lifeCycleListeners.entrySet().iterator(); while (it.hasNext()) { - Map.Entry> items = (Map.Entry>) it - .next(); + Map.Entry> items = (Map.Entry>) it.next(); List lst = items.getValue(); lst.remove(listener); } } } - protected void processResourceEvent(Integer event, Object... params) { + protected void processResourceEvent(Integer event, Object... params) { List lst = _lifeCycleListeners.get(event); if (lst == null || lst.size() == 0) { return; @@ -337,10 +330,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, String eventName; for (ResourceListener l : lst) { if (event == ResourceListener.EVENT_DISCOVER_BEFORE) { - l.processDiscoverEventBefore((Long) params[0], - (Long) params[1], (Long) params[2], (URI) params[3], - (String) params[4], (String) params[5], - (List) params[6]); + l.processDiscoverEventBefore((Long) params[0], (Long) params[1], (Long) params[2], (URI) params[3], (String) params[4], + (String) params[5], (List) params[6]); eventName = "EVENT_DISCOVER_BEFORE"; } else if (event == ResourceListener.EVENT_DISCOVER_AFTER) { l.processDiscoverEventAfter((Map>) params[0]); @@ -364,20 +355,16 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, l.processPrepareMaintenaceEventAfter((Long) params[0]); eventName = "EVENT_PREPARE_MAINTENANCE_AFTER"; } else { - throw new CloudRuntimeException("Unknown resource event:" - + event); + throw new CloudRuntimeException("Unknown resource event:" + event); } - s_logger.debug("Sent resource event " + eventName + " to listener " - + l.getClass().getSimpleName()); + s_logger.debug("Sent resource event " + eventName + " to listener " + l.getClass().getSimpleName()); } } @DB @Override - public List discoverCluster(AddClusterCmd cmd) - throws IllegalArgumentException, DiscoveryException, - ResourceInUseException { + public List discoverCluster(AddClusterCmd cmd) throws IllegalArgumentException, DiscoveryException, ResourceInUseException { long dcId = cmd.getZoneId(); long podId = cmd.getPodId(); String clusterName = cmd.getClusterName(); @@ -401,24 +388,21 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } Account account = UserContext.current().getCaller(); - if (Grouping.AllocationState.Disabled == zone.getAllocationState() - && !_accountMgr.isRootAdmin(account.getType())) { - PermissionDeniedException ex = new PermissionDeniedException( - "Cannot perform this operation, Zone with specified id is currently disabled"); + if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(account.getType())) { + PermissionDeniedException ex = new PermissionDeniedException( + "Cannot perform this operation, Zone with specified id is currently disabled"); ex.addProxyObject(zone.getUuid(), "dcId"); throw ex; } HostPodVO pod = _podDao.findById(podId); if (pod == null) { - throw new InvalidParameterValueException( - "Can't find pod with specified podId " + podId); + throw new InvalidParameterValueException("Can't find pod with specified podId " + podId); } // Check if the pod exists in the system if (_podDao.findById(podId) == null) { - throw new InvalidParameterValueException("Can't find pod by id " - + podId); + throw new InvalidParameterValueException("Can't find pod by id " + podId); } // check if pod belongs to the zone if (!Long.valueOf(pod.getDataCenterId()).equals(dcId)) { @@ -431,22 +415,17 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, // Verify cluster information and create a new cluster if needed if (clusterName == null || clusterName.isEmpty()) { - throw new InvalidParameterValueException( - "Please specify cluster name"); + throw new InvalidParameterValueException("Please specify cluster name"); } if (cmd.getHypervisor() == null || cmd.getHypervisor().isEmpty()) { - throw new InvalidParameterValueException( - "Please specify a hypervisor"); + throw new InvalidParameterValueException("Please specify a hypervisor"); } - Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType - .getType(cmd.getHypervisor()); + Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.getType(cmd.getHypervisor()); if (hypervisorType == null) { - s_logger.error("Unable to resolve " + cmd.getHypervisor() - + " to a valid supported hypervisor type"); - throw new InvalidParameterValueException("Unable to resolve " - + cmd.getHypervisor() + " to a supported "); + s_logger.error("Unable to resolve " + cmd.getHypervisor() + " to a valid supported hypervisor type"); + throw new InvalidParameterValueException("Unable to resolve " + cmd.getHypervisor() + " to a supported "); } if (zone.isSecurityGroupEnabled() && zone.getNetworkType().equals(NetworkType.Advanced)) { @@ -465,16 +444,11 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } Grouping.AllocationState allocationState = null; - if (cmd.getAllocationState() != null - && !cmd.getAllocationState().isEmpty()) { + if (cmd.getAllocationState() != null && !cmd.getAllocationState().isEmpty()) { try { - allocationState = Grouping.AllocationState.valueOf(cmd - .getAllocationState()); + allocationState = Grouping.AllocationState.valueOf(cmd.getAllocationState()); } catch (IllegalArgumentException ex) { - throw new InvalidParameterValueException( - "Unable to resolve Allocation State '" - + cmd.getAllocationState() - + "' to a supported state"); + throw new InvalidParameterValueException("Unable to resolve Allocation State '" + cmd.getAllocationState() + "' to a supported state"); } } if (allocationState == null) { @@ -484,9 +458,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, Discoverer discoverer = getMatchingDiscover(hypervisorType); if (discoverer == null) { - throw new InvalidParameterValueException( - "Could not find corresponding resource manager for " - + cmd.getHypervisor()); + throw new InvalidParameterValueException("Could not find corresponding resource manager for " + cmd.getHypervisor()); } if (hypervisorType == HypervisorType.VMware) { @@ -506,9 +478,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, cluster = _clusterDao.persist(cluster); } catch (Exception e) { // no longer tolerate exception during the cluster creation phase - CloudRuntimeException ex = new CloudRuntimeException( - "Unable to create cluster " + clusterName - + " in pod and data center with specified ids", e); + CloudRuntimeException ex = new CloudRuntimeException("Unable to create cluster " + clusterName + + " in pod and data center with specified ids", e); // Get the pod VO object's table name. ex.addProxyObject(pod.getUuid(), "podId"); ex.addProxyObject(zone.getUuid(), "dcId"); @@ -535,8 +506,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, _clusterDetailsDao.persist(cluster_detail_cpu); _clusterDetailsDao.persist(cluster_detail_ram); - //create a new entry only if the overcommit ratios are greater than 1. - if(cmd.getCpuOvercommitRatio().compareTo(1f) > 0) { + // create a new entry only if the overcommit ratios are greater than 1. + if (cmd.getCpuOvercommitRatio().compareTo(1f) > 0) { cluster_detail_cpu = new ClusterDetailsVO(clusterId, "cpuOvercommitRatio", Float.toString(cmd.getCpuOvercommitRatio())); _clusterDetailsDao.persist(cluster_detail_cpu); } @@ -547,54 +518,42 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, _clusterDetailsDao.persist(cluster_detail_ram); } - boolean success = false; try { try { uri = new URI(UriUtils.encodeURIComponent(url)); if (uri.getScheme() == null) { - throw new InvalidParameterValueException( - "uri.scheme is null " + url - + ", add http:// as a prefix"); + throw new InvalidParameterValueException("uri.scheme is null " + url + ", add http:// as a prefix"); } else if (uri.getScheme().equalsIgnoreCase("http")) { - if (uri.getHost() == null - || uri.getHost().equalsIgnoreCase("") - || uri.getPath() == null - || uri.getPath().equalsIgnoreCase("")) { - throw new InvalidParameterValueException( - "Your host and/or path is wrong. Make sure it's of the format http://hostname/path"); + if (uri.getHost() == null || uri.getHost().equalsIgnoreCase("") || uri.getPath() == null || uri.getPath().equalsIgnoreCase("")) { + throw new InvalidParameterValueException("Your host and/or path is wrong. Make sure it's of the format http://hostname/path"); } } } catch (URISyntaxException e) { - throw new InvalidParameterValueException(url - + " is not a valid uri"); + throw new InvalidParameterValueException(url + " is not a valid uri"); } List hosts = new ArrayList(); Map> resources = null; - resources = discoverer.find(dcId, podId, clusterId, uri, username, - password, null); + resources = discoverer.find(dcId, podId, clusterId, uri, username, password, null); if (resources != null) { - for (Map.Entry> entry : resources - .entrySet()) { + for (Map.Entry> entry : resources.entrySet()) { ServerResource resource = entry.getKey(); - // For Hyper-V, we are here means agent have already started - // and connected to management server + // For Hyper-V, we are here means agent have already started + // and connected to management server if (hypervisorType == Hypervisor.HypervisorType.Hyperv) { break; } - HostVO host = (HostVO) createHostAndAgent(resource, - entry.getValue(), true, null, false); + HostVO host = (HostVO) createHostAndAgent(resource, entry.getValue(), true, null, false); if (host != null) { hosts.add(host); } discoverer.postDiscovery(hosts, _nodeId); } - s_logger.info("External cluster has been successfully discovered by " - + discoverer.getName()); + s_logger.info("External cluster has been successfully discovered by " + discoverer.getName()); success = true; return result; } @@ -610,19 +569,16 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } @Override - public Discoverer getMatchingDiscover( - Hypervisor.HypervisorType hypervisorType) { - for (Discoverer discoverer : _discoverers) { - if (discoverer.getHypervisorType() == hypervisorType) + public Discoverer getMatchingDiscover(Hypervisor.HypervisorType hypervisorType) { + for (Discoverer discoverer : _discoverers) { + if (discoverer.getHypervisorType() == hypervisorType) return discoverer; - } + } return null; } @Override - public List discoverHosts(AddHostCmd cmd) - throws IllegalArgumentException, DiscoveryException, - InvalidParameterValueException { + public List discoverHosts(AddHostCmd cmd) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException { Long dcId = cmd.getZoneId(); Long podId = cmd.getPodId(); Long clusterId = cmd.getClusterId(); @@ -632,8 +588,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, String password = cmd.getPassword(); List hostTags = cmd.getHostTags(); - dcId = _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current() - .getCaller(), dcId); + dcId = _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), dcId); // this is for standalone option if (clusterName == null && clusterId == null) { @@ -651,8 +606,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (cluster.getGuid() == null) { List hosts = listAllHostsInCluster(clusterId); if (!hosts.isEmpty()) { - CloudRuntimeException ex = new CloudRuntimeException( - "Guid is not updated for cluster with specified cluster id; need to wait for hosts in this cluster to come up"); + CloudRuntimeException ex = new CloudRuntimeException( + "Guid is not updated for cluster with specified cluster id; need to wait for hosts in this cluster to come up"); ex.addProxyObject(cluster.getUuid(), "clusterId"); throw ex; } @@ -660,13 +615,13 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } } - return discoverHostsFull(dcId, podId, clusterId, clusterName, url, username, password, cmd.getHypervisor(), hostTags, cmd.getFullUrlParams(), true); + return discoverHostsFull(dcId, podId, clusterId, clusterName, url, username, password, cmd.getHypervisor(), hostTags, cmd.getFullUrlParams(), + true); } @Override - public List discoverHosts(AddSecondaryStorageCmd cmd) - throws IllegalArgumentException, DiscoveryException, - InvalidParameterValueException { + public List discoverHosts(AddSecondaryStorageCmd cmd) throws IllegalArgumentException, DiscoveryException, + InvalidParameterValueException { Long dcId = cmd.getZoneId(); String url = cmd.getUrl(); return discoverHostsFull(dcId, null, null, null, url, null, null, "SecondaryStorage", null, null, false); @@ -679,7 +634,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, @Override public Pair, Integer> listSwifts(ListSwiftsCmd cmd) { - Pair, Integer> swifts = _swiftMgr.listSwifts(cmd); + Pair, Integer> swifts = _swiftMgr.listSwifts(cmd); return new Pair, Integer>(swifts.first(), swifts.second()); } @@ -693,22 +648,22 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, return this._s3Mgr.listS3s(cmd); } - private List discoverHostsFull(Long dcId, Long podId, Long clusterId, String clusterName, String url, String username, String password, String hypervisorType, List hostTags, - Map params, boolean deferAgentCreation) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException { + + private List discoverHostsFull(Long dcId, Long podId, Long clusterId, String clusterName, String url, String username, String password, + String hypervisorType, List hostTags, Map params, boolean deferAgentCreation) throws IllegalArgumentException, + DiscoveryException, InvalidParameterValueException { URI uri = null; // Check if the zone exists in the system DataCenterVO zone = _dcDao.findById(dcId); if (zone == null) { - throw new InvalidParameterValueException("Can't find zone by id " - + dcId); + throw new InvalidParameterValueException("Can't find zone by id " + dcId); } Account account = UserContext.current().getCaller(); - if (Grouping.AllocationState.Disabled == zone.getAllocationState() - && !_accountMgr.isRootAdmin(account.getType())) { - PermissionDeniedException ex = new PermissionDeniedException( - "Cannot perform this operation, Zone with specified id is currently disabled"); + if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(account.getType())) { + PermissionDeniedException ex = new PermissionDeniedException( + "Cannot perform this operation, Zone with specified id is currently disabled"); ex.addProxyObject(zone.getUuid(), "dcId"); throw ex; } @@ -717,8 +672,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (podId != null) { HostPodVO pod = _podDao.findById(podId); if (pod == null) { - throw new InvalidParameterValueException( - "Can't find pod by id " + podId); + throw new InvalidParameterValueException("Can't find pod by id " + podId); } // check if pod belongs to the zone if (!Long.valueOf(pod.getDataCenterId()).equals(dcId)) { @@ -735,47 +689,40 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, // Verify cluster information and create a new cluster if needed if (clusterName != null && clusterId != null) { - throw new InvalidParameterValueException( - "Can't specify cluster by both id and name"); + throw new InvalidParameterValueException("Can't specify cluster by both id and name"); } if (hypervisorType == null || hypervisorType.isEmpty()) { - throw new InvalidParameterValueException( - "Need to specify Hypervisor Type"); + throw new InvalidParameterValueException("Need to specify Hypervisor Type"); } if ((clusterName != null || clusterId != null) && podId == null) { - throw new InvalidParameterValueException( - "Can't specify cluster without specifying the pod"); + throw new InvalidParameterValueException("Can't specify cluster without specifying the pod"); } if (clusterId != null) { if (_clusterDao.findById(clusterId) == null) { - throw new InvalidParameterValueException( - "Can't find cluster by id " + clusterId); - } + throw new InvalidParameterValueException("Can't find cluster by id " + clusterId); + } - if (hypervisorType.equalsIgnoreCase(HypervisorType.VMware - .toString())) { - // VMware only allows adding host to an existing cluster, as we - // already have a lot of information - // in cluster object, to simplify user input, we will construct - // neccessary information here - Map clusterDetails = this._clusterDetailsDao - .findDetails(clusterId); + if (hypervisorType.equalsIgnoreCase(HypervisorType.VMware.toString())) { + // VMware only allows adding host to an existing cluster, as we + // already have a lot of information + // in cluster object, to simplify user input, we will construct + // neccessary information here + Map clusterDetails = this._clusterDetailsDao.findDetails(clusterId); username = clusterDetails.get("username"); - assert (username != null); + assert (username != null); password = clusterDetails.get("password"); - assert (password != null); + assert (password != null); try { uri = new URI(UriUtils.encodeURIComponent(url)); url = clusterDetails.get("url") + "/" + uri.getHost(); } catch (URISyntaxException e) { - throw new InvalidParameterValueException(url - + " is not a valid uri"); + throw new InvalidParameterValueException(url + " is not a valid uri"); } } } @@ -783,8 +730,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (clusterName != null) { HostPodVO pod = _podDao.findById(podId); if (pod == null) { - throw new InvalidParameterValueException( - "Can't find pod by id " + podId); + throw new InvalidParameterValueException("Can't find pod by id " + podId); } ClusterVO cluster = new ClusterVO(dcId, podId, clusterName); cluster.setHypervisorType(hypervisorType); @@ -804,11 +750,11 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } } clusterId = cluster.getId(); - if (_clusterDetailsDao.findDetail(clusterId,"cpuOvercommitRatio") == null) { - ClusterDetailsVO cluster_cpu_detail = new ClusterDetailsVO(clusterId,"cpuOvercommitRatio","1"); - ClusterDetailsVO cluster_memory_detail = new ClusterDetailsVO(clusterId,"memoryOvercommitRatio","1"); - _clusterDetailsDao.persist(cluster_cpu_detail); - _clusterDetailsDao.persist(cluster_memory_detail); + if (_clusterDetailsDao.findDetail(clusterId, "cpuOvercommitRatio") == null) { + ClusterDetailsVO cluster_cpu_detail = new ClusterDetailsVO(clusterId, "cpuOvercommitRatio", "1"); + ClusterDetailsVO cluster_memory_detail = new ClusterDetailsVO(clusterId, "memoryOvercommitRatio", "1"); + _clusterDetailsDao.persist(cluster_cpu_detail); + _clusterDetailsDao.persist(cluster_memory_detail); } } @@ -816,26 +762,20 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, try { uri = new URI(UriUtils.encodeURIComponent(url)); if (uri.getScheme() == null) { - throw new InvalidParameterValueException("uri.scheme is null " - + url + ", add nfs:// as a prefix"); + throw new InvalidParameterValueException("uri.scheme is null " + url + ", add nfs:// as a prefix"); } else if (uri.getScheme().equalsIgnoreCase("nfs")) { - if (uri.getHost() == null || uri.getHost().equalsIgnoreCase("") - || uri.getPath() == null - || uri.getPath().equalsIgnoreCase("")) { - throw new InvalidParameterValueException( - "Your host and/or path is wrong. Make sure it's of the format nfs://hostname/path"); + if (uri.getHost() == null || uri.getHost().equalsIgnoreCase("") || uri.getPath() == null || uri.getPath().equalsIgnoreCase("")) { + throw new InvalidParameterValueException("Your host and/or path is wrong. Make sure it's of the format nfs://hostname/path"); } } } catch (URISyntaxException e) { - throw new InvalidParameterValueException(url - + " is not a valid uri"); + throw new InvalidParameterValueException(url + " is not a valid uri"); } List hosts = new ArrayList(); - s_logger.info("Trying to add a new host at " + url + " in data center " - + dcId); + s_logger.info("Trying to add a new host at " + url + " in data center " + dcId); boolean isHypervisorTypeSupported = false; - for (Discoverer discoverer : _discoverers) { + for (Discoverer discoverer : _discoverers) { if (params != null) { discoverer.putParam(params); } @@ -846,43 +786,35 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, isHypervisorTypeSupported = true; Map> resources = null; - processResourceEvent(ResourceListener.EVENT_DISCOVER_BEFORE, dcId, - podId, clusterId, uri, username, password, hostTags); + processResourceEvent(ResourceListener.EVENT_DISCOVER_BEFORE, dcId, podId, clusterId, uri, username, password, hostTags); try { - resources = discoverer.find(dcId, podId, clusterId, uri, - username, password, hostTags); - } catch (DiscoveryException e) { + resources = discoverer.find(dcId, podId, clusterId, uri, username, password, hostTags); + } catch (DiscoveryException e) { throw e; } catch (Exception e) { - s_logger.info("Exception in host discovery process with discoverer: " - + discoverer.getName() - + ", skip to another discoverer if there is any"); + s_logger.info("Exception in host discovery process with discoverer: " + discoverer.getName() + + ", skip to another discoverer if there is any"); } - processResourceEvent(ResourceListener.EVENT_DISCOVER_AFTER, - resources); + processResourceEvent(ResourceListener.EVENT_DISCOVER_AFTER, resources); if (resources != null) { - for (Map.Entry> entry : resources - .entrySet()) { + for (Map.Entry> entry : resources.entrySet()) { ServerResource resource = entry.getKey(); /* - * For KVM, if we go to here, that means kvm agent is - * already connected to mgt svr. + * For KVM, if we go to here, that means kvm agent is + * already connected to mgt svr. */ if (resource instanceof KvmDummyResourceBase) { Map details = entry.getValue(); String guid = details.get("guid"); - List kvmHosts = listAllUpAndEnabledHosts( - Host.Type.Routing, clusterId, podId, dcId); + List kvmHosts = listAllUpAndEnabledHosts(Host.Type.Routing, clusterId, podId, dcId); for (HostVO host : kvmHosts) { if (host.getGuid().equalsIgnoreCase(guid)) { - if (hostTags != null) { - if (s_logger.isTraceEnabled()) { - s_logger.trace("Adding Host Tags for KVM host, tags: :" - + hostTags); + if (hostTags != null) { + if (s_logger.isTraceEnabled()) { + s_logger.trace("Adding Host Tags for KVM host, tags: :" + hostTags); } - _hostTagsDao - .persist(host.getId(), hostTags); + _hostTagsDao.persist(host.getId(), hostTags); } hosts.add(host); return hosts; @@ -893,9 +825,9 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, HostVO host = null; if (deferAgentCreation) { - host = (HostVO)createHostAndAgentDeferred(resource, entry.getValue(), true, hostTags, false); + host = (HostVO) createHostAndAgentDeferred(resource, entry.getValue(), true, hostTags, false); } else { - host = (HostVO)createHostAndAgent(resource, entry.getValue(), true, hostTags, false); + host = (HostVO) createHostAndAgent(resource, entry.getValue(), true, hostTags, false); } if (host != null) { hosts.add(host); @@ -903,14 +835,12 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, discoverer.postDiscovery(hosts, _nodeId); } - s_logger.info("server resources successfully discovered by " - + discoverer.getName()); + s_logger.info("server resources successfully discovered by " + discoverer.getName()); return hosts; } } if (!isHypervisorTypeSupported) { - String msg = "Do not support HypervisorType " + hypervisorType - + " for " + url; + String msg = "Do not support HypervisorType " + hypervisorType + " for " + url; s_logger.warn(msg); throw new DiscoveryException(msg); } @@ -924,42 +854,33 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } @DB - protected boolean doDeleteHost(long hostId, boolean isForced, - boolean isForceDeleteStorage) { - User caller = _accountMgr.getActiveUser(UserContext.current() - .getCallerUserId()); + protected boolean doDeleteHost(long hostId, boolean isForced, boolean isForceDeleteStorage) { + User caller = _accountMgr.getActiveUser(UserContext.current().getCallerUserId()); // Verify that host exists HostVO host = _hostDao.findById(hostId); if (host == null) { - throw new InvalidParameterValueException("Host with id " + hostId - + " doesn't exist"); + throw new InvalidParameterValueException("Host with id " + hostId + " doesn't exist"); } - _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current() - .getCaller(), host.getDataCenterId()); + _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), host.getDataCenterId()); /* - * TODO: check current agent status and updateAgentStatus to removed. If - * it was already removed, that means someone is deleting host - * concurrently, return. And consider the situation of CloudStack - * shutdown during delete. A global lock? + * TODO: check current agent status and updateAgentStatus to removed. If + * it was already removed, that means someone is deleting host + * concurrently, return. And consider the situation of CloudStack + * shutdown during delete. A global lock? */ AgentAttache attache = _agentMgr.findAttache(hostId); - // Get storage pool host mappings here because they can be removed as a - // part of handleDisconnect later - // TODO: find out the bad boy, what's a buggy logic! - List pools = _storagePoolHostDao - .listByHostIdIncludingRemoved(hostId); + // Get storage pool host mappings here because they can be removed as a + // part of handleDisconnect later + // TODO: find out the bad boy, what's a buggy logic! + List pools = _storagePoolHostDao.listByHostIdIncludingRemoved(hostId); - ResourceStateAdapter.DeleteHostAnswer answer = (ResourceStateAdapter.DeleteHostAnswer) dispatchToStateAdapters( - ResourceStateAdapter.Event.DELETE_HOST, false, host, - new Boolean(isForced), new Boolean(isForceDeleteStorage)); + ResourceStateAdapter.DeleteHostAnswer answer = (ResourceStateAdapter.DeleteHostAnswer) dispatchToStateAdapters( + ResourceStateAdapter.Event.DELETE_HOST, false, host, new Boolean(isForced), new Boolean(isForceDeleteStorage)); if (answer == null) { - throw new CloudRuntimeException( - "No resource adapter respond to DELETE_HOST event for " - + host.getName() + " id = " + hostId - + ", hypervisorType is " + host.getHypervisorType() - + ", host type is " + host.getType()); + throw new CloudRuntimeException("No resource adapter respond to DELETE_HOST event for " + host.getName() + " id = " + hostId + + ", hypervisorType is " + host.getHypervisorType() + ", host type is " + host.getType()); } if (answer.getIsException()) { @@ -973,8 +894,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, Transaction txn = Transaction.currentTxn(); txn.start(); - _dcDao.releasePrivateIpAddress(host.getPrivateIpAddress(), - host.getDataCenterId(), null); + _dcDao.releasePrivateIpAddress(host.getPrivateIpAddress(), host.getDataCenterId(), null); _agentMgr.disconnectWithoutInvestigation(hostId, Status.Event.Remove); // delete host details @@ -996,18 +916,16 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } try { - resourceStateTransitTo(host, ResourceState.Event.DeleteHost, - _nodeId); + resourceStateTransitTo(host, ResourceState.Event.DeleteHost, _nodeId); } catch (NoTransitionException e) { - s_logger.debug("Cannot transmit host " + host.getId() - + "to Enabled state", e); + s_logger.debug("Cannot transmit host " + host.getId() + "to Enabled state", e); } // Delete the associated entries in host ref table _storagePoolHostDao.deletePrimaryRecordsForHost(hostId); - // For pool ids you got, delete local storage host entries in pool table - // where + // For pool ids you got, delete local storage host entries in pool table + // where for (StoragePoolHostVO pool : pools) { Long poolId = pool.getPoolId(); StoragePoolVO storagePool = _storagePoolDao.findById(poolId); @@ -1016,19 +934,15 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, storagePool.setClusterId(null); _storagePoolDao.update(poolId, storagePool); _storagePoolDao.remove(poolId); - s_logger.debug("Local storage id=" + poolId - + " is removed as a part of host removal id=" + hostId); + s_logger.debug("Local storage id=" + poolId + " is removed as a part of host removal id=" + hostId); } } // delete the op_host_capacity entry - Object[] capacityTypes = { Capacity.CAPACITY_TYPE_CPU, - Capacity.CAPACITY_TYPE_MEMORY }; - SearchCriteria hostCapacitySC = _capacityDao - .createSearchCriteria(); + Object[] capacityTypes = { Capacity.CAPACITY_TYPE_CPU, Capacity.CAPACITY_TYPE_MEMORY }; + SearchCriteria hostCapacitySC = _capacityDao.createSearchCriteria(); hostCapacitySC.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, hostId); - hostCapacitySC.addAnd("capacityType", SearchCriteria.Op.IN, - capacityTypes); + hostCapacitySC.addAnd("capacityType", SearchCriteria.Op.IN, capacityTypes); _capacityDao.remove(hostCapacitySC); // remove from dedicated resources DedicatedResourceVO dr = _dedicatedDao.findByHostId(hostId); @@ -1040,11 +954,9 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } @Override - public boolean deleteHost(long hostId, boolean isForced, - boolean isForceDeleteStorage) { + public boolean deleteHost(long hostId, boolean isForced, boolean isForceDeleteStorage) { try { - Boolean result = _clusterMgr.propagateResourceEvent(hostId, - ResourceState.Event.DeleteHost); + Boolean result = _clusterMgr.propagateResourceEvent(hostId, ResourceState.Event.DeleteHost); if (result != null) { return result; } @@ -1064,63 +976,52 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, ClusterVO cluster = _clusterDao.lockRow(cmd.getId(), true); if (cluster == null) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Cluster: " + cmd.getId() - + " does not even exist. Delete call is ignored."); + s_logger.debug("Cluster: " + cmd.getId() + " does not even exist. Delete call is ignored."); } txn.rollback(); - throw new CloudRuntimeException("Cluster: " + cmd.getId() - + " does not exist"); + throw new CloudRuntimeException("Cluster: " + cmd.getId() + " does not exist"); } - Hypervisor.HypervisorType hypervisorType = cluster - .getHypervisorType(); + Hypervisor.HypervisorType hypervisorType = cluster.getHypervisorType(); List hosts = listAllHostsInCluster(cmd.getId()); if (hosts.size() > 0) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Cluster: " + cmd.getId() - + " still has hosts, can't remove"); + s_logger.debug("Cluster: " + cmd.getId() + " still has hosts, can't remove"); } txn.rollback(); - throw new CloudRuntimeException("Cluster: " + cmd.getId() - + " cannot be removed. Cluster still has hosts"); + throw new CloudRuntimeException("Cluster: " + cmd.getId() + " cannot be removed. Cluster still has hosts"); } - // don't allow to remove the cluster if it has non-removed storage - // pools - List storagePools = _storagePoolDao - .listPoolsByCluster(cmd.getId()); + // don't allow to remove the cluster if it has non-removed storage + // pools + List storagePools = _storagePoolDao.listPoolsByCluster(cmd.getId()); if (storagePools.size() > 0) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Cluster: " + cmd.getId() - + " still has storage pools, can't remove"); + s_logger.debug("Cluster: " + cmd.getId() + " still has storage pools, can't remove"); } txn.rollback(); - throw new CloudRuntimeException("Cluster: " + cmd.getId() - + " cannot be removed. Cluster still has storage pools"); + throw new CloudRuntimeException("Cluster: " + cmd.getId() + " cannot be removed. Cluster still has storage pools"); } - if (_clusterDao.remove(cmd.getId())) { + if (_clusterDao.remove(cmd.getId())) { _capacityDao.removeBy(null, null, null, cluster.getId(), null); - // If this cluster is of type vmware, and if the nexus vswitch - // global parameter setting is turned + // If this cluster is of type vmware, and if the nexus vswitch + // global parameter setting is turned // on, remove the row in cluster_vsm_map for this cluster id. - if (hypervisorType == HypervisorType.VMware - && Boolean.parseBoolean(_configDao - .getValue(Config.VmwareUseNexusVSwitch - .toString()))) { - _clusterVSMMapDao.removeByClusterId(cmd.getId()); - } + if (hypervisorType == HypervisorType.VMware && Boolean.parseBoolean(_configDao.getValue(Config.VmwareUseNexusVSwitch.toString()))) { + _clusterVSMMapDao.removeByClusterId(cmd.getId()); + } // remove from dedicated resources DedicatedResourceVO dr = _dedicatedDao.findByClusterId(cluster.getId()); if (dr != null) { _dedicatedDao.remove(dr.getId()); } - } + } - txn.commit(); + txn.commit(); return true; - } catch (CloudRuntimeException e) { + } catch (CloudRuntimeException e) { throw e; } catch (Throwable t) { s_logger.error("Unable to delete cluster: " + cmd.getId(), t); @@ -1131,21 +1032,18 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, @Override @DB - public Cluster updateCluster(Cluster clusterToUpdate, String clusterType, - String hypervisor, String allocationState, String managedstate,Float memoryovercommitratio, Float cpuovercommitratio) { + public Cluster updateCluster(Cluster clusterToUpdate, String clusterType, String hypervisor, String allocationState, String managedstate, + Float memoryovercommitratio, Float cpuovercommitratio) { ClusterVO cluster = (ClusterVO) clusterToUpdate; // Verify cluster information and update the cluster if needed boolean doUpdate = false; if (hypervisor != null && !hypervisor.isEmpty()) { - Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType - .getType(hypervisor); + Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.getType(hypervisor); if (hypervisorType == null) { - s_logger.error("Unable to resolve " + hypervisor - + " to a valid supported hypervisor type"); - throw new InvalidParameterValueException("Unable to resolve " - + hypervisor + " to a supported type"); + s_logger.error("Unable to resolve " + hypervisor + " to a valid supported hypervisor type"); + throw new InvalidParameterValueException("Unable to resolve " + hypervisor + " to a supported type"); } else { cluster.setHypervisorType(hypervisor); doUpdate = true; @@ -1157,14 +1055,11 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, try { newClusterType = Cluster.ClusterType.valueOf(clusterType); } catch (IllegalArgumentException ex) { - throw new InvalidParameterValueException("Unable to resolve " - + clusterType + " to a supported type"); + throw new InvalidParameterValueException("Unable to resolve " + clusterType + " to a supported type"); } if (newClusterType == null) { - s_logger.error("Unable to resolve " + clusterType - + " to a valid supported cluster type"); - throw new InvalidParameterValueException("Unable to resolve " - + clusterType + " to a supported type"); + s_logger.error("Unable to resolve " + clusterType + " to a valid supported cluster type"); + throw new InvalidParameterValueException("Unable to resolve " + clusterType + " to a supported type"); } else { cluster.setClusterType(newClusterType); doUpdate = true; @@ -1174,21 +1069,15 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, Grouping.AllocationState newAllocationState = null; if (allocationState != null && !allocationState.isEmpty()) { try { - newAllocationState = Grouping.AllocationState - .valueOf(allocationState); + newAllocationState = Grouping.AllocationState.valueOf(allocationState); } catch (IllegalArgumentException ex) { - throw new InvalidParameterValueException( - "Unable to resolve Allocation State '" - + allocationState + "' to a supported state"); + throw new InvalidParameterValueException("Unable to resolve Allocation State '" + allocationState + "' to a supported state"); } if (newAllocationState == null) { - s_logger.error("Unable to resolve " + allocationState - + " to a valid supported allocation State"); - throw new InvalidParameterValueException("Unable to resolve " - + allocationState + " to a supported state"); + s_logger.error("Unable to resolve " + allocationState + " to a valid supported allocation State"); + throw new InvalidParameterValueException("Unable to resolve " + allocationState + " to a supported state"); } else { - _capacityDao.updateCapacityState(null, null, cluster.getId(), - null, allocationState); + _capacityDao.updateCapacityState(null, null, cluster.getId(), null, allocationState); cluster.setAllocationState(newAllocationState); doUpdate = true; } @@ -1200,21 +1089,17 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, try { newManagedState = Managed.ManagedState.valueOf(managedstate); } catch (IllegalArgumentException ex) { - throw new InvalidParameterValueException( - "Unable to resolve Managed State '" + managedstate - + "' to a supported state"); + throw new InvalidParameterValueException("Unable to resolve Managed State '" + managedstate + "' to a supported state"); } if (newManagedState == null) { - s_logger.error("Unable to resolve Managed State '" - + managedstate + "' to a supported state"); - throw new InvalidParameterValueException( - "Unable to resolve Managed State '" + managedstate - + "' to a supported state"); + s_logger.error("Unable to resolve Managed State '" + managedstate + "' to a supported state"); + throw new InvalidParameterValueException("Unable to resolve Managed State '" + managedstate + "' to a supported state"); } else { doUpdate = true; } } + if (memoryovercommitratio != null) { ClusterDetailsVO memory_detail = _clusterDetailsDao.findDetail(cluster.getId(),"memoryOvercommitRatio"); memory_detail.setValue(Float.toString(memoryovercommitratio)); @@ -1227,7 +1112,6 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, _clusterDetailsDao.update(cpu_detail.getId(),cpu_detail); } - if (doUpdate) { Transaction txn = Transaction.currentTxn(); try { @@ -1235,82 +1119,67 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, _clusterDao.update(cluster.getId(), cluster); txn.commit(); } catch (Exception e) { - s_logger.error( - "Unable to update cluster due to " + e.getMessage(), e); - throw new CloudRuntimeException( - "Failed to update cluster. Please contact Cloud Support."); + s_logger.error("Unable to update cluster due to " + e.getMessage(), e); + throw new CloudRuntimeException("Failed to update cluster. Please contact Cloud Support."); } } - if (newManagedState != null && !newManagedState.equals(oldManagedState)) { + if (newManagedState != null && !newManagedState.equals(oldManagedState)) { Transaction txn = Transaction.currentTxn(); - if (newManagedState.equals(Managed.ManagedState.Unmanaged)) { + if (newManagedState.equals(Managed.ManagedState.Unmanaged)) { boolean success = false; try { txn.start(); cluster.setManagedState(Managed.ManagedState.PrepareUnmanaged); _clusterDao.update(cluster.getId(), cluster); txn.commit(); - List hosts = listAllUpAndEnabledHosts( - Host.Type.Routing, cluster.getId(), - cluster.getPodId(), cluster.getDataCenterId()); - for (HostVO host : hosts) { - if (host.getType().equals(Host.Type.Routing) - && !host.getStatus().equals(Status.Down) - && !host.getStatus() - .equals(Status.Disconnected) - && !host.getStatus().equals(Status.Up) - && !host.getStatus().equals(Status.Alert)) { - String msg = "host " + host.getPrivateIpAddress() - + " should not be in " - + host.getStatus().toString() + " status"; - throw new CloudRuntimeException( - "PrepareUnmanaged Failed due to " + msg); + List hosts = listAllUpAndEnabledHosts(Host.Type.Routing, cluster.getId(), cluster.getPodId(), cluster.getDataCenterId()); + for (HostVO host : hosts) { + if (host.getType().equals(Host.Type.Routing) && !host.getStatus().equals(Status.Down) + && !host.getStatus().equals(Status.Disconnected) && !host.getStatus().equals(Status.Up) + && !host.getStatus().equals(Status.Alert)) { + String msg = "host " + host.getPrivateIpAddress() + " should not be in " + host.getStatus().toString() + " status"; + throw new CloudRuntimeException("PrepareUnmanaged Failed due to " + msg); } } - for (HostVO host : hosts) { - if (host.getStatus().equals(Status.Up)) { + for (HostVO host : hosts) { + if (host.getStatus().equals(Status.Up)) { umanageHost(host.getId()); } } int retry = 40; boolean lsuccess = true; - for (int i = 0; i < retry; i++) { + for (int i = 0; i < retry; i++) { lsuccess = true; try { Thread.sleep(5 * 1000); } catch (Exception e) { } - hosts = listAllUpAndEnabledHosts(Host.Type.Routing, - cluster.getId(), cluster.getPodId(), - cluster.getDataCenterId()); - for (HostVO host : hosts) { - if (!host.getStatus().equals(Status.Down) - && !host.getStatus().equals( - Status.Disconnected) + hosts = listAllUpAndEnabledHosts(Host.Type.Routing, cluster.getId(), cluster.getPodId(), cluster.getDataCenterId()); + for (HostVO host : hosts) { + if (!host.getStatus().equals(Status.Down) && !host.getStatus().equals(Status.Disconnected) && !host.getStatus().equals(Status.Alert)) { lsuccess = false; break; } } - if (lsuccess == true) { + if (lsuccess == true) { success = true; break; } } - if (success == false) { - throw new CloudRuntimeException( - "PrepareUnmanaged Failed due to some hosts are still in UP status after 5 Minutes, please try later "); + if (success == false) { + throw new CloudRuntimeException( + "PrepareUnmanaged Failed due to some hosts are still in UP status after 5 Minutes, please try later "); } } finally { txn.start(); - cluster.setManagedState(success ? Managed.ManagedState.Unmanaged - : Managed.ManagedState.PrepareUnmanagedError); + cluster.setManagedState(success ? Managed.ManagedState.Unmanaged : Managed.ManagedState.PrepareUnmanagedError); _clusterDao.update(cluster.getId(), cluster); txn.commit(); } - } else if (newManagedState.equals(Managed.ManagedState.Managed)) { + } else if (newManagedState.equals(Managed.ManagedState.Managed)) { txn.start(); cluster.setManagedState(Managed.ManagedState.Managed); _clusterDao.update(cluster.getId(), cluster); @@ -1329,18 +1198,14 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, // verify input parameters HostVO host = _hostDao.findById(hostId); if (host == null || host.getRemoved() != null) { - throw new InvalidParameterValueException("Host with id " - + hostId.toString() + " doesn't exist"); + throw new InvalidParameterValueException("Host with id " + hostId.toString() + " doesn't exist"); } - processResourceEvent(ResourceListener.EVENT_CANCEL_MAINTENANCE_BEFORE, - hostId); + processResourceEvent(ResourceListener.EVENT_CANCEL_MAINTENANCE_BEFORE, hostId); boolean success = cancelMaintenance(hostId); - processResourceEvent(ResourceListener.EVENT_CANCEL_MAINTENANCE_AFTER, - hostId); + processResourceEvent(ResourceListener.EVENT_CANCEL_MAINTENANCE_AFTER, hostId); if (!success) { - throw new CloudRuntimeException( - "Internal error cancelling maintenance."); + throw new CloudRuntimeException("Internal error cancelling maintenance."); } return host; } @@ -1351,63 +1216,51 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, HostVO host = _hostDao.findById(hostId); if (host == null) { - throw new InvalidParameterValueException("Host with id " - + hostId.toString() + " doesn't exist"); + throw new InvalidParameterValueException("Host with id " + hostId.toString() + " doesn't exist"); } return (_agentMgr.reconnect(hostId) ? host : null); } @Override - public boolean resourceStateTransitTo(Host host, ResourceState.Event event, - long msId) throws NoTransitionException { + public boolean resourceStateTransitTo(Host host, ResourceState.Event event, long msId) throws NoTransitionException { ResourceState currentState = host.getResourceState(); ResourceState nextState = currentState.getNextState(event); if (nextState == null) { - throw new NoTransitionException( - "No next resource state found for current state =" - + currentState + " event =" + event); + throw new NoTransitionException("No next resource state found for current state =" + currentState + " event =" + event); } - // TO DO - Make it more granular and have better conversion into - // capacity type + // TO DO - Make it more granular and have better conversion into + // capacity type - if (host.getType() == Type.Routing && host.getClusterId() != null) { - AllocationState capacityState = _configMgr - .findClusterAllocationState(ApiDBUtils.findClusterById(host - .getClusterId())); - if (capacityState == AllocationState.Enabled - && nextState != ResourceState.Enabled) { + if (host.getType() == Type.Routing && host.getClusterId() != null) { + AllocationState capacityState = _configMgr.findClusterAllocationState(ApiDBUtils.findClusterById(host.getClusterId())); + if (capacityState == AllocationState.Enabled && nextState != ResourceState.Enabled) { capacityState = AllocationState.Disabled; } - _capacityDao.updateCapacityState(null, null, null, host.getId(), - capacityState.toString()); + _capacityDao.updateCapacityState(null, null, null, host.getId(), capacityState.toString()); } - return _hostDao.updateResourceState(currentState, event, nextState, - host); + return _hostDao.updateResourceState(currentState, event, nextState, host); } private boolean doMaintain(final long hostId) { HostVO host = _hostDao.findById(hostId); - MaintainAnswer answer = (MaintainAnswer) _agentMgr.easySend(hostId, - new MaintainCommand()); + MaintainAnswer answer = (MaintainAnswer) _agentMgr.easySend(hostId, new MaintainCommand()); if (answer == null || !answer.getResult()) { s_logger.warn("Unable to send MaintainCommand to host: " + hostId); } try { - resourceStateTransitTo(host, - ResourceState.Event.AdminAskMaintenace, _nodeId); + resourceStateTransitTo(host, ResourceState.Event.AdminAskMaintenace, _nodeId); } catch (NoTransitionException e) { - String err = "Cannot transimit resource state of host " - + host.getId() + " to " + ResourceState.Maintenance; + String err = "Cannot transimit resource state of host " + host.getId() + " to " + ResourceState.Maintenance; s_logger.debug(err, e); throw new CloudRuntimeException(err + e.getMessage()); } _agentMgr.pullAgentToMaintenance(hostId); - /* TODO: move below to listener */ + /* TODO: move below to listener */ if (host.getType() == Host.Type.Routing) { final List vms = _vmDao.listByHostId(hostId); @@ -1415,9 +1268,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, return true; } - List hosts = listAllUpAndEnabledHosts(Host.Type.Routing, - host.getClusterId(), host.getPodId(), - host.getDataCenterId()); + List hosts = listAllUpAndEnabledHosts(Host.Type.Routing, host.getClusterId(), host.getPodId(), host.getDataCenterId()); for (final VMInstanceVO vm : vms) { if (hosts == null || hosts.isEmpty() || !answer.getMigrate()) { // for the last host in this cluster, stop all the VMs @@ -1433,8 +1284,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, @Override public boolean maintain(final long hostId) throws AgentUnavailableException { - Boolean result = _clusterMgr.propagateResourceEvent(hostId, - ResourceState.Event.AdminAskMaintenace); + Boolean result = _clusterMgr.propagateResourceEvent(hostId, ResourceState.Event.AdminAskMaintenace); if (result != null) { return result; } @@ -1449,39 +1299,29 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (host == null) { s_logger.debug("Unable to find host " + hostId); - throw new InvalidParameterValueException( - "Unable to find host with ID: " + hostId - + ". Please specify a valid host ID."); + throw new InvalidParameterValueException("Unable to find host with ID: " + hostId + ". Please specify a valid host ID."); } - if (_hostDao.countBy(host.getClusterId(), - ResourceState.PrepareForMaintenance, - ResourceState.ErrorInMaintenance) > 0) { - throw new InvalidParameterValueException( - "There are other servers in PrepareForMaintenance OR ErrorInMaintenance STATUS in cluster " - + host.getClusterId()); + if (_hostDao.countBy(host.getClusterId(), ResourceState.PrepareForMaintenance, ResourceState.ErrorInMaintenance) > 0) { + throw new InvalidParameterValueException("There are other servers in PrepareForMaintenance OR ErrorInMaintenance STATUS in cluster " + + host.getClusterId()); } if (_storageMgr.isLocalStorageActiveOnHost(host.getId())) { - throw new InvalidParameterValueException( - "There are active VMs using the host's local storage pool. Please stop all VMs on this host that use local storage."); + throw new InvalidParameterValueException( + "There are active VMs using the host's local storage pool. Please stop all VMs on this host that use local storage."); } try { - processResourceEvent( - ResourceListener.EVENT_PREPARE_MAINTENANCE_BEFORE, hostId); + processResourceEvent(ResourceListener.EVENT_PREPARE_MAINTENANCE_BEFORE, hostId); if (maintain(hostId)) { - processResourceEvent( - ResourceListener.EVENT_PREPARE_MAINTENANCE_AFTER, - hostId); + processResourceEvent(ResourceListener.EVENT_PREPARE_MAINTENANCE_AFTER, hostId); return _hostDao.findById(hostId); } else { - throw new CloudRuntimeException( - "Unable to prepare for maintenance host " + hostId); + throw new CloudRuntimeException("Unable to prepare for maintenance host " + hostId); } } catch (AgentUnavailableException e) { - throw new CloudRuntimeException( - "Unable to prepare for maintenance host " + hostId); + throw new CloudRuntimeException("Unable to prepare for maintenance host " + hostId); } } @@ -1493,18 +1333,13 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, // Verify that the host exists HostVO host = _hostDao.findById(hostId); if (host == null) { - throw new InvalidParameterValueException("Host with id " + hostId - + " doesn't exist"); + throw new InvalidParameterValueException("Host with id " + hostId + " doesn't exist"); } if (cmd.getAllocationState() != null) { - ResourceState.Event resourceEvent = ResourceState.Event.toEvent(cmd - .getAllocationState()); - if (resourceEvent != ResourceState.Event.Enable - && resourceEvent != ResourceState.Event.Disable) { - throw new CloudRuntimeException("Invalid allocation state:" - + cmd.getAllocationState() - + ", only Enable/Disable are allowed"); + ResourceState.Event resourceEvent = ResourceState.Event.toEvent(cmd.getAllocationState()); + if (resourceEvent != ResourceState.Event.Enable && resourceEvent != ResourceState.Event.Disable) { + throw new CloudRuntimeException("Invalid allocation state:" + cmd.getAllocationState() + ", only Enable/Disable are allowed"); } resourceStateTransitTo(host, resourceEvent, _nodeId); @@ -1514,22 +1349,16 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, // Verify that the guest OS Category exists if (guestOSCategoryId > 0) { if (_guestOSCategoryDao.findById(guestOSCategoryId) == null) { - throw new InvalidParameterValueException( - "Please specify a valid guest OS category."); + throw new InvalidParameterValueException("Please specify a valid guest OS category."); } } - GuestOSCategoryVO guestOSCategory = _guestOSCategoryDao - .findById(guestOSCategoryId); - Map hostDetails = _hostDetailsDao - .findDetails(hostId); + GuestOSCategoryVO guestOSCategory = _guestOSCategoryDao.findById(guestOSCategoryId); + Map hostDetails = _hostDetailsDao.findDetails(hostId); - if (guestOSCategory != null - && !GuestOSCategoryVO.CATEGORY_NONE - .equalsIgnoreCase(guestOSCategory.getName())) { + if (guestOSCategory != null && !GuestOSCategoryVO.CATEGORY_NONE.equalsIgnoreCase(guestOSCategory.getName())) { // Save a new entry for guest.os.category.id - hostDetails.put("guest.os.category.id", - String.valueOf(guestOSCategory.getId())); + hostDetails.put("guest.os.category.id", String.valueOf(guestOSCategory.getId())); } else { // Delete any existing entry for guest.os.category.id hostDetails.remove("guest.os.category.id"); @@ -1539,8 +1368,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, List hostTags = cmd.getHostTags(); if (hostTags != null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Updating Host Tags to :" + hostTags); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Updating Host Tags to :" + hostTags); } _hostTagsDao.persist(hostId, hostTags); } @@ -1560,16 +1389,13 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } @Override - public boolean configure(String name, Map params) - throws ConfigurationException { - _defaultSystemVMHypervisor = HypervisorType.getType(_configDao - .getValue(Config.SystemVMDefaultHypervisor.toString())); + public boolean configure(String name, Map params) throws ConfigurationException { + _defaultSystemVMHypervisor = HypervisorType.getType(_configDao.getValue(Config.SystemVMDefaultHypervisor.toString())); return true; } @Override - public List getSupportedHypervisorTypes(long zoneId, - boolean forVirtualRouter, Long podId) { + public List getSupportedHypervisorTypes(long zoneId, boolean forVirtualRouter, Long podId) { List hypervisorTypes = new ArrayList(); List clustersForZone = new ArrayList(); @@ -1581,8 +1407,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, for (ClusterVO cluster : clustersForZone) { HypervisorType hType = cluster.getHypervisorType(); - if (!forVirtualRouter - || (forVirtualRouter && hType != HypervisorType.BareMetal && hType != HypervisorType.Ovm)) { + if (!forVirtualRouter || (forVirtualRouter && hType != HypervisorType.BareMetal && hType != HypervisorType.Ovm)) { hypervisorTypes.add(hType); } } @@ -1602,14 +1427,12 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, return HypervisorType.None; } _dcDao.loadDetails(dc); - String defaultHypervisorInZone = dc - .getDetail("defaultSystemVMHypervisorType"); + String defaultHypervisorInZone = dc.getDetail("defaultSystemVMHypervisorType"); if (defaultHypervisorInZone != null) { defaultHyper = HypervisorType.getType(defaultHypervisorInZone); } - List systemTemplates = _templateDao - .listAllSystemVMTemplates(); + List systemTemplates = _templateDao.listAllSystemVMTemplates(); boolean isValid = false; for (VMTemplateVO template : systemTemplates) { if (template.getHypervisorType() == defaultHyper) { @@ -1619,8 +1442,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } if (isValid) { - List clusters = _clusterDao.listByDcHyType(zoneId, - defaultHyper.toString()); + List clusters = _clusterDao.listByDcHyType(zoneId, defaultHyper.toString()); if (clusters.size() <= 0) { isValid = false; } @@ -1637,8 +1459,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, public HypervisorType getAvailableHypervisor(long zoneId) { HypervisorType defaultHype = getDefaultHypervisor(zoneId); if (defaultHype == HypervisorType.None) { - List supportedHypes = getSupportedHypervisorTypes( - zoneId, false, null); + List supportedHypes = getSupportedHypervisorTypes(zoneId, false, null); if (supportedHypes.size() > 0) { defaultHype = supportedHypes.get(0); } @@ -1651,8 +1472,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } @Override - public void registerResourceStateAdapter(String name, - ResourceStateAdapter adapter) { + public void registerResourceStateAdapter(String name, ResourceStateAdapter adapter) { if (_resourceStateAdapters.get(name) != null) { throw new CloudRuntimeException(name + " has registered"); } @@ -1669,8 +1489,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } } - private Object dispatchToStateAdapters(ResourceStateAdapter.Event event, - boolean singleTaker, Object... args) { + private Object dispatchToStateAdapters(ResourceStateAdapter.Event event, boolean singleTaker, Object... args) { synchronized (_resourceStateAdapters) { Iterator> it = _resourceStateAdapters.entrySet().iterator(); Object result = null; @@ -1679,41 +1498,32 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, .next(); ResourceStateAdapter adapter = item.getValue(); - String msg = new String("Dispatching resource state event " - + event + " to " + item.getKey()); + String msg = new String("Dispatching resource state event " + event + " to " + item.getKey()); s_logger.debug(msg); if (event == ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_CONNECTED) { - result = adapter.createHostVOForConnectedAgent( - (HostVO) args[0], (StartupCommand[]) args[1]); + result = adapter.createHostVOForConnectedAgent((HostVO) args[0], (StartupCommand[]) args[1]); if (result != null && singleTaker) { break; } } else if (event == ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_DIRECT_CONNECT) { - result = adapter.createHostVOForDirectConnectAgent( - (HostVO) args[0], (StartupCommand[]) args[1], - (ServerResource) args[2], - (Map) args[3], - (List) args[4]); + result = adapter.createHostVOForDirectConnectAgent((HostVO) args[0], (StartupCommand[]) args[1], (ServerResource) args[2], + (Map) args[3], (List) args[4]); if (result != null && singleTaker) { break; } } else if (event == ResourceStateAdapter.Event.DELETE_HOST) { try { - result = adapter.deleteHost((HostVO) args[0], - (Boolean) args[1], (Boolean) args[2]); + result = adapter.deleteHost((HostVO) args[0], (Boolean) args[1], (Boolean) args[2]); if (result != null) { break; } } catch (UnableDeleteHostException e) { - s_logger.debug("Adapter " + adapter.getName() - + " says unable to delete host", e); - result = new ResourceStateAdapter.DeleteHostAnswer( - false, true); + s_logger.debug("Adapter " + adapter.getName() + " says unable to delete host", e); + result = new ResourceStateAdapter.DeleteHostAnswer(false, true); } } else { - throw new CloudRuntimeException( - "Unknown resource state event:" + event); + throw new CloudRuntimeException("Unknown resource state event:" + event); } } @@ -1722,9 +1532,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } @Override - public void checkCIDR(HostPodVO pod, DataCenterVO dc, - String serverPrivateIP, String serverPrivateNetmask) - throws IllegalArgumentException { + public void checkCIDR(HostPodVO pod, DataCenterVO dc, String serverPrivateIP, String serverPrivateNetmask) throws IllegalArgumentException { if (serverPrivateIP == null) { return; } @@ -1735,36 +1543,27 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, // If the server's private IP address is not in the same subnet as the // pod's CIDR, return false String cidrSubnet = NetUtils.getCidrSubNet(cidrAddress, cidrSize); - String serverSubnet = NetUtils.getSubNet(serverPrivateIP, - serverPrivateNetmask); + String serverSubnet = NetUtils.getSubNet(serverPrivateIP, serverPrivateNetmask); if (!cidrSubnet.equals(serverSubnet)) { - s_logger.warn("The private ip address of the server (" - + serverPrivateIP - + ") is not compatible with the CIDR of pod: " - + pod.getName() + " and zone: " + dc.getName()); - throw new IllegalArgumentException( - "The private ip address of the server (" + serverPrivateIP - + ") is not compatible with the CIDR of pod: " - + pod.getName() + " and zone: " + dc.getName()); + s_logger.warn("The private ip address of the server (" + serverPrivateIP + ") is not compatible with the CIDR of pod: " + pod.getName() + + " and zone: " + dc.getName()); + throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + + ") is not compatible with the CIDR of pod: " + pod.getName() + " and zone: " + dc.getName()); } // If the server's private netmask is less inclusive than the pod's CIDR // netmask, return false - String cidrNetmask = NetUtils - .getCidrSubNet("255.255.255.255", cidrSize); + String cidrNetmask = NetUtils.getCidrSubNet("255.255.255.255", cidrSize); long cidrNetmaskNumeric = NetUtils.ip2Long(cidrNetmask); long serverNetmaskNumeric = NetUtils.ip2Long(serverPrivateNetmask); if (serverNetmaskNumeric > cidrNetmaskNumeric) { - throw new IllegalArgumentException( - "The private ip address of the server (" + serverPrivateIP - + ") is not compatible with the CIDR of pod: " - + pod.getName() + " and zone: " + dc.getName()); + throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + + ") is not compatible with the CIDR of pod: " + pod.getName() + " and zone: " + dc.getName()); } } - private boolean checkCIDR(HostPodVO pod, String serverPrivateIP, - String serverPrivateNetmask) { + private boolean checkCIDR(HostPodVO pod, String serverPrivateIP, String serverPrivateNetmask) { if (serverPrivateIP == null) { return true; } @@ -1775,16 +1574,14 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, // If the server's private IP address is not in the same subnet as the // pod's CIDR, return false String cidrSubnet = NetUtils.getCidrSubNet(cidrAddress, cidrSize); - String serverSubnet = NetUtils.getSubNet(serverPrivateIP, - serverPrivateNetmask); + String serverSubnet = NetUtils.getSubNet(serverPrivateIP, serverPrivateNetmask); if (!cidrSubnet.equals(serverSubnet)) { return false; } // If the server's private netmask is less inclusive than the pod's CIDR // netmask, return false - String cidrNetmask = NetUtils - .getCidrSubNet("255.255.255.255", cidrSize); + String cidrNetmask = NetUtils.getCidrSubNet("255.255.255.255", cidrSize); long cidrNetmaskNumeric = NetUtils.ip2Long(cidrNetmask); long serverNetmaskNumeric = NetUtils.ip2Long(serverPrivateNetmask); if (serverNetmaskNumeric > cidrNetmaskNumeric) { @@ -1793,9 +1590,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, return true; } - protected HostVO createHostVO(StartupCommand[] cmds, - ServerResource resource, Map details, - List hostTags, ResourceStateAdapter.Event stateEvent) { + protected HostVO createHostVO(StartupCommand[] cmds, ServerResource resource, Map details, List hostTags, + ResourceStateAdapter.Event stateEvent) { StartupCommand startup = cmds[0]; HostVO host = findHostByGuid(startup.getGuid()); boolean isNew = false; @@ -1811,16 +1607,12 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, String pod = startup.getPod(); String cluster = startup.getCluster(); - if (pod != null && dataCenter != null - && pod.equalsIgnoreCase("default") - && dataCenter.equalsIgnoreCase("default")) { + if (pod != null && dataCenter != null && pod.equalsIgnoreCase("default") && dataCenter.equalsIgnoreCase("default")) { List pods = _podDao.listAllIncludingRemoved(); for (HostPodVO hpv : pods) { - if (checkCIDR(hpv, startup.getPrivateIpAddress(), - startup.getPrivateNetmask())) { + if (checkCIDR(hpv, startup.getPrivateIpAddress(), startup.getPrivateNetmask())) { pod = hpv.getName(); - dataCenter = _dcDao.findById(hpv.getDataCenterId()) - .getName(); + dataCenter = _dcDao.findById(hpv.getDataCenterId()).getName(); break; } } @@ -1836,9 +1628,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } } if (dc == null) { - throw new IllegalArgumentException("Host " - + startup.getPrivateIpAddress() - + " sent incorrect data center: " + dataCenter); + throw new IllegalArgumentException("Host " + startup.getPrivateIpAddress() + " sent incorrect data center: " + dataCenter); } dcId = dc.getId(); @@ -1900,11 +1690,9 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, host.setResource(resource.getClass().getName()); } - host = (HostVO) dispatchToStateAdapters(stateEvent, true, host, cmds, - resource, details, hostTags); + host = (HostVO) dispatchToStateAdapters(stateEvent, true, host, cmds, resource, details, hostTags); if (host == null) { - throw new CloudRuntimeException( - "No resource state adapter response"); + throw new CloudRuntimeException("No resource state adapter response"); } if (isNew) { @@ -1914,28 +1702,23 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } try { - resourceStateTransitTo(host, ResourceState.Event.InternalCreated, - _nodeId); + resourceStateTransitTo(host, ResourceState.Event.InternalCreated, _nodeId); /* Agent goes to Connecting status */ - _agentMgr.agentStatusTransitTo(host, Status.Event.AgentConnected, - _nodeId); + _agentMgr.agentStatusTransitTo(host, Status.Event.AgentConnected, _nodeId); } catch (Exception e) { - s_logger.debug("Cannot transmit host " + host.getId() - + " to Creating state", e); + s_logger.debug("Cannot transmit host " + host.getId() + " to Creating state", e); _agentMgr.agentStatusTransitTo(host, Status.Event.Error, _nodeId); try { resourceStateTransitTo(host, ResourceState.Event.Error, _nodeId); } catch (NoTransitionException e1) { - s_logger.debug("Cannot transmit host " + host.getId() - + "to Error state", e); + s_logger.debug("Cannot transmit host " + host.getId() + "to Error state", e); } } return host; } - private boolean isFirstHostInCluster(HostVO host) - { + private boolean isFirstHostInCluster(HostVO host) { boolean isFirstHost = true; if (host.getClusterId() != null) { SearchBuilder sb = _hostDao.createSearchBuilder(); @@ -1954,7 +1737,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } private void markHostAsDisconnected(HostVO host, StartupCommand[] cmds) { - if (host == null) { // in case host is null due to some errors, try reloading the host from db + if (host == null) { // in case host is null due to some errors, try + // reloading the host from db if (cmds != null) { StartupCommand firstCmd = cmds[0]; host = findHostByGuid(firstCmd.getGuid()); @@ -1965,13 +1749,13 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } if (host != null) { - // Change agent status to Alert, so that host is considered for reconnection next time + // Change agent status to Alert, so that host is considered for + // reconnection next time _agentMgr.agentStatusTransitTo(host, Status.Event.AgentDisconnected, _nodeId); } } - private Host createHostAndAgent(ServerResource resource, Map details, boolean old, List hostTags, - boolean forRebalance) { + private Host createHostAndAgent(ServerResource resource, Map details, boolean old, List hostTags, boolean forRebalance) { HostVO host = null; AgentAttache attache = null; StartupCommand[] cmds = null; @@ -1985,17 +1769,16 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } /* Generate a random version in a dev setup situation */ - if (this.getClass().getPackage().getImplementationVersion() == null) { - for (StartupCommand cmd : cmds) { - if (cmd.getVersion() == null) { + if (this.getClass().getPackage().getImplementationVersion() == null) { + for (StartupCommand cmd : cmds) { + if (cmd.getVersion() == null) { cmd.setVersion(Long.toString(System.currentTimeMillis())); } } } if (s_logger.isDebugEnabled()) { - new Request(-1l, -1l, cmds, true, false).logD( - "Startup request from directly connected host: ", true); + new Request(-1l, -1l, cmds, true, false).logD("Startup request from directly connected host: ", true); } if (old) { @@ -2004,22 +1787,21 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (host == null) { host = findHostByGuid(firstCmd.getGuidWithoutResource()); } - if (host != null && host.getRemoved() == null) { // host already added, no need to add again + if (host != null && host.getRemoved() == null) { // host already + // added, no + // need to add + // again s_logger.debug("Found the host " + host.getId() + " by guid: " + firstCmd.getGuid() + ", old host reconnected as new"); - hostExists = true; // ensures that host status is left unchanged in case of adding same one again + hostExists = true; // ensures that host status is left + // unchanged in case of adding same one + // again return null; } } - host = createHostVO( - cmds, - resource, - details, - hostTags, - ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_DIRECT_CONNECT); + host = createHostVO(cmds, resource, details, hostTags, ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_DIRECT_CONNECT); if (host != null) { - attache = _agentMgr.handleDirectConnectAgent(host, cmds, - resource, forRebalance); + attache = _agentMgr.handleDirectConnectAgent(host, cmds, resource, forRebalance); /* reload myself from database */ host = _hostDao.findById(host.getId()); } @@ -2059,9 +1841,9 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } /* Generate a random version in a dev setup situation */ - if ( this.getClass().getPackage().getImplementationVersion() == null ) { - for ( StartupCommand cmd : cmds ) { - if ( cmd.getVersion() == null ) { + if (this.getClass().getPackage().getImplementationVersion() == null) { + for (StartupCommand cmd : cmds) { + if (cmd.getVersion() == null) { cmd.setVersion(Long.toString(System.currentTimeMillis())); } } @@ -2077,9 +1859,14 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (host == null) { host = findHostByGuid(firstCmd.getGuidWithoutResource()); } - if (host != null && host.getRemoved() == null) { // host already added, no need to add again + if (host != null && host.getRemoved() == null) { // host already + // added, no + // need to add + // again s_logger.debug("Found the host " + host.getId() + " by guid: " + firstCmd.getGuid() + ", old host reconnected as new"); - hostExists = true; // ensures that host status is left unchanged in case of adding same one again + hostExists = true; // ensures that host status is left + // unchanged in case of adding same one + // again return null; } } @@ -2087,11 +1874,30 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, host = null; GlobalLock addHostLock = GlobalLock.getInternLock("AddHostLock"); try { - if (addHostLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) { // to safely determine first host in cluster in multi-MS scenario + if (addHostLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) { // to + // safely + // determine + // first + // host + // in + // cluster + // in + // multi-MS + // scenario try { host = createHostVO(cmds, resource, details, hostTags, ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_DIRECT_CONNECT); if (host != null) { - deferAgentCreation = !isFirstHostInCluster(host); // if first host in cluster no need to defer agent creation + deferAgentCreation = !isFirstHostInCluster(host); // if + // first + // host + // in + // cluster + // no + // need + // to + // defer + // agent + // creation } } finally { addHostLock.unlock(); @@ -2102,12 +1908,15 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } if (host != null) { - if (!deferAgentCreation) { // if first host in cluster then create agent otherwise defer it to scan task + if (!deferAgentCreation) { // if first host in cluster then + // create agent otherwise defer it to + // scan task attache = _agentMgr.handleDirectConnectAgent(host, cmds, resource, forRebalance); host = _hostDao.findById(host.getId()); // reload } else { host = _hostDao.findById(host.getId()); // reload - // force host status to 'Alert' so that it is loaded for connection during next scan task + // force host status to 'Alert' so that it is loaded for + // connection during next scan task _agentMgr.agentStatusTransitTo(host, Status.Event.AgentDisconnected, _nodeId); host = _hostDao.findById(host.getId()); // reload @@ -2116,7 +1925,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, // schedule a scan task immediately if (_agentMgr instanceof ClusteredAgentManagerImpl) { - ClusteredAgentManagerImpl clusteredAgentMgr = (ClusteredAgentManagerImpl)_agentMgr; + ClusteredAgentManagerImpl clusteredAgentMgr = (ClusteredAgentManagerImpl) _agentMgr; if (s_logger.isDebugEnabled()) { s_logger.debug("Scheduling a host scan task"); } @@ -2151,29 +1960,24 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } @Override - public Host createHostAndAgent(Long hostId, ServerResource resource, - Map details, boolean old, List hostTags, - boolean forRebalance) { + public Host createHostAndAgent(Long hostId, ServerResource resource, Map details, boolean old, List hostTags, + boolean forRebalance) { _agentMgr.tapLoadingAgents(hostId, TapAgentsAction.Add); - Host host = createHostAndAgent(resource, details, old, hostTags, - forRebalance); + Host host = createHostAndAgent(resource, details, old, hostTags, forRebalance); _agentMgr.tapLoadingAgents(hostId, TapAgentsAction.Del); return host; } @Override - public Host addHost(long zoneId, ServerResource resource, Type hostType, - Map hostDetails) { + public Host addHost(long zoneId, ServerResource resource, Type hostType, Map hostDetails) { // Check if the zone exists in the system if (_dcDao.findById(zoneId) == null) { - throw new InvalidParameterValueException("Can't find zone with id " - + zoneId); + throw new InvalidParameterValueException("Can't find zone with id " + zoneId); } Map details = hostDetails; String guid = details.get("guid"); - List currentHosts = this - .listAllUpAndEnabledHostsInOneZoneByType(hostType, zoneId); + List currentHosts = this.listAllUpAndEnabledHostsInOneZoneByType(hostType, zoneId); for (HostVO currentHost : currentHosts) { if (currentHost.getGuid().equals(guid)) { return currentHost; @@ -2185,85 +1989,59 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, @Override public HostVO createHostVOForConnectedAgent(StartupCommand[] cmds) { - return createHostVO(cmds, null, null, null, - ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_CONNECTED); + return createHostVO(cmds, null, null, null, ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_CONNECTED); } - private void checkIPConflicts(HostPodVO pod, DataCenterVO dc, - String serverPrivateIP, String serverPrivateNetmask, - String serverPublicIP, String serverPublicNetmask) { + private void checkIPConflicts(HostPodVO pod, DataCenterVO dc, String serverPrivateIP, String serverPrivateNetmask, String serverPublicIP, + String serverPublicNetmask) { // If the server's private IP is the same as is public IP, this host has // a host-only private network. Don't check for conflicts with the // private IP address table. if (serverPrivateIP != serverPublicIP) { - if (!_privateIPAddressDao.mark(dc.getId(), pod.getId(), - serverPrivateIP)) { + if (!_privateIPAddressDao.mark(dc.getId(), pod.getId(), serverPrivateIP)) { // If the server's private IP address is already in the // database, return false - List existingPrivateIPs = _privateIPAddressDao - .listByPodIdDcIdIpAddress(pod.getId(), dc.getId(), - serverPrivateIP); + List existingPrivateIPs = _privateIPAddressDao.listByPodIdDcIdIpAddress(pod.getId(), dc.getId(), + serverPrivateIP); - assert existingPrivateIPs.size() <= 1 : " How can we get more than one ip address with " - + serverPrivateIP; + assert existingPrivateIPs.size() <= 1 : " How can we get more than one ip address with " + serverPrivateIP; if (existingPrivateIPs.size() > 1) { - throw new IllegalArgumentException( - "The private ip address of the server (" - + serverPrivateIP - + ") is already in use in pod: " - + pod.getName() + " and zone: " - + dc.getName()); + throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + ") is already in use in pod: " + + pod.getName() + " and zone: " + dc.getName()); } if (existingPrivateIPs.size() == 1) { DataCenterIpAddressVO vo = existingPrivateIPs.get(0); if (vo.getInstanceId() != null) { - throw new IllegalArgumentException( - "The private ip address of the server (" - + serverPrivateIP - + ") is already in use in pod: " - + pod.getName() + " and zone: " - + dc.getName()); + throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + + ") is already in use in pod: " + pod.getName() + " and zone: " + dc.getName()); } } } } - if (serverPublicIP != null - && !_publicIPAddressDao - .mark(dc.getId(), new Ip(serverPublicIP))) { + if (serverPublicIP != null && !_publicIPAddressDao.mark(dc.getId(), new Ip(serverPublicIP))) { // If the server's public IP address is already in the database, // return false - List existingPublicIPs = _publicIPAddressDao - .listByDcIdIpAddress(dc.getId(), serverPublicIP); + List existingPublicIPs = _publicIPAddressDao.listByDcIdIpAddress(dc.getId(), serverPublicIP); if (existingPublicIPs.size() > 0) { - throw new IllegalArgumentException( - "The public ip address of the server (" - + serverPublicIP - + ") is already in use in zone: " - + dc.getName()); + throw new IllegalArgumentException("The public ip address of the server (" + serverPublicIP + ") is already in use in zone: " + + dc.getName()); } } } @Override - public HostVO fillRoutingHostVO(HostVO host, StartupRoutingCommand ssCmd, - HypervisorType hyType, Map details, - List hostTags) { + public HostVO fillRoutingHostVO(HostVO host, StartupRoutingCommand ssCmd, HypervisorType hyType, Map details, + List hostTags) { if (host.getPodId() == null) { - s_logger.error("Host " + ssCmd.getPrivateIpAddress() - + " sent incorrect pod, pod id is null"); - throw new IllegalArgumentException("Host " - + ssCmd.getPrivateIpAddress() - + " sent incorrect pod, pod id is null"); + s_logger.error("Host " + ssCmd.getPrivateIpAddress() + " sent incorrect pod, pod id is null"); + throw new IllegalArgumentException("Host " + ssCmd.getPrivateIpAddress() + " sent incorrect pod, pod id is null"); } ClusterVO clusterVO = _clusterDao.findById(host.getClusterId()); if (clusterVO.getHypervisorType() != hyType) { - throw new IllegalArgumentException( - "Can't add host whose hypervisor type is: " + hyType - + " into cluster: " + clusterVO.getId() - + " whose hypervisor type is: " - + clusterVO.getHypervisorType()); + throw new IllegalArgumentException("Can't add host whose hypervisor type is: " + hyType + " into cluster: " + clusterVO.getId() + + " whose hypervisor type is: " + clusterVO.getHypervisorType()); } final Map hostDetails = ssCmd.getHostDetails(); @@ -2277,9 +2055,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, HostPodVO pod = _podDao.findById(host.getPodId()); DataCenterVO dc = _dcDao.findById(host.getDataCenterId()); - checkIPConflicts(pod, dc, ssCmd.getPrivateIpAddress(), - ssCmd.getPublicIpAddress(), ssCmd.getPublicIpAddress(), - ssCmd.getPublicNetmask()); + checkIPConflicts(pod, dc, ssCmd.getPrivateIpAddress(), ssCmd.getPublicIpAddress(), ssCmd.getPublicIpAddress(), ssCmd.getPublicNetmask()); host.setType(com.cloud.host.Host.Type.Routing); host.setDetails(details); host.setCaps(ssCmd.getCapabilities()); @@ -2292,69 +2068,48 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } @Override - public void deleteRoutingHost(HostVO host, boolean isForced, - boolean forceDestroyStorage) throws UnableDeleteHostException { + public void deleteRoutingHost(HostVO host, boolean isForced, boolean forceDestroyStorage) throws UnableDeleteHostException { if (host.getType() != Host.Type.Routing) { - throw new CloudRuntimeException( - "Non-Routing host gets in deleteRoutingHost, id is " - + host.getId()); + throw new CloudRuntimeException("Non-Routing host gets in deleteRoutingHost, id is " + host.getId()); } if (s_logger.isDebugEnabled()) { - s_logger.debug("Deleting Host: " + host.getId() + " Guid:" - + host.getGuid()); + s_logger.debug("Deleting Host: " + host.getId() + " Guid:" + host.getGuid()); } - User caller = _accountMgr.getActiveUser(UserContext.current() - .getCallerUserId()); + User caller = _accountMgr.getActiveUser(UserContext.current().getCallerUserId()); - if (forceDestroyStorage) { - // put local storage into mainenance mode, will set all the VMs on - // this local storage into stopped state - StoragePoolVO storagePool = _storageMgr.findLocalStorageOnHost(host - .getId()); + if (forceDestroyStorage) { + // put local storage into mainenance mode, will set all the VMs on + // this local storage into stopped state + StoragePoolVO storagePool = _storageMgr.findLocalStorageOnHost(host.getId()); if (storagePool != null) { - if (storagePool.getStatus() == StoragePoolStatus.Up - || storagePool.getStatus() == StoragePoolStatus.ErrorInMaintenance) { - try { - StoragePool pool = _storageSvr - .preparePrimaryStorageForMaintenance(storagePool - .getId()); - if (pool == null) { - s_logger.debug("Failed to set primary storage into maintenance mode"); + if (storagePool.getStatus() == StoragePoolStatus.Up || storagePool.getStatus() == StoragePoolStatus.ErrorInMaintenance) { + try { + StoragePool pool = _storageSvr.preparePrimaryStorageForMaintenance(storagePool.getId()); + if (pool == null) { + s_logger.debug("Failed to set primary storage into maintenance mode"); - throw new UnableDeleteHostException( - "Failed to set primary storage into maintenance mode"); + throw new UnableDeleteHostException("Failed to set primary storage into maintenance mode"); } } catch (Exception e) { - s_logger.debug("Failed to set primary storage into maintenance mode, due to: " - + e.toString()); - throw new UnableDeleteHostException( - "Failed to set primary storage into maintenance mode, due to: " - + e.toString()); + s_logger.debug("Failed to set primary storage into maintenance mode, due to: " + e.toString()); + throw new UnableDeleteHostException("Failed to set primary storage into maintenance mode, due to: " + e.toString()); } } - List vmsOnLocalStorage = _storageMgr - .listByStoragePool(storagePool.getId()); + List vmsOnLocalStorage = _storageMgr.listByStoragePool(storagePool.getId()); for (VMInstanceVO vm : vmsOnLocalStorage) { try { - if (!_vmMgr.destroy(vm, caller, - _accountMgr.getAccount(vm.getAccountId()))) { - String errorMsg = "There was an error Destory the vm: " - + vm - + " as a part of hostDelete id=" - + host.getId(); + if (!_vmMgr.destroy(vm, caller, _accountMgr.getAccount(vm.getAccountId()))) { + String errorMsg = "There was an error Destory the vm: " + vm + " as a part of hostDelete id=" + host.getId(); s_logger.warn(errorMsg); throw new UnableDeleteHostException(errorMsg); } } catch (Exception e) { - String errorMsg = "There was an error Destory the vm: " - + vm + " as a part of hostDelete id=" - + host.getId(); + String errorMsg = "There was an error Destory the vm: " + vm + " as a part of hostDelete id=" + host.getId(); s_logger.debug(errorMsg, e); - throw new UnableDeleteHostException(errorMsg + "," - + e.getMessage()); + throw new UnableDeleteHostException(errorMsg + "," + e.getMessage()); } } } @@ -2366,45 +2121,26 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, // Stop HA disabled vms and HA enabled vms in Stopping state // Restart HA enabled vms for (VMInstanceVO vm : vms) { - if (!vm.isHaEnabled() - || vm.getState() == State.Stopping) { - s_logger.debug("Stopping vm: " + vm - + " as a part of deleteHost id=" - + host.getId()); + if (!vm.isHaEnabled() || vm.getState() == State.Stopping) { + s_logger.debug("Stopping vm: " + vm + " as a part of deleteHost id=" + host.getId()); try { - if (!_vmMgr.advanceStop(vm, true, caller, - _accountMgr.getAccount(vm - .getAccountId()))) { - String errorMsg = "There was an error stopping the vm: " - + vm - + " as a part of hostDelete id=" - + host.getId(); + if (!_vmMgr.advanceStop(vm, true, caller, _accountMgr.getAccount(vm.getAccountId()))) { + String errorMsg = "There was an error stopping the vm: " + vm + " as a part of hostDelete id=" + host.getId(); s_logger.warn(errorMsg); - throw new UnableDeleteHostException( - errorMsg); + throw new UnableDeleteHostException(errorMsg); } } catch (Exception e) { - String errorMsg = "There was an error stopping the vm: " - + vm - + " as a part of hostDelete id=" - + host.getId(); + String errorMsg = "There was an error stopping the vm: " + vm + " as a part of hostDelete id=" + host.getId(); s_logger.debug(errorMsg, e); - throw new UnableDeleteHostException(errorMsg - + "," + e.getMessage()); - } - } else if (vm.isHaEnabled() - && (vm.getState() == State.Running || vm - .getState() == State.Starting)) { - s_logger.debug("Scheduling restart for vm: " + vm - + " " + vm.getState() + " on the host id=" - + host.getId()); + throw new UnableDeleteHostException(errorMsg + "," + e.getMessage()); + } + } else if (vm.isHaEnabled() && (vm.getState() == State.Running || vm.getState() == State.Starting)) { + s_logger.debug("Scheduling restart for vm: " + vm + " " + vm.getState() + " on the host id=" + host.getId()); _haMgr.scheduleRestart(vm, false); } } } else { - throw new UnableDeleteHostException( - "Unable to delete the host as there are vms in " - + vms.get(0).getState() + throw new UnableDeleteHostException("Unable to delete the host as there are vms in " + vms.get(0).getState() + " state using this host and isForced=false specified"); } } @@ -2419,35 +2155,31 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, return true; } - /* - * TODO: think twice about returning true or throwing out exception, I - * really prefer to exception that always exposes bugs - */ - if (host.getResourceState() != ResourceState.PrepareForMaintenance - && host.getResourceState() != ResourceState.Maintenance - && host.getResourceState() != ResourceState.ErrorInMaintenance) { - throw new CloudRuntimeException( - "Cannot perform cancelMaintenance when resource state is " - + host.getResourceState() + ", hostId = " + hostId); + /* + * TODO: think twice about returning true or throwing out exception, I + * really prefer to exception that always exposes bugs + */ + if (host.getResourceState() != ResourceState.PrepareForMaintenance && host.getResourceState() != ResourceState.Maintenance + && host.getResourceState() != ResourceState.ErrorInMaintenance) { + throw new CloudRuntimeException("Cannot perform cancelMaintenance when resource state is " + host.getResourceState() + ", hostId = " + + hostId); } - /* TODO: move to listener */ + /* TODO: move to listener */ _haMgr.cancelScheduledMigrations(host); List vms = _haMgr.findTakenMigrationWork(); for (VMInstanceVO vm : vms) { if (vm.getHostId() != null && vm.getHostId() == hostId) { - s_logger.info("Unable to cancel migration because the vm is being migrated: " - + vm); + s_logger.info("Unable to cancel migration because the vm is being migrated: " + vm); return false; } } try { - resourceStateTransitTo(host, - ResourceState.Event.AdminCancelMaintenance, _nodeId); + resourceStateTransitTo(host, ResourceState.Event.AdminCancelMaintenance, _nodeId); _agentMgr.pullAgentOutMaintenance(hostId); - // for kvm, need to log into kvm host, restart cloudstack-agent + // for kvm, need to log into kvm host, restart cloudstack-agent if (host.getHypervisorType() == HypervisorType.KVM) { _hostDao.loadDetails(host); String password = host.getDetail("password"); @@ -2456,19 +2188,14 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, s_logger.debug("Can't find password/username"); return false; } - com.trilead.ssh2.Connection connection = SSHCmdHelper - .acquireAuthorizedConnection( - host.getPrivateIpAddress(), 22, username, - password); + com.trilead.ssh2.Connection connection = SSHCmdHelper.acquireAuthorizedConnection(host.getPrivateIpAddress(), 22, username, password); if (connection == null) { - s_logger.debug("Failed to connect to host: " - + host.getPrivateIpAddress()); + s_logger.debug("Failed to connect to host: " + host.getPrivateIpAddress()); return false; } try { - SSHCmdHelper.sshExecuteCmdOneShot(connection, - "service cloudstack-agent restart"); + SSHCmdHelper.sshExecuteCmdOneShot(connection, "service cloudstack-agent restart"); } catch (sshException e) { return false; } @@ -2476,16 +2203,14 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, return true; } catch (NoTransitionException e) { - s_logger.debug("Cannot transmit host " + host.getId() - + "to Enabled state", e); + s_logger.debug("Cannot transmit host " + host.getId() + "to Enabled state", e); return false; } } private boolean cancelMaintenance(long hostId) { try { - Boolean result = _clusterMgr.propagateResourceEvent(hostId, - ResourceState.Event.AdminCancelMaintenance); + Boolean result = _clusterMgr.propagateResourceEvent(hostId, ResourceState.Event.AdminCancelMaintenance); if (result != null) { return result; @@ -2498,49 +2223,42 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } @Override - public boolean executeUserRequest(long hostId, ResourceState.Event event) - throws AgentUnavailableException { + public boolean executeUserRequest(long hostId, ResourceState.Event event) throws AgentUnavailableException { if (event == ResourceState.Event.AdminAskMaintenace) { return doMaintain(hostId); } else if (event == ResourceState.Event.AdminCancelMaintenance) { return doCancelMaintenance(hostId); } else if (event == ResourceState.Event.DeleteHost) { - /* TODO: Ask alex why we assume the last two parameters are false */ + /* TODO: Ask alex why we assume the last two parameters are false */ return doDeleteHost(hostId, false, false); } else if (event == ResourceState.Event.Unmanaged) { return doUmanageHost(hostId); } else if (event == ResourceState.Event.UpdatePassword) { return doUpdateHostPassword(hostId); } else { - throw new CloudRuntimeException( - "Received an resource event we are not handling now, " - + event); + throw new CloudRuntimeException("Received an resource event we are not handling now, " + event); } } private boolean doUmanageHost(long hostId) { HostVO host = _hostDao.findById(hostId); if (host == null) { - s_logger.debug("Cannot find host " + hostId - + ", assuming it has been deleted, skip umanage"); + s_logger.debug("Cannot find host " + hostId + ", assuming it has been deleted, skip umanage"); return true; } if (host.getHypervisorType() == HypervisorType.KVM) { - MaintainAnswer answer = (MaintainAnswer) _agentMgr.easySend(hostId, - new MaintainCommand()); + MaintainAnswer answer = (MaintainAnswer) _agentMgr.easySend(hostId, new MaintainCommand()); } - _agentMgr.disconnectWithoutInvestigation(hostId, - Event.ShutdownRequested); + _agentMgr.disconnectWithoutInvestigation(hostId, Event.ShutdownRequested); return true; } @Override public boolean umanageHost(long hostId) { try { - Boolean result = _clusterMgr.propagateResourceEvent(hostId, - ResourceState.Event.Unmanaged); + Boolean result = _clusterMgr.propagateResourceEvent(hostId, ResourceState.Event.Unmanaged); if (result != null) { return result; @@ -2562,8 +2280,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, String username = nv.getValue(); nv = _hostDetailsDao.findDetail(hostId, ApiConstants.PASSWORD); String password = nv.getValue(); - UpdateHostPasswordCommand cmd = new UpdateHostPasswordCommand(username, - password); + UpdateHostPasswordCommand cmd = new UpdateHostPasswordCommand(username, password); attache.updatePassword(cmd); return true; } @@ -2573,8 +2290,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (cmd.getClusterId() == null) { // update agent attache password try { - Boolean result = _clusterMgr.propagateResourceEvent( - cmd.getHostId(), ResourceState.Event.UpdatePassword); + Boolean result = _clusterMgr.propagateResourceEvent(cmd.getHostId(), ResourceState.Event.UpdatePassword); if (result != null) { return result; } @@ -2587,12 +2303,11 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, List hosts = this.listAllHostsInCluster(cmd.getClusterId()); for (HostVO h : hosts) { try { - /* - * FIXME: this is a buggy logic, check with alex. Shouldn't - * return if propagation return non null - */ - Boolean result = _clusterMgr.propagateResourceEvent( - h.getId(), ResourceState.Event.UpdatePassword); + /* + * FIXME: this is a buggy logic, check with alex. Shouldn't + * return if propagation return non null + */ + Boolean result = _clusterMgr.propagateResourceEvent(h.getId(), ResourceState.Event.UpdatePassword); if (result != null) { return result; } @@ -2616,14 +2331,10 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, return false; } else { try { - return resourceStateTransitTo(host, - ResourceState.Event.UnableToMigrate, _nodeId); + return resourceStateTransitTo(host, ResourceState.Event.UnableToMigrate, _nodeId); } catch (NoTransitionException e) { - s_logger.debug( - "No next resource state for host " + host.getId() - + " while current state is " - + host.getResourceState() + " with event " - + ResourceState.Event.UnableToMigrate, e); + s_logger.debug("No next resource state for host " + host.getId() + " while current state is " + host.getResourceState() + + " with event " + ResourceState.Event.UnableToMigrate, e); return false; } } @@ -2632,19 +2343,15 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, @Override public List findDirectlyConnectedHosts() { /* The resource column is not null for direct connected resource */ - SearchCriteriaService sc = SearchCriteria2 - .create(HostVO.class); + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); sc.addAnd(sc.getEntity().getResource(), Op.NNULL); - sc.addAnd(sc.getEntity().getResourceState(), Op.NIN, - ResourceState.Disabled); + sc.addAnd(sc.getEntity().getResourceState(), Op.NIN, ResourceState.Disabled); return sc.list(); } @Override - public List listAllUpAndEnabledHosts(Type type, Long clusterId, - Long podId, long dcId) { - SearchCriteriaService sc = SearchCriteria2 - .create(HostVO.class); + public List listAllUpAndEnabledHosts(Type type, Long clusterId, Long podId, long dcId) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); if (type != null) { sc.addAnd(sc.getEntity().getType(), Op.EQ, type); } @@ -2656,23 +2363,19 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId); sc.addAnd(sc.getEntity().getStatus(), Op.EQ, Status.Up); - sc.addAnd(sc.getEntity().getResourceState(), Op.EQ, - ResourceState.Enabled); + sc.addAnd(sc.getEntity().getResourceState(), Op.EQ, ResourceState.Enabled); return sc.list(); } @Override - public List listAllUpAndEnabledNonHAHosts(Type type, - Long clusterId, Long podId, long dcId) { + public List listAllUpAndEnabledNonHAHosts(Type type, Long clusterId, Long podId, long dcId) { String haTag = _haMgr.getHaTag(); - return _hostDao.listAllUpAndEnabledNonHAHosts(type, clusterId, podId, - dcId, haTag); + return _hostDao.listAllUpAndEnabledNonHAHosts(type, clusterId, podId, dcId, haTag); } @Override public List findHostByGuid(long dcId, String guid) { - SearchCriteriaService sc = SearchCriteria2 - .create(HostVO.class); + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId); sc.addAnd(sc.getEntity().getGuid(), Op.EQ, guid); return sc.list(); @@ -2680,53 +2383,44 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, @Override public List listAllHostsInCluster(long clusterId) { - SearchCriteriaService sc = SearchCriteria2 - .create(HostVO.class); + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); sc.addAnd(sc.getEntity().getClusterId(), Op.EQ, clusterId); return sc.list(); } @Override public List listHostsInClusterByStatus(long clusterId, Status status) { - SearchCriteriaService sc = SearchCriteria2 - .create(HostVO.class); + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); sc.addAnd(sc.getEntity().getClusterId(), Op.EQ, clusterId); sc.addAnd(sc.getEntity().getStatus(), Op.EQ, status); return sc.list(); } @Override - public List listAllUpAndEnabledHostsInOneZoneByType(Type type, - long dcId) { - SearchCriteriaService sc = SearchCriteria2 - .create(HostVO.class); + public List listAllUpAndEnabledHostsInOneZoneByType(Type type, long dcId) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); sc.addAnd(sc.getEntity().getType(), Op.EQ, type); sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId); sc.addAnd(sc.getEntity().getStatus(), Op.EQ, Status.Up); - sc.addAnd(sc.getEntity().getResourceState(), Op.EQ, - ResourceState.Enabled); + sc.addAnd(sc.getEntity().getResourceState(), Op.EQ, ResourceState.Enabled); return sc.list(); } @Override - public List listAllNotInMaintenanceHostsInOneZone(Type type, - Long dcId) { - SearchCriteriaService sc = SearchCriteria2 - .create(HostVO.class); - if (dcId != null) { + public List listAllNotInMaintenanceHostsInOneZone(Type type, Long dcId) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + if (dcId != null) { sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId); } sc.addAnd(sc.getEntity().getType(), Op.EQ, type); - sc.addAnd(sc.getEntity().getResourceState(), Op.NIN, - ResourceState.Maintenance, ResourceState.ErrorInMaintenance, - ResourceState.PrepareForMaintenance, ResourceState.Error); + sc.addAnd(sc.getEntity().getResourceState(), Op.NIN, ResourceState.Maintenance, ResourceState.ErrorInMaintenance, + ResourceState.PrepareForMaintenance, ResourceState.Error); return sc.list(); } @Override public List listAllHostsInOneZoneByType(Type type, long dcId) { - SearchCriteriaService sc = SearchCriteria2 - .create(HostVO.class); + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); sc.addAnd(sc.getEntity().getType(), Op.EQ, type); sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId); return sc.list(); @@ -2734,17 +2428,14 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, @Override public List listAllHostsInAllZonesByType(Type type) { - SearchCriteriaService sc = SearchCriteria2 - .create(HostVO.class); + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); sc.addAnd(sc.getEntity().getType(), Op.EQ, type); return sc.list(); } @Override - public List listAvailHypervisorInZone(Long hostId, - Long zoneId) { - SearchCriteriaService sc = SearchCriteria2 - .create(HostVO.class); + public List listAvailHypervisorInZone(Long hostId, Long zoneId) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); if (zoneId != null) { sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, zoneId); } @@ -2763,35 +2454,30 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, @Override public HostVO findHostByGuid(String guid) { - SearchCriteriaService sc = SearchCriteria2 - .create(HostVO.class); + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); sc.addAnd(sc.getEntity().getGuid(), Op.EQ, guid); return sc.find(); } @Override public HostVO findHostByName(String name) { - SearchCriteriaService sc = SearchCriteria2 - .create(HostVO.class); + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); sc.addAnd(sc.getEntity().getName(), Op.EQ, name); return sc.find(); } @Override public List listHostsByNameLike(String name) { - SearchCriteriaService sc = SearchCriteria2 - .create(HostVO.class); + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); sc.addAnd(sc.getEntity().getName(), Op.LIKE, "%" + name + "%"); return sc.list(); } @Override - public Pair findPod(VirtualMachineTemplate template, - ServiceOfferingVO offering, DataCenterVO dc, long accountId, - Set avoids) { - for (PodAllocator allocator : _podAllocators) { - final Pair pod = allocator.allocateTo(template, - offering, dc, accountId, avoids); + public Pair findPod(VirtualMachineTemplate template, ServiceOfferingVO offering, DataCenterVO dc, long accountId, + Set avoids) { + for (PodAllocator allocator : _podAllocators) { + final Pair pod = allocator.allocateTo(template, offering, dc, accountId, avoids); if (pod != null) { return pod; } @@ -2801,9 +2487,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, @Override public HostStats getHostStatistics(long hostId) { - Answer answer = _agentMgr.easySend(hostId, new GetHostStatsCommand( - _hostDao.findById(hostId).getGuid(), _hostDao.findById(hostId) - .getName(), hostId)); + Answer answer = _agentMgr.easySend(hostId, new GetHostStatsCommand(_hostDao.findById(hostId).getGuid(), _hostDao.findById(hostId).getName(), + hostId)); if (answer != null && (answer instanceof UnsupportedAnswer)) { return null; @@ -2830,8 +2515,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, return null; } else { _hostDao.loadDetails(host); - DetailVO detail = _hostDetailsDao.findDetail(hostId, - "guest.os.category.id"); + DetailVO detail = _hostDetailsDao.findDetail(hostId, "guest.os.category.id"); if (detail == null) { return null; } else { @@ -2867,16 +2551,13 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, return pcs; } - @Override - public List listAllUpAndEnabledHostsInOneZoneByHypervisor( - HypervisorType type, long dcId) { - SearchCriteriaService sc = SearchCriteria2 - .create(HostVO.class); + @Override + public List listAllUpAndEnabledHostsInOneZoneByHypervisor(HypervisorType type, long dcId) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); sc.addAnd(sc.getEntity().getHypervisorType(), Op.EQ, type); sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId); sc.addAnd(sc.getEntity().getStatus(), Op.EQ, Status.Up); - sc.addAnd(sc.getEntity().getResourceState(), Op.EQ, - ResourceState.Enabled); + sc.addAnd(sc.getEntity().getResourceState(), Op.EQ, ResourceState.Enabled); return sc.list(); } diff --git a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java index 6d929c6438b..b5c060d8c33 100755 --- a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java +++ b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java @@ -30,6 +30,8 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.cloudstack.acl.SecurityChecker.AccessType; +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; @@ -143,11 +145,11 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim @Inject private ServiceOfferingDao _serviceOfferingDao; @Inject - private VMTemplateHostDao _vmTemplateHostDao; + private TemplateDataStoreDao _vmTemplateStoreDao; @Inject private VlanDao _vlanDao; - protected GenericSearchBuilder templateSizeSearch; + protected GenericSearchBuilder templateSizeSearch; protected SearchBuilder ResourceCountSearch; ScheduledExecutorService _rcExecutor; @@ -177,7 +179,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim ResourceCountSearch.and("domainId", ResourceCountSearch.entity().getDomainId(), SearchCriteria.Op.EQ); ResourceCountSearch.done(); - templateSizeSearch = _vmTemplateHostDao.createSearchBuilder(SumCount.class); + templateSizeSearch = _vmTemplateStoreDao.createSearchBuilder(SumCount.class); templateSizeSearch.select("sum", Func.SUM, templateSizeSearch.entity().getSize()); templateSizeSearch.and("downloadState", templateSizeSearch.entity().getDownloadState(), Op.EQ); templateSizeSearch.and("destroyed", templateSizeSearch.entity().getDestroyed(), Op.EQ); @@ -203,7 +205,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim projectResourceLimitMap.put(Resource.ResourceType.memory, Long.parseLong(_configDao.getValue(Config.DefaultMaxProjectMemory.key()))); projectResourceLimitMap.put(Resource.ResourceType.primary_storage, Long.parseLong(_configDao.getValue(Config.DefaultMaxProjectPrimaryStorage.key()))); projectResourceLimitMap.put(Resource.ResourceType.secondary_storage, Long.parseLong(_configDao.getValue(Config.DefaultMaxProjectSecondaryStorage.key()))); - + accountResourceLimitMap.put(Resource.ResourceType.public_ip, Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountPublicIPs.key()))); accountResourceLimitMap.put(Resource.ResourceType.snapshot, Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountSnapshots.key()))); accountResourceLimitMap.put(Resource.ResourceType.template, Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountTemplates.key()))); @@ -230,6 +232,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim s_logger.trace("Not incrementing resource count for system accounts, returning"); return; } + long numToIncrement = (delta.length == 0) ? 1 : delta[0].longValue(); if (!updateResourceCountForAccount(accountId, type, true, numToIncrement)) { @@ -903,7 +906,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim sc.setParameters("downloadState", Status.DOWNLOADED); sc.setParameters("destroyed", false); sc.setJoinParameters("templates", "accountId", accountId); - List templates = _vmTemplateHostDao.customSearch(sc, null); + List templates = _vmTemplateStoreDao.customSearch(sc, null); if (templates != null) { totalTemplatesSize = templates.get(0).sum; } diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index 510455b5213..8e952aab4f2 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -230,9 +230,20 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio } String hostIpAdr = NetUtils.getDefaultHostIp(); + boolean needUpdateHostIp = true; if (hostIpAdr != null) { - _configDao.update(Config.ManagementHostIPAdr.key(), Config.ManagementHostIPAdr.getCategory(), hostIpAdr); - s_logger.debug("ConfigurationServer saved \"" + hostIpAdr + "\" as host."); + Boolean devel = Boolean.valueOf(_configDao.getValue("developer")); + if (devel) { + String value = _configDao.getValue(Config.ManagementHostIPAdr.key()); + if (value != null) { + needUpdateHostIp = false; + } + } + + if (needUpdateHostIp) { + _configDao.update(Config.ManagementHostIPAdr.key(), Config.ManagementHostIPAdr.getCategory(), hostIpAdr); + s_logger.debug("ConfigurationServer saved \"" + hostIpAdr + "\" as host."); + } } // generate a single sign-on key diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index e415f6f95af..963234588de 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -17,11 +17,6 @@ package com.cloud.server; import java.lang.reflect.Field; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.UnknownHostException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.ArrayList; @@ -29,11 +24,9 @@ import java.util.Calendar; import java.util.Comparator; import java.util.Date; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.TimeZone; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -53,13 +46,10 @@ import org.apache.cloudstack.api.ApiConstants; import com.cloud.event.ActionEventUtils; import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd; import org.apache.cloudstack.api.command.admin.region.*; -import org.apache.cloudstack.api.response.ExtractResponse; import org.apache.commons.codec.binary.Base64; import org.apache.log4j.Logger; import org.apache.cloudstack.affinity.AffinityGroupProcessor; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd; import org.apache.cloudstack.api.command.admin.account.CreateAccountCmd; import org.apache.cloudstack.api.command.admin.account.DeleteAccountCmd; import org.apache.cloudstack.api.command.admin.account.DisableAccountCmd; @@ -147,11 +137,15 @@ import org.apache.cloudstack.api.command.admin.router.RebootRouterCmd; import org.apache.cloudstack.api.command.admin.router.StartRouterCmd; import org.apache.cloudstack.api.command.admin.router.StopRouterCmd; import org.apache.cloudstack.api.command.admin.router.UpgradeRouterCmd; +import org.apache.cloudstack.api.command.admin.storage.AddImageStoreCmd; import org.apache.cloudstack.api.command.admin.storage.AddS3Cmd; import org.apache.cloudstack.api.command.admin.storage.CancelPrimaryStorageMaintenanceCmd; +import org.apache.cloudstack.api.command.admin.storage.CreateCacheStoreCmd; import org.apache.cloudstack.api.command.admin.storage.CreateStoragePoolCmd; +import org.apache.cloudstack.api.command.admin.storage.DeleteImageStoreCmd; import org.apache.cloudstack.api.command.admin.storage.DeletePoolCmd; import org.apache.cloudstack.api.command.admin.storage.FindStoragePoolsForMigrationCmd; +import org.apache.cloudstack.api.command.admin.storage.ListImageStoresCmd; import org.apache.cloudstack.api.command.admin.storage.ListS3sCmd; import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd; import org.apache.cloudstack.api.command.admin.storage.ListStorageProvidersCmd; @@ -279,8 +273,6 @@ import org.apache.cloudstack.api.command.user.nat.DeleteIpForwardingRuleCmd; import org.apache.cloudstack.api.command.user.nat.DisableStaticNatCmd; import org.apache.cloudstack.api.command.user.nat.EnableStaticNatCmd; import org.apache.cloudstack.api.command.user.nat.ListIpForwardingRulesCmd; -import org.apache.cloudstack.api.command.user.network.*; - import org.apache.cloudstack.api.command.user.network.CreateNetworkACLCmd; import org.apache.cloudstack.api.command.user.network.CreateNetworkACLListCmd; import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; @@ -402,32 +394,22 @@ import org.apache.cloudstack.api.command.user.vpn.RemoveVpnUserCmd; import org.apache.cloudstack.api.command.user.vpn.ResetVpnConnectionCmd; import org.apache.cloudstack.api.command.user.vpn.UpdateVpnCustomerGatewayCmd; import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd; -import org.apache.cloudstack.api.response.ExtractResponse; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.commons.codec.binary.Base64; -import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.api.GetVncPortAnswer; import com.cloud.agent.api.GetVncPortCommand; -import com.cloud.agent.api.storage.CopyVolumeAnswer; -import com.cloud.agent.api.storage.CopyVolumeCommand; -import com.cloud.agent.api.storage.CreateVolumeOVAAnswer; -import com.cloud.agent.api.storage.CreateVolumeOVACommand; import com.cloud.agent.manager.allocator.HostAllocator; import com.cloud.alert.Alert; import com.cloud.alert.AlertManager; import com.cloud.alert.AlertVO; import com.cloud.alert.dao.AlertDao; import com.cloud.api.ApiDBUtils; -import com.cloud.async.AsyncJobExecutor; import com.cloud.async.AsyncJobManager; -import com.cloud.async.AsyncJobResult; -import com.cloud.async.AsyncJobVO; -import com.cloud.async.BaseAsyncJobExecutor; import com.cloud.capacity.Capacity; import com.cloud.capacity.CapacityVO; import com.cloud.capacity.dao.CapacityDao; @@ -461,7 +443,6 @@ import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; -import com.cloud.event.ActionEventUtils; import com.cloud.event.EventTypes; import com.cloud.event.EventVO; import com.cloud.event.dao.EventDao; @@ -501,13 +482,9 @@ import com.cloud.storage.GuestOS; import com.cloud.storage.GuestOSCategoryVO; import com.cloud.storage.GuestOSVO; import com.cloud.storage.GuestOsCategory; -import com.cloud.storage.Storage; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; -import com.cloud.storage.Upload; -import com.cloud.storage.Upload.Mode; -import com.cloud.storage.UploadVO; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.Volume; import com.cloud.storage.VolumeManager; @@ -526,7 +503,6 @@ import com.cloud.storage.upload.UploadMonitor; import com.cloud.tags.ResourceTagVO; import com.cloud.tags.dao.ResourceTagDao; import com.cloud.template.TemplateManager; -import com.cloud.template.VirtualMachineTemplate.TemplateFilter; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.SSHKeyPair; @@ -569,78 +545,12 @@ import com.cloud.vm.dao.VMInstanceDao; import edu.emory.mathcs.backport.java.util.Arrays; import edu.emory.mathcs.backport.java.util.Collections; -import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.api.command.admin.autoscale.CreateCounterCmd; -import org.apache.cloudstack.api.command.admin.autoscale.DeleteCounterCmd; -import org.apache.cloudstack.api.command.admin.cluster.AddClusterCmd; -import org.apache.cloudstack.api.command.admin.cluster.DeleteClusterCmd; -import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd; -import org.apache.cloudstack.api.command.admin.cluster.UpdateClusterCmd; -import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd; -import org.apache.cloudstack.api.command.admin.config.ListHypervisorCapabilitiesCmd; -import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; -import org.apache.cloudstack.api.command.admin.config.UpdateHypervisorCapabilitiesCmd; -import org.apache.cloudstack.api.command.admin.ldap.LDAPConfigCmd; -import org.apache.cloudstack.api.command.admin.ldap.LDAPRemoveCmd; -import org.apache.cloudstack.api.command.admin.pod.CreatePodCmd; -import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd; -import org.apache.cloudstack.api.command.admin.pod.ListPodsByCmd; -import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd; -import org.apache.cloudstack.api.command.admin.swift.AddSwiftCmd; -import org.apache.cloudstack.api.command.admin.swift.ListSwiftsCmd; -import org.apache.cloudstack.api.command.admin.template.PrepareTemplateCmd; -import org.apache.cloudstack.api.command.admin.vlan.CreateVlanIpRangeCmd; -import org.apache.cloudstack.api.command.admin.vlan.DeleteVlanIpRangeCmd; -import org.apache.cloudstack.api.command.admin.vlan.ListVlanIpRangesCmd; -import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd; -import org.apache.cloudstack.api.command.admin.vm.MigrateVMCmd; -import org.apache.cloudstack.api.command.admin.vm.MigrateVirtualMachineWithVolumeCmd; -import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; -import org.apache.cloudstack.api.command.admin.zone.CreateZoneCmd; -import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd; -import org.apache.cloudstack.api.command.admin.zone.MarkDefaultZoneForAccountCmd; -import org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd; -import org.apache.cloudstack.api.command.user.account.AddAccountToProjectCmd; -import org.apache.cloudstack.api.command.user.account.DeleteAccountFromProjectCmd; -import org.apache.cloudstack.api.command.user.account.ListAccountsCmd; -import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd; -import org.apache.cloudstack.api.command.user.address.AssociateIPAddrCmd; -import org.apache.cloudstack.api.command.user.address.DisassociateIPAddrCmd; -import org.apache.cloudstack.api.command.user.address.ListPublicIpAddressesCmd; -import org.apache.cloudstack.api.command.user.config.ListCapabilitiesCmd; -import org.apache.cloudstack.api.command.user.event.ArchiveEventsCmd; -import org.apache.cloudstack.api.command.user.event.DeleteEventsCmd; -import org.apache.cloudstack.api.command.user.event.ListEventTypesCmd; -import org.apache.cloudstack.api.command.user.event.ListEventsCmd; -import org.apache.cloudstack.api.command.user.guest.ListGuestOsCategoriesCmd; -import org.apache.cloudstack.api.command.user.guest.ListGuestOsCmd; -import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd; -import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd; -import org.apache.cloudstack.api.command.user.offering.ListDiskOfferingsCmd; -import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd; -import org.apache.cloudstack.api.command.user.region.ListRegionsCmd; -import org.apache.cloudstack.api.command.user.region.ha.gslb.*; -import org.apache.cloudstack.api.command.user.ssh.CreateSSHKeyPairCmd; -import org.apache.cloudstack.api.command.user.ssh.DeleteSSHKeyPairCmd; -import org.apache.cloudstack.api.command.user.ssh.ListSSHKeyPairsCmd; -import org.apache.cloudstack.api.command.user.ssh.RegisterSSHKeyPairCmd; -import org.apache.cloudstack.api.command.user.tag.CreateTagsCmd; -import org.apache.cloudstack.api.command.user.tag.DeleteTagsCmd; -import org.apache.cloudstack.api.command.user.tag.ListTagsCmd; -import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd; -import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd; -import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd; -import org.apache.cloudstack.api.command.user.vmgroup.UpdateVMGroupCmd; -import org.apache.cloudstack.api.command.user.vmsnapshot.CreateVMSnapshotCmd; -import org.apache.cloudstack.api.command.user.vmsnapshot.DeleteVMSnapshotCmd; -import org.apache.cloudstack.api.command.user.vmsnapshot.ListVMSnapshotCmd; -import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; -import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.api.command.admin.region.AddRegionCmd; +import org.apache.cloudstack.api.command.admin.region.RemoveRegionCmd; +import org.apache.cloudstack.api.command.admin.region.UpdateRegionCmd; import org.apache.cloudstack.api.command.admin.config.ListDeploymentPlannersCmd; + public class ManagementServerImpl extends ManagerBase implements ManagementServer { public static final Logger s_logger = Logger.getLogger(ManagementServerImpl.class.getName()); @@ -766,8 +676,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe ConfigurationServer _configServer; @Inject UserVmManager _userVmMgr; - @Inject ClusterManager _clusterMgr; - + @Inject + VolumeDataFactory _volFactory; private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker")); private final ScheduledExecutorService _alertExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AlertChecker")); @@ -790,10 +700,10 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe this._planners = _planners; } + @Inject ClusterManager _clusterMgr; private String _hashKey = null; private String _encryptionKey = null; private String _encryptionIV = null; - protected boolean _executeInSequence; @Inject protected AffinityGroupVMMapDao _affinityGroupVMMapDao; @@ -863,8 +773,6 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe _availableIdsMap.put(id, true); } - _executeInSequence = Boolean.parseBoolean(_configDao.getValue(Config.ExecuteInSequence.key())); - return true; } @@ -1000,10 +908,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe @Override public Pair, Integer> searchForClusters(ListClustersCmd cmd) { - Filter searchFilter = new Filter(ClusterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); - SearchCriteria sc = _clusterDao.createSearchCriteria(); - - Object id = cmd.getId(); + Object id = cmd.getId(); Object name = cmd.getClusterName(); Object podId = cmd.getPodId(); Long zoneId = cmd.getZoneId(); @@ -1011,35 +916,47 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe Object clusterType = cmd.getClusterType(); Object allocationState = cmd.getAllocationState(); String keyword = cmd.getKeyword(); - zoneId = _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), zoneId); + + Filter searchFilter = new Filter(ClusterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); + + SearchBuilder sb = _clusterDao.createSearchBuilder(); + sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); + sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); + sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ); + sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); + sb.and("hypervisorType", sb.entity().getHypervisorType(), SearchCriteria.Op.EQ); + sb.and("clusterType", sb.entity().getClusterType(), SearchCriteria.Op.EQ); + sb.and("allocationState", sb.entity().getAllocationState(), SearchCriteria.Op.EQ); + + SearchCriteria sc = sb.create(); if (id != null) { - sc.addAnd("id", SearchCriteria.Op.EQ, id); + sc.setParameters("id", id); } if (name != null) { - sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%"); + sc.setParameters("name", "%" + name + "%"); } if (podId != null) { - sc.addAnd("podId", SearchCriteria.Op.EQ, podId); + sc.setParameters("podId", podId); } if (zoneId != null) { - sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId); + sc.setParameters("dataCenterId", zoneId); } if (hypervisorType != null) { - sc.addAnd("hypervisorType", SearchCriteria.Op.EQ, hypervisorType); + sc.setParameters("hypervisorType", hypervisorType); } if (clusterType != null) { - sc.addAnd("clusterType", SearchCriteria.Op.EQ, clusterType); + sc.setParameters("clusterType", clusterType); } if (allocationState != null) { - sc.addAnd("allocationState", SearchCriteria.Op.EQ, allocationState); + sc.setParameters("allocationState", allocationState); } if (keyword != null) { @@ -1452,17 +1369,22 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe @Override public Pair, Integer> searchForPods(ListPodsByCmd cmd) { - Filter searchFilter = new Filter(HostPodVO.class, "dataCenterId", true, cmd.getStartIndex(), cmd.getPageSizeVal()); - SearchCriteria sc = _hostPodDao.createSearchCriteria(); - String podName = cmd.getPodName(); Long id = cmd.getId(); Long zoneId = cmd.getZoneId(); Object keyword = cmd.getKeyword(); Object allocationState = cmd.getAllocationState(); - zoneId = _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), zoneId); + + Filter searchFilter = new Filter(HostPodVO.class, "dataCenterId", true, cmd.getStartIndex(), cmd.getPageSizeVal()); + SearchBuilder sb = _hostPodDao.createSearchBuilder(); + sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); + sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); + sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); + sb.and("allocationState", sb.entity().getAllocationState(), SearchCriteria.Op.EQ); + + SearchCriteria sc = sb.create(); if (keyword != null) { SearchCriteria ssc = _hostPodDao.createSearchCriteria(); ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); @@ -1472,19 +1394,19 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } if (id != null) { - sc.addAnd("id", SearchCriteria.Op.EQ, id); + sc.setParameters("id", id); } if (podName != null) { - sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + podName + "%"); + sc.setParameters("name", "%" + podName + "%"); } if (zoneId != null) { - sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId); + sc.setParameters("dataCenterId", zoneId); } if (allocationState != null) { - sc.addAnd("allocationState", SearchCriteria.Op.EQ, allocationState); + sc.setParameters("allocationState", allocationState); } Pair, Integer> result = _hostPodDao.searchAndCount(sc, searchFilter); @@ -1695,73 +1617,13 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe return new Pair, Integer>(result.first(), result.second()); } - @Override - public Set> listIsos(ListIsosCmd cmd) throws IllegalArgumentException, InvalidParameterValueException { - TemplateFilter isoFilter = TemplateFilter.valueOf(cmd.getIsoFilter()); - Account caller = UserContext.current().getCaller(); - Map tags = cmd.getTags(); - boolean listAll = false; - if (isoFilter != null && isoFilter == TemplateFilter.all) { - if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { - throw new InvalidParameterValueException("Filter " + TemplateFilter.all + " can be specified by admin only"); - } - listAll = true; - } - List permittedAccountIds = new ArrayList(); - Ternary domainIdRecursiveListProject = new Ternary( - cmd.getDomainId(), cmd.isRecursive(), null); - _accountMgr.buildACLSearchParameters(caller, cmd.getId(), cmd.getAccountName(), cmd.getProjectId(), permittedAccountIds, - domainIdRecursiveListProject, listAll, false); - ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); - - List permittedAccounts = new ArrayList(); - for (Long accountId : permittedAccountIds) { - permittedAccounts.add(_accountMgr.getAccount(accountId)); - } - - HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor()); - return listTemplates(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true, cmd.isBootable(), cmd.getPageSizeVal(), - cmd.getStartIndex(), cmd.getZoneId(), hypervisorType, true, cmd.listInReadyState(), permittedAccounts, caller, - listProjectResourcesCriteria, tags); - } - - @Override - public Set> listTemplates(ListTemplatesCmd cmd) throws IllegalArgumentException, InvalidParameterValueException { - TemplateFilter templateFilter = TemplateFilter.valueOf(cmd.getTemplateFilter()); - Long id = cmd.getId(); - Map tags = cmd.getTags(); - Account caller = UserContext.current().getCaller(); - - boolean listAll = false; - if (templateFilter != null && templateFilter == TemplateFilter.all) { - if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { - throw new InvalidParameterValueException("Filter " + TemplateFilter.all + " can be specified by admin only"); - } - listAll = true; - } - - List permittedAccountIds = new ArrayList(); - Ternary domainIdRecursiveListProject = new Ternary( - cmd.getDomainId(), cmd.isRecursive(), null); - _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccountIds, domainIdRecursiveListProject, - listAll, false); - ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); - List permittedAccounts = new ArrayList(); - for (Long accountId : permittedAccountIds) { - permittedAccounts.add(_accountMgr.getAccount(accountId)); - } - - boolean showDomr = ((templateFilter != TemplateFilter.selfexecutable) && (templateFilter != TemplateFilter.featured)); - HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor()); - - return listTemplates(id, cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, cmd.getPageSizeVal(), cmd.getStartIndex(), - cmd.getZoneId(), hypervisorType, showDomr, cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags); - } + /* TODO: this method should go away. Keep here just in case that our latest refactoring using template_store_ref missed anything + * in handling Swift or S3. private Set> listTemplates(Long templateId, String name, String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long pageSize, Long startIndex, Long zoneId, HypervisorType hyperType, boolean showDomr, boolean onlyReady, - List permittedAccounts, Account caller, ListProjectResourcesCriteria listProjectResourcesCriteria, Map tags) { + List permittedAccounts, Account caller, ListProjectResourcesCriteria listProjectResourcesCriteria, Map tags, String zoneType) { VMTemplateVO template = null; if (templateId != null) { @@ -1802,7 +1664,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe startIndex, zoneId, hyperType, onlyReady, showDomr, permittedAccounts, caller, tags); Set> templateZonePairSet2 = new HashSet>(); templateZonePairSet2 = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, hypers, bootable, domain, pageSize, - startIndex, zoneId, hyperType, onlyReady, showDomr, permittedAccounts, caller, listProjectResourcesCriteria, tags); + startIndex, zoneId, hyperType, onlyReady, showDomr, permittedAccounts, caller, listProjectResourcesCriteria, tags, zoneType); for (Pair tmpltPair : templateZonePairSet2) { if (!templateZonePairSet.contains(new Pair(tmpltPair.first(), -1L))) { @@ -1826,7 +1688,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe Set> templateZonePairSet2 = new HashSet>(); templateZonePairSet2 = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, hypers, bootable, domain, pageSize, startIndex, zoneId, hyperType, onlyReady, showDomr, - permittedAccounts, caller, listProjectResourcesCriteria, tags); + permittedAccounts, caller, listProjectResourcesCriteria, tags, zoneType); for (Pair tmpltPair : templateZonePairSet2) { if (!templateZonePairSet.contains(new Pair(tmpltPair.first(), -1L))) { @@ -1844,7 +1706,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } else { if (template == null) { templateZonePairSet = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, hypers, bootable, domain, pageSize, - startIndex, zoneId, hyperType, onlyReady, showDomr, permittedAccounts, caller, listProjectResourcesCriteria, tags); + startIndex, zoneId, hyperType, onlyReady, showDomr, permittedAccounts, caller, listProjectResourcesCriteria, tags, zoneType); } else { // if template is not public, perform permission check here if (!template.isPublicTemplate() && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { @@ -1857,16 +1719,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe return templateZonePairSet; } - - @Override - public VMTemplateVO updateTemplate(UpdateIsoCmd cmd) { - return updateTemplateOrIso(cmd); - } - - @Override - public VMTemplateVO updateTemplate(UpdateTemplateCmd cmd) { - return updateTemplateOrIso(cmd); - } +*/ private VMTemplateVO updateTemplateOrIso(BaseUpdateTemplateOrIsoCmd cmd) { Long id = cmd.getId(); @@ -2898,6 +2751,10 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe cmdList.add(AssignToGlobalLoadBalancerRuleCmd.class); cmdList.add(RemoveFromGlobalLoadBalancerRuleCmd.class); cmdList.add(ListStorageProvidersCmd.class); + cmdList.add(AddImageStoreCmd.class); + cmdList.add(ListImageStoresCmd.class); + cmdList.add(DeleteImageStoreCmd.class); + cmdList.add(CreateCacheStoreCmd.class); cmdList.add(CreateApplicationLoadBalancerCmd.class); cmdList.add(ListApplicationLoadBalancersCmd.class); cmdList.add(DeleteApplicationLoadBalancerCmd.class); @@ -3353,207 +3210,6 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe return _guestOSDao.findById(guestOsId); } - @Override - @ActionEvent(eventType = EventTypes.EVENT_VOLUME_EXTRACT, eventDescription = "extracting volume", async = true) - public Long extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException { - Long volumeId = cmd.getId(); - String url = cmd.getUrl(); - Long zoneId = cmd.getZoneId(); - AsyncJobVO job = null; // FIXME: cmd.getJob(); - String mode = cmd.getMode(); - Account account = UserContext.current().getCaller(); - - if (!_accountMgr.isRootAdmin(account.getType()) && ApiDBUtils.isExtractionDisabled()) { - throw new PermissionDeniedException("Extraction has been disabled by admin"); - } - - VolumeVO volume = _volumeDao.findById(volumeId); - if (volume == null) { - InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find volume with specified volumeId"); - ex.addProxyObject(volumeId.toString(), "volumeId"); - throw ex; - } - - // perform permission check - _accountMgr.checkAccess(account, null, true, volume); - - if (_dcDao.findById(zoneId) == null) { - throw new InvalidParameterValueException("Please specify a valid zone."); - } - if (volume.getPoolId() == null) { - throw new InvalidParameterValueException("The volume doesnt belong to a storage pool so cant extract it"); - } - // Extract activity only for detached volumes or for volumes whose - // instance is stopped - if (volume.getInstanceId() != null && ApiDBUtils.findVMInstanceById(volume.getInstanceId()).getState() != State.Stopped) { - s_logger.debug("Invalid state of the volume with ID: " + volumeId - + ". It should be either detached or the VM should be in stopped state."); - PermissionDeniedException ex = new PermissionDeniedException( - "Invalid state of the volume with specified ID. It should be either detached or the VM should be in stopped state."); - ex.addProxyObject(volume.getUuid(), "volumeId"); - throw ex; - } - - if (volume.getVolumeType() != Volume.Type.DATADISK) { // Datadisk dont - // have any - // template - // dependence. - - VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId()); - if (template != null) { // For ISO based volumes template = null and - // we allow extraction of all ISO based - // volumes - boolean isExtractable = template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM; - if (!isExtractable && account != null && account.getType() != Account.ACCOUNT_TYPE_ADMIN) { // Global - // admins are always allowed to extract - PermissionDeniedException ex = new PermissionDeniedException("The volume with specified volumeId is not allowed to be extracted"); - ex.addProxyObject(volume.getUuid(), "volumeId"); - throw ex; - } - } - } - - Upload.Mode extractMode; - if (mode == null || (!mode.equals(Upload.Mode.FTP_UPLOAD.toString()) && !mode.equals(Upload.Mode.HTTP_DOWNLOAD.toString()))) { - throw new InvalidParameterValueException("Please specify a valid extract Mode "); - } else { - extractMode = mode.equals(Upload.Mode.FTP_UPLOAD.toString()) ? Upload.Mode.FTP_UPLOAD : Upload.Mode.HTTP_DOWNLOAD; - } - - // If mode is upload perform extra checks on url and also see if there - // is an ongoing upload on the same. - if (extractMode == Upload.Mode.FTP_UPLOAD) { - URI uri = new URI(url); - if ((uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp"))) { - throw new IllegalArgumentException("Unsupported scheme for url: " + url); - } - - String host = uri.getHost(); - try { - InetAddress hostAddr = InetAddress.getByName(host); - if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress()) { - throw new IllegalArgumentException("Illegal host specified in url"); - } - if (hostAddr instanceof Inet6Address) { - throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")"); - } - } catch (UnknownHostException uhe) { - throw new IllegalArgumentException("Unable to resolve " + host); - } - - if (_uploadMonitor.isTypeUploadInProgress(volumeId, Upload.Type.VOLUME)) { - throw new IllegalArgumentException(volume.getName() - + " upload is in progress. Please wait for some time to schedule another upload for the same"); - } - } - - long accountId = volume.getAccountId(); - StoragePool srcPool = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(volume.getPoolId()); - HostVO sserver = this.templateMgr.getSecondaryStorageHost(zoneId); - String secondaryStorageURL = sserver.getStorageUrl(); - - List extractURLList = _uploadDao.listByTypeUploadStatus(volumeId, Upload.Type.VOLUME, UploadVO.Status.DOWNLOAD_URL_CREATED); - - if (extractMode == Upload.Mode.HTTP_DOWNLOAD && extractURLList.size() > 0) { - return extractURLList.get(0).getId(); // If download url already Note: volss - // exists then return - } else { - UploadVO uploadJob = _uploadMonitor.createNewUploadEntry(sserver.getId(), volumeId, UploadVO.Status.COPY_IN_PROGRESS, Upload.Type.VOLUME, - url, extractMode); - s_logger.debug("Extract Mode - " + uploadJob.getMode()); - uploadJob = _uploadDao.createForUpdate(uploadJob.getId()); - - // Update the async Job - - ExtractResponse resultObj = new ExtractResponse(ApiDBUtils.findVolumeById(volumeId).getUuid(), - volume.getName(), ApiDBUtils.findAccountById(accountId).getUuid(), UploadVO.Status.COPY_IN_PROGRESS.toString(), - uploadJob.getUuid()); - resultObj.setResponseName(cmd.getCommandName()); - AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor(); - if (asyncExecutor != null) { - job = asyncExecutor.getJob(); - _asyncMgr.updateAsyncJobAttachment(job.getId(), Upload.Type.VOLUME.toString(), volumeId); - _asyncMgr.updateAsyncJobStatus(job.getId(), AsyncJobResult.STATUS_IN_PROGRESS, resultObj); - } - String value = _configs.get(Config.CopyVolumeWait.toString()); - int copyvolumewait = NumbersUtil.parseInt(value, Integer.parseInt(Config.CopyVolumeWait.getDefaultValue())); - // Copy the volume from the source storage pool to secondary storage - CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true, copyvolumewait, _executeInSequence); - CopyVolumeAnswer cvAnswer = null; - try { - cvAnswer = (CopyVolumeAnswer) _storageMgr.sendToPool(srcPool, cvCmd); - } catch (StorageUnavailableException e) { - s_logger.debug("Storage unavailable"); - } - - // Check if you got a valid answer. - if (cvAnswer == null || !cvAnswer.getResult()) { - String errorString = "Failed to copy the volume from the source primary storage pool to secondary storage."; - - // Update the async job. - resultObj.setResultString(errorString); - resultObj.setUploadStatus(UploadVO.Status.COPY_ERROR.toString()); - if (asyncExecutor != null) { - _asyncMgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_FAILED, 0, resultObj); - } - - // Update the DB that volume couldn't be copied - uploadJob.setUploadState(UploadVO.Status.COPY_ERROR); - uploadJob.setErrorString(errorString); - uploadJob.setLastUpdated(new Date()); - _uploadDao.update(uploadJob.getId(), uploadJob); - - throw new CloudRuntimeException(errorString); - } - - String volumeLocalPath = "volumes/" + volume.getId() + "/" + cvAnswer.getVolumePath() + "." + getFormatForPool(srcPool); - //Fang: volss, handle the ova special case; - if (getFormatForPool(srcPool) == "ova") { - CreateVolumeOVACommand cvOVACmd = new CreateVolumeOVACommand(secondaryStorageURL, volumeLocalPath, cvAnswer.getVolumePath(), srcPool, copyvolumewait); - CreateVolumeOVAAnswer OVAanswer = null; - - try { - cvOVACmd.setContextParam("hypervisor", HypervisorType.VMware.toString()); - OVAanswer = (CreateVolumeOVAAnswer) _storageMgr.sendToPool(srcPool, cvOVACmd); //Fang: for extract volume, create the ova file here; - - } catch (StorageUnavailableException e) { - s_logger.debug("Storage unavailable"); - } - } - // Update the DB that volume is copied and volumePath - uploadJob.setUploadState(UploadVO.Status.COPY_COMPLETE); - uploadJob.setLastUpdated(new Date()); - uploadJob.setInstallPath(volumeLocalPath); - _uploadDao.update(uploadJob.getId(), uploadJob); - - if (extractMode == Mode.FTP_UPLOAD) { // Now that the volume is - // copied perform the actual - // uploading - _uploadMonitor.extractVolume(uploadJob, sserver, volume, url, zoneId, volumeLocalPath, cmd.getStartEventId(), job.getId(), _asyncMgr); - return uploadJob.getId(); - } else { // Volume is copied now make it visible under apache and - // create a URL. - _uploadMonitor.createVolumeDownloadURL(volumeId, volumeLocalPath, Upload.Type.VOLUME, zoneId, uploadJob.getId()); - return uploadJob.getId(); - } - } - } - - private String getFormatForPool(StoragePool pool) { - ClusterVO cluster = ApiDBUtils.findClusterById(pool.getClusterId()); - - if (cluster.getHypervisorType() == HypervisorType.XenServer) { - return "vhd"; - } else if (cluster.getHypervisorType() == HypervisorType.KVM) { - return "qcow2"; - } else if (cluster.getHypervisorType() == HypervisorType.VMware) { - return "ova"; - } else if (cluster.getHypervisorType() == HypervisorType.Ovm) { - return "raw"; - } else { - return null; - } - } @Override public InstanceGroupVO updateVmGroup(UpdateVMGroupCmd cmd) { @@ -3721,6 +3377,11 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe _encryptionIV = null; } + @Override + public boolean getExecuteInSequence() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + private static String getBase64EncodedRandomKey(int nBits) { SecureRandom random; try { @@ -4089,9 +3750,5 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe return plannersAvailable; } - - @Override - public boolean getExecuteInSequence() { - return _executeInSequence; - } + } diff --git a/server/src/com/cloud/server/StatsCollector.java b/server/src/com/cloud/server/StatsCollector.java index 8d84c6ca237..0d7fc3d65ee 100755 --- a/server/src/com/cloud/server/StatsCollector.java +++ b/server/src/com/cloud/server/StatsCollector.java @@ -30,9 +30,14 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import javax.annotation.PostConstruct; import javax.inject.Inject; +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.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; @@ -60,19 +65,14 @@ import com.cloud.host.HostStats; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; -import com.cloud.resource.ResourceManager; import com.cloud.resource.ResourceState; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePoolHostVO; import com.cloud.storage.StorageStats; -import com.cloud.storage.Volume; import com.cloud.storage.VolumeStats; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.storage.dao.VolumeDao; -import com.cloud.storage.secondary.SecondaryStorageVmManager; -import com.cloud.user.UserStatisticsVO; -import com.cloud.user.UserStatsLogVO; import com.cloud.user.VmDiskStatisticsVO; import com.cloud.user.dao.VmDiskStatisticsDao; import com.cloud.utils.NumbersUtil; @@ -84,12 +84,10 @@ import com.cloud.utils.db.GlobalLock; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; import com.cloud.utils.net.MacAddress; -import com.cloud.vm.NicVO; import com.cloud.vm.UserVmManager; import com.cloud.vm.UserVmVO; import com.cloud.vm.VmStats; import com.cloud.vm.VirtualMachine; -import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.dao.UserVmDao; /** @@ -109,11 +107,13 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc @Inject private UserVmDao _userVmDao; @Inject private VolumeDao _volsDao; @Inject private PrimaryDataStoreDao _storagePoolDao; + @Inject private ImageStoreDao _imageStoreDao; @Inject private StorageManager _storageManager; @Inject private StoragePoolHostDao _storagePoolHostDao; - @Inject private SecondaryStorageVmManager _ssvmMgr; + @Inject private DataStoreManager _dataStoreMgr; @Inject private ResourceManager _resourceMgr; @Inject private ConfigurationDao _configDao; + @Inject private EndPointSelector _epSelector; @Inject private VmDiskStatisticsDao _vmDiskStatsDao; @Inject private ManagementServerHostDao _msHostDao; @@ -122,13 +122,13 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc private ConcurrentHashMap _volumeStats = new ConcurrentHashMap(); private ConcurrentHashMap _storageStats = new ConcurrentHashMap(); private ConcurrentHashMap _storagePoolStats = new ConcurrentHashMap(); - + long hostStatsInterval = -1L; long hostAndVmStatsInterval = -1L; long storageStatsInterval = -1L; long volumeStatsInterval = -1L; int vmDiskStatsInterval = 0; - + private ScheduledExecutorService _diskStatsUpdateExecutor; private int _usageAggregationRange = 1440; private String _usageTimeZone = "GMT"; @@ -142,12 +142,12 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc public static StatsCollector getInstance() { return s_instance; } - + public static StatsCollector getInstance(Map configs) { s_instance.init(configs); return s_instance; } - + public StatsCollector() { s_instance = this; } @@ -170,28 +170,21 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc if (hostStatsInterval > 0) { _executor.scheduleWithFixedDelay(new HostCollector(), 15000L, hostStatsInterval, TimeUnit.MILLISECONDS); } - + if (hostAndVmStatsInterval > 0) { _executor.scheduleWithFixedDelay(new VmStatsCollector(), 15000L, hostAndVmStatsInterval, TimeUnit.MILLISECONDS); } - + if (storageStatsInterval > 0) { _executor.scheduleWithFixedDelay(new StorageCollector(), 15000L, storageStatsInterval, TimeUnit.MILLISECONDS); } - + if (vmDiskStatsInterval > 0) { if (vmDiskStatsInterval < 300) vmDiskStatsInterval = 300; _executor.scheduleAtFixedRate(new VmDiskStatsTask(), vmDiskStatsInterval, vmDiskStatsInterval, TimeUnit.SECONDS); } - - // -1 means we don't even start this thread to pick up any data. - if (volumeStatsInterval > 0) { - _executor.scheduleWithFixedDelay(new VolumeCollector(), 15000L, volumeStatsInterval, TimeUnit.MILLISECONDS); - } else { - s_logger.info("Disabling volume stats collector"); - } - + //Schedule disk stats update task _diskStatsUpdateExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("DiskStatsUpdater")); String aggregationRange = configs.get("usage.stats.job.aggregation.range"); @@ -233,7 +226,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc } _diskStatsUpdateExecutor.scheduleAtFixedRate(new VmDiskStatsUpdaterTask(), (endDate - System.currentTimeMillis()), (_usageAggregationRange * 60 * 1000), TimeUnit.MILLISECONDS); - + } class HostCollector implements Runnable { @@ -241,7 +234,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc public void run() { try { s_logger.debug("HostStatsCollector is running..."); - + SearchCriteria sc = _hostDao.createSearchCriteria(); sc.addAnd("status", SearchCriteria.Op.EQ, Status.Up.toString()); sc.addAnd("resourceState", SearchCriteria.Op.NIN, ResourceState.Maintenance, ResourceState.PrepareForMaintenance, ResourceState.ErrorInMaintenance); @@ -276,13 +269,13 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc } } } - + class VmStatsCollector implements Runnable { @Override public void run() { try { s_logger.debug("VmStatsCollector is running..."); - + SearchCriteria sc = _hostDao.createSearchCriteria(); sc.addAnd("status", SearchCriteria.Op.EQ, Status.Up.toString()); sc.addAnd("resourceState", SearchCriteria.Op.NIN, ResourceState.Maintenance, ResourceState.PrepareForMaintenance, ResourceState.ErrorInMaintenance); @@ -293,29 +286,29 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc sc.addAnd("type", SearchCriteria.Op.NEQ, Host.Type.TrafficMonitor.toString()); sc.addAnd("type", SearchCriteria.Op.NEQ, Host.Type.SecondaryStorageVM.toString()); List hosts = _hostDao.search(sc, null); - + for (HostVO host : hosts) { List vms = _userVmDao.listRunningByHostId(host.getId()); List vmIds = new ArrayList(); - + for (UserVmVO vm : vms) { vmIds.add(vm.getId()); } - + try { HashMap vmStatsById = _userVmMgr.getVirtualMachineStatistics(host.getId(), host.getName(), vmIds); - + if(vmStatsById != null) { VmStatsEntry statsInMemory = null; - + Set vmIdSet = vmStatsById.keySet(); for(Long vmId : vmIdSet) { VmStatsEntry statsForCurrentIteration = vmStatsById.get(vmId); statsInMemory = (VmStatsEntry) _VmStats.get(vmId); - + if(statsInMemory == null) { //no stats exist for this vm, directly persist @@ -332,18 +325,18 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc statsInMemory.setDiskReadIOs(statsInMemory.getDiskReadIOs() + statsForCurrentIteration.getDiskReadIOs()); statsInMemory.setDiskWriteIOs(statsInMemory.getDiskWriteIOs() + statsForCurrentIteration.getDiskWriteIOs()); statsInMemory.setDiskReadKBs(statsInMemory.getDiskReadKBs() + statsForCurrentIteration.getDiskReadKBs()); - + _VmStats.put(vmId, statsInMemory); } } } - + } catch (Exception e) { s_logger.debug("Failed to get VM stats for host with ID: " + host.getId()); continue; } } - + } catch (Throwable t) { s_logger.error("Error trying to retrieve VM stats", t); } @@ -353,7 +346,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc public VmStats getVmStats(long id) { return _VmStats.get(id); } - + class VmDiskStatsUpdaterTask implements Runnable { @Override public void run() { @@ -375,7 +368,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc List updatedVmNetStats = _vmDiskStatsDao.listUpdatedStats(); for(VmDiskStatisticsVO stat : updatedVmNetStats){ if (_dailyOrHourly) { - //update agg bytes + //update agg bytes stat.setAggBytesRead(stat.getCurrentBytesRead() + stat.getNetBytesRead()); stat.setAggBytesWrite(stat.getCurrentBytesWrite() + stat.getNetBytesWrite()); stat.setAggIORead(stat.getCurrentIORead() + stat.getNetIORead()); @@ -400,7 +393,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc } } } - + class VmDiskStatsTask implements Runnable { @Override public void run() { @@ -413,20 +406,20 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc sc.addAnd("resourceState", SearchCriteria.Op.NIN, ResourceState.Maintenance, ResourceState.PrepareForMaintenance, ResourceState.ErrorInMaintenance); sc.addAnd("type", SearchCriteria.Op.EQ, Host.Type.Routing.toString()); List hosts = _hostDao.search(sc, null); - + for (HostVO host : hosts) { List vms = _userVmDao.listRunningByHostId(host.getId()); List vmIds = new ArrayList(); - + for (UserVmVO vm : vms) { if (vm.getType() == VirtualMachine.Type.User) // user vm vmIds.add(vm.getId()); } - + HashMap> vmDiskStatsById = _userVmMgr.getVmDiskStatistics(host.getId(), host.getName(), vmIds); if (vmDiskStatsById == null) continue; - + Set vmIdSet = vmDiskStatsById.keySet(); for(Long vmId : vmIdSet) { @@ -440,13 +433,13 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc VolumeVO volume = _volsDao.search(sc_volume, null).get(0); VmDiskStatisticsVO previousVmDiskStats = _vmDiskStatsDao.findBy(userVm.getAccountId(), userVm.getDataCenterId(), vmId, volume.getId()); VmDiskStatisticsVO vmDiskStat_lock = _vmDiskStatsDao.lock(userVm.getAccountId(), userVm.getDataCenterId(), vmId, volume.getId()); - + if ((vmDiskStat.getBytesRead() == 0) && (vmDiskStat.getBytesWrite() == 0) && (vmDiskStat.getIORead() == 0) && (vmDiskStat.getIOWrite() == 0)) { s_logger.debug("IO/bytes read and write are all 0. Not updating vm_disk_statistics"); continue; } - + if (vmDiskStat_lock == null) { s_logger.warn("unable to find vm disk stats from host for account: " + userVm.getAccountId() + " with vmId: " + userVm.getId()+ " and volumeId:" + volume.getId()); continue; @@ -458,7 +451,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc || (previousVmDiskStats.getCurrentIORead() != vmDiskStat_lock.getCurrentIORead()) || (previousVmDiskStats.getCurrentIOWrite() != vmDiskStat_lock.getCurrentIOWrite()))) { s_logger.debug("vm disk stats changed from the time GetVmDiskStatsCommand was sent. " + - "Ignoring current answer. Host: " + host.getName() + " . VM: " + vmDiskStat.getVmName() + + "Ignoring current answer. Host: " + host.getName() + " . VM: " + vmDiskStat.getVmName() + " Read(Bytes): " + vmDiskStat.getBytesRead() + " write(Bytes): " + vmDiskStat.getBytesWrite() + " Read(IO): " + vmDiskStat.getIORead() + " write(IO): " + vmDiskStat.getIOWrite()); continue; @@ -500,9 +493,9 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc vmDiskStat_lock.setNetIOWrite(vmDiskStat_lock.getNetIOWrite() + vmDiskStat_lock.getCurrentIOWrite()); } vmDiskStat_lock.setCurrentIOWrite(vmDiskStat.getIOWrite()); - + if (! _dailyOrHourly) { - //update agg bytes + //update agg bytes vmDiskStat_lock.setAggBytesWrite(vmDiskStat_lock.getNetBytesWrite() + vmDiskStat_lock.getCurrentBytesWrite()); vmDiskStat_lock.setAggBytesRead(vmDiskStat_lock.getNetBytesRead() + vmDiskStat_lock.getCurrentBytesRead()); vmDiskStat_lock.setAggIOWrite(vmDiskStat_lock.getNetIOWrite() + vmDiskStat_lock.getCurrentIOWrite()); @@ -519,7 +512,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc } finally { txn.close(); } - + } } @@ -530,30 +523,24 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc if (s_logger.isDebugEnabled()) { s_logger.debug("StorageCollector is running..."); } - - List hosts = _ssvmMgr.listSecondaryStorageHostsInAllZones(); + + List stores = _dataStoreMgr.listImageStores(); ConcurrentHashMap storageStats = new ConcurrentHashMap(); - for (HostVO host : hosts) { - if ( host.getStorageUrl() == null ) { + for (DataStore store : stores) { + if ( store.getUri() == null ) { continue; } - GetStorageStatsCommand command = new GetStorageStatsCommand(host.getStorageUrl()); - HostVO ssAhost = _ssvmMgr.pickSsvmHost(host); + GetStorageStatsCommand command = new GetStorageStatsCommand(store.getUri()); + EndPoint ssAhost = _epSelector.select(store); if (ssAhost == null) { - s_logger.debug("There is no secondary storage VM for secondary storage host " + host.getName()); + s_logger.debug("There is no secondary storage VM for secondary storage host " + store.getName()); continue; } - long hostId = host.getId(); - Answer answer = _agentMgr.easySend(ssAhost.getId(), command); + long storeId = store.getId(); + Answer answer = ssAhost.sendMessage(command); if (answer != null && answer.getResult()) { - storageStats.put(hostId, (StorageStats)answer); - s_logger.trace("HostId: "+hostId+ " Used: " + ((StorageStats)answer).getByteUsed() + " Total Available: " + ((StorageStats)answer).getCapacityBytes()); - //Seems like we have dynamically updated the sec. storage as prev. size and the current do not match - if (_storageStats.get(hostId)!=null && - _storageStats.get(hostId).getCapacityBytes() != ((StorageStats)answer).getCapacityBytes()){ - host.setTotalSize(((StorageStats)answer).getCapacityBytes()); - _hostDao.update(hostId, host); - } + storageStats.put(storeId, (StorageStats)answer); + s_logger.trace("HostId: "+storeId+ " Used: " + ((StorageStats)answer).getByteUsed() + " Total Available: " + ((StorageStats)answer).getCapacityBytes()); } } _storageStats = storageStats; @@ -570,7 +557,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc Answer answer = _storageManager.sendToPool(pool, command); if (answer != null && answer.getResult()) { storagePoolStats.put(pool.getId(), (StorageStats)answer); - + // Seems like we have dynamically updated the pool size since the prev. size and the current do not match if (_storagePoolStats.get(poolId)!= null && _storagePoolStats.get(poolId).getCapacityBytes() != ((StorageStats)answer).getCapacityBytes()){ @@ -594,87 +581,12 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc public StorageStats getStorageStats(long id) { return _storageStats.get(id); } - + public HostStats getHostStats(long hostId){ return _hostStats.get(hostId); } - + public StorageStats getStoragePoolStats(long id) { return _storagePoolStats.get(id); } - - class VolumeCollector implements Runnable { - @Override - public void run() { - try { - List volumes = _volsDao.listAll(); - Map> commandsByPool = new HashMap>(); - - for (VolumeVO volume : volumes) { - List commands = commandsByPool.get(volume.getPoolId()); - if (commands == null) { - commands = new ArrayList(); - commandsByPool.put(volume.getPoolId(), commands); - } - VolumeCommand vCommand = new VolumeCommand(); - vCommand.volumeId = volume.getId(); - vCommand.command = new GetFileStatsCommand(volume); - commands.add(vCommand); - } - ConcurrentHashMap volumeStats = new ConcurrentHashMap(); - for (Iterator iter = commandsByPool.keySet().iterator(); iter.hasNext();) { - Long poolId = iter.next(); - if(poolId != null) { - List commandsList = commandsByPool.get(poolId); - - long[] volumeIdArray = new long[commandsList.size()]; - Commands commands = new Commands(OnError.Continue); - for (int i = 0; i < commandsList.size(); i++) { - VolumeCommand vCommand = commandsList.get(i); - volumeIdArray[i] = vCommand.volumeId; - commands.addCommand(vCommand.command); - } - - List poolhosts = _storagePoolHostDao.listByPoolId(poolId); - for(StoragePoolHostVO poolhost : poolhosts) { - Answer[] answers = _agentMgr.send(poolhost.getHostId(), commands); - if (answers != null) { - long totalBytes = 0L; - for (int i = 0; i < answers.length; i++) { - if (answers[i].getResult()) { - VolumeStats vStats = (VolumeStats)answers[i]; - volumeStats.put(volumeIdArray[i], vStats); - totalBytes += vStats.getBytesUsed(); - } - } - break; - } - } - } - } - - // We replace the existing volumeStats so that it does not grow with no bounds - _volumeStats = volumeStats; - } catch (AgentUnavailableException e) { - s_logger.debug(e.getMessage()); - } catch (Throwable t) { - s_logger.error("Error trying to retrieve volume stats", t); - } - } - } - - private class VolumeCommand { - public long volumeId; - public GetFileStatsCommand command; - } - - public VolumeStats[] getVolumeStats(long[] ids) { - VolumeStats[] stats = new VolumeStats[ids.length]; - if (volumeStatsInterval > 0) { - for (int i = 0; i < ids.length; i++) { - stats[i] = _volumeStats.get(ids[i]); - } - } - return stats; - } } diff --git a/server/src/com/cloud/storage/CreateSnapshotPayload.java b/server/src/com/cloud/storage/CreateSnapshotPayload.java new file mode 100644 index 00000000000..5adc7462ffe --- /dev/null +++ b/server/src/com/cloud/storage/CreateSnapshotPayload.java @@ -0,0 +1,50 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.storage; + +import com.cloud.user.Account; + +public class CreateSnapshotPayload { + private Long snapshotPolicyId; + private Long snapshotId; + private Account account; + + public Long getSnapshotPolicyId() { + return snapshotPolicyId; + } + + public void setSnapshotPolicyId(Long snapshotPolicyId) { + this.snapshotPolicyId = snapshotPolicyId; + } + + public Long getSnapshotId() { + return snapshotId; + } + + public void setSnapshotId(Long snapshotId) { + this.snapshotId = snapshotId; + } + + public Account getAccount() { + return account; + } + + public void setAccount(Account account) { + this.account = account; + } + +} diff --git a/server/src/com/cloud/storage/LocalStoragePoolListener.java b/server/src/com/cloud/storage/LocalStoragePoolListener.java index 244f7fbe271..088d601376c 100755 --- a/server/src/com/cloud/storage/LocalStoragePoolListener.java +++ b/server/src/com/cloud/storage/LocalStoragePoolListener.java @@ -32,7 +32,7 @@ import com.cloud.agent.api.StoragePoolInfo; import com.cloud.capacity.dao.CapacityDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.exception.ConnectionException; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.host.Status; import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.utils.db.DB; @@ -67,7 +67,7 @@ public class LocalStoragePoolListener implements Listener { @Override @DB - public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { + public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { if (!(cmd instanceof StartupStorageCommand)) { return; } diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 20b435c60dc..0df3dbe9116 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -25,6 +25,7 @@ import java.sql.ResultSet; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -40,9 +41,12 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.api.command.admin.storage.AddImageStoreCmd; import com.cloud.server.ConfigurationServer; import org.apache.cloudstack.api.command.admin.storage.CancelPrimaryStorageMaintenanceCmd; +import org.apache.cloudstack.api.command.admin.storage.CreateCacheStoreCmd; import org.apache.cloudstack.api.command.admin.storage.CreateStoragePoolCmd; +import org.apache.cloudstack.api.command.admin.storage.DeleteImageStoreCmd; import org.apache.cloudstack.api.command.admin.storage.DeletePoolCmd; import org.apache.cloudstack.api.command.admin.storage.UpdateStoragePoolCmd; import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; @@ -51,37 +55,47 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; -import org.apache.cloudstack.engine.subsystem.api.storage.ImageDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.ImageStoreProvider; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult; import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +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.log4j.Logger; import org.springframework.stereotype.Component; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; -import com.cloud.agent.api.BackupSnapshotCommand; -import com.cloud.agent.api.CleanupSnapshotBackupCommand; import com.cloud.agent.api.Command; -import com.cloud.agent.api.ManageSnapshotCommand; import com.cloud.agent.api.StoragePoolInfo; -import com.cloud.agent.api.storage.DeleteTemplateCommand; -import com.cloud.agent.api.storage.DeleteVolumeCommand; import com.cloud.agent.manager.Commands; -import com.cloud.alert.AlertManager; import com.cloud.api.ApiDBUtils; -import com.cloud.async.AsyncJobManager; +import com.cloud.api.query.dao.TemplateJoinDao; +import com.cloud.api.query.vo.TemplateJoinVO; import com.cloud.capacity.Capacity; import com.cloud.capacity.CapacityManager; import com.cloud.capacity.CapacityState; @@ -92,19 +106,16 @@ import com.cloud.cluster.ManagementServerHostVO; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.dao.ConfigurationDao; -import com.cloud.consoleproxy.ConsoleProxyManager; import com.cloud.dc.ClusterVO; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.DataCenterDao; -import com.cloud.dc.dao.HostPodDao; import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeploymentPlanner.ExcludeList; -import com.cloud.domain.dao.DomainDao; -import com.cloud.event.dao.EventDao; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConnectionException; +import com.cloud.exception.DiscoveryException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.OperationTimedoutException; @@ -118,11 +129,8 @@ import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.HypervisorGuruManager; -import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; -import com.cloud.network.NetworkModel; import com.cloud.org.Grouping; import com.cloud.org.Grouping.AllocationState; -import com.cloud.resource.ResourceManager; import com.cloud.resource.ResourceState; import com.cloud.server.ManagementServer; import com.cloud.server.StatsCollector; @@ -131,34 +139,23 @@ import com.cloud.service.ServiceOfferingVO; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Volume.Type; -import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.SnapshotDao; -import com.cloud.storage.dao.SnapshotPolicyDao; import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.storage.dao.StoragePoolWorkDao; import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VMTemplateHostDao; import com.cloud.storage.dao.VMTemplatePoolDao; -import com.cloud.storage.dao.VMTemplateS3Dao; -import com.cloud.storage.dao.VMTemplateSwiftDao; +import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.dao.VolumeHostDao; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.download.DownloadMonitor; import com.cloud.storage.listener.StoragePoolMonitor; import com.cloud.storage.listener.VolumeStateListener; -import com.cloud.storage.s3.S3Manager; -import com.cloud.storage.secondary.SecondaryStorageVmManager; -import com.cloud.storage.snapshot.SnapshotManager; -import com.cloud.storage.snapshot.SnapshotScheduler; -import com.cloud.tags.dao.ResourceTagDao; import com.cloud.template.TemplateManager; import com.cloud.user.Account; import com.cloud.user.AccountManager; -import com.cloud.user.ResourceLimitService; import com.cloud.user.User; import com.cloud.user.UserContext; -import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserDao; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; @@ -177,16 +174,10 @@ import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.DiskProfile; -import com.cloud.vm.UserVmManager; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine.State; -import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.VirtualMachineProfileImpl; -import com.cloud.vm.dao.ConsoleProxyDao; -import com.cloud.vm.dao.DomainRouterDao; -import com.cloud.vm.dao.SecondaryStorageVmDao; -import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; @Component @@ -196,8 +187,6 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C protected String _name; @Inject - protected UserVmManager _userVmMgr; - @Inject protected AgentManager _agentMgr; @Inject protected TemplateManager _tmpltMgr; @@ -210,62 +199,40 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C @Inject protected HostDao _hostDao; @Inject - protected ConsoleProxyDao _consoleProxyDao; - @Inject protected SnapshotDao _snapshotDao; @Inject - protected SnapshotManager _snapMgr; - @Inject - protected SnapshotPolicyDao _snapshotPolicyDao; - @Inject protected StoragePoolHostDao _storagePoolHostDao; @Inject - protected AlertManager _alertMgr; - @Inject - protected VMTemplateHostDao _vmTemplateHostDao = null; - @Inject protected VMTemplatePoolDao _vmTemplatePoolDao = null; @Inject - protected VMTemplateSwiftDao _vmTemplateSwiftDao = null; - @Inject - protected VMTemplateS3Dao _vmTemplateS3Dao; - @Inject - protected S3Manager _s3Mgr; + protected VMTemplateZoneDao _vmTemplateZoneDao; @Inject protected VMTemplateDao _vmTemplateDao = null; @Inject - protected StoragePoolHostDao _poolHostDao = null; - @Inject - protected UserVmDao _userVmDao; - @Inject - VolumeHostDao _volumeHostDao; - @Inject protected VMInstanceDao _vmInstanceDao; @Inject protected PrimaryDataStoreDao _storagePoolDao = null; @Inject + protected ImageStoreDao _imageStoreDao = null; + @Inject + protected ImageStoreDetailsDao _imageStoreDetailsDao = null; + @Inject + protected SnapshotDataStoreDao _snapshotStoreDao = null; + @Inject + protected TemplateDataStoreDao _templateStoreDao = null; + @Inject + protected TemplateJoinDao _templateViewDao = null; + @Inject + protected VolumeDataStoreDao _volumeStoreDao = null; + @Inject protected CapacityDao _capacityDao; @Inject protected CapacityManager _capacityMgr; @Inject - protected DiskOfferingDao _diskOfferingDao; - @Inject - protected AccountDao _accountDao; - @Inject - protected EventDao _eventDao = null; - @Inject protected DataCenterDao _dcDao = null; @Inject - protected HostPodDao _podDao = null; - @Inject protected VMTemplateDao _templateDao; @Inject - protected VMTemplateHostDao _templateHostDao; - @Inject - protected ServiceOfferingDao _offeringDao; - @Inject - protected DomainDao _domainDao; - @Inject protected UserDao _userDao; @Inject protected ClusterDao _clusterDao; @@ -276,8 +243,6 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C @Inject protected VolumeDao _volumeDao; @Inject - protected SecondaryStorageVmManager _ssvmMgr; - @Inject ConfigurationDao _configDao; @Inject ManagementServer _msServer; @@ -290,36 +255,41 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C @Inject VolumeDataFactory volFactory; @Inject - ImageDataFactory tmplFactory; + TemplateDataFactory tmplFactory; @Inject SnapshotDataFactory snapshotFactory; @Inject - protected HypervisorCapabilitiesDao _hypervisorCapabilitiesDao; - @Inject ConfigurationServer _configServer; - - @Inject protected ResourceTagDao _resourceTagDao; - - + @Inject + DataStoreManager _dataStoreMgr; + @Inject + DataStoreProviderManager _dataStoreProviderMgr; + @Inject + private TemplateService _imageSrv; + @Inject + EndPointSelector _epSelector; protected List _storagePoolAllocators; + public List getStoragePoolAllocators() { - return _storagePoolAllocators; - } - public void setStoragePoolAllocators( - List _storagePoolAllocators) { - this._storagePoolAllocators = _storagePoolAllocators; - } + return _storagePoolAllocators; + } + + public void setStoragePoolAllocators(List _storagePoolAllocators) { + this._storagePoolAllocators = _storagePoolAllocators; + } protected List _discoverers; - public List getDiscoverers() { - return _discoverers; - } - public void setDiscoverers(List _discoverers) { - this._discoverers = _discoverers; - } - protected SearchBuilder HostTemplateStatesSearch; + public List getDiscoverers() { + return _discoverers; + } + + public void setDiscoverers(List _discoverers) { + this._discoverers = _discoverers; + } + + protected SearchBuilder HostTemplateStatesSearch; protected GenericSearchBuilder UpHostsInPoolSearch; protected SearchBuilder StoragePoolSearch; protected SearchBuilder LocalStorageSearch; @@ -334,7 +304,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C protected int _retry = 2; protected int _pingInterval = 60; // seconds protected int _hostRetry; - //protected BigDecimal _overProvisioningFactor = new BigDecimal(1); + // protected BigDecimal _overProvisioningFactor = new BigDecimal(1); private long _maxVolumeSizeInGb; private long _serverId; @@ -344,18 +314,14 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C private boolean _recreateSystemVmEnabled; - public boolean share(VMInstanceVO vm, List vols, HostVO host, - boolean cancelPreviousShare) throws StorageUnavailableException { + public boolean share(VMInstanceVO vm, List vols, HostVO host, boolean cancelPreviousShare) throws StorageUnavailableException { // if pool is in maintenance and it is the ONLY pool available; reject - List rootVolForGivenVm = _volsDao.findByInstanceAndType( - vm.getId(), Type.ROOT); + List rootVolForGivenVm = _volsDao.findByInstanceAndType(vm.getId(), Type.ROOT); if (rootVolForGivenVm != null && rootVolForGivenVm.size() > 0) { - boolean isPoolAvailable = isPoolAvailable(rootVolForGivenVm.get(0) - .getPoolId()); + boolean isPoolAvailable = isPoolAvailable(rootVolForGivenVm.get(0).getPoolId()); if (!isPoolAvailable) { - throw new StorageUnavailableException("Can not share " + vm, - rootVolForGivenVm.get(0).getPoolId()); + throw new StorageUnavailableException("Can not share " + vm, rootVolForGivenVm.get(0).getPoolId()); } } @@ -365,8 +331,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C // available for (VolumeVO vol : vols) { if (vol.getRemoved() != null) { - s_logger.warn("Volume id:" + vol.getId() - + " is removed, cannot share on this instance"); + s_logger.warn("Volume id:" + vol.getId() + " is removed, cannot share on this instance"); // not ok to share return false; } @@ -381,10 +346,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C List pools = _storagePoolDao.listAll(); // if no pools or 1 pool which is in maintenance - if (pools == null - || pools.size() == 0 - || (pools.size() == 1 && pools.get(0).getStatus() - .equals(StoragePoolStatus.Maintenance))) { + if (pools == null || pools.size() == 0 || (pools.size() == 1 && pools.get(0).getStatus().equals(StoragePoolStatus.Maintenance))) { return false; } else { return true; @@ -392,10 +354,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } @Override - public List ListByDataCenterHypervisor( - long datacenterId, HypervisorType type) { - List pools = _storagePoolDao - .listByDataCenterId(datacenterId); + public List ListByDataCenterHypervisor(long datacenterId, HypervisorType type) { + List pools = _storagePoolDao.listByDataCenterId(datacenterId); List retPools = new ArrayList(); for (StoragePoolVO pool : pools) { if (pool.getStatus() != StoragePoolStatus.Up) { @@ -412,35 +372,23 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C @Override public boolean isLocalStorageActiveOnHost(Long hostId) { - List storagePoolHostRefs = _storagePoolHostDao - .listByHostId(hostId); + List storagePoolHostRefs = _storagePoolHostDao.listByHostId(hostId); for (StoragePoolHostVO storagePoolHostRef : storagePoolHostRefs) { - StoragePoolVO PrimaryDataStoreVO = _storagePoolDao - .findById(storagePoolHostRef.getPoolId()); - if (PrimaryDataStoreVO.getPoolType() == StoragePoolType.LVM - || PrimaryDataStoreVO.getPoolType() == StoragePoolType.EXT) { - SearchBuilder volumeSB = _volsDao - .createSearchBuilder(); - volumeSB.and("poolId", volumeSB.entity().getPoolId(), - SearchCriteria.Op.EQ); - volumeSB.and("removed", volumeSB.entity().getRemoved(), - SearchCriteria.Op.NULL); + StoragePoolVO PrimaryDataStoreVO = _storagePoolDao.findById(storagePoolHostRef.getPoolId()); + if (PrimaryDataStoreVO.getPoolType() == StoragePoolType.LVM || PrimaryDataStoreVO.getPoolType() == StoragePoolType.EXT) { + SearchBuilder volumeSB = _volsDao.createSearchBuilder(); + volumeSB.and("poolId", volumeSB.entity().getPoolId(), SearchCriteria.Op.EQ); + volumeSB.and("removed", volumeSB.entity().getRemoved(), SearchCriteria.Op.NULL); volumeSB.and("state", volumeSB.entity().getState(), SearchCriteria.Op.NIN); - SearchBuilder activeVmSB = _vmInstanceDao - .createSearchBuilder(); - activeVmSB.and("state", activeVmSB.entity().getState(), - SearchCriteria.Op.IN); - volumeSB.join("activeVmSB", activeVmSB, volumeSB.entity() - .getInstanceId(), activeVmSB.entity().getId(), - JoinBuilder.JoinType.INNER); + SearchBuilder activeVmSB = _vmInstanceDao.createSearchBuilder(); + activeVmSB.and("state", activeVmSB.entity().getState(), SearchCriteria.Op.IN); + volumeSB.join("activeVmSB", activeVmSB, volumeSB.entity().getInstanceId(), activeVmSB.entity().getId(), JoinBuilder.JoinType.INNER); SearchCriteria volumeSC = volumeSB.create(); volumeSC.setParameters("poolId", PrimaryDataStoreVO.getId()); volumeSC.setParameters("state", Volume.State.Expunging, Volume.State.Destroy); - volumeSC.setJoinParameters("activeVmSB", "state", - State.Starting, State.Running, State.Stopping, - State.Migrating); + volumeSC.setJoinParameters("activeVmSB", "state", State.Starting, State.Running, State.Stopping, State.Migrating); List volumes = _volsDao.search(volumeSC, null); if (volumes.size() > 0) { @@ -453,39 +401,34 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } @Override - public StoragePool findStoragePool(DiskProfile dskCh, - final DataCenterVO dc, HostPodVO pod, Long clusterId, Long hostId, - VMInstanceVO vm, final Set avoid) { + public StoragePool findStoragePool(DiskProfile dskCh, final DataCenterVO dc, HostPodVO pod, Long clusterId, Long hostId, VMInstanceVO vm, + final Set avoid) { - VirtualMachineProfile profile = new VirtualMachineProfileImpl( - vm); + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); for (StoragePoolAllocator allocator : _storagePoolAllocators) { - ExcludeList avoidList = new ExcludeList(); - for(StoragePool pool : avoid){ - avoidList.addPool(pool.getId()); - } - DataCenterDeployment plan = new DataCenterDeployment(dc.getId(), pod.getId(), clusterId, hostId, null, null); + ExcludeList avoidList = new ExcludeList(); + for (StoragePool pool : avoid) { + avoidList.addPool(pool.getId()); + } + DataCenterDeployment plan = new DataCenterDeployment(dc.getId(), pod.getId(), clusterId, hostId, null, null); - final List poolList = allocator.allocateToPool(dskCh, profile, plan, avoidList, 1); - if (poolList != null && !poolList.isEmpty()) { - return (StoragePool)this.dataStoreMgr.getDataStore(poolList.get(0).getId(), DataStoreRole.Primary); - } + final List poolList = allocator.allocateToPool(dskCh, profile, plan, avoidList, 1); + if (poolList != null && !poolList.isEmpty()) { + return (StoragePool) this.dataStoreMgr.getDataStore(poolList.get(0).getId(), DataStoreRole.Primary); + } } return null; } @Override - public Answer[] sendToPool(StoragePool pool, Commands cmds) - throws StorageUnavailableException { + public Answer[] sendToPool(StoragePool pool, Commands cmds) throws StorageUnavailableException { return sendToPool(pool, null, null, cmds).second(); } @Override - public Answer sendToPool(StoragePool pool, long[] hostIdsToTryFirst, - Command cmd) throws StorageUnavailableException { - Answer[] answers = sendToPool(pool, hostIdsToTryFirst, null, - new Commands(cmd)).second(); + public Answer sendToPool(StoragePool pool, long[] hostIdsToTryFirst, Command cmd) throws StorageUnavailableException { + Answer[] answers = sendToPool(pool, hostIdsToTryFirst, null, new Commands(cmd)).second(); if (answers == null) { return null; } @@ -493,8 +436,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } @Override - public Answer sendToPool(StoragePool pool, Command cmd) - throws StorageUnavailableException { + public Answer sendToPool(StoragePool pool, Command cmd) throws StorageUnavailableException { Answer[] answers = sendToPool(pool, new Commands(cmd)); if (answers == null) { return null; @@ -502,15 +444,13 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C return answers[0]; } - public Long chooseHostForStoragePool(StoragePoolVO poolVO, - List avoidHosts, boolean sendToVmResidesOn, Long vmId) { + public Long chooseHostForStoragePool(StoragePoolVO poolVO, List avoidHosts, boolean sendToVmResidesOn, Long vmId) { if (sendToVmResidesOn) { if (vmId != null) { VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId); if (vmInstance != null) { Long hostId = vmInstance.getHostId(); - if (hostId != null - && !avoidHosts.contains(vmInstance.getHostId())) { + if (hostId != null && !avoidHosts.contains(vmInstance.getHostId())) { return hostId; } } @@ -521,8 +461,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C * cmd */ } - List poolHosts = _poolHostDao.listByHostStatus( - poolVO.getId(), Status.Up); + List poolHosts = _storagePoolHostDao.listByHostStatus(poolVO.getId(), Status.Up); Collections.shuffle(poolHosts); if (poolHosts != null && poolHosts.size() > 0) { for (StoragePoolHostVO sphvo : poolHosts) { @@ -537,130 +476,91 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C @Override public boolean configure(String name, Map params) throws ConfigurationException { - - Map configs = _configDao.getConfiguration( - "management-server", params); + Map configs = _configDao.getConfiguration("management-server", params); _retry = NumbersUtil.parseInt(configs.get(Config.StartRetry.key()), 10); _pingInterval = NumbersUtil.parseInt(configs.get("ping.interval"), 60); _hostRetry = NumbersUtil.parseInt(configs.get("host.retry"), 2); - _storagePoolAcquisitionWaitSeconds = NumbersUtil.parseInt( - configs.get("pool.acquisition.wait.seconds"), 1800); - s_logger.info("pool.acquisition.wait.seconds is configured as " - + _storagePoolAcquisitionWaitSeconds + " seconds"); + _storagePoolAcquisitionWaitSeconds = NumbersUtil.parseInt(configs.get("pool.acquisition.wait.seconds"), 1800); + s_logger.info("pool.acquisition.wait.seconds is configured as " + _storagePoolAcquisitionWaitSeconds + " seconds"); - _agentMgr.registerForHostEvents(new StoragePoolMonitor(this, - _storagePoolDao), true, false, true); + _agentMgr.registerForHostEvents(new StoragePoolMonitor(this, _storagePoolDao), true, false, true); String storageCleanupEnabled = configs.get("storage.cleanup.enabled"); - _storageCleanupEnabled = (storageCleanupEnabled == null) ? true - : Boolean.parseBoolean(storageCleanupEnabled); + _storageCleanupEnabled = (storageCleanupEnabled == null) ? true : Boolean.parseBoolean(storageCleanupEnabled); - String value = _configDao.getValue(Config.CreateVolumeFromSnapshotWait - .toString()); - _createVolumeFromSnapshotWait = NumbersUtil.parseInt(value, - Integer.parseInt(Config.CreateVolumeFromSnapshotWait - .getDefaultValue())); + String value = _configDao.getValue(Config.CreateVolumeFromSnapshotWait.toString()); + _createVolumeFromSnapshotWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.CreateVolumeFromSnapshotWait.getDefaultValue())); value = _configDao.getValue(Config.CopyVolumeWait.toString()); - _copyvolumewait = NumbersUtil.parseInt(value, - Integer.parseInt(Config.CopyVolumeWait.getDefaultValue())); + _copyvolumewait = NumbersUtil.parseInt(value, Integer.parseInt(Config.CopyVolumeWait.getDefaultValue())); value = _configDao.getValue(Config.RecreateSystemVmEnabled.key()); _recreateSystemVmEnabled = Boolean.parseBoolean(value); value = _configDao.getValue(Config.StorageTemplateCleanupEnabled.key()); - _templateCleanupEnabled = (value == null ? true : Boolean - .parseBoolean(value)); + _templateCleanupEnabled = (value == null ? true : Boolean.parseBoolean(value)); String time = configs.get("storage.cleanup.interval"); _storageCleanupInterval = NumbersUtil.parseInt(time, 86400); - s_logger.info("Storage cleanup enabled: " + _storageCleanupEnabled - + ", interval: " + _storageCleanupInterval + s_logger.info("Storage cleanup enabled: " + _storageCleanupEnabled + ", interval: " + _storageCleanupInterval + ", template cleanup enabled: " + _templateCleanupEnabled); String workers = configs.get("expunge.workers"); int wrks = NumbersUtil.parseInt(workers, 10); - _executor = Executors.newScheduledThreadPool(wrks, - new NamedThreadFactory("StorageManager-Scavenger")); + _executor = Executors.newScheduledThreadPool(wrks, new NamedThreadFactory("StorageManager-Scavenger")); - _agentMgr.registerForHostEvents( - ComponentContext.inject(LocalStoragePoolListener.class), true, - false, false); + _agentMgr.registerForHostEvents(ComponentContext.inject(LocalStoragePoolListener.class), true, false, false); - String maxVolumeSizeInGbString = _configDao - .getValue("storage.max.volume.size"); - _maxVolumeSizeInGb = NumbersUtil.parseLong(maxVolumeSizeInGbString, - 2000); + String maxVolumeSizeInGbString = _configDao.getValue("storage.max.volume.size"); + _maxVolumeSizeInGb = NumbersUtil.parseLong(maxVolumeSizeInGbString, 2000); - String _customDiskOfferingMinSizeStr = _configDao - .getValue(Config.CustomDiskOfferingMinSize.toString()); - _customDiskOfferingMinSize = NumbersUtil.parseInt( - _customDiskOfferingMinSizeStr, Integer - .parseInt(Config.CustomDiskOfferingMinSize - .getDefaultValue())); - - String _customDiskOfferingMaxSizeStr = _configDao - .getValue(Config.CustomDiskOfferingMaxSize.toString()); - _customDiskOfferingMaxSize = NumbersUtil.parseInt( - _customDiskOfferingMaxSizeStr, Integer - .parseInt(Config.CustomDiskOfferingMaxSize - .getDefaultValue())); + String _customDiskOfferingMinSizeStr = _configDao.getValue(Config.CustomDiskOfferingMinSize.toString()); + _customDiskOfferingMinSize = NumbersUtil.parseInt(_customDiskOfferingMinSizeStr, + Integer.parseInt(Config.CustomDiskOfferingMinSize.getDefaultValue())); + String _customDiskOfferingMaxSizeStr = _configDao.getValue(Config.CustomDiskOfferingMaxSize.toString()); + _customDiskOfferingMaxSize = NumbersUtil.parseInt(_customDiskOfferingMaxSizeStr, + Integer.parseInt(Config.CustomDiskOfferingMaxSize.getDefaultValue())); _serverId = _msServer.getId(); - UpHostsInPoolSearch = _storagePoolHostDao - .createSearchBuilder(Long.class); - UpHostsInPoolSearch.selectField(UpHostsInPoolSearch.entity() - .getHostId()); + UpHostsInPoolSearch = _storagePoolHostDao.createSearchBuilder(Long.class); + UpHostsInPoolSearch.selectField(UpHostsInPoolSearch.entity().getHostId()); SearchBuilder hostSearch = _hostDao.createSearchBuilder(); hostSearch.and("status", hostSearch.entity().getStatus(), Op.EQ); - hostSearch.and("resourceState", hostSearch.entity().getResourceState(), - Op.EQ); - UpHostsInPoolSearch.join("hosts", hostSearch, hostSearch.entity() - .getId(), UpHostsInPoolSearch.entity().getHostId(), - JoinType.INNER); - UpHostsInPoolSearch.and("pool", UpHostsInPoolSearch.entity() - .getPoolId(), Op.EQ); + hostSearch.and("resourceState", hostSearch.entity().getResourceState(), Op.EQ); + UpHostsInPoolSearch.join("hosts", hostSearch, hostSearch.entity().getId(), UpHostsInPoolSearch.entity().getHostId(), JoinType.INNER); + UpHostsInPoolSearch.and("pool", UpHostsInPoolSearch.entity().getPoolId(), Op.EQ); UpHostsInPoolSearch.done(); StoragePoolSearch = _vmInstanceDao.createSearchBuilder(); SearchBuilder volumeSearch = _volumeDao.createSearchBuilder(); - volumeSearch.and("volumeType", volumeSearch.entity().getVolumeType(), - SearchCriteria.Op.EQ); - volumeSearch.and("poolId", volumeSearch.entity().getPoolId(), - SearchCriteria.Op.EQ); + volumeSearch.and("volumeType", volumeSearch.entity().getVolumeType(), SearchCriteria.Op.EQ); + volumeSearch.and("poolId", volumeSearch.entity().getPoolId(), SearchCriteria.Op.EQ); volumeSearch.and("state", volumeSearch.entity().getState(), SearchCriteria.Op.EQ); - StoragePoolSearch.join("vmVolume", volumeSearch, volumeSearch.entity() - .getInstanceId(), StoragePoolSearch.entity().getId(), + StoragePoolSearch.join("vmVolume", volumeSearch, volumeSearch.entity().getInstanceId(), StoragePoolSearch.entity().getId(), JoinBuilder.JoinType.INNER); StoragePoolSearch.done(); LocalStorageSearch = _storagePoolDao.createSearchBuilder(); - SearchBuilder storageHostSearch = _storagePoolHostDao - .createSearchBuilder(); - storageHostSearch.and("hostId", storageHostSearch.entity().getHostId(), - SearchCriteria.Op.EQ); - LocalStorageSearch.join("poolHost", storageHostSearch, - storageHostSearch.entity().getPoolId(), LocalStorageSearch - .entity().getId(), JoinBuilder.JoinType.INNER); - LocalStorageSearch.and("type", LocalStorageSearch.entity() - .getPoolType(), SearchCriteria.Op.IN); + SearchBuilder storageHostSearch = _storagePoolHostDao.createSearchBuilder(); + storageHostSearch.and("hostId", storageHostSearch.entity().getHostId(), SearchCriteria.Op.EQ); + LocalStorageSearch.join("poolHost", storageHostSearch, storageHostSearch.entity().getPoolId(), LocalStorageSearch.entity().getId(), + JoinBuilder.JoinType.INNER); + LocalStorageSearch.and("type", LocalStorageSearch.entity().getPoolType(), SearchCriteria.Op.IN); LocalStorageSearch.done(); - Volume.State.getStateMachine().registerListener( new VolumeStateListener()); + Volume.State.getStateMachine().registerListener(new VolumeStateListener()); return true; } - @Override public String getStoragePoolTags(long poolId) { - return _configMgr.listToCsvTags(_storagePoolDao - .searchForStoragePoolDetails(poolId, "true")); + return _configMgr.listToCsvTags(_storagePoolDao.searchForStoragePoolDetails(poolId, "true")); } @Override @@ -668,8 +568,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C if (_storageCleanupEnabled) { Random generator = new Random(); int initialDelay = generator.nextInt(_storageCleanupInterval); - _executor.scheduleWithFixedDelay(new StorageGarbageCollector(), - initialDelay, _storageCleanupInterval, TimeUnit.SECONDS); + _executor.scheduleWithFixedDelay(new StorageGarbageCollector(), initialDelay, _storageCleanupInterval, TimeUnit.SECONDS); } else { s_logger.debug("Storage cleanup is not enabled, so the storage cleanup thread is not being scheduled."); } @@ -696,12 +595,16 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } DataStore store = null; try { - StoragePoolVO pool = _storagePoolDao.findPoolByHostPath(host.getDataCenterId(), host.getPodId(), pInfo.getHost(), pInfo.getHostPath(), pInfo.getUuid()); - if(pool == null && host.getHypervisorType() == HypervisorType.VMware) { - // perform run-time upgrade. In versions prior to 2.2.12, there is a bug that we don't save local datastore info (host path is empty), this will cause us - // not able to distinguish multiple local datastores that may be available on the host, to support smooth migration, we + StoragePoolVO pool = _storagePoolDao.findPoolByHostPath(host.getDataCenterId(), host.getPodId(), pInfo.getHost(), pInfo.getHostPath(), + pInfo.getUuid()); + if (pool == null && host.getHypervisorType() == HypervisorType.VMware) { + // perform run-time upgrade. In versions prior to 2.2.12, there + // is a bug that we don't save local datastore info (host path + // is empty), this will cause us + // not able to distinguish multiple local datastores that may be + // available on the host, to support smooth migration, we // need to perform runtime upgrade here - if(pInfo.getHostPath().length() > 0) { + if (pInfo.getHostPath().length() > 0) { pool = _storagePoolDao.findPoolByHostPath(host.getDataCenterId(), host.getPodId(), pInfo.getHost(), "", pInfo.getUuid()); } } @@ -722,35 +625,30 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C store = lifeCycle.initialize(params); } else { - store = (DataStore) dataStoreMgr.getDataStore(pool.getId(), - DataStoreRole.Primary); + store = (DataStore) dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary); } - HostScope scope = new HostScope(host.getId()); + HostScope scope = new HostScope(host.getId(), host.getDataCenterId()); lifeCycle.attachHost(store, scope, pInfo); } catch (Exception e) { s_logger.warn("Unable to setup the local storage pool for " + host, e); throw new ConnectionException(true, "Unable to setup the local storage pool for " + host, e); } - return (DataStore) dataStoreMgr.getDataStore(store.getId(), - DataStoreRole.Primary); + return (DataStore) dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Primary); } @Override @SuppressWarnings("rawtypes") - public PrimaryDataStoreInfo createPool(CreateStoragePoolCmd cmd) - throws ResourceInUseException, IllegalArgumentException, - UnknownHostException, ResourceUnavailableException { + public PrimaryDataStoreInfo createPool(CreateStoragePoolCmd cmd) throws ResourceInUseException, IllegalArgumentException, UnknownHostException, + ResourceUnavailableException { String providerName = cmd.getStorageProviderName(); - DataStoreProvider storeProvider = dataStoreProviderMgr - .getDataStoreProvider(providerName); + DataStoreProvider storeProvider = dataStoreProviderMgr.getDataStoreProvider(providerName); if (storeProvider == null) { storeProvider = dataStoreProviderMgr.getDefaultPrimaryDataStoreProvider(); if (storeProvider == null) { - throw new InvalidParameterValueException( - "can't find storage provider: " + providerName); + throw new InvalidParameterValueException("can't find storage provider: " + providerName); } } @@ -764,17 +662,14 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C try { scopeType = Enum.valueOf(ScopeType.class, scope.toUpperCase()); } catch (Exception e) { - throw new InvalidParameterValueException("invalid scope" - + scope); + throw new InvalidParameterValueException("invalid scope" + scope); } } if (scopeType == ScopeType.CLUSTER && clusterId == null) { - throw new InvalidParameterValueException( - "cluster id can't be null, if scope is cluster"); + throw new InvalidParameterValueException("cluster id can't be null, if scope is cluster"); } else if (scopeType == ScopeType.ZONE && zoneId == null) { - throw new InvalidParameterValueException( - "zone id can't be null, if scope is zone"); + throw new InvalidParameterValueException("zone id can't be null, if scope is zone"); } HypervisorType hypervisorType = HypervisorType.KVM; @@ -809,24 +704,19 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C Iterator it2 = d.entrySet().iterator(); while (it2.hasNext()) { Map.Entry entry = (Map.Entry) it2.next(); - details.put((String) entry.getKey(), - (String) entry.getValue()); + details.put((String) entry.getKey(), (String) entry.getValue()); } } } DataCenterVO zone = _dcDao.findById(cmd.getZoneId()); if (zone == null) { - throw new InvalidParameterValueException( - "unable to find zone by id " + zoneId); + throw new InvalidParameterValueException("unable to find zone by id " + zoneId); } // Check if zone is disabled Account account = UserContext.current().getCaller(); - if (Grouping.AllocationState.Disabled == zone.getAllocationState() - && !_accountMgr.isRootAdmin(account.getType())) { - throw new PermissionDeniedException( - "Cannot perform this operation, Zone is currently disabled: " - + zoneId); + if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(account.getType())) { + throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: " + zoneId); } Map params = new HashMap(); @@ -845,8 +735,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C store = lifeCycle.initialize(params); if (scopeType == ScopeType.CLUSTER) { - ClusterScope clusterScope = new ClusterScope(clusterId, podId, - zoneId); + ClusterScope clusterScope = new ClusterScope(clusterId, podId, zoneId); lifeCycle.attachCluster(store, clusterScope); } else if (scopeType == ScopeType.ZONE) { ZoneScope zoneScope = new ZoneScope(zoneId); @@ -857,21 +746,18 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C throw new CloudRuntimeException("Failed to add data store", e); } - return (PrimaryDataStoreInfo) dataStoreMgr.getDataStore(store.getId(), - DataStoreRole.Primary); + return (PrimaryDataStoreInfo) dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Primary); } @Override - public PrimaryDataStoreInfo updateStoragePool(UpdateStoragePoolCmd cmd) - throws IllegalArgumentException { + public PrimaryDataStoreInfo updateStoragePool(UpdateStoragePoolCmd cmd) throws IllegalArgumentException { // Input validation Long id = cmd.getId(); List tags = cmd.getTags(); StoragePoolVO pool = _storagePoolDao.findById(id); if (pool == null) { - throw new IllegalArgumentException( - "Unable to find storage pool with ID: " + id); + throw new IllegalArgumentException("Unable to find storage pool with ID: " + id); } if (tags != null) { @@ -886,8 +772,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C _storagePoolDao.updateDetails(id, details); } - return (PrimaryDataStoreInfo) dataStoreMgr.getDataStore(pool.getId(), - DataStoreRole.Primary); + return (PrimaryDataStoreInfo) dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary); } @Override @@ -899,30 +784,23 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C StoragePoolVO sPool = _storagePoolDao.findById(id); if (sPool == null) { s_logger.warn("Unable to find pool:" + id); - throw new InvalidParameterValueException( - "Unable to find pool by id " + id); + throw new InvalidParameterValueException("Unable to find pool by id " + id); } if (sPool.getStatus() != StoragePoolStatus.Maintenance) { - s_logger.warn("Unable to delete storage id: " + id - + " due to it is not in Maintenance state"); - throw new InvalidParameterValueException( - "Unable to delete storage due to it is not in Maintenance state, id: " - + id); + s_logger.warn("Unable to delete storage id: " + id + " due to it is not in Maintenance state"); + throw new InvalidParameterValueException("Unable to delete storage due to it is not in Maintenance state, id: " + id); } if (sPool.isLocal()) { s_logger.warn("Unable to delete local storage id:" + id); - throw new InvalidParameterValueException( - "Unable to delete local storage id: " + id); + throw new InvalidParameterValueException("Unable to delete local storage id: " + id); } Pair vlms = _volsDao.getCountAndTotalByPool(id); if (forced) { if (vlms.first() > 0) { - Pair nonDstrdVlms = _volsDao - .getNonDestroyedCountAndTotalByPool(id); + Pair nonDstrdVlms = _volsDao.getNonDestroyedCountAndTotalByPool(id); if (nonDstrdVlms.first() > 0) { - throw new CloudRuntimeException("Cannot delete pool " - + sPool.getName() + " as there are associated " + throw new CloudRuntimeException("Cannot delete pool " + sPool.getName() + " as there are associated " + "non-destroyed vols for this pool"); } // force expunge non-destroyed volumes @@ -942,20 +820,16 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C // Check if the pool has associated volumes in the volumes table // If it does , then you cannot delete the pool if (vlms.first() > 0) { - throw new CloudRuntimeException("Cannot delete pool " - + sPool.getName() + " as there are associated vols" - + " for this pool"); + throw new CloudRuntimeException("Cannot delete pool " + sPool.getName() + " as there are associated vols" + " for this pool"); } } // First get the host_id from storage_pool_host_ref for given pool id - StoragePoolVO lock = _storagePoolDao.acquireInLockTable(sPool - .getId()); + StoragePoolVO lock = _storagePoolDao.acquireInLockTable(sPool.getId()); if (lock == null) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Failed to acquire lock when deleting PrimaryDataStoreVO with ID: " - + sPool.getId()); + s_logger.debug("Failed to acquire lock when deleting PrimaryDataStoreVO with ID: " + sPool.getId()); } return false; } @@ -963,30 +837,27 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C _storagePoolDao.releaseFromLockTable(lock.getId()); s_logger.trace("Released lock for storage pool " + id); - DataStoreProvider storeProvider = dataStoreProviderMgr - .getDataStoreProvider(sPool.getStorageProviderName()); + DataStoreProvider storeProvider = dataStoreProviderMgr.getDataStoreProvider(sPool.getStorageProviderName()); DataStoreLifeCycle lifeCycle = storeProvider.getDataStoreLifeCycle(); - DataStore store = dataStoreMgr.getDataStore( - sPool.getId(), DataStoreRole.Primary); + DataStore store = dataStoreMgr.getDataStore(sPool.getId(), DataStoreRole.Primary); return lifeCycle.deleteDataStore(store); } @Override - public void connectHostToSharedPool(long hostId, long poolId) - throws StorageUnavailableException { - StoragePool pool = (StoragePool)this.dataStoreMgr.getDataStore(poolId, DataStoreRole.Primary); + public void connectHostToSharedPool(long hostId, long poolId) throws StorageUnavailableException { + StoragePool pool = (StoragePool) this.dataStoreMgr.getDataStore(poolId, DataStoreRole.Primary); assert (pool.isShared()) : "Now, did you actually read the name of this method?"; s_logger.debug("Adding pool " + pool.getName() + " to host " + hostId); - DataStoreProvider provider = dataStoreProviderMgr - .getDataStoreProvider(pool.getStorageProviderName()); + DataStoreProvider provider = dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName()); HypervisorHostListener listener = hostListeners.get(provider.getName()); listener.hostConnect(hostId, pool.getId()); } @Override - public BigDecimal getStorageOverProvisioningFactor(Long dcId){ - return new BigDecimal(_configServer.getConfigValue(Config.StorageOverprovisioningFactor.key(), Config.ConfigurationParameterScope.zone.toString(), dcId)); + public BigDecimal getStorageOverProvisioningFactor(Long dcId) { + return new BigDecimal(_configServer.getConfigValue(Config.StorageOverprovisioningFactor.key(), + Config.ConfigurationParameterScope.zone.toString(), dcId)); } @Override @@ -1001,13 +872,24 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C long totalOverProvCapacity; if (storagePool.getPoolType() == StoragePoolType.NetworkFilesystem) { BigDecimal overProvFactor = getStorageOverProvisioningFactor(storagePool.getDataCenterId()); - totalOverProvCapacity = overProvFactor.multiply(new BigDecimal(storagePool.getCapacityBytes())).longValue();// All this for the inaccuracy of floats for big number multiplication. + totalOverProvCapacity = overProvFactor.multiply(new BigDecimal(storagePool.getCapacityBytes())).longValue();// All + // this + // for + // the + // inaccuracy + // of + // floats + // for + // big + // number + // multiplication. } else { totalOverProvCapacity = storagePool.getCapacityBytes(); } if (capacities.size() == 0) { - CapacityVO capacity = new CapacityVO(storagePool.getId(), storagePool.getDataCenterId(), storagePool.getPodId(), storagePool.getClusterId(), allocated, totalOverProvCapacity, capacityType); + CapacityVO capacity = new CapacityVO(storagePool.getId(), storagePool.getDataCenterId(), storagePool.getPodId(), + storagePool.getClusterId(), allocated, totalOverProvCapacity, capacityType); AllocationState allocationState = null; if (storagePool.getScope() == ScopeType.ZONE) { DataCenterVO dc = ApiDBUtils.findZoneById(storagePool.getDataCenterId()); @@ -1015,8 +897,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } else { allocationState = _configMgr.findClusterAllocationState(ApiDBUtils.findClusterById(storagePool.getClusterId())); } - CapacityState capacityState = (allocationState == AllocationState.Disabled) ? - CapacityState.Disabled : CapacityState.Enabled; + CapacityState capacityState = (allocationState == AllocationState.Disabled) ? CapacityState.Disabled : CapacityState.Enabled; capacity.setCapacityState(capacityState); _capacityDao.persist(capacity); @@ -1049,7 +930,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } @Override - public Pair sendToPool(StoragePool pool, long[] hostIdsToTryFirst, List hostIdsToAvoid, Commands cmds) throws StorageUnavailableException { + public Pair sendToPool(StoragePool pool, long[] hostIdsToTryFirst, List hostIdsToAvoid, Commands cmds) + throws StorageUnavailableException { List hostIds = getUpHostsInPool(pool.getId()); Collections.shuffle(hostIds); if (hostIdsToTryFirst != null) { @@ -1064,7 +946,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C hostIds.removeAll(hostIdsToAvoid); } if (hostIds == null || hostIds.isEmpty()) { - throw new StorageUnavailableException("Unable to send command to the pool " + pool.getId() + " due to there is no enabled hosts up in this cluster", pool.getId()); + throw new StorageUnavailableException("Unable to send command to the pool " + pool.getId() + + " due to there is no enabled hosts up in this cluster", pool.getId()); } for (Long hostId : hostIds) { try { @@ -1087,7 +970,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } @Override - public Pair sendToPool(StoragePool pool, long[] hostIdsToTryFirst, List hostIdsToAvoid, Command cmd) throws StorageUnavailableException { + public Pair sendToPool(StoragePool pool, long[] hostIdsToTryFirst, List hostIdsToAvoid, Command cmd) + throws StorageUnavailableException { Commands cmds = new Commands(cmd); Pair result = sendToPool(pool, hostIdsToTryFirst, hostIdsToAvoid, cmds); return new Pair(result.first(), result.second()[0]); @@ -1107,17 +991,20 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C try { List unusedTemplatesInPool = _tmpltMgr.getUnusedTemplatesInPool(pool); - s_logger.debug("Storage pool garbage collector found " + unusedTemplatesInPool.size() + " templates to clean up in storage pool: " + pool.getName()); + s_logger.debug("Storage pool garbage collector found " + unusedTemplatesInPool.size() + + " templates to clean up in storage pool: " + pool.getName()); for (VMTemplateStoragePoolVO templatePoolVO : unusedTemplatesInPool) { if (templatePoolVO.getDownloadState() != VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { - s_logger.debug("Storage pool garbage collector is skipping templatePoolVO with ID: " + templatePoolVO.getId() + " because it is not completely downloaded."); + s_logger.debug("Storage pool garbage collector is skipping templatePoolVO with ID: " + templatePoolVO.getId() + + " because it is not completely downloaded."); continue; } if (!templatePoolVO.getMarkedForGC()) { templatePoolVO.setMarkedForGC(true); _vmTemplatePoolDao.update(templatePoolVO.getId(), templatePoolVO); - s_logger.debug("Storage pool garbage collector has marked templatePoolVO with ID: " + templatePoolVO.getId() + " for garbage collection."); + s_logger.debug("Storage pool garbage collector has marked templatePoolVO with ID: " + templatePoolVO.getId() + + " for garbage collection."); continue; } @@ -1129,7 +1016,6 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } } - cleanupSecondaryStorage(recurring); List vols = _volsDao.listVolumesToBeDestroyed(); @@ -1143,44 +1029,42 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } } - // remove snapshots in Error state List snapshots = _snapshotDao.listAllByStatus(Snapshot.State.Error); for (SnapshotVO snapshotVO : snapshots) { - try{ + try { _snapshotDao.expunge(snapshotVO.getId()); - }catch (Exception e) { + } catch (Exception e) { s_logger.warn("Unable to destroy " + snapshotVO.getId(), e); } } - }finally { + } finally { scanLock.unlock(); } } - }finally { + } finally { scanLock.releaseRef(); } } @DB - List findAllVolumeIdInSnapshotTable(Long hostId) { - String sql = "SELECT volume_id from snapshots WHERE sechost_id=? GROUP BY volume_id"; + List findAllVolumeIdInSnapshotTable(Long storeId) { + String sql = "SELECT volume_id from snapshots, snapshot_store_ref WHERE snapshots.id = snapshot_store_ref.snapshot_id and store_id=? GROUP BY volume_id"; List list = new ArrayList(); try { Transaction txn = Transaction.currentTxn(); ResultSet rs = null; PreparedStatement pstmt = null; pstmt = txn.prepareAutoCloseStatement(sql); - pstmt.setLong(1, hostId); + pstmt.setLong(1, storeId); rs = pstmt.executeQuery(); while (rs.next()) { list.add(rs.getLong(1)); } return list; } catch (Exception e) { - s_logger.debug("failed to get all volumes who has snapshots in secondary storage " - + hostId + " due to " + e.getMessage()); + s_logger.debug("failed to get all volumes who has snapshots in secondary storage " + storeId + " due to " + e.getMessage()); return null; } @@ -1201,8 +1085,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } return list; } catch (Exception e) { - s_logger.debug("failed to get all snapshots for a volume " - + volumeId + " due to " + e.getMessage()); + s_logger.debug("failed to get all snapshots for a volume " + volumeId + " due to " + e.getMessage()); return null; } } @@ -1212,177 +1095,130 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C public void cleanupSecondaryStorage(boolean recurring) { try { // Cleanup templates in secondary storage hosts - List secondaryStorageHosts = _ssvmMgr - .listSecondaryStorageHostsInAllZones(); - for (HostVO secondaryStorageHost : secondaryStorageHosts) { + List imageStores = this.dataStoreMgr.getImageStoresByScope(new ZoneScope(null)); + for (DataStore store : imageStores) { try { - long hostId = secondaryStorageHost.getId(); - List destroyedTemplateHostVOs = _vmTemplateHostDao - .listDestroyed(hostId); - s_logger.debug("Secondary storage garbage collector found " - + destroyedTemplateHostVOs.size() - + " templates to cleanup on secondary storage host: " - + secondaryStorageHost.getName()); - for (VMTemplateHostVO destroyedTemplateHostVO : destroyedTemplateHostVOs) { - if (!_tmpltMgr - .templateIsDeleteable(destroyedTemplateHostVO)) { + long storeId = store.getId(); + List destroyedTemplateStoreVOs = this._templateStoreDao.listDestroyed(storeId); + s_logger.debug("Secondary storage garbage collector found " + destroyedTemplateStoreVOs.size() + + " templates to cleanup on secondary storage host: " + store.getName()); + for (TemplateDataStoreVO destroyedTemplateStoreVO : destroyedTemplateStoreVOs) { + if (!_tmpltMgr.templateIsDeleteable(destroyedTemplateStoreVO.getTemplateId())) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Not deleting template at: " - + destroyedTemplateHostVO); + s_logger.debug("Not deleting template at: " + destroyedTemplateStoreVO); } continue; } if (s_logger.isDebugEnabled()) { - s_logger.debug("Deleting template host: " - + destroyedTemplateHostVO); + s_logger.debug("Deleting template store: " + destroyedTemplateStoreVO); } - String installPath = destroyedTemplateHostVO - .getInstallPath(); + VMTemplateVO destroyedTemplate = this._vmTemplateDao.findById(destroyedTemplateStoreVO.getTemplateId()); + if (destroyedTemplate == null) { + s_logger.error("Cannot find template : " + destroyedTemplateStoreVO.getTemplateId() + " from template table"); + throw new CloudRuntimeException("Template " + destroyedTemplateStoreVO.getTemplateId() + + " is found in secondary storage, but not found in template table"); + } + String installPath = destroyedTemplateStoreVO.getInstallPath(); + TemplateInfo tmpl = tmplFactory.getTemplate(destroyedTemplateStoreVO.getTemplateId(), store); if (installPath != null) { - Answer answer = _agentMgr.sendToSecStorage( - secondaryStorageHost, - new DeleteTemplateCommand( - secondaryStorageHost - .getStorageUrl(), - destroyedTemplateHostVO - .getInstallPath())); + EndPoint ep = _epSelector.select(store); + Command cmd = new DeleteCommand(tmpl.getTO()); + Answer answer = ep.sendMessage(cmd); if (answer == null || !answer.getResult()) { - s_logger.debug("Failed to delete " - + destroyedTemplateHostVO - + " due to " - + ((answer == null) ? "answer is null" - : answer.getDetails())); + s_logger.debug("Failed to delete " + destroyedTemplateStoreVO + " due to " + + ((answer == null) ? "answer is null" : answer.getDetails())); } else { - _vmTemplateHostDao - .remove(destroyedTemplateHostVO.getId()); - s_logger.debug("Deleted template at: " - + destroyedTemplateHostVO - .getInstallPath()); + _templateStoreDao.remove(destroyedTemplateStoreVO.getId()); + s_logger.debug("Deleted template at: " + destroyedTemplateStoreVO.getInstallPath()); } } else { - _vmTemplateHostDao.remove(destroyedTemplateHostVO - .getId()); + _templateStoreDao.remove(destroyedTemplateStoreVO.getId()); } } } catch (Exception e) { - s_logger.warn( - "problem cleaning up templates in secondary storage " - + secondaryStorageHost, e); + s_logger.warn("problem cleaning up templates in secondary storage store " + store.getName(), e); } } - // Cleanup snapshot in secondary storage hosts - for (HostVO secondaryStorageHost : secondaryStorageHosts) { + // CleanUp snapshots on Secondary Storage. + for (DataStore store : imageStores) { try { - long hostId = secondaryStorageHost.getId(); - List vIDs = findAllVolumeIdInSnapshotTable(hostId); - if (vIDs == null) { - continue; - } - for (Long volumeId : vIDs) { - boolean lock = false; - try { - VolumeVO volume = _volsDao - .findByIdIncludingRemoved(volumeId); - if (volume.getRemoved() == null) { - volume = _volsDao.acquireInLockTable(volumeId, - 10); - if (volume == null) { - continue; - } - lock = true; - } - List snapshots = findAllSnapshotForVolume(volumeId); - if (snapshots == null) { - continue; - } - CleanupSnapshotBackupCommand cmd = new CleanupSnapshotBackupCommand( - secondaryStorageHost.getStorageUrl(), - secondaryStorageHost.getDataCenterId(), - volume.getAccountId(), volumeId, snapshots); + List destroyedSnapshotStoreVOs = _snapshotStoreDao.listDestroyed(store.getId()); + s_logger.debug("Secondary storage garbage collector found " + destroyedSnapshotStoreVOs.size() + + " snapshots to cleanup on secondary storage host: " + store.getName()); + for (SnapshotDataStoreVO destroyedSnapshotStoreVO : destroyedSnapshotStoreVOs) { + // check if this snapshot has child + SnapshotInfo snap = snapshotFactory.getSnapshot(destroyedSnapshotStoreVO.getSnapshotId(), store); + if ( snap.getChild() != null ){ + s_logger.debug("Skip snapshot on store: " + destroyedSnapshotStoreVO + " , because it has child"); + continue; + } - Answer answer = _agentMgr.sendToSecStorage( - secondaryStorageHost, cmd); - if ((answer == null) || !answer.getResult()) { - String details = "Failed to cleanup snapshots for volume " - + volumeId - + " due to " - + (answer == null ? "null" : answer - .getDetails()); - s_logger.warn(details); - } - } catch (Exception e1) { - s_logger.warn( - "problem cleaning up snapshots in secondary storage " - + secondaryStorageHost, e1); - } finally { - if (lock) { - _volsDao.releaseFromLockTable(volumeId); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Deleting snapshot on store: " + destroyedSnapshotStoreVO); + } + + String installPath = destroyedSnapshotStoreVO.getInstallPath(); + + if (installPath != null) { + EndPoint ep = _epSelector.select(store); + DeleteCommand cmd = new DeleteCommand(snap.getTO()); + Answer answer = ep.sendMessage(cmd); + if (answer == null || !answer.getResult()) { + s_logger.debug("Failed to delete " + destroyedSnapshotStoreVO + " due to " + + ((answer == null) ? "answer is null" : answer.getDetails())); + } else { + _volumeStoreDao.remove(destroyedSnapshotStoreVO.getId()); + s_logger.debug("Deleted snapshot at: " + destroyedSnapshotStoreVO.getInstallPath()); } + } else { + _snapshotStoreDao.remove(destroyedSnapshotStoreVO.getId()); } } + } catch (Exception e2) { - s_logger.warn( - "problem cleaning up snapshots in secondary storage " - + secondaryStorageHost, e2); + s_logger.warn("problem cleaning up snapshots in secondary storage store " + store.getName(), e2); } + } // CleanUp volumes on Secondary Storage. - for (HostVO secondaryStorageHost : secondaryStorageHosts) { + for (DataStore store : imageStores) { try { - long hostId = secondaryStorageHost.getId(); - List destroyedVolumeHostVOs = _volumeHostDao - .listDestroyed(hostId); - s_logger.debug("Secondary storage garbage collector found " - + destroyedVolumeHostVOs.size() - + " templates to cleanup on secondary storage host: " - + secondaryStorageHost.getName()); - for (VolumeHostVO destroyedVolumeHostVO : destroyedVolumeHostVOs) { + List destroyedStoreVOs = _volumeStoreDao.listDestroyed(store.getId()); + s_logger.debug("Secondary storage garbage collector found " + destroyedStoreVOs.size() + + " volumes to cleanup on secondary storage host: " + store.getName()); + for (VolumeDataStoreVO destroyedStoreVO : destroyedStoreVOs) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Deleting volume host: " - + destroyedVolumeHostVO); + s_logger.debug("Deleting volume on store: " + destroyedStoreVO); } - String installPath = destroyedVolumeHostVO - .getInstallPath(); + String installPath = destroyedStoreVO.getInstallPath(); + + VolumeInfo vol = this.volFactory.getVolume(destroyedStoreVO.getVolumeId(), store); if (installPath != null) { - Answer answer = _agentMgr.sendToSecStorage( - secondaryStorageHost, - new DeleteVolumeCommand( - secondaryStorageHost - .getStorageUrl(), - destroyedVolumeHostVO - .getInstallPath())); - + EndPoint ep = _epSelector.select(store); + DeleteCommand cmd = new DeleteCommand(vol.getTO()); + Answer answer = ep.sendMessage(cmd); if (answer == null || !answer.getResult()) { - s_logger.debug("Failed to delete " - + destroyedVolumeHostVO - + " due to " - + ((answer == null) ? "answer is null" - : answer.getDetails())); + s_logger.debug("Failed to delete " + destroyedStoreVO + " due to " + + ((answer == null) ? "answer is null" : answer.getDetails())); } else { - _volumeHostDao.remove(destroyedVolumeHostVO - .getId()); - s_logger.debug("Deleted volume at: " - + destroyedVolumeHostVO - .getInstallPath()); + _volumeStoreDao.remove(destroyedStoreVO.getId()); + s_logger.debug("Deleted volume at: " + destroyedStoreVO.getInstallPath()); } } else { - _volumeHostDao - .remove(destroyedVolumeHostVO.getId()); + _volumeStoreDao.remove(destroyedStoreVO.getId()); } } } catch (Exception e2) { - s_logger.warn( - "problem cleaning up volumes in secondary storage " - + secondaryStorageHost, e2); + s_logger.warn("problem cleaning up volumes in secondary storage store " + store.getName(), e2); } } } catch (Exception e3) { @@ -1397,16 +1233,14 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C // poolId is null only if volume is destroyed, which has been checked // before. assert poolId != null; - StoragePoolVO PrimaryDataStoreVO = _storagePoolDao - .findById(poolId); + StoragePoolVO PrimaryDataStoreVO = _storagePoolDao.findById(poolId); assert PrimaryDataStoreVO != null; return PrimaryDataStoreVO.getUuid(); } @Override @DB - public PrimaryDataStoreInfo preparePrimaryStorageForMaintenance( - Long primaryStorageId) throws ResourceUnavailableException, + public PrimaryDataStoreInfo preparePrimaryStorageForMaintenance(Long primaryStorageId) throws ResourceUnavailableException, InsufficientCapacityException { Long userId = UserContext.current().getCallerUserId(); User user = _userDao.findById(userId); @@ -1423,43 +1257,31 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C throw new InvalidParameterValueException(msg); } - List spes = _storagePoolDao.listBy( - primaryStorage.getDataCenterId(), primaryStorage.getPodId(), - primaryStorage.getClusterId(), ScopeType.CLUSTER); + List spes = _storagePoolDao.listBy(primaryStorage.getDataCenterId(), primaryStorage.getPodId(), primaryStorage.getClusterId(), + ScopeType.CLUSTER); for (StoragePoolVO sp : spes) { if (sp.getStatus() == StoragePoolStatus.PrepareForMaintenance) { - throw new CloudRuntimeException( - "Only one storage pool in a cluster can be in PrepareForMaintenance mode, " - + sp.getId() - + " is already in PrepareForMaintenance mode "); + throw new CloudRuntimeException("Only one storage pool in a cluster can be in PrepareForMaintenance mode, " + sp.getId() + + " is already in PrepareForMaintenance mode "); } } - if (!primaryStorage.getStatus().equals(StoragePoolStatus.Up) - && !primaryStorage.getStatus().equals( - StoragePoolStatus.ErrorInMaintenance)) { - throw new InvalidParameterValueException("Primary storage with id " - + primaryStorageId - + " is not ready for migration, as the status is:" + if (!primaryStorage.getStatus().equals(StoragePoolStatus.Up) && !primaryStorage.getStatus().equals(StoragePoolStatus.ErrorInMaintenance)) { + throw new InvalidParameterValueException("Primary storage with id " + primaryStorageId + " is not ready for migration, as the status is:" + primaryStorage.getStatus().toString()); } - DataStoreProvider provider = dataStoreProviderMgr - .getDataStoreProvider(primaryStorage.getStorageProviderName()); + DataStoreProvider provider = dataStoreProviderMgr.getDataStoreProvider(primaryStorage.getStorageProviderName()); DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle(); - DataStore store = dataStoreMgr.getDataStore( - primaryStorage.getId(), DataStoreRole.Primary); + DataStore store = dataStoreMgr.getDataStore(primaryStorage.getId(), DataStoreRole.Primary); lifeCycle.maintain(store); - return (PrimaryDataStoreInfo) dataStoreMgr.getDataStore( - primaryStorage.getId(), DataStoreRole.Primary); + return (PrimaryDataStoreInfo) dataStoreMgr.getDataStore(primaryStorage.getId(), DataStoreRole.Primary); } @Override @DB - public PrimaryDataStoreInfo cancelPrimaryStorageForMaintenance( - CancelPrimaryStorageMaintenanceCmd cmd) - throws ResourceUnavailableException { + public PrimaryDataStoreInfo cancelPrimaryStorageForMaintenance(CancelPrimaryStorageMaintenanceCmd cmd) throws ResourceUnavailableException { Long primaryStorageId = cmd.getId(); Long userId = UserContext.current().getCallerUserId(); User user = _userDao.findById(userId); @@ -1474,24 +1296,17 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C throw new InvalidParameterValueException(msg); } - if (primaryStorage.getStatus().equals(StoragePoolStatus.Up) - || primaryStorage.getStatus().equals( - StoragePoolStatus.PrepareForMaintenance)) { - throw new StorageUnavailableException("Primary storage with id " - + primaryStorageId - + " is not ready to complete migration, as the status is:" - + primaryStorage.getStatus().toString(), primaryStorageId); + if (primaryStorage.getStatus().equals(StoragePoolStatus.Up) || primaryStorage.getStatus().equals(StoragePoolStatus.PrepareForMaintenance)) { + throw new StorageUnavailableException("Primary storage with id " + primaryStorageId + + " is not ready to complete migration, as the status is:" + primaryStorage.getStatus().toString(), primaryStorageId); } - DataStoreProvider provider = dataStoreProviderMgr - .getDataStoreProvider(primaryStorage.getStorageProviderName()); + DataStoreProvider provider = dataStoreProviderMgr.getDataStoreProvider(primaryStorage.getStorageProviderName()); DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle(); - DataStore store = dataStoreMgr.getDataStore( - primaryStorage.getId(), DataStoreRole.Primary); + DataStore store = dataStoreMgr.getDataStore(primaryStorage.getId(), DataStoreRole.Primary); lifeCycle.cancelMaintain(store); - return (PrimaryDataStoreInfo) dataStoreMgr.getDataStore( - primaryStorage.getId(), DataStoreRole.Primary); + return (PrimaryDataStoreInfo) dataStoreMgr.getDataStore(primaryStorage.getId(), DataStoreRole.Primary); } protected class StorageGarbageCollector implements Runnable { @@ -1513,35 +1328,26 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } @Override - public void onManagementNodeJoined(List nodeList, - long selfNodeId) { + public void onManagementNodeJoined(List nodeList, long selfNodeId) { // TODO Auto-generated method stub } @Override - public void onManagementNodeLeft(List nodeList, - long selfNodeId) { + public void onManagementNodeLeft(List nodeList, long selfNodeId) { for (ManagementServerHostVO vo : nodeList) { if (vo.getMsid() == _serverId) { - s_logger.info("Cleaning up storage maintenance jobs associated with Management server" - + vo.getMsid()); - List poolIds = _storagePoolWorkDao - .searchForPoolIdsForPendingWorkJobs(vo.getMsid()); + s_logger.info("Cleaning up storage maintenance jobs associated with Management server" + vo.getMsid()); + List poolIds = _storagePoolWorkDao.searchForPoolIdsForPendingWorkJobs(vo.getMsid()); if (poolIds.size() > 0) { for (Long poolId : poolIds) { - StoragePoolVO pool = _storagePoolDao - .findById(poolId); + StoragePoolVO pool = _storagePoolDao.findById(poolId); // check if pool is in an inconsistent state if (pool != null - && (pool.getStatus().equals( - StoragePoolStatus.ErrorInMaintenance) - || pool.getStatus() - .equals(StoragePoolStatus.PrepareForMaintenance) || pool - .getStatus() - .equals(StoragePoolStatus.CancelMaintenance))) { - _storagePoolWorkDao.removePendingJobsOnMsRestart( - vo.getMsid(), poolId); + && (pool.getStatus().equals(StoragePoolStatus.ErrorInMaintenance) + || pool.getStatus().equals(StoragePoolStatus.PrepareForMaintenance) || pool.getStatus().equals( + StoragePoolStatus.CancelMaintenance))) { + _storagePoolWorkDao.removePendingJobsOnMsRestart(vo.getMsid(), poolId); pool.setStatus(StoragePoolStatus.ErrorInMaintenance); _storagePoolDao.update(poolId, pool); } @@ -1563,35 +1369,34 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId); } - List hosts = new ArrayList(); + List hosts = new ArrayList(); if (hostId != null) { - hosts.add(ApiDBUtils.findHostById(hostId)); + hosts.add(hostId); } else { - hosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(zoneId); + List stores = this._dataStoreMgr.getImageStoresByScope(new ZoneScope(zoneId)); + if (stores != null) { + for (DataStore store : stores) { + hosts.add(store.getId()); + } + } } - CapacityVO capacity = new CapacityVO(hostId, zoneId, null, null, 0, 0, - CapacityVO.CAPACITY_TYPE_SECONDARY_STORAGE); - for (HostVO host : hosts) { - StorageStats stats = ApiDBUtils.getSecondaryStorageStatistics(host - .getId()); + CapacityVO capacity = new CapacityVO(hostId, zoneId, null, null, 0, 0, CapacityVO.CAPACITY_TYPE_SECONDARY_STORAGE); + for (Long id : hosts) { + StorageStats stats = ApiDBUtils.getSecondaryStorageStatistics(id); if (stats == null) { continue; } - capacity.setUsedCapacity(stats.getByteUsed() - + capacity.getUsedCapacity()); - capacity.setTotalCapacity(stats.getCapacityBytes() - + capacity.getTotalCapacity()); + capacity.setUsedCapacity(stats.getByteUsed() + capacity.getUsedCapacity()); + capacity.setTotalCapacity(stats.getCapacityBytes() + capacity.getTotalCapacity()); } return capacity; } @Override - public CapacityVO getStoragePoolUsedStats(Long poolId, Long clusterId, - Long podId, Long zoneId) { - SearchCriteria sc = _storagePoolDao - .createSearchCriteria(); + public CapacityVO getStoragePoolUsedStats(Long poolId, Long clusterId, Long podId, Long zoneId) { + SearchCriteria sc = _storagePoolDao.createSearchCriteria(); List pools = new ArrayList(); if (zoneId != null) { @@ -1615,30 +1420,23 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C pools = _storagePoolDao.search(sc, null); } - CapacityVO capacity = new CapacityVO(poolId, zoneId, podId, clusterId, - 0, 0, CapacityVO.CAPACITY_TYPE_STORAGE); + CapacityVO capacity = new CapacityVO(poolId, zoneId, podId, clusterId, 0, 0, CapacityVO.CAPACITY_TYPE_STORAGE); for (StoragePoolVO PrimaryDataStoreVO : pools) { - StorageStats stats = ApiDBUtils - .getStoragePoolStatistics(PrimaryDataStoreVO.getId()); + StorageStats stats = ApiDBUtils.getStoragePoolStatistics(PrimaryDataStoreVO.getId()); if (stats == null) { continue; } - capacity.setUsedCapacity(stats.getByteUsed() - + capacity.getUsedCapacity()); - capacity.setTotalCapacity(stats.getCapacityBytes() - + capacity.getTotalCapacity()); + capacity.setUsedCapacity(stats.getByteUsed() + capacity.getUsedCapacity()); + capacity.setTotalCapacity(stats.getCapacityBytes() + capacity.getTotalCapacity()); } return capacity; } @Override public PrimaryDataStoreInfo getStoragePool(long id) { - return (PrimaryDataStoreInfo) dataStoreMgr.getDataStore(id, - DataStoreRole.Primary); + return (PrimaryDataStoreInfo) dataStoreMgr.getDataStore(id, DataStoreRole.Primary); } - - @Override @DB public List listByStoragePool(long storagePoolId) { @@ -1653,11 +1451,9 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C @DB public StoragePoolVO findLocalStorageOnHost(long hostId) { SearchCriteria sc = LocalStorageSearch.create(); - sc.setParameters("type", new Object[] { StoragePoolType.Filesystem, - StoragePoolType.LVM }); + sc.setParameters("type", new Object[] { StoragePoolType.Filesystem, StoragePoolType.LVM }); sc.setJoinParameters("poolHost", "hostId", hostId); - List storagePools = _storagePoolDao - .search(sc, null); + List storagePools = _storagePoolDao.search(sc, null); if (!storagePools.isEmpty()) { return storagePools.get(0); } else { @@ -1669,33 +1465,25 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C public Host updateSecondaryStorage(long secStorageId, String newUrl) { HostVO secHost = _hostDao.findById(secStorageId); if (secHost == null) { - throw new InvalidParameterValueException( - "Can not find out the secondary storage id: " - + secStorageId); + throw new InvalidParameterValueException("Can not find out the secondary storage id: " + secStorageId); } if (secHost.getType() != Host.Type.SecondaryStorage) { - throw new InvalidParameterValueException("host: " + secStorageId - + " is not a secondary storage"); + throw new InvalidParameterValueException("host: " + secStorageId + " is not a secondary storage"); } URI uri = null; try { uri = new URI(UriUtils.encodeURIComponent(newUrl)); if (uri.getScheme() == null) { - throw new InvalidParameterValueException("uri.scheme is null " - + newUrl + ", add nfs:// as a prefix"); + throw new InvalidParameterValueException("uri.scheme is null " + newUrl + ", add nfs:// as a prefix"); } else if (uri.getScheme().equalsIgnoreCase("nfs")) { - if (uri.getHost() == null || uri.getHost().equalsIgnoreCase("") - || uri.getPath() == null - || uri.getPath().equalsIgnoreCase("")) { - throw new InvalidParameterValueException( - "Your host and/or path is wrong. Make sure it's of the format nfs://hostname/path"); + if (uri.getHost() == null || uri.getHost().equalsIgnoreCase("") || uri.getPath() == null || uri.getPath().equalsIgnoreCase("")) { + throw new InvalidParameterValueException("Your host and/or path is wrong. Make sure it's of the format nfs://hostname/path"); } } } catch (URISyntaxException e) { - throw new InvalidParameterValueException(newUrl - + " is not a valid uri"); + throw new InvalidParameterValueException(newUrl + " is not a valid uri"); } String oldUrl = secHost.getStorageUrl(); @@ -1704,9 +1492,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C try { oldUri = new URI(UriUtils.encodeURIComponent(oldUrl)); if (!oldUri.getScheme().equalsIgnoreCase(uri.getScheme())) { - throw new InvalidParameterValueException( - "can not change old scheme:" + oldUri.getScheme() - + " to " + uri.getScheme()); + throw new InvalidParameterValueException("can not change old scheme:" + oldUri.getScheme() + " to " + uri.getScheme()); } } catch (URISyntaxException e) { s_logger.debug("Failed to get uri from " + oldUrl); @@ -1719,8 +1505,6 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C return secHost; } - - @Override public HypervisorType getHypervisorTypeFromFormat(ImageFormat format) { @@ -1743,7 +1527,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C private boolean checkUsagedSpace(StoragePool pool) { StatsCollector sc = StatsCollector.getInstance(); - double storageUsedThreshold = Double.parseDouble(_configServer.getConfigValue(Config.StorageCapacityDisableThreshold.key(), Config.ConfigurationParameterScope.zone.toString(), pool.getDataCenterId())); + double storageUsedThreshold = Double.parseDouble(_configServer.getConfigValue(Config.StorageCapacityDisableThreshold.key(), + Config.ConfigurationParameterScope.zone.toString(), pool.getDataCenterId())); if (sc != null) { long totalSize = pool.getCapacityBytes(); StorageStats stats = sc.getStoragePoolStats(pool.getId()); @@ -1753,21 +1538,13 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C if (stats != null) { double usedPercentage = ((double) stats.getByteUsed() / (double) totalSize); if (s_logger.isDebugEnabled()) { - s_logger.debug("Checking pool " + pool.getId() - + " for storage, totalSize: " - + pool.getCapacityBytes() + ", usedBytes: " - + stats.getByteUsed() + ", usedPct: " - + usedPercentage + ", disable threshold: " - + storageUsedThreshold); + s_logger.debug("Checking pool " + pool.getId() + " for storage, totalSize: " + pool.getCapacityBytes() + ", usedBytes: " + + stats.getByteUsed() + ", usedPct: " + usedPercentage + ", disable threshold: " + storageUsedThreshold); } if (usedPercentage >= storageUsedThreshold) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Insufficient space on pool: " - + pool.getId() - + " since its usage percentage: " - + usedPercentage - + " has crossed the pool.storage.capacity.disablethreshold: " - + storageUsedThreshold); + s_logger.debug("Insufficient space on pool: " + pool.getId() + " since its usage percentage: " + usedPercentage + + " has crossed the pool.storage.capacity.disablethreshold: " + storageUsedThreshold); } return false; } @@ -1778,8 +1555,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } @Override - public boolean storagePoolHasEnoughSpace(List volumes, - StoragePool pool) { + public boolean storagePoolHasEnoughSpace(List volumes, StoragePool pool) { if (volumes == null || volumes.isEmpty()) return false; @@ -1788,16 +1564,13 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C // allocated space includes template of specified volume StoragePoolVO poolVO = _storagePoolDao.findById(pool.getId()); - long allocatedSizeWithtemplate = _capacityMgr.getAllocatedPoolCapacity( - poolVO, null); + long allocatedSizeWithtemplate = _capacityMgr.getAllocatedPoolCapacity(poolVO, null); long totalAskingSize = 0; for (Volume volume : volumes) { if (volume.getTemplateId() != null) { - VMTemplateVO tmpl = _templateDao.findById(volume - .getTemplateId()); + VMTemplateVO tmpl = _templateDao.findById(volume.getTemplateId()); if (tmpl.getFormat() != ImageFormat.ISO) { - allocatedSizeWithtemplate = _capacityMgr - .getAllocatedPoolCapacity(poolVO, tmpl); + allocatedSizeWithtemplate = _capacityMgr.getAllocatedPoolCapacity(poolVO, tmpl); } } if (volume.getState() != Volume.State.Ready) @@ -1806,48 +1579,36 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C long totalOverProvCapacity; if (pool.getPoolType() == StoragePoolType.NetworkFilesystem) { - totalOverProvCapacity = getStorageOverProvisioningFactor(pool.getDataCenterId()).multiply( - new BigDecimal(pool.getCapacityBytes())).longValue(); + totalOverProvCapacity = getStorageOverProvisioningFactor(pool.getDataCenterId()).multiply(new BigDecimal(pool.getCapacityBytes())) + .longValue(); } else { totalOverProvCapacity = pool.getCapacityBytes(); } - double storageAllocatedThreshold = Double.parseDouble(_configServer.getConfigValue(Config.StorageAllocatedCapacityDisableThreshold.key(), Config.ConfigurationParameterScope.zone.toString(), pool.getDataCenterId())); + double storageAllocatedThreshold = Double.parseDouble(_configServer.getConfigValue(Config.StorageAllocatedCapacityDisableThreshold.key(), + Config.ConfigurationParameterScope.zone.toString(), pool.getDataCenterId())); if (s_logger.isDebugEnabled()) { - s_logger.debug("Checking pool: " + pool.getId() - + " for volume allocation " + volumes.toString() - + ", maxSize : " + totalOverProvCapacity - + ", totalAllocatedSize : " + allocatedSizeWithtemplate - + ", askingSize : " + totalAskingSize - + ", allocated disable threshold: " + s_logger.debug("Checking pool: " + pool.getId() + " for volume allocation " + volumes.toString() + ", maxSize : " + totalOverProvCapacity + + ", totalAllocatedSize : " + allocatedSizeWithtemplate + ", askingSize : " + totalAskingSize + ", allocated disable threshold: " + storageAllocatedThreshold); } - double usedPercentage = (allocatedSizeWithtemplate + totalAskingSize) - / (double) (totalOverProvCapacity); + double usedPercentage = (allocatedSizeWithtemplate + totalAskingSize) / (double) (totalOverProvCapacity); if (usedPercentage > storageAllocatedThreshold) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Insufficient un-allocated capacity on: " - + pool.getId() - + " for volume allocation: " - + volumes.toString() - + " since its allocated percentage: " - + usedPercentage - + " has crossed the allocated pool.storage.allocated.capacity.disablethreshold: " - + storageAllocatedThreshold + ", skipping this pool"); + s_logger.debug("Insufficient un-allocated capacity on: " + pool.getId() + " for volume allocation: " + volumes.toString() + + " since its allocated percentage: " + usedPercentage + + " has crossed the allocated pool.storage.allocated.capacity.disablethreshold: " + storageAllocatedThreshold + + ", skipping this pool"); } return false; } if (totalOverProvCapacity < (allocatedSizeWithtemplate + totalAskingSize)) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Insufficient un-allocated capacity on: " - + pool.getId() + " for volume allocation: " - + volumes.toString() - + ", not enough storage, maxSize : " - + totalOverProvCapacity + ", totalAllocatedSize : " - + allocatedSizeWithtemplate + ", askingSize : " - + totalAskingSize); + s_logger.debug("Insufficient un-allocated capacity on: " + pool.getId() + " for volume allocation: " + volumes.toString() + + ", not enough storage, maxSize : " + totalOverProvCapacity + ", totalAllocatedSize : " + allocatedSizeWithtemplate + + ", askingSize : " + totalAskingSize); } return false; } @@ -1860,24 +1621,20 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C createCapacityEntry(storage, Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED, 0); } - @Override - public synchronized boolean registerHostListener(String providerName, - HypervisorHostListener listener) { + public synchronized boolean registerHostListener(String providerName, HypervisorHostListener listener) { hostListeners.put(providerName, listener); return true; } @Override - public Answer sendToPool(long poolId, Command cmd) - throws StorageUnavailableException { + public Answer sendToPool(long poolId, Command cmd) throws StorageUnavailableException { // TODO Auto-generated method stub return null; } @Override - public Answer[] sendToPool(long poolId, Commands cmd) - throws StorageUnavailableException { + public Answer[] sendToPool(long poolId, Commands cmd) throws StorageUnavailableException { // TODO Auto-generated method stub return null; } @@ -1888,6 +1645,233 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C return null; } + @Override + public ImageStore discoverImageStore(AddImageStoreCmd cmd) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException { + String providerName = cmd.getProviderName(); + DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(providerName); + + if (storeProvider == null) { + storeProvider = _dataStoreProviderMgr.getDefaultImageDataStoreProvider(); + if (storeProvider == null) { + throw new InvalidParameterValueException("can't find image store provider: " + providerName); + } + providerName = storeProvider.getName(); // ignored passed provider name and use default image store provider name + } + + Long dcId = cmd.getZoneId(); + String url = cmd.getUrl(); + Map details = cmd.getDetails(); + ScopeType scopeType = ScopeType.ZONE; + if (dcId == null) { + scopeType = ScopeType.REGION; + } + + // check if scope is supported by store provider + if (!((ImageStoreProvider) storeProvider).isScopeSupported(scopeType)) { + throw new InvalidParameterValueException("Image store provider " + providerName + " does not support scope " + scopeType); + } + + // check if we have already image stores from other different providers, + // we currently are not supporting image stores from different + // providers co-existing + List imageStores = _imageStoreDao.listImageStores(); + for (ImageStoreVO store : imageStores) { + if (!store.getProviderName().equalsIgnoreCase(providerName)) { + throw new InvalidParameterValueException("You can only add new image stores from the same provider " + store.getProviderName() + + " already added"); + } + } + + if (dcId != null) { + // Check if the zone exists in the system + DataCenterVO zone = _dcDao.findById(dcId); + if (zone == null) { + throw new InvalidParameterValueException("Can't find zone by id " + dcId); + } + + Account account = UserContext.current().getCaller(); + if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(account.getType())) { + PermissionDeniedException ex = new PermissionDeniedException( + "Cannot perform this operation, Zone with specified id is currently disabled"); + ex.addProxyObject(zone.getUuid(), "dcId"); + throw ex; + } + } + + Map params = new HashMap(); + params.put("zoneId", dcId); + params.put("url", cmd.getUrl()); + params.put("name", cmd.getName()); + params.put("details", details); + params.put("scope", scopeType); + params.put("providerName", storeProvider.getName()); + params.put("role", DataStoreRole.Image); + + DataStoreLifeCycle lifeCycle = storeProvider.getDataStoreLifeCycle(); + DataStore store = null; + try { + store = lifeCycle.initialize(params); + } catch (Exception e) { + s_logger.debug("Failed to add data store", e); + throw new CloudRuntimeException("Failed to add data store", e); + } + + if (((ImageStoreProvider) storeProvider).needDownloadSysTemplate()) { + // trigger system vm template download + this._imageSrv.downloadBootstrapSysTemplate(store); + } + else { + // populate template_store_ref table + this._imageSrv.addSystemVMTemplatesToSecondary(store); + } + + // associate builtin template with zones associated with this image + // store + this.associateCrosszoneTemplatesToZone(dcId); + + return (ImageStore) _dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Image); + } + + private void associateCrosszoneTemplatesToZone(Long zoneId) { + VMTemplateZoneVO tmpltZone; + + List allTemplates = _vmTemplateDao.listAll(); + List dcIds = new ArrayList(); + if (zoneId != null) { + dcIds.add(zoneId); + } else { + List dcs = _dcDao.listAll(); + if (dcs != null) { + for (DataCenterVO dc : dcs) { + dcIds.add(dc.getId()); + } + } + } + + for (VMTemplateVO vt : allTemplates) { + if (vt.isCrossZones()) { + for (Long dcId : dcIds) { + tmpltZone = _vmTemplateZoneDao.findByZoneTemplate(dcId, vt.getId()); + if (tmpltZone == null) { + VMTemplateZoneVO vmTemplateZone = new VMTemplateZoneVO(dcId, vt.getId(), new Date()); + _vmTemplateZoneDao.persist(vmTemplateZone); + } + } + } + } + } + + @Override + public boolean deleteImageStore(DeleteImageStoreCmd cmd) { + long storeId = cmd.getId(); + User caller = _accountMgr.getActiveUser(UserContext.current().getCallerUserId()); + // Verify that image store exists + ImageStoreVO store = _imageStoreDao.findById(storeId); + if (store == null) { + throw new InvalidParameterValueException("Image store with id " + storeId + " doesn't exist"); + } + _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), store.getDataCenterId()); + + // Verify that there are no live snapshot, template, volume on the image + // store to be deleted + List snapshots = _snapshotStoreDao.listByStoreId(storeId, DataStoreRole.Image); + if (snapshots != null && snapshots.size() > 0) { + throw new InvalidParameterValueException("Cannot delete image store with active snapshots backup!"); + } + List volumes = _volumeStoreDao.listByStoreId(storeId); + if (volumes != null && volumes.size() > 0) { + throw new InvalidParameterValueException("Cannot delete image store with active volumes backup!"); + } + + // search if there are user templates stored on this image store, excluding system, builtin templates + List templates = this._templateViewDao.listActiveTemplates(storeId); + if (templates != null && templates.size() > 0) { + throw new InvalidParameterValueException("Cannot delete image store with active templates backup!"); + } + + // ready to delete + Transaction txn = Transaction.currentTxn(); + txn.start(); + // first delete from image_store_details table, we need to do that since + // we are not actually deleting record from main + // image_data_store table, so delete cascade will not work + _imageStoreDetailsDao.deleteDetails(storeId); + _snapshotStoreDao.deletePrimaryRecordsForStore(storeId); + _volumeStoreDao.deletePrimaryRecordsForStore(storeId); + _templateStoreDao.deletePrimaryRecordsForStore(storeId); + _imageStoreDao.remove(storeId); + txn.commit(); + return true; + } + + @Override + public ImageStore createCacheStore(CreateCacheStoreCmd cmd) { + String providerName = cmd.getProviderName(); + DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(providerName); + + if (storeProvider == null) { + storeProvider = _dataStoreProviderMgr.getDefaultCacheDataStoreProvider(); + if (storeProvider == null) { + throw new InvalidParameterValueException("can't find cache store provider: " + providerName); + } + } + + Long dcId = cmd.getZoneId(); + + ScopeType scopeType = null; + String scope = cmd.getScope(); + if (scope != null) { + try { + scopeType = Enum.valueOf(ScopeType.class, scope.toUpperCase()); + + } catch (Exception e) { + throw new InvalidParameterValueException("invalid scope" + scope); + } + + if (scopeType != ScopeType.ZONE) { + throw new InvalidParameterValueException("Only zone wide cache storage is supported"); + } + } + + if (scopeType == ScopeType.ZONE && dcId == null) { + throw new InvalidParameterValueException("zone id can't be null, if scope is zone"); + } + + // Check if the zone exists in the system + DataCenterVO zone = _dcDao.findById(dcId); + if (zone == null) { + throw new InvalidParameterValueException("Can't find zone by id " + dcId); + } + + Account account = UserContext.current().getCaller(); + if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(account.getType())) { + PermissionDeniedException ex = new PermissionDeniedException( + "Cannot perform this operation, Zone with specified id is currently disabled"); + ex.addProxyObject(zone.getUuid(), "dcId"); + throw ex; + } + + Map params = new HashMap(); + params.put("zoneId", dcId); + params.put("url", cmd.getUrl()); + params.put("name", cmd.getUrl()); + params.put("details", cmd.getDetails()); + params.put("scope", scopeType); + params.put("providerName", storeProvider.getName()); + params.put("role", DataStoreRole.ImageCache); + + DataStoreLifeCycle lifeCycle = storeProvider.getDataStoreLifeCycle(); + DataStore store = null; + try { + store = lifeCycle.initialize(params); + } catch (Exception e) { + s_logger.debug("Failed to add data store", e); + throw new CloudRuntimeException("Failed to add data store", e); + } + + return (ImageStore) _dataStoreMgr.getDataStore(store.getId(), DataStoreRole.ImageCache); + } + // get bytesReadRate from service_offering, disk_offering and vm.disk.throttling.bytes_read_rate @Override public Long getDiskBytesReadRate(ServiceOfferingVO offering, DiskOfferingVO diskOffering) { diff --git a/server/src/com/cloud/storage/StoragePoolAutomationImpl.java b/server/src/com/cloud/storage/StoragePoolAutomationImpl.java index 9bba979b9c0..40017756fd4 100644 --- a/server/src/com/cloud/storage/StoragePoolAutomationImpl.java +++ b/server/src/com/cloud/storage/StoragePoolAutomationImpl.java @@ -27,7 +27,6 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.log4j.Logger; diff --git a/server/src/com/cloud/storage/TemplateProfile.java b/server/src/com/cloud/storage/TemplateProfile.java index ca23d00058c..00aab4d76db 100755 --- a/server/src/com/cloud/storage/TemplateProfile.java +++ b/server/src/com/cloud/storage/TemplateProfile.java @@ -21,7 +21,7 @@ import java.util.Map; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.Storage.ImageFormat; -public class TemplateProfile { +public class TemplateProfile { Long userId; String name; String displayText; @@ -45,10 +45,10 @@ public class TemplateProfile { Long templateId; VMTemplateVO template; String templateTag; - Long imageStoreId; Map details; Boolean isDynamicallyScalable; + public TemplateProfile(Long templateId, Long userId, String name, String displayText, Integer bits, Boolean passwordEnabled, Boolean requiresHvm, String url, Boolean isPublic, Boolean featured, Boolean isExtractable, ImageFormat format, Long guestOsId, Long zoneId, HypervisorType hypervisorType, String accountName, Long domainId, Long accountId, String chksum, Boolean bootable, Map details, Boolean sshKeyEnabled) { @@ -75,191 +75,187 @@ public class TemplateProfile { this.details = details; this.sshKeyEnbaled = sshKeyEnabled; } - + public TemplateProfile(Long userId, VMTemplateVO template, Long zoneId) { this.userId = userId; this.template = template; this.zoneId = zoneId; } - + public TemplateProfile(Long templateId, Long userId, String name, String displayText, Integer bits, Boolean passwordEnabled, Boolean requiresHvm, String url, Boolean isPublic, Boolean featured, Boolean isExtractable, ImageFormat format, Long guestOsId, Long zoneId, + HypervisorType hypervisorType, String accountName, Long domainId, Long accountId, String chksum, Boolean bootable, String templateTag, Map details, Boolean sshKeyEnabled, Long imageStoreId, Boolean isDynamicallyScalable) { this(templateId, userId, name, displayText, bits, passwordEnabled, requiresHvm, url, isPublic, featured, isExtractable, format, guestOsId, zoneId, hypervisorType, accountName, domainId, accountId, chksum, bootable, details, sshKeyEnabled); this.templateTag = templateTag; - this.imageStoreId = imageStoreId; this.isDynamicallyScalable = isDynamicallyScalable; } - + public Long getTemplateId() { return templateId; } public void setTemplateId(Long id) { this.templateId = id; } - + public Long getUserId() { return userId; } public void setUserId(Long userId) { this.userId = userId; } - + public String getName() { return name; } public void setName(String name) { this.name = name; } - + public String getDisplayText() { return displayText; } public void setDisplayText(String text) { this.displayText = text; } - + public Integer getBits() { return bits; } public void setBits(Integer bits) { this.bits = bits; } - + public Boolean getPasswordEnabled() { return passwordEnabled; } public void setPasswordEnabled(Boolean enabled) { this.passwordEnabled = enabled; } - + public Boolean getRequiresHVM() { return requiresHvm; } public void setRequiresHVM(Boolean hvm) { this.requiresHvm = hvm; } - + public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } - + public Boolean getIsPublic() { return isPublic; } public void setIsPublic(Boolean is) { this.isPublic = is; } - + public Boolean getFeatured() { return featured; } public void setFeatured(Boolean featured) { this.featured = featured; } - + public Boolean getIsExtractable() { return isExtractable; } public void setIsExtractable(Boolean is) { this.isExtractable = is; } - + public ImageFormat getFormat() { return format; } public void setFormat(ImageFormat format) { this.format = format; } - + public Long getGuestOsId() { return guestOsId; } public void setGuestOsId(Long id) { this.guestOsId = id; } - + public Long getZoneId() { return zoneId; } public void setZoneId(Long id) { this.zoneId = id; } - + public HypervisorType getHypervisorType() { return hypervisorType; } public void setHypervisorType(HypervisorType type) { this.hypervisorType = type; } - + public Long getDomainId() { return domainId; } public void setDomainId(Long id) { this.domainId = id; } - + public Long getAccountId() { return accountId; } public void setAccountId(Long id) { this.accountId = id; } - + public String getCheckSum() { return chksum; } public void setCheckSum(String chksum) { this.chksum = chksum; } - + public Boolean getBootable() { return this.bootable; } public void setBootable(Boolean bootable) { this.bootable = bootable; } - + public VMTemplateVO getTemplate() { return template; } public void setTemplate(VMTemplateVO template) { this.template = template; } - + public String getTemplateTag() { return templateTag; - } + } public void setTemplateTag(String templateTag) { this.templateTag = templateTag; - } - + } + public Map getDetails() { return this.details; } - + public void setDetails(Map details) { this.details = details; } - + public void setSshKeyEnabled(Boolean enabled) { this.sshKeyEnbaled = enabled; } - + public Boolean getSshKeyEnabled() { return this.sshKeyEnbaled; } - - public Long getImageStoreId() { - return this.imageStoreId; - } public Boolean IsDynamicallyScalable() { return this.isDynamicallyScalable; @@ -268,4 +264,5 @@ public class TemplateProfile { public void setScalabe(Boolean isDynamicallyScalabe) { this.isDynamicallyScalable = isDynamicallyScalabe; } + } diff --git a/server/src/com/cloud/storage/VolumeManager.java b/server/src/com/cloud/storage/VolumeManager.java index 56de408e6f5..c84bb67e038 100644 --- a/server/src/com/cloud/storage/VolumeManager.java +++ b/server/src/com/cloud/storage/VolumeManager.java @@ -50,6 +50,7 @@ public interface VolumeManager extends VolumeApiService { Long destPoolClusterId, HypervisorType dataDiskHyperType) throws ConcurrentOperationException; + @Override VolumeVO uploadVolume(UploadVolumeCmd cmd) throws ResourceAllocationException; @@ -61,28 +62,35 @@ public interface VolumeManager extends VolumeApiService { String getVmNameOnVolume(Volume volume); + @Override VolumeVO allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationException; + @Override VolumeVO createVolume(CreateVolumeCmd cmd); + @Override VolumeVO resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationException; + @Override boolean deleteVolume(long volumeId, Account caller) throws ConcurrentOperationException; - + void destroyVolume(VolumeVO volume); DiskProfile allocateRawVolume(Type type, String name, DiskOfferingVO offering, Long size, VMInstanceVO vm, Account owner); + @Override Volume attachVolumeToVM(AttachVolumeCmd command); + @Override Volume detachVolumeFromVM(DetachVolumeCmd cmmd); void release(VirtualMachineProfile profile); void cleanupVolumes(long vmId) throws ConcurrentOperationException; + @Override Volume migrateVolume(MigrateVolumeCmd cmd); void migrateVolumes(T vm, VirtualMachineTO vmTo, Host srcHost, Host destHost, @@ -106,6 +114,7 @@ public interface VolumeManager extends VolumeApiService { DiskOfferingVO offering, VMTemplateVO template, VMInstanceVO vm, Account owner); + String getVmNameFromVolumeId(long volumeId); String getStoragePoolOfVolume(long volumeId); diff --git a/server/src/com/cloud/storage/VolumeManagerImpl.java b/server/src/com/cloud/storage/VolumeManagerImpl.java index e5868d3d603..4e7b3353ba0 100644 --- a/server/src/com/cloud/storage/VolumeManagerImpl.java +++ b/server/src/com/cloud/storage/VolumeManagerImpl.java @@ -18,17 +18,12 @@ */ package com.cloud.storage; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.HashMap; import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutionException; @@ -36,38 +31,55 @@ import java.util.concurrent.ExecutionException; import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.storage.dao.*; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + import org.apache.cloudstack.api.BaseCmd; -import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; +import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.ExtractVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd; + +import com.cloud.storage.dao.*; import org.apache.cloudstack.api.command.user.volume.*; 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.DataStoreProviderManager; -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.PrimaryDataStoreInfo; import org.apache.cloudstack.engine.subsystem.api.storage.Scope; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult; import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.storage.command.AttachAnswer; +import org.apache.cloudstack.storage.command.AttachCommand; +import org.apache.cloudstack.storage.command.CommandResult; +import org.apache.cloudstack.storage.command.DettachCommand; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; +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.image.datastore.ImageStoreEntity; +import org.apache.commons.lang.StringUtils; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; -import com.cloud.agent.api.AttachVolumeAnswer; -import com.cloud.agent.api.AttachVolumeCommand; +import com.cloud.agent.api.storage.CreateVolumeOVAAnswer; +import com.cloud.agent.api.storage.CreateVolumeOVACommand; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.DiskTO; import com.cloud.agent.api.to.VirtualMachineTO; -import com.cloud.agent.api.to.VolumeTO; import com.cloud.alert.AlertManager; import com.cloud.api.ApiDBUtils; import com.cloud.async.AsyncJobExecutor; @@ -82,6 +94,7 @@ import com.cloud.configuration.Resource.ResourceType; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.consoleproxy.ConsoleProxyManager; import com.cloud.dc.ClusterVO; +import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; import com.cloud.dc.dao.ClusterDao; @@ -105,9 +118,9 @@ import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.hypervisor.HypervisorCapabilitiesVO; import com.cloud.hypervisor.HypervisorGuruManager; import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; -import com.cloud.hypervisor.HypervisorCapabilitiesVO; import com.cloud.network.NetworkModel; import com.cloud.org.Grouping; import com.cloud.resource.ResourceManager; @@ -115,15 +128,25 @@ import com.cloud.server.ManagementServer; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.Storage.ImageFormat; -import com.cloud.storage.StorageManager; -import com.cloud.storage.Storage.StoragePoolType; -import com.cloud.storage.Volume.Event; import com.cloud.storage.Volume.Type; +import com.cloud.storage.dao.DiskOfferingDao; +import com.cloud.storage.dao.SnapshotDao; +import com.cloud.storage.dao.SnapshotPolicyDao; +import com.cloud.storage.dao.StoragePoolHostDao; +import com.cloud.storage.dao.StoragePoolWorkDao; +import com.cloud.storage.dao.UploadDao; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VMTemplatePoolDao; +import com.cloud.storage.dao.VMTemplateS3Dao; +import com.cloud.storage.dao.VMTemplateSwiftDao; +import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.download.DownloadMonitor; import com.cloud.storage.s3.S3Manager; import com.cloud.storage.secondary.SecondaryStorageVmManager; +import com.cloud.storage.snapshot.SnapshotApiService; import com.cloud.storage.snapshot.SnapshotManager; import com.cloud.storage.snapshot.SnapshotScheduler; +import com.cloud.storage.upload.UploadMonitor; import com.cloud.tags.dao.ResourceTagDao; import com.cloud.template.TemplateManager; import com.cloud.user.Account; @@ -141,9 +164,6 @@ import com.cloud.utils.Pair; import com.cloud.utils.UriUtils; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.DB; -import com.cloud.utils.db.JoinBuilder; -import com.cloud.utils.db.SearchBuilder; -import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.fsm.NoTransitionException; @@ -209,7 +229,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { @Inject protected AlertManager _alertMgr; @Inject - protected VMTemplateHostDao _vmTemplateHostDao = null; + protected TemplateDataStoreDao _vmTemplateStoreDao = null; @Inject protected VMTemplatePoolDao _vmTemplatePoolDao = null; @Inject @@ -225,7 +245,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { @Inject protected UserVmDao _userVmDao; @Inject - VolumeHostDao _volumeHostDao; + VolumeDataStoreDao _volumeStoreDao; @Inject protected VMInstanceDao _vmInstanceDao; @Inject @@ -247,8 +267,6 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { @Inject protected VMTemplateDao _templateDao; @Inject - protected VMTemplateHostDao _templateHostDao; - @Inject protected ServiceOfferingDao _offeringDao; @Inject protected DomainDao _domainDao; @@ -303,9 +321,16 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { @Inject VolumeDataFactory volFactory; @Inject - ImageDataFactory tmplFactory; + TemplateDataFactory tmplFactory; @Inject SnapshotDataFactory snapshotFactory; + @Inject + SnapshotApiService snapshotMgr; + @Inject + UploadMonitor _uploadMonitor; + @Inject + UploadDao _uploadDao; + private int _copyvolumewait; @Inject protected HypervisorCapabilitiesDao _hypervisorCapabilitiesDao; @@ -313,15 +338,14 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { @Inject StorageManager storageMgr; private int _customDiskOfferingMinSize = 1; - private int _customDiskOfferingMaxSize = 1024; + private final int _customDiskOfferingMaxSize = 1024; private long _maxVolumeSizeInGb; private boolean _recreateSystemVmEnabled; - protected SearchBuilder HostTemplateStatesSearch; - + public VolumeManagerImpl() { _volStateMachine = Volume.State.getStateMachine(); } - + @Override public VolumeInfo moveVolume(VolumeInfo volume, long destPoolDcId, Long destPoolPodId, Long destPoolClusterId, @@ -337,14 +361,9 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { diskOffering.getUseLocalStorage(), diskOffering.isRecreatable(), null); dskCh.setHyperType(dataDiskHyperType); - dskCh.setBytesReadRate(storageMgr.getDiskBytesReadRate(null, diskOffering)); - dskCh.setBytesWriteRate(storageMgr.getDiskBytesWriteRate(null, diskOffering)); - dskCh.setIopsReadRate(storageMgr.getDiskIopsReadRate(null, diskOffering)); - dskCh.setIopsWriteRate(storageMgr.getDiskIopsWriteRate(null, diskOffering)); - DataCenterVO destPoolDataCenter = _dcDao.findById(destPoolDcId); HostPodVO destPoolPod = _podDao.findById(destPoolPodId); - + StoragePool destPool = storageMgr.findStoragePool(dskCh, destPoolDataCenter, destPoolPod, destPoolClusterId, null, null, new HashSet()); @@ -353,9 +372,9 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { throw new CloudRuntimeException( "Failed to find a storage pool with enough capacity to move the volume to."); } - + Volume newVol = migrateVolume(volume, destPool); - return this.volFactory.getVolume(newVol.getId()); + return volFactory.getVolume(newVol.getId()); } /* @@ -374,20 +393,20 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { String url = cmd.getUrl(); String format = cmd.getFormat(); String imageStoreUuid = cmd.getImageStoreUuid(); - DataStore store = this._tmpltMgr.getImageStore(imageStoreUuid, zoneId); + DataStore store = _tmpltMgr.getImageStore(imageStoreUuid, zoneId); validateVolume(caller, ownerId, zoneId, volumeName, url, format); - + VolumeVO volume = persistVolume(owner, zoneId, volumeName, url, cmd.getFormat()); - - VolumeInfo vol = this.volFactory.getVolume(volume.getId()); - + + VolumeInfo vol = volFactory.getVolume(volume.getId()); + RegisterVolumePayload payload = new RegisterVolumePayload(cmd.getUrl(), cmd.getChecksum(), cmd.getFormat()); vol.addPayload(payload); - - this.volService.registerVolume(vol, store); + + volService.registerVolume(vol, store); return volume; } @@ -474,7 +493,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { + " is an invalid for the format " + format.toLowerCase()); } - validateUrl(url); + UriUtils.validateUrl(url); // Check that the resource limit for secondary storage won't be exceeded _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(ownerId), ResourceType.secondary_storage, @@ -482,7 +501,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { return false; } - + @Override public VolumeVO allocateDuplicateVolume(VolumeVO oldVol, Long templateId) { VolumeVO newVol = new VolumeVO(oldVol.getVolumeType(), @@ -497,9 +516,10 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { newVol.setDeviceId(oldVol.getDeviceId()); newVol.setInstanceId(oldVol.getInstanceId()); newVol.setRecreatable(oldVol.isRecreatable()); + newVol.setFormat(oldVol.getFormat()); return _volsDao.persist(newVol); } - + @DB protected VolumeInfo createVolumeFromSnapshot(VolumeVO volume, SnapshotVO snapshot) { @@ -517,10 +537,6 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { DataCenterVO dc = _dcDao.findById(volume.getDataCenterId()); DiskProfile dskCh = new DiskProfile(volume, diskOffering, snapshot.getHypervisorType()); - dskCh.setBytesReadRate(storageMgr.getDiskBytesReadRate(null, diskOffering)); - dskCh.setBytesWriteRate(storageMgr.getDiskBytesWriteRate(null, diskOffering)); - dskCh.setIopsReadRate(storageMgr.getDiskIopsReadRate(null, diskOffering)); - dskCh.setIopsWriteRate(storageMgr.getDiskIopsWriteRate(null, diskOffering)); // Determine what pod to store the volume in while ((pod = _resourceMgr.findPod(null, null, dc, account.getId(), @@ -530,14 +546,14 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { while ((pool = storageMgr.findStoragePool(dskCh, dc, pod.first(), null, null, null, poolsToAvoid)) != null) { break; - + } } - - VolumeInfo vol = this.volFactory.getVolume(volume.getId()); - DataStore store = this.dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary); - SnapshotInfo snapInfo = this.snapshotFactory.getSnapshot(snapshot.getId()); - AsyncCallFuture future = this.volService.createVolumeFromSnapshot(vol, store, snapInfo); + + VolumeInfo vol = volFactory.getVolume(volume.getId()); + DataStore store = dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary); + SnapshotInfo snapInfo = snapshotFactory.getSnapshot(snapshot.getId(), DataStoreRole.Image); + AsyncCallFuture future = volService.createVolumeFromSnapshot(vol, store, snapInfo); try { VolumeApiResult result = future.get(); if (result.isFailed()) { @@ -559,22 +575,14 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { VMTemplateVO template, DataCenterVO dc, DiskOfferingVO diskOffering) { if (volume.getVolumeType() == Type.ROOT && Storage.ImageFormat.ISO != template.getFormat()) { - SearchCriteria sc = HostTemplateStatesSearch - .create(); - sc.setParameters("id", template.getId()); - sc.setParameters( - "state", - com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED); - sc.setJoinParameters("host", "dcId", dc.getId()); - - List sss = _vmTemplateHostDao.search(sc, null); - if (sss.size() == 0) { + TemplateDataStoreVO ss = _vmTemplateStoreDao.findByTemplateZoneDownloadStatus(template.getId(), dc.getId(), + VMTemplateStorageResourceAssoc.Status.DOWNLOADED); + if (ss == null) { throw new CloudRuntimeException("Template " + template.getName() + " has not been completely downloaded to zone " + dc.getId()); } - VMTemplateHostVO ss = sss.get(0); return new DiskProfile(volume.getId(), volume.getVolumeType(), volume.getName(), diskOffering.getId(), ss.getSize(), @@ -594,7 +602,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { protected VolumeVO createVolumeFromSnapshot(VolumeVO volume, long snapshotId) { VolumeInfo createdVolume = null; - SnapshotVO snapshot = _snapshotDao.findById(snapshotId); + SnapshotVO snapshot = _snapshotDao.findById(snapshotId); createdVolume = createVolumeFromSnapshot(volume, snapshot); @@ -606,7 +614,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { null, createdVolume.getSize()); _usageEventDao.persist(usageEvent); - return this._volsDao.findById(createdVolume.getId()); + return _volsDao.findById(createdVolume.getId()); } @DB @@ -621,23 +629,18 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { DiskProfile dskCh = createDiskCharacteristics(volume, template, dc, diskOffering); dskCh.setHyperType(vm.getHypervisorType()); - dskCh.setBytesReadRate(storageMgr.getDiskBytesReadRate(null, diskOffering)); - dskCh.setBytesWriteRate(storageMgr.getDiskBytesWriteRate(null, diskOffering)); - dskCh.setIopsReadRate(storageMgr.getDiskIopsReadRate(null, diskOffering)); - dskCh.setIopsWriteRate(storageMgr.getDiskIopsWriteRate(null, diskOffering)); - // Find a suitable storage to create volume on StoragePool destPool = storageMgr.findStoragePool(dskCh, dc, pod, clusterId, null, vm, avoidPools); - DataStore destStore = this.dataStoreMgr.getDataStore(destPool.getId(), DataStoreRole.Primary); - AsyncCallFuture future = this.volService.copyVolume(volume, destStore); + DataStore destStore = dataStoreMgr.getDataStore(destPool.getId(), DataStoreRole.Primary); + AsyncCallFuture future = volService.copyVolume(volume, destStore); try { VolumeApiResult result = future.get(); if (result.isFailed()) { s_logger.debug("copy volume failed: " + result.getResult()); throw new CloudRuntimeException("copy volume failed: " + result.getResult()); - } + } return result.getVolume(); } catch (InterruptedException e) { s_logger.debug("Failed to copy volume: " + volume.getId(), e); @@ -655,26 +658,18 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { DiskOfferingVO diskOffering, List avoids, long size, HypervisorType hyperType) { StoragePool pool = null; - + if (diskOffering != null && diskOffering.isCustomized()) { diskOffering.setDiskSize(size); } - + DiskProfile dskCh = null; if (volume.getVolumeType() == Type.ROOT && Storage.ImageFormat.ISO != template.getFormat()) { dskCh = createDiskCharacteristics(volume, template, dc, offering); - dskCh.setBytesReadRate(storageMgr.getDiskBytesReadRate(offering, diskOffering)); - dskCh.setBytesWriteRate(storageMgr.getDiskBytesWriteRate(offering, diskOffering)); - dskCh.setIopsReadRate(storageMgr.getDiskIopsReadRate(offering, diskOffering)); - dskCh.setIopsWriteRate(storageMgr.getDiskIopsWriteRate(offering, diskOffering)); } else { dskCh = createDiskCharacteristics(volume, template, dc, diskOffering); - dskCh.setBytesReadRate(storageMgr.getDiskBytesReadRate(null, diskOffering)); - dskCh.setBytesWriteRate(storageMgr.getDiskBytesWriteRate(null, diskOffering)); - dskCh.setIopsReadRate(storageMgr.getDiskIopsReadRate(null, diskOffering)); - dskCh.setIopsWriteRate(storageMgr.getDiskIopsWriteRate(null, diskOffering)); } dskCh.setHyperType(hyperType); @@ -693,14 +688,14 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { if (s_logger.isDebugEnabled()) { s_logger.debug("Trying to create " + volume + " on " + pool); } - DataStore store = this.dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary); + DataStore store = dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary); AsyncCallFuture future = null; boolean isNotCreatedFromTemplate = volume.getTemplateId() == null ? true : false; if (isNotCreatedFromTemplate) { - future = this.volService.createVolumeAsync(volume, store); + future = volService.createVolumeAsync(volume, store); } else { - TemplateInfo templ = this.tmplFactory.getTemplate(template.getId()); - future = this.volService.createVolumeFromTemplateAsync(volume, store.getId(), templ); + TemplateInfo templ = tmplFactory.getTemplate(template.getId(), DataStoreRole.Image); + future = volService.createVolumeFromTemplateAsync(volume, store.getId(), templ); } try { VolumeApiResult result = future.get(); @@ -708,6 +703,8 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { s_logger.debug("create volume failed: " + result.getResult()); throw new CloudRuntimeException("create volume failed:" + result.getResult()); } + + UsageEventVO usageEvent = new UsageEventVO( EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), @@ -723,18 +720,18 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { } } - + public String getRandomVolumeName() { return UUID.randomUUID().toString(); } - + private VolumeVO persistVolume(Account owner, Long zoneId, String volumeName, String url, String format) { Transaction txn = Transaction.currentTxn(); txn.start(); - VolumeVO volume = new VolumeVO(volumeName, zoneId, -1, -1, -1, + VolumeVO volume = new VolumeVO(volumeName, zoneId, -1L, -1L, -1, new Long(-1), null, null, 0, Volume.Type.DATADISK); volume.setPoolId(null); volume.setDataCenterId(zoneId); @@ -747,14 +744,10 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { // volume.setSize(size); volume.setInstanceId(null); volume.setUpdated(new Date()); - + volume.setDomainId((owner == null) ? Domain.ROOT_DOMAIN : owner + .getDomainId()); + volume.setFormat(ImageFormat.valueOf(format)); volume = _volsDao.persist(volume); - try { - stateTransitTo(volume, Event.UploadRequested); - } catch (NoTransitionException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } UserContext.current().setEventDetails("Volume Id: " + volume.getId()); // Increment resource count during allocation; if actual creation fails, @@ -767,7 +760,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { txn.commit(); return volume; } - + @Override public boolean volumeOnSharedStoragePool(VolumeVO volume) { Long poolId = volume.getPoolId(); @@ -977,7 +970,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { Transaction txn = Transaction.currentTxn(); txn.start(); - VolumeVO volume = new VolumeVO(userSpecifiedName, -1, -1, -1, -1, + VolumeVO volume = new VolumeVO(userSpecifiedName, -1L, -1L, -1, -1, new Long(-1), null, null, 0, Volume.Type.DATADISK); volume.setPoolId(null); volume.setDataCenterId(zoneId); @@ -994,6 +987,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { volume.setDisplayVolume(displayVolumeEnabled); if (parentVolume != null) { volume.setTemplateId(parentVolume.getTemplateId()); + volume.setFormat(parentVolume.getFormat()); } else { volume.setTemplateId(null); } @@ -1062,12 +1056,12 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { throws ResourceAllocationException { Long newSize = null; boolean shrinkOk = cmd.getShrinkOk(); - + VolumeVO volume = _volsDao.findById(cmd.getEntityId()); if (volume == null) { throw new InvalidParameterValueException("No such volume"); } - + DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume .getDiskOfferingId()); DiskOfferingVO newDiskOffering = null; @@ -1177,7 +1171,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { UserVmVO userVm = _userVmDao.findById(volume.getInstanceId()); - PrimaryDataStoreInfo pool = (PrimaryDataStoreInfo)this.dataStoreMgr.getDataStore(volume.getPoolId(), DataStoreRole.Primary); + PrimaryDataStoreInfo pool = (PrimaryDataStoreInfo)dataStoreMgr.getDataStore(volume.getPoolId(), DataStoreRole.Primary); long currentSize = volume.getSize(); /* @@ -1224,14 +1218,14 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { "VM must be stopped or disk detached in order to resize with the Xen HV"); } } - + ResizeVolumePayload payload = new ResizeVolumePayload(newSize, shrinkOk, instanceName, hosts); - + try { - VolumeInfo vol = this.volFactory.getVolume(volume.getId()); + VolumeInfo vol = volFactory.getVolume(volume.getId()); vol.addPayload(payload); - AsyncCallFuture future = this.volService.resize(vol); + AsyncCallFuture future = volService.resize(vol); future.get(); volume = _volsDao.findById(volume.getId()); @@ -1259,7 +1253,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { return null; } - + @Override @DB @ActionEvent(eventType = EventTypes.EVENT_VOLUME_DELETE, eventDescription = "deleting volume") @@ -1285,9 +1279,9 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { } if (volume.getState() == Volume.State.UploadOp) { - VolumeHostVO volumeHost = _volumeHostDao.findByVolumeId(volume + VolumeDataStoreVO volumeStore = _volumeStoreDao.findByVolume(volume .getId()); - if (volumeHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS) { + if (volumeStore.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS) { throw new InvalidParameterValueException( "Please specify a volume that is not uploading"); } @@ -1296,11 +1290,11 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { try { if (volume.getState() != Volume.State.Destroy && volume.getState() != Volume.State.Expunging && volume.getState() != Volume.State.Expunging) { Long instanceId = volume.getInstanceId(); - if (!this.volService.destroyVolume(volume.getId())) { + if (!volService.destroyVolume(volume.getId())) { return false; } - - VMInstanceVO vmInstance = this._vmInstanceDao.findById(instanceId); + + VMInstanceVO vmInstance = _vmInstanceDao.findById(instanceId); if (instanceId == null || (vmInstance.getType().equals(VirtualMachine.Type.User))) { // Decrement the resource count for volumes and primary storage belonging user VM's only @@ -1323,9 +1317,9 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { _usageEventDao.persist(usageEvent); } } - AsyncCallFuture future = this.volService.expungeVolumeAsync(this.volFactory.getVolume(volume.getId())); + AsyncCallFuture future = volService.expungeVolumeAsync(volFactory.getVolume(volume.getId())); future.get(); - + } catch (Exception e) { s_logger.warn("Failed to expunge volume:", e); return false; @@ -1375,6 +1369,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { vol.setDeviceId(1l); } + vol.setFormat(this.getSupportedImageFormatForCluster(vm.getHypervisorType())); vol = _volsDao.persist(vol); // Save usage event and update resource count for user vm volumes @@ -1400,10 +1395,11 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { VMTemplateVO template, VMInstanceVO vm, Account owner) { assert (template.getFormat() != ImageFormat.ISO) : "ISO is not a template really...."; - Long size = this._tmpltMgr.getTemplateSize(template.getId(), vm.getDataCenterId()); + Long size = _tmpltMgr.getTemplateSize(template.getId(), vm.getDataCenterId()); VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterId(), owner.getDomainId(), owner.getId(), offering.getId(), size); + vol.setFormat(this.getSupportedImageFormatForCluster(template.getHypervisorType())); if (vm != null) { vol.setInstanceId(vm.getId()); } @@ -1442,36 +1438,32 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { } return toDiskProfile(vol, offering); } - - private String getSupportedImageFormatForCluster(Long clusterId) { - ClusterVO cluster = ApiDBUtils.findClusterById(clusterId); - if (cluster.getHypervisorType() == HypervisorType.XenServer) { - return "vhd"; - } else if (cluster.getHypervisorType() == HypervisorType.KVM) { - return "qcow2"; - } else if (cluster.getHypervisorType() == HypervisorType.VMware) { - return "ova"; - } else if (cluster.getHypervisorType() == HypervisorType.Ovm) { - return "raw"; + private ImageFormat getSupportedImageFormatForCluster(HypervisorType hyperType) { + if (hyperType == HypervisorType.XenServer) { + return ImageFormat.VHD; + } else if (hyperType == HypervisorType.KVM) { + return ImageFormat.QCOW2; + } else if (hyperType == HypervisorType.VMware) { + return ImageFormat.OVA; + } else if (hyperType == HypervisorType.Ovm) { + return ImageFormat.RAW; } else { return null; } } - + private VolumeInfo copyVolume(StoragePoolVO rootDiskPool , VolumeInfo volume, VMInstanceVO vm, VMTemplateVO rootDiskTmplt, DataCenterVO dcVO, HostPodVO pod, DiskOfferingVO diskVO, ServiceOfferingVO svo, HypervisorType rootDiskHyperType) throws NoTransitionException { - VolumeHostVO volHostVO = _volumeHostDao.findByHostVolume(volume.getDataStore().getId(), volume.getId()); - if (!volHostVO + + if (!volume .getFormat() - .getFileExtension() .equals( - getSupportedImageFormatForCluster(rootDiskPool - .getClusterId()))) { + getSupportedImageFormatForCluster(rootDiskHyperType))) { throw new InvalidParameterValueException( "Failed to attach volume to VM since volumes format " - + volHostVO.getFormat() + + volume.getFormat() .getFileExtension() + " is not compatible with the vm hypervisor type"); } @@ -1518,39 +1510,43 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { ResourceType.primary_storage, new Long(volume.getSize())); } } - return vol; + + VolumeVO volVO = this._volsDao.findById(vol.getId()); + volVO.setFormat(this.getSupportedImageFormatForCluster(rootDiskHyperType)); + this._volsDao.update(volVO.getId(), volVO); + return this.volFactory.getVolume(volVO.getId()); } private boolean needMoveVolume(VolumeVO rootVolumeOfVm, VolumeInfo volume) { - DataStore storeForRootVol = this.dataStoreMgr.getPrimaryDataStore(rootVolumeOfVm.getPoolId()); - DataStore storeForDataVol = this.dataStoreMgr.getPrimaryDataStore(volume.getPoolId()); - + DataStore storeForRootVol = dataStoreMgr.getPrimaryDataStore(rootVolumeOfVm.getPoolId()); + DataStore storeForDataVol = dataStoreMgr.getPrimaryDataStore(volume.getPoolId()); + Scope storeForRootStoreScope = storeForRootVol.getScope(); if (storeForRootStoreScope == null) { throw new CloudRuntimeException("Can't get scope of data store: " + storeForRootVol.getId()); } - + Scope storeForDataStoreScope = storeForDataVol.getScope(); if (storeForDataStoreScope == null) { throw new CloudRuntimeException("Can't get scope of data store: " + storeForDataVol.getId()); } - + if (storeForDataStoreScope.getScopeType() == ScopeType.ZONE) { return false; } - + if (storeForRootStoreScope.getScopeType() != storeForDataStoreScope.getScopeType()) { throw new CloudRuntimeException("Can't move volume between scope: " + storeForDataStoreScope.getScopeType() + " and " + storeForRootStoreScope.getScopeType()); } - + return !storeForRootStoreScope.isSameScope(storeForDataStoreScope); } - + private VolumeVO sendAttachVolumeCommand(UserVmVO vm, VolumeVO volume, Long deviceId) { String errorMsg = "Failed to attach volume: " + volume.getName() + " to VM: " + vm.getHostName(); boolean sendCommand = (vm.getState() == State.Running); - AttachVolumeAnswer answer = null; + AttachAnswer answer = null; Long hostId = vm.getHostId(); if (hostId == null) { hostId = vm.getLastHostId(); @@ -1562,21 +1558,11 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { } if (sendCommand) { - StoragePoolVO volumePool = _storagePoolDao.findById(volume - .getPoolId()); - AttachVolumeCommand cmd = new AttachVolumeCommand(true, - vm.getInstanceName(), volume.getPoolType(), - volume.getFolder(), volume.getPath(), volume.getName(), - deviceId, volume.getChainInfo()); - cmd.setPoolUuid(volumePool.getUuid()); - DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); - cmd.setBytesReadRate(storageMgr.getDiskBytesReadRate(null, diskOffering)); - cmd.setBytesWriteRate(storageMgr.getDiskBytesWriteRate(null, diskOffering)); - cmd.setIopsReadRate(storageMgr.getDiskIopsReadRate(null, diskOffering)); - cmd.setIopsWriteRate(storageMgr.getDiskIopsWriteRate(null, diskOffering)); - + DataTO volTO = volFactory.getVolume(volume.getId()).getTO(); + DiskTO disk = new DiskTO(volTO, deviceId, volume.getVolumeType()); + AttachCommand cmd = new AttachCommand(disk, vm.getInstanceName()); try { - answer = (AttachVolumeAnswer) _agentMgr.send(hostId, cmd); + answer = (AttachAnswer) _agentMgr.send(hostId, cmd); } catch (Exception e) { throw new CloudRuntimeException(errorMsg + " due to: " + e.getMessage()); @@ -1586,8 +1572,9 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { if (!sendCommand || (answer != null && answer.getResult())) { // Mark the volume as attached if (sendCommand) { + DiskTO disk = answer.getDisk(); _volsDao.attachVolume(volume.getId(), vm.getId(), - answer.getDeviceId()); + disk.getDiskSeq()); } else { _volsDao.attachVolume(volume.getId(), vm.getId(), deviceId); } @@ -1609,7 +1596,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { throw new CloudRuntimeException(errorMsg); } } - + private int getMaxDataVolumesSupported(UserVmVO vm) { Long hostId = vm.getHostId(); if (hostId == null) { @@ -1631,7 +1618,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { return maxDataVolumesSupported.intValue(); } - + @Override @ActionEvent(eventType = EventTypes.EVENT_VOLUME_ATTACH, eventDescription = "attaching volume", async = true) public Volume attachVolumeToVM(AttachVolumeCmd command) { @@ -1716,9 +1703,9 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { List vmSnapshots = _vmSnapshotDao.findByVm(vmId); if(vmSnapshots.size() > 0){ throw new InvalidParameterValueException( - "Unable to attach volume, please specify a VM that does not have VM snapshots"); + "Unable to attach volume, please specify a VM that does not have VM snapshots"); } - + // permission check _accountMgr.checkAccess(caller, null, true, volume, vm); @@ -1752,7 +1739,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { + " to a " + rootDiskHyperType + " vm"); } - + deviceId = getDeviceId(vmId, deviceId); VolumeInfo volumeOnPrimaryStorage = volume; if (volume.getState().equals(Volume.State.Allocated) @@ -1888,7 +1875,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { } // Check that the VM is in the correct state - UserVmVO vm = this._userVmDao.findById(vmId); + UserVmVO vm = _userVmDao.findById(vmId); if (vm.getState() != State.Running && vm.getState() != State.Stopped && vm.getState() != State.Destroyed) { throw new InvalidParameterValueException( @@ -1899,7 +1886,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { List vmSnapshots = _vmSnapshotDao.findByVm(vmId); if(vmSnapshots.size() > 0){ throw new InvalidParameterValueException( - "Unable to detach volume, the specified volume is attached to a VM that has VM snapshots."); + "Unable to detach volume, the specified volume is attached to a VM that has VM snapshots."); } AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor @@ -1925,24 +1912,9 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { Answer answer = null; if (sendCommand) { - AttachVolumeCommand cmd = new AttachVolumeCommand(false, - vm.getInstanceName(), volume.getPoolType(), - volume.getFolder(), volume.getPath(), volume.getName(), - cmmd.getDeviceId() != null ? cmmd.getDeviceId() : volume - .getDeviceId(), volume.getChainInfo()); - - StoragePoolVO volumePool = _storagePoolDao.findById(volume - .getPoolId()); - cmd.setPoolUuid(volumePool.getUuid()); - DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); - cmd.setBytesReadRate(storageMgr.getDiskBytesReadRate(null, diskOffering)); - cmd.setBytesWriteRate(storageMgr.getDiskBytesWriteRate(null, diskOffering)); - cmd.setIopsReadRate(storageMgr.getDiskIopsReadRate(null, diskOffering)); - cmd.setIopsWriteRate(storageMgr.getDiskIopsWriteRate(null, diskOffering)); - - // Collect vm disk statistics from host before stopping Vm - _userVmMgr.collectVmDiskStatistics(vm); - + DataTO volTO = volFactory.getVolume(volume.getId()).getTO(); + DiskTO disk = new DiskTO(volTO, volume.getDeviceId(), volume.getVolumeType()); + DettachCommand cmd = new DettachCommand(disk, vm.getInstanceName()); try { answer = _agentMgr.send(vm.getHostId(), cmd); } catch (Exception e) { @@ -1954,12 +1926,6 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { if (!sendCommand || (answer != null && answer.getResult())) { // Mark the volume as detached _volsDao.detachVolume(volume.getId()); - if (answer != null && answer instanceof AttachVolumeAnswer) { - volume.setChainInfo(((AttachVolumeAnswer) answer) - .getChainInfo()); - _volsDao.update(volume.getId(), volume); - } - return _volsDao.findById(volumeId); } else { @@ -1974,10 +1940,10 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { } } - - - + + + @DB protected VolumeVO switchVolume(VolumeVO existingVolume, @@ -2018,13 +1984,13 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { } - + @Override public void release(VirtualMachineProfile profile) { // add code here } - + @Override @DB public void cleanupVolumes(long vmId) throws ConcurrentOperationException { @@ -2040,7 +2006,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { // This check is for VM in Error state (volume is already // destroyed) if (!vol.getState().equals(Volume.State.Destroy)) { - this.volService.destroyVolume(vol.getId()); + volService.destroyVolume(vol.getId()); } toBeExpunged.add(vol); } else { @@ -2053,7 +2019,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { txn.commit(); AsyncCallFuture future = null; for (VolumeVO expunge : toBeExpunged) { - future = this.volService.expungeVolumeAsync(this.volFactory.getVolume(expunge.getId())); + future = volService.expungeVolumeAsync(volFactory.getVolume(expunge.getId())); try { future.get(); } catch (InterruptedException e) { @@ -2116,7 +2082,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { "the parameter livemigrate should be specified"); } - StoragePool destPool = (StoragePool)this.dataStoreMgr.getDataStore(storagePoolId, DataStoreRole.Primary); + StoragePool destPool = (StoragePool)dataStoreMgr.getDataStore(storagePoolId, DataStoreRole.Primary); if (destPool == null) { throw new InvalidParameterValueException( "Failed to find the destination storage pool: " @@ -2139,12 +2105,12 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { @DB protected Volume migrateVolume(Volume volume, StoragePool destPool) { - VolumeInfo vol = this.volFactory.getVolume(volume.getId()); - AsyncCallFuture future = this.volService.copyVolume(vol, (DataStore)destPool); + VolumeInfo vol = volFactory.getVolume(volume.getId()); + AsyncCallFuture future = volService.copyVolume(vol, (DataStore)destPool); try { VolumeApiResult result = future.get(); if (result.isFailed()) { - s_logger.debug("migrate volume failed:" + result.getResult()); + s_logger.error("migrate volume failed:" + result.getResult()); return null; } return result.getVolume(); @@ -2159,8 +2125,8 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { @DB protected Volume liveMigrateVolume(Volume volume, StoragePool destPool) { - VolumeInfo vol = this.volFactory.getVolume(volume.getId()); - AsyncCallFuture future = this.volService.migrateVolume(vol, (DataStore)destPool); + VolumeInfo vol = volFactory.getVolume(volume.getId()); + AsyncCallFuture future = volService.migrateVolume(vol, (DataStore)destPool); try { VolumeApiResult result = future.get(); if (result.isFailed()) { @@ -2187,7 +2153,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { for (Map.Entry entry : volumeToPool.entrySet()) { VolumeVO volume = entry.getKey(); StoragePoolVO storagePool = entry.getValue(); - StoragePool destPool = (StoragePool)this.dataStoreMgr.getDataStore(storagePool.getId(), + StoragePool destPool = (StoragePool)dataStoreMgr.getDataStore(storagePool.getId(), DataStoreRole.Primary); if (volume.getInstanceId() != vm.getId()) { @@ -2199,10 +2165,10 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { throw new CloudRuntimeException("Failed to find the destination storage pool " + storagePool.getId()); } - volumeMap.put(this.volFactory.getVolume(volume.getId()), (DataStore)destPool); + volumeMap.put(volFactory.getVolume(volume.getId()), (DataStore)destPool); } - AsyncCallFuture future = this.volService.migrateVolumes(volumeMap, vmTo, srcHost, destHost); + AsyncCallFuture future = volService.migrateVolumes(volumeMap, vmTo, srcHost, destHost); try { CommandResult result = future.get(); if (result.isFailed()) { @@ -2254,7 +2220,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { } return true; } - + @Override public void prepareForMigration( VirtualMachineProfile vm, @@ -2265,41 +2231,22 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { } for (VolumeVO vol : vols) { - PrimaryDataStoreInfo pool = (PrimaryDataStoreInfo)this.dataStoreMgr.getDataStore(vol.getPoolId(), DataStoreRole.Primary); - ServiceOfferingVO offering = _offeringDao.findById(vm.getServiceOfferingId()); - DiskOfferingVO diskOffering = _diskOfferingDao.findById(vol.getDiskOfferingId()); - VolumeTO newVolume = new VolumeTO(vol, pool); - if (vol.getVolumeType() == Type.ROOT) { - newVolume.setBytesReadRate(storageMgr.getDiskBytesReadRate(offering, diskOffering)); - newVolume.setBytesWriteRate(storageMgr.getDiskBytesWriteRate(offering, diskOffering)); - newVolume.setIopsReadRate(storageMgr.getDiskIopsReadRate(offering, diskOffering)); - newVolume.setIopsWriteRate(storageMgr.getDiskIopsWriteRate(offering, diskOffering)); - } else { - newVolume.setBytesReadRate(storageMgr.getDiskBytesReadRate(null, diskOffering)); - newVolume.setBytesWriteRate(storageMgr.getDiskBytesWriteRate(null, diskOffering)); - newVolume.setIopsReadRate(storageMgr.getDiskIopsReadRate(null, diskOffering)); - newVolume.setIopsWriteRate(storageMgr.getDiskIopsWriteRate(null, diskOffering)); - } - vm.addDisk(newVolume); + DataTO volTO = volFactory.getVolume(vol.getId()).getTO(); + DiskTO disk = new DiskTO(volTO, vol.getDeviceId(), vol.getVolumeType()); + vm.addDisk(disk); } if (vm.getType() == VirtualMachine.Type.User) { UserVmVO userVM = (UserVmVO) vm.getVirtualMachine(); if (userVM.getIsoId() != null) { - Pair isoPathPair = this._tmpltMgr.getAbsoluteIsoPath( - userVM.getIsoId(), userVM.getDataCenterId()); - if (isoPathPair != null) { - String isoPath = isoPathPair.first(); - VolumeTO iso = new VolumeTO(vm.getId(), Volume.Type.ISO, - StoragePoolType.ISO, null, null, null, isoPath, 0, - null, null); - vm.addDisk(iso); - } + DataTO dataTO = tmplFactory.getTemplate(userVM.getIsoId(), DataStoreRole.Image, userVM.getDataCenterId()).getTO(); + DiskTO iso = new DiskTO(dataTO, 3L, Volume.Type.ISO); + vm.addDisk(iso); } } } - + private static enum VolumeTaskType { RECREATE, @@ -2316,7 +2263,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { this.volume = volume; } } - + private List getTasks(List vols, Map destVols) throws StorageUnavailableException { boolean recreate = _recreateSystemVmEnabled; List tasks = new ArrayList(); @@ -2404,11 +2351,11 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { tasks.add(task); } } - + return tasks; } - - private Pair recreateVolume(VolumeVO vol, VirtualMachineProfile vm, + + private Pair recreateVolume(VolumeVO vol, VirtualMachineProfile vm, DeployDestination dest) throws StorageUnavailableException { VolumeVO newVol; boolean recreate = _recreateSystemVmEnabled; @@ -2446,10 +2393,10 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { Long templateId = newVol.getTemplateId(); AsyncCallFuture future = null; if (templateId == null) { - future = this.volService.createVolumeAsync(volume, destPool); + future = volService.createVolumeAsync(volume, destPool); } else { - TemplateInfo templ = this.tmplFactory.getTemplate(templateId); - future = this.volService.createVolumeFromTemplateAsync(volume, destPool.getId(), templ); + TemplateInfo templ = tmplFactory.getTemplate(templateId, DataStoreRole.Image); + future = volService.createVolumeFromTemplateAsync(volume, destPool.getId(), templ); } VolumeApiResult result = null; try { @@ -2460,7 +2407,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { throw new StorageUnavailableException("Unable to create " + newVol + ":" + result.getResult(), destPool.getId()); } - newVol = this._volsDao.findById(newVol.getId()); + newVol = _volsDao.findById(newVol.getId()); } catch (InterruptedException e) { s_logger.error("Unable to create " + newVol, e); throw new StorageUnavailableException("Unable to create " @@ -2470,15 +2417,15 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { throw new StorageUnavailableException("Unable to create " + newVol + ":" + e.toString(), destPool.getId()); } - + return new Pair(newVol, destPool); } - + @Override public void prepare(VirtualMachineProfile vm, DeployDestination dest) throws StorageUnavailableException, InsufficientStorageCapacityException, ConcurrentOperationException { - + if (dest == null) { if (s_logger.isDebugEnabled()) { s_logger.debug("DeployDestination cannot be null, cannot prepare Volumes for the vm: " @@ -2510,24 +2457,12 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { pool = (StoragePool)dataStoreMgr.getDataStore(result.second().getId(), DataStoreRole.Primary); vol = result.first(); } - ServiceOfferingVO offering = _offeringDao.findById(vm.getServiceOfferingId()); - DiskOfferingVO diskOffering = _diskOfferingDao.findById(vol.getDiskOfferingId()); - VolumeTO newVolume = new VolumeTO(vol, pool); - if (vol.getVolumeType() == Type.ROOT) { - newVolume.setBytesReadRate(storageMgr.getDiskBytesReadRate(offering, diskOffering)); - newVolume.setBytesWriteRate(storageMgr.getDiskBytesWriteRate(offering, diskOffering)); - newVolume.setIopsReadRate(storageMgr.getDiskIopsReadRate(offering, diskOffering)); - newVolume.setIopsWriteRate(storageMgr.getDiskIopsWriteRate(offering, diskOffering)); - } else { - newVolume.setBytesReadRate(storageMgr.getDiskBytesReadRate(null, diskOffering)); - newVolume.setBytesWriteRate(storageMgr.getDiskBytesWriteRate(null, diskOffering)); - newVolume.setIopsReadRate(storageMgr.getDiskIopsReadRate(null, diskOffering)); - newVolume.setIopsWriteRate(storageMgr.getDiskIopsWriteRate(null, diskOffering)); - } - vm.addDisk(newVolume); + DataTO volumeTO = volFactory.getVolume(vol.getId()).getTO(); + DiskTO disk = new DiskTO(volumeTO, vol.getDeviceId(), vol.getVolumeType()); + vm.addDisk(disk); } } - + private Long getDeviceId(long vmId, Long deviceId) { // allocate deviceId List vols = _volsDao.findByInstance(vmId); @@ -2554,58 +2489,18 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { } deviceId = Long.parseLong(devIds.iterator().next()); } - + return deviceId; } - + private boolean stateTransitTo(Volume vol, Volume.Event event) throws NoTransitionException { return _volStateMachine.transitTo(vol, event, null, _volsDao); } - - private String validateUrl(String url) { - try { - URI uri = new URI(url); - if ((uri.getScheme() == null) - || (!uri.getScheme().equalsIgnoreCase("http") - && !uri.getScheme().equalsIgnoreCase("https") && !uri - .getScheme().equalsIgnoreCase("file"))) { - throw new IllegalArgumentException( - "Unsupported scheme for url: " + url); - } - int port = uri.getPort(); - if (!(port == 80 || port == 443 || port == -1)) { - throw new IllegalArgumentException( - "Only ports 80 and 443 are allowed"); - } - String host = uri.getHost(); - try { - InetAddress hostAddr = InetAddress.getByName(host); - if (hostAddr.isAnyLocalAddress() - || hostAddr.isLinkLocalAddress() - || hostAddr.isLoopbackAddress() - || hostAddr.isMulticastAddress()) { - throw new IllegalArgumentException( - "Illegal host specified in url"); - } - if (hostAddr instanceof Inet6Address) { - throw new IllegalArgumentException( - "IPV6 addresses not supported (" - + hostAddr.getHostAddress() + ")"); - } - } catch (UnknownHostException uhe) { - throw new IllegalArgumentException("Unable to resolve " + host); - } - return uri.toString(); - } catch (URISyntaxException e) { - throw new IllegalArgumentException("Invalid URL " + url); - } - } - @Override public boolean canVmRestartOnAnotherServer(long vmId) { List vols = _volsDao.findCreatedByInstance(vmId); @@ -2616,7 +2511,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { } return true; } - + @Override public boolean configure(String name, Map params) throws ConfigurationException { @@ -2637,21 +2532,6 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { _copyvolumewait = NumbersUtil.parseInt(value, Integer.parseInt(Config.CopyVolumeWait.getDefaultValue())); - HostTemplateStatesSearch = _vmTemplateHostDao.createSearchBuilder(); - HostTemplateStatesSearch.and("id", HostTemplateStatesSearch.entity() - .getTemplateId(), SearchCriteria.Op.EQ); - HostTemplateStatesSearch.and("state", HostTemplateStatesSearch.entity() - .getDownloadState(), SearchCriteria.Op.EQ); - - SearchBuilder HostSearch = _hostDao.createSearchBuilder(); - HostSearch.and("dcId", HostSearch.entity().getDataCenterId(), - SearchCriteria.Op.EQ); - - HostTemplateStatesSearch.join("host", HostSearch, HostSearch.entity() - .getId(), HostTemplateStatesSearch.entity().getHostId(), - JoinBuilder.JoinType.INNER); - HostSearch.done(); - HostTemplateStatesSearch.done(); return true; } @@ -2669,11 +2549,11 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { public String getName() { return "Volume Manager"; } - + @Override public void destroyVolume(VolumeVO volume) { try { - this.volService.destroyVolume(volume.getId()); + volService.destroyVolume(volume.getId()); } catch (ConcurrentOperationException e) { s_logger.debug("Failed to destroy volume" + volume.getId(), e); throw new CloudRuntimeException("Failed to destroy volume" + volume.getId(), e); @@ -2681,6 +2561,188 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { } + @Override + public Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account) throws ResourceAllocationException { + VolumeInfo volume = volFactory.getVolume(volumeId); + if (volume == null) { + throw new InvalidParameterValueException("Creating snapshot failed due to volume:" + volumeId + " doesn't exist"); + } + + if (volume.getState() != Volume.State.Ready) { + throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in " + Volume.State.Ready + " state but " + volume.getState() + ". Cannot take snapshot."); + } + + CreateSnapshotPayload payload = new CreateSnapshotPayload(); + payload.setSnapshotId(snapshotId); + payload.setSnapshotPolicyId(policyId); + payload.setAccount(account); + volume.addPayload(payload); + return volService.takeSnapshot(volume); + } + + @Override + public Snapshot allocSnapshot(Long volumeId, Long policyId) throws ResourceAllocationException { + Account caller = UserContext.current().getCaller(); + + VolumeInfo volume = volFactory.getVolume(volumeId); + if (volume == null) { + throw new InvalidParameterValueException("Creating snapshot failed due to volume:" + volumeId + " doesn't exist"); + } + DataCenter zone = _dcDao.findById(volume.getDataCenterId()); + if (zone == null) { + throw new InvalidParameterValueException("Can't find zone by id " + volume.getDataCenterId()); + } + + if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) { + throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: " + zone.getName()); + } + + if (volume.getState() != Volume.State.Ready) { + throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in " + Volume.State.Ready + " state but " + volume.getState() + ". Cannot take snapshot."); + } + + if ( volume.getTemplateId() != null ) { + VMTemplateVO template = _templateDao.findById(volume.getTemplateId()); + if( template != null && template.getTemplateType() == Storage.TemplateType.SYSTEM ) { + throw new InvalidParameterValueException("VolumeId: " + volumeId + " is for System VM , Creating snapshot against System VM volumes is not supported"); + } + } + + StoragePool storagePool = (StoragePool)volume.getDataStore(); + if (storagePool == null) { + throw new InvalidParameterValueException("VolumeId: " + volumeId + " please attach this volume to a VM before create snapshot for it"); + } + + return snapshotMgr.allocSnapshot(volumeId, policyId); + } + + + @Override + @ActionEvent(eventType = EventTypes.EVENT_VOLUME_EXTRACT, eventDescription = "extracting volume", async = true) + public String extractVolume(ExtractVolumeCmd cmd) { + Long volumeId = cmd.getId(); + Long zoneId = cmd.getZoneId(); + String mode = cmd.getMode(); + Account account = UserContext.current().getCaller(); + + if (!_accountMgr.isRootAdmin(account.getType()) && ApiDBUtils.isExtractionDisabled()) { + throw new PermissionDeniedException("Extraction has been disabled by admin"); + } + + VolumeVO volume = _volumeDao.findById(volumeId); + if (volume == null) { + InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find volume with specified volumeId"); + ex.addProxyObject(volumeId.toString(), "volumeId"); + throw ex; + } + + // perform permission check + _accountMgr.checkAccess(account, null, true, volume); + + if (_dcDao.findById(zoneId) == null) { + throw new InvalidParameterValueException("Please specify a valid zone."); + } + if (volume.getPoolId() == null) { + throw new InvalidParameterValueException("The volume doesnt belong to a storage pool so cant extract it"); + } + // Extract activity only for detached volumes or for volumes whose + // instance is stopped + if (volume.getInstanceId() != null && ApiDBUtils.findVMInstanceById(volume.getInstanceId()).getState() != State.Stopped) { + s_logger.debug("Invalid state of the volume with ID: " + volumeId + + ". It should be either detached or the VM should be in stopped state."); + PermissionDeniedException ex = new PermissionDeniedException( + "Invalid state of the volume with specified ID. It should be either detached or the VM should be in stopped state."); + ex.addProxyObject(volume.getUuid(), "volumeId"); + throw ex; + } + + if (volume.getVolumeType() != Volume.Type.DATADISK) { + // Datadisk dont have any template dependence. + + VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId()); + if (template != null) { // For ISO based volumes template = null and + // we allow extraction of all ISO based + // volumes + boolean isExtractable = template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM; + if (!isExtractable && account != null && account.getType() != Account.ACCOUNT_TYPE_ADMIN) { + // Global admins are always allowed to extract + PermissionDeniedException ex = new PermissionDeniedException("The volume with specified volumeId is not allowed to be extracted"); + ex.addProxyObject(volume.getUuid(), "volumeId"); + throw ex; + } + } + } + + Upload.Mode extractMode; + if (mode == null || (!mode.equals(Upload.Mode.FTP_UPLOAD.toString()) && !mode.equals(Upload.Mode.HTTP_DOWNLOAD.toString()))) { + throw new InvalidParameterValueException("Please specify a valid extract Mode "); + } else { + extractMode = mode.equals(Upload.Mode.FTP_UPLOAD.toString()) ? Upload.Mode.FTP_UPLOAD : Upload.Mode.HTTP_DOWNLOAD; + } + + // Clean up code to remove all those previous uploadVO and uploadMonitor code. Previous code is trying to fake an async operation purely in + // db table with uploadVO and async_job entry, but internal implementation is actually synchronous. + StoragePool srcPool = (StoragePool) this.dataStoreMgr.getPrimaryDataStore(volume.getPoolId()); + ImageStoreEntity secStore = (ImageStoreEntity) this.dataStoreMgr.getImageStore(zoneId); + String secondaryStorageURL = secStore.getUri(); + + String value = this._configDao.getValue(Config.CopyVolumeWait.toString()); + int copyvolumewait = NumbersUtil.parseInt(value, Integer.parseInt(Config.CopyVolumeWait.getDefaultValue())); + // Copy volume from primary to secondary storage + VolumeInfo srcVol = this.volFactory.getVolume(volume.getId()); + AsyncCallFuture cvAnswer = this.volService.copyVolume(srcVol, secStore); + // Check if you got a valid answer. + VolumeApiResult cvResult = null; + try { + cvResult = cvAnswer.get(); + } catch (InterruptedException e1) { + s_logger.debug("failed copy volume", e1); + throw new CloudRuntimeException("Failed to copy volume", e1); + } catch (ExecutionException e1) { + s_logger.debug("failed copy volume", e1); + throw new CloudRuntimeException("Failed to copy volume", e1); + } + if (cvResult == null || cvResult.isFailed()) { + String errorString = "Failed to copy the volume from the source primary storage pool to secondary storage."; + throw new CloudRuntimeException(errorString); + } + + VolumeInfo vol = cvResult.getVolume(); + String volumeLocalPath = vol.getPath(); + String volumeName = StringUtils.substringBeforeLast(StringUtils.substringAfterLast(volumeLocalPath, "/"), "."); + // volss, handle the ova special case; + if (getFormatForPool(srcPool) == "ova") { + // TODO: need to handle this for S3 as secondary storage + CreateVolumeOVACommand cvOVACmd = new CreateVolumeOVACommand(secondaryStorageURL, volumeLocalPath, volumeName, srcPool, copyvolumewait); + CreateVolumeOVAAnswer OVAanswer = null; + + try { + cvOVACmd.setContextParam("hypervisor", HypervisorType.VMware.toString()); + // for extract volume, create the ova file here; + OVAanswer = (CreateVolumeOVAAnswer) storageMgr.sendToPool(srcPool, cvOVACmd); + } catch (StorageUnavailableException e) { + s_logger.debug("Storage unavailable"); + } + } + return secStore.createEntityExtractUrl(vol.getPath(), vol.getFormat()); + } + + private String getFormatForPool(StoragePool pool) { + ClusterVO cluster = ApiDBUtils.findClusterById(pool.getClusterId()); + + if (cluster.getHypervisorType() == HypervisorType.XenServer) { + return "vhd"; + } else if (cluster.getHypervisorType() == HypervisorType.KVM) { + return "qcow2"; + } else if (cluster.getHypervisorType() == HypervisorType.VMware) { + return "ova"; + } else if (cluster.getHypervisorType() == HypervisorType.Ovm) { + return "raw"; + } else { + return null; + } + } + @Override public String getVmNameFromVolumeId(long volumeId) { Long instanceId; diff --git a/core/src/com/cloud/agent/api/DeleteSnapshotBackupAnswer.java b/server/src/com/cloud/storage/dao/GuestOSHypervisorDao.java similarity index 71% rename from core/src/com/cloud/agent/api/DeleteSnapshotBackupAnswer.java rename to server/src/com/cloud/storage/dao/GuestOSHypervisorDao.java index 9a895d8471a..945a542d9e0 100644 --- a/core/src/com/cloud/agent/api/DeleteSnapshotBackupAnswer.java +++ b/server/src/com/cloud/storage/dao/GuestOSHypervisorDao.java @@ -14,19 +14,14 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.agent.api; +package com.cloud.storage.dao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.GuestOSHypervisorVO; +import com.cloud.utils.db.GenericDao; -public class DeleteSnapshotBackupAnswer extends Answer { - - protected DeleteSnapshotBackupAnswer() { - - } - - public DeleteSnapshotBackupAnswer(DeleteSnapshotBackupCommand cmd, boolean success, String details) { - super(cmd, success, details); - } - +public interface GuestOSHypervisorDao extends GenericDao { + HypervisorType findHypervisorTypeByGuestOsId(long guestOsId); } diff --git a/server/src/com/cloud/storage/dao/GuestOSHypervisorDaoImpl.java b/server/src/com/cloud/storage/dao/GuestOSHypervisorDaoImpl.java new file mode 100644 index 00000000000..48de6e9ae80 --- /dev/null +++ b/server/src/com/cloud/storage/dao/GuestOSHypervisorDaoImpl.java @@ -0,0 +1,49 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.storage.dao; + +import javax.ejb.Local; + +import org.springframework.stereotype.Component; + +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.GuestOSHypervisorVO; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + +@Component +@Local(value = { GuestOSHypervisorDao.class }) +public class GuestOSHypervisorDaoImpl extends GenericDaoBase implements GuestOSHypervisorDao { + + protected final SearchBuilder guestOsSearch; + + protected GuestOSHypervisorDaoImpl() { + guestOsSearch = createSearchBuilder(); + guestOsSearch.and("guest_os_id", guestOsSearch.entity().getGuestOsId(), SearchCriteria.Op.EQ); + guestOsSearch.done(); + } + + @Override + public HypervisorType findHypervisorTypeByGuestOsId(long guestOsId) { + SearchCriteria sc = guestOsSearch.create(); + sc.setParameters("guest_os_id", guestOsId); + GuestOSHypervisorVO goh = findOneBy(sc); + return HypervisorType.getType(goh.getHypervisorType()); + } + +} diff --git a/server/src/com/cloud/storage/download/DownloadAbandonedState.java b/server/src/com/cloud/storage/download/DownloadAbandonedState.java index 200683c4c33..187683b7e73 100644 --- a/server/src/com/cloud/storage/download/DownloadAbandonedState.java +++ b/server/src/com/cloud/storage/download/DownloadAbandonedState.java @@ -16,7 +16,9 @@ // under the License. package com.cloud.storage.download; -import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType; +import org.apache.cloudstack.storage.command.DownloadProgressCommand.RequestType; + +import com.cloud.agent.api.storage.DownloadAnswer; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; public class DownloadAbandonedState extends DownloadInactiveState { @@ -34,7 +36,8 @@ public class DownloadAbandonedState extends DownloadInactiveState { public void onEntry(String prevState, DownloadEvent event, Object evtObj) { super.onEntry(prevState, event, evtObj); if (!prevState.equalsIgnoreCase(getName())){ - getDownloadListener().updateDatabase(Status.ABANDONED, "Download canceled"); + DownloadAnswer answer = new DownloadAnswer("Download canceled", Status.ABANDONED); + getDownloadListener().callback(answer); getDownloadListener().cancelStatusTask(); getDownloadListener().cancelTimeoutTask(); getDownloadListener().sendCommand(RequestType.ABORT); diff --git a/server/src/com/cloud/storage/download/DownloadActiveState.java b/server/src/com/cloud/storage/download/DownloadActiveState.java index f2cd5af4c71..44efa4bd4f4 100644 --- a/server/src/com/cloud/storage/download/DownloadActiveState.java +++ b/server/src/com/cloud/storage/download/DownloadActiveState.java @@ -16,10 +16,10 @@ // under the License. package com.cloud.storage.download; +import org.apache.cloudstack.storage.command.DownloadProgressCommand.RequestType; import org.apache.log4j.Level; import com.cloud.agent.api.storage.DownloadAnswer; -import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; public abstract class DownloadActiveState extends DownloadState { @@ -64,7 +64,7 @@ public abstract class DownloadActiveState extends DownloadState { } if (event==DownloadEvent.DOWNLOAD_ANSWER) { - getDownloadListener().updateDatabase((DownloadAnswer)evtObj); + getDownloadListener().callback((DownloadAnswer)evtObj); getDownloadListener().setLastUpdated(); } diff --git a/server/src/com/cloud/storage/download/DownloadCompleteState.java b/server/src/com/cloud/storage/download/DownloadCompleteState.java index 6e8edcbf691..ea2ae9107f6 100644 --- a/server/src/com/cloud/storage/download/DownloadCompleteState.java +++ b/server/src/com/cloud/storage/download/DownloadCompleteState.java @@ -16,7 +16,8 @@ // under the License. package com.cloud.storage.download; -import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType; +import org.apache.cloudstack.storage.command.DownloadProgressCommand.RequestType; + import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; public class DownloadCompleteState extends DownloadInactiveState { diff --git a/server/src/com/cloud/storage/download/DownloadErrorState.java b/server/src/com/cloud/storage/download/DownloadErrorState.java index 0fdfd523ba5..aedb56e7250 100644 --- a/server/src/com/cloud/storage/download/DownloadErrorState.java +++ b/server/src/com/cloud/storage/download/DownloadErrorState.java @@ -16,10 +16,10 @@ // under the License. package com.cloud.storage.download; +import org.apache.cloudstack.storage.command.DownloadProgressCommand.RequestType; import org.apache.log4j.Level; import com.cloud.agent.api.storage.DownloadAnswer; -import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; public class DownloadErrorState extends DownloadInactiveState { @@ -76,10 +76,12 @@ public class DownloadErrorState extends DownloadInactiveState { getDownloadListener().logDisconnect(); getDownloadListener().cancelStatusTask(); getDownloadListener().cancelTimeoutTask(); - getDownloadListener().updateDatabase(Status.DOWNLOAD_ERROR, "Storage agent or storage VM disconnected"); + DownloadAnswer answer = new DownloadAnswer("Storage agent or storage VM disconnected", Status.DOWNLOAD_ERROR); + getDownloadListener().callback(answer); getDownloadListener().log("Entering download error state because the storage host disconnected", Level.WARN); } else if (event==DownloadEvent.TIMEOUT_CHECK){ - getDownloadListener().updateDatabase(Status.DOWNLOAD_ERROR, "Timeout waiting for response from storage host"); + DownloadAnswer answer = new DownloadAnswer("Timeout waiting for response from storage host", Status.DOWNLOAD_ERROR); + getDownloadListener().callback(answer); getDownloadListener().log("Entering download error state: timeout waiting for response from storage host", Level.WARN); } getDownloadListener().setDownloadInactive(Status.DOWNLOAD_ERROR); diff --git a/server/src/com/cloud/storage/download/DownloadListener.java b/server/src/com/cloud/storage/download/DownloadListener.java index 1d488034c5a..3b6c0dd687f 100755 --- a/server/src/com/cloud/storage/download/DownloadListener.java +++ b/server/src/com/cloud/storage/download/DownloadListener.java @@ -18,6 +18,7 @@ package com.cloud.storage.download; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Timer; import java.util.TimerTask; @@ -27,6 +28,19 @@ import javax.inject.Inject; import org.apache.log4j.Level; import org.apache.log4j.Logger; +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +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.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.storage.command.DownloadCommand; +import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType; +import org.apache.cloudstack.storage.command.DownloadProgressCommand; +import org.apache.cloudstack.storage.command.DownloadProgressCommand.RequestType; + import com.cloud.agent.Listener; import com.cloud.agent.api.AgentControlAnswer; import com.cloud.agent.api.AgentControlCommand; @@ -35,33 +49,16 @@ import com.cloud.agent.api.Command; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; import com.cloud.agent.api.StartupSecondaryStorageCommand; -import com.cloud.agent.api.StartupStorageCommand; import com.cloud.agent.api.storage.DownloadAnswer; -import com.cloud.agent.api.storage.DownloadCommand; -import com.cloud.agent.api.storage.DownloadCommand.ResourceType; -import com.cloud.agent.api.storage.DownloadProgressCommand; -import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType; -import com.cloud.alert.AlertManager; -import com.cloud.exception.AgentUnavailableException; +import com.cloud.agent.api.to.DataObjectType; import com.cloud.exception.ConnectionException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.host.HostVO; -import com.cloud.host.dao.HostDao; -import com.cloud.storage.Storage; -import com.cloud.storage.StorageManager; +import com.cloud.host.Host; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.resource.ResourceManager; import com.cloud.storage.VMTemplateHostVO; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; -import com.cloud.storage.VMTemplateVO; -import com.cloud.storage.VolumeHostVO; -import com.cloud.storage.VolumeVO; -import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VMTemplateHostDao; -import com.cloud.storage.dao.VolumeDao; -import com.cloud.storage.dao.VolumeHostDao; import com.cloud.storage.download.DownloadState.DownloadEvent; -import com.cloud.user.AccountManager; -import com.cloud.user.ResourceLimitService; -import com.cloud.utils.UriUtils; +import com.cloud.storage.upload.UploadListener; import com.cloud.utils.exception.CloudRuntimeException; /** @@ -74,9 +71,9 @@ public class DownloadListener implements Listener { private static final class StatusTask extends TimerTask { private final DownloadListener dl; private final RequestType reqType; - + public StatusTask( DownloadListener dl, RequestType req) { - this.reqType = req; + reqType = req; this.dl = dl; } @@ -86,10 +83,10 @@ public class DownloadListener implements Listener { } } - + private static final class TimeoutTask extends TimerTask { private final DownloadListener dl; - + public TimeoutTask( DownloadListener dl) { this.dl = dl; } @@ -104,103 +101,77 @@ public class DownloadListener implements Listener { public static final Logger s_logger = Logger.getLogger(DownloadListener.class.getName()); public static final int SMALL_DELAY = 100; public static final long STATUS_POLL_INTERVAL = 10000L; - + public static final String DOWNLOADED=Status.DOWNLOADED.toString(); public static final String NOT_DOWNLOADED=Status.NOT_DOWNLOADED.toString(); public static final String DOWNLOAD_ERROR=Status.DOWNLOAD_ERROR.toString(); public static final String DOWNLOAD_IN_PROGRESS=Status.DOWNLOAD_IN_PROGRESS.toString(); public static final String DOWNLOAD_ABANDONED=Status.ABANDONED.toString(); + private EndPoint _ssAgent; - private HostVO sserver; - private HostVO ssAgent; - private VMTemplateVO template; - private VolumeVO volume; - - private boolean downloadActive = true; + private DataObject object; - private VolumeHostDao volumeHostDao; - private VolumeDao _volumeDao; - private StorageManager _storageMgr; - private VMTemplateHostDao vmTemplateHostDao; - private VMTemplateDao _vmTemplateDao; - private ResourceLimitService _resourceLimitMgr; - private AccountManager _accountMgr; - private AlertManager _alertMgr; + private boolean _downloadActive = true; + private final DownloadMonitorImpl _downloadMonitor; - private final DownloadMonitorImpl downloadMonitor; - - private DownloadState currState; - - private DownloadCommand cmd; + private DownloadState _currState; - private Timer timer; + private DownloadCommand _cmd; + + private Timer _timer; + + private StatusTask _statusTask; + private TimeoutTask _timeoutTask; + private Date _lastUpdated = new Date(); + private String _jobId; + + private final Map _stateMap = new HashMap(); + private AsyncCompletionCallback _callback; + + @Inject + private ResourceManager _resourceMgr; + @Inject + private TemplateService _imageSrv; + @Inject + private DataStoreManager _storeMgr; + @Inject + private VolumeService _volumeSrv; + + // TODO: this constructor should be the one used for template only, remove other template constructor later + public DownloadListener(EndPoint ssAgent, DataStore store, DataObject object, Timer _timer, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, AsyncCompletionCallback callback) { + _ssAgent = ssAgent; + this.object = object; + _downloadMonitor = downloadMonitor; + _cmd = cmd; + initStateMachine(); + _currState=getState(Status.NOT_DOWNLOADED.toString()); + this._timer = _timer; + _timeoutTask = new TimeoutTask(this); + this._timer.schedule(_timeoutTask, 3*STATUS_POLL_INTERVAL); + _callback = callback; + DownloadAnswer answer = new DownloadAnswer("", Status.NOT_DOWNLOADED); + callback(answer); + } + + public AsyncCompletionCallback getCallback() { + return _callback; + } - private StatusTask statusTask; - private TimeoutTask timeoutTask; - private Date lastUpdated = new Date(); - private String jobId; - - private final Map stateMap = new HashMap(); - private Long templateHostId; - private Long volumeHostId; - - public DownloadListener(HostVO ssAgent, HostVO host, VMTemplateVO template, Timer _timer, VMTemplateHostDao dao, Long templHostId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VMTemplateDao templateDao, ResourceLimitService _resourceLimitMgr, AlertManager _alertMgr, AccountManager _accountMgr) { - this.ssAgent = ssAgent; - this.sserver = host; - this.template = template; - this.vmTemplateHostDao = dao; - this.downloadMonitor = downloadMonitor; - this.cmd = cmd; - this.templateHostId = templHostId; - 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; - 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; - this.volume = volume; - this.volumeHostDao = dao; - this.downloadMonitor = downloadMonitor; - this.cmd = cmd; - this.volumeHostId = volHostId; - 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._volumeDao = volumeDao; - this._storageMgr = storageMgr; - this._resourceLimitMgr = _resourceLimitMgr; - this._accountMgr = _accountMgr; - this._alertMgr = _alertMgr; - updateDatabase(Status.NOT_DOWNLOADED, ""); - } - - public void setCurrState(VMTemplateHostVO.Status currState) { - this.currState = getState(currState.toString()); + _currState = getState(currState.toString()); } private void initStateMachine() { - stateMap.put(Status.NOT_DOWNLOADED.toString(), new NotDownloadedState(this)); - stateMap.put(Status.DOWNLOADED.toString(), new DownloadCompleteState(this)); - stateMap.put(Status.DOWNLOAD_ERROR.toString(), new DownloadErrorState(this)); - stateMap.put(Status.DOWNLOAD_IN_PROGRESS.toString(), new DownloadInProgressState(this)); - stateMap.put(Status.ABANDONED.toString(), new DownloadAbandonedState(this)); + _stateMap.put(Status.NOT_DOWNLOADED.toString(), new NotDownloadedState(this)); + _stateMap.put(Status.DOWNLOADED.toString(), new DownloadCompleteState(this)); + _stateMap.put(Status.DOWNLOAD_ERROR.toString(), new DownloadErrorState(this)); + _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); + return _stateMap.get(stateName); } public void sendCommand(RequestType reqType) { @@ -210,14 +181,14 @@ public class DownloadListener implements Listener { } try { DownloadProgressCommand dcmd = new DownloadProgressCommand(getCommand(), getJobId(), reqType); - if (template == null){ + if (object.getType() == DataObjectType.VOLUME) { dcmd.setResourceType(ResourceType.VOLUME); } - downloadMonitor.send(ssAgent.getId(), dcmd, this); - } catch (AgentUnavailableException e) { + _ssAgent.sendMessageAsync(dcmd, new UploadListener.Callback(_ssAgent.getId(), this)); + } catch (Exception e) { s_logger.debug("Send command failed", e); setDisconnected(); - } + } } } @@ -231,65 +202,26 @@ public class DownloadListener implements Listener { } public void logDisconnect() { - if (template != null){ - s_logger.warn("Unable to monitor download progress of " + template.getName() + " at host " + sserver.getName()); - }else { - s_logger.warn("Unable to monitor download progress of " + volume.getName() + " at host " + sserver.getName()); - } + s_logger.warn("Unable to monitor download progress of " + object.getType() + ": " + + object.getId() + " at host " + _ssAgent.getId()); } - public synchronized void updateDatabase(Status state, String errorString) { - if (template != null){ - VMTemplateHostVO vo = vmTemplateHostDao.createForUpdate(); - vo.setDownloadState(state); - vo.setLastUpdated(new Date()); - vo.setErrorString(errorString); - vmTemplateHostDao.update(getTemplateHostId(), vo); - }else { - VolumeHostVO vo = volumeHostDao.createForUpdate(); - vo.setDownloadState(state); - vo.setLastUpdated(new Date()); - vo.setErrorString(errorString); - 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()); - }else { - s_logger.log(level, message + ", volume=" + volume.getName() + " at host " + sserver.getName()); - } - } - - private Long getTemplateHostId() { - if (templateHostId == null){ - VMTemplateHostVO templHost = vmTemplateHostDao.findByHostTemplate(sserver.getId(), template.getId()); - templateHostId = templHost.getId(); - } - return templateHostId; - } - - private Long getVolumeHostId() { - if (volumeHostId == null){ - VolumeHostVO volHost = volumeHostDao.findByHostVolume(sserver.getId(), volume.getId()); - volumeHostId = volHost.getId(); - } - return volumeHostId; + s_logger.log(level, message + ", " + object.getType() + ": " + object.getId() + " at host " + _ssAgent.getId()); } public DownloadListener(DownloadMonitorImpl monitor) { - downloadMonitor = monitor; + _downloadMonitor = monitor; } - + @Override public boolean isRecurring() { return false; } - + @Override public boolean processAnswers(long agentId, long seq, Answer[] answers) { boolean processed = false; @@ -307,17 +239,17 @@ public class DownloadListener implements Listener { } return processed; } - + private synchronized void transition(DownloadEvent event, Object evtObj) { - if (currState == null) { + if (_currState == null) { return; } - String prevName = currState.getName(); - String nextState = currState.handleEvent(event, evtObj); + String prevName = _currState.getName(); + String nextState = _currState.handleEvent(event, evtObj); if (nextState != null) { - currState = getState(nextState); - if (currState != null) { - currState.onEntry(prevName, event, evtObj); + _currState = getState(nextState); + if (_currState != null) { + _currState.onEntry(prevName, event, evtObj); } else { throw new CloudRuntimeException("Invalid next state: currState="+prevName+", evt="+event + ", next=" + nextState); } @@ -326,86 +258,11 @@ public class DownloadListener implements Listener { } } - public synchronized void updateDatabase(DownloadAnswer answer) { - if (template != null){ - VMTemplateHostVO updateBuilder = vmTemplateHostDao.createForUpdate(); - updateBuilder.setDownloadPercent(answer.getDownloadPct()); - updateBuilder.setDownloadState(answer.getDownloadStatus()); - updateBuilder.setLastUpdated(new Date()); - updateBuilder.setErrorString(answer.getErrorString()); - updateBuilder.setJobId(answer.getJobId()); - updateBuilder.setLocalDownloadPath(answer.getDownloadPath()); - updateBuilder.setInstallPath(answer.getInstallPath()); - updateBuilder.setSize(answer.getTemplateSize()); - updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize()); - - vmTemplateHostDao.update(getTemplateHostId(), updateBuilder); - - if (answer.getCheckSum() != null) { - VMTemplateVO templateDaoBuilder = _vmTemplateDao.createForUpdate(); - templateDaoBuilder.setChecksum(answer.getCheckSum()); - _vmTemplateDao.update(template.getId(), templateDaoBuilder); - } - - if (answer.getTemplateSize() > 0) { - //long hostId = vmTemplateHostDao.findByTemplateId(template.getId()).getHostId(); - long accountId = template.getAccountId(); - try { - _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(accountId), - com.cloud.configuration.Resource.ResourceType.secondary_storage, - answer.getTemplateSize() - UriUtils.getRemoteSize(template.getUrl())); - } catch (ResourceAllocationException e) { - s_logger.warn(e.getMessage()); - _alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, sserver.getDataCenterId(), - null, e.getMessage(), e.getMessage()); - } finally { - _resourceLimitMgr.recalculateResourceCount(accountId, _accountMgr.getAccount(accountId).getDomainId(), - com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal()); - } - } - - } else { - VolumeHostVO updateBuilder = volumeHostDao.createForUpdate(); - updateBuilder.setDownloadPercent(answer.getDownloadPct()); - updateBuilder.setDownloadState(answer.getDownloadStatus()); - updateBuilder.setLastUpdated(new Date()); - updateBuilder.setErrorString(answer.getErrorString()); - updateBuilder.setJobId(answer.getJobId()); - updateBuilder.setLocalDownloadPath(answer.getDownloadPath()); - updateBuilder.setInstallPath(answer.getInstallPath()); - updateBuilder.setSize(answer.getTemplateSize()); - updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize()); - - volumeHostDao.update(getVolumeHostId(), updateBuilder); - - // Update volume size in Volume table. - VolumeVO updateVolume = _volumeDao.createForUpdate(); - updateVolume.setSize(answer.getTemplateSize()); - _volumeDao.update(volume.getId(), updateVolume); - - if (answer.getTemplateSize() > 0) { - try { - String url = volumeHostDao.findByVolumeId(volume.getId()).getDownloadUrl(); - _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()), - com.cloud.configuration.Resource.ResourceType.secondary_storage, - answer.getTemplateSize() - UriUtils.getRemoteSize(url)); - } catch (ResourceAllocationException e) { - s_logger.warn(e.getMessage()); - _alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, volume.getDataCenterId(), - volume.getPodId(), e.getMessage(), e.getMessage()); - } finally { - _resourceLimitMgr.recalculateResourceCount(volume.getAccountId(), volume.getDomainId(), - com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal()); - } - } - - /*if (answer.getCheckSum() != null) { - VMTemplateVO templateDaoBuilder = _vmTemplateDao.createForUpdate(); - templateDaoBuilder.setChecksum(answer.getCheckSum()); - _vmTemplateDao.update(template.getId(), templateDaoBuilder); - }*/ - } - } + public void callback(DownloadAnswer answer) { + if ( _callback != null ){ + _callback.complete(answer); + } + } @Override public boolean processCommands(long agentId, long seq, Command[] req) { @@ -422,105 +279,112 @@ public class DownloadListener implements Listener { setDisconnected(); return true; } - + @Override - public void processConnect(HostVO agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException { + public void processConnect(Host agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException { if (cmd instanceof StartupRoutingCommand) { - downloadMonitor.handleSysTemplateDownload(agent); - } else if ( cmd instanceof StartupStorageCommand) { + List hypers = _resourceMgr.listAvailHypervisorInZone(agent.getId(), agent.getDataCenterId()); + HypervisorType hostHyper = agent.getHypervisorType(); + if (hypers.contains(hostHyper)) { + return; + } + _imageSrv.handleSysTemplateDownload(hostHyper, agent.getDataCenterId()); + } + /* This can be removed + 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); downloadMonitor.handleVolumeSync(agent); } - } else if ( cmd instanceof StartupSecondaryStorageCommand ) { - downloadMonitor.handleSync(agent.getDataCenterId()); + }*/ + else if ( cmd instanceof StartupSecondaryStorageCommand ) { + List imageStores = _storeMgr.getImageStoresByScope(new ZoneScope(agent.getDataCenterId())); + for (DataStore store : imageStores){ + _volumeSrv.handleVolumeSync(store); + _imageSrv.handleTemplateSync(store); + } } } public void setCommand(DownloadCommand _cmd) { - this.cmd = _cmd; + this._cmd = _cmd; } public DownloadCommand getCommand() { - return cmd; + return _cmd; } - + public void abandon() { transition(DownloadEvent.ABANDON_DOWNLOAD, null); } public void setJobId(String _jobId) { - this.jobId = _jobId; + this._jobId = _jobId; } public String getJobId() { - return jobId; + return _jobId; } public void scheduleStatusCheck(RequestType request) { - if (statusTask != null) statusTask.cancel(); + if (_statusTask != null) _statusTask.cancel(); - statusTask = new StatusTask(this, request); - timer.schedule(statusTask, STATUS_POLL_INTERVAL); + _statusTask = new StatusTask(this, request); + _timer.schedule(_statusTask, STATUS_POLL_INTERVAL); } - - public void scheduleTimeoutTask(long delay) { - if (timeoutTask != null) timeoutTask.cancel(); - timeoutTask = new TimeoutTask(this); - timer.schedule(timeoutTask, delay); + public void scheduleTimeoutTask(long delay) { + if (_timeoutTask != null) _timeoutTask.cancel(); + + _timeoutTask = new TimeoutTask(this); + _timer.schedule(_timeoutTask, delay); if (s_logger.isDebugEnabled()) { log("Scheduling timeout at " + delay + " ms", Level.DEBUG); } } - + public void scheduleImmediateStatusCheck(RequestType request) { - if (statusTask != null) statusTask.cancel(); - statusTask = new StatusTask(this, request); - timer.schedule(statusTask, SMALL_DELAY); + if (_statusTask != null) _statusTask.cancel(); + _statusTask = new StatusTask(this, request); + _timer.schedule(_statusTask, SMALL_DELAY); } public boolean isDownloadActive() { - return downloadActive; + return _downloadActive; } public void cancelStatusTask() { - if (statusTask != null) statusTask.cancel(); + if (_statusTask != null) _statusTask.cancel(); } public Date getLastUpdated() { - return lastUpdated; + return _lastUpdated; } - + public void setLastUpdated() { - lastUpdated = new Date(); + _lastUpdated = new Date(); } public void setDownloadInactive(Status reason) { - downloadActive=false; - if (template != null){ - downloadMonitor.handleDownloadEvent(sserver, template, reason); - }else { - downloadMonitor.handleDownloadEvent(sserver, volume, reason); - } + _downloadActive=false; } public void cancelTimeoutTask() { - if (timeoutTask != null) timeoutTask.cancel(); + if (_timeoutTask != null) _timeoutTask.cancel(); } 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..5b8f9a087b1 100644 --- a/server/src/com/cloud/storage/download/DownloadMonitor.java +++ b/server/src/com/cloud/storage/download/DownloadMonitor.java @@ -16,15 +16,10 @@ // under the License. package com.cloud.storage.download; -import java.util.Map; +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; - -import com.cloud.exception.StorageUnavailableException; -import com.cloud.host.HostVO; -import com.cloud.storage.VMTemplateVO; -import com.cloud.storage.VolumeVO; -import com.cloud.storage.Storage.ImageFormat; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.agent.api.storage.DownloadAnswer; import com.cloud.utils.component.Manager; /** @@ -32,24 +27,10 @@ import com.cloud.utils.component.Manager; * */ public interface DownloadMonitor extends Manager{ - - public boolean downloadTemplateToStorage(VMTemplateVO template, Long zoneId); - - public void cancelAllDownloads(Long templateId); - public void handleTemplateSync(HostVO host); - public boolean copyTemplate(VMTemplateVO template, HostVO sourceServer, HostVO destServer) - throws StorageUnavailableException; + public void downloadTemplateToStorage(DataObject template, AsyncCompletionCallback callback); - void handleSysTemplateDownload(HostVO hostId); - - void handleSync(Long dcId); - - void addSystemVMTemplatesToHost(HostVO host, Map templateInfos); - - boolean downloadVolumeToStorage(VolumeVO volume, Long zoneId, String url, String checkSum, ImageFormat format); - - void handleVolumeSync(HostVO ssHost); + public void downloadVolumeToStorage(DataObject volume, AsyncCompletionCallback callback); } \ 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 f72a5634053..2b1aa4e1bf2 100755 --- a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java +++ b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java @@ -18,1051 +18,295 @@ package com.cloud.storage.download; import java.net.URI; import java.net.URISyntaxException; -import java.util.ArrayList; import java.util.Date; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.Timer; import java.util.concurrent.ConcurrentHashMap; import javax.ejb.Local; import javax.inject.Inject; +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +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.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.storage.command.DownloadCommand; +import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType; +import org.apache.cloudstack.storage.command.DownloadProgressCommand; +import org.apache.cloudstack.storage.command.DownloadProgressCommand.RequestType; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +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.to.TemplateObjectTO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import com.cloud.agent.AgentManager; -import com.cloud.agent.Listener; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.Command; -import com.cloud.agent.api.storage.DeleteTemplateCommand; -import com.cloud.agent.api.storage.DeleteVolumeCommand; -import com.cloud.agent.api.storage.DownloadCommand; -import com.cloud.agent.api.storage.DownloadCommand.Proxy; -import com.cloud.agent.api.storage.DownloadCommand.ResourceType; -import com.cloud.agent.api.storage.DownloadProgressCommand; -import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType; -import com.cloud.agent.api.storage.ListTemplateAnswer; -import com.cloud.agent.api.storage.ListTemplateCommand; -import com.cloud.agent.api.storage.ListVolumeAnswer; -import com.cloud.agent.api.storage.ListVolumeCommand; -import com.cloud.agent.manager.Commands; -import com.cloud.alert.AlertManager; +import com.cloud.agent.api.storage.DownloadAnswer; +import com.cloud.agent.api.storage.Proxy; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; -import com.cloud.dc.DataCenterVO; -import com.cloud.dc.dao.ClusterDao; -import com.cloud.dc.dao.DataCenterDao; -import com.cloud.event.EventTypes; -import com.cloud.event.UsageEventUtils; -import com.cloud.event.dao.UsageEventDao; -import com.cloud.exception.AgentUnavailableException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.StorageUnavailableException; -import com.cloud.host.Host; -import com.cloud.host.HostVO; -import com.cloud.host.dao.HostDao; -import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.resource.ResourceManager; +import com.cloud.storage.RegisterVolumePayload; import com.cloud.storage.Storage.ImageFormat; -import com.cloud.storage.StorageManager; -import com.cloud.storage.SwiftVO; -import com.cloud.storage.VMTemplateHostVO; -import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; -import com.cloud.storage.VMTemplateVO; -import com.cloud.storage.VMTemplateZoneVO; -import com.cloud.storage.VolumeHostVO; -import com.cloud.storage.VolumeVO; -import com.cloud.storage.dao.StoragePoolHostDao; -import com.cloud.storage.dao.SwiftDao; +import com.cloud.storage.Volume; import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VMTemplateHostDao; -import com.cloud.storage.dao.VMTemplatePoolDao; -import com.cloud.storage.dao.VMTemplateSwiftDao; -import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.storage.dao.VolumeDao; -import com.cloud.storage.dao.VolumeHostDao; import com.cloud.storage.secondary.SecondaryStorageVmManager; -import com.cloud.storage.swift.SwiftManager; import com.cloud.storage.template.TemplateConstants; -import com.cloud.storage.template.TemplateInfo; -import com.cloud.template.TemplateManager; -import com.cloud.user.Account; -import com.cloud.user.AccountManager; -import com.cloud.user.ResourceLimitService; -import com.cloud.utils.UriUtils; +import com.cloud.storage.upload.UploadListener; +import com.cloud.template.VirtualMachineTemplate; +import com.cloud.utils.component.ComponentContext; import com.cloud.utils.component.ManagerBase; -import com.cloud.utils.db.DB; -import com.cloud.utils.db.JoinBuilder; -import com.cloud.utils.db.SearchBuilder; -import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.db.Transaction; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.vm.SecondaryStorageVm; -import com.cloud.vm.SecondaryStorageVmVO; -import com.cloud.vm.UserVmManager; -import com.cloud.vm.UserVmVO; -import com.cloud.vm.VirtualMachine.State; -import com.cloud.vm.dao.SecondaryStorageVmDao; -import com.cloud.vm.dao.UserVmDao; - -import edu.emory.mathcs.backport.java.util.Collections; - @Component -@Local(value={DownloadMonitor.class}) -public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor { +@Local(value = { DownloadMonitor.class }) +public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor { static final Logger s_logger = Logger.getLogger(DownloadMonitorImpl.class); - - @Inject - VMTemplateHostDao _vmTemplateHostDao; - @Inject - VMTemplateZoneDao _vmTemplateZoneDao; + @Inject - VMTemplatePoolDao _vmTemplatePoolDao; + TemplateDataStoreDao _vmTemplateStoreDao; @Inject - VMTemplateSwiftDao _vmTemplateSwiftlDao; - @Inject - StoragePoolHostDao _poolHostDao; - @Inject - SecondaryStorageVmDao _secStorageVmDao; + ImageStoreDao _imageStoreDao; @Inject VolumeDao _volumeDao; @Inject - VolumeHostDao _volumeHostDao; + VolumeDataStoreDao _volumeStoreDao; @Inject - AlertManager _alertMgr; + VMTemplateDao _templateDao = null; @Inject - protected SwiftManager _swiftMgr; + private AgentManager _agentMgr; @Inject - SecondaryStorageVmManager _ssvmMgr; - @Inject - StorageManager _storageMgr ; - - @Inject - private final DataCenterDao _dcDao = null; - @Inject - VMTemplateDao _templateDao = null; - @Inject - private AgentManager _agentMgr; - @Inject SecondaryStorageVmManager _secMgr; + SecondaryStorageVmManager _secMgr; @Inject ConfigurationDao _configDao; @Inject - UserVmManager _vmMgr; + EndPointSelector _epSelector; + @Inject + TemplateDataFactory tmplFactory; - @Inject TemplateManager templateMgr; + private Boolean _sslCopy = new Boolean(false); + private String _copyAuthPasswd; + private String _proxy = null; - - @Inject - private UsageEventDao _usageEventDao; - + Timer _timer; @Inject - private ClusterDao _clusterDao; - @Inject - private HostDao _hostDao; - @Inject - private ResourceManager _resourceMgr; - @Inject - private SwiftDao _swiftDao; - @Inject - protected ResourceLimitService _resourceLimitMgr; - @Inject - protected UserVmDao _userVmDao; - @Inject - protected AccountManager _accountMgr; + DataStoreManager storeMgr; - private Boolean _sslCopy = new Boolean(false); - String _ssvmUrlDomain; - private String _copyAuthPasswd; - private String _proxy = null; - protected SearchBuilder ReadyTemplateStatesSearch; - - Timer _timer; - - final Map _listenerMap = new ConcurrentHashMap(); - final Map _listenerVolumeMap = new ConcurrentHashMap(); + final Map _listenerTemplateMap = new ConcurrentHashMap(); + final Map _listenerVolMap = new ConcurrentHashMap(); - public void send(Long hostId, Command cmd, Listener listener) throws AgentUnavailableException { - _agentMgr.send(hostId, new Commands(cmd), listener); - } - - @Override - public boolean configure(String name, Map params) { + @Override + public boolean configure(String name, Map params) { final Map configs = _configDao.getConfiguration("ManagementServer", params); _sslCopy = Boolean.parseBoolean(configs.get("secstorage.encrypt.copy")); _proxy = configs.get(Config.SecStorageProxy.key()); - - _ssvmUrlDomain = configs.get("secstorage.ssl.cert.domain"); - + + 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.and("destroyed", ReadyTemplateStatesSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); - ReadyTemplateStatesSearch.and("host_id", ReadyTemplateStatesSearch.entity().getHostId(), SearchCriteria.Op.EQ); - SearchBuilder TemplatesWithNoChecksumSearch = _templateDao.createSearchBuilder(); - TemplatesWithNoChecksumSearch.and("checksum", TemplatesWithNoChecksumSearch.entity().getChecksum(), SearchCriteria.Op.NULL); + DownloadListener dl = new DownloadListener(this); + ComponentContext.inject(dl); + _agentMgr.registerForHostEvents(dl, true, false, false); - ReadyTemplateStatesSearch.join("vm_template", TemplatesWithNoChecksumSearch, TemplatesWithNoChecksumSearch.entity().getId(), - ReadyTemplateStatesSearch.entity().getTemplateId(), JoinBuilder.JoinType.INNER); - TemplatesWithNoChecksumSearch.done(); - ReadyTemplateStatesSearch.done(); - - return true; - } + return true; + } - @Override - public boolean start() { - _timer = new Timer(); - return true; - } + @Override + public boolean start() { + _timer = new Timer(); + return true; + } - @Override - 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); - return (downloadsInProgress.size() == 0); - } - - @Override - public boolean copyTemplate(VMTemplateVO template, HostVO sourceServer, HostVO destServer) throws StorageUnavailableException{ + @Override + public boolean stop() { + return true; + } - boolean downloadJobExists = false; - VMTemplateHostVO destTmpltHost = null; - VMTemplateHostVO srcTmpltHost = null; + public boolean isTemplateUpdateable(Long templateId, Long storeId) { + List downloadsInProgress = _vmTemplateStoreDao.listByTemplateStoreDownloadStatus(templateId, storeId, + Status.DOWNLOAD_IN_PROGRESS, Status.DOWNLOADED); + return (downloadsInProgress.size() == 0); + } - srcTmpltHost = _vmTemplateHostDao.findByHostTemplate(sourceServer.getId(), template.getId()); - if (srcTmpltHost == null) { - throw new InvalidParameterValueException("Template " + template.getName() + " not associated with " + sourceServer.getName()); - } + private void initiateTemplateDownload(DataObject template, AsyncCompletionCallback callback) { + boolean downloadJobExists = false; + TemplateDataStoreVO vmTemplateStore = null; + DataStore store = template.getDataStore(); - String url = generateCopyUrl(sourceServer, srcTmpltHost); - if (url == null) { - s_logger.warn("Unable to start/resume copy of template " + template.getUniqueName() + " to " + destServer.getName() + ", no secondary storage vm in running state in source zone"); - throw new CloudRuntimeException("No secondary VM in running state in zone " + sourceServer.getDataCenterId()); - } - destTmpltHost = _vmTemplateHostDao.findByHostTemplate(destServer.getId(), template.getId()); - if (destTmpltHost == null) { - destTmpltHost = new VMTemplateHostVO(destServer.getId(), template.getId(), new Date(), 0, VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED, null, null, "jobid0000", null, url); - destTmpltHost.setCopy(true); - destTmpltHost.setPhysicalSize(srcTmpltHost.getPhysicalSize()); - _vmTemplateHostDao.persist(destTmpltHost); - } else if ((destTmpltHost.getJobId() != null) && (destTmpltHost.getJobId().length() > 2)) { + vmTemplateStore = _vmTemplateStoreDao.findByStoreTemplate(store.getId(), template.getId()); + if (vmTemplateStore == null) { + vmTemplateStore = new TemplateDataStoreVO(store.getId(), template.getId(), new Date(), 0, + Status.NOT_DOWNLOADED, null, null, "jobid0000", null, template.getUri()); + vmTemplateStore.setDataStoreRole(store.getRole()); + _vmTemplateStoreDao.persist(vmTemplateStore); + } else if ((vmTemplateStore.getJobId() != null) && (vmTemplateStore.getJobId().length() > 2)) { downloadJobExists = true; } Long maxTemplateSizeInBytes = getMaxTemplateSizeInBytes(); - if (srcTmpltHost.getSize() > maxTemplateSizeInBytes){ - 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); - if (downloadJobExists) { - dcmd = new DownloadProgressCommand(dcmd, destTmpltHost.getJobId(), RequestType.GET_OR_RESTART); - } + if (vmTemplateStore != null) { + start(); + VirtualMachineTemplate tmpl = this._templateDao.findById(template.getId()); + DownloadCommand dcmd = new DownloadCommand((TemplateObjectTO)(template.getTO()), maxTemplateSizeInBytes); dcmd.setProxy(getHttpProxy()); - dcmd.setChecksum(sourceChecksum); // We need to set the checksum as the source template might be a compressed url and have cksum for compressed image. Bug #10775 - HostVO ssAhost = _ssvmMgr.pickSsvmHost(destServer); - if( ssAhost == null ) { - s_logger.warn("There is no secondary storage VM for secondary storage host " + destServer.getName()); - return false; - } - DownloadListener dl = new DownloadListener(ssAhost, destServer, template, _timer, _vmTemplateHostDao, destTmpltHost.getId(), this, dcmd, _templateDao, _resourceLimitMgr, _alertMgr, _accountMgr); if (downloadJobExists) { - dl.setCurrState(destTmpltHost.getDownloadState()); + dcmd = new DownloadProgressCommand(dcmd, vmTemplateStore.getJobId(), RequestType.GET_OR_RESTART); } - DownloadListener old = null; - synchronized (_listenerMap) { - old = _listenerMap.put(destTmpltHost, dl); - } - if( old != null ) { - old.abandon(); - } - - try { - send(ssAhost.getId(), dcmd, dl); - return true; - } catch (AgentUnavailableException e) { - s_logger.warn("Unable to start /resume COPY of template " + template.getUniqueName() + " to " + destServer.getName(), e); - dl.setDisconnected(); - dl.scheduleStatusCheck(RequestType.GET_OR_RESTART); - e.printStackTrace(); + if (vmTemplateStore.isCopy()) { + dcmd.setCreds(TemplateConstants.DEFAULT_HTTP_AUTH_USER, _copyAuthPasswd); + } + EndPoint ep = _epSelector.select(template); + if (ep == null) { + s_logger.warn("There is no secondary storage VM for downloading template to image store " + store.getName()); + return; + } + DownloadListener dl = new DownloadListener(ep, store, template, _timer, this, dcmd, + callback); + ComponentContext.inject(dl); // initialize those auto-wired field in download listener. + if (downloadJobExists) { + // 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()); } - } - - return false; - } - - private String generateCopyUrl(String ipAddress, String dir, String path){ - String hostname = ipAddress; - String scheme = "http"; - if (_sslCopy) { - hostname = ipAddress.replace(".", "-"); - scheme = "https"; - - // Code for putting in custom certificates. - if(_ssvmUrlDomain != null && _ssvmUrlDomain.length() > 0){ - hostname = hostname + "." + _ssvmUrlDomain; - }else{ - hostname = hostname + ".realhostip.com"; - } - } - 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) { - SecondaryStorageVmVO ssVm = ssVms.get(0); - if (ssVm.getPublicIpAddress() == null) { - s_logger.warn("A running secondary storage vm has a null public ip?"); - return null; - } - return generateCopyUrl(ssVm.getPublicIpAddress(), sourceServer.getParent(), srcTmpltHost.getInstallPath()); - } - - VMTemplateVO tmplt = _templateDao.findById(srcTmpltHost.getTemplateId()); - HypervisorType hyperType = tmplt.getHypervisorType(); - /*No secondary storage vm yet*/ - if (hyperType != null && hyperType == HypervisorType.KVM) { - return "file://" + sourceServer.getParent() + "/" + srcTmpltHost.getInstallPath(); - } - return null; - } - private void downloadTemplateToStorage(VMTemplateVO template, HostVO sserver) { - boolean downloadJobExists = false; - VMTemplateHostVO vmTemplateHost = 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)) { - downloadJobExists = true; - } - - Long maxTemplateSizeInBytes = getMaxTemplateSizeInBytes(); - String secUrl = sserver.getStorageUrl(); - if(vmTemplateHost != null) { - start(); - DownloadCommand dcmd = - new DownloadCommand(secUrl, template, maxTemplateSizeInBytes); - if (downloadJobExists) { - dcmd = new DownloadProgressCommand(dcmd, vmTemplateHost.getJobId(), RequestType.GET_OR_RESTART); - } - dcmd.setProxy(getHttpProxy()); - if (vmTemplateHost.isCopy()) { - dcmd.setCreds(TemplateConstants.DEFAULT_HTTP_AUTH_USER, _copyAuthPasswd); - } - HostVO ssAhost = _ssvmMgr.pickSsvmHost(sserver); - if( ssAhost == null ) { - s_logger.warn("There is no secondary storage VM for secondary storage host " + sserver.getName()); - return; - } - DownloadListener dl = new DownloadListener(ssAhost, sserver, template, _timer, _vmTemplateHostDao, vmTemplateHost.getId(), this, dcmd, _templateDao, _resourceLimitMgr, _alertMgr, _accountMgr); - if (downloadJobExists) { - dl.setCurrState(vmTemplateHost.getDownloadState()); - } DownloadListener old = null; - synchronized (_listenerMap) { - old = _listenerMap.put(vmTemplateHost, dl); + synchronized (_listenerTemplateMap) { + old = _listenerTemplateMap.put(vmTemplateStore, dl); } - if( old != null ) { + if (old != null) { old.abandon(); } - 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); - dl.setDisconnected(); - dl.scheduleStatusCheck(RequestType.GET_OR_RESTART); + try { + ep.sendMessageAsync(dcmd, new UploadListener.Callback(ep.getId(), dl)); + } catch (Exception e) { + s_logger.warn("Unable to start /resume download of template " + template.getId() + " to " + store.getName(), e); + dl.setDisconnected(); + dl.scheduleStatusCheck(RequestType.GET_OR_RESTART); } - } - } - - - - @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)); } - 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; - } - } - } - } - 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; + } - volumeHost = _volumeHostDao.findByHostVolume(sserver.getId(), volume.getId()); + + @Override + public void downloadTemplateToStorage(DataObject template, AsyncCompletionCallback callback) { + long templateId = template.getId(); + DataStore store = template.getDataStore(); + if (isTemplateUpdateable(templateId, store.getId())) { + if (template != null && template.getUri() != null) { + initiateTemplateDownload(template, callback); + } + } + } + + @Override + public void downloadVolumeToStorage(DataObject volume, AsyncCompletionCallback callback) { + boolean downloadJobExists = false; + VolumeDataStoreVO volumeHost = null; + DataStore store = volume.getDataStore(); + VolumeInfo volInfo = (VolumeInfo)volume; + RegisterVolumePayload payload = (RegisterVolumePayload)volInfo.getpayload(); + String url = payload.getUrl(); + String checkSum = payload.getChecksum(); + ImageFormat format = ImageFormat.valueOf(payload.getFormat()); + + volumeHost = _volumeStoreDao.findByStoreVolume(store.getId(), volume.getId()); if (volumeHost == null) { - volumeHost = new VolumeHostVO(sserver.getId(), volume.getId(), sserver.getDataCenterId(), new Date(), 0, VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED, null, null, - "jobid0000", null, url, checkSum, format); - _volumeHostDao.persist(volumeHost); + volumeHost = new VolumeDataStoreVO(store.getId(), volume.getId(), new Date(), 0, Status.NOT_DOWNLOADED, + null, null, "jobid0000", null, url, checkSum); + _volumeStoreDao.persist(volumeHost); } else if ((volumeHost.getJobId() != null) && (volumeHost.getJobId().length() > 2)) { downloadJobExists = true; } - Long maxVolumeSizeInBytes = getMaxVolumeSizeInBytes(); - String secUrl = sserver.getStorageUrl(); - if(volumeHost != null) { - start(); - DownloadCommand dcmd = new DownloadCommand(secUrl, volume, maxVolumeSizeInBytes, checkSum, url, format); - if (downloadJobExists) { - dcmd = new DownloadProgressCommand(dcmd, volumeHost.getJobId(), RequestType.GET_OR_RESTART); - dcmd.setResourceType(ResourceType.VOLUME); - } + if (volumeHost != null) { + start(); + Volume vol = this._volumeDao.findById(volume.getId()); + DownloadCommand dcmd = new DownloadCommand((VolumeObjectTO)(volume.getTO()), maxVolumeSizeInBytes, checkSum, url, format); dcmd.setProxy(getHttpProxy()); - HostVO ssvm = _ssvmMgr.pickSsvmHost(sserver); - if( ssvm == null ) { - s_logger.warn("There is no secondary storage VM for secondary storage host " + sserver.getName()); - return; - } - DownloadListener dl = new DownloadListener(ssvm, sserver, volume, _timer, _volumeHostDao, volumeHost.getId(), - this, dcmd, _volumeDao, _storageMgr, _resourceLimitMgr, _alertMgr, _accountMgr); - - if (downloadJobExists) { - dl.setCurrState(volumeHost.getDownloadState()); - } - DownloadListener old = null; - synchronized (_listenerVolumeMap) { - old = _listenerVolumeMap.put(volumeHost, dl); + if (downloadJobExists) { + dcmd = new DownloadProgressCommand(dcmd, volumeHost.getJobId(), RequestType.GET_OR_RESTART); + dcmd.setResourceType(ResourceType.VOLUME); } - if( old != null ) { + + EndPoint ep = this._epSelector.select(volume); + if (ep == null) { + s_logger.warn("There is no secondary storage VM for image store " + store.getName()); + return; + } + DownloadListener dl = new DownloadListener(ep, store, volume, _timer, this, dcmd, callback); + ComponentContext.inject(dl); // auto-wired those injected fields in DownloadListener + + if (downloadJobExists) { + dl.setCurrState(volumeHost.getDownloadState()); + } + DownloadListener old = null; + synchronized (_listenerVolMap) { + old = _listenerVolMap.put(volumeHost, dl); + } + if (old != null) { old.abandon(); } - try { - send(ssvm.getId(), dcmd, dl); - } catch (AgentUnavailableException e) { - s_logger.warn("Unable to start /resume download of volume " + volume.getName() + " to " + sserver.getName(), e); - dl.setDisconnected(); - dl.scheduleStatusCheck(RequestType.GET_OR_RESTART); - } - } - } - - - private void initiateTemplateDownload(Long templateId, HostVO ssHost) { - VMTemplateVO template = _templateDao.findById(templateId); - if (template != null && (template.getUrl() != null)) { - //find all storage hosts and tell them to initiate download - downloadTemplateToStorage(template, ssHost); - } - - } - - @DB - public void handleDownloadEvent(HostVO host, VMTemplateVO template, Status dnldStatus) { - if ((dnldStatus == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) || (dnldStatus==Status.ABANDONED)){ - VMTemplateHostVO vmTemplateHost = new VMTemplateHostVO(host.getId(), template.getId()); - synchronized (_listenerMap) { - _listenerMap.remove(vmTemplateHost); - } - } - - VMTemplateHostVO vmTemplateHost = _vmTemplateHostDao.findByHostTemplate(host.getId(), template.getId()); - - Transaction txn = Transaction.currentTxn(); - txn.start(); - - if (dnldStatus == Status.DOWNLOADED) { - long size = -1; - if(vmTemplateHost!=null){ - size = vmTemplateHost.getPhysicalSize(); - template.setSize(size); - this._templateDao.update(template.getId(), template); - } - else{ - s_logger.warn("Failed to get size for template" + template.getName()); - } - String eventType = EventTypes.EVENT_TEMPLATE_CREATE; - if((template.getFormat()).equals(ImageFormat.ISO)){ - eventType = EventTypes.EVENT_ISO_CREATE; - } - if(template.getAccountId() != Account.ACCOUNT_ID_SYSTEM){ - UsageEventUtils.publishUsageEvent(eventType, template.getAccountId(), host.getDataCenterId(), - template.getId(), template.getName(), null, template.getSourceTemplateId(), size, - template.getClass().getName(), template.getUuid()); - } - } - txn.commit(); - } - - @DB - public void handleDownloadEvent(HostVO host, VolumeVO volume, Status dnldStatus) { - if ((dnldStatus == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) || (dnldStatus==Status.ABANDONED)){ - VolumeHostVO volumeHost = new VolumeHostVO(host.getId(), volume.getId()); - synchronized (_listenerVolumeMap) { - _listenerVolumeMap.remove(volumeHost); - } - } - - VolumeHostVO volumeHost = _volumeHostDao.findByHostVolume(host.getId(), volume.getId()); - - Transaction txn = Transaction.currentTxn(); - txn.start(); - - if (dnldStatus == Status.DOWNLOADED) { - - //Create usage event - long size = -1; - if(volumeHost!=null){ - size = volumeHost.getSize(); - volume.setSize(size); - this._volumeDao.update(volume.getId(), volume); - } - else{ - s_logger.warn("Failed to get size for volume" + volume.getName()); - } - String eventType = EventTypes.EVENT_VOLUME_UPLOAD; - if(volume.getAccountId() != Account.ACCOUNT_ID_SYSTEM){ - UsageEventUtils.publishUsageEvent(eventType, volume.getAccountId(), host.getDataCenterId(), - volume.getId(), volume.getName(), null, 0l, size, volume.getClass().getName(), volume.getUuid()); - } - }else if (dnldStatus == Status.DOWNLOAD_ERROR || dnldStatus == Status.ABANDONED || dnldStatus == Status.UNKNOWN){ - //Decrement the volume and secondary storage space count - _resourceLimitMgr.decrementResourceCount(volume.getAccountId(), - com.cloud.configuration.Resource.ResourceType.volume); - _resourceLimitMgr.recalculateResourceCount(volume.getAccountId(), volume.getDomainId(), - com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal()); - } - txn.commit(); - } - - @Override - public void handleSysTemplateDownload(HostVO host) { - List hypers = _resourceMgr.listAvailHypervisorInZone(host.getId(), host.getDataCenterId()); - HypervisorType hostHyper = host.getHypervisorType(); - if (hypers.contains(hostHyper)) { - return; - } - - Set toBeDownloaded = new HashSet(); - 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) { - 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); - } - } - } - } - - @Override - public void addSystemVMTemplatesToHost(HostVO host, Map templateInfos){ - if ( templateInfos == null ) { - return; - } - Long hostId = host.getId(); - List rtngTmplts = _templateDao.listAllSystemVMTemplates(); - for ( VMTemplateVO tmplt : rtngTmplts ) { - TemplateInfo tmpltInfo = templateInfos.get(tmplt.getUniqueName()); - if ( tmpltInfo == null ) { - continue; - } - VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(hostId, tmplt.getId()); - if ( tmpltHost == null ) { - tmpltHost = new VMTemplateHostVO(hostId, 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); - } - } - } - - @Override - public void handleSync(Long dcId) { - if (dcId != null) { - List ssHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(dcId); - for (HostVO ssHost : ssHosts) { - handleTemplateSync(ssHost); - handleVolumeSync(ssHost); + try { + ep.sendMessageAsync(dcmd, new UploadListener.Callback(ep.getId(), dl)); + } catch (Exception e) { + s_logger.warn("Unable to start /resume download of volume " + volume.getId() + " to " + store.getName(), e); + dl.setDisconnected(); + dl.scheduleStatusCheck(RequestType.GET_OR_RESTART); } } } - - private Map listTemplate(HostVO ssHost) { - ListTemplateCommand cmd = new ListTemplateCommand(ssHost.getStorageUrl()); - Answer answer = _agentMgr.sendToSecStorage(ssHost, cmd); - if (answer != null && answer.getResult()) { - ListTemplateAnswer tanswer = (ListTemplateAnswer)answer; - return tanswer.getTemplateInfo(); - } else { - 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); - if (answer != null && answer.getResult()) { - ListVolumeAnswer tanswer = (ListVolumeAnswer)answer; - return tanswer.getTemplateInfo(); - } else { - 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) { + + + + + private Long getMaxTemplateSizeInBytes() { + try { + return Long.parseLong(_configDao.getValue("max.template.iso.size")) * 1024L * 1024L * 1024L; + } catch (NumberFormatException e) { return null; } - ListTemplateCommand cmd = new ListTemplateCommand(swift.toSwiftTO()); - Answer answer = _agentMgr.sendToSSVM(null, cmd); - if (answer != null && answer.getResult()) { - ListTemplateAnswer tanswer = (ListTemplateAnswer) answer; - return tanswer.getTemplateInfo(); - } else { - if (s_logger.isDebugEnabled()) { - s_logger.debug("can not list template for swift " + swift); - } - } - return null; } - - @Override - public void handleVolumeSync(HostVO ssHost) { - if (ssHost == null) { - s_logger.warn("Huh? ssHost is null"); - return; - } - 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; - } - Map volumeInfos = listVolume(ssHost); - if (volumeInfos == null) { - return; - } - - List dbVolumes = _volumeHostDao.listBySecStorage(sserverId); - List toBeDownloaded = new ArrayList(dbVolumes); - for (VolumeHostVO volumeHost : dbVolumes){ - VolumeVO volume = _volumeDao.findById(volumeHost.getVolumeId()); - //Exists then don't download - if (volumeInfos.containsKey(volume.getId())){ - TemplateInfo volInfo = volumeInfos.remove(volume.getId()); - toBeDownloaded.remove(volumeHost); - s_logger.info("Volume Sync found " + volume.getUuid() + " already in the volume host table"); - if (volumeHost.getDownloadState() != Status.DOWNLOADED) { - volumeHost.setErrorString(""); - } - if (volInfo.isCorrupted()) { - volumeHost.setDownloadState(Status.DOWNLOAD_ERROR); - String msg = "Volume " + volume.getUuid() + " is corrupted on secondary storage "; - volumeHost.setErrorString(msg); - s_logger.info("msg"); - if (volumeHost.getDownloadUrl() == null) { - msg = "Volume (" + volume.getUuid() + ") with install path " + volInfo.getInstallPath() + "is corrupted, please check in secondary storage: " + volumeHost.getHostId(); - s_logger.warn(msg); - } else { - toBeDownloaded.add(volumeHost); - } - - } else { // Put them in right status - volumeHost.setDownloadPercent(100); - volumeHost.setDownloadState(Status.DOWNLOADED); - volumeHost.setInstallPath(volInfo.getInstallPath()); - volumeHost.setSize(volInfo.getSize()); - volumeHost.setPhysicalSize(volInfo.getPhysicalSize()); - volumeHost.setLastUpdated(new Date()); - _volumeHostDao.update(volumeHost.getId(), volumeHost); - - if (volume.getSize() == 0) { - // Set volume size in volumes table - volume.setSize(volInfo.getSize()); - _volumeDao.update(volumeHost.getVolumeId(), volume); - } - - if (volInfo.getSize() > 0) { - try { - String url = _volumeHostDao.findByVolumeId(volume.getId()).getDownloadUrl(); - _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()), - com.cloud.configuration.Resource.ResourceType.secondary_storage, - volInfo.getSize() - UriUtils.getRemoteSize(url)); - } catch (ResourceAllocationException e) { - s_logger.warn(e.getMessage()); - _alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, volume.getDataCenterId(), - volume.getPodId(), e.getMessage(), e.getMessage()); - } finally { - _resourceLimitMgr.recalculateResourceCount(volume.getAccountId(), volume.getDomainId(), - com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal()); - } - } - } - continue; - } - // Volume is not on secondary but we should download. - 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()); - } - } - - //Delete volumes which are not present on DB. - for (Long uniqueName : volumeInfos.keySet()) { - TemplateInfo vInfo = volumeInfos.get(uniqueName); - DeleteVolumeCommand dtCommand = new DeleteVolumeCommand(ssHost.getStorageUrl(), vInfo.getInstallPath()); - try { - _agentMgr.sendToSecStorage(ssHost, dtCommand, null); - } catch (AgentUnavailableException e) { - String err = "Failed to delete " + vInfo.getTemplateName() + " on secondary storage " + sserverId + " which isn't in the database"; - 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); - if (templateInfos == null) { - return; - } - - Set toBeDownloaded = new HashSet(); - List allTemplates = _templateDao.listAllInZone(zoneId); - List rtngTmplts = _templateDao.listAllSystemVMTemplates(); - List defaultBuiltin = _templateDao.listDefaultBuiltinTemplates(); - - if (rtngTmplts != null) { - for (VMTemplateVO rtngTmplt : rtngTmplts) { - if (!allTemplates.contains(rtngTmplt)) { - allTemplates.add(rtngTmplt); - } - } - } - - if (defaultBuiltin != null) { - for (VMTemplateVO builtinTmplt : defaultBuiltin) { - if (!allTemplates.contains(builtinTmplt)) { - allTemplates.add(builtinTmplt); - } - } - } - - toBeDownloaded.addAll(allTemplates); - - for (VMTemplateVO tmplt : allTemplates) { - String uniqueName = tmplt.getUniqueName(); - VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(sserverId, tmplt.getId()); - if (templateInfos.containsKey(uniqueName)) { - TemplateInfo tmpltInfo = templateInfos.remove(uniqueName); - toBeDownloaded.remove(tmplt); - if (tmpltHost != null) { - s_logger.info("Template Sync found " + tmplt.getName() + " already in the template host table"); - if (tmpltHost.getDownloadState() != Status.DOWNLOADED) { - tmpltHost.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); - 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(); - 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()); - - // Skipping limit checks for SYSTEM Account and for the templates created from volumes or snapshots - // which already got checked and incremented during createTemplate API call. - if (tmpltInfo.getSize() > 0 && tmplt.getAccountId() != Account.ACCOUNT_ID_SYSTEM && tmplt.getUrl() != null) { - long accountId = tmplt.getAccountId(); - try { - _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(accountId), - com.cloud.configuration.Resource.ResourceType.secondary_storage, - tmpltInfo.getSize() - UriUtils.getRemoteSize(tmplt.getUrl())); - } catch (ResourceAllocationException e) { - s_logger.warn(e.getMessage()); - _alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, ssHost.getDataCenterId(), - null, e.getMessage(), e.getMessage()); - } finally { - _resourceLimitMgr.recalculateResourceCount(accountId, _accountMgr.getAccount(accountId).getDomainId(), - com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal()); - } - } - } - _vmTemplateHostDao.update(tmpltHost.getId(), tmpltHost); - } 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()); - if (tmpltZoneVO == null) { - tmpltZoneVO = new VMTemplateZoneVO(zoneId, 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 " + tmplt.getName() + " ready on server " + sserverId - + ", will request download to start/resume shortly"); - - } else if (tmpltHost == null) { - s_logger.info("Template Sync did not find " + tmplt.getName() + " 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); - } - } - - } - - if (toBeDownloaded.size() > 0) { - /* Only download templates whose hypervirsor type is in the zone */ - List availHypers = _clusterDao.getAvailableHypervisorInZone(zoneId); - if (availHypers.isEmpty()) { - /* - * This is for cloudzone, local secondary storage resource - * started before cluster created - */ - availHypers.add(HypervisorType.KVM); - } - /* Baremetal need not to download any template */ - availHypers.remove(HypervisorType.BareMetal); - availHypers.add(HypervisorType.None); // bug 9809: resume ISO - // download. - for (VMTemplateVO tmplt : toBeDownloaded) { - if (tmplt.getUrl() == null) { // If url is null we can't - // initiate the download - continue; - } - // 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()); - if (tmpltHost == null) { - continue; - } - } - if (availHypers.contains(tmplt.getHypervisorType())) { - if (_swiftMgr.isSwiftEnabled()) { - if (_swiftMgr.isTemplateInstalled(tmplt.getId())) { - continue; - } - } - s_logger.debug("Template " + tmplt.getName() + " needs to be downloaded to " + ssHost.getName()); - downloadTemplateToStorage(tmplt, ssHost); - } else { - s_logger.info("Skipping download of template " + tmplt.getName() + " since we don't have any " - + tmplt.getHypervisorType() + " hypervisors"); - } - } - } - - for (String uniqueName : templateInfos.keySet()) { - TemplateInfo tInfo = templateInfos.get(uniqueName); - 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()); - try { - _agentMgr.sendToSecStorage(ssHost, dtCommand, null); - } catch (AgentUnavailableException e) { - String err = "Failed to delete " + tInfo.getTemplateName() + " on secondary storage " + sserverId + " 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"; - s_logger.info(description); - } + private Long getMaxVolumeSizeInBytes() { + try { + return Long.parseLong(_configDao.getValue("storage.max.volume.upload.size")) * 1024L * 1024L * 1024L; + } catch (NumberFormatException e) { + return null; } } - @Override - public void cancelAllDownloads(Long templateId) { - List downloadsInProgress = - _vmTemplateHostDao.listByTemplateStates(templateId, VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS, VMTemplateHostVO.Status.NOT_DOWNLOADED); - if (downloadsInProgress.size() > 0){ - for (VMTemplateHostVO vmthvo: downloadsInProgress) { - DownloadListener dl = null; - synchronized (_listenerMap) { - dl = _listenerMap.remove(vmthvo); - } - if (dl != null) { - dl.abandon(); - s_logger.info("Stopping download of template " + templateId + " to storage server " + vmthvo.getHostId()); - } - } - } - } - - private void checksumSync(long hostId){ - SearchCriteria sc = ReadyTemplateStatesSearch.create(); - sc.setParameters("download_state", com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED); - sc.setParameters("host_id", hostId); - - List templateHostRefList = _vmTemplateHostDao.search(sc, null); - s_logger.debug("Found " +templateHostRefList.size()+ " templates with no checksum. Will ask for computation"); - for(VMTemplateHostVO templateHostRef : templateHostRefList){ - s_logger.debug("Getting checksum for template - " + templateHostRef.getTemplateId()); - String checksum = this.templateMgr.getChecksum(hostId, templateHostRef.getInstallPath()); - VMTemplateVO template = _templateDao.findById(templateHostRef.getTemplateId()); - s_logger.debug("Setting checksum " +checksum+ " for template - " + template.getName()); - template.setChecksum(checksum); - _templateDao.update(template.getId(), template); + private Proxy getHttpProxy() { + if (_proxy == null) { + return null; } + try { + URI uri = new URI(_proxy); + Proxy prx = new Proxy(uri); + return prx; + } catch (URISyntaxException e) { + return null; + } + } - } - - private Long getMaxTemplateSizeInBytes() { - try { - return Long.parseLong(_configDao.getValue("max.template.iso.size")) * 1024L * 1024L * 1024L; - } catch (NumberFormatException e) { - return null; - } - } - - private Long getMaxVolumeSizeInBytes() { - try { - return Long.parseLong(_configDao.getValue("storage.max.volume.upload.size")) * 1024L * 1024L * 1024L; - } catch (NumberFormatException e) { - return null; - } - } - - private Proxy getHttpProxy() { - if (_proxy == null) { - return null; - } - try { - URI uri = new URI(_proxy); - Proxy prx = new Proxy(uri); - return prx; - } catch (URISyntaxException e) { - return null; - } - } - } - diff --git a/server/src/com/cloud/storage/download/DownloadState.java b/server/src/com/cloud/storage/download/DownloadState.java index 471ab6124f7..9d404f02e37 100644 --- a/server/src/com/cloud/storage/download/DownloadState.java +++ b/server/src/com/cloud/storage/download/DownloadState.java @@ -62,7 +62,7 @@ public abstract class DownloadState { getDownloadListener().log("onEntry, event type=" + event + ", curr state=" + getName(), Level.TRACE); } if (event==DownloadEvent.DOWNLOAD_ANSWER) { - getDownloadListener().updateDatabase((DownloadAnswer)evtObj); + getDownloadListener().callback((DownloadAnswer)evtObj); } } diff --git a/server/src/com/cloud/storage/download/NotDownloadedState.java b/server/src/com/cloud/storage/download/NotDownloadedState.java index 77521731769..e10feb312d4 100644 --- a/server/src/com/cloud/storage/download/NotDownloadedState.java +++ b/server/src/com/cloud/storage/download/NotDownloadedState.java @@ -16,7 +16,8 @@ // under the License. package com.cloud.storage.download; -import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType; +import org.apache.cloudstack.storage.command.DownloadProgressCommand.RequestType; + import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; public class NotDownloadedState extends DownloadActiveState { diff --git a/server/src/com/cloud/storage/listener/StoragePoolMonitor.java b/server/src/com/cloud/storage/listener/StoragePoolMonitor.java index 4848d446d21..2be0c65fb4c 100755 --- a/server/src/com/cloud/storage/listener/StoragePoolMonitor.java +++ b/server/src/com/cloud/storage/listener/StoragePoolMonitor.java @@ -20,7 +20,6 @@ import java.util.List; import javax.inject.Inject; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.log4j.Logger; @@ -33,11 +32,12 @@ import com.cloud.agent.api.Command; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; import com.cloud.exception.ConnectionException; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.host.Status; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.OCFS2Manager; import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.storage.ScopeType; import com.cloud.storage.StorageManagerImpl; import com.cloud.storage.StoragePoolStatus; @@ -71,7 +71,7 @@ public class StoragePoolMonitor implements Listener { } @Override - public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { + public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { if (cmd instanceof StartupRoutingCommand) { StartupRoutingCommand scCmd = (StartupRoutingCommand)cmd; if (scCmd.getHypervisorType() == HypervisorType.XenServer || scCmd.getHypervisorType() == HypervisorType.KVM || diff --git a/server/src/com/cloud/storage/listener/StorageSyncListener.java b/server/src/com/cloud/storage/listener/StorageSyncListener.java index d9282a35ad7..5b7c7f75980 100755 --- a/server/src/com/cloud/storage/listener/StorageSyncListener.java +++ b/server/src/com/cloud/storage/listener/StorageSyncListener.java @@ -24,7 +24,7 @@ import com.cloud.agent.api.AgentControlCommand; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.StartupCommand; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.host.Status; public class StorageSyncListener implements Listener { @@ -51,7 +51,7 @@ public class StorageSyncListener implements Listener { } @Override - public void processConnect(HostVO agent, StartupCommand cmd, boolean forRebalance) { + public void processConnect(Host agent, StartupCommand cmd, boolean forRebalance) { } @Override diff --git a/server/src/com/cloud/storage/resource/DummySecondaryStorageResource.java b/server/src/com/cloud/storage/resource/DummySecondaryStorageResource.java index 8f25514180c..29e6a055b81 100644 --- a/server/src/com/cloud/storage/resource/DummySecondaryStorageResource.java +++ b/server/src/com/cloud/storage/resource/DummySecondaryStorageResource.java @@ -24,6 +24,8 @@ import java.util.Map; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.storage.command.DownloadCommand; +import org.apache.cloudstack.storage.command.DownloadProgressCommand; import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; @@ -39,8 +41,6 @@ import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupStorageCommand; import com.cloud.agent.api.storage.DownloadAnswer; -import com.cloud.agent.api.storage.DownloadCommand; -import com.cloud.agent.api.storage.DownloadProgressCommand; import com.cloud.host.Host; import com.cloud.host.Host.Type; import com.cloud.resource.ServerResource; @@ -50,7 +50,7 @@ import com.cloud.storage.VMTemplateVO; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.template.TemplateConstants; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; public class DummySecondaryStorageResource extends ServerResourceBase implements ServerResource { @@ -113,7 +113,7 @@ public class DummySecondaryStorageResource extends ServerResourceBase implements public StartupCommand[] initialize() { final StartupStorageCommand cmd = new StartupStorageCommand("dummy", StoragePoolType.NetworkFilesystem, 1024*1024*1024*100L, - new HashMap()); + new HashMap()); cmd.setResourceType(Storage.StorageResourceType.SECONDARY_STORAGE); cmd.setIqn(null); @@ -173,12 +173,12 @@ public class DummySecondaryStorageResource extends ServerResourceBase implements return _useServiceVm; } - public Map getDefaultSystemVmTemplateInfo() { + public Map getDefaultSystemVmTemplateInfo() { List tmplts = _tmpltDao.listAllSystemVMTemplates(); - Map tmpltInfo = new HashMap(); + Map tmpltInfo = new HashMap(); if (tmplts != null) { for (VMTemplateVO tmplt : tmplts) { - TemplateInfo routingInfo = new TemplateInfo(tmplt.getUniqueName(), TemplateConstants.DEFAULT_SYSTEM_VM_TEMPLATE_PATH + tmplt.getId() + File.separator, false, false); + TemplateProp routingInfo = new TemplateProp(tmplt.getUniqueName(), TemplateConstants.DEFAULT_SYSTEM_VM_TEMPLATE_PATH + tmplt.getId() + File.separator, false, false); tmpltInfo.put(tmplt.getUniqueName(), routingInfo); } } diff --git a/server/src/com/cloud/storage/s3/S3Manager.java b/server/src/com/cloud/storage/s3/S3Manager.java index 0f74e431376..058c5caf32c 100644 --- a/server/src/com/cloud/storage/s3/S3Manager.java +++ b/server/src/com/cloud/storage/s3/S3Manager.java @@ -19,6 +19,7 @@ package com.cloud.storage.s3; import java.util.List; +import java.util.Map; import com.cloud.agent.api.to.S3TO; import org.apache.cloudstack.api.command.admin.storage.AddS3Cmd; @@ -40,13 +41,15 @@ public interface S3Manager extends Manager { S3 addS3(AddS3Cmd addS3Cmd) throws DiscoveryException; + void verifyS3Fields(Map params) throws DiscoveryException; + Long chooseZoneForTemplateExtract(VMTemplateVO template); boolean isS3Enabled(); boolean isTemplateInstalled(Long templateId); - void deleteTemplate(final Long accountId, final Long templateId); + //void deleteTemplate(final Long accountId, final Long templateId); String downloadTemplateFromS3ToSecondaryStorage(final long dcId, final long templateId, final int primaryStorageDownloadWait); diff --git a/server/src/com/cloud/storage/s3/S3ManagerImpl.java b/server/src/com/cloud/storage/s3/S3ManagerImpl.java index 91fa9c34f0f..f393fff6268 100644 --- a/server/src/com/cloud/storage/s3/S3ManagerImpl.java +++ b/server/src/com/cloud/storage/s3/S3ManagerImpl.java @@ -45,14 +45,16 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.command.admin.storage.AddS3Cmd; import org.apache.cloudstack.api.command.admin.storage.ListS3sCmd; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; -import com.cloud.agent.api.DeleteTemplateFromS3Command; import com.cloud.agent.api.DownloadTemplateFromS3ToSecondaryStorageCommand; import com.cloud.agent.api.UploadTemplateToS3FromSecondaryStorageCommand; import com.cloud.agent.api.to.S3TO; @@ -88,12 +90,13 @@ public class S3ManagerImpl extends ManagerBase implements S3Manager { private static final Logger LOGGER = Logger.getLogger(S3ManagerImpl.class); - @Inject + @Inject private AgentManager agentManager; @Inject private S3Dao s3Dao; + @Inject private VMTemplateZoneDao vmTemplateZoneDao; @@ -115,12 +118,13 @@ public class S3ManagerImpl extends ManagerBase implements S3Manager { @Inject private HostDao hostDao; + @Inject - private SecondaryStorageVmManager secondaryStorageVMManager; + private DataStoreManager dataStoreManager; public S3ManagerImpl() { } - + private void verifyConnection(final S3TO s3) throws DiscoveryException { if (!canConnect(s3)) { @@ -245,6 +249,26 @@ public class S3ManagerImpl extends ManagerBase implements S3Manager { } + + @Override + public void verifyS3Fields(Map params) throws DiscoveryException { + final S3VO s3VO = new S3VO(UUID.randomUUID().toString(), + params.get(ApiConstants.S3_ACCESS_KEY), + params.get(ApiConstants.S3_SECRET_KEY), + params.get(ApiConstants.S3_END_POINT), + params.get(ApiConstants.S3_BUCKET_NAME), + params.get(ApiConstants.S3_HTTPS_FLAG) == null ? false : Boolean.valueOf(params.get(ApiConstants.S3_HTTPS_FLAG)), + params.get(ApiConstants.S3_CONNECTION_TIMEOUT) == null ? null : Integer.valueOf(params.get(ApiConstants.S3_CONNECTION_TIMEOUT)), + params.get(ApiConstants.S3_MAX_ERROR_RETRY) == null ? null : Integer.valueOf(params.get(ApiConstants.S3_MAX_ERROR_RETRY)), + params.get(ApiConstants.S3_SOCKET_TIMEOUT) == null ? null : Integer.valueOf(params.get(ApiConstants.S3_SOCKET_TIMEOUT)), now()); + + this.validateFields(s3VO); + + final S3TO s3 = s3VO.toS3TO(); + this.verifyConnection(s3); + this.verifyBuckets(s3); + } + @Override public boolean isS3Enabled() { return Boolean @@ -258,70 +282,7 @@ public class S3ManagerImpl extends ManagerBase implements S3Manager { + "been implemented"); } - @Override - public void deleteTemplate(final Long templateId, final Long accountId) { - final S3TO s3 = getS3TO(); - - if (s3 == null) { - final String errorMessage = "Delete Template Failed: No S3 configuration defined."; - LOGGER.error(errorMessage); - throw new CloudRuntimeException(errorMessage); - } - - final VMTemplateS3VO vmTemplateS3VO = vmTemplateS3Dao - .findOneByS3Template(s3.getId(), templateId); - if (vmTemplateS3VO == null) { - final String errorMessage = format( - "Delete Template Failed: Unable to find Template %1$s in S3.", - templateId); - LOGGER.error(errorMessage); - throw new CloudRuntimeException(errorMessage); - } - - try { - - executeWithNoWaitLock(determineLockId(accountId, templateId), - new Callable() { - - @Override - public Void call() throws Exception { - - final Answer answer = agentManager.sendToSSVM(null, - new DeleteTemplateFromS3Command(s3, - accountId, templateId)); - if (answer == null || !answer.getResult()) { - final String errorMessage = format( - "Delete Template Failed: Unable to delete template id %1$s from S3 due to following error: %2$s", - templateId, - ((answer == null) ? "answer is null" - : answer.getDetails())); - LOGGER.error(errorMessage); - throw new CloudRuntimeException(errorMessage); - } - - vmTemplateS3Dao.remove(vmTemplateS3VO.getId()); - LOGGER.debug(format( - "Deleted template %1$s from S3.", - templateId)); - - return null; - - } - - }); - - } catch (Exception e) { - - final String errorMessage = format( - "Delete Template Failed: Unable to delete template id %1$s from S3 due to the following error: %2$s.", - templateId, e.getMessage()); - LOGGER.error(errorMessage); - throw new CloudRuntimeException(errorMessage, e); - - } - - } @SuppressWarnings("unchecked") @Override @@ -360,11 +321,10 @@ public class S3ManagerImpl extends ManagerBase implements S3Manager { return errorMessage; } - final HostVO secondaryStorageHost = secondaryStorageVMManager - .findSecondaryStorageHost(dataCenterId); - if (secondaryStorageHost == null) { + final DataStore secondaryStore = this.dataStoreManager.getImageStore(dataCenterId); + if (secondaryStore == null) { final String errorMessage = format( - "Unable to find secondary storage host for zone id %1$s.", + "Unable to find secondary storage for zone id %1$s.", dataCenterId); LOGGER.error(errorMessage); throw new CloudRuntimeException(errorMessage); @@ -372,7 +332,7 @@ public class S3ManagerImpl extends ManagerBase implements S3Manager { final long accountId = template.getAccountId(); final DownloadTemplateFromS3ToSecondaryStorageCommand cmd = new DownloadTemplateFromS3ToSecondaryStorageCommand( - s3, accountId, templateId, secondaryStorageHost.getName(), + s3, accountId, templateId, secondaryStore.getName(), primaryStorageDownloadWait); try { @@ -397,7 +357,7 @@ public class S3ManagerImpl extends ManagerBase implements S3Manager { final String installPath = join(File.separator, "template", "tmpl", accountId, templateId); final VMTemplateHostVO tmpltHost = new VMTemplateHostVO( - secondaryStorageHost.getId(), templateId, + secondaryStore.getId(), templateId, now(), 100, Status.DOWNLOADED, null, null, null, installPath, template.getUrl()); tmpltHost.setSize(templateS3VO.getSize()); diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageListener.java b/server/src/com/cloud/storage/secondary/SecondaryStorageListener.java index 6635b3cf317..d524f29008d 100755 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageListener.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageListener.java @@ -27,7 +27,7 @@ import com.cloud.agent.api.Command; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupSecondaryStorageCommand; import com.cloud.agent.api.StartupStorageCommand; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.host.Status; import com.cloud.storage.Storage; @@ -68,7 +68,7 @@ public class SecondaryStorageListener implements Listener { } @Override - public void processConnect(HostVO agent, StartupCommand cmd, boolean forRebalance) { + public void processConnect(Host agent, StartupCommand cmd, boolean forRebalance) { if ((cmd instanceof StartupStorageCommand) ) { StartupStorageCommand scmd = (StartupStorageCommand)cmd; if (scmd.getResourceType() == Storage.StorageResourceType.SECONDARY_STORAGE ) { diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java index c3432863bec..954c7e970f0 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,11 @@ 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.DataStoreManager; +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; import com.cloud.agent.AgentManager; @@ -42,10 +47,10 @@ import com.cloud.agent.api.SecStorageSetupCommand.Certificates; import com.cloud.agent.api.SecStorageVMSetupCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupSecondaryStorageCommand; -import com.cloud.agent.api.StartupStorageCommand; import com.cloud.agent.api.StopAnswer; import com.cloud.agent.api.check.CheckSshAnswer; import com.cloud.agent.api.check.CheckSshCommand; +import com.cloud.agent.api.to.NfsTO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.manager.Commands; @@ -93,18 +98,12 @@ 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.SnapshotVO; -import com.cloud.storage.Storage; -import com.cloud.storage.VMTemplateHostVO; -import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VMTemplateHostDao; -import com.cloud.storage.resource.DummySecondaryStorageResource; -import com.cloud.storage.swift.SwiftManager; import com.cloud.storage.template.TemplateConstants; +import com.cloud.template.TemplateManager; import com.cloud.user.Account; import com.cloud.user.AccountService; import com.cloud.user.User; @@ -183,21 +182,14 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar private HostDao _hostDao; @Inject private StoragePoolHostDao _storagePoolHostDao; - - @Inject - private VMTemplateHostDao _vmTemplateHostDao; - @Inject private AgentManager _agentMgr; @Inject - protected SwiftManager _swiftMgr; - @Inject protected NetworkManager _networkMgr; @Inject protected NetworkModel _networkModel; @Inject protected SnapshotDao _snapshotDao; - @Inject private ClusterManager _clusterMgr; @@ -219,7 +211,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; @@ -231,9 +223,15 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar protected IPAddressDao _ipAddressDao = null; @Inject protected RulesManager _rulesMgr; - + @Inject + TemplateManager templateMgr; + @Inject KeystoreManager _keystoreMgr; + @Inject + DataStoreManager _dataStoreMgr; + @Inject + ImageStoreDao _imageStoreDao; private long _capacityScanInterval = DEFAULT_CAPACITY_SCAN_INTERVAL; private int _secStorageVmMtuSize; @@ -252,7 +250,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar public SecondaryStorageManagerImpl() { _ssvmMgr = this; } - + @Override public SecondaryStorageVmVO startSecStorageVm(long secStorageVmId) { try { @@ -281,46 +279,54 @@ 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"); return false; } - List ssHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(zoneId); - for( HostVO ssHost : ssHosts ) { - String secUrl = ssHost.getStorageUrl(); + List ssStores = this._dataStoreMgr.getImageStoresByScope(new ZoneScope(zoneId)); + for( DataStore ssStore : ssStores ) { + if (!(ssStore.getTO() instanceof NfsTO )) + continue; // only do this for Nfs + String secUrl = ssStore.getUri(); SecStorageSetupCommand setupCmd = null; if (!_useSSlCopy) { - setupCmd = new SecStorageSetupCommand(secUrl, null); + setupCmd = new SecStorageSetupCommand(ssStore.getTO(), secUrl, null); } else { Certificates certs = _keystoreMgr.getCertificates(ConsoleProxyManager.CERTIFICATE_NAME); - setupCmd = new SecStorageSetupCommand(secUrl, certs); + setupCmd = new SecStorageSetupCommand(ssStore.getTO(), secUrl, certs); } - + Answer answer = _agentMgr.easySend(ssHostId, setupCmd); if (answer != null && answer.getResult()) { SecStorageSetupAnswer an = (SecStorageSetupAnswer) answer; - ssHost.setParent(an.get_dir()); - _hostDao.update(ssHost.getId(), ssHost); + if (an.get_dir() != null){ + // update the parent path in image_store table for this image store + ImageStoreVO svo = this._imageStoreDao.findById(ssStore.getId()); + svo.setParent(an.get_dir()); + _imageStoreDao.update(ssStore.getId(), svo); + } if (s_logger.isDebugEnabled()) { - s_logger.debug("Successfully programmed secondary storage " + ssHost.getName() + " in secondary storage VM " + secStorageVm.getInstanceName()); + s_logger.debug("Successfully programmed secondary storage " + ssStore.getName() + " in secondary storage VM " + secStorageVm.getInstanceName()); } } else { if (s_logger.isDebugEnabled()) { - s_logger.debug("Successfully programmed secondary storage " + ssHost.getName() + " in secondary storage VM " + secStorageVm.getInstanceName()); + s_logger.debug("Successfully programmed secondary storage " + ssStore.getName() + " in secondary storage VM " + secStorageVm.getInstanceName()); } return false; } } - } else if( cssHost.getType() == Host.Type.SecondaryStorage ) { + } + /* After removing SecondaryStorage entries from host table, control should never come here!! + else if( cssHost.getType() == Host.Type.SecondaryStorage ) { List alreadyRunning = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, zoneId, State.Running); String secUrl = cssHost.getStorageUrl(); SecStorageSetupCommand setupCmd = new SecStorageSetupCommand(secUrl, null); @@ -336,34 +342,16 @@ 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 - public boolean deleteHost(Long hostId) { - List snapshots = _snapshotDao.listByHostId(hostId); - if( snapshots != null && !snapshots.isEmpty()) { - throw new CloudRuntimeException("Can not delete this secondary storage since it contains atleast one or more snapshots "); - } - if (!_swiftMgr.isSwiftEnabled()) { - List list = _templateDao.listPrivateTemplatesByHost(hostId); - if (list != null && !list.isEmpty()) { - throw new CloudRuntimeException("Can not delete this secondary storage since it contains private templates "); - } - } - _vmTemplateHostDao.deleteByHost(hostId); - HostVO host = _hostDao.findById(hostId); - host.setGuid(null); - _hostDao.update(hostId, host); - _hostDao.remove(hostId); - - return true; - } - + + + + @Override public boolean generateVMSetupCommand(Long ssAHostId) { HostVO ssAHost = _hostDao.findById(ssAHostId); @@ -375,7 +363,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(); @@ -417,7 +405,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; @@ -426,7 +414,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); @@ -447,7 +435,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar return false; } } - + SecStorageFirewallCfgCommand allSSVMIpList = new SecStorageFirewallCfgCommand(false); for (HostVO ssvm : ssvms) { if (ssvm.getId() == ssAHostId) { @@ -455,7 +443,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()) { @@ -467,7 +455,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } return false; } - + return true; } @@ -524,8 +512,8 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } protected Map createSecStorageVmInstance(long dataCenterId, SecondaryStorageVm.Role role) { - HostVO secHost = findSecondaryStorageHost(dataCenterId); - if (secHost == null) { + DataStore secStore = this._dataStoreMgr.getImageStore(dataCenterId); + if (secStore == null) { String msg = "No secondary storage available in zone " + dataCenterId + ", cannot create secondary storage vm"; s_logger.warn(msg); throw new CloudRuntimeException(msg); @@ -537,7 +525,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar DataCenterDeployment plan = new DataCenterDeployment(dataCenterId); DataCenter dc = _dcDao.findById(plan.getDataCenterId()); - + NetworkVO defaultNetwork = null; if (dc.getNetworkType() == NetworkType.Advanced && dc.isSecurityGroupEnabled()) { List networks = _networkDao.listByZoneSecurityGroup(dataCenterId); @@ -546,14 +534,14 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } defaultNetwork = networks.get(0); } else { - TrafficType defaultTrafficType = TrafficType.Public; + TrafficType defaultTrafficType = TrafficType.Public; - if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) { - defaultTrafficType = TrafficType.Guest; - } - List defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType); + 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) { + if (defaultNetworks.size() != 1) { throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + defaultTrafficType + " when expect to find 1"); } @@ -576,7 +564,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"); @@ -602,7 +590,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; } @@ -658,8 +646,8 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } return; } - - + + boolean secStorageVmFromStoppedPool = false; SecondaryStorageVmVO secStorageVm = assignSecStorageVmFromStoppedPool(dataCenterId, role); if (secStorageVm == null) { @@ -726,41 +714,35 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenterId); if (zoneHostInfo != null && (zoneHostInfo.getFlags() & RunningHostInfoAgregator.ZoneHostInfo.ROUTING_HOST_MASK) != 0) { VMTemplateVO template = _templateDao.findSystemVMTemplate(dataCenterId); - HostVO secHost = _ssvmMgr.findSecondaryStorageHost(dataCenterId); - if (secHost == null) { + if (template == null) { + s_logger.debug("No hypervisor host added in zone " + dataCenterId + ", wait until it is ready to launch secondary storage vm"); + return false; + } + + List stores = this._dataStoreMgr.getImageStoresByScope(new ZoneScope(dataCenterId)); + if (stores.size() < 1) { + s_logger.debug("No image store added in zone " + dataCenterId + ", wait until it is ready to launch secondary storage vm"); + return false; + } + + DataStore store = templateMgr.getImageStore(dataCenterId, template.getId()); + if (store == null) { if (s_logger.isDebugEnabled()) { s_logger.debug("No secondary storage available in zone " + dataCenterId + ", wait until it is ready to launch secondary storage vm"); } return false; } - boolean templateReady = false; - if (template != null) { - VMTemplateHostVO templateHostRef = _vmTemplateHostDao.findByHostTemplate(secHost.getId(), template.getId()); - templateReady = (templateHostRef != null) && (templateHostRef.getDownloadState() == Status.DOWNLOADED); - } - - if (templateReady) { - - List> l = _storagePoolHostDao.getDatacenterStoragePoolHostInfo(dataCenterId, !_useLocalStorage); - if (l != null && l.size() > 0 && l.get(0).second().intValue() > 0) { - - return true; - } else { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Primary storage is not ready, wait until it is ready to launch secondary storage vm. dcId: " + dataCenterId + " system.vm.use.local.storage: " + _useLocalStorage + - "If you want to use local storage to start ssvm, need to set system.vm.use.local.storage to true"); - } - } + List> l = _storagePoolHostDao.getDatacenterStoragePoolHostInfo(dataCenterId, !_useLocalStorage); + if (l != null && l.size() > 0 && l.get(0).second().intValue() > 0) { + return true; } else { if (s_logger.isDebugEnabled()) { - if (template == null) { - s_logger.debug("Zone host is ready, but secondary storage vm template does not exist"); - } else { - s_logger.debug("Zone host is ready, but secondary storage vm template: " + template.getId() + " is not ready on secondary storage: " + secHost.getId()); - } + s_logger.debug("Primary storage is not ready, wait until it is ready to launch secondary storage vm. dcId: " + dataCenterId + " system.vm.use.local.storage: " + _useLocalStorage + + "If you want to use local storage to start ssvm, need to set system.vm.use.local.storage to true"); } } + } return false; } @@ -804,7 +786,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; @@ -840,7 +822,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) { @@ -858,7 +840,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?"; @@ -871,7 +853,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; @@ -995,14 +977,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); @@ -1048,9 +1030,9 @@ 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); + + DataStore secStore = this._dataStoreMgr.getImageStore(dest.getDataCenter().getId()); + assert (secStore != null); StringBuilder buf = profile.getBootArgsBuilder(); buf.append(" template=domP type=secstorage"); @@ -1087,7 +1069,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")); } @@ -1295,9 +1277,9 @@ 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); - int hostSize = (ssHosts == null)? 0 : ssHosts.size(); - if ( hostSize > vmSize ) { + List ssStores = this._dataStoreMgr.getImageStoresByScope(new ZoneScope(dataCenterId)); + int storeSize = (ssStores == null)? 0 : ssStores.size(); + if ( storeSize > vmSize ) { s_logger.info("No secondary storage vms found in datacenter id=" + dataCenterId + ", starting a new one"); return new Pair(AfterScanAction.expand, SecondaryStorageVm.Role.templateProcessor); } @@ -1326,15 +1308,17 @@ 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 public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map details, List hostTags) { - /* Called when add secondary storage on UI */ + // Used to be Called when add secondary storage on UI through DummySecondaryStorageResource to update that host entry for Secondary Storage. + // Now since we move secondary storage from host table, this code is not needed to be invoked anymore. + /* StartupCommand firstCmd = startup[0]; if (!(firstCmd instanceof StartupStorageCommand)) { return null; @@ -1374,63 +1358,17 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar host.setStorageUrl(ssCmd.getNfsShare()); } } - - return host; + */ + return null; // no need to handle this event anymore since secondary storage is not in host table anymore. } @Override public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { - if (host.getType() == Host.Type.SecondaryStorage) { - deleteHost(host.getId()); - return new DeleteHostAnswer(false); - } + // Since secondary storage is moved out of host table, this class should not handle delete secondary storage anymore. return null; } - @Override - public HostVO findSecondaryStorageHost(long dcId) { - SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); - sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.SecondaryStorage); - sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId); - List storageHosts = sc.list(); - if (storageHosts == null || storageHosts.size() < 1) { - return null; - } else { - Collections.shuffle(storageHosts); - return storageHosts.get(0); - } - } - @Override - public List listSecondaryStorageHostsInAllZones() { - SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); - sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.SecondaryStorage); - return sc.list(); - } - - @Override - public List listSecondaryStorageHostsInOneZone(long dataCenterId) { - SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); - sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dataCenterId); - sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.SecondaryStorage); - return sc.list(); - } - - @Override - public List listLocalSecondaryStorageHostsInOneZone(long dataCenterId) { - SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); - sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dataCenterId); - sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.LocalSecondaryStorage); - return sc.list(); - } - - @Override - public List listAllTypesSecondaryStorageHostsInOneZone(long dataCenterId) { - SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); - sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dataCenterId); - sc.addAnd(sc.getEntity().getType(), Op.IN, Host.Type.LocalSecondaryStorage, Host.Type.SecondaryStorage); - return sc.list(); - } @Override public List listUpAndConnectingSecondaryStorageVmHost(Long dcId) { @@ -1458,7 +1396,8 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } return null; } - + + @Override public boolean plugNic(Network network, NicTO nic, VirtualMachineTO vm, ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException, @@ -1477,6 +1416,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..4f87346828c 100755 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageVmManager.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageVmManager.java @@ -29,12 +29,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,15 +42,9 @@ 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); - public HostVO findSecondaryStorageHost(long dcId); - public List listSecondaryStorageHostsInAllZones(); - public List listSecondaryStorageHostsInOneZone(long dataCenterId); - public List listLocalSecondaryStorageHostsInOneZone(long dataCenterId); - public List listAllTypesSecondaryStorageHostsInOneZone(long dataCenterId); public List listUpAndConnectingSecondaryStorageVmHost(Long dcId); public HostVO pickSsvmHost(HostVO ssHost); } diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManager.java b/server/src/com/cloud/storage/snapshot/SnapshotManager.java index 818133002c9..027fad6dbcb 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManager.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManager.java @@ -18,6 +18,7 @@ package com.cloud.storage.snapshot; import java.util.List; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import com.cloud.agent.api.Answer; @@ -33,8 +34,8 @@ import com.cloud.utils.db.Filter; import com.cloud.utils.fsm.NoTransitionException; /** - * - * + * + * */ public interface SnapshotManager { @@ -50,25 +51,24 @@ public interface SnapshotManager { * For each of the volumes in the account, (which can span across multiple zones and multiple secondary storages), delete * the dir on the secondary storage which contains the backed up snapshots for that volume. This is called during * deleteAccount. - * + * * @param accountId * The account which is to be deleted. */ boolean deleteSnapshotDirsForAccount(long accountId); - - void downloadSnapshotsFromSwift(SnapshotVO ss); - - void downloadSnapshotsFromS3(SnapshotVO snapshot); String getSecondaryStorageURL(SnapshotVO snapshot); - void deleteSnapshotsDirForVolume(String secondaryStoragePoolUrl, Long dcId, Long accountId, Long volumeId); + //void deleteSnapshotsDirForVolume(String secondaryStoragePoolUrl, Long dcId, Long accountId, Long volumeId); boolean canOperateOnVolume(Volume volume); Answer sendToPool(Volume vol, Command cmd); - SnapshotVO getParentSnapshot(VolumeInfo volume, Snapshot snapshot); + SnapshotVO getParentSnapshot(VolumeInfo volume); Snapshot backupSnapshot(Long snapshotId); + + SnapshotInfo takeSnapshot(VolumeInfo volume) + throws ResourceAllocationException; } diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java index c720169b2d3..ebe06e707a2 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -17,7 +17,6 @@ package com.cloud.storage.snapshot; import java.util.ArrayList; -import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; @@ -31,33 +30,34 @@ import org.apache.cloudstack.api.command.user.snapshot.CreateSnapshotPolicyCmd; import org.apache.cloudstack.api.command.user.snapshot.DeleteSnapshotPoliciesCmd; import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotPoliciesCmd; import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotsCmd; +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.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; -import com.cloud.agent.api.DeleteSnapshotBackupCommand; import com.cloud.agent.api.DeleteSnapshotsDirCommand; -import com.cloud.agent.api.DownloadSnapshotFromS3Command; -import com.cloud.agent.api.DownloadSnapshotFromSwiftCommand; -import com.cloud.agent.api.to.S3TO; -import com.cloud.agent.api.to.SwiftTO; import com.cloud.alert.AlertManager; import com.cloud.api.commands.ListRecurringSnapshotScheduleCmd; import com.cloud.configuration.Config; import com.cloud.configuration.Resource.ResourceType; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.ClusterVO; -import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.domain.dao.DomainDao; @@ -74,11 +74,13 @@ import com.cloud.exception.StorageUnavailableException; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.org.Grouping; import com.cloud.projects.Project.ListProjectResourcesCriteria; +import com.cloud.resource.ResourceManager; import com.cloud.server.ResourceTag.TaggedResourceType; +import com.cloud.storage.CreateSnapshotPayload; import com.cloud.storage.Snapshot; import com.cloud.storage.Snapshot.Type; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.SnapshotPolicyVO; import com.cloud.storage.SnapshotScheduleVO; import com.cloud.storage.SnapshotVO; @@ -98,6 +100,7 @@ import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.s3.S3Manager; import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.storage.swift.SwiftManager; +import com.cloud.storage.template.TemplateConstants; import com.cloud.tags.ResourceTagVO; import com.cloud.tags.dao.ResourceTagDao; import com.cloud.template.TemplateManager; @@ -121,13 +124,17 @@ import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.UserVmVO; import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.dao.UserVmDao; +import com.cloud.vm.snapshot.VMSnapshot; +import com.cloud.vm.snapshot.VMSnapshotVO; import com.cloud.vm.snapshot.dao.VMSnapshotDao; @Component -@Local(value = { SnapshotManager.class, SnapshotService.class }) -public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, SnapshotService { +@Local(value = { SnapshotManager.class, SnapshotApiService.class }) +public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, SnapshotApiService { private static final Logger s_logger = Logger.getLogger(SnapshotManagerImpl.class); @Inject protected VMTemplateDao _templateDao; @@ -146,6 +153,8 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, @Inject protected SnapshotDao _snapshotDao; @Inject + protected SnapshotDataStoreDao _snapshotStoreDao; + @Inject protected PrimaryDataStoreDao _storagePoolDao; @Inject protected EventDao _eventDao; @@ -171,9 +180,9 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, private ResourceLimitService _resourceLimitMgr; @Inject private SwiftManager _swiftMgr; - @Inject + @Inject private S3Manager _s3Mgr; - @Inject + @Inject private SecondaryStorageVmManager _ssvmMgr; @Inject private DomainManager _domainMgr; @@ -181,17 +190,21 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, private ResourceTagDao _resourceTagDao; @Inject private ConfigurationDao _configDao; - @Inject - private PrimaryDataStoreDao _primaryDataStoreDao; + @Inject + private VMSnapshotDao _vmSnapshotDao; String _name; - @Inject TemplateManager templateMgr; @Inject VolumeManager volumeMgr; @Inject DataStoreManager dataStoreMgr; - @Inject List snapshotStrategies; + @Inject SnapshotService snapshotSrv; @Inject VolumeDataFactory volFactory; @Inject SnapshotDataFactory snapshotFactory; - + @Inject EndPointSelector _epSelector; + @Inject + private ResourceManager _resourceMgr; + @Inject + protected List snapshotStrategies; + private int _totalRetries; private int _pauseInterval; @@ -200,14 +213,14 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, protected SearchBuilder PolicySnapshotSearch; protected SearchBuilder PoliciesForSnapSearch; - + @Override public Answer sendToPool(Volume vol, Command cmd) { StoragePool pool = (StoragePool)dataStoreMgr.getPrimaryDataStore(vol.getPoolId()); long[] hostIdsToTryFirst = null; - + Long vmHostId = getHostIdForSnapshotOperation(vol); - + if (vmHostId != null) { hostIdsToTryFirst = new long[] { vmHostId }; } @@ -262,44 +275,30 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, if (volume == null) { throw new InvalidParameterValueException("No such volume exist"); } - + if (volume.getState() != Volume.State.Ready) { throw new InvalidParameterValueException("Volume is not in ready state"); } - - SnapshotInfo snapshot = null; - + + boolean backedUp = false; // does the caller have the authority to act on this volume _accountMgr.checkAccess(UserContext.current().getCaller(), null, true, volume); - - SnapshotInfo snap = this.snapshotFactory.getSnapshot(snapshotId); - SnapshotStrategy strategy = null; - for (SnapshotStrategy st : snapshotStrategies) { - if (st.canHandle(snap)) { - strategy = st; - break; - } - } + SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotId, DataStoreRole.Primary); try { - snapshot = strategy.takeSnapshot(volume, snapshotId); - if (snapshot != null) { - postCreateSnapshot(volumeId, snapshot.getId(), policyId); - //Check if the snapshot was removed while backingUp. If yes, do not log snapshot create usage event - SnapshotVO freshSnapshot = _snapshotDao.findById(snapshot.getId()); - if ((freshSnapshot != null) && backedUp) { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(), - snapshot.getDataCenterId(), snapshotId, snapshot.getName(), null, null, - volume.getSize(), snapshot.getClass().getName(), snapshot.getUuid()); - } + postCreateSnapshot(volumeId, snapshot.getId(), policyId); + //Check if the snapshot was removed while backingUp. If yes, do not log snapshot create usage event + SnapshotVO freshSnapshot = _snapshotDao.findById(snapshot.getId()); + if ((freshSnapshot != null) && backedUp) { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(), + snapshot.getDataCenterId(), snapshotId, snapshot.getName(), null, null, + volume.getSize(), snapshot.getClass().getName(), snapshot.getUuid()); + } + + _resourceLimitMgr.incrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot); - _resourceLimitMgr.incrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot); - } - if (backup) { - this.backupSnapshot(snapshotId); - } } catch(Exception e) { s_logger.debug("Failed to create snapshot", e); if (backup) { @@ -315,58 +314,27 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, return snapshot; } - private void checkObjectStorageConfiguration(SwiftTO swift, S3TO s3) { - if (swift != null && s3 != null) { - throw new CloudRuntimeException( - "Swift and S3 are not simultaneously supported for snapshot backup."); - } - - } - - @Override - public void deleteSnapshotsDirForVolume(String secondaryStoragePoolUrl, Long dcId, Long accountId, Long volumeId) { - DeleteSnapshotsDirCommand cmd = new DeleteSnapshotsDirCommand(secondaryStoragePoolUrl, dcId, accountId, volumeId); - try { - Answer ans = _agentMgr.sendToSSVM(dcId, cmd); - if (ans == null || !ans.getResult()) { - s_logger.warn("DeleteSnapshotsDirCommand failed due to " + ans.getDetails() + " volume id: " + volumeId); - } - } catch (Exception e) { - s_logger.warn("DeleteSnapshotsDirCommand failed due to" + e.toString() + " volume id: " + volumeId); - } - } @Override public Snapshot backupSnapshot(Long snapshotId) { - SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotId); - if (snapshot == null) { - throw new CloudRuntimeException("Can't find snapshot:" + snapshotId); + SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotId, DataStoreRole.Image); + if (snapshot != null) { + throw new CloudRuntimeException("Already in the backup snapshot:" + snapshotId); } - - if (snapshot.getState() == Snapshot.State.BackedUp) { - return snapshot; - } - - SnapshotStrategy strategy = null; - for (SnapshotStrategy st : snapshotStrategies) { - if (st.canHandle(snapshot)) { - strategy = st; - break; - } - } - - return strategy.backupSnapshot(snapshot); + + return this.snapshotSrv.backupSnapshot(snapshot); } + /* @Override public void downloadSnapshotsFromSwift(SnapshotVO ss) { + long volumeId = ss.getVolumeId(); VolumeVO volume = _volsDao.findById(volumeId); Long dcId = volume.getDataCenterId(); Long accountId = volume.getAccountId(); - HostVO secHost = this.templateMgr.getSecondaryStorageHost(dcId); - String secondaryStoragePoolUrl = secHost.getStorageUrl(); + DataStore secStore = this.dataStoreMgr.getImageStore(dcId); Long swiftId = ss.getSwiftId(); SwiftTO swift = _swiftMgr.getSwiftTO(swiftId); @@ -383,7 +351,11 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, String parent = null; try { for (String backupUuid : BackupUuids) { +<<<<<<< HEAD + downloadSnapshotFromSwiftCommand cmd = new downloadSnapshotFromSwiftCommand(swift, secStore.getUri(), dcId, accountId, volumeId, parent, backupUuid, _backupsnapshotwait); +======= DownloadSnapshotFromSwiftCommand cmd = new DownloadSnapshotFromSwiftCommand(swift, secondaryStoragePoolUrl, dcId, accountId, volumeId, parent, backupUuid, _backupsnapshotwait); +>>>>>>> master Answer answer = _agentMgr.sendToSSVM(dcId, cmd); if ((answer == null) || !answer.getResult()) { throw new CloudRuntimeException("downloadSnapshotsFromSwift failed "); @@ -393,7 +365,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, } catch (Exception e) { throw new CloudRuntimeException("downloadSnapshotsFromSwift failed due to " + e.toString()); } - + } private List determineBackupUuids(final SnapshotVO snapshot) { @@ -416,7 +388,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, final VolumeVO volume = _volsDao.findById(snapshot.getVolumeId()); final Long zoneId = volume.getDataCenterId(); - final HostVO secHost = this.templateMgr.getSecondaryStorageHost(zoneId); + final DataStore secStore = this.dataStoreMgr.getImageStore(zoneId); final S3TO s3 = _s3Mgr.getS3TO(snapshot.getS3Id()); final List backupUuids = determineBackupUuids(snapshot); @@ -425,7 +397,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, String parent = null; for (final String backupUuid : backupUuids) { final DownloadSnapshotFromS3Command cmd = new DownloadSnapshotFromS3Command( - s3, parent, secHost.getStorageUrl(), zoneId, + s3, parent, secStore.getUri(), zoneId, volume.getAccountId(), volume.getId(), backupUuid, _backupsnapshotwait); final Answer answer = _agentMgr.sendToSSVM(zoneId, cmd); @@ -443,17 +415,17 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, e); } - } - + }*/ + @Override - public SnapshotVO getParentSnapshot(VolumeInfo volume, Snapshot snapshot) { - long preId = _snapshotDao.getLastSnapshot(volume.getId(), snapshot.getId()); + public SnapshotVO getParentSnapshot(VolumeInfo volume) { + long preId = _snapshotDao.getLastSnapshot(volume.getId(), DataStoreRole.Primary); SnapshotVO preSnapshotVO = null; if (preId != 0 && !(volume.getLastPoolId() != null && !volume.getLastPoolId().equals(volume.getPoolId()))) { preSnapshotVO = _snapshotDao.findByIdIncludingRemoved(preId); } - + return preSnapshotVO; } @@ -474,7 +446,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, snapshotSchedule.setSnapshotId(snapshotId); _snapshotScheduleDao.update(snapshotSchedule.getId(), snapshotSchedule); } - + if (snapshot != null && snapshot.isRecursive()) { postCreateRecurringSnapshotForPolicy(userId, volumeId, snapshotId, policyId); } @@ -510,22 +482,21 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, Account caller = UserContext.current().getCaller(); // Verify parameters - SnapshotInfo snapshotCheck = this.snapshotFactory.getSnapshot(snapshotId); + SnapshotVO snapshotCheck = this._snapshotDao.findById(snapshotId); if (snapshotCheck == null) { throw new InvalidParameterValueException("unable to find a snapshot with id " + snapshotId); } - + _accountMgr.checkAccess(caller, null, true, snapshotCheck); - - SnapshotStrategy strategy = null; - for (SnapshotStrategy st : snapshotStrategies) { - if (st.canHandle(snapshotCheck)) { - strategy = st; + SnapshotStrategy snapshotStrategy = null; + for (SnapshotStrategy strategy : this.snapshotStrategies) { + if (strategy.canHandle(snapshotCheck)) { + snapshotStrategy = strategy; break; } } try { - boolean result = strategy.deleteSnapshot(snapshotCheck); + boolean result = snapshotStrategy.deleteSnapshot(snapshotId); if (result) { if (snapshotCheck.getState() == Snapshot.State.BackedUp) { UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_DELETE, snapshotCheck.getAccountId(), @@ -543,24 +514,17 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, } } - private HostVO getSecondaryStorageHost(SnapshotVO snapshot) { - HostVO secHost = null; - if( snapshot.getSwiftId() == null || snapshot.getSwiftId() == 0) { - secHost = _hostDao.findById(snapshot.getSecHostId()); - } else { - Long dcId = snapshot.getDataCenterId(); - secHost = this.templateMgr.getSecondaryStorageHost(dcId); - } - return secHost; - } @Override public String getSecondaryStorageURL(SnapshotVO snapshot) { - HostVO secHost = getSecondaryStorageHost(snapshot); - if (secHost != null) { - return secHost.getStorageUrl(); + SnapshotDataStoreVO snapshotStore = this._snapshotStoreDao.findBySnapshot(snapshot.getId(), DataStoreRole.Image); + if (snapshotStore != null){ + DataStore store = this.dataStoreMgr.getDataStore(snapshotStore.getDataStoreId(), DataStoreRole.Image); + if ( store != null ){ + return store.getUri(); + } } - throw new CloudRuntimeException("Can not find secondary storage"); + throw new CloudRuntimeException("Can not find secondary storage hosting the snapshot"); } @Override @@ -573,7 +537,6 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, String intervalTypeStr = cmd.getIntervalType(); Map tags = cmd.getTags(); Long zoneId = cmd.getZoneId(); - Account caller = UserContext.current().getCaller(); List permittedAccounts = new ArrayList(); @@ -589,13 +552,13 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false); Long domainId = domainIdRecursiveListProject.first(); Boolean isRecursive = domainIdRecursiveListProject.second(); - ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); - + ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); + Filter searchFilter = new Filter(SnapshotVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal()); SearchBuilder sb = _snapshotDao.createSearchBuilder(); _accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); - sb.and("status", sb.entity().getState(), SearchCriteria.Op.EQ); + sb.and("statusNEQ", sb.entity().getState(), SearchCriteria.Op.NEQ); //exclude those Destroyed snapshot, not showing on UI sb.and("volumeId", sb.entity().getVolumeId(), SearchCriteria.Op.EQ); sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); @@ -604,24 +567,26 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); if (tags != null && !tags.isEmpty()) { - SearchBuilder tagSearch = _resourceTagDao.createSearchBuilder(); - for (int count=0; count < tags.size(); count++) { - tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ); - tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ); - tagSearch.cp(); + SearchBuilder tagSearch = _resourceTagDao.createSearchBuilder(); + for (int count=0; count < tags.size(); count++) { + tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ); + tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ); + tagSearch.cp(); + } + tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ); + sb.groupBy(sb.entity().getId()); + sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER); } - tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ); - sb.groupBy(sb.entity().getId()); - sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER); - } SearchCriteria sc = sb.create(); _accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + sc.setParameters("statusNEQ", Snapshot.State.Destroyed); + if (volumeId != null) { sc.setParameters("volumeId", volumeId); } - + if (tags != null && !tags.isEmpty()) { int count = 0; sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.Snapshot.toString()); @@ -635,7 +600,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, if (zoneId != null) { sc.setParameters("dataCenterId", zoneId); } - + if (name != null) { sc.setParameters("name", "%" + name + "%"); } @@ -694,47 +659,18 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, // This volume doesn't have any snapshots. Nothing do delete. continue; } - List ssHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(dcId); - SwiftTO swift = _swiftMgr.getSwiftTO(); - S3TO s3 = _s3Mgr.getS3TO(); - - checkObjectStorageConfiguration(swift, s3); - StoragePoolVO pool = _primaryDataStoreDao.findById(volume.getPoolId()); - if (swift == null && s3 == null) { - for (HostVO ssHost : ssHosts) { - DeleteSnapshotBackupCommand cmd = new DeleteSnapshotBackupCommand( - pool,null, null, ssHost.getStorageUrl(), dcId, - accountId, volumeId, "", true); - Answer answer = null; - try { - answer = _agentMgr.sendToSSVM(dcId, cmd); - } catch (Exception e) { - s_logger.warn("Failed to delete all snapshot for volume " + volumeId + " on secondary storage " + ssHost.getStorageUrl()); - } - if ((answer != null) && answer.getResult()) { - s_logger.debug("Deleted all snapshots for volume: " + volumeId + " under account: " + accountId); - } else { - success = false; - if (answer != null) { - s_logger.error(answer.getDetails()); - } - } - } - } else { - DeleteSnapshotBackupCommand cmd = new DeleteSnapshotBackupCommand( - pool,swift, s3, "", dcId, accountId, volumeId, "", true); - Answer answer = null; - try { - answer = _agentMgr.sendToSSVM(dcId, cmd); - } catch (Exception e) { - final String storeType = s3 != null ? "S3" : "swift"; - s_logger.warn("Failed to delete all snapshot for volume " + volumeId + " on " + storeType); - } + List ssHosts = this.dataStoreMgr.getImageStoresByScope(new ZoneScope(dcId)); + for (DataStore ssHost : ssHosts) { + String snapshotDir = TemplateConstants.DEFAULT_SNAPSHOT_ROOT_DIR + "/" + accountId + "/" + volumeId; + DeleteSnapshotsDirCommand cmd = new DeleteSnapshotsDirCommand(ssHost.getTO(), snapshotDir); + EndPoint ep = _epSelector.select(ssHost); + Answer answer = ep.sendMessage(cmd); if ((answer != null) && answer.getResult()) { s_logger.debug("Deleted all snapshots for volume: " + volumeId + " under account: " + accountId); } else { success = false; if (answer != null) { + s_logger.warn("Failed to delete all snapshot for volume " + volumeId + " on secondary storage " + ssHost.getUri()); s_logger.error(answer.getDetails()); } } @@ -770,9 +706,9 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, if (volume == null) { throw new InvalidParameterValueException("Failed to create snapshot policy, unable to find a volume with id " + volumeId); } - + _accountMgr.checkAccess(UserContext.current().getCaller(), null, true, volume); - + if (volume.getState() != Volume.State.Ready) { throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in " + Volume.State.Ready + " state but " + volume.getState() + ". Cannot take snapshot."); } @@ -828,7 +764,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, if (owner.getType() == Account.ACCOUNT_TYPE_PROJECT) { message = "domain/project"; } - + throw new InvalidParameterValueException("Max number of snapshots shouldn't exceed the " + message + " level snapshot limit"); } @@ -874,11 +810,11 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, return new Pair, Integer>(result.first(), result.second()); } - + private List listPoliciesforVolume(long volumeId) { return _snapshotPolicyDao.listByVolumeId(volumeId); } - + private List listSnapsforVolume(long volumeId) { return _snapshotDao.listByVolumeId(volumeId); } @@ -963,94 +899,118 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, return null; } - @Override - public SnapshotVO allocSnapshot(Long volumeId, Long policyId) throws ResourceAllocationException { - Account caller = UserContext.current().getCaller(); - - VolumeVO volume = _volsDao.findById(volumeId); - if (volume == null) { - throw new InvalidParameterValueException("Creating snapshot failed due to volume:" + volumeId + " doesn't exist"); - } - DataCenter zone = _dcDao.findById(volume.getDataCenterId()); - if (zone == null) { - throw new InvalidParameterValueException("Can't find zone by id " + volume.getDataCenterId()); - } - - if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) { - throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: " + zone.getName()); - } - - if (volume.getState() != Volume.State.Ready) { - throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in " + Volume.State.Ready + " state but " + volume.getState() + ". Cannot take snapshot."); - } - if ( volume.getTemplateId() != null ) { - VMTemplateVO template = _templateDao.findById(volume.getTemplateId()); - if( template != null && template.getTemplateType() == Storage.TemplateType.SYSTEM ) { - throw new InvalidParameterValueException("VolumeId: " + volumeId + " is for System VM , Creating snapshot against System VM volumes is not supported"); - } - } - - StoragePoolVO storagePoolVO = _storagePoolDao.findById(volume.getPoolId()); - if (storagePoolVO == null) { - throw new InvalidParameterValueException("VolumeId: " + volumeId + " please attach this volume to a VM before create snapshot for it"); - } - ClusterVO cluster = _clusterDao.findById(storagePoolVO.getClusterId()); + private boolean hostSupportSnapsthot(HostVO host) { + if (host.getHypervisorType() != HypervisorType.KVM) { + return true; + } + // Determine host capabilities + String caps = host.getCapabilities(); + + if (caps != null) { + String[] tokens = caps.split(","); + for (String token : tokens) { + if (token.contains("snapshot")) { + return true; + } + } + } + return false; + } + + private boolean supportedByHypervisor(VolumeInfo volume) { + StoragePool storagePool = (StoragePool)volume.getDataStore(); + ClusterVO cluster = _clusterDao.findById(storagePool.getClusterId()); if (cluster != null && cluster.getHypervisorType() == HypervisorType.Ovm) { throw new InvalidParameterValueException("Ovm won't support taking snapshot"); } - // Verify permissions - _accountMgr.checkAccess(caller, null, true, volume); - Type snapshotType = getSnapshotType(policyId); - Account owner = _accountMgr.getAccount(volume.getAccountId()); + if (volume.getHypervisorType().equals(HypervisorType.KVM)) { + List hosts = _resourceMgr.listAllHostsInCluster(cluster.getId()); + if (hosts != null && !hosts.isEmpty()) { + HostVO host = hosts.get(0); + if (!hostSupportSnapsthot(host)) { + throw new CloudRuntimeException("KVM Snapshot is not supported on cluster: " + host.getId()); + } + } + } - try{ - _resourceLimitMgr.checkResourceLimit(owner, ResourceType.snapshot); + // if volume is attached to a vm in destroyed or expunging state; disallow + if (volume.getInstanceId() != null) { + UserVmVO userVm = _vmDao.findById(volume.getInstanceId()); + if (userVm != null) { + if (userVm.getState().equals(State.Destroyed) || userVm.getState().equals(State.Expunging)) { + throw new CloudRuntimeException("Creating snapshot failed due to volume:" + volume.getId() + + " is associated with vm:" + userVm.getInstanceName() + " is in " + + userVm.getState().toString() + " state"); + } + + if (userVm.getHypervisorType() == HypervisorType.VMware + || userVm.getHypervisorType() == HypervisorType.KVM) { + List activeSnapshots = _snapshotDao.listByInstanceId(volume.getInstanceId(), + Snapshot.State.Creating, Snapshot.State.CreatedOnPrimary, Snapshot.State.BackingUp); + if (activeSnapshots.size() > 1) + throw new CloudRuntimeException( + "There is other active snapshot tasks on the instance to which the volume is attached, please try again later"); + } + + List activeVMSnapshots = _vmSnapshotDao.listByInstanceId(userVm.getId(), + VMSnapshot.State.Creating, VMSnapshot.State.Reverting, VMSnapshot.State.Expunging); + if (activeVMSnapshots.size() > 0) { + throw new CloudRuntimeException( + "There is other active vm snapshot tasks on the instance to which the volume is attached, please try again later"); + } + } + } + + return true; + } + @Override + public SnapshotInfo takeSnapshot(VolumeInfo volume) throws ResourceAllocationException { + CreateSnapshotPayload payload = (CreateSnapshotPayload)volume.getpayload(); + Long snapshotId = payload.getSnapshotId(); + Account snapshotOwner = payload.getAccount(); + SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotId, volume.getDataStore()); + boolean processed = false; + + try { + for (SnapshotStrategy strategy : snapshotStrategies) { + if (strategy.canHandle(snapshot)) { + processed = true; + snapshot = strategy.takeSnapshot(snapshot); + break; + } + } + if (!processed) { + throw new CloudRuntimeException("Can't find snapshot strategy to deal with snapshot:" + snapshotId); + } + postCreateSnapshot(volume.getId(), snapshotId, payload.getSnapshotPolicyId()); + + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(), + snapshot.getDataCenterId(), snapshotId, snapshot.getName(), null, null, + volume.getSize(), snapshot.getClass().getName(), snapshot.getUuid()); + + + _resourceLimitMgr.incrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot); + + } catch(Exception e) { + s_logger.debug("Failed to create snapshot", e); if (backup) { - _resourceLimitMgr.checkResourceLimit(owner, ResourceType.secondary_storage, new Long(volume.getSize())); + _resourceLimitMgr.decrementResourceCount(snapshotOwner.getId(), ResourceType.secondary_storage, + new Long(volume.getSize())); } else { - _resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, new Long(volume.getSize())); + _resourceLimitMgr.decrementResourceCount(snapshotOwner.getId(), ResourceType.primary_storage, + new Long(volume.getSize())); } - } catch (ResourceAllocationException e) { - if (snapshotType != Type.MANUAL){ - String msg = "Snapshot resource limit exceeded for account id : " + owner.getId() + ". Failed to create recurring snapshots"; - s_logger.warn(msg); - _alertMgr.sendAlert(AlertManager.ALERT_TYPE_UPDATE_RESOURCE_COUNT, 0L, 0L, msg, - "Snapshot resource limit exceeded for account id : " + owner.getId() + ". Failed to create recurring snapshots; please use updateResourceLimit to increase the limit"); - } - throw e; - } - - // Determine the name for this snapshot - // Snapshot Name: VMInstancename + volumeName + timeString - String timeString = DateUtil.getDateDisplayString(DateUtil.GMT_TIMEZONE, new Date(), DateUtil.YYYYMMDD_FORMAT); - - String snapshotName = volume.getUuid() + "_" + timeString; - - // Create the Snapshot object and save it so we can return it to the - // user - HypervisorType hypervisorType = this._volsDao.getHypervisorType(volumeId); - SnapshotVO snapshotVO = new SnapshotVO(volume.getDataCenterId(), volume.getAccountId(), volume.getDomainId(), volume.getId(), volume.getDiskOfferingId(), null, snapshotName, - (short) snapshotType.ordinal(), snapshotType.name(), volume.getSize(), hypervisorType); - SnapshotVO snapshot = _snapshotDao.persist(snapshotVO); - if (snapshot == null) { - throw new CloudRuntimeException("Failed to create snapshot for volume: "+volumeId); - } - if (backup) { - _resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.secondary_storage, - new Long(volume.getSize())); - } else { - _resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.primary_storage, - new Long(volume.getSize())); + throw new CloudRuntimeException("Failed to create snapshot", e); } return snapshot; } @Override public boolean configure(String name, Map params) throws ConfigurationException { - + String value = _configDao.getValue(Config.BackupSnapshotWait.toString()); _backupsnapshotwait = NumbersUtil.parseInt(value, Integer.parseInt(Config.BackupSnapshotWait.getDefaultValue())); backup = Boolean.parseBoolean(this._configDao.getValue(Config.BackupSnapshotAferTakingSnapshot.toString())); @@ -1124,7 +1084,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, return success; } - + @Override public boolean canOperateOnVolume(Volume volume) { List snapshots = _snapshotDao.listByStatus(volume.getId(), Snapshot.State.Creating, @@ -1134,4 +1094,61 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, } return true; } + + @Override + public Snapshot allocSnapshot(Long volumeId, Long policyId) throws ResourceAllocationException { + Account caller = UserContext.current().getCaller(); + VolumeInfo volume = this.volFactory.getVolume(volumeId); + supportedByHypervisor(volume); + + // Verify permissions + _accountMgr.checkAccess(caller, null, true, volume); + Type snapshotType = getSnapshotType(policyId); + Account owner = _accountMgr.getAccount(volume.getAccountId()); + + try{ + _resourceLimitMgr.checkResourceLimit(owner, ResourceType.snapshot); + if (backup) { + _resourceLimitMgr.checkResourceLimit(owner, ResourceType.secondary_storage, new Long(volume.getSize())); + } else { + _resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, new Long(volume.getSize())); + } + } catch (ResourceAllocationException e) { + if (snapshotType != Type.MANUAL){ + String msg = "Snapshot resource limit exceeded for account id : " + owner.getId() + ". Failed to create recurring snapshots"; + s_logger.warn(msg); + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_UPDATE_RESOURCE_COUNT, 0L, 0L, msg, + "Snapshot resource limit exceeded for account id : " + owner.getId() + ". Failed to create recurring snapshots; please use updateResourceLimit to increase the limit"); + } + throw e; + } + + // Determine the name for this snapshot + // Snapshot Name: VMInstancename + volumeName + timeString + String timeString = DateUtil.getDateDisplayString(DateUtil.GMT_TIMEZONE, new Date(), DateUtil.YYYYMMDD_FORMAT); + + VMInstanceVO vmInstance = _vmDao.findById(volume.getInstanceId()); + String vmDisplayName = "detached"; + if (vmInstance != null) { + vmDisplayName = vmInstance.getHostName(); + } + String snapshotName = vmDisplayName + "_" + volume.getName() + "_" + timeString; + + HypervisorType hypervisorType = volume.getHypervisorType(); + SnapshotVO snapshotVO = new SnapshotVO(volume.getDataCenterId(), volume.getAccountId(), volume.getDomainId(), volume.getId(), volume.getDiskOfferingId(), snapshotName, + (short) snapshotType.ordinal(), snapshotType.name(), volume.getSize(), hypervisorType); + + SnapshotVO snapshot = _snapshotDao.persist(snapshotVO); + if (snapshot == null) { + throw new CloudRuntimeException("Failed to create snapshot for volume: " + volume.getId()); + } + if (backup) { + _resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.secondary_storage, + new Long(volume.getSize())); + } else { + _resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.primary_storage, + new Long(volume.getSize())); + } + return snapshot; + } } diff --git a/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java index 4696bb5d1c2..6a5d0cacbd6 100644 --- a/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java @@ -76,7 +76,7 @@ public class SnapshotSchedulerImpl extends ManagerBase implements SnapshotSchedu @Inject protected AsyncJobManager _asyncMgr; @Inject protected VolumeDao _volsDao; @Inject protected ConfigurationDao _configDao; - + private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION = 5; // 5 seconds private int _snapshotPollInterval; private Timer _testClockTimer; @@ -348,7 +348,7 @@ public class SnapshotSchedulerImpl extends ManagerBase implements SnapshotSchedu _testTimerTask = new TestClock(this, minutesPerHour, hoursPerDay, daysPerWeek, daysPerMonth, weeksPerMonth, monthsPerYear); } _currentTimestamp = new Date(); - + s_logger.info("Snapshot Scheduler is configured."); return true; diff --git a/server/src/com/cloud/storage/swift/SwiftManagerImpl.java b/server/src/com/cloud/storage/swift/SwiftManagerImpl.java index 5a7f01ab20b..3149f5aad17 100644 --- a/server/src/com/cloud/storage/swift/SwiftManagerImpl.java +++ b/server/src/com/cloud/storage/swift/SwiftManagerImpl.java @@ -34,9 +34,11 @@ import org.springframework.stereotype.Component; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; -import com.cloud.agent.api.DeleteObjectFromSwiftCommand; import com.cloud.agent.api.to.SwiftTO; import org.apache.cloudstack.api.command.admin.swift.AddSwiftCmd; +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.to.TemplateObjectTO; + import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.DataCenterVO; @@ -144,7 +146,10 @@ public class SwiftManagerImpl extends ManagerBase implements SwiftManager { s_logger.warn(msg); throw new CloudRuntimeException(msg); } - Answer answer = _agentMgr.sendToSSVM(null, new DeleteObjectFromSwiftCommand(swift, "T-" + cmd.getId(), null)); + TemplateObjectTO tmplTO = new TemplateObjectTO(); + tmplTO.setDataStore(swift); + tmplTO.setId(cmd.getId()); + Answer answer = _agentMgr.sendToSSVM(null, new DeleteCommand(tmplTO)); if (answer == null || !answer.getResult()) { msg = "Failed to delete " + tmpltSwiftRef + " due to " + ((answer == null) ? "answer is null" : answer.getDetails()); s_logger.warn(msg); @@ -170,7 +175,9 @@ public class SwiftManagerImpl extends ManagerBase implements SwiftManager { s_logger.warn(msg); throw new CloudRuntimeException(msg); } - Answer answer = _agentMgr.sendToSSVM(null, new DeleteObjectFromSwiftCommand(swift, "T-" + cmd.getId(), null)); + TemplateObjectTO tmplTO = new TemplateObjectTO(); + tmplTO.setId(cmd.getId()); + Answer answer = _agentMgr.sendToSSVM(null, new DeleteCommand(tmplTO)); if (answer == null || !answer.getResult()) { msg = "Failed to delete " + tmpltSwiftRef + " due to " + ((answer == null) ? "answer is null" : answer.getDetails()); s_logger.warn(msg); @@ -236,7 +243,7 @@ public class SwiftManagerImpl extends ManagerBase implements SwiftManager { if (swift == null) { return null; } - + List tmpltHosts = _vmTmpltHostDao.listByOnlyTemplateId(tmpltId); if (tmpltHosts != null) { Collections.shuffle(tmpltHosts); diff --git a/server/src/com/cloud/storage/upload/UploadListener.java b/server/src/com/cloud/storage/upload/UploadListener.java index ee13cf9b0d8..d3b7af9f675 100755 --- a/server/src/com/cloud/storage/upload/UploadListener.java +++ b/server/src/com/cloud/storage/upload/UploadListener.java @@ -16,7 +16,6 @@ // under the License. package com.cloud.storage.upload; - import java.util.Collections; import java.util.Date; import java.util.HashMap; @@ -24,8 +23,16 @@ import java.util.Map; import java.util.Timer; import java.util.TimerTask; +import javax.inject.Inject; + import org.apache.cloudstack.api.command.user.iso.ExtractIsoCmd; +import org.apache.cloudstack.api.command.user.template.ExtractTemplateCmd; import org.apache.cloudstack.api.command.user.volume.ExtractVolumeCmd; +import org.apache.cloudstack.api.response.ExtractResponse; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.log4j.Level; import org.apache.log4j.Logger; @@ -40,14 +47,10 @@ import com.cloud.agent.api.storage.UploadAnswer; import com.cloud.agent.api.storage.UploadCommand; import com.cloud.agent.api.storage.UploadProgressCommand; import com.cloud.agent.api.storage.UploadProgressCommand.RequestType; -import org.apache.cloudstack.api.command.user.template.ExtractTemplateCmd; -import org.apache.cloudstack.api.response.ExtractResponse; - import com.cloud.api.ApiDBUtils; import com.cloud.async.AsyncJobManager; import com.cloud.async.AsyncJobResult; -import com.cloud.exception.AgentUnavailableException; -import com.cloud.host.HostVO; +import com.cloud.host.Host; import com.cloud.storage.Storage; import com.cloud.storage.Upload.Status; import com.cloud.storage.Upload.Type; @@ -58,401 +61,420 @@ import com.cloud.utils.exception.CloudRuntimeException; public class UploadListener implements Listener { + private static final class StatusTask extends TimerTask { + private final UploadListener ul; + private final RequestType reqType; - private static final class StatusTask extends TimerTask { - private final UploadListener ul; - private final RequestType reqType; + public StatusTask(UploadListener ul, RequestType req) { + this.reqType = req; + this.ul = ul; + } - public StatusTask( UploadListener ul, RequestType req) { - this.reqType = req; - this.ul = ul; - } + @Override + public void run() { + ul.sendCommand(reqType); - @Override - public void run() { - ul.sendCommand(reqType); + } + } - } - } + private static final class TimeoutTask extends TimerTask { + private final UploadListener ul; - private static final class TimeoutTask extends TimerTask { - private final UploadListener ul; + public TimeoutTask(UploadListener ul) { + this.ul = ul; + } - public TimeoutTask( UploadListener ul) { - this.ul = ul; - } + @Override + public void run() { + ul.checkProgress(); + } + } - @Override - public void run() { - ul.checkProgress(); - } - } + public static final Logger s_logger = Logger.getLogger(UploadListener.class.getName()); + public static final int SMALL_DELAY = 100; + public static final long STATUS_POLL_INTERVAL = 10000L; - public static final Logger s_logger = Logger.getLogger(UploadListener.class.getName()); - public static final int SMALL_DELAY = 100; - public static final long STATUS_POLL_INTERVAL = 10000L; - - public static final String UPLOADED=Status.UPLOADED.toString(); - public static final String NOT_UPLOADED=Status.NOT_UPLOADED.toString(); - public static final String UPLOAD_ERROR=Status.UPLOAD_ERROR.toString(); - public static final String UPLOAD_IN_PROGRESS=Status.UPLOAD_IN_PROGRESS.toString(); - public static final String UPLOAD_ABANDONED=Status.ABANDONED.toString(); - public static final Map responseNameMap; - static{ - MaptempMap = new HashMap(); + public static final String UPLOADED = Status.UPLOADED.toString(); + public static final String NOT_UPLOADED = Status.NOT_UPLOADED.toString(); + public static final String UPLOAD_ERROR = Status.UPLOAD_ERROR.toString(); + public static final String UPLOAD_IN_PROGRESS = Status.UPLOAD_IN_PROGRESS.toString(); + public static final String UPLOAD_ABANDONED = Status.ABANDONED.toString(); + public static final Map responseNameMap; + static { + Map tempMap = new HashMap(); tempMap.put(Type.ISO.toString(), ExtractIsoCmd.getStaticName()); tempMap.put(Type.TEMPLATE.toString(), ExtractTemplateCmd.getStaticName()); tempMap.put(Type.VOLUME.toString(), ExtractVolumeCmd.getStaticName()); - tempMap.put("DEFAULT","extractresponse"); + tempMap.put("DEFAULT", "extractresponse"); responseNameMap = Collections.unmodifiableMap(tempMap); - } + } + private DataStore sserver; - private HostVO sserver; + private boolean uploadActive = true; - private boolean uploadActive = true; + private UploadDao uploadDao; - private UploadDao uploadDao; + private final UploadMonitorImpl uploadMonitor; - private final UploadMonitorImpl uploadMonitor; + private UploadState currState; - private UploadState currState; + private UploadCommand cmd; - private UploadCommand cmd; + private Timer timer; - private Timer timer; + private StatusTask statusTask; + private TimeoutTask timeoutTask; + private Date lastUpdated = new Date(); + private String jobId; + private Long accountId; + private String typeName; + private Type type; + private long asyncJobId; + private long eventId; + private AsyncJobManager asyncMgr; + private ExtractResponse resultObj; + @Inject + EndPointSelector _epSelector; - private StatusTask statusTask; - private TimeoutTask timeoutTask; - private Date lastUpdated = new Date(); - private String jobId; - private Long accountId; - private String typeName; - private Type type; - private long asyncJobId; - private long eventId; - private AsyncJobManager asyncMgr; - private ExtractResponse resultObj; + public AsyncJobManager getAsyncMgr() { + return asyncMgr; + } - public AsyncJobManager getAsyncMgr() { - return asyncMgr; - } + public void setAsyncMgr(AsyncJobManager asyncMgr) { + this.asyncMgr = asyncMgr; + } - public void setAsyncMgr(AsyncJobManager asyncMgr) { - this.asyncMgr = asyncMgr; - } + public long getAsyncJobId() { + return asyncJobId; + } - public long getAsyncJobId() { - return asyncJobId; - } + public void setAsyncJobId(long asyncJobId) { + this.asyncJobId = asyncJobId; + } - public void setAsyncJobId(long asyncJobId) { - this.asyncJobId = asyncJobId; - } + public long getEventId() { + return eventId; + } - public long getEventId() { - return eventId; - } + public void setEventId(long eventId) { + this.eventId = eventId; + } - public void setEventId(long eventId) { - this.eventId = eventId; - } + private final Map stateMap = new HashMap(); + private Long uploadId; - private final Map stateMap = new HashMap(); - private Long uploadId; + public UploadListener(DataStore host, Timer _timer, UploadDao uploadDao, + UploadVO uploadObj, UploadMonitorImpl uploadMonitor, UploadCommand cmd, + Long accountId, String typeName, Type type, long eventId, long asyncJobId, AsyncJobManager asyncMgr) { + this.sserver = host; + this.uploadDao = uploadDao; + this.uploadMonitor = uploadMonitor; + this.cmd = cmd; + this.uploadId = uploadObj.getId(); + this.accountId = accountId; + this.typeName = typeName; + this.type = type; + initStateMachine(); + this.currState = getState(Status.NOT_UPLOADED.toString()); + this.timer = _timer; + this.timeoutTask = new TimeoutTask(this); + this.timer.schedule(timeoutTask, 3 * STATUS_POLL_INTERVAL); + this.eventId = eventId; + this.asyncJobId = asyncJobId; + this.asyncMgr = asyncMgr; + String extractId = null; + if (type == Type.VOLUME) { + extractId = ApiDBUtils.findVolumeById(uploadObj.getTypeId()).getUuid(); + } + else { + extractId = ApiDBUtils.findTemplateById(uploadObj.getTypeId()).getUuid(); + } + this.resultObj = new ExtractResponse(extractId, typeName, ApiDBUtils.findAccountById(accountId).getUuid(), Status.NOT_UPLOADED.toString(), + ApiDBUtils.findUploadById(uploadId).getUuid()); + resultObj.setResponseName(responseNameMap.get(type.toString())); + updateDatabase(Status.NOT_UPLOADED, cmd.getUrl(), ""); + } - public UploadListener(HostVO host, Timer _timer, UploadDao uploadDao, - UploadVO uploadObj, UploadMonitorImpl uploadMonitor, UploadCommand cmd, - Long accountId, String typeName, Type type, long eventId, long asyncJobId, AsyncJobManager asyncMgr) { - this.sserver = host; - this.uploadDao = uploadDao; - this.uploadMonitor = uploadMonitor; - this.cmd = cmd; - this.uploadId = uploadObj.getId(); - this.accountId = accountId; - this.typeName = typeName; - this.type = type; - initStateMachine(); - this.currState = getState(Status.NOT_UPLOADED.toString()); - this.timer = _timer; - this.timeoutTask = new TimeoutTask(this); - this.timer.schedule(timeoutTask, 3*STATUS_POLL_INTERVAL); - this.eventId = eventId; - this.asyncJobId = asyncJobId; - this.asyncMgr = asyncMgr; - String extractId = null; - if ( type == Type.VOLUME ){ - extractId = ApiDBUtils.findVolumeById(uploadObj.getTypeId()).getUuid(); - } - else{ - extractId = ApiDBUtils.findTemplateById(uploadObj.getTypeId()).getUuid(); - } - this.resultObj = new ExtractResponse(extractId, typeName, ApiDBUtils.findAccountById(accountId).getUuid(), Status.NOT_UPLOADED.toString(), - ApiDBUtils.findUploadById(uploadId).getUuid()); - resultObj.setResponseName(responseNameMap.get(type.toString())); - updateDatabase(Status.NOT_UPLOADED, cmd.getUrl(),""); - } + public UploadListener(UploadMonitorImpl monitor) { + uploadMonitor = monitor; + } - public UploadListener(UploadMonitorImpl monitor) { - uploadMonitor = monitor; - } + public void checkProgress() { + transition(UploadEvent.TIMEOUT_CHECK, null); + } - public void checkProgress() { - transition(UploadEvent.TIMEOUT_CHECK, null); - } + @Override + public int getTimeout() { + return -1; + } - @Override - public int getTimeout() { - return -1; - } + @Override + public boolean isRecurring() { + return false; + } - @Override - public boolean isRecurring() { - return false; - } + public void setCommand(UploadCommand _cmd) { + this.cmd = _cmd; + } - public void setCommand(UploadCommand _cmd) { - this.cmd = _cmd; - } + public void setJobId(String _jobId) { + this.jobId = _jobId; + } - public void setJobId(String _jobId) { - this.jobId = _jobId; - } + public String getJobId() { + return jobId; + } - public String getJobId() { - return jobId; - } - - @Override - public boolean processAnswers(long agentId, long seq, Answer[] answers) { - boolean processed = false; - if(answers != null & answers.length > 0) { - if(answers[0] instanceof UploadAnswer) { - final UploadAnswer answer = (UploadAnswer)answers[0]; - if (getJobId() == null) { - setJobId(answer.getJobId()); - } else if (!getJobId().equalsIgnoreCase(answer.getJobId())){ - return false;//TODO - } - transition(UploadEvent.UPLOAD_ANSWER, answer); - processed = true; - } - } - return processed; - } - - - @Override - public boolean processCommands(long agentId, long seq, Command[] commands) { - return false; - } - - @Override - public void processConnect(HostVO agent, StartupCommand cmd, boolean forRebalance) { - if (!(cmd instanceof StartupStorageCommand)) { - return; - } - - long agentId = agent.getId(); - - StartupStorageCommand storage = (StartupStorageCommand)cmd; - if (storage.getResourceType() == Storage.StorageResourceType.STORAGE_HOST || - storage.getResourceType() == Storage.StorageResourceType.SECONDARY_STORAGE ) - { - uploadMonitor.handleUploadSync(agentId); - } - } - - @Override - public AgentControlAnswer processControlCommand(long agentId, - AgentControlCommand cmd) { - return null; - } - - public void setUploadInactive(Status reason) { - uploadActive=false; - uploadMonitor.handleUploadEvent(sserver, accountId, typeName, type, uploadId, reason, eventId); - } - - public void logUploadStart() { - //uploadMonitor.logEvent(accountId, event, "Storage server " + sserver.getName() + " started upload of " +type.toString() + " " + typeName, EventVO.LEVEL_INFO, eventId); - } - - public void cancelTimeoutTask() { - if (timeoutTask != null) timeoutTask.cancel(); - } - - public void cancelStatusTask() { - if (statusTask != null) statusTask.cancel(); - } - - @Override - public boolean processDisconnect(long agentId, com.cloud.host.Status state) { - setDisconnected(); - return true; - } - - @Override - public boolean processTimeout(long agentId, long seq) { - return true; - } - - private void initStateMachine() { - stateMap.put(Status.NOT_UPLOADED.toString(), new NotUploadedState(this)); - stateMap.put(Status.UPLOADED.toString(), new UploadCompleteState(this)); - stateMap.put(Status.UPLOAD_ERROR.toString(), new UploadErrorState(this)); - stateMap.put(Status.UPLOAD_IN_PROGRESS.toString(), new UploadInProgressState(this)); - stateMap.put(Status.ABANDONED.toString(), new UploadAbandonedState(this)); - } - - private UploadState getState(String stateName) { - return stateMap.get(stateName); - } - - private synchronized void transition(UploadEvent event, Object evtObj) { - if (currState == null) { - return; - } - String prevName = currState.getName(); - String nextState = currState.handleEvent(event, evtObj); - if (nextState != null) { - currState = getState(nextState); - if (currState != null) { - currState.onEntry(prevName, event, evtObj); - } else { - throw new CloudRuntimeException("Invalid next state: currState="+prevName+", evt="+event + ", next=" + nextState); - } - } else { - throw new CloudRuntimeException("Unhandled event transition: currState="+prevName+", evt="+event); - } - } - - public Date getLastUpdated() { - return lastUpdated; - } - - public void setLastUpdated() { - lastUpdated = new Date(); - } - - public void log(String message, Level level) { - s_logger.log(level, message + ", " + type.toString() + " = " + typeName + " at host " + sserver.getName()); - } - - public void setDisconnected() { - transition(UploadEvent.DISCONNECT, null); - } - - public void scheduleStatusCheck(com.cloud.agent.api.storage.UploadProgressCommand.RequestType getStatus) { - if (statusTask != null) statusTask.cancel(); - - statusTask = new StatusTask(this, getStatus); - timer.schedule(statusTask, STATUS_POLL_INTERVAL); - } - - public void scheduleTimeoutTask(long delay) { - if (timeoutTask != null) timeoutTask.cancel(); - - timeoutTask = new TimeoutTask(this); - timer.schedule(timeoutTask, delay); - if (s_logger.isDebugEnabled()) { - log("Scheduling timeout at " + delay + " ms", Level.DEBUG); - } - } - - public void updateDatabase(Status state, String uploadErrorString) { - resultObj.setResultString(uploadErrorString); - resultObj.setState(state.toString()); - asyncMgr.updateAsyncJobAttachment(asyncJobId, type.toString(), 1L); - asyncMgr.updateAsyncJobStatus(asyncJobId, AsyncJobResult.STATUS_IN_PROGRESS, resultObj); - - UploadVO vo = uploadDao.createForUpdate(); - vo.setUploadState(state); - vo.setLastUpdated(new Date()); - vo.setErrorString(uploadErrorString); - uploadDao.update(getUploadId(), vo); - } - - public void updateDatabase(Status state, String uploadUrl,String uploadErrorString) { - resultObj.setResultString(uploadErrorString); - resultObj.setState(state.toString()); - asyncMgr.updateAsyncJobAttachment(asyncJobId, type.toString(), 1L); - asyncMgr.updateAsyncJobStatus(asyncJobId, AsyncJobResult.STATUS_IN_PROGRESS, resultObj); - - - UploadVO vo = uploadDao.createForUpdate(); - vo.setUploadState(state); - vo.setLastUpdated(new Date()); - vo.setUploadUrl(uploadUrl); - vo.setJobId(null); - vo.setUploadPercent(0); - vo.setErrorString(uploadErrorString); - - uploadDao.update(getUploadId(), vo); - } - - private Long getUploadId() { - return uploadId; - } - - public synchronized void updateDatabase(UploadAnswer answer) { - - if(answer.getErrorString().startsWith("553")){ - answer.setErrorString(answer.getErrorString().concat("Please check if the file name already exists.")); - } - resultObj.setResultString(answer.getErrorString()); - resultObj.setState(answer.getUploadStatus().toString()); - resultObj.setUploadPercent(answer.getUploadPct()); - - if (answer.getUploadStatus() == Status.UPLOAD_IN_PROGRESS){ - asyncMgr.updateAsyncJobAttachment(asyncJobId, type.toString(), 1L); - asyncMgr.updateAsyncJobStatus(asyncJobId, AsyncJobResult.STATUS_IN_PROGRESS, resultObj); - }else if(answer.getUploadStatus() == Status.UPLOADED){ - resultObj.setResultString("Success"); - asyncMgr.completeAsyncJob(asyncJobId, AsyncJobResult.STATUS_SUCCEEDED, 1, resultObj); - }else{ - asyncMgr.completeAsyncJob(asyncJobId, AsyncJobResult.STATUS_FAILED, 2, resultObj); - } - UploadVO updateBuilder = uploadDao.createForUpdate(); - updateBuilder.setUploadPercent(answer.getUploadPct()); - updateBuilder.setUploadState(answer.getUploadStatus()); - updateBuilder.setLastUpdated(new Date()); - updateBuilder.setErrorString(answer.getErrorString()); - updateBuilder.setJobId(answer.getJobId()); - - uploadDao.update(getUploadId(), updateBuilder); - } - - public void sendCommand(RequestType reqType) { - if (getJobId() != null) { - if (s_logger.isTraceEnabled()) { - log("Sending progress command ", Level.TRACE); - } - try { - uploadMonitor.send(sserver.getId(), new UploadProgressCommand(getCommand(), getJobId(), reqType), this); - } catch (AgentUnavailableException e) { - s_logger.debug("Send command failed", e); - setDisconnected(); + @Override + public boolean processAnswers(long agentId, long seq, Answer[] answers) { + boolean processed = false; + if (answers != null & answers.length > 0) { + if (answers[0] instanceof UploadAnswer) { + final UploadAnswer answer = (UploadAnswer)answers[0]; + if (getJobId() == null) { + setJobId(answer.getJobId()); + } else if (!getJobId().equalsIgnoreCase(answer.getJobId())) { + return false;//TODO + } + transition(UploadEvent.UPLOAD_ANSWER, answer); + processed = true; } - } + } + return processed; + } - } + @Override + public boolean processCommands(long agentId, long seq, Command[] commands) { + return false; + } - private UploadCommand getCommand() { - return cmd; - } + @Override + public void processConnect(Host agent, StartupCommand cmd, boolean forRebalance) { + if (!(cmd instanceof StartupStorageCommand)) { + return; + } - public void logDisconnect() { - s_logger.warn("Unable to monitor upload progress of " + typeName + " at host " + sserver.getName()); - } + long agentId = agent.getId(); - public void scheduleImmediateStatusCheck(RequestType request) { - if (statusTask != null) statusTask.cancel(); - statusTask = new StatusTask(this, request); - timer.schedule(statusTask, SMALL_DELAY); - } + StartupStorageCommand storage = (StartupStorageCommand)cmd; + if (storage.getResourceType() == Storage.StorageResourceType.STORAGE_HOST || + storage.getResourceType() == Storage.StorageResourceType.SECONDARY_STORAGE) + { + uploadMonitor.handleUploadSync(agentId); + } + } - public void setCurrState(Status uploadState) { - this.currState = getState(currState.toString()); - } + @Override + public AgentControlAnswer processControlCommand(long agentId, + AgentControlCommand cmd) { + return null; + } + + public void setUploadInactive(Status reason) { + uploadActive = false; + uploadMonitor.handleUploadEvent(accountId, typeName, type, uploadId, reason, eventId); + } + + public void logUploadStart() { + //uploadMonitor.logEvent(accountId, event, "Storage server " + sserver.getName() + " started upload of " +type.toString() + " " + typeName, EventVO.LEVEL_INFO, eventId); + } + + public void cancelTimeoutTask() { + if (timeoutTask != null) + timeoutTask.cancel(); + } + + public void cancelStatusTask() { + if (statusTask != null) + statusTask.cancel(); + } + + @Override + public boolean processDisconnect(long agentId, com.cloud.host.Status state) { + setDisconnected(); + return true; + } + + @Override + public boolean processTimeout(long agentId, long seq) { + return true; + } + + private void initStateMachine() { + stateMap.put(Status.NOT_UPLOADED.toString(), new NotUploadedState(this)); + stateMap.put(Status.UPLOADED.toString(), new UploadCompleteState(this)); + stateMap.put(Status.UPLOAD_ERROR.toString(), new UploadErrorState(this)); + stateMap.put(Status.UPLOAD_IN_PROGRESS.toString(), new UploadInProgressState(this)); + stateMap.put(Status.ABANDONED.toString(), new UploadAbandonedState(this)); + } + + private UploadState getState(String stateName) { + return stateMap.get(stateName); + } + + private synchronized void transition(UploadEvent event, Object evtObj) { + if (currState == null) { + return; + } + String prevName = currState.getName(); + String nextState = currState.handleEvent(event, evtObj); + if (nextState != null) { + currState = getState(nextState); + if (currState != null) { + currState.onEntry(prevName, event, evtObj); + } else { + throw new CloudRuntimeException("Invalid next state: currState=" + prevName + ", evt=" + event + ", next=" + nextState); + } + } else { + throw new CloudRuntimeException("Unhandled event transition: currState=" + prevName + ", evt=" + event); + } + } + + public Date getLastUpdated() { + return lastUpdated; + } + + public void setLastUpdated() { + lastUpdated = new Date(); + } + + public void log(String message, Level level) { + s_logger.log(level, message + ", " + type.toString() + " = " + typeName + " at host " + sserver.getName()); + } + + public void setDisconnected() { + transition(UploadEvent.DISCONNECT, null); + } + + public void scheduleStatusCheck(com.cloud.agent.api.storage.UploadProgressCommand.RequestType getStatus) { + if (statusTask != null) + statusTask.cancel(); + + statusTask = new StatusTask(this, getStatus); + timer.schedule(statusTask, STATUS_POLL_INTERVAL); + } + + public void scheduleTimeoutTask(long delay) { + if (timeoutTask != null) + timeoutTask.cancel(); + + timeoutTask = new TimeoutTask(this); + timer.schedule(timeoutTask, delay); + if (s_logger.isDebugEnabled()) { + log("Scheduling timeout at " + delay + " ms", Level.DEBUG); + } + } + + public void updateDatabase(Status state, String uploadErrorString) { + resultObj.setResultString(uploadErrorString); + resultObj.setState(state.toString()); + asyncMgr.updateAsyncJobAttachment(asyncJobId, type.toString(), 1L); + asyncMgr.updateAsyncJobStatus(asyncJobId, AsyncJobResult.STATUS_IN_PROGRESS, resultObj); + + UploadVO vo = uploadDao.createForUpdate(); + vo.setUploadState(state); + vo.setLastUpdated(new Date()); + vo.setErrorString(uploadErrorString); + uploadDao.update(getUploadId(), vo); + } + + public void updateDatabase(Status state, String uploadUrl, String uploadErrorString) { + resultObj.setResultString(uploadErrorString); + resultObj.setState(state.toString()); + asyncMgr.updateAsyncJobAttachment(asyncJobId, type.toString(), 1L); + asyncMgr.updateAsyncJobStatus(asyncJobId, AsyncJobResult.STATUS_IN_PROGRESS, resultObj); + + UploadVO vo = uploadDao.createForUpdate(); + vo.setUploadState(state); + vo.setLastUpdated(new Date()); + vo.setUploadUrl(uploadUrl); + vo.setJobId(null); + vo.setUploadPercent(0); + vo.setErrorString(uploadErrorString); + + uploadDao.update(getUploadId(), vo); + } + + private Long getUploadId() { + return uploadId; + } + + public synchronized void updateDatabase(UploadAnswer answer) { + + if (answer.getErrorString().startsWith("553")) { + answer.setErrorString(answer.getErrorString().concat("Please check if the file name already exists.")); + } + resultObj.setResultString(answer.getErrorString()); + resultObj.setState(answer.getUploadStatus().toString()); + resultObj.setUploadPercent(answer.getUploadPct()); + + if (answer.getUploadStatus() == Status.UPLOAD_IN_PROGRESS) { + asyncMgr.updateAsyncJobAttachment(asyncJobId, type.toString(), 1L); + asyncMgr.updateAsyncJobStatus(asyncJobId, AsyncJobResult.STATUS_IN_PROGRESS, resultObj); + } else if (answer.getUploadStatus() == Status.UPLOADED) { + resultObj.setResultString("Success"); + asyncMgr.completeAsyncJob(asyncJobId, AsyncJobResult.STATUS_SUCCEEDED, 1, resultObj); + } else { + asyncMgr.completeAsyncJob(asyncJobId, AsyncJobResult.STATUS_FAILED, 2, resultObj); + } + UploadVO updateBuilder = uploadDao.createForUpdate(); + updateBuilder.setUploadPercent(answer.getUploadPct()); + updateBuilder.setUploadState(answer.getUploadStatus()); + updateBuilder.setLastUpdated(new Date()); + updateBuilder.setErrorString(answer.getErrorString()); + updateBuilder.setJobId(answer.getJobId()); + + uploadDao.update(getUploadId(), updateBuilder); + } + + public void sendCommand(RequestType reqType) { + if (getJobId() != null) { + if (s_logger.isTraceEnabled()) { + log("Sending progress command ", Level.TRACE); + } + try { + EndPoint ep = _epSelector.select(sserver); + ep.sendMessageAsync(new UploadProgressCommand(getCommand(), getJobId(), reqType), new Callback(ep.getId(), this)); + } catch (Exception e) { + s_logger.debug("Send command failed", e); + setDisconnected(); + } + } + + } + + private UploadCommand getCommand() { + return cmd; + } + + public void logDisconnect() { + s_logger.warn("Unable to monitor upload progress of " + typeName + " at host " + sserver.getName()); + } + + public void scheduleImmediateStatusCheck(RequestType request) { + if (statusTask != null) + statusTask.cancel(); + statusTask = new StatusTask(this, request); + timer.schedule(statusTask, SMALL_DELAY); + } + + public void setCurrState(Status uploadState) { + this.currState = getState(currState.toString()); + } + + public static class Callback implements AsyncCompletionCallback { + long id; + Listener listener; + + public Callback(long id, Listener listener) { + this.id = id; + this.listener = listener; + } + + @Override + public void complete(Answer answer) { + listener.processAnswers(id, -1, new Answer[] {answer}); + } + } } diff --git a/server/src/com/cloud/storage/upload/UploadMonitor.java b/server/src/com/cloud/storage/upload/UploadMonitor.java index 1c3590e91e2..b4ba5319481 100755 --- a/server/src/com/cloud/storage/upload/UploadMonitor.java +++ b/server/src/com/cloud/storage/upload/UploadMonitor.java @@ -17,8 +17,12 @@ package com.cloud.storage.upload; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; + import com.cloud.async.AsyncJobManager; import com.cloud.host.HostVO; +import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Upload.Mode; import com.cloud.storage.Upload.Status; import com.cloud.storage.Upload.Type; @@ -32,12 +36,12 @@ import com.cloud.utils.component.Manager; * Monitor upload progress of all entities. * */ -public interface UploadMonitor extends Manager{ - +public interface UploadMonitor extends Manager{ + public void cancelAllUploads(Long templateId); public Long extractTemplate(VMTemplateVO template, String url, - VMTemplateHostVO tmpltHostRef,Long dataCenterId, long eventId, long asyncJobId, AsyncJobManager asyncMgr); + TemplateDataStoreVO tmpltStoreRef,Long dataCenterId, long eventId, long asyncJobId, AsyncJobManager asyncMgr); boolean isTypeUploadInProgress(Long typeId, Type type); @@ -46,14 +50,14 @@ public interface UploadMonitor extends Manager{ UploadVO createNewUploadEntry(Long hostId, Long typeId, Status uploadState, Type type, String errorString, Mode extractMode); - void extractVolume(UploadVO uploadVolumeObj, HostVO sserver, VolumeVO volume, String url, + void extractVolume(UploadVO uploadVolumeObj, DataStore secStore, VolumeVO volume, String url, Long dataCenterId, String installPath, long eventId, long asyncJobId, AsyncJobManager asyncMgr); UploadVO createEntityDownloadURL(VMTemplateVO template, - VMTemplateHostVO vmTemplateHost, Long dataCenterId, long eventId); + TemplateDataStoreVO vmTemplateStore, Long dataCenterId, long eventId); void createVolumeDownloadURL(Long entityId, String path, Type type, - Long dataCenterId, Long uploadId); + Long dataCenterId, Long uploadId, ImageFormat format); } \ No newline at end of file diff --git a/server/src/com/cloud/storage/upload/UploadMonitorImpl.java b/server/src/com/cloud/storage/upload/UploadMonitorImpl.java index 31f3e74442a..d46db0ce3a6 100755 --- a/server/src/com/cloud/storage/upload/UploadMonitorImpl.java +++ b/server/src/com/cloud/storage/upload/UploadMonitorImpl.java @@ -32,37 +32,40 @@ 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.DataStoreManager; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; +import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import com.cloud.agent.AgentManager; -import com.cloud.agent.Listener; -import com.cloud.agent.api.Command; +import com.cloud.agent.api.Answer; import com.cloud.agent.api.storage.CreateEntityDownloadURLCommand; import com.cloud.agent.api.storage.DeleteEntityDownloadURLCommand; import com.cloud.agent.api.storage.UploadCommand; import com.cloud.agent.api.storage.UploadProgressCommand.RequestType; -import com.cloud.agent.manager.Commands; import com.cloud.api.ApiDBUtils; import com.cloud.async.AsyncJobManager; import com.cloud.configuration.dao.ConfigurationDao; -import com.cloud.exception.AgentUnavailableException; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.resource.ResourceManager; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Upload; import com.cloud.storage.Upload.Mode; import com.cloud.storage.Upload.Status; import com.cloud.storage.Upload.Type; import com.cloud.storage.UploadVO; -import com.cloud.storage.VMTemplateHostVO; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.UploadDao; import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VMTemplateHostDao; import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.utils.NumbersUtil; import com.cloud.utils.component.ManagerBase; @@ -82,17 +85,15 @@ import com.cloud.vm.dao.SecondaryStorageVmDao; public class UploadMonitorImpl extends ManagerBase implements UploadMonitor { static final Logger s_logger = Logger.getLogger(UploadMonitorImpl.class); - - @Inject - VMTemplateHostDao _vmTemplateHostDao; - @Inject + + @Inject UploadDao _uploadDao; @Inject SecondaryStorageVmDao _secStorageVmDao; - + @Inject - HostDao _serverDao = null; + HostDao _serverDao = null; @Inject VMTemplateDao _templateDao = null; @Inject @@ -103,6 +104,10 @@ public class UploadMonitorImpl extends ManagerBase implements UploadMonitor { ResourceManager _resourceMgr; @Inject SecondaryStorageVmManager _ssvmMgr; + @Inject + EndPointSelector _epSelector; + @Inject + DataStoreManager storeMgr; private String _name; private Boolean _sslCopy = new Boolean(false); @@ -115,137 +120,134 @@ public class UploadMonitorImpl extends ManagerBase implements UploadMonitor { final Map _listenerMap = new ConcurrentHashMap(); - + @Override public void cancelAllUploads(Long templateId) { // TODO - } - + } + @Override public boolean isTypeUploadInProgress(Long typeId, Type type) { List uploadsInProgress = _uploadDao.listByTypeUploadStatus(typeId, type, UploadVO.Status.UPLOAD_IN_PROGRESS); - + if(uploadsInProgress.size() > 0) { return true; } else if (type == Type.VOLUME && _uploadDao.listByTypeUploadStatus(typeId, type, UploadVO.Status.COPY_IN_PROGRESS).size() > 0){ return true; } return false; - + } - + @Override public UploadVO createNewUploadEntry(Long hostId, Long typeId, UploadVO.Status uploadState, Type type, String uploadUrl, Upload.Mode mode){ - - UploadVO uploadObj = new UploadVO(hostId, typeId, new Date(), + + UploadVO uploadObj = new UploadVO(hostId, typeId, new Date(), uploadState, type, uploadUrl, mode); _uploadDao.persist(uploadObj); - + return uploadObj; - + } - + @Override - public void extractVolume(UploadVO uploadVolumeObj, HostVO sserver, VolumeVO volume, String url, Long dataCenterId, String installPath, long eventId, long asyncJobId, AsyncJobManager asyncMgr){ - + public void extractVolume(UploadVO uploadVolumeObj, DataStore secStore, VolumeVO volume, String url, Long dataCenterId, String installPath, long eventId, long asyncJobId, AsyncJobManager asyncMgr){ + uploadVolumeObj.setUploadState(Upload.Status.NOT_UPLOADED); _uploadDao.update(uploadVolumeObj.getId(), uploadVolumeObj); - - start(); + + start(); UploadCommand ucmd = new UploadCommand(url, volume.getId(), volume.getSize(), installPath, Type.VOLUME); - UploadListener ul = new UploadListener(sserver, _timer, _uploadDao, uploadVolumeObj, this, ucmd, volume.getAccountId(), volume.getName(), Type.VOLUME, eventId, asyncJobId, asyncMgr); + UploadListener ul = new UploadListener(secStore, _timer, _uploadDao, uploadVolumeObj, this, ucmd, volume.getAccountId(), volume.getName(), Type.VOLUME, eventId, asyncJobId, asyncMgr); _listenerMap.put(uploadVolumeObj, ul); try { - send(sserver.getId(), ucmd, ul); - } catch (AgentUnavailableException e) { - s_logger.warn("Unable to start upload of volume " + volume.getName() + " from " + sserver.getName() + " to " +url, e); + EndPoint ep = _epSelector.select(secStore); + ep.sendMessageAsync(ucmd, new UploadListener.Callback(ep.getId(), ul)); + } catch (Exception e) { + s_logger.warn("Unable to start upload of volume " + volume.getName() + " from " + secStore.getName() + " to " +url, e); ul.setDisconnected(); ul.scheduleStatusCheck(RequestType.GET_OR_RESTART); - } + } } @Override public Long extractTemplate( VMTemplateVO template, String url, - VMTemplateHostVO vmTemplateHost,Long dataCenterId, long eventId, long asyncJobId, AsyncJobManager asyncMgr){ + TemplateDataStoreVO vmTemplateHost,Long dataCenterId, long eventId, long asyncJobId, AsyncJobManager asyncMgr){ Type type = (template.getFormat() == ImageFormat.ISO) ? Type.ISO : Type.TEMPLATE ; - - List storageServers = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.SecondaryStorage, dataCenterId); - HostVO sserver = storageServers.get(0); - - UploadVO uploadTemplateObj = new UploadVO(sserver.getId(), template.getId(), new Date(), + + DataStore secStore = this.storeMgr.getImageStore(dataCenterId); + + UploadVO uploadTemplateObj = new UploadVO(secStore.getId(), template.getId(), new Date(), Upload.Status.NOT_UPLOADED, type, url, Mode.FTP_UPLOAD); - _uploadDao.persist(uploadTemplateObj); - + _uploadDao.persist(uploadTemplateObj); + if(vmTemplateHost != null) { start(); - UploadCommand ucmd = new UploadCommand(template, url, vmTemplateHost.getInstallPath(), vmTemplateHost.getSize()); - UploadListener ul = new UploadListener(sserver, _timer, _uploadDao, uploadTemplateObj, this, ucmd, template.getAccountId(), template.getName(), type, eventId, asyncJobId, asyncMgr); + UploadCommand ucmd = new UploadCommand(template, url, vmTemplateHost.getInstallPath(), vmTemplateHost.getSize()); + UploadListener ul = new UploadListener(secStore, _timer, _uploadDao, uploadTemplateObj, this, ucmd, template.getAccountId(), template.getName(), type, eventId, asyncJobId, asyncMgr); _listenerMap.put(uploadTemplateObj, ul); - - try { - send(sserver.getId(), ucmd, ul); - } catch (AgentUnavailableException e) { - s_logger.warn("Unable to start upload of " + template.getUniqueName() + " from " + sserver.getName() + " to " +url, e); + try{ + EndPoint ep = _epSelector.select(secStore); + ep.sendMessageAsync(ucmd, new UploadListener.Callback(ep.getId(), ul)); + } catch (Exception e) { + s_logger.warn("Unable to start upload of " + template.getUniqueName() + " from " + secStore.getName() + " to " +url, e); ul.setDisconnected(); ul.scheduleStatusCheck(RequestType.GET_OR_RESTART); } return uploadTemplateObj.getId(); - } - return null; - } - + } + return null; + } + @Override - public UploadVO createEntityDownloadURL(VMTemplateVO template, VMTemplateHostVO vmTemplateHost, Long dataCenterId, long eventId) { - + public UploadVO createEntityDownloadURL(VMTemplateVO template, TemplateDataStoreVO vmTemplateHost, Long dataCenterId, long eventId) { + String errorString = ""; boolean success = false; - Host secStorage = ApiDBUtils.findHostById(vmTemplateHost.getHostId()); Type type = (template.getFormat() == ImageFormat.ISO) ? Type.ISO : Type.TEMPLATE ; - - //Check if ssvm is up - HostVO ssvm = _ssvmMgr.pickSsvmHost(ApiDBUtils.findHostById(vmTemplateHost.getHostId())); - if( ssvm == null ) { - throw new CloudRuntimeException("There is no secondary storage VM for secondary storage host " + secStorage.getId()); - } - + + //Check if it already exists. - List extractURLList = _uploadDao.listByTypeUploadStatus(template.getId(), type, UploadVO.Status.DOWNLOAD_URL_CREATED); + List extractURLList = _uploadDao.listByTypeUploadStatus(template.getId(), type, UploadVO.Status.DOWNLOAD_URL_CREATED); if (extractURLList.size() > 0) { return extractURLList.get(0); } - - // It doesn't exist so create a DB entry. - UploadVO uploadTemplateObj = new UploadVO(vmTemplateHost.getHostId(), template.getId(), new Date(), - Status.DOWNLOAD_URL_NOT_CREATED, 0, type, Mode.HTTP_DOWNLOAD); - uploadTemplateObj.setInstallPath(vmTemplateHost.getInstallPath()); + + // It doesn't exist so create a DB entry. + UploadVO uploadTemplateObj = new UploadVO(vmTemplateHost.getDataStoreId(), template.getId(), new Date(), + Status.DOWNLOAD_URL_NOT_CREATED, 0, type, Mode.HTTP_DOWNLOAD); + uploadTemplateObj.setInstallPath(vmTemplateHost.getInstallPath()); _uploadDao.persist(uploadTemplateObj); + + // find an endpoint to send command + DataStore store = this.storeMgr.getDataStore(vmTemplateHost.getDataStoreId(), DataStoreRole.Image); + EndPoint ep = _epSelector.select(store); try{ // Create Symlink at ssvm String path = vmTemplateHost.getInstallPath(); String uuid = UUID.randomUUID().toString() + "." + template.getFormat().getFileExtension(); // adding "." + vhd/ova... etc. - CreateEntityDownloadURLCommand cmd = new CreateEntityDownloadURLCommand(secStorage.getParent(), path, uuid); - try { - send(ssvm.getId(), cmd, null); - } catch (AgentUnavailableException e) { - errorString = "Unable to create a link for " +type+ " id:"+template.getId() + "," + e.getMessage(); - s_logger.error(errorString, e); + CreateEntityDownloadURLCommand cmd = new CreateEntityDownloadURLCommand(((ImageStoreEntity)store).getMountPoint(), path, uuid); + Answer ans = ep.sendMessage(cmd); + if (ans == null || !ans.getResult()) { + errorString = "Unable to create a link for " +type+ " id:"+template.getId() + "," + ans.getDetails(); + s_logger.error(errorString); throw new CloudRuntimeException(errorString); } //Construct actual URL locally now that the symlink exists at SSVM - String extractURL = generateCopyUrl(ssvm.getPublicIpAddress(), uuid); + String extractURL = generateCopyUrl(ep.getPublicAddr(), uuid); UploadVO vo = _uploadDao.createForUpdate(); vo.setLastUpdated(new Date()); vo.setUploadUrl(extractURL); vo.setUploadState(Status.DOWNLOAD_URL_CREATED); _uploadDao.update(uploadTemplateObj.getId(), vo); success = true; - return _uploadDao.findById(uploadTemplateObj.getId(), true); + return _uploadDao.findById(uploadTemplateObj.getId(), true); }finally{ if(!success){ UploadVO uploadJob = _uploadDao.createForUpdate(uploadTemplateObj.getId()); @@ -255,42 +257,41 @@ public class UploadMonitorImpl extends ManagerBase implements UploadMonitor { _uploadDao.update(uploadTemplateObj.getId(), uploadJob); } } - + } - + @Override - public void createVolumeDownloadURL(Long entityId, String path, Type type, Long dataCenterId, Long uploadId) { - + public void createVolumeDownloadURL(Long entityId, String path, Type type, Long dataCenterId, Long uploadId, ImageFormat format) { + String errorString = ""; boolean success = false; try{ List storageServers = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.SecondaryStorage, dataCenterId); if(storageServers == null ){ errorString = "No Storage Server found at the datacenter - " +dataCenterId; - throw new CloudRuntimeException(errorString); - } - - // Update DB for state = DOWNLOAD_URL_NOT_CREATED. + throw new CloudRuntimeException(errorString); + } + + // Update DB for state = DOWNLOAD_URL_NOT_CREATED. UploadVO uploadJob = _uploadDao.createForUpdate(uploadId); uploadJob.setUploadState(Status.DOWNLOAD_URL_NOT_CREATED); uploadJob.setLastUpdated(new Date()); _uploadDao.update(uploadJob.getId(), uploadJob); // Create Symlink at ssvm - String uuid = UUID.randomUUID().toString() + path.substring(path.length() - 4) ; // last 4 characters of the path specify the format like .vhd - HostVO secStorage = ApiDBUtils.findHostById(ApiDBUtils.findUploadById(uploadId).getHostId()); - HostVO ssvm = _ssvmMgr.pickSsvmHost(secStorage); - if( ssvm == null ) { - errorString = "There is no secondary storage VM for secondary storage host " + secStorage.getName(); + String uuid = UUID.randomUUID().toString() + "." + format.toString().toLowerCase() ; + DataStore secStore = this.storeMgr.getDataStore(ApiDBUtils.findUploadById(uploadId).getDataStoreId(), DataStoreRole.Image); + EndPoint ep = _epSelector.select(secStore); + if( ep == null ) { + errorString = "There is no secondary storage VM for secondary storage host " + secStore.getName(); throw new CloudRuntimeException(errorString); } - - CreateEntityDownloadURLCommand cmd = new CreateEntityDownloadURLCommand(secStorage.getParent(), path, uuid); - try { - send(ssvm.getId(), cmd, null); - } catch (AgentUnavailableException e) { - errorString = "Unable to create a link for " +type+ " id:"+entityId + "," + e.getMessage(); - s_logger.warn(errorString, e); + + CreateEntityDownloadURLCommand cmd = new CreateEntityDownloadURLCommand(((ImageStoreEntity)secStore).getMountPoint(), path, uuid); + Answer ans = ep.sendMessage(cmd); + if (ans == null || !ans.getResult()) { + errorString = "Unable to create a link for " +type+ " id:"+entityId + "," + ans.getDetails(); + s_logger.warn(errorString); throw new CloudRuntimeException(errorString); } @@ -324,7 +325,7 @@ public class UploadMonitorImpl extends ManagerBase implements UploadMonitor { } } } - + private String generateCopyUrl(String ipAddress, String uuid){ String hostname = ipAddress; String scheme = "http"; @@ -339,30 +340,32 @@ public class UploadMonitorImpl extends ManagerBase implements UploadMonitor { hostname = hostname + ".realhostip.com"; } } - return scheme + "://" + hostname + "/userdata/" + uuid; + return scheme + "://" + hostname + "/userdata/" + uuid; } - - public void send(Long hostId, Command cmd, Listener listener) throws AgentUnavailableException { - _agentMgr.send(hostId, new Commands(cmd), listener); - } + @Override public boolean configure(String name, Map params) throws ConfigurationException { final Map configs = _configDao.getConfiguration("ManagementServer", params); _sslCopy = Boolean.parseBoolean(configs.get("secstorage.encrypt.copy")); - + + String cert = configs.get("secstorage.secure.copy.cert"); + if ("realhostip.com".equalsIgnoreCase(cert)) { + s_logger.warn("Only realhostip.com ssl cert is supported, ignoring self-signed and other certs"); + } + _ssvmUrlDomain = configs.get("secstorage.ssl.cert.domain"); _agentMgr.registerForHostEvents(new UploadListener(this), true, false, false); String cleanupInterval = configs.get("extract.url.cleanup.interval"); _cleanupInterval = NumbersUtil.parseInt(cleanupInterval, 7200); - + String urlExpirationInterval = configs.get("extract.url.expiration.interval"); _urlExpirationInterval = NumbersUtil.parseInt(urlExpirationInterval, 14400); - + String workers = (String)params.get("expunge.workers"); int wrks = NumbersUtil.parseInt(workers, 1); _executor = Executors.newScheduledThreadPool(wrks, new NamedThreadFactory("UploadMonitor-Scavenger")); @@ -370,19 +373,19 @@ public class UploadMonitorImpl extends ManagerBase implements UploadMonitor { } @Override - public boolean start() { + public boolean start() { _executor.scheduleWithFixedDelay(new StorageGarbageCollector(), _cleanupInterval, _cleanupInterval, TimeUnit.SECONDS); _timer = new Timer(); return true; } @Override - public boolean stop() { + public boolean stop() { return true; } - - public void handleUploadEvent(HostVO host, Long accountId, String typeName, Type type, Long uploadId, com.cloud.storage.Upload.Status reason, long eventId) { - + + public void handleUploadEvent(Long accountId, String typeName, Type type, Long uploadId, com.cloud.storage.Upload.Status reason, long eventId) { + if ((reason == Upload.Status.UPLOADED) || (reason==Upload.Status.ABANDONED)){ UploadVO uploadObj = new UploadVO(uploadId); UploadListener oldListener = _listenerMap.get(uploadObj); @@ -392,10 +395,10 @@ public class UploadMonitorImpl extends ManagerBase implements UploadMonitor { } } - + @Override public void handleUploadSync(long sserverId) { - + HostVO storageHost = _serverDao.findById(sserverId); if (storageHost == null) { s_logger.warn("Huh? Agent id " + sserverId + " does not correspond to a row in hosts table?"); @@ -412,11 +415,11 @@ public class UploadMonitorImpl extends ManagerBase implements UploadMonitor { uploadJob.setLastUpdated(new Date()); _uploadDao.update(uploadJob.getId(), uploadJob); } - - } - - } + } + + + } protected class StorageGarbageCollector implements Runnable { @@ -444,45 +447,47 @@ public class UploadMonitorImpl extends ManagerBase implements UploadMonitor { } } } - - + + private long getTimeDiff(Date date){ Calendar currentDateCalendar = Calendar.getInstance(); Calendar givenDateCalendar = Calendar.getInstance(); givenDateCalendar.setTime(date); - - return (currentDateCalendar.getTimeInMillis() - givenDateCalendar.getTimeInMillis() )/1000; + + return (currentDateCalendar.getTimeInMillis() - givenDateCalendar.getTimeInMillis() )/1000; } - + public void cleanupStorage() { final int EXTRACT_URL_LIFE_LIMIT_IN_SECONDS = _urlExpirationInterval; List extractJobs= _uploadDao.listByModeAndStatus(Mode.HTTP_DOWNLOAD, Status.DOWNLOAD_URL_CREATED); - + for (UploadVO extractJob : extractJobs){ - if( getTimeDiff(extractJob.getLastUpdated()) > EXTRACT_URL_LIFE_LIMIT_IN_SECONDS ){ + if( getTimeDiff(extractJob.getLastUpdated()) > EXTRACT_URL_LIFE_LIMIT_IN_SECONDS ){ String path = extractJob.getInstallPath(); - HostVO secStorage = ApiDBUtils.findHostById(extractJob.getHostId()); - + DataStore secStore = this.storeMgr.getDataStore(extractJob.getDataStoreId(), DataStoreRole.Image); + + // Would delete the symlink for the Type and if Type == VOLUME then also the volume - DeleteEntityDownloadURLCommand cmd = new DeleteEntityDownloadURLCommand(path, extractJob.getType(),extractJob.getUploadUrl(), secStorage.getParent()); - HostVO ssvm = _ssvmMgr.pickSsvmHost(secStorage); - if( ssvm == null ) { - s_logger.warn("UploadMonitor cleanup: There is no secondary storage VM for secondary storage host " + extractJob.getHostId()); + DeleteEntityDownloadURLCommand cmd = new DeleteEntityDownloadURLCommand(path, extractJob.getType(),extractJob.getUploadUrl(), ((ImageStoreVO)secStore).getParent()); + EndPoint ep = _epSelector.select(secStore); + if( ep == null ) { + s_logger.warn("UploadMonitor cleanup: There is no secondary storage VM for secondary storage host " + extractJob.getDataStoreId()); continue; //TODO: why continue? why not break? } if (s_logger.isDebugEnabled()) { - s_logger.debug("UploadMonitor cleanup: Sending deletion of extract URL "+ extractJob.getUploadUrl() + " to ssvm " + ssvm.getId()); + s_logger.debug("UploadMonitor cleanup: Sending deletion of extract URL "+ extractJob.getUploadUrl() + " to ssvm " + ep.getHostAddr()); } - try { - send(ssvm.getId(), cmd, null); //TODO: how do you know if it was successful? + Answer ans = ep.sendMessage(cmd); + if ( ans != null && ans.getResult()){ _uploadDao.remove(extractJob.getId()); - } catch (AgentUnavailableException e) { - s_logger.warn("UploadMonitor cleanup: Unable to delete the link for " + extractJob.getType()+ " id=" + extractJob.getTypeId()+ " url="+ extractJob.getUploadUrl() + " on ssvm " + ssvm.getId(), e); + } + else{ + s_logger.warn("UploadMonitor cleanup: Unable to delete the link for " + extractJob.getType()+ " id=" + extractJob.getTypeId()+ " url="+ extractJob.getUploadUrl() + " on ssvm " + ep.getHostAddr()); } } } - + } } diff --git a/server/src/com/cloud/template/HypervisorTemplateAdapter.java b/server/src/com/cloud/template/HypervisorTemplateAdapter.java index 322f32eacdf..92148c3f83c 100755 --- a/server/src/com/cloud/template/HypervisorTemplateAdapter.java +++ b/server/src/com/cloud/template/HypervisorTemplateAdapter.java @@ -16,11 +16,6 @@ // under the License. package com.cloud.template; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.UnknownHostException; import java.util.List; import java.util.concurrent.ExecutionException; @@ -31,21 +26,28 @@ import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd; import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd; import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd; import org.apache.cloudstack.api.command.user.template.ExtractTemplateCmd; -import com.cloud.agent.api.storage.PrepareOVAPackingCommand; -import com.cloud.agent.api.storage.PrepareOVAPackingAnswer; import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd; -import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; 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.ImageDataFactory; -import org.apache.cloudstack.engine.subsystem.api.storage.ImageService; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService.TemplateApiResult; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.framework.async.AsyncRpcConext; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import org.apache.log4j.Logger; +import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; -import com.cloud.agent.api.storage.DeleteTemplateCommand; +import com.cloud.agent.api.storage.PrepareOVAPackingCommand; +import com.cloud.alert.AlertManager; import com.cloud.configuration.Resource.ResourceType; import com.cloud.dc.DataCenterVO; import com.cloud.event.EventTypes; @@ -53,72 +55,40 @@ import com.cloud.event.UsageEventUtils; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.ResourceAllocationException; import com.cloud.host.HostVO; +import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.TemplateProfile; -import com.cloud.storage.VMTemplateHostVO; +import com.cloud.storage.VMTemplateZoneVO; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.VMTemplateVO; -import com.cloud.storage.VMTemplateZoneVO; +import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.storage.download.DownloadMonitor; -import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.user.Account; import com.cloud.utils.UriUtils; import com.cloud.utils.db.DB; import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.vm.UserVmVO; -import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.exception.AgentUnavailableException; -import com.cloud.exception.OperationTimedoutException; - @Local(value=TemplateAdapter.class) -public class HypervisorTemplateAdapter extends TemplateAdapterBase implements TemplateAdapter { +public class HypervisorTemplateAdapter extends TemplateAdapterBase { private final static Logger s_logger = Logger.getLogger(HypervisorTemplateAdapter.class); @Inject DownloadMonitor _downloadMonitor; - @Inject SecondaryStorageVmManager _ssvmMgr; @Inject AgentManager _agentMgr; @Inject DataStoreManager storeMgr; - @Inject ImageService imageService; - @Inject ImageDataFactory imageFactory; + @Inject TemplateService imageService; + @Inject TemplateDataFactory imageFactory; @Inject TemplateManager templateMgr; + @Inject AlertManager alertMgr; + @Inject VMTemplateZoneDao templateZoneDao; + @Inject + EndPointSelector _epSelector; @Override public String getName() { return TemplateAdapterType.Hypervisor.getName(); } - - private String validateUrl(String url) { - try { - URI uri = new URI(url); - if ((uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("http") - && !uri.getScheme().equalsIgnoreCase("https") && !uri.getScheme().equalsIgnoreCase("file"))) { - throw new IllegalArgumentException("Unsupported scheme for url: " + url); - } - int port = uri.getPort(); - if (!(port == 80 || port == 443 || port == -1)) { - throw new IllegalArgumentException("Only ports 80 and 443 are allowed"); - } - String host = uri.getHost(); - try { - InetAddress hostAddr = InetAddress.getByName(host); - if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress()) { - throw new IllegalArgumentException("Illegal host specified in url"); - } - if (hostAddr instanceof Inet6Address) { - throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")"); - } - } catch (UnknownHostException uhe) { - throw new IllegalArgumentException("Unable to resolve " + host); - } - - return uri.toString(); - } catch (URISyntaxException e) { - throw new IllegalArgumentException("Invalid URL " + url); - } - } @Override public TemplateProfile prepare(RegisterIsoCmd cmd) throws ResourceAllocationException { @@ -130,7 +100,8 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase implements Te throw new InvalidParameterValueException("Please specify a valid iso"); } - profile.setUrl(validateUrl(url)); + UriUtils.validateUrl(url); + profile.setUrl(url); // Check that the resource limit for secondary storage won't be exceeded _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(cmd.getEntityOwnerId()), ResourceType.secondary_storage, UriUtils.getRemoteSize(url)); @@ -162,7 +133,8 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase implements Te throw new InvalidParameterValueException("Please specify a valid URL. URL:" + url + " is an invalid for the format " + cmd.getFormat().toLowerCase()); } - profile.setUrl(validateUrl(url)); + UriUtils.validateUrl(url); + profile.setUrl(url); // Check that the resource limit for secondary storage won't be exceeded _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(cmd.getEntityOwnerId()), ResourceType.secondary_storage, UriUtils.getRemoteSize(url)); @@ -171,34 +143,173 @@ 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, not that entry at template_store_ref is not created here, and created in createTemplateAsync. 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) { + TemplateInfo tmpl = this.imageFactory.getTemplate(template.getId(), imageStore); + CreateTemplateContext context = new CreateTemplateContext(null, tmpl); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().createTemplateAsyncCallBack(null, null)); + caller.setContext(context); + this.imageService + .createTemplateAsync(tmpl, imageStore, caller); } _resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template); - _resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.secondary_storage, - UriUtils.getRemoteSize(profile.getUrl())); + return template; } + private class CreateTemplateContext extends AsyncRpcConext { + final TemplateInfo template; + public CreateTemplateContext(AsyncCompletionCallback callback, TemplateInfo template) { + super(callback); + this.template = template; + } + } + + protected Void createTemplateAsyncCallBack(AsyncCallbackDispatcher callback, + CreateTemplateContext context) { + TemplateApiResult result = callback.getResult(); + TemplateInfo template = context.template; + if (result.isFailed()) { + // failed in creating template, we need to remove those already + // populated template entry + _tmpltDao.remove(template.getId()); + } else { + VMTemplateVO tmplt = this._tmpltDao.findById(template.getId()); + long accountId = tmplt.getAccountId(); + if (template.getSize() != null) { + _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.secondary_storage, template.getSize()); + } + } + + return null; + } + + @Override @DB + public boolean delete(TemplateProfile profile) { + boolean success = true; + + VMTemplateVO template = profile.getTemplate(); + + // find all eligible image stores for this template + List imageStores = this.templateMgr.getImageStoreByTemplate(template.getId(), profile.getZoneId()); + if ( imageStores == null || imageStores.size() == 0 ){ + throw new CloudRuntimeException("Unable to find image store to delete template "+ profile.getTemplate()); + } + + // Make sure the template is downloaded to all found image stores + for (DataStore store : imageStores) { + long storeId = store.getId(); + List templateStores = _tmpltStoreDao.listByTemplateStore(template.getId(), storeId); + for (TemplateDataStoreVO templateStore : templateStores) { + if (templateStore.getDownloadState() == Status.DOWNLOAD_IN_PROGRESS) { + String errorMsg = "Please specify a template that is not currently being downloaded."; + s_logger.debug("Template: " + template.getName() + " is currently being downloaded to secondary storage host: " + store.getName() + "; cant' delete it."); + throw new CloudRuntimeException(errorMsg); + } + } + } + + String eventType = ""; + if (template.getFormat().equals(ImageFormat.ISO)) { + eventType = EventTypes.EVENT_ISO_DELETE; + } else { + eventType = EventTypes.EVENT_TEMPLATE_DELETE; + } + + for (DataStore imageStore : imageStores) { + // publish zone-wide usage event + Long sZoneId = ((ImageStoreEntity)imageStore).getDataCenterId(); + if (sZoneId != null) { + UsageEventUtils.publishUsageEvent(eventType, template.getAccountId(), sZoneId, template.getId(), null, null, null); + } + + s_logger.info("Delete template from image store: " + imageStore.getName()); + AsyncCallFuture future = this.imageService + .deleteTemplateAsync(this.imageFactory.getTemplate(template.getId(), imageStore)); + try { + TemplateApiResult result = future.get(); + success = result.isSuccess(); + if ( !success ) + break; + + // remove from template_zone_ref + List templateZones = templateZoneDao.listByZoneTemplate(sZoneId, template.getId()); + if (templateZones != null) { + for (VMTemplateZoneVO templateZone : templateZones) { + templateZoneDao.remove(templateZone.getId()); + } + } + } catch (InterruptedException e) { + s_logger.debug("delete template Failed", e); + throw new CloudRuntimeException("delete template Failed", e); + } catch (ExecutionException e) { + s_logger.debug("delete template Failed", e); + throw new CloudRuntimeException("delete template Failed", e); + } + } + + if (success) { + s_logger.info("Delete template from template table"); + // remove template from vm_templates table + if (_tmpltDao.remove(template.getId())) { + // Decrement the number of templates and total secondary storage + // space used by the account + Account account = _accountDao.findByIdIncludingRemoved(template.getAccountId()); + _resourceLimitMgr.decrementResourceCount(template.getAccountId(), ResourceType.template); + _resourceLimitMgr.recalculateResourceCount(template.getAccountId(), account.getDomainId(), + ResourceType.secondary_storage.getOrdinal()); + } + } + return success; + + + } + @Override - public TemplateProfile prepareExtractTemplate(ExtractTemplateCmd extractcmd) { + public TemplateProfile prepareDelete(DeleteTemplateCmd cmd) { + TemplateProfile profile = super.prepareDelete(cmd); + VMTemplateVO template = profile.getTemplate(); + Long zoneId = profile.getZoneId(); + + if (template.getTemplateType() == TemplateType.SYSTEM) { + throw new InvalidParameterValueException("The DomR template cannot be deleted."); + } + + if (zoneId != null && (this.storeMgr.getImageStore(zoneId) == null)) { + throw new InvalidParameterValueException("Failed to find a secondary storage in the specified zone."); + } + + return profile; + } + + @Override + public TemplateProfile prepareDelete(DeleteIsoCmd cmd) { + TemplateProfile profile = super.prepareDelete(cmd); + Long zoneId = profile.getZoneId(); + + if (zoneId != null && (this.storeMgr.getImageStore(zoneId) == null)) { + throw new InvalidParameterValueException("Failed to find a secondary storage in the specified zone."); + } + + return profile; + } + + @Override + public TemplateProfile prepareExtractTemplate(ExtractTemplateCmd extractcmd) { TemplateProfile profile = super.prepareExtractTemplate(extractcmd); - VMTemplateVO template = (VMTemplateVO)profile.getTemplate(); + VMTemplateVO template = profile.getTemplate(); Long zoneId = profile.getZoneId(); Long templateId = template.getId(); @@ -209,211 +320,48 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase implements Te if (!template.isCrossZones() && zoneId != null) { DataCenterVO zone = _dcDao.findById(zoneId); zoneName = zone.getName(); - secondaryStorageHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(zoneId); + 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()); + } s_logger.debug("Attempting to mark template host refs for template: " + template.getName() + " as destroyed in zone: " + zoneName); // Make sure the template is downloaded to all the necessary secondary storage hosts - for (HostVO secondaryStorageHost : secondaryStorageHosts) { - long hostId = secondaryStorageHost.getId(); - List templateHostVOs = _tmpltHostDao.listByHostTemplate(hostId, templateId); - for (VMTemplateHostVO templateHostVO : templateHostVOs) { - if (templateHostVO.getDownloadState() == Status.DOWNLOAD_IN_PROGRESS) { + for (DataStore store : imageStores) { + long storeId = store.getId(); + List templateStoreVOs = _tmpltStoreDao.listByTemplateStore(templateId, storeId); + for (TemplateDataStoreVO templateStoreVO : templateStoreVOs) { + if (templateStoreVO.getDownloadState() == Status.DOWNLOAD_IN_PROGRESS) { String errorMsg = "Please specify a template that is not currently being downloaded."; - s_logger.debug("Template: " + template.getName() + " is currently being downloaded to secondary storage host: " + secondaryStorageHost.getName() + "."); + s_logger.debug("Template: " + template.getName() + " is currently being downloaded to secondary storage host: " + store.getName() + "."); throw new CloudRuntimeException(errorMsg); } - String installPath = templateHostVO.getInstallPath(); + String installPath = templateStoreVO.getInstallPath(); if (installPath != null) { - HostVO ssvmhost = _ssvmMgr.pickSsvmHost(secondaryStorageHost); - if( ssvmhost == null ) { - s_logger.warn("prepareOVAPacking (hyervisorTemplateAdapter): There is no secondary storage VM for secondary storage host " + secondaryStorageHost.getName()); + EndPoint ep = _epSelector.select(store); + if (ep == null) { + s_logger.warn("prepareOVAPacking (hyervisorTemplateAdapter): There is no secondary storage VM for secondary storage host " + store.getName()); throw new CloudRuntimeException("PrepareExtractTemplate: can't locate ssvm for SecStorage Host."); } //Answer answer = _agentMgr.sendToSecStorage(secondaryStorageHost, new PrepareOVAPackingCommand(secondaryStorageHost.getStorageUrl(), installPath)); - cmd = new PrepareOVAPackingCommand(secondaryStorageHost.getStorageUrl(), installPath); - - if (cmd == null) { - s_logger.debug("Fang: PrepareOVAPacking cmd can't created. cmd is null ."); - throw new CloudRuntimeException("PrepareExtractTemplate: can't create a new cmd to packing ova."); - } else { - cmd.setContextParam("hypervisor", HypervisorType.VMware.toString()); - } - Answer answer = null; - s_logger.debug("Fang: PrepareOVAPAcking cmd, before send out. cmd: " + cmd.toString()); - try { - answer = _agentMgr.send(ssvmhost.getId(), cmd); - } catch (AgentUnavailableException e) { - s_logger.warn("Unable to packOVA for template: id: " + templateId + ", name " + ssvmhost.getName(), e); - } catch (OperationTimedoutException e) { - s_logger.warn("Unable to packOVA for template timeout. template id: " + templateId); - e.printStackTrace(); - } + cmd = new PrepareOVAPackingCommand(store.getUri(), installPath); + cmd.setContextParam("hypervisor", HypervisorType.VMware.toString()); + Answer answer = ep.sendMessage(cmd); if (answer == null || !answer.getResult()) { - s_logger.debug("Failed to create OVA for template " + templateHostVO + " due to " + ((answer == null) ? "answer is null" : answer.getDetails())); + s_logger.debug("Failed to create OVA for template " + templateStoreVO + " due to " + ((answer == null) ? "answer is null" : answer.getDetails())); throw new CloudRuntimeException("PrepareExtractTemplate: Failed to create OVA for template extraction. "); } } } } } else { - s_logger.debug("Failed to create OVA for template " + template + " due to zone non-existing."); + s_logger.debug("Failed to create OVA for template " + template + " due to zone non-existing."); throw new CloudRuntimeException("PrepareExtractTemplate: Failed to create OVA for template extraction. "); - } - } - return profile; } - - @Override @DB - public boolean delete(TemplateProfile profile) { - boolean success = true; - - VMTemplateVO template = (VMTemplateVO)profile.getTemplate(); - Long zoneId = profile.getZoneId(); - Long templateId = template.getId(); - - String zoneName; - List secondaryStorageHosts; - if (!template.isCrossZones() && zoneId != null) { - DataCenterVO zone = _dcDao.findById(zoneId); - zoneName = zone.getName(); - secondaryStorageHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(zoneId); - } else { - zoneName = "(all zones)"; - secondaryStorageHosts = _ssvmMgr.listSecondaryStorageHostsInAllZones(); - } - - s_logger.debug("Attempting to mark template host refs for template: " + template.getName() + " as destroyed in zone: " + zoneName); - - // Make sure the template is downloaded to all the necessary secondary storage hosts - for (HostVO secondaryStorageHost : secondaryStorageHosts) { - long hostId = secondaryStorageHost.getId(); - List templateHostVOs = _tmpltHostDao.listByHostTemplate(hostId, templateId); - for (VMTemplateHostVO templateHostVO : templateHostVOs) { - if (templateHostVO.getDownloadState() == Status.DOWNLOAD_IN_PROGRESS) { - String errorMsg = "Please specify a template that is not currently being downloaded."; - s_logger.debug("Template: " + template.getName() + " is currently being downloaded to secondary storage host: " + secondaryStorageHost.getName() + "; cant' delete it."); - throw new CloudRuntimeException(errorMsg); - } - } - } - - Account account = _accountDao.findByIdIncludingRemoved(template.getAccountId()); - String eventType = ""; - - if (template.getFormat().equals(ImageFormat.ISO)){ - eventType = EventTypes.EVENT_ISO_DELETE; - } else { - eventType = EventTypes.EVENT_TEMPLATE_DELETE; - } - - // Iterate through all necessary secondary storage hosts and mark the template on each host as destroyed - for (HostVO secondaryStorageHost : secondaryStorageHosts) { - long hostId = secondaryStorageHost.getId(); - long sZoneId = secondaryStorageHost.getDataCenterId(); - List templateHostVOs = _tmpltHostDao.listByHostTemplate(hostId, templateId); - for (VMTemplateHostVO templateHostVO : templateHostVOs) { - VMTemplateHostVO lock = _tmpltHostDao.acquireInLockTable(templateHostVO.getId()); - try { - if (lock == null) { - s_logger.debug("Failed to acquire lock when deleting templateHostVO with ID: " + templateHostVO.getId()); - success = false; - break; - } - UsageEventUtils.publishUsageEvent(eventType, account.getId(), sZoneId, templateId, null, null, null); - templateHostVO.setDestroyed(true); - _tmpltHostDao.update(templateHostVO.getId(), templateHostVO); - String installPath = templateHostVO.getInstallPath(); - List userVmUsingIso = _userVmDao.listByIsoId(templateId); - //check if there is any VM using this ISO. - if (userVmUsingIso == null || userVmUsingIso.isEmpty()) { - if (installPath != null) { - Answer answer = _agentMgr.sendToSecStorage(secondaryStorageHost, new DeleteTemplateCommand(secondaryStorageHost.getStorageUrl(), installPath)); - - if (answer == null || !answer.getResult()) { - s_logger.debug("Failed to delete " + templateHostVO + " due to " + ((answer == null) ? "answer is null" : answer.getDetails())); - } else { - _tmpltHostDao.remove(templateHostVO.getId()); - s_logger.debug("Deleted template at: " + installPath); - } - } else { - _tmpltHostDao.remove(templateHostVO.getId()); - } - } - VMTemplateZoneVO templateZone = _tmpltZoneDao.findByZoneTemplate(sZoneId, templateId); - - if (templateZone != null) { - _tmpltZoneDao.remove(templateZone.getId()); - } - } finally { - if (lock != null) { - _tmpltHostDao.releaseFromLockTable(lock.getId()); - } - } - } - - if (!success) { - break; - } - } - - s_logger.debug("Successfully marked template host refs for template: " + template.getName() + " as destroyed in zone: " + zoneName); - - // If there are no more non-destroyed template host entries for this template, delete it - if (success && (_tmpltHostDao.listByTemplateId(templateId).size() == 0)) { - long accountId = template.getAccountId(); - - VMTemplateVO lock = _tmpltDao.acquireInLockTable(templateId); - - try { - if (lock == null) { - s_logger.debug("Failed to acquire lock when deleting template with ID: " + templateId); - success = false; - } else if (_tmpltDao.remove(templateId)) { - // Decrement the number of templates and total secondary storage space used by the account - _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.template); - _resourceLimitMgr.recalculateResourceCount(accountId, account.getDomainId(), - ResourceType.secondary_storage.getOrdinal()); - } - - } finally { - if (lock != null) { - _tmpltDao.releaseFromLockTable(lock.getId()); - } - } - - s_logger.debug("Removed template: " + template.getName() + " because all of its template host refs were marked as destroyed."); - } - - return success; - } - - public TemplateProfile prepareDelete(DeleteTemplateCmd cmd) { - TemplateProfile profile = super.prepareDelete(cmd); - VMTemplateVO template = (VMTemplateVO)profile.getTemplate(); - Long zoneId = profile.getZoneId(); - - if (template.getTemplateType() == TemplateType.SYSTEM) { - throw new InvalidParameterValueException("The DomR template cannot be deleted."); - } - - if (zoneId != null && (_ssvmMgr.findSecondaryStorageHost(zoneId) == null)) { - throw new InvalidParameterValueException("Failed to find a secondary storage host in the specified zone."); - } - - return profile; - } - - public TemplateProfile prepareDelete(DeleteIsoCmd cmd) { - TemplateProfile profile = super.prepareDelete(cmd); - Long zoneId = profile.getZoneId(); - - if (zoneId != null && (_ssvmMgr.findSecondaryStorageHost(zoneId) == null)) { - throw new InvalidParameterValueException("Failed to find a secondary storage host in the specified zone."); - } - - return profile; - } + } + return profile; + } } diff --git a/server/src/com/cloud/template/TemplateAdapter.java b/server/src/com/cloud/template/TemplateAdapter.java index bb7cd239b95..d50d45b7e18 100755 --- a/server/src/com/cloud/template/TemplateAdapter.java +++ b/server/src/com/cloud/template/TemplateAdapter.java @@ -34,19 +34,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; @@ -60,14 +60,15 @@ public interface TemplateAdapter extends Adapter { public TemplateProfile prepareExtractTemplate(ExtractTemplateCmd 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, Boolean isDynamicallyScalable) throws ResourceAllocationException; + } diff --git a/server/src/com/cloud/template/TemplateAdapterBase.java b/server/src/com/cloud/template/TemplateAdapterBase.java index c57697b257a..898ed2417d0 100755 --- a/server/src/com/cloud/template/TemplateAdapterBase.java +++ b/server/src/com/cloud/template/TemplateAdapterBase.java @@ -29,7 +29,7 @@ import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd; import org.apache.cloudstack.api.command.user.template.ExtractTemplateCmd; 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.storage.datastore.db.TemplateDataStoreDao; import org.apache.log4j.Logger; import com.cloud.api.ApiDBUtils; @@ -52,8 +52,8 @@ import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.TemplateProfile; import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.dao.GuestOSHypervisorDao; import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VMTemplateHostDao; import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.user.Account; import com.cloud.user.AccountManager; @@ -77,21 +77,22 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat protected @Inject AccountManager _accountMgr; protected @Inject DataCenterDao _dcDao; protected @Inject VMTemplateDao _tmpltDao; - protected @Inject VMTemplateHostDao _tmpltHostDao; + protected @Inject TemplateDataStoreDao _tmpltStoreDao; protected @Inject VMTemplateZoneDao _tmpltZoneDao; protected @Inject UsageEventDao _usageEventDao; protected @Inject HostDao _hostDao; protected @Inject UserVmDao _userVmDao; + protected @Inject GuestOSHypervisorDao _osHyperDao; protected @Inject ResourceLimitService _resourceLimitMgr; protected @Inject DataStoreManager storeMgr; @Inject TemplateManager templateMgr; - @Inject ConfigurationServer _configServer; - + @Inject ConfigurationServer _configServer; + @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) || @@ -99,39 +100,36 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)); } - public TemplateProfile prepare(boolean isIso, Long userId, String name, String displayText, Integer bits, + @Override + 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 { return prepare(isIso, userId, name, displayText, bits, passwordEnabled, requiresHVM, url, isPublic, featured, isExtractable, format, guestOSId, zoneId, hypervisorType, +<<<<<<< HEAD chksum, bootable, null, null, details, false, null, false); +======= + chksum, bootable, null, null, details, false); +>>>>>>> object_store } - - public TemplateProfile prepare(boolean isIso, long userId, String name, String displayText, Integer bits, + + @Override + 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, Boolean isDynamicallyScalable) throws ResourceAllocationException { //Long accountId = null; // 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; @@ -152,9 +150,9 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat } if (requiresHVM == null) { requiresHVM = true; - } + } } - + if (isExtractable == null) { isExtractable = Boolean.FALSE; } @@ -171,6 +169,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat if (url.toLowerCase().contains("file://")) { throw new InvalidParameterValueException("File:// type urls are currently unsupported"); } + // check whether owner can create public templates boolean allowPublicUserTemplates = Boolean.parseBoolean(_configServer.getConfigValue(Config.AllowPublicUserTemplates.key(), Config.ConfigurationParameterScope.account.toString(), templateOwner.getId())); if (!isAdmin && !allowPublicUserTemplates && isPublic) { @@ -180,24 +179,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); @@ -209,64 +208,61 @@ 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, isDynamicallyScalable); + featured, isExtractable, imgfmt, guestOSId, zoneId, hypervisorType, templateOwner.getAccountName(), templateOwner.getDomainId(), templateOwner.getAccountId(), chksum, bootable, templateTag, details, sshkeyEnabled, null, isDynamicallyScalable); + } - + @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.isDynamicallyScalable()); + cmd.getChecksum(), true, cmd.getTemplateTag(), owner, cmd.getDetails(), cmd.isSshKeyEnabled(), null, cmd.isDynamicallyScalable()); + } - public TemplateProfile prepare(RegisterIsoCmd cmd) throws ResourceAllocationException { + @Override + public TemplateProfile prepare(RegisterIsoCmd 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(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.isDynamicallyScalable()); } - + 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.getDetails(), profile.getSshKeyEnabled(), profile.IsDynamicallyScalable()); + 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"); } @@ -275,13 +271,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 { @@ -315,8 +311,9 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat return userId; } - - public TemplateProfile prepareDelete(DeleteTemplateCmd cmd) { + + @Override + public TemplateProfile prepareDelete(DeleteTemplateCmd cmd) { Long templateId = cmd.getId(); Long userId = UserContext.current().getCallerUserId(); Account account = UserContext.current().getCaller(); @@ -358,26 +355,28 @@ 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); } - abstract public VMTemplateVO create(TemplateProfile profile); - abstract public boolean delete(TemplateProfile profile); + @Override + abstract public VMTemplateVO create(TemplateProfile profile); + @Override + abstract public boolean delete(TemplateProfile profile); } diff --git a/server/src/com/cloud/template/TemplateManager.java b/server/src/com/cloud/template/TemplateManager.java index 19ba3b52734..8427fa92c7b 100755 --- a/server/src/com/cloud/template/TemplateManager.java +++ b/server/src/com/cloud/template/TemplateManager.java @@ -19,7 +19,9 @@ package com.cloud.template; import java.util.List; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import com.cloud.dc.DataCenterVO; import com.cloud.exception.InternalErrorException; @@ -35,11 +37,11 @@ import com.cloud.utils.Pair; /** * TemplateManager manages the templates stored on secondary storage. It is responsible for creating private/public templates. */ -public interface TemplateManager extends TemplateService{ +public interface TemplateManager extends TemplateApiService{ /** * Prepares a template for vm creation for a certain storage pool. - * + * * @param template * template to prepare * @param pool @@ -52,21 +54,20 @@ public interface TemplateManager extends TemplateService{ /** * Copies a template from its current secondary storage server to the secondary storage server in the specified zone. - * + * * @param template - * @param srcSecHost - * @param srcZone + * @param srcSecStore * @param destZone * @return true if success * @throws InternalErrorException * @throws StorageUnavailableException * @throws ResourceAllocationException */ - boolean copy(long userId, VMTemplateVO template, HostVO srcSecHost, DataCenterVO srcZone, DataCenterVO dstZone) throws StorageUnavailableException, ResourceAllocationException; + boolean copy(long userId, VMTemplateVO template, DataStore srcSecStore, DataCenterVO dstZone) throws StorageUnavailableException, ResourceAllocationException; /** * Deletes a template from secondary storage servers - * + * * @param userId * @param templateId * @param zoneId @@ -77,7 +78,7 @@ public interface TemplateManager extends TemplateService{ /** * Lists templates in the specified storage pool that are not being used by any VM. - * + * * @param pool * @return list of VMTemplateStoragePoolVO */ @@ -85,36 +86,32 @@ public interface TemplateManager extends TemplateService{ /** * Deletes a template in the specified storage pool. - * + * * @param templatePoolVO */ void evictTemplateFromStoragePool(VMTemplateStoragePoolVO templatePoolVO); boolean templateIsDeleteable(VMTemplateHostVO templateHostRef); - VMTemplateHostVO prepareISOForCreate(VMTemplateVO template, StoragePool pool); - - - VMTemplateHostVO findVmTemplateHost(long templateId, - StoragePool pool); + boolean templateIsDeleteable(long templateId); Pair getAbsoluteIsoPath(long templateId, long dataCenterId); String getSecondaryStorageURL(long zoneId); - HostVO getSecondaryStorageHost(long zoneId, long tmpltId); - - VMTemplateHostVO getTemplateHostRef(long zoneId, long tmpltId, - boolean readyOnly); - - HostVO getSecondaryStorageHost(long zoneId); - - List getSecondaryStorageHosts(long zoneId); + DataStore getImageStore(long zoneId, long tmpltId); Long getTemplateSize(long templateId, long zoneId); DataStore getImageStore(String storeUuid, Long zoneId); - String getChecksum(Long hostId, String templatePath); + String getChecksum(DataStore store, String templatePath); + + List getImageStoreByTemplate(long templateId, Long zoneId); + + TemplateInfo prepareIso(long isoId, long dcId); + + + } diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index 517d4ba80d7..273614ca8e0 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -22,29 +22,26 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.UnknownHostException; import java.util.ArrayList; -import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; -import java.util.Random; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.BaseListTemplateOrIsoPermissionsCmd; +import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd; import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoPermissionsCmd; import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd; import org.apache.cloudstack.api.command.user.iso.ExtractIsoCmd; import org.apache.cloudstack.api.command.user.iso.ListIsoPermissionsCmd; import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd; +import org.apache.cloudstack.api.command.user.iso.UpdateIsoCmd; import org.apache.cloudstack.api.command.user.iso.UpdateIsoPermissionsCmd; import org.apache.cloudstack.api.command.user.template.CopyTemplateCmd; import org.apache.cloudstack.api.command.user.template.CreateTemplateCmd; @@ -52,37 +49,51 @@ import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd; import org.apache.cloudstack.api.command.user.template.ExtractTemplateCmd; import org.apache.cloudstack.api.command.user.template.ListTemplatePermissionsCmd; import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd; +import org.apache.cloudstack.api.command.user.template.UpdateTemplateCmd; import org.apache.cloudstack.api.command.user.template.UpdateTemplatePermissionsCmd; -import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; 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.ImageDataFactory; -import org.apache.cloudstack.engine.subsystem.api.storage.ImageService; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.engine.subsystem.api.storage.Scope; +import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService.TemplateApiResult; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.storage.command.AttachCommand; +import org.apache.cloudstack.storage.command.CommandResult; +import org.apache.cloudstack.storage.command.CopyCommand; +import org.apache.cloudstack.storage.command.DettachCommand; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; +import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.amazonaws.services.s3.model.CannedAccessControlList; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; -import com.cloud.agent.api.AttachIsoCommand; +import com.cloud.agent.api.Command; import com.cloud.agent.api.ComputeChecksumCommand; -import com.cloud.agent.api.DownloadTemplateFromSwiftToSecondaryStorageCommand; -import com.cloud.agent.api.UploadTemplateToSwiftFromSecondaryStorageCommand; -import com.cloud.agent.api.storage.DestroyCommand; -import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; -import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; -import com.cloud.agent.api.to.SwiftTO; +import com.cloud.agent.api.storage.DestroyCommand; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.DiskTO; +import com.cloud.agent.api.to.NfsTO; +import com.cloud.agent.api.to.S3TO; import com.cloud.api.ApiDBUtils; +import com.cloud.api.query.dao.UserVmJoinDao; +import com.cloud.api.query.vo.UserVmJoinVO; import com.cloud.async.AsyncJobManager; import com.cloud.async.AsyncJobVO; import com.cloud.configuration.Config; @@ -103,7 +114,7 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.StorageUnavailableException; -import com.cloud.host.Host; +import com.cloud.exception.UnsupportedServiceException; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor; @@ -122,6 +133,8 @@ import com.cloud.storage.Storage; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ScopeType; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolHostVO; @@ -129,16 +142,14 @@ import com.cloud.storage.StoragePoolStatus; import com.cloud.storage.TemplateProfile; import com.cloud.storage.Upload; import com.cloud.storage.Upload.Type; +import com.cloud.storage.VMTemplateZoneVO; import com.cloud.storage.UploadVO; import com.cloud.storage.VMTemplateHostVO; -import com.cloud.storage.VMTemplateS3VO; import com.cloud.storage.VMTemplateStoragePoolVO; import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; -import com.cloud.storage.VMTemplateSwiftVO; import com.cloud.storage.VMTemplateVO; -import com.cloud.storage.VMTemplateZoneVO; import com.cloud.storage.Volume; import com.cloud.storage.VolumeManager; import com.cloud.storage.VolumeVO; @@ -149,16 +160,13 @@ import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.storage.dao.UploadDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplateDetailsDao; -import com.cloud.storage.dao.VMTemplateHostDao; import com.cloud.storage.dao.VMTemplatePoolDao; import com.cloud.storage.dao.VMTemplateS3Dao; import com.cloud.storage.dao.VMTemplateSwiftDao; import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.download.DownloadMonitor; -import com.cloud.storage.s3.S3Manager; import com.cloud.storage.secondary.SecondaryStorageVmManager; -import com.cloud.storage.swift.SwiftManager; import com.cloud.storage.upload.UploadMonitor; import com.cloud.template.TemplateAdapter.TemplateAdapterType; @@ -173,8 +181,10 @@ import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserAccountDao; import com.cloud.user.dao.UserDao; import com.cloud.uservm.UserVm; +import com.cloud.utils.EnumUtils; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; +import com.cloud.utils.S3Utils; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.concurrency.NamedThreadFactory; @@ -188,35 +198,51 @@ import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; @Component -@Local(value={TemplateManager.class, TemplateService.class}) -public class TemplateManagerImpl extends ManagerBase implements TemplateManager, TemplateService { +@Local(value = { TemplateManager.class, TemplateApiService.class }) +public class TemplateManagerImpl extends ManagerBase implements TemplateManager, TemplateApiService { private final static Logger s_logger = Logger.getLogger(TemplateManagerImpl.class); - @Inject VMTemplateDao _tmpltDao; - @Inject VMTemplateHostDao _tmpltHostDao; - @Inject VMTemplatePoolDao _tmpltPoolDao; - @Inject VMTemplateZoneDao _tmpltZoneDao; + @Inject + VMTemplateDao _tmpltDao; + @Inject + TemplateDataStoreDao _tmplStoreDao; + @Inject + VMTemplatePoolDao _tmpltPoolDao; + @Inject + VMTemplateZoneDao _tmpltZoneDao; @Inject protected VMTemplateDetailsDao _templateDetailsDao; - @Inject VMInstanceDao _vmInstanceDao; - @Inject PrimaryDataStoreDao _poolDao; - @Inject StoragePoolHostDao _poolHostDao; - @Inject EventDao _eventDao; - @Inject DownloadMonitor _downloadMonitor; - @Inject UploadMonitor _uploadMonitor; - @Inject UserAccountDao _userAccountDao; - @Inject AccountDao _accountDao; - @Inject UserDao _userDao; - @Inject AgentManager _agentMgr; - @Inject AccountManager _accountMgr; - @Inject HostDao _hostDao; - @Inject DataCenterDao _dcDao; - @Inject UserVmDao _userVmDao; - @Inject VolumeDao _volumeDao; - @Inject SnapshotDao _snapshotDao; @Inject - SwiftManager _swiftMgr; + VMInstanceDao _vmInstanceDao; @Inject - S3Manager _s3Mgr; + PrimaryDataStoreDao _poolDao; + @Inject + StoragePoolHostDao _poolHostDao; + @Inject + EventDao _eventDao; + @Inject + DownloadMonitor _downloadMonitor; + @Inject + UploadMonitor _uploadMonitor; + @Inject + UserAccountDao _userAccountDao; + @Inject + AccountDao _accountDao; + @Inject + UserDao _userDao; + @Inject + AgentManager _agentMgr; + @Inject + AccountManager _accountMgr; + @Inject + HostDao _hostDao; + @Inject + DataCenterDao _dcDao; + @Inject + UserVmDao _userVmDao; + @Inject + VolumeDao _volumeDao; + @Inject + SnapshotDao _snapshotDao; @Inject VMTemplateSwiftDao _tmpltSwiftDao; @Inject @@ -225,141 +251,153 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, ConfigurationDao _configDao; @Inject ClusterDao _clusterDao; - @Inject DomainDao _domainDao; - @Inject UploadDao _uploadDao; + @Inject + DomainDao _domainDao; + @Inject + UploadDao _uploadDao; @Inject protected GuestOSDao _guestOSDao; long _routerTemplateId = -1; - @Inject StorageManager _storageMgr; - @Inject AsyncJobManager _asyncMgr; - @Inject UserVmManager _vmMgr; - @Inject UsageEventDao _usageEventDao; - @Inject HypervisorGuruManager _hvGuruMgr; - @Inject AccountService _accountService; - @Inject ResourceLimitService _resourceLimitMgr; - @Inject SecondaryStorageVmManager _ssvmMgr; - @Inject LaunchPermissionDao _launchPermissionDao; - @Inject ProjectManager _projectMgr; @Inject - VolumeDataFactory volFactory; + StorageManager _storageMgr; @Inject - ImageDataFactory tmplFactory; + AsyncJobManager _asyncMgr; @Inject - SnapshotDataFactory snapshotFactory; + UserVmManager _vmMgr; @Inject - ImageService imageSvr; + UsageEventDao _usageEventDao; @Inject - DataStoreManager dataStoreMgr; + HypervisorGuruManager _hvGuruMgr; + @Inject + AccountService _accountService; + @Inject + ResourceLimitService _resourceLimitMgr; + @Inject + SecondaryStorageVmManager _ssvmMgr; + @Inject + LaunchPermissionDao _launchPermissionDao; + @Inject + ProjectManager _projectMgr; + @Inject + VolumeDataFactory _volFactory; + @Inject + TemplateDataFactory _tmplFactory; + @Inject + SnapshotDataFactory _snapshotFactory; + @Inject + TemplateService _tmpltSvr; + @Inject + DataStoreManager _dataStoreMgr; @Inject protected ResourceManager _resourceMgr; - @Inject VolumeManager volumeMgr; - @Inject VMTemplateHostDao templateHostDao; + @Inject + VolumeManager _volumeMgr; + @Inject + ImageStoreDao _imageStoreDao; + @Inject + EndPointSelector _epSelector; + @Inject + UserVmJoinDao _userVmJoinDao; + @Inject ConfigurationServer _configServer; - int _primaryStorageDownloadWait; - protected SearchBuilder HostTemplateStatesSearch; - int _storagePoolMaxWaitSeconds = 3600; boolean _disableExtraction = false; ExecutorService _preloadExecutor; - ScheduledExecutorService _swiftTemplateSyncExecutor; - - private ScheduledExecutorService _s3TemplateSyncExecutor = null; @Inject protected List _adapters; - + + @Inject + StorageCacheManager cacheMgr; + @Inject + EndPointSelector selector; + private TemplateAdapter getAdapter(HypervisorType type) { - TemplateAdapter adapter = null; - if (type == HypervisorType.BareMetal) { - adapter = AdapterBase.getAdapterByName(_adapters, TemplateAdapterType.BareMetal.getName()); - } else { - // see HypervisorTemplateAdapter - adapter = AdapterBase.getAdapterByName(_adapters, TemplateAdapterType.Hypervisor.getName()); - } - - if (adapter == null) { - throw new CloudRuntimeException("Cannot find template adapter for " + type.toString()); - } - - return adapter; + TemplateAdapter adapter = null; + if (type == HypervisorType.BareMetal) { + adapter = AdapterBase.getAdapterByName(_adapters, TemplateAdapterType.BareMetal.getName()); + } else { + // see HypervisorTemplateAdapter + adapter = AdapterBase.getAdapterByName(_adapters, TemplateAdapterType.Hypervisor.getName()); + } + + if (adapter == null) { + throw new CloudRuntimeException("Cannot find template adapter for " + type.toString()); + } + + return adapter; } - + @Override @ActionEvent(eventType = EventTypes.EVENT_ISO_CREATE, eventDescription = "creating iso") - public VirtualMachineTemplate registerIso(RegisterIsoCmd cmd) throws ResourceAllocationException{ - TemplateAdapter adapter = getAdapter(HypervisorType.None); - TemplateProfile profile = adapter.prepare(cmd); - VMTemplateVO template = adapter.create(profile); - - if (template != null){ - return template; - }else { - throw new CloudRuntimeException("Failed to create ISO"); + public VirtualMachineTemplate registerIso(RegisterIsoCmd cmd) throws ResourceAllocationException { + TemplateAdapter adapter = getAdapter(HypervisorType.None); + TemplateProfile profile = adapter.prepare(cmd); + VMTemplateVO template = adapter.create(profile); + + if (template != null) { + return template; + } else { + throw new CloudRuntimeException("Failed to create ISO"); } } @Override @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "creating template") - public VirtualMachineTemplate registerTemplate(RegisterTemplateCmd cmd) throws URISyntaxException, ResourceAllocationException{ - if(cmd.getTemplateTag() != null){ + public VirtualMachineTemplate registerTemplate(RegisterTemplateCmd cmd) throws URISyntaxException, ResourceAllocationException { + if (cmd.getTemplateTag() != null) { Account account = UserContext.current().getCaller(); - if(!_accountService.isRootAdmin(account.getType())){ + if (!_accountService.isRootAdmin(account.getType())) { throw new PermissionDeniedException("Parameter templatetag can only be specified by a Root Admin, permission denied"); } } - - TemplateAdapter adapter = getAdapter(HypervisorType.getType(cmd.getHypervisor())); - TemplateProfile profile = adapter.prepare(cmd); - VMTemplateVO template = adapter.create(profile); - - if (template != null){ - return template; - }else { - throw new CloudRuntimeException("Failed to create a template"); + + TemplateAdapter adapter = getAdapter(HypervisorType.getType(cmd.getHypervisor())); + TemplateProfile profile = adapter.prepare(cmd); + VMTemplateVO template = adapter.create(profile); + + if (template != null) { + return template; + } else { + throw new CloudRuntimeException("Failed to create a template"); } } - + @Override public DataStore getImageStore(String storeUuid, Long zoneId) { DataStore imageStore = null; if (storeUuid != null) { - imageStore = this.dataStoreMgr.getDataStore(storeUuid, DataStoreRole.Image); + imageStore = this._dataStoreMgr.getDataStore(storeUuid, DataStoreRole.Image); } else { - List stores = this.dataStoreMgr.getImageStores(new ZoneScope(zoneId)); + List stores = this._dataStoreMgr.getImageStoresByScope(new ZoneScope(zoneId)); if (stores.size() > 1) { throw new CloudRuntimeException("multiple image stores, don't know which one to use"); } imageStore = stores.get(0); } - + return imageStore; } @Override @ActionEvent(eventType = EventTypes.EVENT_ISO_EXTRACT, eventDescription = "extracting ISO", async = true) - public Long extract(ExtractIsoCmd cmd) { + public String extract(ExtractIsoCmd cmd) { Account account = UserContext.current().getCaller(); Long templateId = cmd.getId(); Long zoneId = cmd.getZoneId(); String url = cmd.getUrl(); String mode = cmd.getMode(); Long eventId = cmd.getStartEventId(); - - // FIXME: async job needs fixing - Long uploadId = extract(account, templateId, url, zoneId, mode, eventId, true, null, _asyncMgr); - if (uploadId != null){ - return uploadId; - }else { - throw new CloudRuntimeException("Failed to extract the iso"); - } + + return extract(account, templateId, url, zoneId, mode, eventId, true); } @Override @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_EXTRACT, eventDescription = "extracting template", async = true) - public Long extract(ExtractTemplateCmd cmd) { + public String extract(ExtractTemplateCmd cmd) { Account caller = UserContext.current().getCaller(); Long templateId = cmd.getId(); Long zoneId = cmd.getZoneId(); @@ -374,551 +412,234 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, TemplateAdapter adapter = getAdapter(template.getHypervisorType()); TemplateProfile profile = adapter.prepareExtractTemplate(cmd); - // FIXME: async job needs fixing - Long uploadId = extract(caller, templateId, url, zoneId, mode, eventId, false, null, _asyncMgr); - if (uploadId != null){ - return uploadId; - }else { - throw new CloudRuntimeException("Failed to extract the teamplate"); - } - } - - @Override - public VirtualMachineTemplate prepareTemplate(long templateId, long zoneId) { - - VMTemplateVO vmTemplate = _tmpltDao.findById(templateId); - if(vmTemplate == null) - throw new InvalidParameterValueException("Unable to find template id=" + templateId); - - _accountMgr.checkAccess(UserContext.current().getCaller(), AccessType.ModifyEntry, true, vmTemplate); - - prepareTemplateInAllStoragePools(vmTemplate, zoneId); - return vmTemplate; + return extract(caller, templateId, url, zoneId, mode, eventId, false); } - private Long extract(Account caller, Long templateId, String url, Long zoneId, String mode, Long eventId, boolean isISO, AsyncJobVO job, AsyncJobManager mgr) { + @Override + public VirtualMachineTemplate prepareTemplate(long templateId, long zoneId) { + + VMTemplateVO vmTemplate = _tmpltDao.findById(templateId); + if (vmTemplate == null) + throw new InvalidParameterValueException("Unable to find template id=" + templateId); + + _accountMgr.checkAccess(UserContext.current().getCaller(), AccessType.ModifyEntry, true, vmTemplate); + + prepareTemplateInAllStoragePools(vmTemplate, zoneId); + return vmTemplate; + } + + private String extract(Account caller, Long templateId, String url, Long zoneId, String mode, Long eventId, boolean isISO) { String desc = Upload.Type.TEMPLATE.toString(); if (isISO) { desc = Upload.Type.ISO.toString(); } - eventId = eventId == null ? 0:eventId; - + eventId = eventId == null ? 0 : eventId; + if (!_accountMgr.isRootAdmin(caller.getType()) && _disableExtraction) { throw new PermissionDeniedException("Extraction has been disabled by admin"); } - + VMTemplateVO template = _tmpltDao.findById(templateId); if (template == null || template.getRemoved() != null) { - throw new InvalidParameterValueException("Unable to find " +desc+ " with id " + templateId); + throw new InvalidParameterValueException("Unable to find " + desc + " with id " + templateId); } - - if (template.getTemplateType() == Storage.TemplateType.SYSTEM){ - throw new InvalidParameterValueException("Unable to extract the " + desc + " " + template.getName() + " as it is a default System template"); - } else if (template.getTemplateType() == Storage.TemplateType.PERHOST){ - throw new InvalidParameterValueException("Unable to extract the " + desc + " " + template.getName() + " as it resides on host and not on SSVM"); + + if (template.getTemplateType() == Storage.TemplateType.SYSTEM) { + throw new InvalidParameterValueException("Unable to extract the " + desc + " " + template.getName() + + " as it is a default System template"); + } else if (template.getTemplateType() == Storage.TemplateType.PERHOST) { + throw new InvalidParameterValueException("Unable to extract the " + desc + " " + template.getName() + + " as it resides on host and not on SSVM"); } - + if (isISO) { - if (template.getFormat() != ImageFormat.ISO ){ + if (template.getFormat() != ImageFormat.ISO) { throw new InvalidParameterValueException("Unsupported format, could not extract the ISO"); } } else { - if (template.getFormat() == ImageFormat.ISO ){ + if (template.getFormat() == ImageFormat.ISO) { throw new InvalidParameterValueException("Unsupported format, could not extract the template"); } } - - if (zoneId == null && _swiftMgr.isSwiftEnabled()) { - zoneId = _swiftMgr.chooseZoneForTmpltExtract(templateId); - } - if (zoneId == null && _s3Mgr.isS3Enabled()) { - zoneId = _s3Mgr.chooseZoneForTemplateExtract(template); - } - - if (_dcDao.findById(zoneId) == null) { + if (zoneId != null && _dcDao.findById(zoneId) == null) { throw new IllegalArgumentException("Please specify a valid zone."); } - + if (!_accountMgr.isRootAdmin(caller.getType()) && !template.isExtractable()) { throw new InvalidParameterValueException("Unable to extract template id=" + templateId + " as it's not extractable"); } - - _accountMgr.checkAccess(caller, AccessType.ModifyEntry, true, template); - - List sservers = getSecondaryStorageHosts(zoneId); - VMTemplateHostVO tmpltHostRef = null; - if (sservers != null) { - for(HostVO secondaryStorageHost: sservers){ - tmpltHostRef = _tmpltHostDao.findByHostTemplate(secondaryStorageHost.getId(), templateId); - if (tmpltHostRef != null){ - if (tmpltHostRef.getDownloadState() != com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { - tmpltHostRef = null; - } - else { + _accountMgr.checkAccess(caller, AccessType.ModifyEntry, true, template); + + List ssStores = this._dataStoreMgr.getImageStoresByScope(new ZoneScope(zoneId)); + + TemplateDataStoreVO tmpltStoreRef = null; + ImageStoreEntity tmpltStore = null; + if (ssStores != null) { + for (DataStore store : ssStores) { + tmpltStoreRef = this._tmplStoreDao.findByStoreTemplate(store.getId(), templateId); + if (tmpltStoreRef != null) { + if (tmpltStoreRef.getDownloadState() == com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { + tmpltStore = (ImageStoreEntity) store; break; } } } } - - if (tmpltHostRef == null && _swiftMgr.isSwiftEnabled()) { - SwiftTO swift = _swiftMgr.getSwiftTO(templateId); - if (swift != null && sservers != null) { - downloadTemplateFromSwiftToSecondaryStorage(zoneId, templateId); - } - } else if (tmpltHostRef == null && _s3Mgr.isS3Enabled()) { - if (sservers != null) { - _s3Mgr.downloadTemplateFromS3ToSecondaryStorage(zoneId, - templateId, _primaryStorageDownloadWait); - } - } - if (tmpltHostRef == null) { + if (tmpltStoreRef == null) { throw new InvalidParameterValueException("The " + desc + " has not been downloaded "); } - - Upload.Mode extractMode; - if (mode == null || (!mode.equalsIgnoreCase(Upload.Mode.FTP_UPLOAD.toString()) && !mode.equalsIgnoreCase(Upload.Mode.HTTP_DOWNLOAD.toString())) ){ - throw new InvalidParameterValueException("Please specify a valid extract Mode. Supported modes: "+ Upload.Mode.FTP_UPLOAD + ", " + Upload.Mode.HTTP_DOWNLOAD); - } else { - extractMode = mode.equalsIgnoreCase(Upload.Mode.FTP_UPLOAD.toString()) ? Upload.Mode.FTP_UPLOAD : Upload.Mode.HTTP_DOWNLOAD; - } - - if (extractMode == Upload.Mode.FTP_UPLOAD){ - URI uri = null; - try { - uri = new URI(url); - if ((uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) { - throw new InvalidParameterValueException("Unsupported scheme for url: " + url); - } - } catch (Exception ex) { - throw new InvalidParameterValueException("Invalid url given: " + url); - } - - String host = uri.getHost(); - try { - InetAddress hostAddr = InetAddress.getByName(host); - if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) { - throw new InvalidParameterValueException("Illegal host specified in url"); - } - if (hostAddr instanceof Inet6Address) { - throw new InvalidParameterValueException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")"); - } - } catch (UnknownHostException uhe) { - throw new InvalidParameterValueException("Unable to resolve " + host); - } - - if (_uploadMonitor.isTypeUploadInProgress(templateId, isISO ? Type.ISO : Type.TEMPLATE) ){ - throw new IllegalArgumentException(template.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same"); - } - - return _uploadMonitor.extractTemplate(template, url, tmpltHostRef, zoneId, eventId, job.getId(), mgr); - } - - UploadVO vo = _uploadMonitor.createEntityDownloadURL(template, tmpltHostRef, zoneId, eventId); - if (vo != null){ - return vo.getId(); - }else{ - return null; - } + + return tmpltStore.createEntityExtractUrl(tmpltStoreRef.getInstallPath(), template.getFormat()); } - + public void prepareTemplateInAllStoragePools(final VMTemplateVO template, long zoneId) { - List pools = _poolDao.listByStatus(StoragePoolStatus.Up); - for(final StoragePoolVO pool : pools) { - if(pool.getDataCenterId() == zoneId) { - s_logger.info("Schedule to preload template " + template.getId() + " into primary storage " + pool.getId()); - this._preloadExecutor.execute(new Runnable() { - public void run() { - try { - reallyRun(); - } catch(Throwable e) { - s_logger.warn("Unexpected exception ", e); - } - } - - private void reallyRun() { - s_logger.info("Start to preload template " + template.getId() + " into primary storage " + pool.getId()); - StoragePool pol = (StoragePool)dataStoreMgr.getPrimaryDataStore(pool.getId()); - prepareTemplateForCreate(template, pol); - s_logger.info("End of preloading template " + template.getId() + " into primary storage " + pool.getId()); - } - }); - } else { - s_logger.info("Skip loading template " + template.getId() + " into primary storage " + pool.getId() + " as pool zone " + pool.getDataCenterId() + " is "); - } - } - } - - String downloadTemplateFromSwiftToSecondaryStorage(long dcId, long templateId){ - VMTemplateVO template = _tmpltDao.findById(templateId); - if ( template == null ) { - String errMsg = " Can not find template " + templateId; - s_logger.warn(errMsg); - return errMsg; - } - VMTemplateSwiftVO tmpltSwift = _swiftMgr.findByTmpltId(templateId); - if ( tmpltSwift == null ) { - String errMsg = " Template " + templateId + " doesn't exist in swift"; - s_logger.warn(errMsg); - return errMsg; - } - SwiftTO swift = _swiftMgr.getSwiftTO(tmpltSwift.getSwiftId()); - if ( swift == null ) { - String errMsg = " Swift " + tmpltSwift.getSwiftId() + " doesn't exit ?"; - s_logger.warn(errMsg); - return errMsg; - } + List pools = _poolDao.listByStatus(StoragePoolStatus.Up); + for (final StoragePoolVO pool : pools) { + if (pool.getDataCenterId() == zoneId) { + s_logger.info("Schedule to preload template " + template.getId() + " into primary storage " + pool.getId()); + this._preloadExecutor.execute(new Runnable() { + @Override + public void run() { + try { + reallyRun(); + } catch (Throwable e) { + s_logger.warn("Unexpected exception ", e); + } + } - HostVO secHost = _ssvmMgr.findSecondaryStorageHost(dcId); - if ( secHost == null ) { - String errMsg = "Can not find secondary storage in data center " + dcId; - s_logger.warn(errMsg); - return errMsg; - } - - DownloadTemplateFromSwiftToSecondaryStorageCommand cmd = new DownloadTemplateFromSwiftToSecondaryStorageCommand(swift, secHost.getName(), dcId, template.getAccountId(), templateId, - tmpltSwift.getPath(), _primaryStorageDownloadWait); - try { - Answer answer = _agentMgr.sendToSSVM(dcId, cmd); - if (answer == null || !answer.getResult()) { - String errMsg = "Failed to download template from Swift to secondary storage due to " + (answer == null ? "answer is null" : answer.getDetails()); - s_logger.warn(errMsg); - throw new CloudRuntimeException(errMsg); + private void reallyRun() { + s_logger.info("Start to preload template " + template.getId() + " into primary storage " + pool.getId()); + StoragePool pol = (StoragePool) _dataStoreMgr.getPrimaryDataStore(pool.getId()); + prepareTemplateForCreate(template, pol); + s_logger.info("End of preloading template " + template.getId() + " into primary storage " + pool.getId()); + } + }); + } else { + s_logger.info("Skip loading template " + template.getId() + " into primary storage " + pool.getId() + " as pool zone " + + pool.getDataCenterId() + " is "); } - String installPath = "template/tmpl/" + template.getAccountId() + "/" + template.getId() + "/" + tmpltSwift.getPath(); - VMTemplateHostVO tmpltHost = new VMTemplateHostVO(secHost.getId(), templateId, new Date(), 100, Status.DOWNLOADED, null, null, null, installPath, template.getUrl()); - tmpltHost.setSize(tmpltSwift.getSize()); - tmpltHost.setPhysicalSize(tmpltSwift.getPhysicalSize()); - _tmpltHostDao.persist(tmpltHost); - } catch (Exception e) { - String errMsg = "Failed to download template from Swift to secondary storage due to " + e.toString(); - s_logger.warn(errMsg); - throw new CloudRuntimeException(errMsg); } - return null; } - String uploadTemplateToSwiftFromSecondaryStorage(VMTemplateHostVO templateHostRef) { - Long templateId = templateHostRef.getTemplateId(); - VMTemplateVO template = _tmpltDao.findById(templateId); - if (template == null) { - String errMsg = " Can not find template " + templateId; - s_logger.warn(errMsg); - return errMsg; - } - - if (template.getTemplateType() == TemplateType.PERHOST) { - return null; - } - - SwiftTO swift = _swiftMgr.getSwiftTO(); - if (swift == null) { - String errMsg = " There is no Swift in this setup "; - s_logger.warn(errMsg); - return errMsg; - } - - HostVO secHost = _hostDao.findById(templateHostRef.getHostId()); - if (secHost == null) { - String errMsg = "Can not find secondary storage " + templateHostRef.getHostId(); - s_logger.warn(errMsg); - return errMsg; - } - - UploadTemplateToSwiftFromSecondaryStorageCommand cmd = new UploadTemplateToSwiftFromSecondaryStorageCommand(swift, secHost.getName(), secHost.getDataCenterId(), template.getAccountId(), - templateId, _primaryStorageDownloadWait); - Answer answer = null; - try { - answer = _agentMgr.sendToSSVM(secHost.getDataCenterId(), cmd); - if (answer == null || !answer.getResult()) { - if (template.getTemplateType() != TemplateType.SYSTEM) { - String errMsg = "Failed to upload template " + templateId + " to Swift from secondary storage due to " + ((answer == null) ? "null" : answer.getDetails()); - s_logger.warn(errMsg); - throw new CloudRuntimeException(errMsg); - } - return null; - } - String path = templateHostRef.getInstallPath(); - int index = path.lastIndexOf('/'); - path = path.substring(index + 1); - VMTemplateSwiftVO tmpltSwift = new VMTemplateSwiftVO(swift.getId(), templateHostRef.getTemplateId(), new Date(), path, templateHostRef.getSize(), templateHostRef.getPhysicalSize()); - _tmpltSwiftDao.persist(tmpltSwift); - _swiftMgr.propagateTemplateOnAllZones(templateHostRef.getTemplateId()); - } catch (Exception e) { - String errMsg = "Failed to upload template " + templateId + " to Swift from secondary storage due to " + e.toString(); - s_logger.warn(errMsg); - throw new CloudRuntimeException(errMsg); - } - return null; - } - - @Override @DB + @Override + @DB public VMTemplateStoragePoolVO prepareTemplateForCreate(VMTemplateVO templ, StoragePool pool) { - VMTemplateVO template = _tmpltDao.findById(templ.getId(), true); - + VMTemplateVO template = _tmpltDao.findById(templ.getId(), true); + long poolId = pool.getId(); long templateId = template.getId(); - long dcId = pool.getDataCenterId(); VMTemplateStoragePoolVO templateStoragePoolRef = null; - VMTemplateHostVO templateHostRef = null; - long templateStoragePoolRefId; - String origUrl = null; - + TemplateDataStoreVO templateStoreRef = null; + templateStoragePoolRef = _tmpltPoolDao.findByPoolTemplate(poolId, templateId); if (templateStoragePoolRef != null) { - templateStoragePoolRef.setMarkedForGC(false); + templateStoragePoolRef.setMarkedForGC(false); _tmpltPoolDao.update(templateStoragePoolRef.getId(), templateStoragePoolRef); - + if (templateStoragePoolRef.getDownloadState() == Status.DOWNLOADED) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Template " + templateId + " has already been downloaded to pool " + poolId); - } - - return templateStoragePoolRef; - } - } - - templateHostRef = findVmTemplateHost(templateId, pool); - - if (templateHostRef == null || templateHostRef.getDownloadState() != Status.DOWNLOADED) { - String result = downloadTemplateFromSwiftToSecondaryStorage(dcId, templateId); - if (result != null) { - s_logger.error("Unable to find a secondary storage host who has completely downloaded the template."); - return null; - } - result = _s3Mgr.downloadTemplateFromS3ToSecondaryStorage(dcId, - templateId, _primaryStorageDownloadWait); - if (result != null) { - s_logger.error("Unable to find a secondary storage host who has completely downloaded the template."); - return null; - } - templateHostRef = findVmTemplateHost(templateId, pool); - if (templateHostRef == null || templateHostRef.getDownloadState() != Status.DOWNLOADED) { - s_logger.error("Unable to find a secondary storage host who has completely downloaded the template."); - return null; + if (s_logger.isDebugEnabled()) { + s_logger.debug("Template " + templateId + " has already been downloaded to pool " + poolId); + } + + return templateStoragePoolRef; } } - - HostVO sh = _hostDao.findById(templateHostRef.getHostId()); - origUrl = sh.getStorageUrl(); - if (origUrl == null) { - throw new CloudRuntimeException("Unable to find the orig.url from host " + sh.toString()); + + templateStoreRef = this._tmplStoreDao.findByTemplateZoneDownloadStatus(templateId, pool.getDataCenterId(), + VMTemplateStorageResourceAssoc.Status.DOWNLOADED); + if (templateStoreRef == null) { + s_logger.error("Unable to find a secondary storage host who has completely downloaded the template."); + return null; } - + + List vos = _poolHostDao.listByHostStatus(poolId, com.cloud.host.Status.Up); + if (vos == null || vos.isEmpty()) { + throw new CloudRuntimeException("Cannot download " + templateId + " to poolId " + poolId + + " since there is no host in the Up state connected to this pool"); + } + if (templateStoragePoolRef == null) { if (s_logger.isDebugEnabled()) { s_logger.debug("Downloading template " + templateId + " to pool " + poolId); } - templateStoragePoolRef = new VMTemplateStoragePoolVO(poolId, templateId); + DataStore srcSecStore = this._dataStoreMgr.getDataStore(templateStoreRef.getDataStoreId(), DataStoreRole.Image); + TemplateInfo srcTemplate = this._tmplFactory.getTemplate(templateId, srcSecStore); + + AsyncCallFuture future = this._tmpltSvr.prepareTemplateOnPrimary(srcTemplate, pool); try { - templateStoragePoolRef = _tmpltPoolDao.persist(templateStoragePoolRef); - templateStoragePoolRefId = templateStoragePoolRef.getId(); - - } catch (Exception e) { - s_logger.debug("Assuming we're in a race condition: " + e.getMessage()); - templateStoragePoolRef = _tmpltPoolDao.findByPoolTemplate(poolId, templateId); - if (templateStoragePoolRef == null) { - throw new CloudRuntimeException("Unable to persist a reference for pool " + poolId + " and template " + templateId); + TemplateApiResult result = future.get(); + if (result.isFailed()) { + s_logger.debug("prepare template failed:" + result.getResult()); + return null; } - templateStoragePoolRefId = templateStoragePoolRef.getId(); + + return _tmpltPoolDao.findByPoolTemplate(poolId, templateId); + } catch (Exception ex) { + s_logger.debug("failed to copy template from image store:" + srcSecStore.getName() + " to primary storage"); } - } else { - templateStoragePoolRefId = templateStoragePoolRef.getId(); - } - - List vos = _poolHostDao.listByHostStatus(poolId, com.cloud.host.Status.Up); - if (vos == null || vos.isEmpty()){ - throw new CloudRuntimeException("Cannot download " + templateId + " to poolId " + poolId + " since there is no host in the Up state connected to this pool"); - } - - templateStoragePoolRef = _tmpltPoolDao.acquireInLockTable(templateStoragePoolRefId, _storagePoolMaxWaitSeconds); - if (templateStoragePoolRef == null) { - throw new CloudRuntimeException("Unable to acquire lock on VMTemplateStoragePool: " + templateStoragePoolRefId); } - try { - if (templateStoragePoolRef.getDownloadState() == Status.DOWNLOADED) { - return templateStoragePoolRef; - } - String url = origUrl + "/" + templateHostRef.getInstallPath(); - PrimaryStorageDownloadCommand dcmd = new PrimaryStorageDownloadCommand(template.getUniqueName(), url, template.getFormat(), - template.getAccountId(), pool, _primaryStorageDownloadWait); - HostVO secondaryStorageHost = _hostDao.findById(templateHostRef.getHostId()); - assert(secondaryStorageHost != null); - dcmd.setSecondaryStorageUrl(secondaryStorageHost.getStorageUrl()); - // TODO temporary hacking, hard-coded to NFS primary data store - dcmd.setPrimaryStorageUrl("nfs://" + pool.getHostAddress() + pool.getPath()); - - for (int retry = 0; retry < 2; retry ++){ - Collections.shuffle(vos); // Shuffling to pick a random host in the vm deployment retries - StoragePoolHostVO vo = vos.get(0); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Downloading " + templateId + " via " + vo.getHostId()); - } - dcmd.setLocalPath(vo.getLocalPath()); - // set 120 min timeout for this command - - PrimaryStorageDownloadAnswer answer = (PrimaryStorageDownloadAnswer)_agentMgr.easySend( - _hvGuruMgr.getGuruProcessedCommandTargetHost(vo.getHostId(), dcmd), dcmd); - if (answer != null && answer.getResult() ) { - templateStoragePoolRef.setDownloadPercent(100); - templateStoragePoolRef.setDownloadState(Status.DOWNLOADED); - templateStoragePoolRef.setLocalDownloadPath(answer.getInstallPath()); - templateStoragePoolRef.setInstallPath(answer.getInstallPath()); - templateStoragePoolRef.setTemplateSize(answer.getTemplateSize()); - _tmpltPoolDao.update(templateStoragePoolRef.getId(), templateStoragePoolRef); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Template " + templateId + " is downloaded via " + vo.getHostId()); - } - return templateStoragePoolRef; - } else { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Template " + templateId + " download to pool " + vo.getPoolId() + " failed due to " + (answer!=null?answer.getDetails():"return null")); } - } - } - } finally { - _tmpltPoolDao.releaseFromLockTable(templateStoragePoolRefId); - } - if (s_logger.isDebugEnabled()) { - s_logger.debug("Template " + templateId + " is not found on and can not be downloaded to pool " + poolId); - } return null; } - - - - + @Override - public VMTemplateHostVO findVmTemplateHost(long templateId, - StoragePool pool) { - long dcId = pool.getDataCenterId(); - Long podId = pool.getPodId(); - - List secHosts = _ssvmMgr - .listSecondaryStorageHostsInOneZone(dcId); - - - if (secHosts.size() == 1) { - VMTemplateHostVO templateHostVO = this._tmpltHostDao - .findByHostTemplate(secHosts.get(0).getId(), templateId); - return templateHostVO; - } - if (podId != null) { - List templHosts = this._tmpltHostDao - .listByTemplateStatus(templateId, dcId, podId, - VMTemplateStorageResourceAssoc.Status.DOWNLOADED); - if (templHosts != null && !templHosts.isEmpty()) { - Collections.shuffle(templHosts); - return templHosts.get(0); - } - } - List templHosts = this._tmpltHostDao - .listByTemplateStatus(templateId, dcId, - VMTemplateStorageResourceAssoc.Status.DOWNLOADED); - if (templHosts != null && !templHosts.isEmpty()) { - Collections.shuffle(templHosts); - return templHosts.get(0); - } - return null; - } - - @Override - public String getChecksum(Long hostId, String templatePath) { - HostVO ssHost = _hostDao.findById(hostId); - Host.Type type = ssHost.getType(); - if (type != Host.Type.SecondaryStorage - && type != Host.Type.LocalSecondaryStorage) { - return null; - } - String secUrl = ssHost.getStorageUrl(); - Answer answer; - answer = _agentMgr.sendToSecStorage(ssHost, new ComputeChecksumCommand( - secUrl, templatePath)); + public String getChecksum(DataStore store, String templatePath) { + EndPoint ep = _epSelector.select(store); + ComputeChecksumCommand cmd = new ComputeChecksumCommand(store.getTO(), templatePath); + Answer answer = ep.sendMessage(cmd); if (answer != null && answer.getResult()) { return answer.getDetails(); } return null; } - - @Override - @DB - public VMTemplateHostVO prepareISOForCreate(VMTemplateVO template, StoragePool pool) { - template = _tmpltDao.findById(template.getId(), true); - - long poolId = pool.getId(); - long templateId = template.getId(); - long dcId = pool.getDataCenterId(); - VMTemplateStoragePoolVO templateStoragePoolRef = null; - VMTemplateHostVO templateHostRef = null; - long templateStoragePoolRefId; - String origUrl = null; - - templateHostRef = findVmTemplateHost(templateId, pool); - - if (templateHostRef == null || templateHostRef.getDownloadState() != Status.DOWNLOADED) { - String result = downloadTemplateFromSwiftToSecondaryStorage(dcId, templateId); - if (result != null) { - s_logger.error("Unable to find a secondary storage host who has completely downloaded the template."); - return null; - } - result = _s3Mgr.downloadTemplateFromS3ToSecondaryStorage(dcId, - templateId, _primaryStorageDownloadWait); - if (result != null) { - s_logger.error("Unable to find a secondary storage host who has completely downloaded the template."); - return null; - } - templateHostRef = findVmTemplateHost(templateId, pool); - if (templateHostRef == null || templateHostRef.getDownloadState() != Status.DOWNLOADED) { - s_logger.error("Unable to find a secondary storage host who has completely downloaded the template."); - return null; - } - } - return templateHostRef; - } @Override @DB public boolean resetTemplateDownloadStateOnPool(long templateStoragePoolRefId) { - // have to use the same lock that prepareTemplateForCreate use to maintain state consistency - VMTemplateStoragePoolVO templateStoragePoolRef = _tmpltPoolDao.acquireInLockTable(templateStoragePoolRefId, 1200); - + // have to use the same lock that prepareTemplateForCreate use to + // maintain state consistency + VMTemplateStoragePoolVO templateStoragePoolRef = _tmpltPoolDao.acquireInLockTable(templateStoragePoolRefId, 1200); + if (templateStoragePoolRef == null) { - s_logger.warn("resetTemplateDownloadStateOnPool failed - unable to lock TemplateStorgePoolRef " + templateStoragePoolRefId); + s_logger.warn("resetTemplateDownloadStateOnPool failed - unable to lock TemplateStorgePoolRef " + templateStoragePoolRefId); return false; } - + try { - templateStoragePoolRef.setDownloadState(VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED); - _tmpltPoolDao.update(templateStoragePoolRefId, templateStoragePoolRef); + templateStoragePoolRef.setDownloadState(VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED); + _tmpltPoolDao.update(templateStoragePoolRefId, templateStoragePoolRef); } finally { _tmpltPoolDao.releaseFromLockTable(templateStoragePoolRefId); } - + return true; } - + @Override @DB - public boolean copy(long userId, VMTemplateVO template, HostVO srcSecHost, DataCenterVO srcZone, DataCenterVO dstZone) throws StorageUnavailableException, ResourceAllocationException { - List dstSecHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(dstZone.getId()); + public boolean copy(long userId, VMTemplateVO template, DataStore srcSecStore, DataCenterVO dstZone) throws StorageUnavailableException, + ResourceAllocationException { long tmpltId = template.getId(); long dstZoneId = dstZone.getId(); - if (dstSecHosts == null || dstSecHosts.isEmpty() ) { - throw new StorageUnavailableException("Destination zone is not ready", DataCenter.class, dstZone.getId()); + // find all eligible image stores for the destination zone + List dstSecStores = this._dataStoreMgr.getImageStoresByScope(new ZoneScope(dstZoneId)); + if (dstSecStores == null || dstSecStores.isEmpty()) { + throw new StorageUnavailableException("Destination zone is not ready, no image store associated", DataCenter.class, dstZone.getId()); } AccountVO account = _accountDao.findById(template.getAccountId()); - VMTemplateHostVO srcTmpltHost = _tmpltHostDao.findByHostTemplate(srcSecHost.getId(), tmpltId); + // find the size of the template to be copied + TemplateDataStoreVO srcTmpltStore = this._tmplStoreDao.findByStoreTemplate(srcSecStore.getId(), tmpltId); _resourceLimitMgr.checkResourceLimit(account, ResourceType.template); - _resourceLimitMgr.checkResourceLimit(account, ResourceType.secondary_storage, new Long(srcTmpltHost.getSize())); + _resourceLimitMgr.checkResourceLimit(account, ResourceType.secondary_storage, new Long(srcTmpltStore.getSize())); // Event details String copyEventType; String createEventType; - if (template.getFormat().equals(ImageFormat.ISO)){ + if (template.getFormat().equals(ImageFormat.ISO)) { copyEventType = EventTypes.EVENT_ISO_COPY; createEventType = EventTypes.EVENT_ISO_CREATE; } else { @@ -929,162 +650,146 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, Transaction txn = Transaction.currentTxn(); txn.start(); - for ( HostVO dstSecHost : dstSecHosts ) { - VMTemplateHostVO dstTmpltHost = null; - try { - dstTmpltHost = _tmpltHostDao.findByHostTemplate(dstSecHost.getId(), tmpltId, true); - if (dstTmpltHost != null) { - dstTmpltHost = _tmpltHostDao.lockRow(dstTmpltHost.getId(), true); - if (dstTmpltHost != null && dstTmpltHost.getDownloadState() == Status.DOWNLOADED) { - if (dstTmpltHost.getDestroyed() == false) { - return true; - } else { - dstTmpltHost.setDestroyed(false); - _tmpltHostDao.update(dstTmpltHost.getId(), dstTmpltHost); - - return true; - } - } else if (dstTmpltHost != null && dstTmpltHost.getDownloadState() == Status.DOWNLOAD_ERROR){ - if (dstTmpltHost.getDestroyed() == true) { - dstTmpltHost.setDestroyed(false); - dstTmpltHost.setDownloadState(Status.NOT_DOWNLOADED); - dstTmpltHost.setDownloadPercent(0); - dstTmpltHost.setCopy(true); - dstTmpltHost.setErrorString(""); - dstTmpltHost.setJobId(null); - _tmpltHostDao.update(dstTmpltHost.getId(), dstTmpltHost); - } - } - } - } finally { - txn.commit(); + TemplateInfo srcTemplate = this._tmplFactory.getTemplate(template.getId(), srcSecStore); + // Copy will just find one eligible image store for the destination zone + // and copy template there, not propagate to all image stores + // for that zone + for (DataStore dstSecStore : dstSecStores) { + TemplateDataStoreVO dstTmpltStore = this._tmplStoreDao.findByStoreTemplate(dstSecStore.getId(), tmpltId); + if (dstTmpltStore != null && dstTmpltStore.getDownloadState() == Status.DOWNLOADED) { + return true; // already downloaded on this image store } - if(_downloadMonitor.copyTemplate(template, srcSecHost, dstSecHost) ) { + AsyncCallFuture future = this._tmpltSvr.copyTemplate(srcTemplate, dstSecStore); + try { + TemplateApiResult result = future.get(); + if (result.isFailed()) { + s_logger.debug("copy template failed for image store " + dstSecStore.getName() + ":" + result.getResult()); + continue; // try next image store + } + _tmpltDao.addTemplateToZone(template, dstZoneId); - - if(account.getId() != Account.ACCOUNT_ID_SYSTEM){ - UsageEventUtils.publishUsageEvent(copyEventType, account.getId(), dstZoneId, tmpltId, null, null, null, srcTmpltHost.getSize(), + + if (account.getId() != Account.ACCOUNT_ID_SYSTEM) { + UsageEventUtils.publishUsageEvent(copyEventType, account.getId(), dstZoneId, tmpltId, null, null, null, srcTmpltStore.getSize(), template.getClass().getName(), template.getUuid()); - } - return true; + } + return true; + } catch (Exception ex) { + s_logger.debug("failed to copy template to image store:" + dstSecStore.getName() + " ,will try next one"); } } return false; + } - - + @Override @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_COPY, eventDescription = "copying template", async = true) public VirtualMachineTemplate copyTemplate(CopyTemplateCmd cmd) throws StorageUnavailableException, ResourceAllocationException { - Long templateId = cmd.getId(); - Long userId = UserContext.current().getCallerUserId(); - Long sourceZoneId = cmd.getSourceZoneId(); - Long destZoneId = cmd.getDestinationZoneId(); - Account caller = UserContext.current().getCaller(); - - if (_swiftMgr.isSwiftEnabled()) { - throw new CloudRuntimeException("copytemplate API is disabled in Swift setup, templates in Swift can be accessed by all Zones"); - } + Long templateId = cmd.getId(); + Long userId = UserContext.current().getCallerUserId(); + Long sourceZoneId = cmd.getSourceZoneId(); + Long destZoneId = cmd.getDestinationZoneId(); + Account caller = UserContext.current().getCaller(); - if (_s3Mgr.isS3Enabled()) { - throw new CloudRuntimeException( - "copytemplate API is disabled in S3 setup -- S3 templates are accessible in all zones."); - } - - //Verify parameters + // Verify parameters if (sourceZoneId.equals(destZoneId)) { throw new InvalidParameterValueException("Please specify different source and destination zones."); } - + DataCenterVO sourceZone = _dcDao.findById(sourceZoneId); if (sourceZone == null) { throw new InvalidParameterValueException("Please specify a valid source zone."); } - + DataCenterVO dstZone = _dcDao.findById(destZoneId); if (dstZone == null) { throw new InvalidParameterValueException("Please specify a valid destination zone."); } - + VMTemplateVO template = _tmpltDao.findById(templateId); if (template == null || template.getRemoved() != null) { throw new InvalidParameterValueException("Unable to find template with id"); } - - HostVO dstSecHost = getSecondaryStorageHost(destZoneId, templateId); - if ( dstSecHost != null ) { - s_logger.debug("There is template " + templateId + " in secondary storage " + dstSecHost.getId() + " in zone " + destZoneId + " , don't need to copy"); + + DataStore dstSecStore = getImageStore(destZoneId, templateId); + if (dstSecStore != null) { + s_logger.debug("There is template " + templateId + " in secondary storage " + dstSecStore.getName() + " in zone " + destZoneId + + " , don't need to copy"); return template; } - - HostVO srcSecHost = getSecondaryStorageHost(sourceZoneId, templateId); - if ( srcSecHost == null ) { - throw new InvalidParameterValueException("There is no template " + templateId + " in zone " + sourceZoneId ); + + DataStore srcSecStore = getImageStore(sourceZoneId, templateId); + if (srcSecStore == null) { + throw new InvalidParameterValueException("There is no template " + templateId + " in zone " + sourceZoneId); } - + if (srcSecStore.getScope().getScopeType() == ScopeType.REGION) { + s_logger.debug("Template " + templateId + " is in region-wide secondary storage " + dstSecStore.getName() + " , don't need to copy"); + return template; + } + _accountMgr.checkAccess(caller, AccessType.ModifyEntry, true, template); - - boolean success = copy(userId, template, srcSecHost, sourceZone, dstZone); - - if (success){ - return template; - }else { - throw new CloudRuntimeException("Failed to copy template"); + + boolean success = copy(userId, template, srcSecStore, dstZone); + + if (success) { + return template; + } else { + throw new CloudRuntimeException("Failed to copy template"); } } @Override public boolean delete(long userId, long templateId, Long zoneId) { - VMTemplateVO template = _tmpltDao.findById(templateId); - if (template == null || template.getRemoved() != null) { - throw new InvalidParameterValueException("Please specify a valid template."); - } - - TemplateAdapter adapter = getAdapter(template.getHypervisorType()); - return adapter.delete(new TemplateProfile(userId, template, zoneId)); + VMTemplateVO template = _tmpltDao.findById(templateId); + if (template == null || template.getRemoved() != null) { + throw new InvalidParameterValueException("Please specify a valid template."); + } + + TemplateAdapter adapter = getAdapter(template.getHypervisorType()); + return adapter.delete(new TemplateProfile(userId, template, zoneId)); } - + @Override public List getUnusedTemplatesInPool(StoragePoolVO pool) { - List unusedTemplatesInPool = new ArrayList(); - List allTemplatesInPool = _tmpltPoolDao.listByPoolId(pool.getId()); - - for (VMTemplateStoragePoolVO templatePoolVO : allTemplatesInPool) { - VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templatePoolVO.getTemplateId()); - - // If this is a routing template, consider it in use - if (template.getTemplateType() == TemplateType.SYSTEM) { - continue; - } - - // If the template is not yet downloaded to the pool, consider it in use - if (templatePoolVO.getDownloadState() != Status.DOWNLOADED) { - continue; - } + List unusedTemplatesInPool = new ArrayList(); + List allTemplatesInPool = _tmpltPoolDao.listByPoolId(pool.getId()); - if (template.getFormat() != ImageFormat.ISO && !_volumeDao.isAnyVolumeActivelyUsingTemplateOnPool(template.getId(), pool.getId())) { + for (VMTemplateStoragePoolVO templatePoolVO : allTemplatesInPool) { + VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templatePoolVO.getTemplateId()); + + // If this is a routing template, consider it in use + if (template.getTemplateType() == TemplateType.SYSTEM) { + continue; + } + + // If the template is not yet downloaded to the pool, consider it in + // use + if (templatePoolVO.getDownloadState() != Status.DOWNLOADED) { + continue; + } + + if (template.getFormat() != ImageFormat.ISO && !_volumeDao.isAnyVolumeActivelyUsingTemplateOnPool(template.getId(), pool.getId())) { unusedTemplatesInPool.add(templatePoolVO); - } - } - - return unusedTemplatesInPool; - } - + } + } + + return unusedTemplatesInPool; + } + @Override public void evictTemplateFromStoragePool(VMTemplateStoragePoolVO templatePoolVO) { - StoragePool pool = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(templatePoolVO.getPoolId()); - VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templatePoolVO.getTemplateId()); - - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Evicting " + templatePoolVO); - } - DestroyCommand cmd = new DestroyCommand(pool, templatePoolVO); - + StoragePool pool = (StoragePool) this._dataStoreMgr.getPrimaryDataStore(templatePoolVO.getPoolId()); + VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templatePoolVO.getTemplateId()); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Evicting " + templatePoolVO); + } + DestroyCommand cmd = new DestroyCommand(pool, templatePoolVO); + try { Answer answer = _storageMgr.sendToPool(pool, cmd); - + if (answer != null && answer.getResult()) { // Remove the templatePoolVO if (_tmpltPoolDao.remove(templatePoolVO.getId())) { @@ -1094,267 +799,206 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, s_logger.info("Will retry evicte template: " + template.getName() + " from storage pool: " + pool.getName()); } } catch (StorageUnavailableException e) { - s_logger.info("Storage is unavailable currently. Will retry evicte template: " + template.getName() + " from storage pool: " + pool.getName()); + s_logger.info("Storage is unavailable currently. Will retry evicte template: " + template.getName() + " from storage pool: " + + pool.getName()); } - } - - void swiftTemplateSync() { - GlobalLock swiftTemplateSyncLock = GlobalLock.getInternLock("templatemgr.swiftTemplateSync"); - try { - if (!_swiftMgr.isSwiftEnabled()) { - return; - } - List hypers = _clusterDao.getAvailableHypervisorInZone(null); - List templates = _tmpltDao.listByHypervisorType(hypers); - List templateIds = new ArrayList(); - for (VMTemplateVO template : templates) { - if (template.getTemplateType() != TemplateType.PERHOST) { - templateIds.add(template.getId()); - } - } - List templtSwiftRefs = _tmpltSwiftDao.listAll(); - for (VMTemplateSwiftVO templtSwiftRef : templtSwiftRefs) { - templateIds.remove((Long) templtSwiftRef.getTemplateId()); - } - if (templateIds.size() < 1) { - return; - } - if (swiftTemplateSyncLock.lock(3)) { - try { - List templtHostRefs = _tmpltHostDao.listByState(VMTemplateHostVO.Status.DOWNLOADED); - for (VMTemplateHostVO templtHostRef : templtHostRefs) { - if (templtHostRef.getDestroyed()) { - continue; - } - if (!templateIds.contains(templtHostRef.getTemplateId())) { - continue; - } - try { - uploadTemplateToSwiftFromSecondaryStorage(templtHostRef); - } catch (Exception e) { - s_logger.debug("failed to upload template " + templtHostRef.getTemplateId() + " to Swift due to " + e.toString()); - } - } - } catch (Throwable e) { - s_logger.error("Problem with sync swift template due to " + e.toString(), e); - } finally { - swiftTemplateSyncLock.unlock(); - } - } - } catch (Throwable e) { - s_logger.error("Problem with sync swift template due to " + e.toString(), e); - } finally { - swiftTemplateSyncLock.releaseRef(); - } - } - - private Runnable getSwiftTemplateSyncTask() { - return new Runnable() { - @Override - public void run() { - if (s_logger.isDebugEnabled()) { - s_logger.trace("Start Swift Template sync at" + (new Date())); - } - swiftTemplateSync(); - if (s_logger.isTraceEnabled()) { - s_logger.trace("Finish Swift Template sync at" + (new Date())); - } - } - }; } @Override public boolean start() { - _swiftTemplateSyncExecutor.scheduleAtFixedRate(getSwiftTemplateSyncTask(), 60, 60, TimeUnit.SECONDS); - - if (_s3TemplateSyncExecutor != null) { - - final int initialDelay = 60; - final int period = 60; - - _s3TemplateSyncExecutor.scheduleAtFixedRate(new S3SyncTask( - this._tmpltDao, this._s3Mgr), initialDelay, period, - TimeUnit.SECONDS); - s_logger.info(String.format("Started S3 sync task to execute " - + "execute every %1$s after an initial delay of %2$s.", - period, initialDelay)); - - } - return true; } @Override public boolean stop() { - _swiftTemplateSyncExecutor.shutdownNow(); - - if (_s3TemplateSyncExecutor != null) { - _s3TemplateSyncExecutor.shutdownNow(); - } - return true; } @Override public boolean configure(String name, Map params) throws ConfigurationException { - + final Map configs = _configDao.getConfiguration("AgentManager", params); _routerTemplateId = NumbersUtil.parseInt(configs.get("router.template.id"), 1); String value = _configDao.getValue(Config.PrimaryStorageDownloadWait.toString()); _primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue())); - String disableExtraction = _configDao.getValue(Config.DisableExtraction.toString()); - _disableExtraction = (disableExtraction == null) ? false : Boolean.parseBoolean(disableExtraction); + String disableExtraction = _configDao.getValue(Config.DisableExtraction.toString()); + _disableExtraction = (disableExtraction == null) ? false : Boolean.parseBoolean(disableExtraction); - HostTemplateStatesSearch = _tmpltHostDao.createSearchBuilder(); - HostTemplateStatesSearch.and("id", HostTemplateStatesSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); - HostTemplateStatesSearch.and("state", HostTemplateStatesSearch.entity().getDownloadState(), SearchCriteria.Op.EQ); - - SearchBuilder HostSearch = _hostDao.createSearchBuilder(); - HostSearch.and("dcId", HostSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); - - HostTemplateStatesSearch.join("host", HostSearch, HostSearch.entity().getId(), HostTemplateStatesSearch.entity().getHostId(), JoinBuilder.JoinType.INNER); - HostSearch.done(); - HostTemplateStatesSearch.done(); - _storagePoolMaxWaitSeconds = NumbersUtil.parseInt(_configDao.getValue(Config.StoragePoolMaxWaitSeconds.key()), 3600); _preloadExecutor = Executors.newFixedThreadPool(8, new NamedThreadFactory("Template-Preloader")); - _swiftTemplateSyncExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("swift-template-sync-Executor")); - if (_s3Mgr.isS3Enabled()) { - _s3TemplateSyncExecutor = Executors - .newSingleThreadScheduledExecutor(new NamedThreadFactory( - "s3-template-sync")); - } else { - s_logger.info("S3 secondary storage synchronization is disabled."); + return true; + } + + protected TemplateManagerImpl() { + } + + @Override + public boolean templateIsDeleteable(VMTemplateHostVO templateHostRef) { + VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templateHostRef.getTemplateId()); + long templateId = template.getId(); + HostVO secondaryStorageHost = _hostDao.findById(templateHostRef.getHostId()); + long zoneId = secondaryStorageHost.getDataCenterId(); + DataCenterVO zone = _dcDao.findById(zoneId); + + // Check if there are VMs running in the template host ref's zone that + // use the template + List nonExpungedVms = _vmInstanceDao.listNonExpungedByZoneAndTemplate(zoneId, templateId); + + if (!nonExpungedVms.isEmpty()) { + s_logger.debug("Template " + template.getName() + " in zone " + zone.getName() + + " is not deleteable because there are non-expunged VMs deployed from this template."); + return false; + } + List userVmUsingIso = _userVmDao.listByIsoId(templateId); + // check if there is any VM using this ISO. + if (!userVmUsingIso.isEmpty()) { + s_logger.debug("ISO " + template.getName() + " in zone " + zone.getName() + " is not deleteable because it is attached to " + + userVmUsingIso.size() + " VMs"); + return false; + } + // Check if there are any snapshots for the template in the template + // host ref's zone + List volumes = _volumeDao.findByTemplateAndZone(templateId, zoneId); + for (VolumeVO volume : volumes) { + List snapshots = _snapshotDao.listByVolumeIdVersion(volume.getId(), "2.1"); + if (!snapshots.isEmpty()) { + s_logger.debug("Template " + template.getName() + " in zone " + zone.getName() + + " is not deleteable because there are 2.1 snapshots using this template."); + return false; + } } return true; } - - protected TemplateManagerImpl() { + + @Override + public boolean templateIsDeleteable(long templateId) { + List userVmUsingIso = _userVmJoinDao.listActiveByIsoId(templateId); + // check if there is any Vm using this ISO. We only need to check the + // case where templateId is an ISO since + // VM can be launched from ISO in secondary storage, while template will + // always be copied to + // primary storage before deploying VM. + if (!userVmUsingIso.isEmpty()) { + s_logger.debug("ISO " + templateId + " is not deleteable because it is attached to " + userVmUsingIso.size() + " VMs"); + return false; + } + + return true; } - @Override - public boolean templateIsDeleteable(VMTemplateHostVO templateHostRef) { - VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templateHostRef.getTemplateId()); - long templateId = template.getId(); - HostVO secondaryStorageHost = _hostDao.findById(templateHostRef.getHostId()); - long zoneId = secondaryStorageHost.getDataCenterId(); - DataCenterVO zone = _dcDao.findById(zoneId); - - // Check if there are VMs running in the template host ref's zone that use the template - List nonExpungedVms = _vmInstanceDao.listNonExpungedByZoneAndTemplate(zoneId, templateId); - - if (!nonExpungedVms.isEmpty()) { - s_logger.debug("Template " + template.getName() + " in zone " + zone.getName() + " is not deleteable because there are non-expunged VMs deployed from this template."); - return false; - } - List userVmUsingIso = _userVmDao.listByIsoId(templateId); - //check if there is any VM using this ISO. - if (!userVmUsingIso.isEmpty()) { - s_logger.debug("ISO " + template.getName() + " in zone " + zone.getName() + " is not deleteable because it is attached to " + userVmUsingIso.size() + " VMs"); - return false; - } - // Check if there are any snapshots for the template in the template host ref's zone - List volumes = _volumeDao.findByTemplateAndZone(templateId, zoneId); - for (VolumeVO volume : volumes) { - List snapshots = _snapshotDao.listByVolumeIdVersion(volume.getId(), "2.1"); - if (!snapshots.isEmpty()) { - s_logger.debug("Template " + template.getName() + " in zone " + zone.getName() + " is not deleteable because there are 2.1 snapshots using this template."); - return false; - } - } - - return true; - } - - @Override + @Override @ActionEvent(eventType = EventTypes.EVENT_ISO_DETACH, eventDescription = "detaching ISO", async = true) - public boolean detachIso(long vmId) { + public boolean detachIso(long vmId) { Account caller = UserContext.current().getCaller(); Long userId = UserContext.current().getCallerUserId(); - + // Verify input parameters UserVmVO vmInstanceCheck = _userVmDao.findById(vmId); if (vmInstanceCheck == null) { - throw new InvalidParameterValueException ("Unable to find a virtual machine with id " + vmId); + throw new InvalidParameterValueException("Unable to find a virtual machine with id " + vmId); } - + UserVm userVM = _userVmDao.findById(vmId); if (userVM == null) { throw new InvalidParameterValueException("Please specify a valid VM."); } - + _accountMgr.checkAccess(caller, null, true, userVM); Long isoId = userVM.getIsoId(); if (isoId == null) { throw new InvalidParameterValueException("The specified VM has no ISO attached to it."); } - UserContext.current().setEventDetails("Vm Id: " +vmId+ " ISO Id: "+isoId); - + UserContext.current().setEventDetails("Vm Id: " + vmId + " ISO Id: " + isoId); + State vmState = userVM.getState(); if (vmState != State.Running && vmState != State.Stopped) { - throw new InvalidParameterValueException("Please specify a VM that is either Stopped or Running."); + throw new InvalidParameterValueException("Please specify a VM that is either Stopped or Running."); } - boolean result = attachISOToVM(vmId, userId, isoId, false); //attach=false => detach - if (result){ - return result; - }else { - throw new CloudRuntimeException("Failed to detach iso"); - } - } - - @Override + boolean result = attachISOToVM(vmId, userId, isoId, false); // attach=false + // => detach + if (result) { + return result; + } else { + throw new CloudRuntimeException("Failed to detach iso"); + } + } + + @Override @ActionEvent(eventType = EventTypes.EVENT_ISO_ATTACH, eventDescription = "attaching ISO", async = true) - public boolean attachIso(long isoId, long vmId) { + public boolean attachIso(long isoId, long vmId) { Account caller = UserContext.current().getCaller(); Long userId = UserContext.current().getCallerUserId(); - - // Verify input parameters - UserVmVO vm = _userVmDao.findById(vmId); - if (vm == null) { + + // Verify input parameters + UserVmVO vm = _userVmDao.findById(vmId); + if (vm == null) { throw new InvalidParameterValueException("Unable to find a virtual machine with id " + vmId); } - - VMTemplateVO iso = _tmpltDao.findById(isoId); - if (iso == null || iso.getRemoved() != null) { + + VMTemplateVO iso = _tmpltDao.findById(isoId); + if (iso == null || iso.getRemoved() != null) { throw new InvalidParameterValueException("Unable to find an ISO with id " + isoId); - } - - //check permissions - //check if caller has access to VM and ISO - //and also check if the VM's owner has access to the ISO. - - _accountMgr.checkAccess(caller, null, false, iso, vm); - - Account vmOwner = _accountDao.findById(vm.getAccountId()); - _accountMgr.checkAccess(vmOwner, null, false, iso, vm); - + } + + // check permissions + // check if caller has access to VM and ISO + // and also check if the VM's owner has access to the ISO. + + _accountMgr.checkAccess(caller, null, false, iso, vm); + + Account vmOwner = _accountDao.findById(vm.getAccountId()); + _accountMgr.checkAccess(vmOwner, null, false, iso, vm); + State vmState = vm.getState(); if (vmState != State.Running && vmState != State.Stopped) { - throw new InvalidParameterValueException("Please specify a VM that is either Stopped or Running."); + throw new InvalidParameterValueException("Please specify a VM that is either Stopped or Running."); } - - if ("xen-pv-drv-iso".equals(iso.getDisplayText()) && vm.getHypervisorType() != Hypervisor.HypervisorType.XenServer){ - throw new InvalidParameterValueException("Cannot attach Xenserver PV drivers to incompatible hypervisor " + vm.getHypervisorType()); + + if ("xen-pv-drv-iso".equals(iso.getDisplayText()) && vm.getHypervisorType() != Hypervisor.HypervisorType.XenServer) { + throw new InvalidParameterValueException("Cannot attach Xenserver PV drivers to incompatible hypervisor " + vm.getHypervisorType()); } - - if("vmware-tools.iso".equals(iso.getName()) && vm.getHypervisorType() != Hypervisor.HypervisorType.VMware) { - throw new InvalidParameterValueException("Cannot attach VMware tools drivers to incompatible hypervisor " + vm.getHypervisorType()); + + if ("vmware-tools.iso".equals(iso.getName()) && vm.getHypervisorType() != Hypervisor.HypervisorType.VMware) { + throw new InvalidParameterValueException("Cannot attach VMware tools drivers to incompatible hypervisor " + vm.getHypervisorType()); } boolean result = attachISOToVM(vmId, userId, isoId, true); - if (result){ - return result; - }else { - throw new CloudRuntimeException("Failed to attach iso"); + if (result) { + return result; + } else { + throw new CloudRuntimeException("Failed to attach iso"); } - } - + } + + // for ISO, we need to consider whether to copy to cache storage or not if it is not on NFS, since our hypervisor resource always assumes that they are in NFS + @Override + public TemplateInfo prepareIso(long isoId, long dcId){ + TemplateInfo tmplt = this._tmplFactory.getTemplate(isoId, DataStoreRole.Image, dcId); + if (tmplt == null || tmplt.getFormat() != ImageFormat.ISO ) { + s_logger.warn("ISO: " + isoId + " does not exist in vm_template table"); + return null; + } + + if (tmplt.getDataStore() != null && !(tmplt.getDataStore().getTO() instanceof NfsTO)) { + // if it is s3, need to download into cache storage first + Scope destScope = new ZoneScope(dcId); + TemplateInfo cacheData = (TemplateInfo) cacheMgr.createCacheObject(tmplt, destScope); + if (cacheData == null) { + s_logger.error("Failed in copy iso from S3 to cache storage"); + return null; + } + return cacheData; + } else{ + return tmplt; + } + } + private boolean attachISOToVM(long vmId, long isoId, boolean attach) { UserVmVO vm = this._userVmDao.findById(vmId); @@ -1363,26 +1007,9 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, } else if (vm.getState() != State.Running) { return true; } - String isoPath; - VMTemplateVO tmplt = this._tmpltDao.findById(isoId); - if (tmplt == null) { - s_logger.warn("ISO: " + isoId + " does not exist"); - return false; - } - // Get the path of the ISO - Pair isoPathPair = null; - if (tmplt.getTemplateType() == TemplateType.PERHOST) { - isoPath = tmplt.getName(); - } else { - isoPathPair = getAbsoluteIsoPath(isoId, - vm.getDataCenterId()); - if (isoPathPair == null) { - s_logger.warn("Couldn't get absolute iso path"); - return false; - } else { - isoPath = isoPathPair.first(); - } - } + + // prepare ISO ready to mount on hypervisor resource level + TemplateInfo tmplt = prepareIso(isoId, vm.getDataCenterId()); String vmName = vm.getInstanceName(); @@ -1391,132 +1018,104 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, s_logger.warn("Host: " + vm.getHostId() + " does not exist"); return false; } - AttachIsoCommand cmd = new AttachIsoCommand(vmName, isoPath, attach); - if (isoPathPair != null) { - cmd.setStoreUrl(isoPathPair.second()); + + DataTO isoTO = tmplt.getTO(); + DiskTO disk = new DiskTO(isoTO, null, Volume.Type.ISO); + Command cmd = null; + if (attach) { + cmd = new AttachCommand(disk, vmName); + } else { + cmd = new DettachCommand(disk, vmName); } Answer a = _agentMgr.easySend(vm.getHostId(), cmd); - return (a != null && a.getResult()); } private boolean attachISOToVM(long vmId, long userId, long isoId, boolean attach) { - UserVmVO vm = _userVmDao.findById(vmId); - VMTemplateVO iso = _tmpltDao.findById(isoId); + UserVmVO vm = _userVmDao.findById(vmId); + VMTemplateVO iso = _tmpltDao.findById(isoId); boolean success = attachISOToVM(vmId, isoId, attach); - if ( success && attach) { - vm.setIsoId(iso.getId()); + if (success && attach) { + vm.setIsoId(iso.getId()); _userVmDao.update(vmId, vm); - } - if ( success && !attach ) { + } + if (success && !attach) { vm.setIsoId(null); _userVmDao.update(vmId, vm); - } + } return success; } - - @Override + + @Override @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_DELETE, eventDescription = "deleting template", async = true) public boolean deleteTemplate(DeleteTemplateCmd cmd) { Long templateId = cmd.getId(); Account caller = UserContext.current().getCaller(); - + VirtualMachineTemplate template = getTemplate(templateId); if (template == null) { throw new InvalidParameterValueException("unable to find template with id " + templateId); } - + _accountMgr.checkAccess(caller, AccessType.ModifyEntry, true, template); - - if (template.getFormat() == ImageFormat.ISO) { - throw new InvalidParameterValueException("Please specify a valid template."); - } - if (cmd.getZoneId() == null && _swiftMgr.isSwiftEnabled()) { - _swiftMgr.deleteTemplate(cmd); - } - if (cmd.getZoneId() == null && _s3Mgr.isS3Enabled()) { - _s3Mgr.deleteTemplate(cmd.getId(), caller.getAccountId()); + + if (template.getFormat() == ImageFormat.ISO) { + throw new InvalidParameterValueException("Please specify a valid template."); } - TemplateAdapter adapter = getAdapter(template.getHypervisorType()); - TemplateProfile profile = adapter.prepareDelete(cmd); - boolean result = adapter.delete(profile); - - if (result){ - if (cmd.getZoneId() == null - && (_swiftMgr.isSwiftEnabled() || _s3Mgr.isS3Enabled())) { - List templateZones = _tmpltZoneDao - .listByZoneTemplate(null, templateId); - if (templateZones != null) { - for (VMTemplateZoneVO templateZone : templateZones) { - _tmpltZoneDao.remove(templateZone.getId()); - } - } - } - return true; - }else{ - throw new CloudRuntimeException("Failed to delete template"); - } - } - - @Override + TemplateAdapter adapter = getAdapter(template.getHypervisorType()); + TemplateProfile profile = adapter.prepareDelete(cmd); + return adapter.delete(profile); + } + + @Override @ActionEvent(eventType = EventTypes.EVENT_ISO_DELETE, eventDescription = "deleting iso", async = true) public boolean deleteIso(DeleteIsoCmd cmd) { Long templateId = cmd.getId(); Account caller = UserContext.current().getCaller(); Long zoneId = cmd.getZoneId(); - - VirtualMachineTemplate template = getTemplate(templateId);; + + VirtualMachineTemplate template = getTemplate(templateId); + ; if (template == null) { throw new InvalidParameterValueException("unable to find iso with id " + templateId); } - + _accountMgr.checkAccess(caller, AccessType.ModifyEntry, true, template); - - if (template.getFormat() != ImageFormat.ISO) { - throw new InvalidParameterValueException("Please specify a valid iso."); - } - if (cmd.getZoneId() == null && _swiftMgr.isSwiftEnabled()) { - _swiftMgr.deleteIso(cmd); - } - if (cmd.getZoneId() == null && _s3Mgr.isS3Enabled()) { - _s3Mgr.deleteTemplate(caller.getAccountId(), templateId); + + if (template.getFormat() != ImageFormat.ISO) { + throw new InvalidParameterValueException("Please specify a valid iso."); } - if (zoneId != null && (_ssvmMgr.findSecondaryStorageHost(zoneId) == null)) { - throw new InvalidParameterValueException("Failed to find a secondary storage host in the specified zone."); - } - TemplateAdapter adapter = getAdapter(template.getHypervisorType()); - TemplateProfile profile = adapter.prepareDelete(cmd); + // check if there is any VM using this ISO. + if (!templateIsDeleteable(templateId)) { + throw new InvalidParameterValueException("Unable to delete iso, as it's used by other vms"); + } + + if (zoneId != null && (this._dataStoreMgr.getImageStore(zoneId) == null)) { + throw new InvalidParameterValueException("Failed to find a secondary storage store in the specified zone."); + } + TemplateAdapter adapter = getAdapter(template.getHypervisorType()); + TemplateProfile profile = adapter.prepareDelete(cmd); boolean result = adapter.delete(profile); if (result) { - if (cmd.getZoneId() == null - && (_swiftMgr.isSwiftEnabled() || _s3Mgr.isS3Enabled())) { - List templateZones = _tmpltZoneDao - .listByZoneTemplate(null, templateId); - if (templateZones != null) { - for (VMTemplateZoneVO templateZone : templateZones) { - _tmpltZoneDao.remove(templateZone.getId()); - } - } - } return true; } else { - throw new CloudRuntimeException("Failed to delete ISO"); - } - } - - @Override - public VirtualMachineTemplate getTemplate(long templateId) { - VMTemplateVO template = _tmpltDao.findById(templateId); - if (template != null && template.getRemoved() == null) { - return template; - } - - return null; - } - + throw new CloudRuntimeException("Failed to delete ISO"); + } + } + + @Override + public VirtualMachineTemplate getTemplate(long templateId) { + VMTemplateVO template = _tmpltDao.findById(templateId); + if (template != null && template.getRemoved() == null) { + return template; + } + + return null; + } + @Override public List listTemplatePermissions(BaseListTemplateOrIsoPermissionsCmd cmd) { Account caller = UserContext.current().getCaller(); @@ -1530,7 +1129,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, if (template == null) { throw new InvalidParameterValueException("unable to find " + cmd.getMediaType() + " with id " + id); } - + if (cmd instanceof ListTemplatePermissionsCmd) { if (template.getFormat().equals(ImageFormat.ISO)) { throw new InvalidParameterValueException("Please provide a valid template"); @@ -1562,7 +1161,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, return accountNames; } - + @DB @Override public boolean updateTemplateOrIsoPermissions(BaseUpdateTemplateOrIsoPermissionsCmd cmd) { @@ -1597,15 +1196,19 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, throw new InvalidParameterValueException("Please provide a valid iso"); } } - - //convert projectIds to accountNames + + // convert projectIds to accountNames if (projectIds != null) { + // CS-17842, initialize accountNames list + if (accountNames == null ){ + accountNames = new ArrayList(); + } for (Long projectId : projectIds) { Project project = _projectMgr.getProject(projectId); if (project == null) { throw new InvalidParameterValueException("Unable to find project by id " + projectId); } - + if (!_projectMgr.canAccessProjectAccount(caller, project.getProjectAccountId())) { throw new InvalidParameterValueException("Account " + caller + " can't access project id=" + projectId); } @@ -1626,22 +1229,27 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, } boolean isAdmin = _accountMgr.isAdmin(caller.getType()); - // check configuration parameter(allow.public.user.templates) value for the template owner - boolean allowPublicUserTemplates = Boolean.valueOf(_configServer.getConfigValue(Config.AllowPublicUserTemplates.key(), Config.ConfigurationParameterScope.account.toString(), template.getAccountId())); + // check configuration parameter(allow.public.user.templates) value for + // the template owner + boolean allowPublicUserTemplates = Boolean.valueOf(_configServer.getConfigValue(Config.AllowPublicUserTemplates.key(), + Config.ConfigurationParameterScope.account.toString(), template.getAccountId())); if (!isAdmin && !allowPublicUserTemplates && isPublic != null && isPublic) { throw new InvalidParameterValueException("Only private " + mediaType + "s can be created."); } if (accountNames != null) { - if ((operation == null) || (!operation.equalsIgnoreCase("add") && !operation.equalsIgnoreCase("remove") && !operation.equalsIgnoreCase("reset"))) { - throw new InvalidParameterValueException("Invalid operation on accounts, the operation must be either 'add' or 'remove' in order to modify launch permissions." - + " Given operation is: '" + operation + "'"); + if ((operation == null) + || (!operation.equalsIgnoreCase("add") && !operation.equalsIgnoreCase("remove") && !operation.equalsIgnoreCase("reset"))) { + throw new InvalidParameterValueException( + "Invalid operation on accounts, the operation must be either 'add' or 'remove' in order to modify launch permissions." + + " Given operation is: '" + operation + "'"); } } Long accountId = template.getAccountId(); if (accountId == null) { - // if there is no owner of the template then it's probably already a public template (or domain private template) so + // if there is no owner of the template then it's probably already a + // public template (or domain private template) so // publishing to individual users is irrelevant throw new InvalidParameterValueException("Update template permissions is an invalid operation on template " + template.getName()); } @@ -1655,14 +1263,22 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, if (isFeatured != null) { updatedTemplate.setFeatured(isFeatured.booleanValue()); } - - if (isExtractable != null && caller.getType() == Account.ACCOUNT_TYPE_ADMIN) {//Only ROOT admins allowed to change this powerful attribute - updatedTemplate.setExtractable(isExtractable.booleanValue()); - }else if (isExtractable != null && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { - throw new InvalidParameterValueException("Only ROOT admins are allowed to modify this attribute."); - } - _tmpltDao.update(template.getId(), updatedTemplate); + if (isExtractable != null && caller.getType() == Account.ACCOUNT_TYPE_ADMIN) {// Only + // ROOT + // admins + // allowed + // to + // change + // this + // powerful + // attribute + updatedTemplate.setExtractable(isExtractable.booleanValue()); + } else if (isExtractable != null && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + throw new InvalidParameterValueException("Only ROOT admins are allowed to modify this attribute."); + } + + _tmpltDao.update(template.getId(), updatedTemplate); Long domainId = caller.getDomainId(); if ("add".equalsIgnoreCase(operation)) { @@ -1671,7 +1287,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId); if (permittedAccount != null) { if (permittedAccount.getId() == caller.getId()) { - continue; // don't grant permission to the template owner, they implicitly have permission + continue; // don't grant permission to the template + // owner, they implicitly have permission } LaunchPermissionVO existingPermission = _launchPermissionDao.findByTemplateAndAccount(id, permittedAccount.getId()); if (existingPermission == null) { @@ -1680,8 +1297,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, } } else { txn.rollback(); - throw new InvalidParameterValueException("Unable to grant a launch permission to account " + accountName + ", account not found. " - + "No permissions updated, please verify the account names and retry."); + throw new InvalidParameterValueException("Unable to grant a launch permission to account " + accountName + + ", account not found. " + "No permissions updated, please verify the account names and retry."); } } txn.commit(); @@ -1705,21 +1322,15 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, } return true; } - - + private String getRandomPrivateTemplateName() { return UUID.randomUUID().toString(); } - - - - @Override @DB @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "creating template", async = true) - public VirtualMachineTemplate createPrivateTemplate(CreateTemplateCmd command) - throws CloudRuntimeException { + public VirtualMachineTemplate createPrivateTemplate(CreateTemplateCmd command) throws CloudRuntimeException { Long userId = UserContext.current().getCallerUserId(); if (userId == null) { userId = User.UID_SYSTEM; @@ -1733,34 +1344,31 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, VolumeVO volume = null; try { - TemplateInfo tmplInfo = this.tmplFactory.getTemplate(templateId); - ZoneScope scope = null; + TemplateInfo tmplInfo = this._tmplFactory.getTemplate(templateId, DataStoreRole.Image); Long zoneId = null; if (snapshotId != null) { snapshot = _snapshotDao.findById(snapshotId); zoneId = snapshot.getDataCenterId(); - } else if (volumeId != null) { volume = _volumeDao.findById(volumeId); zoneId = volume.getDataCenterId(); } - scope = new ZoneScope(zoneId); - List store = this.dataStoreMgr.getImageStores(scope); + ZoneScope scope = new ZoneScope(zoneId); + List store = this._dataStoreMgr.getImageStoresByScope(scope); if (store.size() > 1) { throw new CloudRuntimeException("muliple image data store, don't know which one to use"); } - AsyncCallFuture future = null; + AsyncCallFuture future = null; if (snapshotId != null) { - SnapshotInfo snapInfo = this.snapshotFactory.getSnapshot(snapshotId); - future = this.imageSvr.createTemplateFromSnapshotAsync(snapInfo, tmplInfo, store.get(0)); + SnapshotInfo snapInfo = this._snapshotFactory.getSnapshot(snapshotId, DataStoreRole.Image); + future = this._tmpltSvr.createTemplateFromSnapshotAsync(snapInfo, tmplInfo, store.get(0)); } else if (volumeId != null) { - VolumeInfo volInfo = this.volFactory.getVolume(volumeId); - future = this.imageSvr.createTemplateFromVolumeAsync(volInfo, tmplInfo, store.get(0)); + VolumeInfo volInfo = this._volFactory.getVolume(volumeId); + future = this._tmpltSvr.createTemplateFromVolumeAsync(volInfo, tmplInfo, store.get(0)); } else { - throw new CloudRuntimeException( - "Creating private Template need to specify snapshotId or volumeId"); + throw new CloudRuntimeException("Creating private Template need to specify snapshotId or volumeId"); } - + CommandResult result = null; try { result = future.get(); @@ -1769,15 +1377,13 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, s_logger.debug("Failed to create template" + result.getResult()); throw new CloudRuntimeException("Failed to create template" + result.getResult()); } - + + VMTemplateZoneVO templateZone = new VMTemplateZoneVO(zoneId, templateId, new Date()); + this._tmpltZoneDao.persist(templateZone); + privateTemplate = this._tmpltDao.findById(templateId); - UsageEventVO usageEvent = new UsageEventVO( - EventTypes.EVENT_TEMPLATE_CREATE, - privateTemplate.getAccountId(), - zoneId, - privateTemplate.getId(), privateTemplate.getName(), - null, privateTemplate.getSourceTemplateId(), - privateTemplate.getSize()); + UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_TEMPLATE_CREATE, privateTemplate.getAccountId(), zoneId, + privateTemplate.getId(), privateTemplate.getName(), null, privateTemplate.getSourceTemplateId(), privateTemplate.getSize()); _usageEventDao.persist(usageEvent); } catch (InterruptedException e) { s_logger.debug("Failed to create template", e); @@ -1797,14 +1403,22 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, if (privateTemplate == null) { Transaction txn = Transaction.currentTxn(); txn.start(); + // template_store_ref entries should have been removed using our + // DataObject.processEvent command in case of failure, but clean + // it up here to avoid + // some leftovers which will cause removing template from + // vm_template table fail. + this._tmplStoreDao.deletePrimaryRecordsForTemplate(templateId); + // Remove the template_zone_ref record + this._tmpltZoneDao.deletePrimaryRecordsForTemplate(templateId); // Remove the template record this._tmpltDao.expunge(templateId); // decrement resource count if (accountId != null) { _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.template); - _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.secondary_storage, - new Long(volume != null ? volume.getSize() : snapshot.getSize())); + _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.secondary_storage, new Long(volume != null ? volume.getSize() + : snapshot.getSize())); } txn.commit(); } @@ -1818,14 +1432,13 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, } private static boolean isAdmin(short accountType) { - return ((accountType == Account.ACCOUNT_TYPE_ADMIN) - || (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) + return ((accountType == Account.ACCOUNT_TYPE_ADMIN) || (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) || (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)); } + @Override @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "creating template", create = true) - public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd, - Account templateOwner) throws ResourceAllocationException { + public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd, Account templateOwner) throws ResourceAllocationException { Long userId = UserContext.current().getCallerUserId(); Account caller = UserContext.current().getCaller(); @@ -1835,14 +1448,12 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, String name = cmd.getTemplateName(); if ((name == null) || (name.length() > 32)) { - throw new InvalidParameterValueException( - "Template name cannot be null and should be less than 32 characters"); + throw new InvalidParameterValueException("Template name cannot be null and should be less than 32 characters"); } if (cmd.getTemplateTag() != null) { if (!_accountService.isRootAdmin(caller.getType())) { - throw new PermissionDeniedException( - "Parameter templatetag can only be specified by a Root Admin, permission denied"); + throw new PermissionDeniedException("Parameter templatetag can only be specified by a Root Admin, permission denied"); } } @@ -1853,33 +1464,26 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, Boolean isPublic = cmd.isPublic(); Boolean featured = cmd.isFeatured(); int bitsValue = ((bits == null) ? 64 : bits.intValue()); - boolean requiresHvmValue = ((requiresHvm == null) ? true : requiresHvm - .booleanValue()); - boolean passwordEnabledValue = ((passwordEnabled == null) ? false - : passwordEnabled.booleanValue()); + boolean requiresHvmValue = ((requiresHvm == null) ? true : requiresHvm.booleanValue()); + boolean passwordEnabledValue = ((passwordEnabled == null) ? false : passwordEnabled.booleanValue()); if (isPublic == null) { isPublic = Boolean.FALSE; } // check whether template owner can create public templates - boolean allowPublicUserTemplates = Boolean.parseBoolean(_configServer.getConfigValue(Config.AllowPublicUserTemplates.key(), Config.ConfigurationParameterScope.account.toString(), templateOwner.getId())); + boolean allowPublicUserTemplates = Boolean.parseBoolean(_configServer.getConfigValue(Config.AllowPublicUserTemplates.key(), + Config.ConfigurationParameterScope.account.toString(), templateOwner.getId())); if (!isAdmin && !allowPublicUserTemplates && isPublic) { - throw new PermissionDeniedException("Failed to create template " - + name + ", only private templates can be created."); + throw new PermissionDeniedException("Failed to create template " + name + ", only private templates can be created."); } Long volumeId = cmd.getVolumeId(); Long snapshotId = cmd.getSnapshotId(); if ((volumeId == null) && (snapshotId == null)) { - throw new InvalidParameterValueException( - "Failed to create private template record, neither volume ID nor snapshot ID were specified."); + throw new InvalidParameterValueException("Failed to create private template record, neither volume ID nor snapshot ID were specified."); } if ((volumeId != null) && (snapshotId != null)) { - throw new InvalidParameterValueException( - "Failed to create private template record, please specify only one of volume ID (" - + volumeId - + ") and snapshot ID (" - + snapshotId - + ")"); + throw new InvalidParameterValueException("Failed to create private template record, please specify only one of volume ID (" + volumeId + + ") and snapshot ID (" + snapshotId + ")"); } HypervisorType hyperType; @@ -1889,9 +1493,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, if (volumeId != null) { // create template from volume volume = this._volumeDao.findById(volumeId); if (volume == null) { - throw new InvalidParameterValueException( - "Failed to create private template record, unable to find volume " - + volumeId); + throw new InvalidParameterValueException("Failed to create private template record, unable to find volume " + volumeId); } // check permissions _accountMgr.checkAccess(caller, null, true, volume); @@ -1899,9 +1501,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, // If private template is created from Volume, check that the volume // will not be active when the private template is // created - if (!this.volumeMgr.volumeInactive(volume)) { - String msg = "Unable to create private template for volume: " - + volume.getName() + if (!this._volumeMgr.volumeInactive(volume)) { + String msg = "Unable to create private template for volume: " + volume.getName() + "; volume is attached to a non-stopped VM, please stop the VM first"; if (s_logger.isInfoEnabled()) { s_logger.info(msg); @@ -1912,21 +1513,17 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, } else { // create template from snapshot snapshot = _snapshotDao.findById(snapshotId); if (snapshot == null) { - throw new InvalidParameterValueException( - "Failed to create private template record, unable to find snapshot " - + snapshotId); + throw new InvalidParameterValueException("Failed to create private template record, unable to find snapshot " + snapshotId); } volume = this._volumeDao.findById(snapshot.getVolumeId()); - VolumeVO snapshotVolume = this._volumeDao - .findByIdIncludingRemoved(snapshot.getVolumeId()); + VolumeVO snapshotVolume = this._volumeDao.findByIdIncludingRemoved(snapshot.getVolumeId()); // check permissions _accountMgr.checkAccess(caller, null, true, snapshot); if (snapshot.getState() != Snapshot.State.BackedUp) { - throw new InvalidParameterValueException("Snapshot id=" - + snapshotId + " is not in " + Snapshot.State.BackedUp + throw new InvalidParameterValueException("Snapshot id=" + snapshotId + " is not in " + Snapshot.State.BackedUp + " state yet and can't be used for template creation"); } @@ -1952,30 +1549,25 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, Long guestOSId = cmd.getOsTypeId(); GuestOSVO guestOS = this._guestOSDao.findById(guestOSId); if (guestOS == null) { - throw new InvalidParameterValueException("GuestOS with ID: " - + guestOSId + " does not exist."); + throw new InvalidParameterValueException("GuestOS with ID: " + guestOSId + " does not exist."); } - String uniqueName = Long.valueOf((userId == null) ? 1 : userId) - .toString() - + UUID.nameUUIDFromBytes(name.getBytes()).toString(); + String uniqueName = Long.valueOf((userId == null) ? 1 : userId).toString() + UUID.nameUUIDFromBytes(name.getBytes()).toString(); Long nextTemplateId = this._tmpltDao.getNextInSequence(Long.class, "id"); String description = cmd.getDisplayText(); boolean isExtractable = false; Long sourceTemplateId = null; if (volume != null) { - VMTemplateVO template = ApiDBUtils.findTemplateById(volume - .getTemplateId()); - isExtractable = template != null - && template.isExtractable() - && template.getTemplateType() != Storage.TemplateType.SYSTEM; + VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId()); + isExtractable = template != null && template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM; if (template != null) { sourceTemplateId = template.getId(); - } else if (volume.getVolumeType() == Volume.Type.ROOT) { // vm created out + } else if (volume.getVolumeType() == Volume.Type.ROOT) { // vm + // created + // out // of blank // template - UserVm userVm = ApiDBUtils.findUserVmById(volume - .getInstanceId()); + UserVm userVm = ApiDBUtils.findUserVmById(volume.getInstanceId()); sourceTemplateId = userVm.getIsoId(); } } @@ -1985,19 +1577,15 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, s_logger.debug("Adding template tag: " + templateTag); } } - privateTemplate = new VMTemplateVO(nextTemplateId, uniqueName, name, - ImageFormat.RAW, isPublic, featured, isExtractable, - TemplateType.USER, null, null, requiresHvmValue, bitsValue, - templateOwner.getId(), null, description, passwordEnabledValue, - guestOS.getId(), true, hyperType, templateTag, cmd.getDetails()); + privateTemplate = new VMTemplateVO(nextTemplateId, uniqueName, name, ImageFormat.RAW, isPublic, featured, isExtractable, TemplateType.USER, + null, null, requiresHvmValue, bitsValue, templateOwner.getId(), null, description, passwordEnabledValue, guestOS.getId(), true, + hyperType, templateTag, cmd.getDetails()); if (sourceTemplateId != null) { if (s_logger.isDebugEnabled()) { - s_logger.debug("This template is getting created from other template, setting source template Id to: " - + sourceTemplateId); + s_logger.debug("This template is getting created from other template, setting source template Id to: " + sourceTemplateId); } } privateTemplate.setSourceTemplateId(sourceTemplateId); - privateTemplate.setImageDataStoreId(1); VMTemplateVO template = this._tmpltDao.persist(privateTemplate); // Increment the number of templates @@ -2018,159 +1606,163 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, } } - - @Override - public Pair getAbsoluteIsoPath(long templateId, - long dataCenterId) { - String isoPath = null; - List storageHosts = _resourceMgr.listAllHostsInOneZoneByType( - Host.Type.SecondaryStorage, dataCenterId); - if (storageHosts != null) { - for (HostVO storageHost : storageHosts) { - List templateHostVOs = this._tmpltHostDao - .listByTemplateHostStatus( - templateId, - storageHost.getId(), - VMTemplateStorageResourceAssoc.Status.DOWNLOADED); - if (templateHostVOs != null && !templateHostVOs.isEmpty()) { - VMTemplateHostVO tmpHostVO = templateHostVOs.get(0); - isoPath = storageHost.getStorageUrl() + "/" - + tmpHostVO.getInstallPath(); - return new Pair(isoPath, - storageHost.getStorageUrl()); - } - } + @Override + public Pair getAbsoluteIsoPath(long templateId, long dataCenterId) { + TemplateDataStoreVO templateStoreRef = this._tmplStoreDao.findByTemplateZoneDownloadStatus(templateId, dataCenterId, + VMTemplateStorageResourceAssoc.Status.DOWNLOADED); + if (templateStoreRef == null) { + throw new CloudRuntimeException("Template " + templateId + " has not been completely downloaded to zone " + dataCenterId); } - s_logger.warn("Unable to find secondary storage in zone id=" - + dataCenterId); - return null; + DataStore store = this._dataStoreMgr.getDataStore(templateStoreRef.getDataStoreId(), DataStoreRole.Image); + String isoPath = store.getUri() + "/" + templateStoreRef.getInstallPath(); + return new Pair(isoPath, store.getUri()); } @Override public String getSecondaryStorageURL(long zoneId) { - // Determine the secondary storage URL - HostVO secondaryStorageHost = getSecondaryStorageHost(zoneId); - - if (secondaryStorageHost == null) { + DataStore secStore = this._dataStoreMgr.getImageStore(zoneId); + if (secStore == null) { return null; } - return secondaryStorageHost.getStorageUrl(); + return secStore.getUri(); } + // get the image store where a template in a given zone is downloaded to, + // just pick one is enough. @Override - public HostVO getSecondaryStorageHost(long zoneId, long tmpltId) { - List hosts = _ssvmMgr - .listSecondaryStorageHostsInOneZone(zoneId); - if (hosts == null || hosts.size() == 0) { - return null; - } - for (HostVO host : hosts) { - VMTemplateHostVO tmpltHost = this._tmpltHostDao.findByHostTemplate( - host.getId(), tmpltId); - if (tmpltHost != null - && !tmpltHost.getDestroyed() - && tmpltHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { - return host; - } + public DataStore getImageStore(long zoneId, long tmpltId) { + TemplateDataStoreVO tmpltStore = this._tmplStoreDao.findByTemplateZoneDownloadStatus(tmpltId, zoneId, + VMTemplateStorageResourceAssoc.Status.DOWNLOADED); + if (tmpltStore != null) { + return this._dataStoreMgr.getDataStore(tmpltStore.getDataStoreId(), DataStoreRole.Image); } + return null; } @Override - public VMTemplateHostVO getTemplateHostRef(long zoneId, long tmpltId, - boolean readyOnly) { - List hosts = _ssvmMgr - .listSecondaryStorageHostsInOneZone(zoneId); - if (hosts == null || hosts.size() == 0) { + public Long getTemplateSize(long templateId, long zoneId) { + TemplateDataStoreVO templateStoreRef = this._tmplStoreDao.findByTemplateZoneDownloadStatus(templateId, zoneId, + VMTemplateStorageResourceAssoc.Status.DOWNLOADED); + if (templateStoreRef == null) { + throw new CloudRuntimeException("Template " + templateId + " has not been completely downloaded to zone " + zoneId); + } + return templateStoreRef.getSize(); + + } + + // find image store where this template is located + @Override + public List getImageStoreByTemplate(long templateId, Long zoneId) { + // find all eligible image stores for this zone scope + List imageStores = this._dataStoreMgr.getImageStoresByScope(new ZoneScope(zoneId)); + if (imageStores == null || imageStores.size() == 0) { return null; } - VMTemplateHostVO inProgress = null; - VMTemplateHostVO other = null; - for (HostVO host : hosts) { - VMTemplateHostVO tmpltHost = this._tmpltHostDao.findByHostTemplate( - host.getId(), tmpltId); - if (tmpltHost != null && !tmpltHost.getDestroyed()) { - if (tmpltHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { - return tmpltHost; - } else if (tmpltHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS) { - inProgress = tmpltHost; - } else { - other = tmpltHost; - } + List stores = new ArrayList(); + for (DataStore store : imageStores) { + // check if the template is stored there + List storeTmpl = this._tmplStoreDao.listByTemplateStore(templateId, store.getId()); + if (storeTmpl != null && storeTmpl.size() > 0) { + stores.add(store); } } - if (inProgress != null) { - return inProgress; - } - return other; + return stores; } @Override - public HostVO getSecondaryStorageHost(long zoneId) { - List hosts = _ssvmMgr - .listSecondaryStorageHostsInOneZone(zoneId); - if (hosts == null || hosts.size() == 0) { - hosts = _ssvmMgr.listLocalSecondaryStorageHostsInOneZone(zoneId); - if (hosts.isEmpty()) { - return null; - } - } - - int size = hosts.size(); - Random rn = new Random(); - int index = rn.nextInt(size); - return hosts.get(index); + public VMTemplateVO updateTemplate(UpdateIsoCmd cmd) { + return updateTemplateOrIso(cmd); } @Override - public List getSecondaryStorageHosts(long zoneId) { - List hosts = _ssvmMgr - .listSecondaryStorageHostsInOneZone(zoneId); - if (hosts == null || hosts.size() == 0) { - hosts = _ssvmMgr.listLocalSecondaryStorageHostsInOneZone(zoneId); - if (hosts.isEmpty()) { - return new ArrayList(); - } - } - return hosts; - } - - @Override - public Long getTemplateSize(long templateId, long zoneId) { - SearchCriteria sc = HostTemplateStatesSearch.create(); - sc.setParameters("id", templateId); - sc.setParameters( - "state", - com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED); - sc.setJoinParameters("host", "dcId", zoneId); - List tsvs = _tmpltSwiftDao - .listByTemplateId(templateId); - Long size = null; - if (tsvs != null && tsvs.size() > 0) { - size = tsvs.get(0).getSize(); - } - - if (size == null && _s3Mgr.isS3Enabled()) { - VMTemplateS3VO vmTemplateS3VO = _vmS3TemplateDao - .findOneByTemplateId(templateId); - if (vmTemplateS3VO != null) { - size = vmTemplateS3VO.getSize(); - } - } - - if (size == null) { - List sss = this.templateHostDao.search(sc, null); - if (sss == null || sss.size() == 0) { - throw new CloudRuntimeException("Template " - + templateId - + " has not been completely downloaded to zone " - + zoneId); - } - size = sss.get(0).getSize(); - } - return size; + public VMTemplateVO updateTemplate(UpdateTemplateCmd cmd) { + return updateTemplateOrIso(cmd); } + private VMTemplateVO updateTemplateOrIso(BaseUpdateTemplateOrIsoCmd cmd) { + Long id = cmd.getId(); + String name = cmd.getTemplateName(); + String displayText = cmd.getDisplayText(); + String format = cmd.getFormat(); + Long guestOSId = cmd.getOsTypeId(); + Boolean passwordEnabled = cmd.isPasswordEnabled(); + Boolean bootable = cmd.isBootable(); + Integer sortKey = cmd.getSortKey(); + Account account = UserContext.current().getCaller(); + + // verify that template exists + VMTemplateVO template = _tmpltDao.findById(id); + if (template == null || template.getRemoved() != null) { + InvalidParameterValueException ex = new InvalidParameterValueException("unable to find template/iso with specified id"); + ex.addProxyObject(String.valueOf(id), "templateId"); + throw ex; + } + + // Don't allow to modify system template + if (id == Long.valueOf(1)) { + InvalidParameterValueException ex = new InvalidParameterValueException("Unable to update template/iso of specified id"); + ex.addProxyObject(String.valueOf(id), "templateId"); + throw ex; + } + + // do a permission check + _accountMgr.checkAccess(account, AccessType.ModifyEntry, true, template); + + boolean updateNeeded = !(name == null && displayText == null && format == null && guestOSId == null && passwordEnabled == null + && bootable == null && sortKey == null); + if (!updateNeeded) { + return template; + } + + template = _tmpltDao.createForUpdate(id); + + if (name != null) { + template.setName(name); + } + + if (displayText != null) { + template.setDisplayText(displayText); + } + + if (sortKey != null) { + template.setSortKey(sortKey); + } + + ImageFormat imageFormat = null; + if (format != null) { + try { + imageFormat = ImageFormat.valueOf(format.toUpperCase()); + } catch (IllegalArgumentException e) { + throw new InvalidParameterValueException("Image format: " + format + " is incorrect. Supported formats are " + + EnumUtils.listValues(ImageFormat.values())); + } + + template.setFormat(imageFormat); + } + + if (guestOSId != null) { + GuestOSVO guestOS = _guestOSDao.findById(guestOSId); + + if (guestOS == null) { + throw new InvalidParameterValueException("Please specify a valid guest OS ID."); + } else { + template.setGuestOSId(guestOSId); + } + } + + if (passwordEnabled != null) { + template.setEnablePassword(passwordEnabled); + } + + if (bootable != null) { + template.setBootable(bootable); + } + + _tmpltDao.update(id, template); + + return _tmpltDao.findById(id); + } } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 8147b36b31c..7ae96da8b64 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -32,6 +32,9 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.commons.codec.binary.Base64; +import org.apache.log4j.Logger; + import com.cloud.server.ConfigurationServer; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; @@ -58,10 +61,11 @@ import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd; import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd; import org.apache.cloudstack.engine.cloud.entity.api.VirtualMachineEntity; import org.apache.cloudstack.engine.service.api.OrchestrationService; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.commons.codec.binary.Base64; -import org.apache.log4j.Logger; +import org.apache.cloudstack.storage.to.TemplateObjectTO; import com.cloud.agent.AgentManager; import com.cloud.agent.AgentManager.OnError; @@ -79,9 +83,9 @@ import com.cloud.agent.api.UnPlugNicAnswer; import com.cloud.agent.api.UnPlugNicCommand; import com.cloud.agent.api.VmDiskStatsEntry; import com.cloud.agent.api.VmStatsEntry; +import com.cloud.agent.api.to.DiskTO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; -import com.cloud.agent.api.to.VolumeTO; import com.cloud.agent.manager.Commands; import com.cloud.alert.AlertManager; import com.cloud.api.ApiDBUtils; @@ -181,7 +185,6 @@ import com.cloud.storage.GuestOSVO; import com.cloud.storage.SnapshotVO; import com.cloud.storage.Storage; import com.cloud.storage.Storage.ImageFormat; -import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; @@ -197,10 +200,8 @@ import com.cloud.storage.dao.GuestOSDao; import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplateDetailsDao; -import com.cloud.storage.dao.VMTemplateHostDao; import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.storage.dao.VolumeDao; -import com.cloud.storage.dao.VolumeHostDao; import com.cloud.storage.snapshot.SnapshotManager; import com.cloud.tags.dao.ResourceTagDao; import com.cloud.template.TemplateManager; @@ -278,8 +279,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use @Inject protected VMTemplateDetailsDao _templateDetailsDao = null; @Inject - protected VMTemplateHostDao _templateHostDao = null; - @Inject protected VMTemplateZoneDao _templateZoneDao = null; @Inject protected DomainDao _domainDao = null; @@ -387,8 +386,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use @Inject protected ItWorkDao _workDao; @Inject - protected VolumeHostDao _volumeHostDao; - @Inject ResourceTagDao _resourceTagDao; @Inject PhysicalNetworkDao _physicalNetworkDao; @@ -416,6 +413,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use @Inject AffinityGroupDao _affinityGroupDao; @Inject + TemplateDataFactory templateFactory; + @Inject DedicatedResourceDao _dedicatedDao; @Inject ConfigurationServer _configServer; @@ -1095,7 +1094,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } } - + @Override public HashMap> getVmDiskStatistics(long hostId, String hostName, List vmIds) throws CloudRuntimeException { HashMap> vmDiskStatsById = new HashMap>(); @@ -1227,7 +1226,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use // Decrement CPU and Memory count accordingly. if (newCpu > currentCpu) { _resourceLimitMgr.decrementResourceCount(caller.getAccountId(), ResourceType.cpu, new Long (newCpu - currentCpu)); - } + } if (newMemory > currentMemory) { _resourceLimitMgr.decrementResourceCount(caller.getAccountId(), ResourceType.memory, new Long (newMemory - currentMemory)); } @@ -1631,7 +1630,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use .findUsableVolumesForInstance(vm.getId()); for (VolumeVO volume : volumesForThisVm) { if (volume.getState() != Volume.State.Destroy) { - this.volumeMgr.destroyVolume(volume); + volumeMgr.destroyVolume(volume); } } String msg = "Failed to deploy Vm with Id: " + vmId + ", on Host with Id: " + hostId; @@ -2451,7 +2450,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use // check if account/domain is with in resource limits to create a new vm boolean isIso = Storage.ImageFormat.ISO == template.getFormat(); - long size = _templateHostDao.findByTemplateId(template.getId()).getSize(); + long size = _templateDao.findById(template.getId()).getSize(); if (diskOfferingId != null) { size += _diskOfferingDao.findById(diskOfferingId).getDiskSize(); } @@ -2889,52 +2888,30 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use vm.setDetails(details); if (vm.getIsoId() != null) { - String isoPath = null; - - VirtualMachineTemplate template = _templateDao.findById(vm - .getIsoId()); - if (template == null || template.getFormat() != ImageFormat.ISO) { - throw new CloudRuntimeException( - "Can not find ISO in vm_template table for id " - + vm.getIsoId()); + TemplateInfo template = this.templateMgr.prepareIso(vm.getIsoId(), vm.getDataCenterId()); + if (template == null){ + s_logger.error("Failed to prepare ISO on secondary or cache storage"); + throw new CloudRuntimeException("Failed to prepare ISO on secondary or cache storage"); } - - Pair isoPathPair = this.templateMgr.getAbsoluteIsoPath( - template.getId(), vm.getDataCenterId()); - - if (template.getTemplateType() == TemplateType.PERHOST) { - isoPath = template.getName(); - } else { - if (isoPathPair == null) { - s_logger.warn("Couldn't get absolute iso path"); - return false; - } else { - isoPath = isoPathPair.first(); - } - } - if (template.isBootable()) { profile.setBootLoaderType(BootloaderType.CD); } + GuestOSVO guestOS = _guestOSDao.findById(template.getGuestOSId()); String displayName = null; if (guestOS != null) { displayName = guestOS.getDisplayName(); } - VolumeTO iso = new VolumeTO(profile.getId(), Volume.Type.ISO, - StoragePoolType.ISO, null, template.getName(), null, - isoPath, 0, null, displayName); - iso.setDeviceId(3); - profile.addDisk(iso); + TemplateObjectTO iso = (TemplateObjectTO)template.getTO(); + iso.setGuestOsType(displayName); + DiskTO disk = new DiskTO(iso, 3L, Volume.Type.ISO); + profile.addDisk(disk); } else { - VirtualMachineTemplate template = profile.getTemplate(); - /* create a iso placeholder */ - VolumeTO iso = new VolumeTO(profile.getId(), Volume.Type.ISO, - StoragePoolType.ISO, null, template.getName(), null, null, - 0, null); - iso.setDeviceId(3); - profile.addDisk(iso); + TemplateObjectTO iso = new TemplateObjectTO(); + iso.setFormat(ImageFormat.ISO); + DiskTO disk = new DiskTO(iso, 3L, Volume.Type.ISO); + profile.addDisk(disk); } return true; @@ -3415,7 +3392,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use List vmNames = new ArrayList(); vmNames.add(userVm.getInstanceName()); HostVO host = _hostDao.findById(hostId); - + GetVmDiskStatsAnswer diskStatsAnswer = null; try { diskStatsAnswer = (GetVmDiskStatsAnswer) _agentMgr.easySend(hostId, new GetVmDiskStatsCommand(vmNames, host.getGuid(), host.getName())); @@ -3433,39 +3410,39 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use txn.start(); HashMap> vmDiskStatsByName = diskStatsAnswer.getVmDiskStatsMap(); List vmDiskStats = vmDiskStatsByName.get(userVm.getInstanceName()); - + if (vmDiskStats == null) return; - + for (VmDiskStatsEntry vmDiskStat:vmDiskStats) { SearchCriteria sc_volume = _volsDao.createSearchCriteria(); sc_volume.addAnd("path", SearchCriteria.Op.EQ, vmDiskStat.getPath()); VolumeVO volume = _volsDao.search(sc_volume, null).get(0); VmDiskStatisticsVO previousVmDiskStats = _vmDiskStatsDao.findBy(userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), volume.getId()); VmDiskStatisticsVO vmDiskStat_lock = _vmDiskStatsDao.lock(userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), volume.getId()); - + if ((vmDiskStat.getIORead() == 0) && (vmDiskStat.getIOWrite() == 0) && (vmDiskStat.getBytesRead() == 0) && (vmDiskStat.getBytesWrite() == 0)) { s_logger.debug("Read/Write of IO and Bytes are both 0. Not updating vm_disk_statistics"); continue; } - + if (vmDiskStat_lock == null) { s_logger.warn("unable to find vm disk stats from host for account: " + userVm.getAccountId() + " with vmId: " + userVm.getId()+ " and volumeId:" + volume.getId()); continue; } - + if (previousVmDiskStats != null && ((previousVmDiskStats.getCurrentIORead() != vmDiskStat_lock.getCurrentIORead()) || ((previousVmDiskStats.getCurrentIOWrite() != vmDiskStat_lock.getCurrentIOWrite()) || (previousVmDiskStats.getCurrentBytesRead() != vmDiskStat_lock.getCurrentBytesRead()) || (previousVmDiskStats.getCurrentBytesWrite() != vmDiskStat_lock.getCurrentBytesWrite())))) { s_logger.debug("vm disk stats changed from the time GetVmDiskStatsCommand was sent. " + - "Ignoring current answer. Host: " + host.getName() + " . VM: " + vmDiskStat.getVmName() + + "Ignoring current answer. Host: " + host.getName() + " . VM: " + vmDiskStat.getVmName() + " IO Read: " + vmDiskStat.getIORead() + " IO Write: " + vmDiskStat.getIOWrite() + " Bytes Read: " + vmDiskStat.getBytesRead() + " Bytes Write: " + vmDiskStat.getBytesWrite()); continue; } - + if (vmDiskStat_lock.getCurrentIORead() > vmDiskStat.getIORead()) { if (s_logger.isDebugEnabled()) { s_logger.debug("Read # of IO that's less than the last one. " + @@ -3502,15 +3479,15 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use vmDiskStat_lock.setNetBytesWrite(vmDiskStat_lock.getNetBytesWrite() + vmDiskStat_lock.getCurrentBytesWrite()); } vmDiskStat_lock.setCurrentBytesWrite(vmDiskStat.getBytesWrite()); - + if (! _dailyOrHourly) { - //update agg bytes + //update agg bytes vmDiskStat_lock.setAggIORead(vmDiskStat_lock.getNetIORead() + vmDiskStat_lock.getCurrentIORead()); vmDiskStat_lock.setAggIOWrite(vmDiskStat_lock.getNetIOWrite() + vmDiskStat_lock.getCurrentIOWrite()); vmDiskStat_lock.setAggBytesRead(vmDiskStat_lock.getNetBytesRead() + vmDiskStat_lock.getCurrentBytesRead()); vmDiskStat_lock.setAggBytesWrite(vmDiskStat_lock.getNetBytesWrite() + vmDiskStat_lock.getCurrentBytesWrite()); } - + _vmDiskStatsDao.update(vmDiskStat_lock.getId(), vmDiskStat_lock); } txn.commit(); @@ -4584,10 +4561,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use vm.setTemplateId(newTemplateId); _vmDao.update(vmId, vm); } else { - newVol = volumeMgr.allocateDuplicateVolume(root, newTemplateId); - vm.setGuestOSId(template.getGuestOSId()); - vm.setTemplateId(newTemplateId); - _vmDao.update(vmId, vm); + newVol = volumeMgr.allocateDuplicateVolume(root, newTemplateId); + vm.setGuestOSId(template.getGuestOSId()); + vm.setTemplateId(newTemplateId); + _vmDao.update(vmId, vm); } } else { newVol = volumeMgr.allocateDuplicateVolume(root, null); @@ -4598,7 +4575,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use /* Detach and destory the old root volume */ _volsDao.detachVolume(root.getId()); - this.volumeMgr.destroyVolume(root); + volumeMgr.destroyVolume(root); if (template.getEnablePassword()) { String password = generateRandomPassword(); diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index ef35673295e..5a28e6759ee 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -1173,7 +1173,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } vmGuru.prepareStop(profile); - StopCommand stop = new StopCommand(vm, _mgmtServer.getExecuteInSequence()); boolean stopped = false; StopAnswer answer = null; @@ -2591,7 +2590,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } @Override - public void processConnect(HostVO agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException { + public void processConnect(Host agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException { if (!(cmd instanceof StartupRoutingCommand)) { return; } @@ -2834,7 +2833,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac VirtualMachineGuru vmGuru = getVmGuru(vmVO); s_logger.debug("Plugging nic for vm " + vm + " in network " + network); - + boolean result = false; try{ result = vmGuru.plugNic(network, nicTO, vmTO, context, dest); @@ -2844,17 +2843,17 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac // insert nic's Id into DB as resource_name UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vmVO.getAccountId(), vmVO.getDataCenterId(), vmVO.getId(), Long.toString(nic.getId()), network.getNetworkOfferingId(), - null, isDefault, VirtualMachine.class.getName(), vmVO.getUuid()); + null, isDefault, VirtualMachine.class.getName(), vmVO.getUuid()); return nic; } else { s_logger.warn("Failed to plug nic to the vm " + vm + " in network " + network); return null; - } + } }finally{ if(!result){ _networkMgr.removeNic(vmProfile, _nicsDao.findById(nic.getId())); } - } + } } else if (vm.getState() == State.Stopped) { //1) allocate nic return _networkMgr.createNicForVm(network, requested, context, vmProfile, false); @@ -2895,10 +2894,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac s_logger.warn("Failed to remove nic from " + vm + " in " + network + ", nic is default."); throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + ", nic is default."); } - + // if specified nic is associated with PF/LB/Static NAT if(rulesMgr.listAssociatedRulesForGuestNic(nic).size() > 0){ - throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + ", nic has associated Port forwarding or Load balancer or Static NAT rules."); } @@ -2916,7 +2915,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network ); long isDefault = (nic.isDefaultNic()) ? 1 : 0; UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(), - vm.getId(), Long.toString(nic.getId()), network.getNetworkOfferingId(), null, + vm.getId(), Long.toString(nic.getId()), network.getNetworkOfferingId(), null, isDefault, VirtualMachine.class.getName(), vm.getUuid()); } else { s_logger.warn("Failed to unplug nic for the vm " + vm + " from network " + network); diff --git a/server/src/com/cloud/vm/VirtualMachineProfileImpl.java b/server/src/com/cloud/vm/VirtualMachineProfileImpl.java index e777d5ef498..033daf33422 100644 --- a/server/src/com/cloud/vm/VirtualMachineProfileImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineProfileImpl.java @@ -16,7 +16,14 @@ // under the License. package com.cloud.vm; -import com.cloud.agent.api.to.VolumeTO; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +import com.cloud.agent.api.to.DiskTO; + import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.offering.ServiceOffering; import com.cloud.service.ServiceOfferingVO; @@ -28,24 +35,19 @@ import com.cloud.template.VirtualMachineTemplate.BootloaderType; import com.cloud.user.Account; import com.cloud.user.dao.AccountDao; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - /** * Implementation of VirtualMachineProfile. * */ public class VirtualMachineProfileImpl implements VirtualMachineProfile { - + T _vm; ServiceOfferingVO _offering; VMTemplateVO _template; UserVmDetailVO _userVmDetails; Map _params; List _nics = new ArrayList(); - List _disks = new ArrayList(); + List _disks = new ArrayList(); StringBuilder _bootArgs = new StringBuilder(); Account _owner; BootloaderType _bootloader; @@ -53,7 +55,7 @@ public class VirtualMachineProfileImpl implements Virtua Float memoryOvercommitRatio = 1.0f; VirtualMachine.Type _type; - + public VirtualMachineProfileImpl(T vm, VMTemplateVO template, ServiceOfferingVO offering, Account owner, Map params) { _vm = vm; _template = template; @@ -66,25 +68,25 @@ public class VirtualMachineProfileImpl implements Virtua if (vm != null) _type = vm.getType(); } - + public VirtualMachineProfileImpl(T vm) { this(vm, null, null, null, null); } - + public VirtualMachineProfileImpl(VirtualMachine.Type type) { _type = type; } - + @Override public String toString() { return _vm.toString(); } - + @Override public T getVirtualMachine() { return _vm; } - + @Override public ServiceOffering getServiceOffering() { if (_offering == null) { @@ -92,17 +94,17 @@ public class VirtualMachineProfileImpl implements Virtua } return _offering; } - + @Override public void setParameter(Param name, Object value) { _params.put(name, value); } - - @Override + + @Override public void setBootLoaderType(BootloaderType bootLoader) { this._bootloader = bootLoader; } - + @Override public VirtualMachineTemplate getTemplate() { if (_template == null && _vm != null) { @@ -110,7 +112,7 @@ public class VirtualMachineProfileImpl implements Virtua } return _template; } - + @Override public HypervisorType getHypervisorType() { return _vm.getHypervisorType(); @@ -130,7 +132,7 @@ public class VirtualMachineProfileImpl implements Virtua public long getId() { return _vm.getId(); } - + @Override public String getUuid() { return _vm.getUuid(); @@ -139,48 +141,48 @@ public class VirtualMachineProfileImpl implements Virtua public void setNics(List nics) { _nics = nics; } - - public void setDisks(List disks) { + + public void setDisks(List disks) { _disks = disks; } - + @Override public List getNics() { return _nics; } - + @Override - public List getDisks() { + public List getDisks() { return _disks; } - + @Override public void addNic(int index, NicProfile nic) { _nics.add(index, nic); } - + @Override - public void addDisk(int index, VolumeTO disk) { + public void addDisk(int index, DiskTO disk) { _disks.add(index, disk); } - + @Override public StringBuilder getBootArgsBuilder() { return _bootArgs; } - + @Override public void addBootArgs(String... args) { for (String arg : args) { _bootArgs.append(arg).append(" "); } } - + @Override public VirtualMachine.Type getType() { return _type; } - + @Override public Account getOwner() { if (_owner == null) { @@ -188,12 +190,12 @@ public class VirtualMachineProfileImpl implements Virtua } return _owner; } - + @Override public String getBootArgs() { return _bootArgs.toString(); } - + static ServiceOfferingDao s_offeringDao; static VMTemplateDao s_templateDao; static AccountDao s_accountDao; @@ -209,7 +211,7 @@ public class VirtualMachineProfileImpl implements Virtua } @Override - public void addDisk(VolumeTO disk) { + public void addDisk(DiskTO disk) { _disks.add(disk); } @@ -217,12 +219,12 @@ public class VirtualMachineProfileImpl implements Virtua public Object getParameter(Param name) { return _params.get(name); } - + @Override public String getHostName() { return _vm.getHostName(); } - + @Override public String getInstanceName() { return _vm.getInstanceName(); @@ -232,15 +234,15 @@ public class VirtualMachineProfileImpl implements Virtua public BootloaderType getBootLoaderType() { return this._bootloader; } - + @Override public Map getParameters() { return _params; } - public void setServiceOffering(ServiceOfferingVO offering) { - _offering = offering; - } + public void setServiceOffering(ServiceOfferingVO offering) { + _offering = offering; + } public void setCpuOvercommitRatio(Float cpuOvercommitRatio) { this.cpuOvercommitRatio = cpuOvercommitRatio; @@ -254,7 +256,7 @@ public class VirtualMachineProfileImpl implements Virtua @Override public Float getCpuOvercommitRatio() { - return this.cpuOvercommitRatio; + return this.cpuOvercommitRatio; } @Override diff --git a/server/test/com/cloud/agent/MockAgentManagerImpl.java b/server/test/com/cloud/agent/MockAgentManagerImpl.java index 7e3462d8ff8..01f4e9cb071 100755 --- a/server/test/com/cloud/agent/MockAgentManagerImpl.java +++ b/server/test/com/cloud/agent/MockAgentManagerImpl.java @@ -21,6 +21,7 @@ import java.util.Map; import javax.ejb.Local; import javax.naming.ConfigurationException; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.springframework.stereotype.Component; import com.cloud.agent.api.Answer; @@ -130,15 +131,6 @@ public class MockAgentManagerImpl extends ManagerBase implements AgentManager { return null; } - @Override - public void sendToSecStorage(HostVO ssHost, Command cmd, Listener listener) { - } - - @Override - public Answer sendToSecStorage(HostVO ssHost, Command cmd) { - // TODO Auto-generated method stub - return null; - } @Override public boolean tapLoadingAgents(Long hostId, TapAgentsAction action) { @@ -191,7 +183,7 @@ public class MockAgentManagerImpl extends ManagerBase implements AgentManager { @Override public void disconnectWithInvestigation(long hostId, Event event) { // TODO Auto-generated method stub - + } } diff --git a/server/test/com/cloud/resource/MockResourceManagerImpl.java b/server/test/com/cloud/resource/MockResourceManagerImpl.java index 1fff3a63b1d..a1c52aa9dea 100644 --- a/server/test/com/cloud/resource/MockResourceManagerImpl.java +++ b/server/test/com/cloud/resource/MockResourceManagerImpl.java @@ -49,6 +49,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.org.Cluster; import com.cloud.resource.ResourceState.Event; import com.cloud.service.ServiceOfferingVO; +import com.cloud.storage.ImageStore; import com.cloud.storage.S3; import com.cloud.storage.Swift; import com.cloud.template.VirtualMachineTemplate; diff --git a/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java b/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java index 3f6fe9c4e1b..6398e202b94 100644 --- a/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java +++ b/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java @@ -19,10 +19,10 @@ package org.apache.cloudstack.networkoffering; import java.io.IOException; + import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.region.PortableIpDaoImpl; import org.apache.cloudstack.region.dao.RegionDaoImpl; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDaoImpl; import org.apache.cloudstack.test.utils.SpringUtils; import org.mockito.Mockito; @@ -35,6 +35,7 @@ import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.TypeFilter; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import com.cloud.agent.AgentManager; import com.cloud.alert.AlertManager; import com.cloud.api.query.dao.UserAccountJoinDaoImpl; @@ -345,7 +346,7 @@ public class ChildTestConfiguration { @Bean public DataCenterLinkLocalIpAddressDao datacenterLinkLocalIpAddressDao() { - return Mockito.mock(DataCenterLinkLocalIpAddressDao.class); + return Mockito.mock(DataCenterLinkLocalIpAddressDao.class); } @Bean @@ -363,6 +364,11 @@ public class ChildTestConfiguration { return Mockito.mock(AccountDetailsDao.class); } + @Bean + public DataStoreManager dataStoreManager() { + return Mockito.mock(DataStoreManager.class); + } + public static class Library implements TypeFilter { @Override diff --git a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/CifsSecondaryStorageResource.java b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/CifsSecondaryStorageResource.java deleted file mode 100755 index de4cfe0c97f..00000000000 --- a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/CifsSecondaryStorageResource.java +++ /dev/null @@ -1,755 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// 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, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package org.apache.cloudstack.storage.resource; - -import java.io.File; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import javax.naming.ConfigurationException; - -import org.apache.cloudstack.storage.template.DownloadManager; -import org.apache.cloudstack.storage.template.DownloadManagerImpl; -import org.apache.cloudstack.storage.template.UploadManager; -import org.apache.cloudstack.storage.template.UploadManagerImpl; -import org.apache.log4j.Logger; - -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.CheckHealthAnswer; -import com.cloud.agent.api.CheckHealthCommand; -import com.cloud.agent.api.Command; -import com.cloud.agent.api.GetStorageStatsAnswer; -import com.cloud.agent.api.GetStorageStatsCommand; -import com.cloud.agent.api.PingCommand; -import com.cloud.agent.api.PingStorageCommand; -import com.cloud.agent.api.ReadyAnswer; -import com.cloud.agent.api.ReadyCommand; -import com.cloud.agent.api.SecStorageFirewallCfgCommand; -import com.cloud.agent.api.SecStorageFirewallCfgCommand.PortConfig; -import com.cloud.agent.api.SecStorageSetupCommand; -import com.cloud.agent.api.SecStorageVMSetupCommand; -import com.cloud.agent.api.StartupCommand; -import com.cloud.agent.api.StartupStorageCommand; -import com.cloud.agent.api.storage.CreateEntityDownloadURLCommand; -import com.cloud.agent.api.storage.DeleteEntityDownloadURLCommand; -import com.cloud.agent.api.storage.DeleteTemplateCommand; -import com.cloud.agent.api.storage.DownloadCommand; -import com.cloud.agent.api.storage.DownloadProgressCommand; -import com.cloud.agent.api.storage.UploadCommand; -import com.cloud.agent.api.storage.ssCommand; -import com.cloud.host.Host; -import com.cloud.host.Host.Type; -import com.cloud.resource.ServerResourceBase; -import com.cloud.storage.Storage; -import com.cloud.storage.Storage.StoragePoolType; -import com.cloud.storage.StorageLayer; -import com.cloud.storage.template.TemplateInfo; -import com.cloud.utils.NumbersUtil; -import com.cloud.utils.component.ComponentContext; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.net.NetUtils; -import com.cloud.utils.net.NfsUtils; -import com.cloud.utils.script.Script; - -/** - * Implementation of Secondary Storage Resource to handle CIFS share - * - * TODOD: After mount rest of the functionality should be similar to NfsSecondaryStroage. - * Move common functionality of NFS and CIFS secondary storage resource class to base class - **/ - -public class CifsSecondaryStorageResource extends ServerResourceBase implements SecondaryStorageResource { - private static final Logger s_logger = Logger.getLogger(CifsSecondaryStorageResource.class); - int _timeout; - - String _instance; - String _parent; - - String _dc; - String _pod; - String _guid; - String _nfsPath; - String _mountParent; - Map _params; - StorageLayer _storage; - boolean _inSystemVM = false; - boolean _sslCopy = false; - - Random _rand = new Random(System.currentTimeMillis()); - - DownloadManager _dlMgr; - UploadManager _upldMgr; - private String _configSslScr; - private String _configAuthScr; - private String _configIpFirewallScr; - private String _publicIp; - private String _hostname; - private String _localgw; - private String _eth1mask; - private String _eth1ip; - - @Override - public void disconnected() { - if (_parent != null && !_inSystemVM) { - Script script = new Script(!_inSystemVM, "umount", _timeout, s_logger); - script.add(_parent); - script.execute(); - - File file = new File(_parent); - file.delete(); - } - } - - @Override - public Answer executeRequest(Command cmd) { - if (cmd instanceof DownloadProgressCommand) { - return _dlMgr.handleDownloadCommand(this, (DownloadProgressCommand)cmd); - } else if (cmd instanceof DownloadCommand) { - return _dlMgr.handleDownloadCommand(this, (DownloadCommand)cmd); - } else if (cmd instanceof UploadCommand) { - return _upldMgr.handleUploadCommand(this, (UploadCommand)cmd); - } else if (cmd instanceof CreateEntityDownloadURLCommand){ - return _upldMgr.handleCreateEntityURLCommand((CreateEntityDownloadURLCommand)cmd); - } else if(cmd instanceof DeleteEntityDownloadURLCommand){ - return _upldMgr.handleDeleteEntityDownloadURLCommand((DeleteEntityDownloadURLCommand)cmd); - } else if (cmd instanceof GetStorageStatsCommand) { - return execute((GetStorageStatsCommand)cmd); - } else if (cmd instanceof CheckHealthCommand) { - return new CheckHealthAnswer((CheckHealthCommand)cmd, true); - } else if (cmd instanceof DeleteTemplateCommand) { - return execute((DeleteTemplateCommand) cmd); - } else if (cmd instanceof ReadyCommand) { - return new ReadyAnswer((ReadyCommand)cmd); - } else if (cmd instanceof SecStorageFirewallCfgCommand){ - return execute((SecStorageFirewallCfgCommand)cmd); - } else if (cmd instanceof SecStorageVMSetupCommand){ - return execute((SecStorageVMSetupCommand)cmd); - } else if (cmd instanceof SecStorageSetupCommand){ - return new Answer(cmd, true, "success"); - } else { - return Answer.createUnsupportedCommandAnswer(cmd); - } - } - - private Answer execute(SecStorageVMSetupCommand cmd) { - if (!_inSystemVM){ - return new Answer(cmd, true, null); - } - boolean success = true; - StringBuilder result = new StringBuilder(); - for (String cidr: cmd.getAllowedInternalSites()) { - String tmpresult = allowOutgoingOnPrivate(cidr); - if (tmpresult != null) { - result.append(", ").append(tmpresult); - success = false; - } - } - if (success) { - if (cmd.getCopyPassword() != null && cmd.getCopyUserName() != null) { - String tmpresult = configureAuth(cmd.getCopyUserName(), cmd.getCopyPassword()); - if (tmpresult != null) { - result.append("Failed to configure auth for copy ").append(tmpresult); - success = false; - } - } - } - return new Answer(cmd, success, result.toString()); - - } - - private String allowOutgoingOnPrivate(String destCidr) { - - Script command = new Script("/bin/bash", s_logger); - String intf = "eth1"; - command.add("-c"); - command.add("iptables -I OUTPUT -o " + intf + " -d " + destCidr + " -p tcp -m state --state NEW -m tcp -j ACCEPT"); - - String result = command.execute(); - if (result != null) { - s_logger.warn("Error in allowing outgoing to " + destCidr + ", err=" + result ); - return "Error in allowing outgoing to " + destCidr + ", err=" + result; - } - addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, destCidr); - return null; - } - - - - private Answer execute(SecStorageFirewallCfgCommand cmd) { - if (!_inSystemVM){ - return new Answer(cmd, true, null); - } - - List ipList = new ArrayList(); - - for (PortConfig pCfg:cmd.getPortConfigs()){ - if (pCfg.isAdd()) { - ipList.add(pCfg.getSourceIp()); - } - } - boolean success = true; - String result; - result = configureIpFirewall(ipList); - if (result !=null) - success = false; - - return new Answer(cmd, success, result); - } - - protected GetStorageStatsAnswer execute(final GetStorageStatsCommand cmd) { - final long usedSize = getUsedSize(); - final long totalSize = getTotalSize(); - if (usedSize == -1 || totalSize == -1) { - return new GetStorageStatsAnswer(cmd, "Unable to get storage stats"); - } else { - return new GetStorageStatsAnswer(cmd, totalSize, usedSize) ; - } - } - - @Override - public String getRootDir(ssCommand cmd){ - return null; - } - - protected Answer execute(final DeleteTemplateCommand cmd) { - String relativeTemplatePath = cmd.getTemplatePath(); - String parent = _parent; - - if (relativeTemplatePath.startsWith(File.separator)) { - relativeTemplatePath = relativeTemplatePath.substring(1); - } - - if (!parent.endsWith(File.separator)) { - parent += File.separator; - } - String absoluteTemplatePath = parent + relativeTemplatePath; - File tmpltParent = new File(absoluteTemplatePath).getParentFile(); - String details = null; - if (!tmpltParent.exists()) { - details = "template parent directory " + tmpltParent.getName() + " doesn't exist"; - s_logger.debug(details); - return new Answer(cmd, true, details); - } - File[] tmpltFiles = tmpltParent.listFiles(); - if (tmpltFiles == null || tmpltFiles.length == 0) { - details = "No files under template parent directory " + tmpltParent.getName(); - s_logger.debug(details); - } else { - boolean found = false; - for (File f : tmpltFiles) { - if (!found && f.getName().equals("template.properties")) { - found = true; - } - if (!f.delete()) { - return new Answer(cmd, false, "Unable to delete file " + f.getName() + " under Template path " - + relativeTemplatePath); - } - } - if (!found) { - details = "Can not find template.properties under " + tmpltParent.getName(); - s_logger.debug(details); - } - } - if (!tmpltParent.delete()) { - details = "Unable to delete directory " + tmpltParent.getName() + " under Template path " - + relativeTemplatePath; - s_logger.debug(details); - return new Answer(cmd, false, details); - } - return new Answer(cmd, true, null); - } - - protected long getUsedSize() { - return _storage.getUsedSpace(_parent); - } - - protected long getTotalSize() { - return _storage.getTotalSpace(_parent); - } - - protected long convertFilesystemSize(final String size) { - if (size == null || size.isEmpty()) { - return -1; - } - - long multiplier = 1; - if (size.endsWith("T")) { - multiplier = 1024l * 1024l * 1024l * 1024l; - } else if (size.endsWith("G")) { - multiplier = 1024l * 1024l * 1024l; - } else if (size.endsWith("M")) { - multiplier = 1024l * 1024l; - } else { - assert (false) : "Well, I have no idea what this is: " + size; - } - - return (long)(Double.parseDouble(size.substring(0, size.length() - 1)) * multiplier); - } - - - @Override - public Type getType() { - return Host.Type.SecondaryStorage; - } - - @Override - public PingCommand getCurrentStatus(final long id) { - return new PingStorageCommand(Host.Type.Storage, id, new HashMap()); - } - - @Override - public boolean configure(String name, Map params) throws ConfigurationException { - _eth1ip = (String)params.get("eth1ip"); - if (_eth1ip != null) { //can only happen inside service vm - params.put("private.network.device", "eth1"); - } else { - s_logger.warn("Wait, what's going on? eth1ip is null!!"); - } - String eth2ip = (String) params.get("eth2ip"); - if (eth2ip != null) { - params.put("public.network.device", "eth2"); - } - _publicIp = (String) params.get("eth2ip"); - _hostname = (String) params.get("name"); - - super.configure(name, params); - - _params = params; - String value = (String)params.get("scripts.timeout"); - _timeout = NumbersUtil.parseInt(value, 1440) * 1000; - - _storage = (StorageLayer)params.get(StorageLayer.InstanceConfigKey); - if (_storage == null) { - value = (String)params.get(StorageLayer.ClassConfigKey); - if (value == null) { - value = "com.cloud.storage.JavaStorageLayer"; - } - - try { - Class clazz = Class.forName(value); - _storage = (StorageLayer)ComponentContext.inject(clazz); - _storage.configure("StorageLayer", params); - } catch (ClassNotFoundException e) { - throw new ConfigurationException("Unable to find class " + value); - } - } - _configSslScr = Script.findScript(getDefaultScriptsDir(), "config_ssl.sh"); - if (_configSslScr != null) { - s_logger.info("config_ssl.sh found in " + _configSslScr); - } - - _configAuthScr = Script.findScript(getDefaultScriptsDir(), "config_auth.sh"); - if (_configSslScr != null) { - s_logger.info("config_auth.sh found in " + _configAuthScr); - } - - _configIpFirewallScr = Script.findScript(getDefaultScriptsDir(), "ipfirewall.sh"); - if (_configIpFirewallScr != null) { - s_logger.info("_configIpFirewallScr found in " + _configIpFirewallScr); - } - - _guid = (String)params.get("guid"); - if (_guid == null) { - throw new ConfigurationException("Unable to find the guid"); - } - - _dc = (String)params.get("zone"); - if (_dc == null) { - throw new ConfigurationException("Unable to find the zone"); - } - _pod = (String)params.get("pod"); - - _instance = (String)params.get("instance"); - - _mountParent = (String)params.get("mount.parent"); - if (_mountParent == null) { - _mountParent = File.separator + "mnt"; - } - - if (_instance != null) { - _mountParent = _mountParent + File.separator + _instance; - } - - _nfsPath = (String)params.get("mount.path"); - if (_nfsPath == null) { - throw new ConfigurationException("Unable to find mount.path"); - } - - - - String inSystemVM = (String)params.get("secondary.storage.vm"); - if (inSystemVM == null || "true".equalsIgnoreCase(inSystemVM)) { - _inSystemVM = true; - _localgw = (String)params.get("localgw"); - if (_localgw != null) { //can only happen inside service vm - _eth1mask = (String)params.get("eth1mask"); - String internalDns1 = (String)params.get("dns1"); - String internalDns2 = (String)params.get("dns2"); - - if (internalDns1 == null) { - s_logger.warn("No DNS entry found during configuration of NfsSecondaryStorage"); - } else { - addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, internalDns1); - } - - String mgmtHost = (String)params.get("host"); - String nfsHost = NfsUtils.getHostPart(_nfsPath); - if (nfsHost == null) { - s_logger.error("Invalid or corrupt nfs url " + _nfsPath); - throw new CloudRuntimeException("Unable to determine host part of nfs path"); - } - try { - InetAddress nfsHostAddr = InetAddress.getByName(nfsHost); - nfsHost = nfsHostAddr.getHostAddress(); - } catch (UnknownHostException uhe) { - s_logger.error("Unable to resolve nfs host " + nfsHost); - throw new CloudRuntimeException("Unable to resolve nfs host to an ip address " + nfsHost); - } - addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, nfsHost); - addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, mgmtHost); - if (internalDns2 != null) { - addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, internalDns2); - } - - } - String useSsl = (String)params.get("sslcopy"); - if (useSsl != null) { - _sslCopy = Boolean.parseBoolean(useSsl); - if (_sslCopy) { - configureSSL(); - } - } - startAdditionalServices(); - _params.put("install.numthreads", "50"); - _params.put("secondary.storage.vm", "true"); - } - _parent = mount(_nfsPath, _mountParent); - if (_parent == null) { - throw new ConfigurationException("Unable to create mount point"); - } - - - s_logger.info("Mount point established at " + _parent); - - try { - _params.put("template.parent", _parent); - _params.put(StorageLayer.InstanceConfigKey, _storage); - _dlMgr = new DownloadManagerImpl(); - _dlMgr.configure("DownloadManager", _params); - _upldMgr = new UploadManagerImpl(); - _upldMgr.configure("UploadManager", params); - } catch (ConfigurationException e) { - s_logger.warn("Caught problem while configuring DownloadManager", e); - return false; - } - return true; - } - - private void startAdditionalServices() { - Script command = new Script("/bin/bash", s_logger); - command.add("-c"); - command.add("if [ -f /etc/init.d/ssh ]; then service ssh restart; else service sshd restart; fi "); - String result = command.execute(); - if (result != null) { - s_logger.warn("Error in starting sshd service err=" + result ); - } - command = new Script("/bin/bash", s_logger); - command.add("-c"); - command.add("iptables -I INPUT -i eth1 -p tcp -m state --state NEW -m tcp --dport 3922 -j ACCEPT"); - result = command.execute(); - if (result != null) { - s_logger.warn("Error in opening up ssh port err=" + result ); - } - } - - private void addRouteToInternalIpOrCidr(String localgw, String eth1ip, String eth1mask, String destIpOrCidr) { - s_logger.debug("addRouteToInternalIp: localgw=" + localgw + ", eth1ip=" + eth1ip + ", eth1mask=" + eth1mask + ",destIp=" + destIpOrCidr); - if (destIpOrCidr == null) { - s_logger.debug("addRouteToInternalIp: destIp is null"); - return; - } - if (!NetUtils.isValidIp(destIpOrCidr) && !NetUtils.isValidCIDR(destIpOrCidr)){ - s_logger.warn(" destIp is not a valid ip address or cidr destIp=" + destIpOrCidr); - return; - } - boolean inSameSubnet = false; - if (NetUtils.isValidIp(destIpOrCidr)) { - if (eth1ip != null && eth1mask != null) { - inSameSubnet = NetUtils.sameSubnet(eth1ip, destIpOrCidr, eth1mask); - } else { - s_logger.warn("addRouteToInternalIp: unable to determine same subnet: _eth1ip=" + eth1ip + ", dest ip=" + destIpOrCidr + ", _eth1mask=" + eth1mask); - } - } else { - inSameSubnet = NetUtils.isNetworkAWithinNetworkB(destIpOrCidr, NetUtils.ipAndNetMaskToCidr(eth1ip, eth1mask)); - } - if (inSameSubnet) { - s_logger.debug("addRouteToInternalIp: dest ip " + destIpOrCidr + " is in the same subnet as eth1 ip " + eth1ip); - return; - } - Script command = new Script("/bin/bash", s_logger); - command.add("-c"); - command.add("ip route delete " + destIpOrCidr); - command.execute(); - command = new Script("/bin/bash", s_logger); - command.add("-c"); - command.add("ip route add " + destIpOrCidr + " via " + localgw); - String result = command.execute(); - if (result != null) { - s_logger.warn("Error in configuring route to internal ip err=" + result ); - } else { - s_logger.debug("addRouteToInternalIp: added route to internal ip=" + destIpOrCidr + " via " + localgw); - } - } - - private void configureSSL() { - Script command = new Script(_configSslScr); - command.add(_publicIp); - command.add(_hostname); - String result = command.execute(); - if (result != null) { - s_logger.warn("Unable to configure httpd to use ssl"); - } - } - - private String configureAuth(String user, String passwd) { - Script command = new Script(_configAuthScr); - command.add(user); - command.add(passwd); - String result = command.execute(); - if (result != null) { - s_logger.warn("Unable to configure httpd to use auth"); - } - return result; - } - - private String configureIpFirewall(List ipList){ - Script command = new Script(_configIpFirewallScr); - for (String ip : ipList){ - command.add(ip); - } - - String result = command.execute(); - if (result != null) { - s_logger.warn("Unable to configure firewall for command : " +command); - } - return result; - } - - protected String mount(String path, String parent) { - String mountPoint = null; - for (int i = 0; i < 10; i++) { - String mntPt = parent + File.separator + Integer.toHexString(_rand.nextInt(Integer.MAX_VALUE)); - File file = new File(mntPt); - if (!file.exists()) { - if (_storage.mkdir(mntPt)) { - mountPoint = mntPt; - break; - } - } - s_logger.debug("Unable to create mount: " + mntPt); - } - - if (mountPoint == null) { - s_logger.warn("Unable to create a mount point"); - return null; - } - - Script script = null; - String result = null; - script = new Script(!_inSystemVM, "umount", _timeout, s_logger); - script.add(path); - result = script.execute(); - - if( _parent != null ) { - script = new Script("rmdir", _timeout, s_logger); - script.add(_parent); - result = script.execute(); - } - - Script command = new Script(!_inSystemVM, "mount", _timeout, s_logger); - command.add("-t", "cifs"); - if (_inSystemVM) { - //Fedora Core 12 errors out with any -o option executed from java - //command.add("-o", "soft,timeo=133,retrans=2147483647,tcp,acdirmax=0,acdirmin=0"); - } - String tok[] = path.split(":"); - //command.add(path); - command.add("//"+tok[0]+tok[1]); - command.add(mountPoint); - result = command.execute(); - if (result != null) { - s_logger.warn("Unable to mount " + path + " due to " + result); - File file = new File(mountPoint); - if (file.exists()) - file.delete(); - return null; - } - - - - // XXX: Adding the check for creation of snapshots dir here. Might have to move it somewhere more logical later. - if (!checkForSnapshotsDir(mountPoint)) { - return null; - } - - // Create the volumes dir - if (!checkForVolumesDir(mountPoint)) { - return null; - } - - return mountPoint; - } - - @Override - public boolean start() { - return true; - } - - @Override - public boolean stop() { - return true; - } - - @Override - public StartupCommand[] initialize() { - /*disconnected(); - - _parent = mount(_nfsPath, _mountParent); - - if( _parent == null ) { - s_logger.warn("Unable to mount the nfs server"); - return null; - } - - try { - _params.put("template.parent", _parent); - _params.put(StorageLayer.InstanceConfigKey, _storage); - _dlMgr = new DownloadManagerImpl(); - _dlMgr.configure("DownloadManager", _params); - } catch (ConfigurationException e) { - s_logger.warn("Caught problem while configuring folers", e); - return null; - }*/ - - final StartupStorageCommand cmd = new StartupStorageCommand(_parent, StoragePoolType.NetworkFilesystem, getTotalSize(), new HashMap()); - - cmd.setResourceType(Storage.StorageResourceType.SECONDARY_STORAGE); - cmd.setIqn(null); - - fillNetworkInformation(cmd); - cmd.setDataCenter(_dc); - cmd.setPod(_pod); - cmd.setGuid(_guid); - cmd.setName(_guid); - cmd.setVersion(NfsSecondaryStorageResource.class.getPackage().getImplementationVersion()); - cmd.getHostDetails().put("mount.parent", _mountParent); - cmd.getHostDetails().put("mount.path", _nfsPath); - String tok[] = _nfsPath.split(":"); - cmd.setNfsShare("nfs://" + tok[0] + tok[1]); - if (cmd.getHostDetails().get("orig.url") == null) { - if (tok.length != 2) { - throw new CloudRuntimeException("Not valid NFS path" + _nfsPath); - } - String nfsUrl = "nfs://" + tok[0] + tok[1]; - cmd.getHostDetails().put("orig.url", nfsUrl); - } - InetAddress addr; - try { - addr = InetAddress.getByName(tok[0]); - cmd.setPrivateIpAddress(addr.getHostAddress()); - } catch (UnknownHostException e) { - cmd.setPrivateIpAddress(tok[0]); - } - return new StartupCommand [] {cmd}; - } - - protected boolean checkForSnapshotsDir(String mountPoint) { - String snapshotsDirLocation = mountPoint + File.separator + "snapshots"; - return createDir("snapshots", snapshotsDirLocation, mountPoint); - } - - protected boolean checkForVolumesDir(String mountPoint) { - String volumesDirLocation = mountPoint + "/" + "volumes"; - return createDir("volumes", volumesDirLocation, mountPoint); - } - - protected boolean createDir(String dirName, String dirLocation, String mountPoint) { - boolean dirExists = false; - - File dir = new File(dirLocation); - if (dir.exists()) { - if (dir.isDirectory()) { - s_logger.debug(dirName + " already exists on secondary storage, and is mounted at " + mountPoint); - dirExists = true; - } else { - if (dir.delete() && _storage.mkdir(dirLocation)) { - dirExists = true; - } - } - } else if (_storage.mkdir(dirLocation)) { - dirExists = true; - } - - if (dirExists) { - s_logger.info(dirName + " directory created/exists on Secondary Storage."); - } else { - s_logger.info(dirName + " directory does not exist on Secondary Storage."); - } - - return dirExists; - } - - @Override - protected String getDefaultScriptsDir() { - return "./scripts/storage/secondary"; - } - - @Override - public void setName(String name) { - // TODO Auto-generated method stub - - } - - @Override - public void setConfigParams(Map params) { - // TODO Auto-generated method stub - - } - - @Override - public Map getConfigParams() { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getRunLevel() { - // TODO Auto-generated method stub - return 0; - } - - @Override - public void setRunLevel(int level) { - // TODO Auto-generated method stub - - } -} diff --git a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/LocalNfsSecondaryStorageResource.java b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/LocalNfsSecondaryStorageResource.java new file mode 100644 index 00000000000..02ff8bc1261 --- /dev/null +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/LocalNfsSecondaryStorageResource.java @@ -0,0 +1,233 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// 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, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.resource; + +import static com.cloud.utils.StringUtils.join; +import static java.lang.String.format; +import static java.util.Arrays.asList; + +import java.io.File; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.Executors; + +import org.apache.cloudstack.storage.command.DownloadSystemTemplateCommand; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.amazonaws.services.s3.model.S3ObjectSummary; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.storage.DownloadAnswer; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.NfsTO; +import com.cloud.agent.api.to.S3TO; +import com.cloud.agent.api.to.SwiftTO; +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDaoImpl; +import com.cloud.storage.JavaStorageLayer; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; + +import org.apache.cloudstack.storage.template.DownloadManagerImpl; +import org.apache.cloudstack.storage.template.DownloadManagerImpl.ZfsPathParser; +import com.cloud.utils.S3Utils; +import com.cloud.utils.UriUtils; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; + +@Component +public class LocalNfsSecondaryStorageResource extends NfsSecondaryStorageResource { + + private static final Logger s_logger = Logger.getLogger(LocalNfsSecondaryStorageResource.class); + + public LocalNfsSecondaryStorageResource() { + this._dlMgr = new DownloadManagerImpl(); + ((DownloadManagerImpl) _dlMgr).setThreadPool(Executors.newFixedThreadPool(10)); + _storage = new JavaStorageLayer(); + this._inSystemVM = false; + // get mount parent folder configured in global setting, if set, this will overwrite _parent in NfsSecondaryStorageResource to work + // around permission issue for default /mnt folder + ConfigurationDaoImpl configDao = new ConfigurationDaoImpl(); + String mountParent = configDao.getValue(Config.MountParent.key()); + if (mountParent != null) { + _parent = mountParent + File.separator + "secStorage"; + } + } + + @Override + public Answer executeRequest(Command cmd) { + if (cmd instanceof DownloadSystemTemplateCommand) { + return execute((DownloadSystemTemplateCommand) cmd); + } else { + // return Answer.createUnsupportedCommandAnswer(cmd); + return super.executeRequest(cmd); + } + } + + private Answer execute(DownloadSystemTemplateCommand cmd) { + DataStoreTO dstore = cmd.getDataStore(); + if (dstore instanceof S3TO) { + // TODO: how to handle download progress for S3 + S3TO s3 = (S3TO) cmd.getDataStore(); + String url = cmd.getUrl(); + String user = null; + String password = null; + if (cmd.getAuth() != null) { + user = cmd.getAuth().getUserName(); + password = new String(cmd.getAuth().getPassword()); + } + // get input stream from the given url + InputStream in = UriUtils.getInputStreamFromUrl(url, user, password); + URI uri; + URL urlObj; + try { + uri = new URI(url); + urlObj = new URL(url); + } catch (URISyntaxException e) { + throw new CloudRuntimeException("URI is incorrect: " + url); + } catch (MalformedURLException e) { + throw new CloudRuntimeException("URL is incorrect: " + url); + } + + final String bucket = s3.getBucketName(); + // convention is no / in the end for install path based on S3Utils + // implementation. + String path = determineS3TemplateDirectory(cmd.getAccountId(), cmd.getResourceId(), cmd.getName()); + // template key is + // TEMPLATE_ROOT_DIR/account_id/template_id/template_name + String key = join(asList(path, urlObj.getFile()), S3Utils.SEPARATOR); + S3Utils.putObject(s3, in, bucket, key); + List s3Obj = S3Utils.getDirectory(s3, bucket, path); + if (s3Obj == null || s3Obj.size() == 0) { + return new Answer(cmd, false, "Failed to download to S3 bucket: " + bucket + " with key: " + key); + } else { + return new DownloadAnswer(null, 100, null, Status.DOWNLOADED, path, path, s3Obj.get(0).getSize(), s3Obj.get(0).getSize(), s3Obj + .get(0).getETag()); + } + } else if (dstore instanceof NfsTO) { + return new Answer(cmd, false, "Nfs needs to be pre-installed with system vm templates"); + } else if (dstore instanceof SwiftTO) { + // TODO: need to move code from + // execute(uploadTemplateToSwiftFromSecondaryStorageCommand) here, + // but we need to handle + // source is url, most likely we need to modify our existing + // swiftUpload python script. + return new Answer(cmd, false, "Swift is not currently support DownloadCommand"); + } else { + return new Answer(cmd, false, "Unsupported image data store: " + dstore); + } + } + + @Override + synchronized public String getRootDir(String secUrl) { + try { + URI uri = new URI(secUrl); + String nfsHost = uri.getHost(); + + InetAddress nfsHostAddr = InetAddress.getByName(nfsHost); + String nfsHostIp = nfsHostAddr.getHostAddress(); + String nfsPath = nfsHostIp + ":" + uri.getPath(); + String dir = UUID.nameUUIDFromBytes(nfsPath.getBytes()).toString(); + String root = _parent + "/" + dir; + mount(root, nfsPath); + return root; + } catch (Exception e) { + String msg = "GetRootDir for " + secUrl + " failed due to " + e.toString(); + s_logger.error(msg, e); + throw new CloudRuntimeException(msg); + } + } + + @Override + protected String mount(String root, String nfsPath) { + File file = new File(root); + if (!file.exists()) { + if (_storage.mkdir(root)) { + s_logger.debug("create mount point: " + root); + } else { + s_logger.debug("Unable to create mount point: " + root); + return null; + } + } + + Script script = null; + String result = null; + script = new Script(!_inSystemVM, "mount", _timeout, s_logger); + List res = new ArrayList(); + ZfsPathParser parser = new ZfsPathParser(root); + script.execute(parser); + res.addAll(parser.getPaths()); + for (String s : res) { + if (s.contains(root)) { + s_logger.debug("mount point " + root + " already exists"); + return root; + } + } + + Script command = new Script(!_inSystemVM, "mount", _timeout, s_logger); + command.add("-t", "nfs"); + if ("Mac OS X".equalsIgnoreCase(System.getProperty("os.name"))) { + command.add("-o", "resvport"); + } + if (_inSystemVM) { + // Fedora Core 12 errors out with any -o option executed from java + command.add("-o", "soft,timeo=133,retrans=2147483647,tcp,acdirmax=0,acdirmin=0"); + } + command.add(nfsPath); + command.add(root); + result = command.execute(); + if (result != null) { + s_logger.warn("Unable to mount " + nfsPath + " due to " + result); + file = new File(root); + if (file.exists()) + file.delete(); + return null; + } + s_logger.debug("Successfully mount " + nfsPath); + + // Change permissions for the mountpoint + script = new Script(true, "chmod", _timeout, s_logger); + script.add("777", root); + result = script.execute(); + if (result != null) { + s_logger.warn("Unable to set permissions for " + root + " due to " + result); + return null; + } + s_logger.debug("Successfully set 777 permission for " + root); + + // XXX: Adding the check for creation of snapshots dir here. Might have + // to move it somewhere more logical later. + if (!checkForSnapshotsDir(root)) { + return null; + } + + // Create the volumes dir + if (!checkForVolumesDir(root)) { + return null; + } + + return root; + } + +} diff --git a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/LocalSecondaryStorageResource.java b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/LocalSecondaryStorageResource.java index b904254b944..5a806bc16c1 100644 --- a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/LocalSecondaryStorageResource.java +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/LocalSecondaryStorageResource.java @@ -21,6 +21,8 @@ import java.util.Map; import javax.naming.ConfigurationException; +import org.apache.cloudstack.storage.command.DownloadCommand; +import org.apache.cloudstack.storage.command.DownloadProgressCommand; import org.apache.cloudstack.storage.template.DownloadManager; import org.apache.cloudstack.storage.template.DownloadManagerImpl; import org.apache.log4j.Logger; @@ -37,18 +39,16 @@ import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.SecStorageSetupCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupStorageCommand; -import com.cloud.agent.api.storage.DownloadCommand; -import com.cloud.agent.api.storage.DownloadProgressCommand; import com.cloud.agent.api.storage.ListTemplateAnswer; import com.cloud.agent.api.storage.ListTemplateCommand; -import com.cloud.agent.api.storage.ssCommand; +import com.cloud.agent.api.to.NfsTO; import com.cloud.host.Host; import com.cloud.host.Host.Type; import com.cloud.resource.ServerResourceBase; import com.cloud.storage.Storage; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.StorageLayer; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; import com.cloud.utils.component.ComponentContext; public class LocalSecondaryStorageResource extends ServerResourceBase implements SecondaryStorageResource { @@ -72,7 +72,7 @@ public class LocalSecondaryStorageResource extends ServerResourceBase implements @Override - public String getRootDir(ssCommand cmd){ + public String getRootDir(String url){ return getRootDir(); } @@ -94,7 +94,7 @@ public class LocalSecondaryStorageResource extends ServerResourceBase implements } else if (cmd instanceof ReadyCommand) { return new ReadyAnswer((ReadyCommand)cmd); } else if (cmd instanceof ListTemplateCommand){ - return execute((ListTemplateCommand)cmd); + return execute((ListTemplateCommand)cmd); } else if (cmd instanceof ComputeChecksumCommand){ return execute((ComputeChecksumCommand)cmd); } else { @@ -103,14 +103,14 @@ public class LocalSecondaryStorageResource extends ServerResourceBase implements } private Answer execute(ComputeChecksumCommand cmd) { - return new Answer(cmd, false, null); + return new Answer(cmd, false, null); } private Answer execute(ListTemplateCommand cmd) { String root = getRootDir(); - Map templateInfos = _dlMgr.gatherTemplateInfo(root); - return new ListTemplateAnswer(cmd.getSecUrl(), templateInfos); + Map templateInfos = _dlMgr.gatherTemplateInfo(root); + return new ListTemplateAnswer(((NfsTO)cmd.getDataStore()).getUrl(), templateInfos); } @Override @@ -213,14 +213,14 @@ public class LocalSecondaryStorageResource extends ServerResourceBase implements @Override public void setName(String name) { // TODO Auto-generated method stub - + } @Override public void setConfigParams(Map params) { // TODO Auto-generated method stub - + } @@ -241,6 +241,6 @@ public class LocalSecondaryStorageResource extends ServerResourceBase implements @Override public void setRunLevel(int level) { // TODO Auto-generated method stub - + } } diff --git a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java index 9ddba8307b8..17ec0bbf838 100755 --- a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java @@ -16,19 +16,17 @@ // under the License. package org.apache.cloudstack.storage.resource; -import static com.cloud.utils.S3Utils.deleteDirectory; -import static com.cloud.utils.S3Utils.getDirectory; -import static com.cloud.utils.S3Utils.putDirectory; +import static com.cloud.utils.S3Utils.putFile; import static com.cloud.utils.StringUtils.join; import static com.cloud.utils.db.GlobalLock.executeWithNoWaitLock; import static java.lang.String.format; +import static java.util.Arrays.asList; import static org.apache.commons.lang.StringUtils.substringAfterLast; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; -import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; @@ -45,25 +43,32 @@ import java.util.concurrent.Callable; import javax.naming.ConfigurationException; +import org.apache.cloudstack.storage.command.CopyCmdAnswer; +import org.apache.cloudstack.storage.command.CopyCommand; +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.command.DownloadCommand; +import org.apache.cloudstack.storage.command.DownloadProgressCommand; import org.apache.cloudstack.storage.template.DownloadManager; import org.apache.cloudstack.storage.template.DownloadManagerImpl; import org.apache.cloudstack.storage.template.DownloadManagerImpl.ZfsPathParser; import org.apache.cloudstack.storage.template.UploadManager; import org.apache.cloudstack.storage.template.UploadManagerImpl; +import org.apache.cloudstack.storage.to.SnapshotObjectTO; +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; +import com.amazonaws.services.s3.model.S3ObjectSummary; import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckHealthAnswer; import com.cloud.agent.api.CheckHealthCommand; -import com.cloud.agent.api.CleanupSnapshotBackupCommand; import com.cloud.agent.api.Command; import com.cloud.agent.api.ComputeChecksumCommand; -import com.cloud.agent.api.DeleteObjectFromSwiftCommand; -import com.cloud.agent.api.DeleteSnapshotBackupCommand; import com.cloud.agent.api.DeleteSnapshotsDirCommand; -import com.cloud.agent.api.DeleteTemplateFromS3Command; import com.cloud.agent.api.DownloadSnapshotFromS3Command; -import com.cloud.agent.api.DownloadTemplateFromS3ToSecondaryStorageCommand; +import com.cloud.agent.api.DownloadSnapshotFromSwiftCommand; +import com.cloud.agent.api.DownloadTemplateFromSwiftToSecondaryStorageCommand; import com.cloud.agent.api.GetStorageStatsAnswer; import com.cloud.agent.api.GetStorageStatsCommand; import com.cloud.agent.api.PingCommand; @@ -78,64 +83,72 @@ import com.cloud.agent.api.SecStorageSetupCommand.Certificates; import com.cloud.agent.api.SecStorageVMSetupCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupSecondaryStorageCommand; -import com.cloud.agent.api.UploadTemplateToS3FromSecondaryStorageCommand; -import com.cloud.agent.api.DownloadSnapshotFromSwiftCommand; -import com.cloud.agent.api.DownloadTemplateFromSwiftToSecondaryStorageCommand; import com.cloud.agent.api.UploadTemplateToSwiftFromSecondaryStorageCommand; import com.cloud.agent.api.storage.CreateEntityDownloadURLCommand; import com.cloud.agent.api.storage.DeleteEntityDownloadURLCommand; -import com.cloud.agent.api.storage.DeleteTemplateCommand; -import com.cloud.agent.api.storage.DeleteVolumeCommand; -import com.cloud.agent.api.storage.DownloadCommand; -import com.cloud.agent.api.storage.DownloadProgressCommand; import com.cloud.agent.api.storage.ListTemplateAnswer; import com.cloud.agent.api.storage.ListTemplateCommand; import com.cloud.agent.api.storage.ListVolumeAnswer; import com.cloud.agent.api.storage.ListVolumeCommand; import com.cloud.agent.api.storage.UploadCommand; -import com.cloud.agent.api.storage.ssCommand; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.NfsTO; import com.cloud.agent.api.to.S3TO; import com.cloud.agent.api.to.SwiftTO; import com.cloud.exception.InternalErrorException; import com.cloud.host.Host; import com.cloud.host.Host.Type; +import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.resource.ServerResourceBase; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.StorageLayer; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.Processor; +import com.cloud.storage.template.Processor.FormatInfo; import com.cloud.storage.template.TemplateLocation; +import com.cloud.storage.template.TemplateProp; +import com.cloud.storage.template.VhdProcessor; import com.cloud.utils.NumbersUtil; import com.cloud.utils.S3Utils; import com.cloud.utils.S3Utils.FileNamingStrategy; -import com.cloud.utils.S3Utils.ObjectNamingStrategy; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.cloud.utils.script.OutputInterpreter; import com.cloud.utils.script.Script; import com.cloud.vm.SecondaryStorageVm; -public class NfsSecondaryStorageResource extends ServerResourceBase implements -SecondaryStorageResource { +public class NfsSecondaryStorageResource extends ServerResourceBase implements SecondaryStorageResource { - private static final Logger s_logger = Logger - .getLogger(NfsSecondaryStorageResource.class); + private static final Logger s_logger = Logger.getLogger(NfsSecondaryStorageResource.class); private static final String TEMPLATE_ROOT_DIR = "template/tmpl"; private static final String SNAPSHOT_ROOT_DIR = "snapshots"; + private static final String VOLUME_ROOT_DIR = "volumes"; int _timeout; - String _instance; + public int getTimeout() { + return _timeout; + } + + public void setTimeout(int _timeout) { + this._timeout = _timeout; + } + + String _instance; String _dc; String _pod; String _guid; String _role; Map _params; - StorageLayer _storage; + protected StorageLayer _storage; protected boolean _inSystemVM = false; boolean _sslCopy = false; - DownloadManager _dlMgr; - UploadManager _upldMgr; + protected DownloadManager _dlMgr; + protected UploadManager _upldMgr; private String _configSslScr; private String _configAuthScr; private String _configIpFirewallScr; @@ -148,9 +161,11 @@ SecondaryStorageResource { private String _storageNetmask; private String _storageGateway; private final List nfsIps = new ArrayList(); - private String _parent = "/mnt/SecStorage"; + protected String _parent = "/mnt/SecStorage"; final private String _tmpltDir = "/var/cloudstack/template"; final private String _tmpltpp = "template.properties"; + protected String createTemplateFromSnapshotXenScript; + @Override public void disconnected() { } @@ -158,123 +173,305 @@ SecondaryStorageResource { @Override public Answer executeRequest(Command cmd) { if (cmd instanceof DownloadProgressCommand) { - return _dlMgr.handleDownloadCommand(this, (DownloadProgressCommand)cmd); + return _dlMgr.handleDownloadCommand(this, (DownloadProgressCommand) cmd); } else if (cmd instanceof DownloadCommand) { - return _dlMgr.handleDownloadCommand(this, (DownloadCommand)cmd); - } else if (cmd instanceof UploadCommand) { - return _upldMgr.handleUploadCommand(this, (UploadCommand)cmd); - } else if (cmd instanceof CreateEntityDownloadURLCommand){ - return _upldMgr.handleCreateEntityURLCommand((CreateEntityDownloadURLCommand)cmd); - } else if(cmd instanceof DeleteEntityDownloadURLCommand){ - return _upldMgr.handleDeleteEntityDownloadURLCommand((DeleteEntityDownloadURLCommand)cmd); + return execute((DownloadCommand) cmd); + } else if (cmd instanceof UploadCommand) { + return _upldMgr.handleUploadCommand(this, (UploadCommand) cmd); + } else if (cmd instanceof CreateEntityDownloadURLCommand) { + return _upldMgr.handleCreateEntityURLCommand((CreateEntityDownloadURLCommand) cmd); + } else if (cmd instanceof DeleteEntityDownloadURLCommand) { + return _upldMgr.handleDeleteEntityDownloadURLCommand((DeleteEntityDownloadURLCommand) cmd); } else if (cmd instanceof GetStorageStatsCommand) { - return execute((GetStorageStatsCommand)cmd); + return execute((GetStorageStatsCommand) cmd); } else if (cmd instanceof CheckHealthCommand) { - return new CheckHealthAnswer((CheckHealthCommand)cmd, true); - } else if (cmd instanceof DeleteTemplateCommand) { - return execute((DeleteTemplateCommand) cmd); - } else if (cmd instanceof DeleteVolumeCommand) { - return execute((DeleteVolumeCommand) cmd); - }else if (cmd instanceof ReadyCommand) { - return new ReadyAnswer((ReadyCommand)cmd); - } else if (cmd instanceof SecStorageFirewallCfgCommand){ - return execute((SecStorageFirewallCfgCommand)cmd); - } else if (cmd instanceof SecStorageVMSetupCommand){ - return execute((SecStorageVMSetupCommand)cmd); - } else if (cmd instanceof SecStorageSetupCommand){ - return execute((SecStorageSetupCommand)cmd); - } else if (cmd instanceof ComputeChecksumCommand){ - return execute((ComputeChecksumCommand)cmd); - } else if (cmd instanceof ListTemplateCommand){ - return execute((ListTemplateCommand)cmd); - } else if (cmd instanceof ListVolumeCommand){ - return execute((ListVolumeCommand)cmd); - }else if (cmd instanceof DownloadSnapshotFromSwiftCommand){ - return execute((DownloadSnapshotFromSwiftCommand)cmd); + return new CheckHealthAnswer((CheckHealthCommand) cmd, true); + } else if (cmd instanceof ReadyCommand) { + return new ReadyAnswer((ReadyCommand) cmd); + } else if (cmd instanceof SecStorageFirewallCfgCommand) { + return execute((SecStorageFirewallCfgCommand) cmd); + } else if (cmd instanceof SecStorageVMSetupCommand) { + return execute((SecStorageVMSetupCommand) cmd); + } else if (cmd instanceof SecStorageSetupCommand) { + return execute((SecStorageSetupCommand) cmd); + } else if (cmd instanceof ComputeChecksumCommand) { + return execute((ComputeChecksumCommand) cmd); + } else if (cmd instanceof ListTemplateCommand) { + return execute((ListTemplateCommand) cmd); + } else if (cmd instanceof ListVolumeCommand) { + return execute((ListVolumeCommand) cmd); + } else if (cmd instanceof DownloadSnapshotFromSwiftCommand) { + return execute((DownloadSnapshotFromSwiftCommand) cmd); } else if (cmd instanceof DownloadSnapshotFromS3Command) { return execute((DownloadSnapshotFromS3Command) cmd); - } else if (cmd instanceof DeleteSnapshotBackupCommand){ - return execute((DeleteSnapshotBackupCommand)cmd); - } else if (cmd instanceof DeleteSnapshotsDirCommand){ - return execute((DeleteSnapshotsDirCommand)cmd); + } else if (cmd instanceof DeleteSnapshotsDirCommand) { + return execute((DeleteSnapshotsDirCommand) cmd); } else if (cmd instanceof DownloadTemplateFromSwiftToSecondaryStorageCommand) { return execute((DownloadTemplateFromSwiftToSecondaryStorageCommand) cmd); - } else if (cmd instanceof DownloadTemplateFromS3ToSecondaryStorageCommand) { - return execute((DownloadTemplateFromS3ToSecondaryStorageCommand) cmd); } else if (cmd instanceof UploadTemplateToSwiftFromSecondaryStorageCommand) { return execute((UploadTemplateToSwiftFromSecondaryStorageCommand) cmd); - } else if (cmd instanceof UploadTemplateToS3FromSecondaryStorageCommand) { - return execute((UploadTemplateToS3FromSecondaryStorageCommand) cmd); - } else if (cmd instanceof DeleteObjectFromSwiftCommand) { - return execute((DeleteObjectFromSwiftCommand) cmd); - } else if (cmd instanceof DeleteTemplateFromS3Command) { - return execute((DeleteTemplateFromS3Command) cmd); - } else if (cmd instanceof CleanupSnapshotBackupCommand){ - return execute((CleanupSnapshotBackupCommand)cmd); + } else if (cmd instanceof CopyCommand) { + return execute((CopyCommand) cmd); + } else if (cmd instanceof DeleteCommand) { + return execute((DeleteCommand) cmd); } else { return Answer.createUnsupportedCommandAnswer(cmd); } } - static String determineS3TemplateDirectory(final Long accountId, - final Long templateId) { - return join(S3Utils.SEPARATOR, TEMPLATE_ROOT_DIR, accountId, templateId); - } - - private String determineStorageTemplatePath(final String storagePath, - final Long accountId, final Long templateId) { - return join(File.separator, - getRootDir(storagePath), TEMPLATE_ROOT_DIR, accountId, - templateId); - } - - private Answer execute( - final DownloadTemplateFromS3ToSecondaryStorageCommand cmd) { - - final S3TO s3 = cmd.getS3(); - final String storagePath = cmd.getStoragePath(); - final Long accountId = cmd.getAccountId(); - final Long templateId = cmd.getTemplateId(); + protected Answer copyFromS3ToNfs(CopyCommand cmd, DataTO srcData, S3TO s3, DataTO destData, NfsTO destImageStore) { + final String storagePath = destImageStore.getUrl(); + final String destPath = destData.getPath(); try { - final File downloadDirectory = _storage - .getFile(determineStorageTemplatePath(storagePath, - accountId, templateId)); + String downloadPath = determineStorageTemplatePath(storagePath, destPath); + final File downloadDirectory = _storage.getFile(downloadPath); downloadDirectory.mkdirs(); if (!downloadDirectory.exists()) { - final String errMsg = format( - "Unable to create directory " - + "download directory %1$s for download of template id " - + "%2$s from S3.", downloadDirectory.getName(), - templateId); + final String errMsg = "Unable to create directory " + downloadPath + " to copy from S3 to cache."; s_logger.error(errMsg); - return new Answer(cmd, false, errMsg); + return new CopyCmdAnswer(errMsg); + } else { + s_logger.debug("Directory " + downloadPath + " already exists"); } - getDirectory(s3, s3.getBucketName(), - determineS3TemplateDirectory(accountId, templateId), - downloadDirectory, new FileNamingStrategy() { - @Override - public String determineFileName(final String key) { - return substringAfterLast(key, S3Utils.SEPARATOR); - } - }); + File destFile = S3Utils.getFile(s3, s3.getBucketName(), srcData.getPath(), downloadDirectory, + new FileNamingStrategy() { + @Override + public String determineFileName(final String key) { + return substringAfterLast(key, S3Utils.SEPARATOR); + } + }); - return new Answer(cmd, true, format("Successfully downloaded " - + "template id %1$s from S3 to directory %2$s", templateId, - downloadDirectory.getName())); + if (destFile == null) { + return new CopyCmdAnswer("Can't find template"); + } + // do post processing to unzip the file if it is compressed + String scriptsDir = "scripts/storage/secondary"; + String createTmpltScr = Script.findScript(scriptsDir, "createtmplt.sh"); + if (createTmpltScr == null) { + throw new ConfigurationException("Unable to find createtmplt.sh"); + } + s_logger.info("createtmplt.sh found in " + createTmpltScr); + String createVolScr = Script.findScript(scriptsDir, "createvolume.sh"); + if (createVolScr == null) { + throw new ConfigurationException("Unable to find createvolume.sh"); + } + s_logger.info("createvolume.sh found in " + createVolScr); + String script = srcData.getObjectType() == DataObjectType.TEMPLATE ? createTmpltScr : createVolScr; + + int installTimeoutPerGig = 180 * 60 * 1000; + int imgSizeGigs = (int) Math.ceil(destFile.length() * 1.0d / (1024 * 1024 * 1024)); + imgSizeGigs++; // add one just in case + long timeout = imgSizeGigs * installTimeoutPerGig; + + String origPath = destFile.getAbsolutePath(); + String extension = null; + if (srcData.getObjectType() == DataObjectType.TEMPLATE) { + extension = ((TemplateObjectTO) srcData).getFormat().getFileExtension(); + } else { + extension = ((VolumeObjectTO) srcData).getFormat().getFileExtension(); + } + + String templateName = UUID.randomUUID().toString(); + String templateFilename = templateName + "." + extension; + Script scr = new Script(script, timeout, s_logger); + scr.add("-s", Integer.toString(imgSizeGigs)); // not used for now + scr.add("-n", templateFilename); + + scr.add("-t", downloadPath); + scr.add("-f", origPath); // this is the temporary + // template file downloaded + String result; + result = scr.execute(); + + if (result != null) { + // script execution failure + throw new CloudRuntimeException("Failed to run script " + script); + } + + String finalFileName = templateFilename; + String finalDownloadPath = destPath + File.separator + templateFilename; + // compute the size of + long size = this._storage.getSize(downloadPath + File.separator + templateFilename); + + DataTO newDestTO = null; + + if (destData.getObjectType() == DataObjectType.TEMPLATE) { + TemplateObjectTO newTemplTO = new TemplateObjectTO(); + newTemplTO.setPath(finalDownloadPath); + newTemplTO.setName(finalFileName); + newTemplTO.setSize(size); + newDestTO = newTemplTO; + } else { + return new CopyCmdAnswer("not implemented yet"); + } + + return new CopyCmdAnswer(newDestTO); } catch (Exception e) { - final String errMsg = format("Failed to upload template id %1$s " - + "due to $2%s", templateId, e.getMessage()); + final String errMsg = format("Failed to download" + "due to $2%s", e.getMessage()); s_logger.error(errMsg, e); - return new Answer(cmd, false, errMsg); + return new CopyCmdAnswer(errMsg); + } + } + protected Answer copySnapshotToTemplateFromNfsToNfsXenserver(CopyCommand cmd, SnapshotObjectTO srcData, + NfsTO srcDataStore, TemplateObjectTO destData, NfsTO destDataStore) { + String srcMountPoint = this.getRootDir(srcDataStore.getUrl()); + String snapshotPath = srcData.getPath(); + int index = snapshotPath.lastIndexOf("/"); + String snapshotName = snapshotPath.substring(index + 1); + if (!snapshotName.startsWith("VHD-") && !snapshotName.endsWith(".vhd")) { + snapshotName = snapshotName + ".vhd"; + } + snapshotPath = snapshotPath.substring(0, index); + snapshotPath = srcMountPoint + File.separator + snapshotPath; + String destMountPoint = this.getRootDir(destDataStore.getUrl()); + String destPath = destMountPoint + File.separator + destData.getPath(); + + String errMsg = null; + try { + this._storage.mkdir(destPath); + + String templateUuid = UUID.randomUUID().toString(); + String templateName = templateUuid + ".vhd"; + Script command = new Script(this.createTemplateFromSnapshotXenScript, cmd.getWait(), s_logger); + command.add("-p", snapshotPath); + command.add("-s", snapshotName); + command.add("-n", templateName); + command.add("-t", destPath); + String result = command.execute(); + + if (result != null && !result.equalsIgnoreCase("")) { + return new CopyCmdAnswer(result); + } + + Map params = new HashMap(); + params.put(StorageLayer.InstanceConfigKey, _storage); + Processor processor = new VhdProcessor(); + + processor.configure("Vhd Processor", params); + FormatInfo info = processor.process(destPath, null, templateUuid); + + TemplateLocation loc = new TemplateLocation(_storage, destPath); + loc.create(1, true, templateName); + loc.addFormat(info); + loc.save(); + TemplateProp prop = loc.getTemplateInfo(); + TemplateObjectTO newTemplate = new TemplateObjectTO(); + newTemplate.setPath(destData.getPath() + File.separator + templateName); + newTemplate.setFormat(ImageFormat.VHD); + newTemplate.setSize(prop.getSize()); + return new CopyCmdAnswer(newTemplate); + } catch (ConfigurationException e) { + s_logger.debug("Failed to create template from snapshot: " + e.toString()); + errMsg = e.toString(); + } catch (InternalErrorException e) { + s_logger.debug("Failed to create template from snapshot: " + e.toString()); + errMsg = e.toString(); + } catch (IOException e) { + s_logger.debug("Failed to create template from snapshot: " + e.toString()); + errMsg = e.toString(); } + return new CopyCmdAnswer(errMsg); + } + + protected Answer copySnapshotToTemplateFromNfsToNfs(CopyCommand cmd, SnapshotObjectTO srcData, NfsTO srcDataStore, + TemplateObjectTO destData, NfsTO destDataStore) { + + if (srcData.getHypervisorType() == HypervisorType.XenServer) { + return copySnapshotToTemplateFromNfsToNfsXenserver(cmd, srcData, srcDataStore, destData, destDataStore); + } + + return new CopyCmdAnswer(""); + } + + protected Answer createTemplateFromSnapshot(CopyCommand cmd) { + DataTO srcData = cmd.getSrcTO(); + DataTO destData = cmd.getDestTO(); + DataStoreTO srcDataStore = srcData.getDataStore(); + DataStoreTO destDataStore = destData.getDataStore(); + if (srcDataStore.getRole() == DataStoreRole.Image || srcDataStore.getRole() == DataStoreRole.ImageCache) { + if (!(srcDataStore instanceof NfsTO)) { + s_logger.debug("only support nfs storage as src, when create template from snapshot"); + return Answer.createUnsupportedCommandAnswer(cmd); + } + + if (destDataStore instanceof NfsTO) { + return copySnapshotToTemplateFromNfsToNfs(cmd, (SnapshotObjectTO) srcData, (NfsTO) srcDataStore, + (TemplateObjectTO) destData, (NfsTO) destDataStore); + } + + } + return new CopyCmdAnswer(""); + } + + protected Answer copyFromNfsToImage(CopyCommand cmd) { + DataTO destData = cmd.getDestTO(); + DataStoreTO destDataStore = destData.getDataStore(); + + if (destDataStore instanceof S3TO) { + return copyFromNfsToS3(cmd); + } else { + return new CopyCmdAnswer("unsupported "); + } + } + + protected Answer execute(CopyCommand cmd) { + DataTO srcData = cmd.getSrcTO(); + DataTO destData = cmd.getDestTO(); + DataStoreTO srcDataStore = srcData.getDataStore(); + DataStoreTO destDataStore = destData.getDataStore(); + + if (srcData.getObjectType() == DataObjectType.SNAPSHOT && destData.getObjectType() == DataObjectType.TEMPLATE) { + return createTemplateFromSnapshot(cmd); + } + + if (srcDataStore instanceof S3TO && destDataStore instanceof NfsTO + && destDataStore.getRole() == DataStoreRole.ImageCache) { + S3TO s3 = (S3TO) srcDataStore; + NfsTO destImageStore = (NfsTO) destDataStore; + return this.copyFromS3ToNfs(cmd, srcData, s3, destData, destImageStore); + } + + if (srcDataStore.getRole() == DataStoreRole.ImageCache && destDataStore.getRole() == DataStoreRole.Image) { + return copyFromNfsToImage(cmd); + } + + return Answer.createUnsupportedCommandAnswer(cmd); + } + + @SuppressWarnings("unchecked") + protected String determineS3TemplateDirectory(final Long accountId, final Long templateId, + final String templateUniqueName) { + return join(asList(TEMPLATE_ROOT_DIR, accountId, templateId, templateUniqueName), S3Utils.SEPARATOR); + } + + @SuppressWarnings("unchecked") + private String determineS3TemplateNameFromKey(String key) { + return StringUtils.substringAfterLast(StringUtils.substringBeforeLast(key, S3Utils.SEPARATOR), + S3Utils.SEPARATOR); + } + + @SuppressWarnings("unchecked") + protected String determineS3VolumeDirectory(final Long accountId, final Long volId) { + return join(asList(VOLUME_ROOT_DIR, accountId, volId), S3Utils.SEPARATOR); + } + + @SuppressWarnings("unchecked") + protected Long determineS3VolumeIdFromKey(String key) { + return Long.parseLong(StringUtils.substringAfterLast(StringUtils.substringBeforeLast(key, S3Utils.SEPARATOR), + S3Utils.SEPARATOR)); + } + + @SuppressWarnings("unchecked") + private String determineStorageTemplatePath(final String storagePath, String dataPath) { + return join(asList(getRootDir(storagePath), dataPath), File.separator); } private Answer execute(DownloadTemplateFromSwiftToSecondaryStorageCommand cmd) { @@ -297,7 +494,8 @@ SecondaryStorageResource { String lPath = lDir + "/" + path; result = swiftDownload(swift, "T-" + templateId.toString(), path, lPath); if (result != null) { - errMsg = "failed to download template " + path + " from Swift to secondary storage " + lPath + " , err=" + result; + errMsg = "failed to download template " + path + " from Swift to secondary storage " + lPath + + " , err=" + result; s_logger.warn(errMsg); throw new CloudRuntimeException(errMsg); } @@ -305,7 +503,8 @@ SecondaryStorageResource { lPath = lDir + "/" + path; result = swiftDownload(swift, "T-" + templateId.toString(), path, lPath); if (result != null) { - errMsg = "failed to download template " + path + " from Swift to secondary storage " + lPath + " , err=" + result; + errMsg = "failed to download template " + path + " from Swift to secondary storage " + lPath + + " , err=" + result; s_logger.warn(errMsg); throw new CloudRuntimeException(errMsg); } @@ -320,6 +519,59 @@ SecondaryStorageResource { } } + private Answer execute(DownloadCommand cmd) { + DataStoreTO dstore = cmd.getDataStore(); + if (dstore instanceof NfsTO || dstore instanceof S3TO) { + return _dlMgr.handleDownloadCommand(this, cmd); + } + /* + * else if (dstore instanceof S3TO) { // TODO: start download job to + * handle this // TODO: how to handle download progress for S3 S3TO s3 = + * (S3TO) cmd.getDataStore(); String url = cmd.getUrl(); String user = + * null; String password = null; if (cmd.getAuth() != null) { user = + * cmd.getAuth().getUserName(); password = new + * String(cmd.getAuth().getPassword()); } // get input stream from the + * given url InputStream in = UriUtils.getInputStreamFromUrl(url, user, + * password); URI uri; URL urlObj; try { uri = new URI(url); urlObj = + * new URL(url); } catch (URISyntaxException e) { throw new + * CloudRuntimeException("URI is incorrect: " + url); } catch + * (MalformedURLException e) { throw new + * CloudRuntimeException("URL is incorrect: " + url); } + * + * final String bucket = s3.getBucketName(); String path = null; if + * (cmd.getResourceType() == ResourceType.TEMPLATE) { // convention is + * no / in the end for install path based on // S3Utils implementation. + * // template key is // + * TEMPLATE_ROOT_DIR/account_id/template_id/template_name, by // adding + * template_name in the key, I can avoid generating a // + * template.properties file // for listTemplateCommand. path = + * determineS3TemplateDirectory(cmd.getAccountId(), cmd.getResourceId(), + * cmd.getName()); } else { path = + * determineS3VolumeDirectory(cmd.getAccountId(), cmd.getResourceId()); + * } + * + * String key = join(asList(path, urlObj.getFile()), S3Utils.SEPARATOR); + * S3Utils.putObject(s3, in, bucket, key); List s3Obj = + * S3Utils.getDirectory(s3, bucket, path); if (s3Obj == null || + * s3Obj.size() == 0) { return new Answer(cmd, false, + * "Failed to download to S3 bucket: " + bucket + " with key: " + key); + * } else { return new DownloadAnswer(null, 100, null, + * Status.DOWNLOADED, path, path, s3Obj.get(0).getSize(), + * s3Obj.get(0).getSize(), s3Obj .get(0).getETag()); } } + */ + else if (dstore instanceof SwiftTO) { + // TODO: need to move code from + // execute(uploadTemplateToSwiftFromSecondaryStorageCommand) here, + // but we need to handle + // source is url, most likely we need to modify our existing + // swiftUpload python script. + return new Answer(cmd, false, "Swift is not currently support DownloadCommand"); + } else { + return new Answer(cmd, false, "Unsupported image data store: " + dstore); + } + + } + private Answer execute(UploadTemplateToSwiftFromSecondaryStorageCommand cmd) { SwiftTO swift = cmd.getSwift(); String secondaryStorageUrl = cmd.getSecondaryStorageUrl(); @@ -335,7 +587,8 @@ SecondaryStorageResource { } String result = swiftUpload(swift, "T-" + templateId.toString(), lPath, "*"); if (result != null) { - String errMsg = "failed to upload template from secondary storage " + lPath + " to swift , err=" + result; + String errMsg = "failed to upload template from secondary storage " + lPath + " to swift , err=" + + result; s_logger.debug(errMsg); return new Answer(cmd, false, errMsg); } @@ -347,151 +600,81 @@ SecondaryStorageResource { } } - private Answer execute(UploadTemplateToS3FromSecondaryStorageCommand cmd) { + private ImageFormat getTemplateFormat(String filePath) { + String ext = null; + int extensionPos = filePath.lastIndexOf('.'); + int lastSeparator = Math.max(filePath.lastIndexOf('/'), filePath.lastIndexOf('\\')); + int i = lastSeparator > extensionPos ? -1 : extensionPos; + if (i > 0) { + ext = filePath.substring(i + 1); + } + if (ext != null) { + if (ext.equalsIgnoreCase("vhd")) + return ImageFormat.VHD; + else if (ext.equalsIgnoreCase("qcow2")) + return ImageFormat.QCOW2; + else if (ext.equalsIgnoreCase("ova")) + return ImageFormat.OVA; + else if (ext.equalsIgnoreCase("tar")) + return ImageFormat.TAR; + else if (ext.equalsIgnoreCase("img")) + return ImageFormat.RAW; + } - final S3TO s3 = cmd.getS3(); - final Long accountId = cmd.getAccountId(); - final Long templateId = cmd.getTemplateId(); + return null; + + } + + protected Answer copyFromNfsToS3(CopyCommand cmd) { + final DataTO srcData = cmd.getSrcTO(); + final DataTO destData = cmd.getDestTO(); + DataStoreTO srcDataStore = srcData.getDataStore(); + NfsTO srcStore = (NfsTO) srcDataStore; + DataStoreTO destDataStore = destData.getDataStore(); + + final S3TO s3 = (S3TO) destDataStore; try { - - final String templatePath = determineStorageTemplatePath( - cmd.getStoragePath(), accountId, templateId); + final String templatePath = determineStorageTemplatePath(srcStore.getUrl(), srcData.getPath()); if (s_logger.isDebugEnabled()) { - s_logger.debug("Found template id " + templateId - + " account id " + accountId + " from directory " - + templatePath + " to upload to S3."); - } - - if (!_storage.isDirectory(templatePath)) { - final String errMsg = format("S3 Sync Failure: Directory %1$s" - + "for template id %2$s does not exist.", templatePath, - templateId); - s_logger.error(errMsg); - return new Answer(cmd, false, errMsg); - } - - if (!_storage.isFile(templatePath + "/template.properties")) { - final String errMsg = format("S3 Sync Failure: Template id " - + "%1$s does not exist on the file system.", - templatePath); - s_logger.error(errMsg); - return new Answer(cmd, false, errMsg); - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug(format( - "Pushing template id %1$s from %2$s to S3...", - templateId, templatePath)); + s_logger.debug("Found " + srcData.getObjectType() + " from directory " + templatePath + + " to upload to S3."); } final String bucket = s3.getBucketName(); - putDirectory(s3, bucket, _storage.getFile(templatePath), - new FilenameFilter() { - @Override - public boolean accept(final File directory, - final String fileName) { - File fileToUpload = new File(directory.getAbsolutePath() + "/" + fileName); - return !fileName.startsWith(".") && !fileToUpload.isDirectory(); - } - }, new ObjectNamingStrategy() { - @Override - public String determineKey(final File file) { - s_logger.debug(String - .format("Determining key using account id %1$s and template id %2$s", - accountId, templateId)); - return join(S3Utils.SEPARATOR, determineS3TemplateDirectory(accountId, templateId), file.getName()); - } - }); + final File srcFile = _storage.getFile(templatePath); + ImageFormat format = this.getTemplateFormat(templatePath); + String key = destData.getPath() + S3Utils.SEPARATOR + srcFile.getName(); + putFile(s3, srcFile, bucket, key); - return new Answer( - cmd, - true, - format("Uploaded the contents of directory %1$s for template id %2$s to S3 bucket %3$s", - templatePath, templateId, bucket)); - - } catch (Exception e) { - - final String errMsg = format("Failed to upload template id %1$s", - templateId); - s_logger.error(errMsg, e); - return new Answer(cmd, false, errMsg); - - } - - } - - private Answer execute(DeleteObjectFromSwiftCommand cmd) { - SwiftTO swift = cmd.getSwift(); - String container = cmd.getContainer(); - String object = cmd.getObject(); - if (object == null) { - object = ""; - } - try { - String result = swiftDelete(swift, container, object); - if (result != null) { - String errMsg = "failed to delete object " + container + "/" + object + " , err=" + result; - s_logger.warn(errMsg); - return new Answer(cmd, false, errMsg); + DataTO retObj = null; + if (destData.getObjectType() == DataObjectType.TEMPLATE) { + TemplateObjectTO newTemplate = new TemplateObjectTO(); + newTemplate.setPath(key); + newTemplate.setSize(srcFile.length()); + newTemplate.setFormat(format); + retObj = newTemplate; + } else if (destData.getObjectType() == DataObjectType.VOLUME) { + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(key); + newVol.setSize(srcFile.length()); + retObj = newVol; } - return new Answer(cmd, true, "success"); + + return new CopyCmdAnswer(retObj); } catch (Exception e) { - String errMsg = cmd + " Command failed due to " + e.toString(); - s_logger.warn(errMsg, e); - return new Answer(cmd, false, errMsg); + s_logger.error("failed to upload" + srcData.getPath(), e); + return new CopyCmdAnswer("failed to upload" + srcData.getPath() + e.toString()); } - - } - - private Answer execute(final DeleteTemplateFromS3Command cmd) { - - final S3TO s3 = cmd.getS3(); - final Long accountId = cmd.getAccountId(); - final Long templateId = cmd.getTemplateId(); - - if (accountId == null || (accountId != null && accountId <= 0)) { - final String errorMessage = "No account id specified for S3 template deletion."; - s_logger.error(errorMessage); - return new Answer(cmd, false, errorMessage); - } - - if (templateId == null || (templateId != null && templateId <= 0)) { - final String errorMessage = "No template id specified for S3 template deletion."; - s_logger.error(errorMessage); - return new Answer(cmd, false, errorMessage); - } - - if (s3 == null) { - final String errorMessge = "No S3 client options provided"; - s_logger.error(errorMessge); - return new Answer(cmd, false, errorMessge); - } - - final String bucket = s3.getBucketName(); - try { - deleteDirectory(s3, bucket, - determineS3TemplateDirectory(templateId, accountId)); - return new Answer(cmd, true, String.format( - "Deleted template %1%s from bucket %2$s.", templateId, - bucket)); - } catch (Exception e) { - final String errorMessage = String - .format("Failed to delete templaet id %1$s from bucket %2$s due to the following error: %3$s", - templateId, bucket, e.getMessage()); - s_logger.error(errorMessage, e); - return new Answer(cmd, false, errorMessage); - } - } String swiftDownload(SwiftTO swift, String container, String rfilename, String lFullPath) { Script command = new Script("/bin/bash", s_logger); command.add("-c"); - command.add("/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A " - + swift.getUrl() + " -U " + swift.getAccount() + ":" + swift.getUserName() + " -K " + swift.getKey() - + " download " + container + " " + rfilename + " -o " + lFullPath); + command.add("/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A " + swift.getUrl() + + " -U " + swift.getAccount() + ":" + swift.getUserName() + " -K " + swift.getKey() + " download " + + container + " " + rfilename + " -o " + lFullPath); OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser(); String result = command.execute(parser); if (result != null) { @@ -516,8 +699,9 @@ SecondaryStorageResource { String swiftDownloadContainer(SwiftTO swift, String container, String ldir) { Script command = new Script("/bin/bash", s_logger); command.add("-c"); - command.add("cd " + ldir + ";/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A " + swift.getUrl() + " -U " + swift.getAccount() + ":" + swift.getUserName() + " -K " - + swift.getKey() + " download " + container); + command.add("cd " + ldir + ";/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A " + + swift.getUrl() + " -U " + swift.getAccount() + ":" + swift.getUserName() + " -K " + swift.getKey() + + " download " + container); OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser(); String result = command.execute(parser); if (result != null) { @@ -560,11 +744,15 @@ SecondaryStorageResource { Script command = new Script("/bin/bash", s_logger); command.add("-c"); if (size <= SWIFT_MAX_SIZE) { - command.add("cd " + lDir + ";/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A " + swift.getUrl() + " -U " + swift.getAccount() + ":" + swift.getUserName() - + " -K " + swift.getKey() + " upload " + container + " " + file); + command.add("cd " + lDir + + ";/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A " + + swift.getUrl() + " -U " + swift.getAccount() + ":" + swift.getUserName() + " -K " + + swift.getKey() + " upload " + container + " " + file); } else { - command.add("cd " + lDir + ";/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A " + swift.getUrl() + " -U " + swift.getAccount() + ":" + swift.getUserName() - + " -K " + swift.getKey() + " upload -S " + SWIFT_MAX_SIZE + " " + container + " " + file); + command.add("cd " + lDir + + ";/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A " + + swift.getUrl() + " -U " + swift.getAccount() + ":" + swift.getUserName() + " -K " + + swift.getKey() + " upload -S " + SWIFT_MAX_SIZE + " " + container + " " + file); } OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser(); String result = command.execute(parser); @@ -591,8 +779,9 @@ SecondaryStorageResource { String[] swiftList(SwiftTO swift, String container, String rFilename) { Script command = new Script("/bin/bash", s_logger); command.add("-c"); - command.add("/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A " + swift.getUrl() + " -U " + swift.getAccount() + ":" + swift.getUserName() + " -K " - + swift.getKey() + " list " + container + " " + rFilename); + command.add("/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A " + swift.getUrl() + + " -U " + swift.getAccount() + ":" + swift.getUserName() + " -K " + swift.getKey() + " list " + + container + " " + rFilename); OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser(); String result = command.execute(parser); if (result == null && parser.getLines() != null) { @@ -613,9 +802,9 @@ SecondaryStorageResource { String swiftDelete(SwiftTO swift, String container, String object) { Script command = new Script("/bin/bash", s_logger); command.add("-c"); - command.add("/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A " - + swift.getUrl() + " -U " + swift.getAccount() + ":" + swift.getUserName() + " -K " + swift.getKey() - + " delete " + container + " " + object); + command.add("/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A " + swift.getUrl() + + " -U " + swift.getAccount() + ":" + swift.getUserName() + " -K " + swift.getKey() + " delete " + + container + " " + object); OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser(); String result = command.execute(parser); if (result != null) { @@ -636,25 +825,80 @@ SecondaryStorageResource { return null; } + public Answer execute(DeleteSnapshotsDirCommand cmd) { + DataStoreTO dstore = cmd.getDataStore(); + if (dstore instanceof NfsTO) { + NfsTO nfs = (NfsTO) dstore; + String relativeSnapshotPath = cmd.getDirectory(); + String parent = getRootDir(nfs.getUrl()); - public Answer execute(DeleteSnapshotsDirCommand cmd){ - String secondaryStorageUrl = cmd.getSecondaryStorageUrl(); - Long accountId = cmd.getAccountId(); - Long volumeId = cmd.getVolumeId(); - try { - String parent = getRootDir(secondaryStorageUrl); - String lPath = parent + "/snapshots/" + String.valueOf(accountId) + "/" + String.valueOf(volumeId) + "/*"; + if (relativeSnapshotPath.startsWith(File.separator)) { + relativeSnapshotPath = relativeSnapshotPath.substring(1); + } + + if (!parent.endsWith(File.separator)) { + parent += File.separator; + } + String absoluteSnapshotPath = parent + relativeSnapshotPath; + File snapshotDir = new File(absoluteSnapshotPath); + String details = null; + if (!snapshotDir.exists()) { + details = "snapshot directory " + snapshotDir.getName() + " doesn't exist"; + s_logger.debug(details); + return new Answer(cmd, true, details); + } + // delete all files in the directory + String lPath = absoluteSnapshotPath + "/*"; String result = deleteLocalFile(lPath); if (result != null) { String errMsg = "failed to delete all snapshots " + lPath + " , err=" + result; s_logger.warn(errMsg); return new Answer(cmd, false, errMsg); } - return new Answer(cmd, true, "success"); - } catch (Exception e) { - String errMsg = cmd + " Command failed due to " + e.toString(); - s_logger.warn(errMsg, e); - return new Answer(cmd, false, errMsg); + // delete the directory + if (!snapshotDir.delete()) { + details = "Unable to delete directory " + snapshotDir.getName() + " under snapshot path " + + relativeSnapshotPath; + s_logger.debug(details); + return new Answer(cmd, false, details); + } + return new Answer(cmd, true, null); + } else if (dstore instanceof S3TO) { + final S3TO s3 = (S3TO) dstore; + final String path = cmd.getDirectory(); + final String bucket = s3.getBucketName(); + try { + S3Utils.deleteDirectory(s3, bucket, path); + return new Answer(cmd, true, String.format("Deleted snapshot %1%s from bucket %2$s.", path, bucket)); + } catch (Exception e) { + final String errorMessage = String.format( + "Failed to delete snapshot %1$s from bucket %2$s due to the following error: %3$s", path, + bucket, e.getMessage()); + s_logger.error(errorMessage, e); + return new Answer(cmd, false, errorMessage); + } + } else if (dstore instanceof SwiftTO) { + String path = cmd.getDirectory(); + String volumeId = StringUtils.substringAfterLast(path, "/"); // assuming + // that + // the + // filename + // is + // the + // last + // section + // in + // the + // path + String result = swiftDelete((SwiftTO) dstore, "V-" + volumeId.toString(), ""); + if (result != null) { + String errMsg = "failed to delete snapshot for volume " + volumeId + " , err=" + result; + s_logger.warn(errMsg); + return new Answer(cmd, false, errMsg); + } + return new Answer(cmd, true, "Deleted snapshot " + path + " from swift"); + } else { + return new Answer(cmd, false, "Unsupported image data store: " + dstore); } } @@ -667,54 +911,41 @@ SecondaryStorageResource { try { - executeWithNoWaitLock(determineSnapshotLockId(accountId, volumeId), - new Callable() { + executeWithNoWaitLock(determineSnapshotLockId(accountId, volumeId), new Callable() { @Override public Void call() throws Exception { - final String directoryName = determineSnapshotLocalDirectory( - secondaryStorageUrl, accountId, volumeId); + final String directoryName = determineSnapshotLocalDirectory(secondaryStorageUrl, accountId, + volumeId); String result = createLocalDir(directoryName); if (result != null) { - throw new InternalErrorException( - format("Failed to create directory %1$s during S3 snapshot download.", - directoryName)); + throw new InternalErrorException(format( + "Failed to create directory %1$s during S3 snapshot download.", directoryName)); } - final String snapshotFileName = determineSnapshotBackupFilename(cmd - .getSnapshotUuid()); - final String key = determineSnapshotS3Key( - accountId, volumeId, snapshotFileName); - final File targetFile = S3Utils.getFile(s3, - s3.getBucketName(), key, - _storage.getFile(directoryName), - new FileNamingStrategy() { + final String snapshotFileName = determineSnapshotBackupFilename(cmd.getSnapshotUuid()); + final String key = determineSnapshotS3Key(accountId, volumeId, snapshotFileName); + final File targetFile = S3Utils.getFile(s3, s3.getBucketName(), key, + _storage.getFile(directoryName), new FileNamingStrategy() { - @Override - public String determineFileName( - String key) { - return snapshotFileName; - } + @Override + public String determineFileName(String key) { + return snapshotFileName; + } - }); + }); if (cmd.getParent() != null) { - final String parentPath = join( - File.pathSeparator, directoryName, - determineSnapshotBackupFilename(cmd - .getParent())); - result = setVhdParent( - targetFile.getAbsolutePath(), - parentPath); + final String parentPath = join(File.pathSeparator, directoryName, + determineSnapshotBackupFilename(cmd.getParent())); + result = setVhdParent(targetFile.getAbsolutePath(), parentPath); if (result != null) { - throw new InternalErrorException( - format("Failed to set the parent for backup %1$s to %2$s due to %3$s.", - targetFile - .getAbsolutePath(), - parentPath, result)); + throw new InternalErrorException(format( + "Failed to set the parent for backup %1$s to %2$s due to %3$s.", + targetFile.getAbsolutePath(), parentPath, result)); } } @@ -725,11 +956,9 @@ SecondaryStorageResource { }); - return new Answer( - cmd, - true, - format("Succesfully retrieved volume id %1$s for account id %2$s to %3$s from S3.", - volumeId, accountId, secondaryStorageUrl)); + return new Answer(cmd, true, format( + "Succesfully retrieved volume id %1$s for account id %2$s to %3$s from S3.", volumeId, accountId, + secondaryStorageUrl)); } catch (Exception e) { final String errMsg = format( @@ -741,28 +970,23 @@ SecondaryStorageResource { } - private String determineSnapshotS3Directory(final Long accountId, - final Long volumeId) { + private String determineSnapshotS3Directory(final Long accountId, final Long volumeId) { return join(S3Utils.SEPARATOR, SNAPSHOT_ROOT_DIR, accountId, volumeId); } - private String determineSnapshotS3Key(final Long accountId, - final Long volumeId, final String snapshotFileName) { + private String determineSnapshotS3Key(final Long accountId, final Long volumeId, final String snapshotFileName) { - final String directoryName = determineSnapshotS3Directory(accountId, - volumeId); + final String directoryName = determineSnapshotS3Directory(accountId, volumeId); return join(S3Utils.SEPARATOR, directoryName, snapshotFileName); } - private String determineSnapshotLocalDirectory( - final String secondaryStorageUrl, final Long accountId, + private String determineSnapshotLocalDirectory(final String secondaryStorageUrl, final Long accountId, final Long volumeId) { - return join(File.pathSeparator, getRootDir(secondaryStorageUrl), - SNAPSHOT_ROOT_DIR, accountId, volumeId); + return join(File.pathSeparator, getRootDir(secondaryStorageUrl), SNAPSHOT_ROOT_DIR, accountId, volumeId); } - public Answer execute(DownloadSnapshotFromSwiftCommand cmd){ + public Answer execute(DownloadSnapshotFromSwiftCommand cmd) { SwiftTO swift = cmd.getSwift(); String secondaryStorageUrl = cmd.getSecondaryStorageUrl(); Long accountId = cmd.getAccountId(); @@ -775,13 +999,13 @@ SecondaryStorageResource { String lPath = parent + "/snapshots/" + String.valueOf(accountId) + "/" + String.valueOf(volumeId); String result = createLocalDir(lPath); - if ( result != null ) { + if (result != null) { errMsg = "downloadSnapshotFromSwiftCommand failed due to Create local path failed"; s_logger.warn(errMsg); throw new InternalErrorException(errMsg); } String lFilename = rFilename; - if ( rFilename.startsWith("VHD-") ) { + if (rFilename.startsWith("VHD-")) { lFilename = rFilename.replace("VHD-", "") + ".vhd"; } String lFullPath = lPath + "/" + lFilename; @@ -814,7 +1038,12 @@ SecondaryStorageResource { private Answer execute(ComputeChecksumCommand cmd) { String relativeTemplatePath = cmd.getTemplatePath(); - String parent = getRootDir(cmd); + DataStoreTO store = cmd.getStore(); + if (!(store instanceof NfsTO)) { + return new Answer(cmd, false, "can't handle non nfs data store"); + } + NfsTO nfsStore = (NfsTO) store; + String parent = getRootDir(nfsStore.getUrl()); if (relativeTemplatePath.startsWith(File.separator)) { relativeTemplatePath = relativeTemplatePath.substring(1); @@ -826,45 +1055,43 @@ SecondaryStorageResource { String absoluteTemplatePath = parent + relativeTemplatePath; MessageDigest digest; String checksum = null; - File f = new File(absoluteTemplatePath); + File f = new File(absoluteTemplatePath); InputStream is = null; byte[] buffer = new byte[8192]; int read = 0; - if(s_logger.isDebugEnabled()){ - s_logger.debug("parent path " +parent+ " relative template path " +relativeTemplatePath ); + if (s_logger.isDebugEnabled()) { + s_logger.debug("parent path " + parent + " relative template path " + relativeTemplatePath); } - try { - digest = MessageDigest.getInstance("MD5"); - is = new FileInputStream(f); - while( (read = is.read(buffer)) > 0) { + digest = MessageDigest.getInstance("MD5"); + is = new FileInputStream(f); + while ((read = is.read(buffer)) > 0) { digest.update(buffer, 0, read); - } + } byte[] md5sum = digest.digest(); BigInteger bigInt = new BigInteger(1, md5sum); checksum = bigInt.toString(16); - if(s_logger.isDebugEnabled()){ - s_logger.debug("Successfully calculated checksum for file " +absoluteTemplatePath+ " - " +checksum ); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully calculated checksum for file " + absoluteTemplatePath + " - " + checksum); } - }catch(IOException e) { + } catch (IOException e) { String logMsg = "Unable to process file for MD5 - " + absoluteTemplatePath; s_logger.error(logMsg); - return new Answer(cmd, false, checksum); - }catch (NoSuchAlgorithmException e) { return new Answer(cmd, false, checksum); - } - finally { + } catch (NoSuchAlgorithmException e) { + return new Answer(cmd, false, checksum); + } finally { try { - if(is != null) + if (is != null) is.close(); } catch (IOException e) { - if(s_logger.isDebugEnabled()){ - s_logger.debug("Could not close the file " +absoluteTemplatePath); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Could not close the file " + absoluteTemplatePath); } - return new Answer(cmd, false, checksum); - } + return new Answer(cmd, false, checksum); + } } return new Answer(cmd, true, checksum); @@ -904,43 +1131,52 @@ SecondaryStorageResource { } private Answer execute(SecStorageSetupCommand cmd) { - if (!_inSystemVM){ + if (!_inSystemVM) { return new Answer(cmd, true, null); } - String secUrl = cmd.getSecUrl(); - try { - URI uri = new URI(secUrl); - String nfsHost = uri.getHost(); + DataStoreTO dStore = cmd.getDataStore(); + if (dStore instanceof NfsTO) { + String secUrl = cmd.getSecUrl(); + try { + URI uri = new URI(secUrl); + String nfsHost = uri.getHost(); - InetAddress nfsHostAddr = InetAddress.getByName(nfsHost); - String nfsHostIp = nfsHostAddr.getHostAddress(); + InetAddress nfsHostAddr = InetAddress.getByName(nfsHost); + String nfsHostIp = nfsHostAddr.getHostAddress(); - addRouteToInternalIpOrCidr(_storageGateway, _storageIp, _storageNetmask, nfsHostIp); - String nfsPath = nfsHostIp + ":" + uri.getPath(); - String dir = UUID.nameUUIDFromBytes(nfsPath.getBytes()).toString(); - String root = _parent + "/" + dir; - mount(root, nfsPath); + addRouteToInternalIpOrCidr(_storageGateway, _storageIp, _storageNetmask, nfsHostIp); + String nfsPath = nfsHostIp + ":" + uri.getPath(); + String dir = UUID.nameUUIDFromBytes(nfsPath.getBytes()).toString(); + String root = _parent + "/" + dir; + mount(root, nfsPath); - configCerts(cmd.getCerts()); + configCerts(cmd.getCerts()); - nfsIps.add(nfsHostIp); - return new SecStorageSetupAnswer(dir); - } catch (Exception e) { - String msg = "GetRootDir for " + secUrl + " failed due to " + e.toString(); - s_logger.error(msg); - return new Answer(cmd, false, msg); + nfsIps.add(nfsHostIp); + return new SecStorageSetupAnswer(dir); + } catch (Exception e) { + String msg = "GetRootDir for " + secUrl + " failed due to " + e.toString(); + s_logger.error(msg); + return new Answer(cmd, false, msg); + } + } else { + // TODO: what do we need to setup for S3/Swift, maybe need to mount + // to some cache storage + return new Answer(cmd, true, null); } } - private String deleteSnapshotBackupFromLocalFileSystem( - final String secondaryStorageUrl, final Long accountId, + private String deleteSnapshotBackupFromLocalFileSystem(final String secondaryStorageUrl, final Long accountId, final Long volumeId, final String name, final Boolean deleteAllFlag) { - - final String lPath = determineSnapshotLocalDirectory( - secondaryStorageUrl, accountId, volumeId) - + File.pathSeparator - + (deleteAllFlag ? "*" : "*" + name + "*"); + String lPath = null; + int index = name.lastIndexOf(File.separator); + String snapshotPath = name.substring(0, index); + if (deleteAllFlag) { + lPath = this.getRootDir(secondaryStorageUrl) + File.separator + snapshotPath + File.separator + "*"; + } else { + lPath = this.getRootDir(secondaryStorageUrl) + File.separator + name + "*"; + } final String result = deleteLocalFile(lPath); @@ -952,41 +1188,26 @@ SecondaryStorageResource { } - private String deleteSnapshotBackupfromS3(final S3TO s3, - final String secondaryStorageUrl, final Long accountId, - final Long volumeId, final String name, final Boolean deleteAllFlag) { + private String deleteSnapshotBackupfromS3(final S3TO s3, final Long accountId, final Long volumeId, + final String name, final Boolean deleteAllFlag) { try { final String bucket = s3.getBucketName(); - final String result = executeWithNoWaitLock( - determineSnapshotLockId(accountId, volumeId), + final String result = executeWithNoWaitLock(determineSnapshotLockId(accountId, volumeId), new Callable() { @Override public String call() throws Exception { - final String innerResult = deleteSnapshotBackupFromLocalFileSystem( - secondaryStorageUrl, accountId, volumeId, - name, deleteAllFlag); - if (innerResult != null) { - return innerResult; - } - if (deleteAllFlag) { - S3Utils.deleteDirectory( - s3, - bucket, - determineSnapshotS3Directory(accountId, - volumeId)); + S3Utils.deleteDirectory(s3, bucket, determineSnapshotS3Directory(accountId, volumeId)); } else { S3Utils.deleteObject( s3, bucket, - determineSnapshotS3Key( - accountId, - volumeId, + determineSnapshotS3Key(accountId, volumeId, determineSnapshotBackupFilename(name))); } @@ -1000,10 +1221,8 @@ SecondaryStorageResource { } catch (Exception e) { - s_logger.error( - String.format( - "Failed to delete snapshot backup for account id %1$s volume id %2$sfrom S3.", - accountId, volumeId), e); + s_logger.error(String.format("Failed to delete snapshot backup for account id %1$s volume id %2$sfrom S3.", + accountId, volumeId), e); return e.getMessage(); } @@ -1014,65 +1233,89 @@ SecondaryStorageResource { return snapshotUuid + ".vhd"; } - private String determineSnapshotLockId(final Long accountId, - final Long volumeId) { + private String determineSnapshotLockId(final Long accountId, final Long volumeId) { return join("_", "SNAPSHOT", accountId, volumeId); } - protected Answer execute(final DeleteSnapshotBackupCommand cmd) { - String secondaryStorageUrl = cmd.getSecondaryStorageUrl(); - Long accountId = cmd.getAccountId(); - Long volumeId = cmd.getVolumeId(); - String name = cmd.getSnapshotUuid(); - try { - SwiftTO swift = cmd.getSwift(); - S3TO s3 = cmd.getS3(); - if (swift == null) { - final String result = deleteSnapshotBackupFromLocalFileSystem( - secondaryStorageUrl, accountId, volumeId, name, - cmd.isAll()); - if (result != null) { - s_logger.warn(result); - return new Answer(cmd, false, result); - } - } else if (s3 != null) { - final String result = deleteSnapshotBackupfromS3(s3, - secondaryStorageUrl, accountId, volumeId, name, - cmd.isAll()); - if (result != null) { - s_logger.warn(result); - return new Answer(cmd, false, result); - } - } else { - String filename; - if (cmd.isAll()) { - filename = ""; - } else { - filename = name; - } - String result = swiftDelete(swift, "V-" + volumeId.toString(), filename); - if (result != null) { - String errMsg = "failed to delete snapshot " + filename + " , err=" + result; - s_logger.warn(errMsg); - return new Answer(cmd, false, errMsg); - } + protected Answer deleteSnapshot(final DeleteCommand cmd) { + DataTO obj = cmd.getData(); + DataStoreTO dstore = obj.getDataStore(); + if (dstore instanceof NfsTO) { + NfsTO nfs = (NfsTO) dstore; + String relativeSnapshotPath = obj.getPath(); + String parent = getRootDir(nfs.getUrl()); + + if (relativeSnapshotPath.startsWith(File.separator)) { + relativeSnapshotPath = relativeSnapshotPath.substring(1); } - return new Answer(cmd, true, "success"); - } catch (Exception e) { - String errMsg = cmd + " Command failed due to " + e.toString(); - s_logger.warn(errMsg, e); - return new Answer(cmd, false, errMsg); + + if (!parent.endsWith(File.separator)) { + parent += File.separator; + } + String absoluteSnapshotPath = parent + relativeSnapshotPath; + File snapshot = new File(absoluteSnapshotPath); + String details = null; + if (!snapshot.exists()) { + details = "snapshot file " + snapshot.getName() + " doesn't exist"; + s_logger.debug(details); + return new Answer(cmd, true, details); + } + + if (!snapshot.delete()) { + return new Answer(cmd, false, "Unable to delete file " + snapshot.getName() + " under install path " + + relativeSnapshotPath); + } + + return new Answer(cmd, true, null); + } else if (dstore instanceof S3TO) { + final S3TO s3 = (S3TO) dstore; + final String path = obj.getPath(); + final String bucket = s3.getBucketName(); + try { + S3Utils.deleteObject(s3, bucket, path); + return new Answer(cmd, true, String.format("Deleted snapshot %1%s from bucket %2$s.", path, bucket)); + } catch (Exception e) { + final String errorMessage = String.format( + "Failed to delete snapshot %1$s from bucket %2$s due to the following error: %3$s", path, + bucket, e.getMessage()); + s_logger.error(errorMessage, e); + return new Answer(cmd, false, errorMessage); + } + } else if (dstore instanceof SwiftTO) { + String path = obj.getPath(); + String filename = StringUtils.substringAfterLast(path, "/"); // assuming + // that + // the + // filename + // is + // the + // last + // section + // in + // the + // path + String volumeId = StringUtils.substringAfterLast(StringUtils.substringBeforeLast(path, "/"), "/"); + String result = swiftDelete((SwiftTO) dstore, "V-" + volumeId, filename); + if (result != null) { + String errMsg = "failed to delete snapshot " + filename + " , err=" + result; + s_logger.warn(errMsg); + return new Answer(cmd, false, errMsg); + } + return new Answer(cmd, true, "Deleted snapshot " + path + " from swift"); + } else { + return new Answer(cmd, false, "Unsupported image data store: " + dstore); } + } - Map swiftListTemplate(SwiftTO swift) { + Map swiftListTemplate(SwiftTO swift) { String[] containers = swiftList(swift, "", ""); if (containers == null) { return null; } - Map tmpltInfos = new HashMap(); - for( String container : containers) { - if ( container.startsWith("T-")) { + Map tmpltInfos = new HashMap(); + for (String container : containers) { + if (container.startsWith("T-")) { String ldir = _tmpltDir + "/" + UUID.randomUUID().toString(); createLocalDir(ldir); String lFullPath = ldir + "/" + _tmpltpp; @@ -1087,7 +1330,7 @@ SecondaryStorageResource { s_logger.warn("Unable to load template location " + ldir + " due to " + e.toString(), e); continue; } - TemplateInfo tInfo = loc.getTemplateInfo(); + TemplateProp tInfo = loc.getTemplateInfo(); tInfo.setInstallPath(container); tmpltInfos.put(tInfo.getTemplateName(), tInfo); loc.purge(); @@ -1098,37 +1341,105 @@ SecondaryStorageResource { } - private Answer execute(ListTemplateCommand cmd) { + Map s3ListTemplate(S3TO s3) { + String bucket = s3.getBucketName(); + // List the objects in the source directory on S3 + final List objectSummaries = S3Utils.getDirectory(s3, bucket, this.TEMPLATE_ROOT_DIR); + if (objectSummaries == null) + return null; + Map tmpltInfos = new HashMap(); + for (S3ObjectSummary objectSummary : objectSummaries) { + String key = objectSummary.getKey(); + // String installPath = StringUtils.substringBeforeLast(key, + // S3Utils.SEPARATOR); + String uniqueName = this.determineS3TemplateNameFromKey(key); + // TODO: isPublic value, where to get? + TemplateProp tInfo = new TemplateProp(uniqueName, key, objectSummary.getSize(), objectSummary.getSize(), + true, false); + tmpltInfos.put(uniqueName, tInfo); + } + return tmpltInfos; - if (cmd.getSwift() != null) { - Map templateInfos = swiftListTemplate(cmd.getSwift()); - return new ListTemplateAnswer(cmd.getSwift().toString(), templateInfos); + } + + Map s3ListVolume(S3TO s3) { + String bucket = s3.getBucketName(); + // List the objects in the source directory on S3 + final List objectSummaries = S3Utils.getDirectory(s3, bucket, this.VOLUME_ROOT_DIR); + if (objectSummaries == null) + return null; + Map tmpltInfos = new HashMap(); + for (S3ObjectSummary objectSummary : objectSummaries) { + String key = objectSummary.getKey(); + // String installPath = StringUtils.substringBeforeLast(key, + // S3Utils.SEPARATOR); + Long id = this.determineS3VolumeIdFromKey(key); + // TODO: how to get volume template name + TemplateProp tInfo = new TemplateProp(id.toString(), key, objectSummary.getSize(), objectSummary.getSize(), + true, false); + tmpltInfos.put(id, tInfo); + } + return tmpltInfos; + + } + + private Answer execute(ListTemplateCommand cmd) { + if (!_inSystemVM) { + return new Answer(cmd, true, null); + } + + DataStoreTO store = cmd.getDataStore(); + if (store instanceof NfsTO) { + NfsTO nfs = (NfsTO) store; + String secUrl = nfs.getUrl(); + String root = getRootDir(secUrl); + Map templateInfos = _dlMgr.gatherTemplateInfo(root); + return new ListTemplateAnswer(secUrl, templateInfos); + } else if (store instanceof SwiftTO) { + SwiftTO swift = (SwiftTO) store; + Map templateInfos = swiftListTemplate(swift); + return new ListTemplateAnswer(swift.toString(), templateInfos); + } else if (store instanceof S3TO) { + S3TO s3 = (S3TO) store; + Map templateInfos = s3ListTemplate(s3); + return new ListTemplateAnswer(s3.getBucketName(), templateInfos); } else { - String root = getRootDir(cmd.getSecUrl()); - Map templateInfos = _dlMgr.gatherTemplateInfo(root); - return new ListTemplateAnswer(cmd.getSecUrl(), templateInfos); + return new Answer(cmd, false, "Unsupported image data store: " + store); } } private Answer execute(ListVolumeCommand cmd) { - - String root = getRootDir(cmd.getSecUrl()); - Map templateInfos = _dlMgr.gatherVolumeInfo(root); - return new ListVolumeAnswer(cmd.getSecUrl(), templateInfos); + if (!_inSystemVM) { + return new Answer(cmd, true, null); + } + DataStoreTO store = cmd.getDataStore(); + if (store instanceof NfsTO) { + NfsTO nfs = (NfsTO) store; + String root = getRootDir(cmd.getSecUrl()); + Map templateInfos = _dlMgr.gatherVolumeInfo(root); + return new ListVolumeAnswer(cmd.getSecUrl(), templateInfos); + } else if (store instanceof S3TO) { + S3TO s3 = (S3TO) store; + Map templateInfos = s3ListVolume(s3); + return new ListVolumeAnswer(s3.getBucketName(), templateInfos); + } else { + return new Answer(cmd, false, "Unsupported image data store: " + store); + } } private Answer execute(SecStorageVMSetupCommand cmd) { - if (!_inSystemVM){ + if (!_inSystemVM) { return new Answer(cmd, true, null); } boolean success = true; StringBuilder result = new StringBuilder(); - for (String cidr: cmd.getAllowedInternalSites()) { + for (String cidr : cmd.getAllowedInternalSites()) { if (nfsIps.contains(cidr)) { /* - * if the internal download ip is the same with secondary storage ip, adding internal sites will flush - * ip route to nfs through storage ip. + * if the internal download ip is the same with secondary + * storage ip, adding internal sites will flush ip route to nfs + * through storage ip. */ continue; } @@ -1210,11 +1521,12 @@ SecondaryStorageResource { Script command = new Script("/bin/bash", s_logger); String intf = "eth1"; command.add("-c"); - command.add("iptables -I OUTPUT -o " + intf + " -d " + destCidr + " -p tcp -m state --state NEW -m tcp -j ACCEPT"); + command.add("iptables -I OUTPUT -o " + intf + " -d " + destCidr + + " -p tcp -m state --state NEW -m tcp -j ACCEPT"); String result = command.execute(); if (result != null) { - s_logger.warn("Error in allowing outgoing to " + destCidr + ", err=" + result ); + s_logger.warn("Error in allowing outgoing to " + destCidr + ", err=" + result); return "Error in allowing outgoing to " + destCidr + ", err=" + result; } @@ -1224,21 +1536,21 @@ SecondaryStorageResource { } private Answer execute(SecStorageFirewallCfgCommand cmd) { - if (!_inSystemVM){ + if (!_inSystemVM) { return new Answer(cmd, true, null); } List ipList = new ArrayList(); - for (PortConfig pCfg:cmd.getPortConfigs()){ + for (PortConfig pCfg : cmd.getPortConfigs()) { if (pCfg.isAdd()) { - ipList.add(pCfg.getSourceIp()); + ipList.add(pCfg.getSourceIp()); } } boolean success = true; String result; result = configureIpFirewall(ipList, cmd.getIsAppendAIp()); - if (result !=null) + if (result != null) success = false; return new Answer(cmd, success, result); @@ -1251,157 +1563,228 @@ SecondaryStorageResource { if (usedSize == -1 || totalSize == -1) { return new GetStorageStatsAnswer(cmd, "Unable to get storage stats"); } else { - return new GetStorageStatsAnswer(cmd, totalSize, usedSize) ; + return new GetStorageStatsAnswer(cmd, totalSize, usedSize); } } - protected Answer execute(final DeleteTemplateCommand cmd) { - String relativeTemplatePath = cmd.getTemplatePath(); - String parent = getRootDir(cmd); - - if (relativeTemplatePath.startsWith(File.separator)) { - relativeTemplatePath = relativeTemplatePath.substring(1); + protected Answer execute(final DeleteCommand cmd) { + DataTO obj = cmd.getData(); + DataObjectType objType = obj.getObjectType(); + switch (objType) { + case TEMPLATE: + return deleteTemplate(cmd); + case VOLUME: + return deleteVolume(cmd); + case SNAPSHOT: + return deleteSnapshot(cmd); } + return Answer.createUnsupportedCommandAnswer(cmd); + } - if (!parent.endsWith(File.separator)) { - parent += File.separator; - } - String absoluteTemplatePath = parent + relativeTemplatePath; - File tmpltParent = new File(absoluteTemplatePath).getParentFile(); - String details = null; - if (!tmpltParent.exists()) { - details = "template parent directory " + tmpltParent.getName() + " doesn't exist"; - s_logger.debug(details); - return new Answer(cmd, true, details); - } - File[] tmpltFiles = tmpltParent.listFiles(); - if (tmpltFiles == null || tmpltFiles.length == 0) { - details = "No files under template parent directory " + tmpltParent.getName(); - s_logger.debug(details); - } else { - boolean found = false; - for (File f : tmpltFiles) { - if (!found && f.getName().equals("template.properties")) { - found = true; - } + protected Answer deleteTemplate(DeleteCommand cmd) { + DataTO obj = cmd.getData(); + DataStoreTO dstore = obj.getDataStore(); + if (dstore instanceof NfsTO) { + NfsTO nfs = (NfsTO) dstore; + String relativeTemplatePath = obj.getPath(); + String parent = getRootDir(nfs.getUrl()); - // KVM HA monitor makes a mess in the templates with its heartbeat tests - // Don't let this stop us from cleaning up the template - if (f.isDirectory() && f.getName().equals("KVMHA")) { - s_logger.debug("Deleting KVMHA directory contents from template location"); - File[] haFiles = f.listFiles(); - for (File haFile : haFiles) { - haFile.delete(); - } - } - - if (!f.delete()) { - return new Answer(cmd, false, "Unable to delete file " + f.getName() + " under Template path " - + relativeTemplatePath); - } + if (relativeTemplatePath.startsWith(File.separator)) { + relativeTemplatePath = relativeTemplatePath.substring(1); } - if (!found) { - details = "Can not find template.properties under " + tmpltParent.getName(); + + if (!parent.endsWith(File.separator)) { + parent += File.separator; + } + String absoluteTemplatePath = parent + relativeTemplatePath; + File tmpltParent = new File(absoluteTemplatePath).getParentFile(); + String details = null; + if (!tmpltParent.exists()) { + details = "template parent directory " + tmpltParent.getName() + " doesn't exist"; s_logger.debug(details); + return new Answer(cmd, true, details); } - } - if (!tmpltParent.delete()) { - details = "Unable to delete directory " + tmpltParent.getName() + " under Template path " - + relativeTemplatePath; - s_logger.debug(details); - return new Answer(cmd, false, details); - } - return new Answer(cmd, true, null); - } - - protected Answer execute(final DeleteVolumeCommand cmd) { - String relativeVolumePath = cmd.getVolumePath(); - String parent = getRootDir(cmd); - - if (relativeVolumePath.startsWith(File.separator)) { - relativeVolumePath = relativeVolumePath.substring(1); - } - - if (!parent.endsWith(File.separator)) { - parent += File.separator; - } - String absoluteVolumePath = parent + relativeVolumePath; - File tmpltParent = new File(absoluteVolumePath).getParentFile(); - String details = null; - if (!tmpltParent.exists()) { - details = "volume parent directory " + tmpltParent.getName() + " doesn't exist"; - s_logger.debug(details); - return new Answer(cmd, true, details); - } - File[] tmpltFiles = tmpltParent.listFiles(); - if (tmpltFiles == null || tmpltFiles.length == 0) { - details = "No files under volume parent directory " + tmpltParent.getName(); - s_logger.debug(details); - } else { - boolean found = false; - for (File f : tmpltFiles) { - if (!found && f.getName().equals("volume.properties")) { - found = true; - } - - // KVM HA monitor makes a mess in the templates with its heartbeat tests - // Don't let this stop us from cleaning up the template - if (f.isDirectory() && f.getName().equals("KVMHA")) { - s_logger.debug("Deleting KVMHA directory contents from template location"); - File[] haFiles = f.listFiles(); - for (File haFile : haFiles) { - haFile.delete(); - } - } - - if (!f.delete()) { - return new Answer(cmd, false, "Unable to delete file " + f.getName() + " under Volume path " - + relativeVolumePath); - } - } - if (!found) { - details = "Can not find volume.properties under " + tmpltParent.getName(); + File[] tmpltFiles = tmpltParent.listFiles(); + if (tmpltFiles == null || tmpltFiles.length == 0) { + details = "No files under template parent directory " + tmpltParent.getName(); s_logger.debug(details); - } - } - if (!tmpltParent.delete()) { - details = "Unable to delete directory " + tmpltParent.getName() + " under Volume path " - + relativeVolumePath; - s_logger.debug(details); - return new Answer(cmd, false, details); - } - return new Answer(cmd, true, null); - } - - Answer execute(CleanupSnapshotBackupCommand cmd) { - String parent = getRootDir(cmd.getSecondaryStoragePoolURL()); - if (!parent.endsWith(File.separator)) { - parent += File.separator; - } - String absoluteSnapsthotDir = parent + File.separator + "snapshots" + File.separator + cmd.getAccountId() + File.separator + cmd.getVolumeId(); - File ssParent = new File(absoluteSnapsthotDir); - if (ssParent.exists() && ssParent.isDirectory()) { - File[] files = ssParent.listFiles(); - for (File file : files) { + } else { boolean found = false; - String filename = file.getName(); - for (String uuid : cmd.getValidBackupUUIDs()) { - if (filename.startsWith(uuid)) { + for (File f : tmpltFiles) { + if (!found && f.getName().equals("template.properties")) { found = true; - break; + } + + // KVM HA monitor makes a mess in the templates with its + // heartbeat tests + // Don't let this stop us from cleaning up the template + if (f.isDirectory() && f.getName().equals("KVMHA")) { + s_logger.debug("Deleting KVMHA directory contents from template location"); + File[] haFiles = f.listFiles(); + for (File haFile : haFiles) { + haFile.delete(); + } + } + + if (!f.delete()) { + return new Answer(cmd, false, "Unable to delete file " + f.getName() + " under Template path " + + relativeTemplatePath); + } + } + + if (!found) { + details = "Can not find template.properties under " + tmpltParent.getName(); + s_logger.debug(details); + } + } + if (!tmpltParent.delete()) { + details = "Unable to delete directory " + tmpltParent.getName() + " under Template path " + + relativeTemplatePath; + s_logger.debug(details); + return new Answer(cmd, false, details); + } + return new Answer(cmd, true, null); + } else if (dstore instanceof S3TO) { + final S3TO s3 = (S3TO) dstore; + final String path = obj.getPath(); + final String bucket = s3.getBucketName(); + try { + S3Utils.deleteDirectory(s3, bucket, path); + return new Answer(cmd, true, String.format("Deleted template %1$s from bucket %2$s.", path, bucket)); + } catch (Exception e) { + final String errorMessage = String.format( + "Failed to delete template %1$s from bucket %2$s due to the following error: %3$s", path, + bucket, e.getMessage()); + s_logger.error(errorMessage, e); + return new Answer(cmd, false, errorMessage); + } + } else if (dstore instanceof SwiftTO) { + SwiftTO swift = (SwiftTO) dstore; + String container = "T-" + obj.getId(); + String object = ""; + + try { + String result = swiftDelete(swift, container, object); + if (result != null) { + String errMsg = "failed to delete object " + container + "/" + object + " , err=" + result; + s_logger.warn(errMsg); + return new Answer(cmd, false, errMsg); + } + return new Answer(cmd, true, "success"); + } catch (Exception e) { + String errMsg = cmd + " Command failed due to " + e.toString(); + s_logger.warn(errMsg, e); + return new Answer(cmd, false, errMsg); + } + } else { + return new Answer(cmd, false, "Unsupported image data store: " + dstore); + } + } + + protected Answer deleteVolume(final DeleteCommand cmd) { + DataTO obj = cmd.getData(); + DataStoreTO dstore = obj.getDataStore(); + if (dstore instanceof NfsTO) { + NfsTO nfs = (NfsTO) dstore; + String relativeVolumePath = obj.getPath(); + String parent = getRootDir(nfs.getUrl()); + + if (relativeVolumePath.startsWith(File.separator)) { + relativeVolumePath = relativeVolumePath.substring(1); + } + + if (!parent.endsWith(File.separator)) { + parent += File.separator; + } + String absoluteVolumePath = parent + relativeVolumePath; + File tmpltParent = new File(absoluteVolumePath).getParentFile(); + String details = null; + if (!tmpltParent.exists()) { + details = "volume parent directory " + tmpltParent.getName() + " doesn't exist"; + s_logger.debug(details); + return new Answer(cmd, true, details); + } + File[] tmpltFiles = tmpltParent.listFiles(); + if (tmpltFiles == null || tmpltFiles.length == 0) { + details = "No files under volume parent directory " + tmpltParent.getName(); + s_logger.debug(details); + } else { + boolean found = false; + for (File f : tmpltFiles) { + if (!found && f.getName().equals("volume.properties")) { + found = true; + } + + // KVM HA monitor makes a mess in the templates with its + // heartbeat tests + // Don't let this stop us from cleaning up the template + if (f.isDirectory() && f.getName().equals("KVMHA")) { + s_logger.debug("Deleting KVMHA directory contents from template location"); + File[] haFiles = f.listFiles(); + for (File haFile : haFiles) { + haFile.delete(); + } + } + + if (!f.delete()) { + return new Answer(cmd, false, "Unable to delete file " + f.getName() + " under Volume path " + + relativeVolumePath); } } if (!found) { - file.delete(); - String msg = "snapshot " + filename + " is not recorded in DB, remove it"; - s_logger.warn(msg); + details = "Can not find volume.properties under " + tmpltParent.getName(); + s_logger.debug(details); } } + if (!tmpltParent.delete()) { + details = "Unable to delete directory " + tmpltParent.getName() + " under Volume path " + + relativeVolumePath; + s_logger.debug(details); + return new Answer(cmd, false, details); + } + return new Answer(cmd, true, null); + } else if (dstore instanceof S3TO) { + final S3TO s3 = (S3TO) dstore; + final String path = obj.getPath(); + final String bucket = s3.getBucketName(); + try { + S3Utils.deleteDirectory(s3, bucket, path); + return new Answer(cmd, true, String.format("Deleted volume %1%s from bucket %2$s.", path, bucket)); + } catch (Exception e) { + final String errorMessage = String.format( + "Failed to delete volume %1$s from bucket %2$s due to the following error: %3$s", path, bucket, + e.getMessage()); + s_logger.error(errorMessage, e); + return new Answer(cmd, false, errorMessage); + } + } else if (dstore instanceof SwiftTO) { + Long volumeId = obj.getId(); + String path = obj.getPath(); + String filename = StringUtils.substringAfterLast(path, "/"); // assuming + // that + // the + // filename + // is + // the + // last + // section + // in + // the + // path + String result = swiftDelete((SwiftTO) dstore, "V-" + volumeId.toString(), filename); + if (result != null) { + String errMsg = "failed to delete volume " + filename + " , err=" + result; + s_logger.warn(errMsg); + return new Answer(cmd, false, errMsg); + } + return new Answer(cmd, true, "Deleted volume " + path + " from swift"); + } else { + return new Answer(cmd, false, "Unsupported image data store: " + dstore); } - return new Answer(cmd, true, null); + } - + @Override synchronized public String getRootDir(String secUrl) { if (!_inSystemVM) { return _parent; @@ -1415,7 +1798,7 @@ SecondaryStorageResource { String nfsPath = nfsHostIp + ":" + uri.getPath(); String dir = UUID.nameUUIDFromBytes(nfsPath.getBytes()).toString(); String root = _parent + "/" + dir; - mount(root, nfsPath); + mount(root, nfsPath); return root; } catch (Exception e) { String msg = "GetRootDir for " + secUrl + " failed due to " + e.toString(); @@ -1424,13 +1807,6 @@ SecondaryStorageResource { } } - - @Override - public String getRootDir(ssCommand cmd){ - return getRootDir(cmd.getSecUrl()); - - } - protected long getUsedSize(String rootDir) { return _storage.getUsedSpace(rootDir); } @@ -1455,13 +1831,12 @@ SecondaryStorageResource { assert (false) : "Well, I have no idea what this is: " + size; } - return (long)(Double.parseDouble(size.substring(0, size.length() - 1)) * multiplier); + return (long) (Double.parseDouble(size.substring(0, size.length() - 1)) * multiplier); } - @Override public Type getType() { - if(SecondaryStorageVm.Role.templateProcessor.toString().equals(_role)) + if (SecondaryStorageVm.Role.templateProcessor.toString().equals(_role)) return Host.Type.SecondaryStorage; return Host.Type.SecondaryStorageCmdExecutor; @@ -1474,9 +1849,9 @@ SecondaryStorageResource { @Override public boolean configure(String name, Map params) throws ConfigurationException { - _eth1ip = (String)params.get("eth1ip"); - _eth1mask = (String)params.get("eth1mask"); - if (_eth1ip != null) { //can only happen inside service vm + _eth1ip = (String) params.get("eth1ip"); + _eth1mask = (String) params.get("eth1mask"); + if (_eth1ip != null) { // can only happen inside service vm params.put("private.network.device", "eth1"); } else { s_logger.warn("eth1ip parameter has not been configured, assuming that we are not inside a system vm"); @@ -1484,7 +1859,7 @@ SecondaryStorageResource { String eth2ip = (String) params.get("eth2ip"); if (eth2ip != null) { params.put("public.network.device", "eth2"); - } + } _publicIp = (String) params.get("eth2ip"); _hostname = (String) params.get("name"); @@ -1502,19 +1877,19 @@ SecondaryStorageResource { super.configure(name, params); _params = params; - String value = (String)params.get("scripts.timeout"); + String value = (String) params.get("scripts.timeout"); _timeout = NumbersUtil.parseInt(value, 1440) * 1000; - _storage = (StorageLayer)params.get(StorageLayer.InstanceConfigKey); + _storage = (StorageLayer) params.get(StorageLayer.InstanceConfigKey); if (_storage == null) { - value = (String)params.get(StorageLayer.ClassConfigKey); + value = (String) params.get(StorageLayer.ClassConfigKey); if (value == null) { value = "com.cloud.storage.JavaStorageLayer"; } try { Class clazz = Class.forName(value); - _storage = (StorageLayer)clazz.newInstance(); + _storage = (StorageLayer) clazz.newInstance(); _storage.configure("StorageLayer", params); } catch (ClassNotFoundException e) { throw new ConfigurationException("Unable to find class " + value); @@ -1543,31 +1918,37 @@ SecondaryStorageResource { s_logger.info("_configIpFirewallScr found in " + _configIpFirewallScr); } - _role = (String)params.get("role"); - if(_role == null) + createTemplateFromSnapshotXenScript = Script.findScript(getDefaultScriptsDir(), + "create_privatetemplate_from_snapshot_xen.sh"); + if (createTemplateFromSnapshotXenScript == null) { + throw new ConfigurationException("create_privatetemplate_from_snapshot_xen.sh not found in " + + getDefaultScriptsDir()); + } + + _role = (String) params.get("role"); + if (_role == null) _role = SecondaryStorageVm.Role.templateProcessor.toString(); s_logger.info("Secondary storage runs in role " + _role); - _guid = (String)params.get("guid"); + _guid = (String) params.get("guid"); if (_guid == null) { throw new ConfigurationException("Unable to find the guid"); } - _dc = (String)params.get("zone"); + _dc = (String) params.get("zone"); if (_dc == null) { throw new ConfigurationException("Unable to find the zone"); } - _pod = (String)params.get("pod"); + _pod = (String) params.get("pod"); - _instance = (String)params.get("instance"); + _instance = (String) params.get("instance"); if (!_inSystemVM) { _parent = (String) params.get("mount.path"); } - if (_inSystemVM) { - _localgw = (String)params.get("localgw"); + _localgw = (String) params.get("localgw"); if (_localgw != null) { // can only happen inside service vm String mgmtHost = (String) params.get("host"); addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, mgmtHost); @@ -1613,14 +1994,14 @@ SecondaryStorageResource { command.add("if [ -f /etc/init.d/ssh ]; then service ssh restart; else service sshd restart; fi "); String result = command.execute(); if (result != null) { - s_logger.warn("Error in starting sshd service err=" + result ); + s_logger.warn("Error in starting sshd service err=" + result); } command = new Script("/bin/bash", s_logger); command.add("-c"); command.add("iptables -I INPUT -i eth1 -p tcp -m state --state NEW -m tcp --dport 3922 -j ACCEPT"); result = command.execute(); if (result != null) { - s_logger.warn("Error in opening up ssh port err=" + result ); + s_logger.warn("Error in opening up ssh port err=" + result); } } @@ -1628,12 +2009,13 @@ SecondaryStorageResource { if (!_inSystemVM) { return; } - s_logger.debug("addRouteToInternalIp: localgw=" + localgw + ", eth1ip=" + eth1ip + ", eth1mask=" + eth1mask + ",destIp=" + destIpOrCidr); + s_logger.debug("addRouteToInternalIp: localgw=" + localgw + ", eth1ip=" + eth1ip + ", eth1mask=" + eth1mask + + ",destIp=" + destIpOrCidr); if (destIpOrCidr == null) { s_logger.debug("addRouteToInternalIp: destIp is null"); return; } - if (!NetUtils.isValidIp(destIpOrCidr) && !NetUtils.isValidCIDR(destIpOrCidr)){ + if (!NetUtils.isValidIp(destIpOrCidr) && !NetUtils.isValidCIDR(destIpOrCidr)) { s_logger.warn(" destIp is not a valid ip address or cidr destIp=" + destIpOrCidr); return; } @@ -1642,13 +2024,16 @@ SecondaryStorageResource { if (eth1ip != null && eth1mask != null) { inSameSubnet = NetUtils.sameSubnet(eth1ip, destIpOrCidr, eth1mask); } else { - s_logger.warn("addRouteToInternalIp: unable to determine same subnet: _eth1ip=" + eth1ip + ", dest ip=" + destIpOrCidr + ", _eth1mask=" + eth1mask); + s_logger.warn("addRouteToInternalIp: unable to determine same subnet: _eth1ip=" + eth1ip + ", dest ip=" + + destIpOrCidr + ", _eth1mask=" + eth1mask); } } else { - inSameSubnet = NetUtils.isNetworkAWithinNetworkB(destIpOrCidr, NetUtils.ipAndNetMaskToCidr(eth1ip, eth1mask)); + inSameSubnet = NetUtils.isNetworkAWithinNetworkB(destIpOrCidr, + NetUtils.ipAndNetMaskToCidr(eth1ip, eth1mask)); } if (inSameSubnet) { - s_logger.debug("addRouteToInternalIp: dest ip " + destIpOrCidr + " is in the same subnet as eth1 ip " + eth1ip); + s_logger.debug("addRouteToInternalIp: dest ip " + destIpOrCidr + " is in the same subnet as eth1 ip " + + eth1ip); return; } Script command = new Script("/bin/bash", s_logger); @@ -1660,7 +2045,7 @@ SecondaryStorageResource { command.add("ip route add " + destIpOrCidr + " via " + localgw); String result = command.execute(); if (result != null) { - s_logger.warn("Error in configuring route to internal ip err=" + result ); + s_logger.warn("Error in configuring route to internal ip err=" + result); } else { s_logger.debug("addRouteToInternalIp: added route to internal ip=" + destIpOrCidr + " via " + localgw); } @@ -1708,16 +2093,16 @@ SecondaryStorageResource { return result; } - private String configureIpFirewall(List ipList, boolean isAppend){ + private String configureIpFirewall(List ipList, boolean isAppend) { Script command = new Script(_configIpFirewallScr); command.add(String.valueOf(isAppend)); - for (String ip : ipList){ + for (String ip : ipList) { command.add(ip); - } + } String result = command.execute(); if (result != null) { - s_logger.warn("Unable to configure firewall for command : " +command); + s_logger.warn("Unable to configure firewall for command : " + command); } return result; } @@ -1729,7 +2114,7 @@ SecondaryStorageResource { s_logger.debug("create mount point: " + root); } else { s_logger.debug("Unable to create mount point: " + root); - return null; + return null; } } @@ -1740,8 +2125,8 @@ SecondaryStorageResource { ZfsPathParser parser = new ZfsPathParser(root); script.execute(parser); res.addAll(parser.getPaths()); - for( String s : res ) { - if ( s.contains(root)) { + for (String s : res) { + if (s.contains(root)) { return root; } } @@ -1749,7 +2134,7 @@ SecondaryStorageResource { Script command = new Script(!_inSystemVM, "mount", _timeout, s_logger); command.add("-t", "nfs"); if (_inSystemVM) { - //Fedora Core 12 errors out with any -o option executed from java + // Fedora Core 12 errors out with any -o option executed from java command.add("-o", "soft,timeo=133,retrans=2147483647,tcp,acdirmax=0,acdirmin=0"); } command.add(nfsPath); @@ -1763,7 +2148,8 @@ SecondaryStorageResource { return null; } - // XXX: Adding the check for creation of snapshots dir here. Might have to move it somewhere more logical later. + // XXX: Adding the check for creation of snapshots dir here. Might have + // to move it somewhere more logical later. if (!checkForSnapshotsDir(root)) { return null; } @@ -1791,7 +2177,7 @@ SecondaryStorageResource { final StartupSecondaryStorageCommand cmd = new StartupSecondaryStorageCommand(); fillNetworkInformation(cmd); - if(_publicIp != null) + if (_publicIp != null) cmd.setPublicIpAddress(_publicIp); if (_inSystemVM) { @@ -1804,7 +2190,7 @@ SecondaryStorageResource { return null; } } - return new StartupCommand[] {cmd}; + return new StartupCommand[] { cmd }; } protected boolean checkForSnapshotsDir(String mountPoint) { @@ -1835,7 +2221,7 @@ SecondaryStorageResource { } if (dirExists) { - s_logger.info(dirName + " directory created/exists on Secondary Storage."); + s_logger.info(dirName + " directory created/exists on Secondary Storage."); } else { s_logger.info(dirName + " directory does not exist on Secondary Storage."); } diff --git a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/SecondaryStorageDiscoverer.java b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/SecondaryStorageDiscoverer.java index d3af792faa5..62b98133b8d 100755 --- a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/SecondaryStorageDiscoverer.java +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/SecondaryStorageDiscoverer.java @@ -44,7 +44,6 @@ import com.cloud.resource.ServerResource; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateZoneVO; import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VMTemplateHostDao; import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.storage.resource.DummySecondaryStorageResource; import com.cloud.utils.component.ComponentContext; @@ -59,19 +58,17 @@ import com.cloud.utils.script.Script; @Local(value=Discoverer.class) public class SecondaryStorageDiscoverer extends DiscovererBase implements Discoverer { private static final Logger s_logger = Logger.getLogger(SecondaryStorageDiscoverer.class); - + long _timeout = 2 * 60 * 1000; // 2 minutes String _mountParent; boolean _useServiceVM = false; - + Random _random = new Random(System.currentTimeMillis()); @Inject protected HostDao _hostDao = null; @Inject protected VMTemplateDao _tmpltDao = null; @Inject - protected VMTemplateHostDao _vmTemplateHostDao = null; - @Inject protected VMTemplateZoneDao _vmTemplateZoneDao = null; @Inject protected VMTemplateDao _vmTemplateDao = null; @@ -79,10 +76,10 @@ public class SecondaryStorageDiscoverer extends DiscovererBase implements Discov protected ConfigurationDao _configDao = null; @Inject protected AgentManager _agentMgr = null; - + protected SecondaryStorageDiscoverer() { } - + @Override public Map> find(long dcId, Long podId, Long clusterId, URI uri, String username, String password, List hostTags) { if (!uri.getScheme().equalsIgnoreCase("nfs") && !uri.getScheme().equalsIgnoreCase("file") @@ -101,14 +98,14 @@ public class SecondaryStorageDiscoverer extends DiscovererBase implements Discov return null; } } - + protected Map> createNfsSecondaryStorageResource(long dcId, Long podId, URI uri) { - + if (_useServiceVM) { return createDummySecondaryStorageResource(dcId, podId, uri); } String mountStr = NfsUtils.uri2Mount(uri); - + Script script = new Script(true, "mount", _timeout, s_logger); String mntPoint = null; File file = null; @@ -116,12 +113,12 @@ public class SecondaryStorageDiscoverer extends DiscovererBase implements Discov mntPoint = _mountParent + File.separator + Integer.toHexString(_random.nextInt(Integer.MAX_VALUE)); file = new File(mntPoint); } while (file.exists()); - + if (!file.mkdirs()) { s_logger.warn("Unable to make directory: " + mntPoint); return null; } - + script.add(mountStr, mntPoint); String result = script.execute(); if (result != null && !result.contains("already mounted")) { @@ -129,15 +126,15 @@ public class SecondaryStorageDiscoverer extends DiscovererBase implements Discov file.delete(); return null; } - + script = new Script(true, "umount", 0, s_logger); script.add(mntPoint); script.execute(); - + file.delete(); - + Map> srs = new HashMap>(); - + NfsSecondaryStorageResource storage; if(_configDao.isPremium()) { Class impl; @@ -172,12 +169,12 @@ public class SecondaryStorageDiscoverer extends DiscovererBase implements Discov } else { storage = new NfsSecondaryStorageResource(); } - + Map details = new HashMap(); details.put("mount.path", mountStr); details.put("orig.url", uri.toString()); details.put("mount.parent", _mountParent); - + Map params = new HashMap(); params.putAll(details); params.put("zone", Long.toString(dcId)); @@ -187,7 +184,7 @@ public class SecondaryStorageDiscoverer extends DiscovererBase implements Discov params.put("guid", uri.toString()); params.put("secondary.storage.vm", "false"); params.put("max.template.iso.size", _configDao.getValue("max.template.iso.size")); - + try { storage.configure("Storage", params); } catch (ConfigurationException e) { @@ -195,22 +192,22 @@ public class SecondaryStorageDiscoverer extends DiscovererBase implements Discov return null; } srs.put(storage, details); - + return srs; } - + protected Map> createLocalSecondaryStorageResource(long dcId, Long podId, URI uri) { Map> srs = new HashMap>(); - + LocalSecondaryStorageResource storage = new LocalSecondaryStorageResource(); storage = ComponentContext.inject(storage); - + Map details = new HashMap(); - + File file = new File(uri); details.put("mount.path", file.getAbsolutePath()); details.put("orig.url", uri.toString()); - + Map params = new HashMap(); params.putAll(details); params.put("zone", Long.toString(dcId)); @@ -218,7 +215,7 @@ public class SecondaryStorageDiscoverer extends DiscovererBase implements Discov params.put("pod", podId.toString()); } params.put("guid", uri.toString()); - + try { storage.configure("Storage", params); } catch (ConfigurationException e) { @@ -226,21 +223,21 @@ public class SecondaryStorageDiscoverer extends DiscovererBase implements Discov return null; } srs.put(storage, details); - + return srs; } - + protected Map> createDummySecondaryStorageResource(long dcId, Long podId, URI uri) { Map> srs = new HashMap>(); - + DummySecondaryStorageResource storage = new DummySecondaryStorageResource(_useServiceVM); storage = ComponentContext.inject(storage); - + Map details = new HashMap(); - + details.put("mount.path", uri.toString()); details.put("orig.url", uri.toString()); - + Map params = new HashMap(); params.putAll(details); params.put("zone", Long.toString(dcId)); @@ -248,7 +245,7 @@ public class SecondaryStorageDiscoverer extends DiscovererBase implements Discov params.put("pod", podId.toString()); } params.put("guid", uri.toString()); - + try { storage.configure("Storage", params); } catch (ConfigurationException e) { @@ -256,26 +253,26 @@ public class SecondaryStorageDiscoverer extends DiscovererBase implements Discov return null; } srs.put(storage, details); - + return srs; } - + @Override public boolean configure(String name, Map params) throws ConfigurationException { super.configure(name, params); - + _mountParent = _params.get("mount.parent"); if (_mountParent == null) { _mountParent = "/mnt"; } - + String useServiceVM = _params.get("secondary.storage.vm"); if ("true".equalsIgnoreCase(useServiceVM)){ _useServiceVM = true; } return true; } - + @Override public boolean matchHypervisor(String hypervisor) { if( hypervisor.equals("SecondaryStorage")) { @@ -289,7 +286,7 @@ public class SecondaryStorageDiscoverer extends DiscovererBase implements Discov public Hypervisor.HypervisorType getHypervisorType() { return Hypervisor.HypervisorType.None; } - + @Override public void postDiscovery(List hosts, long msId) { if (_useServiceVM) { @@ -300,9 +297,9 @@ public class SecondaryStorageDiscoverer extends DiscovererBase implements Discov for (HostVO h: hosts) { associateTemplatesToZone(h.getId(), h.getDataCenterId()); } - + } - + private void associateTemplatesToZone(long hostId, long dcId){ VMTemplateZoneVO tmpltZone; diff --git a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/SecondaryStorageResource.java b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/SecondaryStorageResource.java index 5c87b0dcc92..ae871a62c29 100755 --- a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/SecondaryStorageResource.java +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/SecondaryStorageResource.java @@ -15,7 +15,6 @@ // specific language governing permissions and limitations // under the License. package org.apache.cloudstack.storage.resource; -import com.cloud.agent.api.storage.ssCommand; import com.cloud.resource.ServerResource; /** * @@ -23,6 +22,6 @@ import com.cloud.resource.ServerResource; */ public interface SecondaryStorageResource extends ServerResource { - public String getRootDir(ssCommand cmd); + public String getRootDir(String cmd); } diff --git a/services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManager.java b/services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManager.java index 3e5072abfa3..9f14d9012c2 100644 --- a/services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManager.java +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManager.java @@ -18,16 +18,21 @@ package org.apache.cloudstack.storage.template; import java.util.Map; -import org.apache.cloudstack.storage.resource.SecondaryStorageResource; +import org.apache.cloudstack.storage.command.DownloadCommand; +import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType; import com.cloud.agent.api.storage.DownloadAnswer; -import com.cloud.agent.api.storage.DownloadCommand; -import com.cloud.agent.api.storage.DownloadCommand.Proxy; -import com.cloud.agent.api.storage.DownloadCommand.ResourceType; +import com.cloud.agent.api.storage.Proxy; +import com.cloud.agent.api.to.S3TO; +import com.cloud.storage.VMTemplateHostVO; + +import org.apache.cloudstack.storage.resource.SecondaryStorageResource; + import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.VMTemplateHostVO; import com.cloud.storage.template.TemplateDownloader; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; + import com.cloud.utils.component.Manager; public interface DownloadManager extends Manager { @@ -42,19 +47,21 @@ public interface DownloadManager extends Manager { * @param user username used for authentication to the server * @param password password used for authentication to the server * @param maxDownloadSizeInBytes (optional) max download size for the template, in bytes. - * @param resourceType signifying the type of resource like template, volume etc. + * @param resourceType signifying the type of resource like template, volume etc. * @return job-id that can be used to interrogate the status of the download. */ - public String downloadPublicTemplate(long id, String url, String name, ImageFormat format, boolean hvm, Long accountId, String descr, String cksum, String installPathPrefix, String userName, String passwd, long maxDownloadSizeInBytes, Proxy proxy, ResourceType resourceType); - - + public String downloadPublicTemplate(long id, String url, String name, ImageFormat format, boolean hvm, Long accountId, String descr, String cksum, String installPathPrefix, String templatePath, String userName, String passwd, long maxDownloadSizeInBytes, Proxy proxy, ResourceType resourceType); + + public String downloadS3Template(S3TO s3, long id, String url, String name, ImageFormat format, boolean hvm, Long accountId, String descr, String cksum, String installPathPrefix, String user, String password, long maxTemplateSizeInBytes, Proxy proxy, ResourceType resourceType); + + /** * Get the status of a download job * @param jobId job Id * @return status of the download job */ public TemplateDownloader.Status getDownloadStatus(String jobId); - + /** * Get the status of a download job * @param jobId job Id @@ -82,24 +89,24 @@ public interface DownloadManager extends Manager { * @return public String getDownloadLocalPath(String jobId); */ - + /** Handle download commands from the management server * @param cmd cmd from server * @return answer representing status of download. */ public DownloadAnswer handleDownloadCommand(SecondaryStorageResource resource, DownloadCommand cmd); - + /** /** * @return list of template info for installed templates */ - public Map gatherTemplateInfo(String templateDir); - + public Map gatherTemplateInfo(String templateDir); + /** /** * @return list of volume info for installed volumes */ - public Map gatherVolumeInfo(String volumeDir); + public Map gatherVolumeInfo(String volumeDir); } \ No newline at end of file diff --git a/services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java b/services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java index a9d23cb7779..bf68b299c5c 100755 --- a/services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java @@ -41,15 +41,19 @@ import java.util.concurrent.Executors; import javax.ejb.Local; import javax.naming.ConfigurationException; -import org.apache.cloudstack.storage.resource.SecondaryStorageResource; import org.apache.log4j.Logger; +import org.apache.cloudstack.storage.command.DownloadCommand; +import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType; +import org.apache.cloudstack.storage.command.DownloadProgressCommand; +import org.apache.cloudstack.storage.command.DownloadProgressCommand.RequestType; +import org.apache.cloudstack.storage.resource.SecondaryStorageResource; + import com.cloud.agent.api.storage.DownloadAnswer; -import com.cloud.agent.api.storage.DownloadCommand; -import com.cloud.agent.api.storage.DownloadCommand.Proxy; -import com.cloud.agent.api.storage.DownloadCommand.ResourceType; -import com.cloud.agent.api.storage.DownloadProgressCommand; -import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType; +import com.cloud.agent.api.storage.Proxy; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.NfsTO; +import com.cloud.agent.api.to.S3TO; import com.cloud.exception.InternalErrorException; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.StorageLayer; @@ -62,13 +66,14 @@ import com.cloud.storage.template.Processor; import com.cloud.storage.template.Processor.FormatInfo; import com.cloud.storage.template.QCOW2Processor; import com.cloud.storage.template.RawImageProcessor; +import com.cloud.storage.template.S3TemplateDownloader; import com.cloud.storage.template.ScpTemplateDownloader; import com.cloud.storage.template.TemplateConstants; import com.cloud.storage.template.TemplateDownloader; import com.cloud.storage.template.TemplateDownloader.DownloadCompleteCallback; import com.cloud.storage.template.TemplateDownloader.Status; -import com.cloud.storage.template.TemplateInfo; import com.cloud.storage.template.TemplateLocation; +import com.cloud.storage.template.TemplateProp; import com.cloud.storage.template.VhdProcessor; import com.cloud.storage.template.VmdkProcessor; import com.cloud.utils.NumbersUtil; @@ -112,7 +117,8 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager private final long id; private final ResourceType resourceType; - public DownloadJob(TemplateDownloader td, String jobId, long id, String tmpltName, ImageFormat format, boolean hvm, Long accountId, String descr, String cksum, String installPathPrefix, ResourceType resourceType) { + public DownloadJob(TemplateDownloader td, String jobId, long id, String tmpltName, ImageFormat format, boolean hvm, Long accountId, + String descr, String cksum, String installPathPrefix, ResourceType resourceType) { super(); this.td = td; this.jobId = jobId; @@ -120,10 +126,10 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager this.format = format; this.hvm = hvm; this.accountId = accountId; - this.description = descr; - this.checksum = cksum; + description = descr; + checksum = cksum; this.installPathPrefix = installPathPrefix; - this.templatesize = 0; + templatesize = 0; this.id = id; this.resourceType = resourceType; } @@ -235,9 +241,18 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager private int installTimeoutPerGig = 180 * 60 * 1000; private boolean _sslCopy; + public void setThreadPool(ExecutorService threadPool) { + this.threadPool = threadPool; + } + + public void setStorageLayer(StorageLayer storage) { + _storage = storage; + } + /** - * Get notified of change of job status. Executed in context of downloader thread - * + * Get notified of change of job status. Executed in context of downloader + * thread + * * @param jobId * the id of the job * @param status @@ -251,7 +266,8 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager } TemplateDownloader td = dj.getTemplateDownloader(); s_logger.info("Download Completion for jobId: " + jobId + ", status=" + status); - s_logger.info("local: " + td.getDownloadLocalPath() + ", bytes=" + td.getDownloadedBytes() + ", error=" + td.getDownloadError() + ", pct=" + td.getDownloadPercent()); + s_logger.info("local: " + td.getDownloadLocalPath() + ", bytes=" + td.getDownloadedBytes() + ", error=" + td.getDownloadError() + ", pct=" + + td.getDownloadPercent()); switch (status) { case ABORTED: @@ -271,15 +287,30 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager threadPool.execute(td); break; case DOWNLOAD_FINISHED: - td.setDownloadError("Download success, starting install "); - String result = postDownload(jobId); - if (result != null) { - s_logger.error("Failed post download script: " + result); - td.setStatus(Status.UNRECOVERABLE_ERROR); - td.setDownloadError("Failed post download script: " + result); + if (!(td instanceof S3TemplateDownloader)) { + // we currently only create template.properties for NFS by + // running some post download script + td.setDownloadError("Download success, starting install "); + String result = postDownload(jobId); + if (result != null) { + s_logger.error("Failed post download script: " + result); + td.setStatus(Status.UNRECOVERABLE_ERROR); + td.setDownloadError("Failed post download script: " + result); + } else { + td.setStatus(Status.POST_DOWNLOAD_FINISHED); + td.setDownloadError("Install completed successfully at " + new SimpleDateFormat().format(new Date())); + } } else { + // for s3 and swift, we skip post download step and just set + // status to trigger callback. td.setStatus(Status.POST_DOWNLOAD_FINISHED); - td.setDownloadError("Install completed successfully at " + new SimpleDateFormat().format(new Date())); + // set template size for S3 + S3TemplateDownloader std = (S3TemplateDownloader) td; + long size = std.totalBytes; + DownloadJob dnld = jobs.get(jobId); + dnld.setTemplatesize(size); + dnld.setTemplatePhysicalSize(size); + dnld.setTmpltPath(std.getDownloadLocalPath()); // update template path to include file name. } dj.cleanup(); break; @@ -292,56 +323,63 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager byte[] buffer = new byte[8192]; int read = 0; MessageDigest digest; - String checksum = null; + String checksum = null; InputStream is = null; try { - digest = MessageDigest.getInstance("MD5"); - is = new FileInputStream(f); - while( (read = is.read(buffer)) > 0) { + digest = MessageDigest.getInstance("MD5"); + is = new FileInputStream(f); + while ((read = is.read(buffer)) > 0) { digest.update(buffer, 0, read); - } + } byte[] md5sum = digest.digest(); BigInteger bigInt = new BigInteger(1, md5sum); - checksum = String.format("%032x",bigInt); + checksum = String.format("%032x", bigInt); return checksum; - }catch(IOException e) { + } catch (IOException e) { return null; - }catch (NoSuchAlgorithmException e) { + } catch (NoSuchAlgorithmException e) { return null; - } - finally { + } finally { try { - if(is != null) + if (is != null) is.close(); } catch (IOException e) { return null; - } + } } } /** - * Post download activity (install and cleanup). Executed in context of downloader thread - * + * Post download activity (install and cleanup). Executed in context of + * downloader thread + * * @throws IOException */ private String postDownload(String jobId) { DownloadJob dnld = jobs.get(jobId); TemplateDownloader td = dnld.getTemplateDownloader(); - String resourcePath = null; + String resourcePath = dnld.getInstallPathPrefix(); // path with mount + // directory + String finalResourcePath = dnld.getTmpltPath(); // template download + // path on secondary + // storage ResourceType resourceType = dnld.getResourceType(); - // once template path is set, remove the parent dir so that the template is installed with a relative path + /* + // once template path is set, remove the parent dir so that the template + // is installed with a relative path String finalResourcePath = ""; - if (resourceType == ResourceType.TEMPLATE){ + if (resourceType == ResourceType.TEMPLATE) { finalResourcePath += _templateDir + File.separator + dnld.getAccountId() + File.separator + dnld.getId() + File.separator; resourcePath = dnld.getInstallPathPrefix() + dnld.getAccountId() + File.separator + dnld.getId() + File.separator;// dnld.getTmpltName(); - }else { + } else { finalResourcePath += _volumeDir + File.separator + dnld.getId() + File.separator; resourcePath = dnld.getInstallPathPrefix() + dnld.getId() + File.separator;// dnld.getTmpltName(); } _storage.mkdirs(resourcePath); dnld.setTmpltPath(finalResourcePath); + */ File originalTemplate = new File(td.getDownloadLocalPath()); String checkSum = computeCheckSum(originalTemplate); @@ -368,18 +406,21 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager // add options common to ISO and template String extension = dnld.getFormat().getFileExtension(); String templateName = ""; - if( extension.equals("iso")) { + if (extension.equals("iso")) { templateName = jobs.get(jobId).getTmpltName().trim().replace(" ", "_"); } else { templateName = java.util.UUID.nameUUIDFromBytes((jobs.get(jobId).getTmpltName() + System.currentTimeMillis()).getBytes()).toString(); } + // run script to mv the temporary template file to the final template + // file String templateFilename = templateName + "." + extension; dnld.setTmpltPath(finalResourcePath + "/" + templateFilename); scr.add("-n", templateFilename); scr.add("-t", resourcePath); - scr.add("-f", td.getDownloadLocalPath()); + scr.add("-f", td.getDownloadLocalPath()); // this is the temporary + // template file downloaded if (dnld.getChecksum() != null && dnld.getChecksum().length() > 1) { scr.add("-c", dnld.getChecksum()); } @@ -397,9 +438,9 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager // Set permissions for template/volume.properties String propertiesFile = resourcePath; - if (resourceType == ResourceType.TEMPLATE){ + if (resourceType == ResourceType.TEMPLATE) { propertiesFile += "/template.properties"; - }else{ + } else { propertiesFile += "/volume.properties"; } File templateProperties = new File(propertiesFile); @@ -454,15 +495,43 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager } @Override - public String downloadPublicTemplate(long id, String url, String name, ImageFormat format, boolean hvm, Long accountId, String descr, String cksum, String installPathPrefix, String user, String password, long maxTemplateSizeInBytes, Proxy proxy, ResourceType resourceType) { + public String downloadS3Template(S3TO s3, long id, String url, String name, ImageFormat format, boolean hvm, Long accountId, String descr, + String cksum, String installPathPrefix, String user, String password, long maxTemplateSizeInBytes, Proxy proxy, ResourceType resourceType) { UUID uuid = UUID.randomUUID(); String jobId = uuid.toString(); - String tmpDir = ""; - if(resourceType == ResourceType.TEMPLATE){ - tmpDir = installPathPrefix + File.separator + accountId + File.separator + id; - }else { - tmpDir = installPathPrefix + File.separator + id; + + URI uri; + try { + uri = new URI(url); + } catch (URISyntaxException e) { + throw new CloudRuntimeException("URI is incorrect: " + url); } + TemplateDownloader td; + if ((uri != null) && (uri.getScheme() != null)) { + if (uri.getScheme().equalsIgnoreCase("http") || uri.getScheme().equalsIgnoreCase("https")) { + td = new S3TemplateDownloader(s3, url, installPathPrefix, new Completion(jobId), maxTemplateSizeInBytes, user, password, proxy, + resourceType); + } else { + throw new CloudRuntimeException("Scheme is not supported " + url); + } + } else { + throw new CloudRuntimeException("Unable to download from URL: " + url); + } + DownloadJob dj = new DownloadJob(td, jobId, id, name, format, hvm, accountId, descr, cksum, installPathPrefix, resourceType); + dj.setTmpltPath(installPathPrefix); + jobs.put(jobId, dj); + threadPool.execute(td); + + return jobId; + } + + @Override + public String downloadPublicTemplate(long id, String url, String name, ImageFormat format, boolean hvm, Long accountId, String descr, + String cksum, String installPathPrefix, String templatePath, String user, String password, long maxTemplateSizeInBytes, Proxy proxy, + ResourceType resourceType) { + UUID uuid = UUID.randomUUID(); + String jobId = uuid.toString(); + String tmpDir = installPathPrefix; try { @@ -470,10 +539,10 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager s_logger.warn("Unable to create " + tmpDir); return "Unable to create " + tmpDir; } - // TO DO - define constant for volume properties. - File file = ResourceType.TEMPLATE == resourceType ? _storage.getFile(tmpDir + File.separator + TemplateLocation.Filename) : - _storage.getFile(tmpDir + File.separator + "volume.properties"); - if ( file.exists() ) { + // TO DO - define constant for volume properties. + File file = ResourceType.TEMPLATE == resourceType ? _storage.getFile(tmpDir + File.separator + TemplateLocation.Filename) : _storage + .getFile(tmpDir + File.separator + "volume.properties"); + if (file.exists()) { file.delete(); } @@ -491,7 +560,8 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager TemplateDownloader td; if ((uri != null) && (uri.getScheme() != null)) { if (uri.getScheme().equalsIgnoreCase("http") || uri.getScheme().equalsIgnoreCase("https")) { - td = new HttpTemplateDownloader(_storage, url, tmpDir, new Completion(jobId), maxTemplateSizeInBytes, user, password, proxy, resourceType); + td = new HttpTemplateDownloader(_storage, url, tmpDir, new Completion(jobId), maxTemplateSizeInBytes, user, password, proxy, + resourceType); } else if (uri.getScheme().equalsIgnoreCase("file")) { td = new LocalTemplateDownloader(_storage, url, tmpDir, maxTemplateSizeInBytes, new Completion(jobId)); } else if (uri.getScheme().equalsIgnoreCase("scp")) { @@ -506,7 +576,13 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager } else { throw new CloudRuntimeException("Unable to download from URL: " + url); } + // NOTE the difference between installPathPrefix and templatePath + // here. instalPathPrefix is the absolute path for template + // including mount directory + // on ssvm, while templatePath is the final relative path on + // secondary storage. DownloadJob dj = new DownloadJob(td, jobId, id, name, format, hvm, accountId, descr, cksum, installPathPrefix, resourceType); + dj.setTmpltPath(templatePath); jobs.put(jobId, dj); threadPool.execute(td); @@ -600,39 +676,48 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager public DownloadAnswer handleDownloadCommand(SecondaryStorageResource resource, DownloadCommand cmd) { ResourceType resourceType = cmd.getResourceType(); if (cmd instanceof DownloadProgressCommand) { - return handleDownloadProgressCmd( resource, (DownloadProgressCommand) cmd); + return handleDownloadProgressCmd(resource, (DownloadProgressCommand) cmd); } if (cmd.getUrl() == null) { - return new DownloadAnswer(resourceType.toString() + " is corrupted on storage due to an invalid url , cannot download", VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR); + return new DownloadAnswer(resourceType.toString() + " is corrupted on storage due to an invalid url , cannot download", + VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR); } if (cmd.getName() == null) { return new DownloadAnswer("Invalid Name", VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR); } - String installPathPrefix = null; - if (ResourceType.TEMPLATE == resourceType){ - installPathPrefix = resource.getRootDir(cmd) + File.separator + _templateDir; - }else { - installPathPrefix = resource.getRootDir(cmd) + File.separator + _volumeDir; + DataStoreTO dstore = cmd.getDataStore(); + String installPathPrefix = cmd.getInstallPath(); + // for NFS, we need to get mounted path + if (dstore instanceof NfsTO) { + installPathPrefix = resource.getRootDir(((NfsTO) dstore).getUrl()) + File.separator + installPathPrefix; } - String user = null; String password = null; if (cmd.getAuth() != null) { user = cmd.getAuth().getUserName(); password = new String(cmd.getAuth().getPassword()); } - //TO DO - Define Volume max size as well - long maxDownloadSizeInBytes = (cmd.getMaxDownloadSizeInBytes() == null) ? TemplateDownloader.DEFAULT_MAX_TEMPLATE_SIZE_IN_BYTES : (cmd.getMaxDownloadSizeInBytes()); - String jobId = downloadPublicTemplate(cmd.getId(), cmd.getUrl(), cmd.getName(), cmd.getFormat(), cmd.isHvm(), cmd.getAccountId(), cmd.getDescription(), cmd.getChecksum(), installPathPrefix, user, password, maxDownloadSizeInBytes, cmd.getProxy(), resourceType); + // TO DO - Define Volume max size as well + long maxDownloadSizeInBytes = (cmd.getMaxDownloadSizeInBytes() == null) ? TemplateDownloader.DEFAULT_MAX_TEMPLATE_SIZE_IN_BYTES : (cmd + .getMaxDownloadSizeInBytes()); + String jobId = null; + if (dstore instanceof S3TO) { + jobId = downloadS3Template((S3TO) dstore, cmd.getId(), cmd.getUrl(), cmd.getName(), cmd.getFormat(), cmd.isHvm(), cmd.getAccountId(), + cmd.getDescription(), cmd.getChecksum(), installPathPrefix, user, password, maxDownloadSizeInBytes, cmd.getProxy(), resourceType); + } else { + jobId = downloadPublicTemplate(cmd.getId(), cmd.getUrl(), cmd.getName(), cmd.getFormat(), cmd.isHvm(), cmd.getAccountId(), + cmd.getDescription(), cmd.getChecksum(), installPathPrefix, cmd.getInstallPath(), user, password, maxDownloadSizeInBytes, + cmd.getProxy(), resourceType); + } sleep(); if (jobId == null) { return new DownloadAnswer("Internal Error", VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR); } - return new DownloadAnswer(jobId, getDownloadPct(jobId), getDownloadError(jobId), getDownloadStatus2(jobId), getDownloadLocalPath(jobId), getInstallPath(jobId), - getDownloadTemplateSize(jobId), getDownloadTemplateSize(jobId), getDownloadCheckSum(jobId)); + return new DownloadAnswer(jobId, getDownloadPct(jobId), getDownloadError(jobId), getDownloadStatus2(jobId), getDownloadLocalPath(jobId), + getInstallPath(jobId), getDownloadTemplateSize(jobId), getDownloadTemplateSize(jobId), getDownloadCheckSum(jobId)); } private void sleep() { @@ -673,8 +758,9 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager break; case PURGE: td.stopDownload(); - answer = new DownloadAnswer(jobId, getDownloadPct(jobId), getDownloadError(jobId), getDownloadStatus2(jobId), getDownloadLocalPath(jobId), - getInstallPath(jobId), getDownloadTemplateSize(jobId), getDownloadTemplatePhysicalSize(jobId), getDownloadCheckSum(jobId)); + answer = new DownloadAnswer(jobId, getDownloadPct(jobId), getDownloadError(jobId), getDownloadStatus2(jobId), + getDownloadLocalPath(jobId), getInstallPath(jobId), getDownloadTemplateSize(jobId), getDownloadTemplatePhysicalSize(jobId), + getDownloadCheckSum(jobId)); jobs.remove(jobId); return answer; default: @@ -702,7 +788,6 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager } - private List listVolumes(String rootdir) { List result = new ArrayList(); @@ -715,8 +800,6 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager return result; } - - private List listTemplates(String rootdir) { List result = new ArrayList(); @@ -730,11 +813,11 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager } @Override - public Map gatherTemplateInfo(String rootDir) { - Map result = new HashMap(); + public Map gatherTemplateInfo(String rootDir) { + Map result = new HashMap(); String templateDir = rootDir + File.separator + _templateDir; - if (! _storage.exists(templateDir)) { + if (!_storage.exists(templateDir)) { _storage.mkdirs(templateDir); } @@ -745,7 +828,7 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager try { if (!loc.load()) { s_logger.warn("Post download installation was not completed for " + path); - //loc.purge(); + // loc.purge(); _storage.cleanup(path, templateDir); continue; } @@ -754,19 +837,19 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager continue; } - TemplateInfo tInfo = loc.getTemplateInfo(); + TemplateProp tInfo = loc.getTemplateInfo(); if ((tInfo.getSize() == tInfo.getPhysicalSize()) && (tInfo.getInstallPath().endsWith(ImageFormat.OVA.getFileExtension()))) { try { Processor processor = _processors.get("VMDK Processor"); - VmdkProcessor vmdkProcessor = (VmdkProcessor)processor; - long vSize = - vmdkProcessor.getTemplateVirtualSize( - path, - tInfo.getInstallPath().substring( - tInfo.getInstallPath().lastIndexOf(File.separator) + 1)); - tInfo.setSize(vSize); + VmdkProcessor vmdkProcessor = (VmdkProcessor) processor; + long vSize = + vmdkProcessor.getTemplateVirtualSize( + path, + tInfo.getInstallPath().substring( + tInfo.getInstallPath().lastIndexOf(File.separator) + 1)); + tInfo.setSize(vSize); loc.updateVirtualSize(vSize); loc.save(); } catch (Exception e) { @@ -793,11 +876,11 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager } @Override - public Map gatherVolumeInfo(String rootDir) { - Map result = new HashMap(); + public Map gatherVolumeInfo(String rootDir) { + Map result = new HashMap(); String volumeDir = rootDir + File.separator + _volumeDir; - if (! _storage.exists(volumeDir)) { + if (!_storage.exists(volumeDir)) { _storage.mkdirs(volumeDir); } @@ -808,7 +891,7 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager try { if (!loc.load()) { s_logger.warn("Post download installation was not completed for " + path); - //loc.purge(); + // loc.purge(); _storage.cleanup(path, volumeDir); continue; } @@ -817,7 +900,7 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager continue; } - TemplateInfo vInfo = loc.getTemplateInfo(); + TemplateProp vInfo = loc.getTemplateInfo(); if ((vInfo.getSize() == vInfo.getPhysicalSize()) && (vInfo.getInstallPath().endsWith(ImageFormat.OVA.getFileExtension()))) { @@ -902,7 +985,7 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager String value = null; - _storage = (StorageLayer)params.get(StorageLayer.InstanceConfigKey); + _storage = (StorageLayer) params.get(StorageLayer.InstanceConfigKey); if (_storage == null) { value = (String) params.get(StorageLayer.ClassConfigKey); if (value == null) { @@ -921,12 +1004,12 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager throw new ConfigurationException("Unable to instantiate " + value); } } - String useSsl = (String)params.get("sslcopy"); + String useSsl = (String) params.get("sslcopy"); if (useSsl != null) { _sslCopy = Boolean.parseBoolean(useSsl); } - String inSystemVM = (String)params.get("secondary.storage.vm"); + String inSystemVM = (String) params.get("secondary.storage.vm"); if (inSystemVM != null && "true".equalsIgnoreCase(inSystemVM)) { s_logger.info("DownloadManager: starting additional services since we are inside system vm"); startAdditionalServices(); @@ -934,7 +1017,7 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager } value = (String) params.get("install.timeout.pergig"); - this.installTimeoutPerGig = NumbersUtil.parseInt(value, 15 * 60) * 1000; + installTimeoutPerGig = NumbersUtil.parseInt(value, 15 * 60) * 1000; value = (String) params.get("install.numthreads"); final int numInstallThreads = NumbersUtil.parseInt(value, 10); @@ -1005,12 +1088,12 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager Script command = new Script("/bin/bash", s_logger); String intf = "eth1"; command.add("-c"); - command.add("iptables -A OUTPUT -o " + intf + " -p tcp -m state --state NEW -m tcp --dport " + "80" + " -j REJECT;" + - "iptables -A OUTPUT -o " + intf + " -p tcp -m state --state NEW -m tcp --dport " + "443" + " -j REJECT;"); + command.add("iptables -A OUTPUT -o " + intf + " -p tcp -m state --state NEW -m tcp --dport " + "80" + " -j REJECT;" + + "iptables -A OUTPUT -o " + intf + " -p tcp -m state --state NEW -m tcp --dport " + "443" + " -j REJECT;"); String result = command.execute(); if (result != null) { - s_logger.warn("Error in blocking outgoing to port 80/443 err=" + result ); + s_logger.warn("Error in blocking outgoing to port 80/443 err=" + result); return; } } @@ -1037,19 +1120,19 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager command.add("if [ -d /etc/apache2 ] ; then service apache2 stop; else service httpd stop; fi "); String result = command.execute(); if (result != null) { - s_logger.warn("Error in stopping httpd service err=" + result ); + s_logger.warn("Error in stopping httpd service err=" + result); } String port = Integer.toString(TemplateConstants.DEFAULT_TMPLT_COPY_PORT); String intf = TemplateConstants.DEFAULT_TMPLT_COPY_INTF; command = new Script("/bin/bash", s_logger); command.add("-c"); - command.add("iptables -I INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + port + " -j ACCEPT;" + - "iptables -I INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + "443" + " -j ACCEPT;"); + command.add("iptables -I INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + port + " -j ACCEPT;" + "iptables -I INPUT -i " + + intf + " -p tcp -m state --state NEW -m tcp --dport " + "443" + " -j ACCEPT;"); result = command.execute(); if (result != null) { - s_logger.warn("Error in opening up httpd port err=" + result ); + s_logger.warn("Error in opening up httpd port err=" + result); return; } @@ -1058,7 +1141,7 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager command.add("if [ -d /etc/apache2 ] ; then service apache2 start; else service httpd start; fi "); result = command.execute(); if (result != null) { - s_logger.warn("Error in starting httpd service err=" + result ); + s_logger.warn("Error in starting httpd service err=" + result); return; } command = new Script("mkdir", s_logger); @@ -1066,7 +1149,7 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager command.add("/var/www/html/copy/template"); result = command.execute(); if (result != null) { - s_logger.warn("Error in creating directory =" + result ); + s_logger.warn("Error in creating directory =" + result); return; } } diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 76c10138e3e..34e023be443 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -37,12 +37,13 @@ ALTER TABLE `cloud`.`load_balancer_vm_map` ADD state VARCHAR(40) NULL COMMENT 's alter table storage_pool add hypervisor varchar(32); alter table storage_pool change storage_provider_id storage_provider_name varchar(255); -alter table template_host_ref add state varchar(255); -alter table template_host_ref add update_count bigint unsigned; -alter table template_host_ref add updated datetime; -alter table volume_host_ref add state varchar(255); -alter table volume_host_ref add update_count bigint unsigned; -alter table volume_host_ref add updated datetime; +alter table storage_pool change available_bytes used_bytes bigint unsigned; +-- alter table template_host_ref add state varchar(255); +-- alter table template_host_ref add update_count bigint unsigned; +-- alter table template_host_ref add updated datetime; +-- alter table volume_host_ref add state varchar(255); +-- alter table volume_host_ref add update_count bigint unsigned; +-- alter table volume_host_ref add updated datetime; alter table template_spool_ref add updated datetime; CREATE TABLE `cloud`.`object_datastore_ref` ( `id` bigint unsigned NOT NULL auto_increment, @@ -68,25 +69,160 @@ CREATE TABLE `cloud`.`object_datastore_ref` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; -CREATE TABLE `cloud`.`data_store_provider` ( - `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', - `name` varchar(255) NOT NULL COMMENT 'name of primary data store provider', - `uuid` varchar(255) NOT NULL COMMENT 'uuid of primary data store provider', - PRIMARY KEY(`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- CREATE TABLE `cloud`.`data_store_provider` ( +-- `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', +-- `name` varchar(255) NOT NULL COMMENT 'name of primary data store provider', +-- `uuid` varchar(255) NOT NULL COMMENT 'uuid of primary data store provider', +-- PRIMARY KEY(`id`) +-- ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -CREATE TABLE `cloud`.`image_data_store` ( +CREATE TABLE `cloud`.`image_store` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', `name` varchar(255) NOT NULL COMMENT 'name of data store', - `image_provider_name` varchar(255) NOT NULL COMMENT 'id of image_data_store_provider', + `image_provider_name` varchar(255) NOT NULL COMMENT 'id of image_store_provider', `protocol` varchar(255) NOT NULL COMMENT 'protocol of data store', + `url` varchar(255) COMMENT 'url for image data store', `data_center_id` bigint unsigned COMMENT 'datacenter id of data store', `scope` varchar(255) COMMENT 'scope of data store', + `role` varchar(255) COMMENT 'role of data store', `uuid` varchar(255) COMMENT 'uuid of data store', + `parent` varchar(255) COMMENT 'parent path for the storage server', + `created` datetime COMMENT 'date the image store first signed on', + `removed` datetime COMMENT 'date removed if not null', + `total_size` bigint unsigned COMMENT 'storage total size statistics', + `used_bytes` bigint unsigned COMMENT 'storage available bytes statistics', PRIMARY KEY(`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -ALTER TABLE `cloud`.`vm_template` ADD COLUMN `image_data_store_id` bigint unsigned; +CREATE TABLE `cloud`.`image_store_details` ( + `id` bigint unsigned UNIQUE NOT NULL AUTO_INCREMENT COMMENT 'id', + `store_id` bigint unsigned NOT NULL COMMENT 'store the detail is related to', + `name` varchar(255) NOT NULL COMMENT 'name of the detail', + `value` varchar(255) NOT NULL COMMENT 'value of the detail', + PRIMARY KEY (`id`), + CONSTRAINT `fk_image_store_details__store_id` FOREIGN KEY `fk_image_store__store_id`(`store_id`) REFERENCES `image_store`(`id`) ON DELETE CASCADE, + INDEX `i_image_store__name__value`(`name`(128), `value`(128)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP VIEW IF EXISTS `cloud`.`image_store_view`; +CREATE VIEW `cloud`.`image_store_view` AS + select + image_store.id, + image_store.uuid, + image_store.name, + image_store.image_provider_name, + image_store.protocol, + image_store.url, + image_store.scope, + image_store.role, + image_store.removed, + data_center.id data_center_id, + data_center.uuid data_center_uuid, + data_center.name data_center_name, + image_store_details.name detail_name, + image_store_details.value detail_value + from + `cloud`.`image_store` + left join + `cloud`.`data_center` ON image_store.data_center_id = data_center.id + left join + `cloud`.`image_store_details` ON image_store_details.store_id = image_store.id; + + +-- here we have to allow null for store_id to accomodate baremetal case to search for ready templates since template state is only stored in this table +-- FK also commented out due to this +CREATE TABLE `cloud`.`template_store_ref` ( + `id` bigint unsigned NOT NULL auto_increment, + `store_id` bigint unsigned, + `template_id` bigint unsigned NOT NULL, + `created` DATETIME NOT NULL, + `last_updated` DATETIME, + `job_id` varchar(255), + `download_pct` int(10) unsigned, + `size` bigint unsigned, + `store_role` varchar(255), + `physical_size` bigint unsigned DEFAULT 0, + `download_state` varchar(255), + `error_str` varchar(255), + `local_path` varchar(255), + `install_path` varchar(255), + `url` varchar(255), + `state` varchar(255) NOT NULL, + `destroyed` tinyint(1) COMMENT 'indicates whether the template_store entry was destroyed by the user or not', + `is_copy` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'indicates whether this was copied ', + `update_count` bigint unsigned, + `ref_cnt` bigint unsigned, + `updated` datetime, + PRIMARY KEY (`id`), +-- CONSTRAINT `fk_template_store_ref__store_id` FOREIGN KEY `fk_template_store_ref__store_id` (`store_id`) REFERENCES `image_store` (`id`) ON DELETE CASCADE, + INDEX `i_template_store_ref__store_id`(`store_id`), + CONSTRAINT `fk_template_store_ref__template_id` FOREIGN KEY `fk_template_store_ref__template_id` (`template_id`) REFERENCES `vm_template` (`id`), + INDEX `i_template_store_ref__template_id`(`template_id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +-- ALTER TABLE `cloud`.`vm_template` ADD COLUMN `image_data_store_id` bigint unsigned; + +-- Do we still need these columns? TODO, to delete them, remove FK constraints from snapshots table +-- ALTER TABLE `cloud`.`snapshots` DROP COLUMN `swift_id`; +-- ALTER TABLE `cloud`.`snapshots` DROP COLUMN `s3_id`; +-- ALTER TABLE `cloud`.`snapshots` DROP COLUMN `sechost_id`; + +-- change upload host_id FK to point to image_store table +ALTER TABLE `cloud`.`upload` DROP FOREIGN KEY `fk_upload__host_id`; +ALTER TABLE `cloud`.`upload` ADD CONSTRAINT `fk_upload__store_id` FOREIGN KEY(`host_id`) REFERENCES `image_store` (`id`) ON DELETE CASCADE; + +CREATE TABLE `cloud`.`snapshot_store_ref` ( + `id` bigint unsigned NOT NULL auto_increment, + `store_id` bigint unsigned NOT NULL, + `snapshot_id` bigint unsigned NOT NULL, + `created` DATETIME NOT NULL, + `last_updated` DATETIME, + `job_id` varchar(255), + `store_role` varchar(255), + `size` bigint unsigned, + `physical_size` bigint unsigned DEFAULT 0, + `parent_snapshot_id` bigint unsigned DEFAULT 0, + `install_path` varchar(255), + `state` varchar(255) NOT NULL, + -- `removed` datetime COMMENT 'date removed if not null', + `update_count` bigint unsigned, + `ref_cnt` bigint unsigned, + `updated` datetime, + PRIMARY KEY (`id`), + INDEX `i_snapshot_store_ref__store_id`(`store_id`), + CONSTRAINT `fk_snapshot_store_ref__snapshot_id` FOREIGN KEY `fk_snapshot_store_ref__snapshot_id` (`snapshot_id`) REFERENCES `snapshots` (`id`), + INDEX `i_snapshot_store_ref__snapshot_id`(`snapshot_id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`volume_store_ref` ( + `id` bigint unsigned NOT NULL auto_increment, + `store_id` bigint unsigned NOT NULL, + `volume_id` bigint unsigned NOT NULL, + `zone_id` bigint unsigned NOT NULL, + `created` DATETIME NOT NULL, + `last_updated` DATETIME, + `job_id` varchar(255), + `download_pct` int(10) unsigned, + `size` bigint unsigned, + `physical_size` bigint unsigned DEFAULT 0, + `download_state` varchar(255), + `checksum` varchar(255) COMMENT 'checksum for the data disk', + `error_str` varchar(255), + `local_path` varchar(255), + `install_path` varchar(255), + `url` varchar(255), + `state` varchar(255) NOT NULL, + `destroyed` tinyint(1) COMMENT 'indicates whether the volume_host entry was destroyed by the user or not', + `update_count` bigint unsigned, + `ref_cnt` bigint unsigned, + `updated` datetime, + PRIMARY KEY (`id`), + CONSTRAINT `fk_volume_store_ref__store_id` FOREIGN KEY `fk_volume_store_ref__store_id` (`store_id`) REFERENCES `image_store` (`id`) ON DELETE CASCADE, + INDEX `i_volume_store_ref__store_id`(`store_id`), + CONSTRAINT `fk_volume_store_ref__volume_id` FOREIGN KEY `fk_volume_store_ref__volume_id` (`volume_id`) REFERENCES `volumes` (`id`), + INDEX `i_volume_store_ref__volume_id`(`volume_id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + ALTER TABLE `cloud`.`service_offering` ADD COLUMN `is_volatile` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if the vm needs to be volatile, i.e., on every reboot of vm from API root disk is discarded and creates a new root disk'; @@ -284,6 +420,8 @@ ALTER TABLE `cloud`.`user_vm_details` ADD COLUMN `display_detail` tinyint(1) NOT ALTER TABLE `cloud`.`volumes` ADD COLUMN `display_volume` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Should volume be displayed to the end user'; +ALTER TABLE `cloud`.`volumes` ADD COLUMN `format` varchar(255) COMMENT 'volume format'; + ALTER TABLE `cloud`.`networks` ADD COLUMN `display_network` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Should network be displayed to the end user'; ALTER TABLE `cloud`.`nics` ADD COLUMN `display_nic` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Should nic be displayed to the end user'; @@ -439,7 +577,7 @@ CREATE TABLE `cloud`.`service_offering_details` ( CONSTRAINT `fk_service_offering_details__service_offering_id` FOREIGN KEY (`service_offering_id`) REFERENCES `service_offering`(`id`) ON DELETE CASCADE, CONSTRAINT UNIQUE KEY `uk_service_offering_id_name` (`service_offering_id`, `name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; - + DROP VIEW IF EXISTS `cloud`.`user_vm_view`; CREATE VIEW `cloud`.`user_vm_view` AS select @@ -1700,6 +1838,107 @@ ALTER TABLE `cloud`.`cluster_details` MODIFY value varchar(255); ALTER TABLE `cloud`.`storage_pool_details` MODIFY value varchar(255); ALTER TABLE `cloud`.`account_details` MODIFY value varchar(255); +-- END: support for LXC + +DROP VIEW IF EXISTS `cloud`.`template_view`; +CREATE VIEW `cloud`.`template_view` AS + select + vm_template.id, + vm_template.uuid, + vm_template.unique_name, + vm_template.name, + vm_template.public, + vm_template.featured, + vm_template.type, + vm_template.hvm, + vm_template.bits, + vm_template.url, + vm_template.format, + vm_template.created, + vm_template.checksum, + vm_template.display_text, + vm_template.enable_password, + vm_template.guest_os_id, + -- vm_template.state, + guest_os.uuid guest_os_uuid, + guest_os.display_name guest_os_name, + vm_template.bootable, + vm_template.prepopulate, + vm_template.cross_zones, + vm_template.hypervisor_type, + vm_template.extractable, + vm_template.template_tag, + vm_template.sort_key, + vm_template.removed, + vm_template.enable_sshkey, + source_template.id source_template_id, + source_template.uuid source_template_uuid, + account.id account_id, + account.uuid account_uuid, + account.account_name account_name, + account.type account_type, + domain.id domain_id, + domain.uuid domain_uuid, + domain.name domain_name, + domain.path domain_path, + projects.id project_id, + projects.uuid project_uuid, + projects.name project_name, + data_center.id data_center_id, + data_center.uuid data_center_uuid, + data_center.name data_center_name, + launch_permission.account_id lp_account_id, + template_store_ref.store_id, + template_store_ref.state, + template_store_ref.download_state, + template_store_ref.download_pct, + template_store_ref.error_str, + template_store_ref.size, + template_store_ref.destroyed, + template_store_ref.created created_on_store, + vm_template_details.name detail_name, + vm_template_details.value detail_value, + resource_tags.id tag_id, + resource_tags.uuid tag_uuid, + resource_tags.key tag_key, + resource_tags.value tag_value, + resource_tags.domain_id tag_domain_id, + resource_tags.account_id tag_account_id, + resource_tags.resource_id tag_resource_id, + resource_tags.resource_uuid tag_resource_uuid, + resource_tags.resource_type tag_resource_type, + resource_tags.customer tag_customer + from + `cloud`.`vm_template` + inner join + `cloud`.`guest_os` ON guest_os.id = vm_template.guest_os_id + inner join + `cloud`.`account` ON account.id = vm_template.account_id + inner join + `cloud`.`domain` ON domain.id = account.domain_id + left join + `cloud`.`projects` ON projects.project_account_id = account.id + left join + `cloud`.`vm_template_details` ON vm_template_details.template_id = vm_template.id + left join + `cloud`.`vm_template` source_template ON source_template.id = vm_template.source_template_id + left join + `cloud`.`template_zone_ref` ON template_zone_ref.template_id = vm_template.id + AND template_zone_ref.removed is null + left join + `cloud`.`data_center` ON template_zone_ref.zone_id = data_center.id + left join + `cloud`.`image_store` ON image_store.removed is NULL AND (image_store.data_center_id = data_center.id OR image_store.scope = 'REGION') + left join + `cloud`.`template_store_ref` ON template_store_ref.template_id = vm_template.id AND template_store_ref.store_id = image_store.id + left join + `cloud`.`launch_permission` ON launch_permission.template_id = vm_template.id + left join + `cloud`.`resource_tags` ON resource_tags.resource_id = vm_template.id + and (resource_tags.resource_type = 'Template' or resource_tags.resource_type='ISO'); + + + INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Network', 'DEFAULT', 'management-server', 'midonet.apiserver.address', 'http://localhost:8081', 'Specify the address at which the Midonet API server can be contacted (if using Midonet)'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Network', 'DEFAULT', 'management-server', 'midonet.providerrouter.id', 'd7c5e6a3-e2f4-426b-b728-b7ce6a0448e5', 'Specifies the UUID of the Midonet provider router (if using Midonet)'); @@ -1721,6 +1960,9 @@ CREATE TABLE `cloud`.`account_vnet_map` ( ALTER TABLE `cloud`.`op_dc_vnet_alloc` ADD COLUMN account_vnet_map_id bigint unsigned; ALTER TABLE `cloud`.`op_dc_vnet_alloc` ADD CONSTRAINT `fk_op_dc_vnet_alloc__account_vnet_map_id` FOREIGN KEY `fk_op_dc_vnet_alloc__account_vnet_map_id` (`account_vnet_map_id`) REFERENCES `account_vnet_map` (`id`); + + update `cloud`.`vm_template` set state='Allocated' where state is NULL; + update `cloud`.`vm_template` set update_count=0 where update_count is NULL; CREATE TABLE `cloud`.`network_acl` ( `id` bigint unsigned NOT NULL auto_increment COMMENT 'id', @@ -1876,7 +2118,7 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'manag INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'vm.disk.throttling.bytes_write_rate', 0, 'Default disk I/O write rate in bytes per second allowed in User vm\'s disk. '); -- Re-enable foreign key checking, at the end of the upgrade path -SET foreign_key_checks = 1; +SET foreign_key_checks = 1; UPDATE `cloud`.`snapshot_policy` set uuid=id WHERE uuid is NULL; #update shared sg enabled network with not null name in Advance Security Group enabled network diff --git a/test/integration/smoke/test_volumes.py b/test/integration/smoke/test_volumes.py index 4c4b78076e7..dd3d8a41b0b 100644 --- a/test/integration/smoke/test_volumes.py +++ b/test/integration/smoke/test_volumes.py @@ -19,6 +19,7 @@ #Import Local Modules import marvin from marvin.cloudstackTestCase import * +from marvin.cloudstackException import * from marvin.cloudstackAPI import * from marvin.remoteSSHClient import remoteSSHClient from marvin.integration.lib.utils import * @@ -345,7 +346,7 @@ class TestVolumes(cloudstackTestCase): cls.disk_offering, cls.volume, cls.account - ] + ] @classmethod def tearDownClass(cls): diff --git a/test/pom.xml b/test/pom.xml index d4b88326fa2..92e62734ac4 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -75,7 +75,7 @@ compile - src + test test diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py index 3dd526a0e3b..43dad9987cd 100644 --- a/tools/apidoc/gen_toc.py +++ b/tools/apidoc/gen_toc.py @@ -142,6 +142,10 @@ known_categories = { 'removeIpFromNic': 'Nic', 'listNics':'Nic', 'AffinityGroup': 'Affinity Group', + 'addImageStore': 'Image Store', + 'listImageStore': 'Image Store', + 'deleteImageStore': 'Image Store', + 'createCacheStore': 'Image Store', 'InternalLoadBalancer': 'Internal LB', 'DeploymentPlanners': 'Configuration', 'PortableIp': 'Portable IP', diff --git a/tools/devcloud/devcloud.cfg b/tools/devcloud/devcloud.cfg index f665e82c4c9..8ce62051b0b 100644 --- a/tools/devcloud/devcloud.cfg +++ b/tools/devcloud/devcloud.cfg @@ -84,10 +84,12 @@ "internaldns1": "192.168.56.1", "secondaryStorages": [ { - "url": "nfs://192.168.56.10:/opt/storage/secondary" - } + "url": "nfs://192.168.56.10/opt/storage/secondary", + "providerName": "NFS", + "details": [ ] + } ] - } + } ], "logger": [ { diff --git a/tools/devcloud/devcloud_s3.cfg b/tools/devcloud/devcloud_s3.cfg new file mode 100644 index 00000000000..18efec35d37 --- /dev/null +++ b/tools/devcloud/devcloud_s3.cfg @@ -0,0 +1,141 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# 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, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +{ + "zones": [ + { + "name": "DevCloud0", + "physical_networks": [ + { + "broadcastdomainrange": "Zone", + "name": "test-network", + "traffictypes": [ + { + "typ": "Guest" + }, + { + "typ": "Management" + } + ], + "providers": [ + { + "broadcastdomainrange": "ZONE", + "name": "VirtualRouter" + }, + { + "broadcastdomainrange": "Pod", + "name": "SecurityGroupProvider" + } + ] + } + ], + "dns2": "4.4.4.4", + "dns1": "8.8.8.8", + "securitygroupenabled": "true", + "localstorageenabled": "true", + "networktype": "Basic", + "pods": [ + { + "endip": "192.168.56.220", + "name": "test00", + "startip": "192.168.56.200", + "guestIpRanges": [ + { + "startip": "192.168.56.100", + "endip": "192.168.56.199", + "netmask": "255.255.255.0", + "gateway": "192.168.56.1" + } + ], + "netmask": "255.255.255.0", + "clusters": [ + { + "clustername": "test000", + "hypervisor": "XenServer", + "hosts": [ + { + "username": "root", + "url": "http://192.168.56.10/", + "password": "password" + } + ], + "clustertype": "CloudManaged" + } + ], + "gateway": "192.168.56.1" + } + ], + "internaldns1": "192.168.56.1", + "secondaryStorages": [ + { + "providerName": "S3", + "details": [ + { + "key" : "accesskey", + "value" :"OYAZXCAFUC1DAFOXNJWI" + }, + { + "key" : "secretkey", + "value" : "YHpRtzNDwl12DtrQmwRvdpnf2xK2AeVM30rXxQ==" + }, + { + "key" : "endpoint", + "value" : "10.223.89.7:8080" + }, + { + "key" : "bucket", + "value" : "cloudstack" + } + ] + } + ], + "cacheStorages": [ + { + "url": "nfs://192.168.56.10/opt/storage/secondary", + "providerName": "NFS", + "details": [ + ] + } + ] + } + ], + "logger": [ + { + "name": "TestClient", + "file": "/tmp/testclient.log" + }, + { + "name": "TestCase", + "file": "/tmp/testcase.log" + } + ], + "mgtSvr": [ + { + "mgtSvrIp": "127.0.0.1", + "port": 8096 + } + ], + "dbSvr": + { + "dbSvr": "127.0.0.1", + "port": 3306, + "user": "cloud", + "passwd": "cloud", + "db": "cloud" + } +} diff --git a/tools/marvin/marvin/configGenerator.py b/tools/marvin/marvin/configGenerator.py index bd83efbc126..7f6776a3559 100644 --- a/tools/marvin/marvin/configGenerator.py +++ b/tools/marvin/marvin/configGenerator.py @@ -70,6 +70,8 @@ class zone(): self.physical_networks = [] self.pods = [] self.secondaryStorages = [] + self.cacheStorages = [] + class traffictype(): def __init__(self, typ, labeldict=None): @@ -179,7 +181,15 @@ class primaryStorage(): class secondaryStorage(): def __init__(self): self.url = None + self.providerName = None + self.details = None +class cacheStorage(): + def __init__(self): + self.url = None + self.providerName = None + self.details = None + class s3(): def __init__(self): self.accesskey = None diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py index cf5cf782676..66b3e322890 100644 --- a/tools/marvin/marvin/deployDataCenter.py +++ b/tools/marvin/marvin/deployDataCenter.py @@ -138,10 +138,30 @@ class deployDataCenters(): if secondaryStorages is None: return for secondary in secondaryStorages: - secondarycmd = addSecondaryStorage.addSecondaryStorageCmd() + secondarycmd = addImageStore.addImageStoreCmd() secondarycmd.url = secondary.url - secondarycmd.zoneid = zoneId - self.apiClient.addSecondaryStorage(secondarycmd) + secondarycmd.provider = secondary.providerName + secondarycmd.details = [] + + if isinstance(secondary.details, list): + for item in secondary.details: + secondarycmd.details.append(item.__dict__) + if secondarycmd.provider == "NFS": + secondarycmd.zoneid = zoneId + self.apiClient.addImageStore(secondarycmd) + + def createCacheStorages(self, cacheStorages, zoneId): + if cacheStorages is None: + return + for cache in cacheStorages: + cachecmd = createCacheStore.createCacheStoreCmd() + cachecmd.url = cache.url + cachecmd.provider = cache.providerName + cachecmd.zoneid = zoneId + cachecmd.details = [] + for item in cache.details: + cachecmd.details.append(item.__dict__) + self.apiClient.createCacheStore(cachecmd) def createnetworks(self, networks, zoneId): if networks is None: @@ -368,6 +388,7 @@ class deployDataCenters(): self.createpods(zone.pods, zoneId, networkId) self.createSecondaryStorages(zone.secondaryStorages, zoneId) + self.createCacheStorages(zone.cacheStorages, zoneId) enabled = getattr(zone, 'enabled', 'True') if enabled == 'True' or enabled is None: diff --git a/ui/scripts/cloudStack.js b/ui/scripts/cloudStack.js index b943a946c8f..b06cf5c7606 100644 --- a/ui/scripts/cloudStack.js +++ b/ui/scripts/cloudStack.js @@ -191,22 +191,26 @@ if (userValid && isAdmin()) { $.ajax({ - url: createURL("listSwifts"), - dataType: "json", + url: createURL("listImageStores"), + data: { + provider: 'Swift' + }, async: false, success: function(json) { - var items = json.listswiftsresponse.swift; + var items = json.listimagestoreresponse.imagestore; if(items != null && items.length > 0) havingSwift = true; } }); if (havingSwift == false) { $.ajax({ - url: createURL("listS3s"), - dataType: "json", + url: createURL("listImageStores"), + data: { + provider: 'S3' + }, async: false, success: function(json) { - var items = json.lists3sresponse.s3; + var items = json.listimagestoreresponse.imagestore; if (items != null && items.length > 0) { havingS3 = true; } @@ -332,22 +336,26 @@ if (isAdmin()) { $.ajax({ - url: createURL("listSwifts"), - dataType: "json", + url: createURL("listImageStores"), + data:{ + provider: 'Swift' + }, async: false, success: function(json) { - var items = json.listswiftsresponse.swift; + var items = json.listimagestoreresponse.imagestore; if(items != null && items.length > 0) havingSwift = true; } }); if (havingSwift = false) { $.ajax({ - url: createURL("listS3s"), - dataType: "json", + url: createURL("listImageStores"), + data: { + provider: 'S3' + }, async: false, success: function(json) { - var items = json.lists3sresponse.s3; + var items = json.listimagestoreresponse.imagestore; if (items != null && items.length > 0) { havingS3 = true; } diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 8df635c8a2c..227b67e40bf 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -279,12 +279,12 @@ pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property. }; $.ajax({ - url: createURL('listHosts'), + url: createURL('listImageStores'), data: data2, success: function(json) { dataFns.systemVmCount($.extend(data, { - secondaryStorageCount: json.listhostsresponse.count ? - json.listhostsresponse.count : 0 + secondaryStorageCount: json.listimagestoreresponse.imagestore ? + json.listimagestoreresponse.count : 0 })); } }); @@ -2280,7 +2280,7 @@ } } } - } + } } } } @@ -2873,7 +2873,7 @@ } } }, - + InternalLbVm: { id: 'InternalLbVm', label: 'InternalLbVm', @@ -5699,7 +5699,7 @@ detailView: { isMaximized: true, - actions: { + actions: { addVmwareDc: { label: 'Add VMware datacenter', messages: { @@ -5860,14 +5860,14 @@ dedicateZone:{ label: 'Dedicate Zone', - messages: { - confirm: function(args) { + messages: { + confirm: function(args) { return 'Do you really want to dedicate this zone to a domain/account? '; - }, - notification: function(args) { + }, + notification: function(args) { return 'Zone Dedicated'; - } - }, + } + }, createForm:{ title:'Dedicate Zone', fields:{ @@ -5875,11 +5875,11 @@ label:'Domain', validation:{required:true}, select:function(args){ - $.ajax({ + $.ajax({ url:createURL("listDomains&listAll=true"), dataType:"json", async:false, - success: function(json) { + success: function(json) { var domainObjs= json.listdomainsresponse.domain; var items=[]; @@ -5890,20 +5890,20 @@ args.response.success({ data: items }); - } - - - }); } - }, + + }); + } + }, + accountId:{ label:'Account', docID:'helpAccountForDedication', validation:{required:false} } - } + } }, action: function(args) { @@ -5911,16 +5911,16 @@ var array2 = []; if(args.data.accountId != "") array2.push("&account=" +todb(args.data.accountId)); - - $.ajax({ + + $.ajax({ url: createURL("dedicateZone&zoneId=" + args.context.physicalResources[0].id + "&domainId=" +args.data.domainId + array2.join("") ), - dataType: "json", - success: function(json) { + dataType: "json", + success: function(json) { var jid = json.dedicatezoneresponse.jobid; args.response.success({ _custom: { jobId: jid - }, + }, notification: { poll: pollAsyncJobResult }, @@ -6073,7 +6073,7 @@ isdedicated:{label:'Dedicated'}, domainid:{label:'Domain ID'} - } + } ], dataProvider: function(args) { @@ -6083,7 +6083,7 @@ id: args.context.physicalResources[0].id }, success: function(json) { - selectedZoneObj = json.listzonesresponse.zone[0]; + selectedZoneObj = json.listzonesresponse.zone[0]; $.ajax({ url:createURL("listDedicatedZones&zoneid=" +args.context.physicalResources[0].id), dataType:"json", @@ -6103,12 +6103,12 @@ args.response.error(parseXMLHttpResponse(XMLHttpResponse)); } }); - args.response.success({ + args.response.success({ actionFilter: zoneActionfilter, data: selectedZoneObj - }); + }); - } + } }); } }, @@ -6843,51 +6843,55 @@ return listView; }, secondaryStorage: function() { - var listView = $.extend(true, {}, cloudStack.sections.system.subsections['secondary-storage'].listView, { - dataProvider: function (args) { - var searchByArgs = args.filterBy.search.value.length ? - '&name=' + args.filterBy.search.value : ''; + var listView = $.extend( + true, {}, + cloudStack.sections.system.subsections['secondary-storage'].sections.secondaryStorage, { + listView: { + dataProvider: function (args) { + var searchByArgs = args.filterBy.search.value.length ? + '&name=' + args.filterBy.search.value : ''; - var data = { - type: 'SecondaryStorage', - page: args.page, - pageSize: pageSize, - listAll: true - }; + var data = { + type: 'SecondaryStorage', + page: args.page, + pageSize: pageSize, + listAll: true + }; - $.ajax({ - url: createURL('listHosts' + searchByArgs), - data: data, - success: function (json) { - args.response.success({ data: json.listhostsresponse.host }); + $.ajax({ + url: createURL('listImageStores' + searchByArgs), + data: data, + success: function (json) { + args.response.success({ data: json.listimagestoreresponse.imagestore }); + }, + error: function (json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); }, - error: function (json) { - args.response.error(parseXMLHttpResponse(json)); - } - }); - }, + detailView: { + updateContext: function (args) { + var zone; - detailView: { - updateContext: function (args) { - var zone; + $.ajax({ + url: createURL('listZones'), + data: { id: args.context.secondarystorages[0].zoneid }, + async: false, + success: function (json) { + zone = json.listzonesresponse.zone[0]; + } + }); - $.ajax({ - url: createURL('listZones'), - data: { id: args.context.secondarystorages[0].zoneid }, - async: false, - success: function (json) { - zone = json.listzonesresponse.zone[0]; + selectedZoneObj = zone; + + return { + zones: [zone] + }; } - }); - - selectedZoneObj = zone; - - return { - zones: [zone] - }; + } } } - }); + ); return listView; }, @@ -9234,7 +9238,7 @@ args.response.success({ data: items }); - } + } }); @@ -9287,7 +9291,7 @@ dataType:"json", success:function(json){ var jid = json.dedicatepodresponse.jobid; - args.response.success({ + args.response.success({ _custom: { jobId: jid }, @@ -9295,8 +9299,8 @@ poll: pollAsyncJobResult }, - data:item - }); + data:item + }); }, @@ -9308,13 +9312,13 @@ } } - }, - error: function(XMLHttpResponse) { + }, + error: function(XMLHttpResponse) { var errorMsg = parseXMLHttpResponse(XMLHttpResponse); args.response.error(errorMsg); } - }); + }); }, @@ -9610,7 +9614,7 @@ isdedicated:{label:'Dedicated'}, domainid:{label:'Domain ID'} - } + } ], @@ -9653,7 +9657,7 @@ }); - } + } }, ipAllocations: { @@ -9983,7 +9987,7 @@ }, //hypervisor==VMWare begins here - + vCenterHost: { label: 'label.vcenter.host', docID: 'helpClustervCenterHost', @@ -10234,7 +10238,7 @@ dataType:"json", success:function(json){ var jid = json.dedicateclusterresponse.jobid; - args.response.success({ + args.response.success({ _custom: { jobId: jid }, @@ -10243,7 +10247,7 @@ }, data:$.extend(item, {state:'Enabled'}) - }); + }); }, @@ -10252,8 +10256,8 @@ } }); } - }, - error: function(XMLHttpResponse) { + }, + error: function(XMLHttpResponse) { var errorMsg = parseXMLHttpResponse(XMLHttpResponse); args.response.error(errorMsg); } @@ -10618,7 +10622,7 @@ { isdedicated:{label:'Dedicated'}, domainid:{label:'Domain ID'} - } + } ], dataProvider: function(args) { @@ -10647,21 +10651,21 @@ args.response.error(parseXMLHttpResponse(XMLHttpResponse)); } }); - args.response.success({ - actionFilter: clusterActionfilter, - data: item - }); + args.response.success({ + actionFilter: clusterActionfilter, + data: item + }); }, error:function(json){ args.response.error(parseXMLHttpResponse(XMLHttpResponse)); - } + } - }); - } - }, + }); + } + }, nexusVswitch: { title:'label.nexusVswitch', listView: { @@ -11147,7 +11151,7 @@ validation: { required: true }, isHidden: true, isPassword: true - }, + }, isDedicated:{ label:'Dedicate', @@ -11312,7 +11316,7 @@ }); } } - + var hostId = null; $.ajax({ url: createURL("addHost"), @@ -11336,7 +11340,7 @@ dataType:"json", success:function(json){ var jid = json.dedicatehostresponse.host.jobid; - args.response.success({ + args.response.success({ _custom: { jobId: jid }, @@ -11346,9 +11350,9 @@ data:item - }); + }); - }, + }, error:function(json){ args.response.error(parseXMLHttpResponse(XMLHttpResponse)); @@ -11357,7 +11361,7 @@ } }, - error: function(XMLHttpResponse) { + error: function(XMLHttpResponse) { var errorMsg = parseXMLHttpResponse(XMLHttpResponse); args.response.error(errorMsg); } @@ -11750,18 +11754,18 @@ isdedicated:{label:'Dedicated'}, domainid:{label:'Domain ID'} - } + } ], dataProvider: function(args) { - $.ajax({ - url: createURL("listHosts&id=" + args.context.hosts[0].id), - dataType: "json", - async: true, - success: function(json) { - var item = json.listhostsresponse.host[0]; + $.ajax({ + url: createURL("listHosts&id=" + args.context.hosts[0].id), + dataType: "json", + async: true, + success: function(json) { + var item = json.listhostsresponse.host[0]; $.ajax({ url:createURL("listDedicatedHosts&hostid=" +args.context.hosts[0].id), dataType:"json", @@ -11781,10 +11785,10 @@ args.response.error(parseXMLHttpResponse(XMLHttpResponse)); } }); - args.response.success({ - actionFilter: hostActionfilter, - data: item - }); + args.response.success({ + actionFilter: hostActionfilter, + data: item + }); } }); @@ -12436,7 +12440,7 @@ array1.push("&scope=" + todb(args.data.scope)); array1.push("&zoneid=" + args.data.zoneid); - + if(args.data.scope == 'zone'){ array1.push("&hypervisor=" + args.data.hypervisor); @@ -12811,214 +12815,1108 @@ 'secondary-storage': { title: 'label.secondary.storage', id: 'secondarystorages', - listView: { - id: 'secondarystorages', - section: 'seconary-storage', - fields: { - name: { label: 'label.name' }, - created: { label: 'label.created', converter: cloudStack.converters.toLocalDate }, - resourcestate: { - label: 'label.state', - indicator: { - 'Enabled': 'on', - 'Disabled': 'off', - 'Destroyed': 'off' - } - } - }, + sectionSelect: { + label: 'label.select.view' + }, + sections: { + secondaryStorage: { + type: 'select', + title: 'label.secondary.storage', + listView: { + id: 'secondarystorages', + section: 'seconary-storage', + fields: { + name: { label: 'label.name' }, + url: { label: 'label.url' }, + providername: { label: 'Provider' } + }, - dataProvider: function(args) { - var array1 = []; - if(args.filterBy != null) { - if(args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) { - switch(args.filterBy.search.by) { - case "name": - if(args.filterBy.search.value.length > 0) - array1.push("&keyword=" + args.filterBy.search.value); - break; - } - } - } - array1.push("&zoneid=" + args.context.zones[0].id); + dataProvider: function(args) { + var array1 = []; + if(args.filterBy != null) { + if(args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) { + switch(args.filterBy.search.by) { + case "name": + if(args.filterBy.search.value.length > 0) + array1.push("&keyword=" + args.filterBy.search.value); + break; + } + } + } + array1.push("&zoneid=" + args.context.zones[0].id); - $.ajax({ - url: createURL("listHosts&type=SecondaryStorage&page=" + args.page + "&pagesize=" + pageSize + array1.join("")), - dataType: "json", - async: true, - success: function(json) { - var items = json.listhostsresponse.host; - args.response.success({ - actionFilter: secondarystorageActionfilter, - data:items + $.ajax({ + url: createURL("listImageStores&page=" + args.page + "&pagesize=" + pageSize + array1.join("")), + dataType: "json", + async: true, + success: function(json) { + var items = json.listimagestoreresponse.imagestore; + args.response.success({ + actionFilter: secondarystorageActionfilter, + data:items + }); + } }); - } - }); - }, + }, - actions: { - add: { - label: 'label.add.secondary.storage', + actions: { + add: { + label: 'label.add.secondary.storage', - createForm: { - title: 'label.add.secondary.storage', - fields: { - zoneid: { - label: 'Zone', - docID: 'helpSecondaryStorageZone', - validation: { required: true }, - select: function(args) { - var data = args.context.zones ? - { id: args.context.zones[0].id } : { listAll: true }; + createForm: { + title: 'label.add.secondary.storage', + + fields: { + name: { label: 'label.name' }, + provider: { + label: 'Provider', + select: function(args){ + $.ajax({ + url: createURL('listStorageProviders'), + data: { + type: 'image' + }, + success: function(json){ + var objs = json.liststorageprovidersresponse.dataStoreProvider; + var items = []; + if(objs != null) { + for(var i = 0; i < objs.length; i++){ + if(objs[i].name == 'NFS') + items.unshift({id: objs[i].name, description: objs[i].name}); + else + items.push({id: objs[i].name, description: objs[i].name}); + } + } + args.response.success({ + data: items + }); + + args.$select.change(function() { + var $form = $(this).closest('form'); + if($(this).val() == "NFS") { + //NFS + $form.find('.form-item[rel=zoneid]').css('display', 'inline-block'); + $form.find('.form-item[rel=nfsServer]').css('display', 'inline-block'); + $form.find('.form-item[rel=path]').css('display', 'inline-block'); + + //S3 + $form.find('.form-item[rel=accesskey]').hide(); + $form.find('.form-item[rel=secretkey]').hide(); + $form.find('.form-item[rel=bucket]').hide(); + $form.find('.form-item[rel=endpoint]').hide(); + $form.find('.form-item[rel=usehttps]').hide(); + $form.find('.form-item[rel=connectiontimeout]').hide(); + $form.find('.form-item[rel=maxerrorretry]').hide(); + $form.find('.form-item[rel=sockettimeout]').hide(); + + $form.find('.form-item[rel=createNfsCache]').find('input').removeAttr('checked'); + $form.find('.form-item[rel=createNfsCache]').hide(); + $form.find('.form-item[rel=nfsCacheZoneid]').hide(); + $form.find('.form-item[rel=nfsCacheNfsServer]').hide(); + $form.find('.form-item[rel=nfsCachePath]').hide(); + + //Swift + $form.find('.form-item[rel=url]').hide(); + $form.find('.form-item[rel=account]').hide(); + $form.find('.form-item[rel=username]').hide(); + $form.find('.form-item[rel=key]').hide(); + } + else if ($(this).val() == "S3") { + //NFS + $form.find('.form-item[rel=zoneid]').hide(); + $form.find('.form-item[rel=nfsServer]').hide(); + $form.find('.form-item[rel=path]').hide(); + + //S3 + $form.find('.form-item[rel=accesskey]').css('display', 'inline-block'); + $form.find('.form-item[rel=secretkey]').css('display', 'inline-block'); + $form.find('.form-item[rel=bucket]').css('display', 'inline-block'); + $form.find('.form-item[rel=endpoint]').css('display', 'inline-block'); + $form.find('.form-item[rel=usehttps]').css('display', 'inline-block'); + $form.find('.form-item[rel=connectiontimeout]').css('display', 'inline-block'); + $form.find('.form-item[rel=maxerrorretry]').css('display', 'inline-block'); + $form.find('.form-item[rel=sockettimeout]').css('display', 'inline-block'); + + $form.find('.form-item[rel=createNfsCache]').find('input').attr('checked','checked'); + $form.find('.form-item[rel=createNfsCache]').css('display', 'inline-block'); + $form.find('.form-item[rel=nfsCacheZoneid]').css('display', 'inline-block'); + $form.find('.form-item[rel=nfsCacheNfsServer]').css('display', 'inline-block'); + $form.find('.form-item[rel=nfsCachePath]').css('display', 'inline-block'); + + + //Swift + $form.find('.form-item[rel=url]').hide(); + $form.find('.form-item[rel=account]').hide(); + $form.find('.form-item[rel=username]').hide(); + $form.find('.form-item[rel=key]').hide(); + } + else if($(this).val() == "Swift") { + //NFS + $form.find('.form-item[rel=zoneid]').hide(); + $form.find('.form-item[rel=nfsServer]').hide(); + $form.find('.form-item[rel=path]').hide(); + + //S3 + $form.find('.form-item[rel=accesskey]').hide(); + $form.find('.form-item[rel=secretkey]').hide(); + $form.find('.form-item[rel=bucket]').hide(); + $form.find('.form-item[rel=endpoint]').hide(); + $form.find('.form-item[rel=usehttps]').hide(); + $form.find('.form-item[rel=connectiontimeout]').hide(); + $form.find('.form-item[rel=maxerrorretry]').hide(); + $form.find('.form-item[rel=sockettimeout]').hide(); + + $form.find('.form-item[rel=createNfsCache]').find('input').removeAttr('checked'); + $form.find('.form-item[rel=createNfsCache]').hide(); + $form.find('.form-item[rel=nfsCacheZoneid]').hide(); + $form.find('.form-item[rel=nfsCacheNfsServer]').hide(); + $form.find('.form-item[rel=nfsCachePath]').hide(); + + //Swift + $form.find('.form-item[rel=url]').css('display', 'inline-block'); + $form.find('.form-item[rel=account]').css('display', 'inline-block'); + $form.find('.form-item[rel=username]').css('display', 'inline-block'); + $form.find('.form-item[rel=key]').css('display', 'inline-block'); + } + }); + + args.$select.change(); + } + }); + } + }, + + + //NFS (begin) + zoneid: { + label: 'Zone', + docID: 'helpSecondaryStorageZone', + validation: { required: true }, + select: function(args) { + $.ajax({ + url: createURL('listZones'), + data: { + listAll: true + }, + success: function(json) { + var zones = json.listzonesresponse.zone ? json.listzonesresponse.zone : []; + + if(zones != null){ //$.map(items, fn) - items can not be null + args.response.success({ + data: $.map(zones, function(zone) { + return { + id: zone.id, + description: zone.name + }; + }) + }); + } + else { + args.response.success({data: null}); + } + } + }); + } + }, + nfsServer: { + label: 'label.nfs.server', + docID: 'helpSecondaryStorageNFSServer', + validation: { required: true } + }, + path: { + label: 'label.path', + docID: 'helpSecondaryStoragePath', + validation: { required: true } + }, + //NFS (end) + + + //S3 (begin) + accesskey: { label: 'label.s3.access_key', validation: { required: true } }, + secretkey: { label: 'label.s3.secret_key', validation: { required: true} }, + bucket: { label: 'label.s3.bucket', validation: { required: true} }, + endpoint: { label: 'label.s3.endpoint' }, + usehttps: { + label: 'label.s3.use_https', + isEditable: true, + isBoolean: true, + isChecked: true, + converter:cloudStack.converters.toBooleanText + }, + connectiontimeout: { label: 'label.s3.connection_timeout' }, + maxerrorretry: { label: 'label.s3.max_error_retry' }, + sockettimeout: { label: 'label.s3.socket_timeout' }, + + createNfsCache: { + label: 'Create NFS Cache Storage', + isBoolean: true, + isChecked: true + }, + nfsCacheZoneid: { + dependsOn: 'createNfsCache', + label: 'Zone', + validation: { required: true }, + select: function(args) { + $.ajax({ + url: createURL('listZones'), + data: { + listAll: true + }, + success: function(json) { + var zones = json.listzonesresponse.zone; + + if(zones != null){ //$.map(items, fn) - items can not be null + args.response.success({ + data: $.map(zones, function(zone) { + return { + id: zone.id, + description: zone.name + }; + }) + }); + } + else { + args.response.success({data: null}); + } + } + }); + } + }, + nfsCacheNfsServer: { + dependsOn: 'createNfsCache', + label: 'label.nfs.server', + validation: { required: true } + }, + nfsCachePath: { + dependsOn: 'createNfsCache', + label: 'label.path', + validation: { required: true } + }, + //S3 (end) + + + //Swift (begin) + url: { label: 'label.url', validation: { required: true } }, + account: { label: 'label.account' }, + username: { label: 'label.username' }, + key: { label: 'label.key' } + //Swift (end) + } + }, + + action: function(args) { + var data = {}; + if(args.data.name != null && args.data.name.length > 0) { + $.extend(data, { + name: args.data.name + }); + } + + if(args.data.provider == 'NFS') { + var zoneid = args.data.zoneid; + var nfs_server = args.data.nfsServer; + var path = args.data.path; + var url = nfsURL(nfs_server, path); + + $.extend(data, { + provider: args.data.provider, + zoneid: zoneid, + url: url + }); $.ajax({ - url: createURL('listZones'), + url: createURL('addImageStore'), data: data, success: function(json) { - var zones = json.listzonesresponse.zone ? json.listzonesresponse.zone : []; - + var item = json.addimagestoreresponse.secondarystorage; args.response.success({ - data: $.map(zones, function(zone) { - return { - id: zone.id, - description: zone.name - }; - }) + data:item }); + }, + error: function(XMLHttpResponse) { + var errorMsg = parseXMLHttpResponse(XMLHttpResponse); + args.response.error(errorMsg); + } + }); + } + else if(args.data.provider == 'S3') { + $.extend(data, { + provider: args.data.provider, + 'details[0].key': 'accesskey', + 'details[0].value': args.data.accesskey, + 'details[1].key': 'secretkey', + 'details[1].value': args.data.secretkey, + 'details[2].key': 'bucket', + 'details[2].value': args.data.bucket, + 'details[3].key': 'usehttps', + 'details[3].value': (args.data.usehttps != null && args.data.usehttps == 'on' ? 'true' : 'false') + }); + + var index = 4; + if(args.data.endpoint != null && args.data.endpoint.length > 0){ + data['details[' + index.toString() + '].key'] = 'endpoint'; + data['details[' + index.toString() + '].value'] = args.data.endpoint; + index++; + } + if(args.data.connectiontimeout != null && args.data.connectiontimeout.length > 0){ + data['details[' + index.toString() + '].key'] = 'connectiontimeout'; + data['details[' + index.toString() + '].value'] = args.data.connectiontimeout; + index++; + } + if(args.data.maxerrorretry != null && args.data.maxerrorretry.length > 0){ + data['details[' + index.toString() + '].key'] = 'maxerrorretry'; + data['details[' + index.toString() + '].value'] = args.data.maxerrorretry; + index++; + } + if(args.data.sockettimeout != null && args.data.sockettimeout.length > 0){ + data['details[' + index.toString() + '].key'] = 'sockettimeout'; + data['details[' + index.toString() + '].value'] = args.data.sockettimeout; + index++; + } + + $.ajax({ + url: createURL('addImageStore'), + data: data, + success: function(json) { + havingS3 = true; + var item = json.addimagestoreresponse.secondarystorage; + args.response.success({ + data:item + }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + + if(args.data.createNfsCache == 'on') { + var zoneid = args.data.nfsCacheZoneid; + var nfs_server = args.data.nfsCacheNfsServer; + var path = args.data.nfsCachePath; + var url = nfsURL(nfs_server, path); + + var nfsCacheData = { + provider: 'NFS', + zoneid: zoneid, + url: url + }; + + $.ajax({ + url: createURL('createCacheStore'), + data: nfsCacheData, + success: function(json) { + //do nothing + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + } + } + else if(args.data.provider == 'Swift') { + $.extend(data, { + provider: args.data.provider, + url: args.data.url + }); + + var index = 0; + if(args.data.account != null && args.data.account.length > 0){ + data['details[' + index.toString() + '].key'] = 'account'; + data['details[' + index.toString() + '].value'] = args.data.account; + index++; + } + if(args.data.username != null && args.data.username.length > 0){ + data['details[' + index.toString() + '].key'] = 'username'; + data['details[' + index.toString() + '].value'] = args.data.username; + index++; + } + if(args.data.key != null && args.data.key.length > 0){ + data['details[' + index.toString() + '].key'] = 'key'; + data['details[' + index.toString() + '].value'] = args.data.key; + index++; + } + $.ajax({ + url: createURL('addImageStore'), + data: data, + success: function(json) { + havingSwift = true; + var item = json.addimagestoreresponse.secondarystorage; + args.response.success({ + data:item + }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); } }); } }, - nfsServer: { - label: 'label.nfs.server', - docID: 'helpSecondaryStorageNFSServer', - validation: { required: true } + + notification: { + poll: function(args) { + args.complete({ + actionFilter: secondarystorageActionfilter + }); + } }, - path: { - label: 'label.path', - docID: 'helpSecondaryStoragePath', - validation: { required: true } + + messages: { + notification: function(args) { + return 'label.add.secondary.storage'; + } } } }, - action: function(args) { - var zoneId = args.data.zoneid; - var nfs_server = args.data.nfsServer; - var path = args.data.path; - var url = nfsURL(nfs_server, path); - - $.ajax({ - url: createURL("addSecondaryStorage&zoneId=" + zoneId + "&url=" + todb(url)), - dataType: "json", - success: function(json) { - var item = json.addsecondarystorageresponse.secondarystorage; - args.response.success({ - data:item - }); - }, - error: function(XMLHttpResponse) { - var errorMsg = parseXMLHttpResponse(XMLHttpResponse); - args.response.error(errorMsg); + detailView: { + name: 'Secondary storage details', + isMaximized: true, + actions: { + remove: { + label: 'label.action.delete.secondary.storage' , + messages: { + confirm: function(args) { + return 'message.action.delete.secondary.storage'; + }, + notification: function(args) { + return 'label.action.delete.secondary.storage'; + } + }, + action: function(args) { + $.ajax({ + url: createURL("deleteImageStore&id=" + args.context.secondarystorages[0].id), + dataType: "json", + async: true, + success: function(json) { + args.response.success(); + } + }); + }, + notification: { + poll: function(args) { args.complete({ data: { resourcestate: 'Destroyed' } }); } + } } - }); - }, - notification: { - poll: function(args) { - args.complete({ - actionFilter: secondarystorageActionfilter - }); - } - }, + }, + tabs: { + details: { + title: 'label.details', + fields: [ + { + name: { label: 'label.name' } + }, + { + url: { label: 'label.url' }, + providername: { label: 'Provider' }, + scope: { label: 'label.scope' }, + zonename: { label: 'label.zone' }, + details: { + label: 'label.details', + converter: function(array1) { + var string1 = ''; + if(array1 != null) { + for(var i = 0; i < array1.length; i++) { + if(i > 0) + string1 += ', '; - messages: { - notification: function(args) { - return 'label.add.secondary.storage'; + string1 += array1[i].name + ': ' + array1[i].value; + } + } + return string1; + } + }, + id: { label: 'label.id' } + } + ], + + dataProvider: function(args) { + $.ajax({ + url: createURL("listImageStores&id=" + args.context.secondarystorages[0].id), + dataType: "json", + async: true, + success: function(json) { + var item = json.listimagestoreresponse.imagestore[0]; + args.response.success({ + actionFilter: secondarystorageActionfilter, + data:item + }); + } + }); + } + } + + // Granular settings for storage pool for secondary storage is not required + /* settings: { + title: 'label.menu.global.settings', + custom: cloudStack.uiCustom.granularSettings({ + dataProvider: function(args) { + args.response.success({ + data: [ + { name: 'config.param.1', value: 1 }, + { name: 'config.param.2', value: 2 } + ] + }); + }, + actions: { + edit: function(args) { + // call updateStorageLevelParameters + args.response.success(); + } + } + }) + } */ } } } }, + imageStores: { + type: 'select', + title: 'Image stores', + listView: { + id: 'secondarystorages', + section: 'seconary-storage', + fields: { + name: { label: 'label.name' }, + url: { label: 'label.url' }, + providername: { label: 'Provider' } + }, - detailView: { - name: 'Secondary storage details', - isMaximized: true, - actions: { - remove: { - label: 'label.action.delete.secondary.storage' , - messages: { - confirm: function(args) { - return 'message.action.delete.secondary.storage'; - }, - notification: function(args) { - return 'label.action.delete.secondary.storage'; - } - }, - action: function(args) { - $.ajax({ - url: createURL("deleteHost&id=" + args.context.secondarystorages[0].id), - dataType: "json", - async: true, - success: function(json) { - args.response.success(); + dataProvider: function(args) { + var array1 = []; + if(args.filterBy != null) { + if(args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) { + switch(args.filterBy.search.by) { + case "name": + if(args.filterBy.search.value.length > 0) + array1.push("&keyword=" + args.filterBy.search.value); + break; } - }); - }, - notification: { - poll: function(args) { args.complete({ data: { resourcestate: 'Destroyed' } }); } - } - } - - }, - tabs: { - details: { - title: 'label.details', - fields: [ - { - name: { label: 'label.name' } - }, - { - id: { label: 'label.id' }, - zonename: { label: 'label.zone' }, - created: { label: 'label.created', converter: cloudStack.converters.toLocalDate } } - ], - - dataProvider: function(args) { - $.ajax({ - url: createURL("listHosts&type=SecondaryStorage&id=" + args.context.secondarystorages[0].id), - dataType: "json", - async: true, - success: function(json) { - var item = json.listhostsresponse.host[0]; - args.response.success({ - actionFilter: secondarystorageActionfilter, - data:item - }); - } - }); } - } - - // Granular settings for storage pool for secondary storage is not required - /* settings: { - title: 'label.menu.global.settings', - custom: cloudStack.uiCustom.granularSettings({ - dataProvider: function(args) { + array1.push("&zoneid=" + args.context.zones[0].id); + + $.ajax({ + url: createURL("listImageStores&page=" + args.page + "&pagesize=" + pageSize + array1.join("")), + dataType: "json", + async: true, + success: function(json) { + var items = json.listimagestoreresponse.imagestore; args.response.success({ - data: [ - { name: 'config.param.1', value: 1 }, - { name: 'config.param.2', value: 2 } - ] + actionFilter: secondarystorageActionfilter, + data:items }); + } + }); + }, + + actions: { + add: { + label: 'label.add.secondary.storage', + + createForm: { + title: 'label.add.secondary.storage', + + fields: { + name: { label: 'label.name' }, + provider: { + label: 'Provider', + select: function(args){ + $.ajax({ + url: createURL('listStorageProviders'), + data: { + type: 'image' + }, + success: function(json){ + var objs = json.liststorageprovidersresponse.dataStoreProvider; + var items = []; + if(objs != null) { + for(var i = 0; i < objs.length; i++){ + if(objs[i].name == 'NFS') + items.unshift({id: objs[i].name, description: objs[i].name}); + else + items.push({id: objs[i].name, description: objs[i].name}); + } + } + args.response.success({ + data: items + }); + + args.$select.change(function() { + var $form = $(this).closest('form'); + if($(this).val() == "NFS") { + //NFS + $form.find('.form-item[rel=zoneid]').css('display', 'inline-block'); + $form.find('.form-item[rel=nfsServer]').css('display', 'inline-block'); + $form.find('.form-item[rel=path]').css('display', 'inline-block'); + + //S3 + $form.find('.form-item[rel=accesskey]').hide(); + $form.find('.form-item[rel=secretkey]').hide(); + $form.find('.form-item[rel=bucket]').hide(); + $form.find('.form-item[rel=endpoint]').hide(); + $form.find('.form-item[rel=usehttps]').hide(); + $form.find('.form-item[rel=connectiontimeout]').hide(); + $form.find('.form-item[rel=maxerrorretry]').hide(); + $form.find('.form-item[rel=sockettimeout]').hide(); + + $form.find('.form-item[rel=createNfsCache]').find('input').removeAttr('checked'); + $form.find('.form-item[rel=createNfsCache]').hide(); + $form.find('.form-item[rel=nfsCacheZoneid]').hide(); + $form.find('.form-item[rel=nfsCacheNfsServer]').hide(); + $form.find('.form-item[rel=nfsCachePath]').hide(); + + //Swift + $form.find('.form-item[rel=url]').hide(); + $form.find('.form-item[rel=account]').hide(); + $form.find('.form-item[rel=username]').hide(); + $form.find('.form-item[rel=key]').hide(); + } + else if ($(this).val() == "S3") { + //NFS + $form.find('.form-item[rel=zoneid]').hide(); + $form.find('.form-item[rel=nfsServer]').hide(); + $form.find('.form-item[rel=path]').hide(); + + //S3 + $form.find('.form-item[rel=accesskey]').css('display', 'inline-block'); + $form.find('.form-item[rel=secretkey]').css('display', 'inline-block'); + $form.find('.form-item[rel=bucket]').css('display', 'inline-block'); + $form.find('.form-item[rel=endpoint]').css('display', 'inline-block'); + $form.find('.form-item[rel=usehttps]').css('display', 'inline-block'); + $form.find('.form-item[rel=connectiontimeout]').css('display', 'inline-block'); + $form.find('.form-item[rel=maxerrorretry]').css('display', 'inline-block'); + $form.find('.form-item[rel=sockettimeout]').css('display', 'inline-block'); + + $form.find('.form-item[rel=createNfsCache]').find('input').attr('checked','checked'); + $form.find('.form-item[rel=createNfsCache]').css('display', 'inline-block'); + $form.find('.form-item[rel=nfsCacheZoneid]').css('display', 'inline-block'); + $form.find('.form-item[rel=nfsCacheNfsServer]').css('display', 'inline-block'); + $form.find('.form-item[rel=nfsCachePath]').css('display', 'inline-block'); + + + //Swift + $form.find('.form-item[rel=url]').hide(); + $form.find('.form-item[rel=account]').hide(); + $form.find('.form-item[rel=username]').hide(); + $form.find('.form-item[rel=key]').hide(); + } + else if($(this).val() == "Swift") { + //NFS + $form.find('.form-item[rel=zoneid]').hide(); + $form.find('.form-item[rel=nfsServer]').hide(); + $form.find('.form-item[rel=path]').hide(); + + //S3 + $form.find('.form-item[rel=accesskey]').hide(); + $form.find('.form-item[rel=secretkey]').hide(); + $form.find('.form-item[rel=bucket]').hide(); + $form.find('.form-item[rel=endpoint]').hide(); + $form.find('.form-item[rel=usehttps]').hide(); + $form.find('.form-item[rel=connectiontimeout]').hide(); + $form.find('.form-item[rel=maxerrorretry]').hide(); + $form.find('.form-item[rel=sockettimeout]').hide(); + + $form.find('.form-item[rel=createNfsCache]').find('input').removeAttr('checked'); + $form.find('.form-item[rel=createNfsCache]').hide(); + $form.find('.form-item[rel=nfsCacheZoneid]').hide(); + $form.find('.form-item[rel=nfsCacheNfsServer]').hide(); + $form.find('.form-item[rel=nfsCachePath]').hide(); + + //Swift + $form.find('.form-item[rel=url]').css('display', 'inline-block'); + $form.find('.form-item[rel=account]').css('display', 'inline-block'); + $form.find('.form-item[rel=username]').css('display', 'inline-block'); + $form.find('.form-item[rel=key]').css('display', 'inline-block'); + } + }); + + args.$select.change(); + } + }); + } + }, + + + //NFS (begin) + zoneid: { + label: 'Zone', + docID: 'helpSecondaryStorageZone', + validation: { required: true }, + select: function(args) { + $.ajax({ + url: createURL('listZones'), + data: { + listAll: true + }, + success: function(json) { + var zones = json.listzonesresponse.zone ? json.listzonesresponse.zone : []; + + if(zones != null){ //$.map(items, fn) - items can not be null + args.response.success({ + data: $.map(zones, function(zone) { + return { + id: zone.id, + description: zone.name + }; + }) + }); + } + else { + args.response.success({data: null}); + } + } + }); + } + }, + nfsServer: { + label: 'label.nfs.server', + docID: 'helpSecondaryStorageNFSServer', + validation: { required: true } + }, + path: { + label: 'label.path', + docID: 'helpSecondaryStoragePath', + validation: { required: true } + }, + //NFS (end) + + + //S3 (begin) + accesskey: { label: 'label.s3.access_key', validation: { required: true } }, + secretkey: { label: 'label.s3.secret_key', validation: { required: true} }, + bucket: { label: 'label.s3.bucket', validation: { required: true} }, + endpoint: { label: 'label.s3.endpoint' }, + usehttps: { + label: 'label.s3.use_https', + isEditable: true, + isBoolean: true, + isChecked: true, + converter:cloudStack.converters.toBooleanText + }, + connectiontimeout: { label: 'label.s3.connection_timeout' }, + maxerrorretry: { label: 'label.s3.max_error_retry' }, + sockettimeout: { label: 'label.s3.socket_timeout' }, + + createNfsCache: { + label: 'Create NFS Cache Storage', + isBoolean: true, + isChecked: true + }, + nfsCacheZoneid: { + dependsOn: 'createNfsCache', + label: 'Zone', + validation: { required: true }, + select: function(args) { + $.ajax({ + url: createURL('listZones'), + data: { + listAll: true + }, + success: function(json) { + var zones = json.listzonesresponse.zone; + + if(zones != null){ //$.map(items, fn) - items can not be null + args.response.success({ + data: $.map(zones, function(zone) { + return { + id: zone.id, + description: zone.name + }; + }) + }); + } + else { + args.response.success({data: null}); + } + } + }); + } + }, + nfsCacheNfsServer: { + dependsOn: 'createNfsCache', + label: 'label.nfs.server', + validation: { required: true } + }, + nfsCachePath: { + dependsOn: 'createNfsCache', + label: 'label.path', + validation: { required: true } + }, + //S3 (end) + + + //Swift (begin) + url: { label: 'label.url', validation: { required: true } }, + account: { label: 'label.account' }, + username: { label: 'label.username' }, + key: { label: 'label.key' } + //Swift (end) + } }, - actions: { - edit: function(args) { - // call updateStorageLevelParameters - args.response.success(); + + action: function(args) { + var data = {}; + if(args.data.name != null && args.data.name.length > 0) { + $.extend(data, { + name: args.data.name + }); + } + + if(args.data.provider == 'NFS') { + var zoneid = args.data.zoneid; + var nfs_server = args.data.nfsServer; + var path = args.data.path; + var url = nfsURL(nfs_server, path); + + $.extend(data, { + provider: args.data.provider, + zoneid: zoneid, + url: url + }); + + $.ajax({ + url: createURL('addImageStore'), + data: data, + success: function(json) { + var item = json.addimagestoreresponse.secondarystorage; + args.response.success({ + data:item + }); + }, + error: function(XMLHttpResponse) { + var errorMsg = parseXMLHttpResponse(XMLHttpResponse); + args.response.error(errorMsg); + } + }); + } + else if(args.data.provider == 'S3') { + $.extend(data, { + provider: args.data.provider, + 'details[0].key': 'accesskey', + 'details[0].value': args.data.accesskey, + 'details[1].key': 'secretkey', + 'details[1].value': args.data.secretkey, + 'details[2].key': 'bucket', + 'details[2].value': args.data.bucket, + 'details[3].key': 'usehttps', + 'details[3].value': (args.data.usehttps != null && args.data.usehttps == 'on' ? 'true' : 'false') + }); + + var index = 4; + if(args.data.endpoint != null && args.data.endpoint.length > 0){ + data['details[' + index.toString() + '].key'] = 'endpoint'; + data['details[' + index.toString() + '].value'] = args.data.endpoint; + index++; + } + if(args.data.connectiontimeout != null && args.data.connectiontimeout.length > 0){ + data['details[' + index.toString() + '].key'] = 'connectiontimeout'; + data['details[' + index.toString() + '].value'] = args.data.connectiontimeout; + index++; + } + if(args.data.maxerrorretry != null && args.data.maxerrorretry.length > 0){ + data['details[' + index.toString() + '].key'] = 'maxerrorretry'; + data['details[' + index.toString() + '].value'] = args.data.maxerrorretry; + index++; + } + if(args.data.sockettimeout != null && args.data.sockettimeout.length > 0){ + data['details[' + index.toString() + '].key'] = 'sockettimeout'; + data['details[' + index.toString() + '].value'] = args.data.sockettimeout; + index++; + } + + $.ajax({ + url: createURL('addImageStore'), + data: data, + success: function(json) { + havingS3 = true; + var item = json.addimagestoreresponse.secondarystorage; + args.response.success({ + data:item + }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + + if(args.data.createNfsCache == 'on') { + var zoneid = args.data.nfsCacheZoneid; + var nfs_server = args.data.nfsCacheNfsServer; + var path = args.data.nfsCachePath; + var url = nfsURL(nfs_server, path); + + var nfsCacheData = { + provider: 'NFS', + zoneid: zoneid, + url: url + }; + + $.ajax({ + url: createURL('createCacheStore'), + data: nfsCacheData, + success: function(json) { + //do nothing + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + } + } + else if(args.data.provider == 'Swift') { + $.extend(data, { + provider: args.data.provider, + url: args.data.url + }); + + var index = 0; + if(args.data.account != null && args.data.account.length > 0){ + data['details[' + index.toString() + '].key'] = 'account'; + data['details[' + index.toString() + '].value'] = args.data.account; + index++; + } + if(args.data.username != null && args.data.username.length > 0){ + data['details[' + index.toString() + '].key'] = 'username'; + data['details[' + index.toString() + '].value'] = args.data.username; + index++; + } + if(args.data.key != null && args.data.key.length > 0){ + data['details[' + index.toString() + '].key'] = 'key'; + data['details[' + index.toString() + '].value'] = args.data.key; + index++; + } + $.ajax({ + url: createURL('addImageStore'), + data: data, + success: function(json) { + havingSwift = true; + var item = json.addimagestoreresponse.secondarystorage; + args.response.success({ + data:item + }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + } + }, + + notification: { + poll: function(args) { + args.complete({ + actionFilter: secondarystorageActionfilter + }); + } + }, + + messages: { + notification: function(args) { + return 'label.add.secondary.storage'; } } - }) - } */ + } + }, + + detailView: { + name: 'Secondary storage details', + isMaximized: true, + actions: { + remove: { + label: 'label.action.delete.secondary.storage' , + messages: { + confirm: function(args) { + return 'message.action.delete.secondary.storage'; + }, + notification: function(args) { + return 'label.action.delete.secondary.storage'; + } + }, + action: function(args) { + $.ajax({ + url: createURL("deleteImageStore&id=" + args.context.secondarystorages[0].id), + dataType: "json", + async: true, + success: function(json) { + args.response.success(); + } + }); + }, + notification: { + poll: function(args) { args.complete({ data: { resourcestate: 'Destroyed' } }); } + } + } + + }, + tabs: { + details: { + title: 'label.details', + fields: [ + { + name: { label: 'label.name' } + }, + { + url: { label: 'label.url' }, + providername: { label: 'Provider' }, + scope: { label: 'label.scope' }, + zonename: { label: 'label.zone' }, + details: { + label: 'label.details', + converter: function(array1) { + var string1 = ''; + if(array1 != null) { + for(var i = 0; i < array1.length; i++) { + if(i > 0) + string1 += ', '; + + string1 += array1[i].name + ': ' + array1[i].value; + } + } + return string1; + } + }, + id: { label: 'label.id' } + } + ], + + dataProvider: function(args) { + $.ajax({ + url: createURL("listImageStores&id=" + args.context.secondarystorages[0].id), + dataType: "json", + async: true, + success: function(json) { + var item = json.listimagestoreresponse.imagestore[0]; + args.response.success({ + actionFilter: secondarystorageActionfilter, + data:item + }); + } + }); + } + } + + // Granular settings for storage pool for secondary storage is not required + /* settings: { + title: 'label.menu.global.settings', + custom: cloudStack.uiCustom.granularSettings({ + dataProvider: function(args) { + args.response.success({ + data: [ + { name: 'config.param.1', value: 1 }, + { name: 'config.param.2', value: 2 } + ] + }); + }, + actions: { + edit: function(args) { + // call updateStorageLevelParameters + args.response.success(); + } + } + }) + } */ + } + } } } } @@ -14018,7 +14916,7 @@ var clusterActionfilter = function(args) { var jsonObj = args.context.item; var allowedActions = []; - + if(jsonObj.domainid != null) allowedActions.push("release"); else @@ -14152,7 +15050,7 @@ } return allowedActions; } - + var internallbinstanceActionfilter = function(args) { var jsonObj = args.context.item; var allowedActions = []; @@ -14351,7 +15249,7 @@ } ); - nspHardcodingArray.push( + nspHardcodingArray.push( { id: 'vpcVirtualRouter', name: 'VPC Virtual Router', diff --git a/ui/scripts/ui-custom/physicalResources.js b/ui/scripts/ui-custom/physicalResources.js index 69c0295c08d..65b87e4415a 100644 --- a/ui/scripts/ui-custom/physicalResources.js +++ b/ui/scripts/ui-custom/physicalResources.js @@ -18,8 +18,9 @@ cloudStack.uiCustom.physicalResources = function(args) { var listView = function(targetID) { var target = args.sections.physicalResources.listView[targetID]; + var listViewArgs = $.isFunction(target) ? target() : target; - return $('

').listView({ listView: $.isFunction(target) ? target() : target }); + return $('
').listView(listViewArgs.listView ? listViewArgs : { listView: listViewArgs }); }; var $dashboard = $('#template').find('.system-dashboard-view').clone(); var getData = function() { diff --git a/ui/scripts/ui-custom/zoneChart.js b/ui/scripts/ui-custom/zoneChart.js index 12ba6aa6edc..fcfc7669334 100644 --- a/ui/scripts/ui-custom/zoneChart.js +++ b/ui/scripts/ui-custom/zoneChart.js @@ -58,12 +58,11 @@ listView: function(targetID, context) { return function(args) { var $elem = args.$panel; - var listViewArgs = cloudStack.sections.system.subsections[targetID].listView; + var listView = cloudStack.sections.system.subsections[targetID]; - $elem.listView({ - context: context, - listView: listViewArgs - }); + $elem.listView($.extend(true, {}, listView, { + context: context + })); }; }, diff --git a/ui/scripts/zoneWizard.js b/ui/scripts/zoneWizard.js index 84d19e890f2..ef8ddbb6b8c 100755 --- a/ui/scripts/zoneWizard.js +++ b/ui/scripts/zoneWizard.js @@ -358,7 +358,7 @@ $form.find('[rel=domain]').hide(); $form.find('[rel=accountId]').hide(); - } + } });*/ }, fields: { @@ -826,7 +826,7 @@ if($(this).val() == "VMware") { //$('li[input_sub_group="external"]', $dialogAddCluster).show(); if(dvSwitchEnabled ){ - /* $form.find('.form-item[rel=vSwitchPublicType]').css('display', 'inline-block'); + /* $fields.filter('[rel=vSwitchPublicType]').css('display', 'inline-block'); $form.find('.form-item[rel=vSwitchGuestType]').css('display', 'inline-block'); $form.find('.form-item[rel=vSwitchPublicName]').css('display','inline-block'); @@ -1233,21 +1233,21 @@ if(selectedHypervisorObj == null) { return; } - + //zone-wide-primary-storage is supported only for KVM and VMWare if(selectedHypervisorObj.hypervisortype == "KVM" || selectedHypervisorObj.hypervisortype == "VMware"){ - var scope=[]; + var scope=[]; scope.push({ id: 'zone', description: _l('label.zone.wide') }); - scope.push({ id: 'cluster', description: _l('label.cluster') }); - args.response.success({data: scope}); - } - else { - var scope=[]; - scope.push({ id: 'cluster', description: _l('label.cluster') }); - args.response.success({data: scope}); - } - } - }, + scope.push({ id: 'cluster', description: _l('label.cluster') }); + args.response.success({data: scope}); + } + else { + var scope=[]; + scope.push({ id: 'cluster', description: _l('label.cluster') }); + args.response.success({data: scope}); + } + } + }, protocol: { label: 'label.protocol', @@ -1531,7 +1531,126 @@ } }, secondaryStorage: { - fields: { + fields: { + name: { label: 'label.name' }, + provider: { + label: 'Provider', + select: function(args){ + $.ajax({ + url: createURL('listStorageProviders'), + data: { + type: 'image' + }, + success: function(json){ + var objs = json.liststorageprovidersresponse.dataStoreProvider; + var items = []; + if(objs != null) { + for(var i = 0; i < objs.length; i++){ + if(objs[i].name == 'NFS') + items.unshift({id: objs[i].name, description: objs[i].name}); + else + items.push({id: objs[i].name, description: objs[i].name}); + } + } + args.response.success({ + data: items + }); + + args.$select.change(function() { + var $form = $(this).closest('form'); + var $fields = $form.find('.field'); + + if($(this).val() == "NFS") { + //NFS + $fields.filter('[rel=zoneid]').css('display', 'inline-block'); + $fields.filter('[rel=nfsServer]').css('display', 'inline-block'); + $fields.filter('[rel=path]').css('display', 'inline-block'); + + //S3 + $fields.filter('[rel=accesskey]').hide(); + $fields.filter('[rel=secretkey]').hide(); + $fields.filter('[rel=bucket]').hide(); + $fields.filter('[rel=endpoint]').hide(); + $fields.filter('[rel=usehttps]').hide(); + $fields.filter('[rel=connectiontimeout]').hide(); + $fields.filter('[rel=maxerrorretry]').hide(); + $fields.filter('[rel=sockettimeout]').hide(); + + $fields.filter('[rel=createNfsCache]').hide(); + $fields.filter('[rel=createNfsCache]').find('input').removeAttr('checked'); + $fields.filter('[rel=nfsCacheNfsServer]').hide(); + $fields.filter('[rel=nfsCachePath]').hide(); + + //Swift + $fields.filter('[rel=url]').hide(); + $fields.filter('[rel=account]').hide(); + $fields.filter('[rel=username]').hide(); + $fields.filter('[rel=key]').hide(); + } + else if ($(this).val() == "S3") { + //NFS + $fields.filter('[rel=zoneid]').hide(); + $fields.filter('[rel=nfsServer]').hide(); + $fields.filter('[rel=path]').hide(); + + //S3 + $fields.filter('[rel=accesskey]').css('display', 'inline-block'); + $fields.filter('[rel=secretkey]').css('display', 'inline-block'); + $fields.filter('[rel=bucket]').css('display', 'inline-block'); + $fields.filter('[rel=endpoint]').css('display', 'inline-block'); + $fields.filter('[rel=usehttps]').css('display', 'inline-block'); + $fields.filter('[rel=connectiontimeout]').css('display', 'inline-block'); + $fields.filter('[rel=maxerrorretry]').css('display', 'inline-block'); + $fields.filter('[rel=sockettimeout]').css('display', 'inline-block'); + + $fields.filter('[rel=createNfsCache]').find('input').attr('checked','checked'); + $fields.filter('[rel=createNfsCache]').css('display', 'inline-block'); + $fields.filter('[rel=nfsCacheNfsServer]').css('display', 'inline-block'); + $fields.filter('[rel=nfsCachePath]').css('display', 'inline-block'); + + //Swift + $fields.filter('[rel=url]').hide(); + $fields.filter('[rel=account]').hide(); + $fields.filter('[rel=username]').hide(); + $fields.filter('[rel=key]').hide(); + } + else if($(this).val() == "Swift") { + //NFS + $fields.filter('[rel=zoneid]').hide(); + $fields.filter('[rel=nfsServer]').hide(); + $fields.filter('[rel=path]').hide(); + + //S3 + $fields.filter('[rel=accesskey]').hide(); + $fields.filter('[rel=secretkey]').hide(); + $fields.filter('[rel=bucket]').hide(); + $fields.filter('[rel=endpoint]').hide(); + $fields.filter('[rel=usehttps]').hide(); + $fields.filter('[rel=connectiontimeout]').hide(); + $fields.filter('[rel=maxerrorretry]').hide(); + $fields.filter('[rel=sockettimeout]').hide(); + + $fields.filter('[rel=createNfsCache]').hide(); + $fields.filter('[rel=createNfsCache]').find('input').removeAttr('checked'); + $fields.filter('[rel=nfsCacheNfsServer]').hide(); + $fields.filter('[rel=nfsCachePath]').hide(); + + //Swift + $fields.filter('[rel=url]').css('display', 'inline-block'); + $fields.filter('[rel=account]').css('display', 'inline-block'); + $fields.filter('[rel=username]').css('display', 'inline-block'); + $fields.filter('[rel=key]').css('display', 'inline-block'); + } + }); + + args.$select.change(); + } + }); + } + }, + + + //NFS (begin) nfsServer: { label: 'label.nfs.server', validation: { required: true } @@ -1539,7 +1658,50 @@ path: { label: 'label.path', validation: { required: true } - } + }, + //NFS (end) + + + //S3 (begin) + accesskey: { label: 'label.s3.access_key', validation: { required: true } }, + secretkey: { label: 'label.s3.secret_key', validation: { required: true} }, + bucket: { label: 'label.s3.bucket', validation: { required: true} }, + endpoint: { label: 'label.s3.endpoint' }, + usehttps: { + label: 'label.s3.use_https', + isEditable: true, + isBoolean: true, + isChecked: true, + converter:cloudStack.converters.toBooleanText + }, + connectiontimeout: { label: 'label.s3.connection_timeout' }, + maxerrorretry: { label: 'label.s3.max_error_retry' }, + sockettimeout: { label: 'label.s3.socket_timeout' }, + + createNfsCache: { + label: 'Create NFS Cache Storage', + isBoolean: true, + isChecked: true + }, + nfsCacheNfsServer: { + dependsOn: 'createNfsCache', + label: 'label.nfs.server', + validation: { required: true } + }, + nfsCachePath: { + dependsOn: 'createNfsCache', + label: 'label.path', + validation: { required: true } + }, + //S3 (end) + + + //Swift (begin) + url: { label: 'label.url', validation: { required: true } }, + account: { label: 'label.account' }, + username: { label: 'label.username' }, + key: { label: 'label.key' } + //Swift (end) } } }, @@ -1607,7 +1769,7 @@ if(args.data.zone.networkdomain != null && args.data.zone.networkdomain.length > 0) array1.push("&domain=" + todb(args.data.zone.networkdomain)); - + var dedicatedZoneId = null; $.ajax({ @@ -3377,16 +3539,16 @@ success: function(json) { var item = json.addvmwaredcresponse.vmwaredc; if(item.id != null){ - $.ajax({ - url: createURL("addCluster" + array1.join("")), - dataType: "json", - async: true, - success: function(json) { + $.ajax({ + url: createURL("addCluster" + array1.join("")), + dataType: "json", + async: true, + success: function(json) { stepFns.addPrimaryStorage({ //skip "add host step" when hypervisor is VMware - data: $.extend(args.data, { - returnedCluster: json.addclusterresponse.cluster[0] - }) - }); + data: $.extend(args.data, { + returnedCluster: json.addclusterresponse.cluster[0] + }) + }); }, error: function(XMLHttpResponse) { var errorMsg = parseXMLHttpResponse(XMLHttpResponse); @@ -3410,10 +3572,10 @@ async: true, success: function(json) { stepFns.addHost({ - data: $.extend(args.data, { - returnedCluster: json.addclusterresponse.cluster[0] - }) - }); + data: $.extend(args.data, { + returnedCluster: json.addclusterresponse.cluster[0] + }) + }); }, error: function(XMLHttpResponse) { var errorMsg = parseXMLHttpResponse(XMLHttpResponse); @@ -3589,25 +3751,153 @@ addSecondaryStorage: function(args) { message(dictionary['message.creating.secondary.storage']); - var nfs_server = args.data.secondaryStorage.nfsServer; - var path = args.data.secondaryStorage.path; - var url = nfsURL(nfs_server, path); - - $.ajax({ - url: createURL("addSecondaryStorage&zoneId=" + args.data.returnedZone.id + "&url=" + todb(url)), - dataType: "json", - success: function(json) { - complete({ - data: $.extend(args.data, { - returnedSecondaryStorage: json.addsecondarystorageresponse.secondarystorage - }) - }); - }, - error: function(XMLHttpResponse) { - var errorMsg = parseXMLHttpResponse(XMLHttpResponse); - error('addSecondaryStorage', errorMsg, { fn: 'addSecondaryStorage', args: args }); + var data = {}; + if(args.data.secondaryStorage.name != null && args.data.secondaryStorage.name.length > 0) { + $.extend(data, { + name: args.data.secondaryStorage.name + }); + } + + if(args.data.secondaryStorage.provider == 'NFS') { + var nfs_server = args.data.secondaryStorage.nfsServer; + var path = args.data.secondaryStorage.path; + var url = nfsURL(nfs_server, path); + + $.extend(data, { + provider: 'NFS', + zoneid: args.data.returnedZone.id, + url: url + }); + + $.ajax({ + url: createURL('addImageStore'), + data: data, + success: function(json) { + complete({ + data: $.extend(args.data, { + returnedSecondaryStorage: json.addimagestoreresponse.secondarystorage + }) + }); + }, + error: function(XMLHttpResponse) { + var errorMsg = parseXMLHttpResponse(XMLHttpResponse); + error('addSecondaryStorage', errorMsg, { fn: 'addSecondaryStorage', args: args }); + } + }); + } + else if(args.data.secondaryStorage.provider == 'S3') { + $.extend(data, { + provider: args.data.secondaryStorage.provider, + 'details[0].key': 'accesskey', + 'details[0].value': args.data.secondaryStorage.accesskey, + 'details[1].key': 'secretkey', + 'details[1].value': args.data.secondaryStorage.secretkey, + 'details[2].key': 'bucket', + 'details[2].value': args.data.secondaryStorage.bucket, + 'details[3].key': 'usehttps', + 'details[3].value': (args.data.secondaryStorage.usehttps != null && args.data.secondaryStorage.usehttps == 'on' ? 'true' : 'false') + }); + + var index = 4; + if(args.data.secondaryStorage.endpoint != null && args.data.secondaryStorage.endpoint.length > 0){ + data['details[' + index.toString() + '].key'] = 'endpoint'; + data['details[' + index.toString() + '].value'] = args.data.secondaryStorage.endpoint; + index++; } - }); + if(args.data.secondaryStorage.connectiontimeout != null && args.data.secondaryStorage.connectiontimeout.length > 0){ + data['details[' + index.toString() + '].key'] = 'connectiontimeout'; + data['details[' + index.toString() + '].value'] = args.data.secondaryStorage.connectiontimeout; + index++; + } + if(args.data.secondaryStorage.maxerrorretry != null && args.data.secondaryStorage.maxerrorretry.length > 0){ + data['details[' + index.toString() + '].key'] = 'maxerrorretry'; + data['details[' + index.toString() + '].value'] = args.data.secondaryStorage.maxerrorretry; + index++; + } + if(args.data.secondaryStorage.sockettimeout != null && args.data.secondaryStorage.sockettimeout.length > 0){ + data['details[' + index.toString() + '].key'] = 'sockettimeout'; + data['details[' + index.toString() + '].value'] = args.data.secondaryStorage.sockettimeout; + index++; + } + $.ajax({ + url: createURL('addImageStore'), + data: data, + success: function(json) { + complete({ + data: $.extend(args.data, { + returnedSecondaryStorage: json.addimagestoreresponse.secondarystorage + }) + }); + }, + error: function(XMLHttpResponse) { + var errorMsg = parseXMLHttpResponse(XMLHttpResponse); + error('addSecondaryStorage', errorMsg, { fn: 'addSecondaryStorage', args: args }); + } + }); + + if(args.data.secondaryStorage.createNfsCache == 'on') { + var zoneid = args.data.secondaryStorage.nfsCacheZoneid; + var nfs_server = args.data.secondaryStorage.nfsCacheNfsServer; + var path = args.data.secondaryStorage.nfsCachePath; + var url = nfsURL(nfs_server, path); + + var nfsCacheData = { + provider: 'NFS', + zoneid: args.data.returnedZone.id, + url: url + }; + + $.ajax({ + url: createURL('createCacheStore'), + data: nfsCacheData, + success: function(json) { + //do nothing + }, + error: function(XMLHttpResponse) { + var errorMsg = parseXMLHttpResponse(XMLHttpResponse); + error('addSecondaryStorage', errorMsg, { fn: 'addSecondaryStorage', args: args }); + } + }); + } + } + else if(args.data.secondaryStorage.provider == 'Swift') { + $.extend(data, { + provider: args.data.secondaryStorage.provider, + url: args.data.secondaryStorage.url + }); + + var index = 0; + if(args.data.secondaryStorage.account != null && args.data.secondaryStorage.account.length > 0){ + data['details[' + index.toString() + '].key'] = 'account'; + data['details[' + index.toString() + '].value'] = args.data.secondaryStorage.account; + index++; + } + if(args.data.secondaryStorage.username != null && args.data.secondaryStorage.username.length > 0){ + data['details[' + index.toString() + '].key'] = 'username'; + data['details[' + index.toString() + '].value'] = args.data.secondaryStorage.username; + index++; + } + if(args.data.secondaryStorage.key != null && args.data.secondaryStorage.key.length > 0){ + data['details[' + index.toString() + '].key'] = 'key'; + data['details[' + index.toString() + '].value'] = args.data.secondaryStorage.key; + index++; + } + $.ajax({ + url: createURL('addImageStore'), + data: data, + success: function(json) { + complete({ + data: $.extend(args.data, { + returnedSecondaryStorage: json.addimagestoreresponse.secondarystorage + }) + }); + }, + error: function(XMLHttpResponse) { + var errorMsg = parseXMLHttpResponse(XMLHttpResponse); + error('addSecondaryStorage', errorMsg, { fn: 'addSecondaryStorage', args: args }); + } + }); + } } }; diff --git a/utils/src/com/cloud/utils/S3Utils.java b/utils/src/com/cloud/utils/S3Utils.java index 33a3ebde660..5ee578304d5 100644 --- a/utils/src/com/cloud/utils/S3Utils.java +++ b/utils/src/com/cloud/utils/S3Utils.java @@ -38,7 +38,9 @@ import java.io.FileNotFoundException; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; +import java.net.URL; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.UUID; @@ -47,13 +49,17 @@ import org.apache.log4j.Logger; import com.amazonaws.AmazonClientException; import com.amazonaws.ClientConfiguration; +import com.amazonaws.HttpMethod; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.model.Bucket; +import com.amazonaws.services.s3.model.CannedAccessControlList; import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.PutObjectRequest; +import com.amazonaws.services.s3.model.S3Object; import com.amazonaws.services.s3.model.S3ObjectSummary; import com.cloud.utils.exception.CloudRuntimeException; @@ -70,7 +76,7 @@ public final class S3Utils { super(); } - private static AmazonS3 acquireClient(final ClientOptions clientOptions) { + public static AmazonS3 acquireClient(final ClientOptions clientOptions) { final AWSCredentials credentials = new BasicAWSCredentials( clientOptions.getAccessKey(), clientOptions.getSecretKey()); @@ -138,6 +144,71 @@ public final class S3Utils { } + public static void putObject(final ClientOptions clientOptions, + final InputStream sourceStream, final String bucketName, final String key) { + + assert clientOptions != null; + assert sourceStream != null; + assert !isBlank(bucketName); + assert !isBlank(key); + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(format("Sending stream as S3 object %1$s in " + + "bucket %2$s", key, bucketName)); + } + + acquireClient(clientOptions).putObject(bucketName, key, sourceStream, null); + + } + + public static void putObject(final ClientOptions clientOptions, + final PutObjectRequest req) { + + assert clientOptions != null; + assert req != null; + + acquireClient(clientOptions).putObject(req); + + } + + public static void setObjectAcl(final ClientOptions clientOptions, final String bucketName, final String key, + final CannedAccessControlList acl) { + + assert clientOptions != null; + assert acl != null; + + acquireClient(clientOptions).setObjectAcl(bucketName, key, acl); + + } + + public static URL generatePresignedUrl(final ClientOptions clientOptions, final String bucketName, final String key, + final Date expiration) { + + assert clientOptions != null; + assert !isBlank(bucketName); + assert !isBlank(key); + + return acquireClient(clientOptions).generatePresignedUrl(bucketName, key, expiration, HttpMethod.GET); + + } + + // Note that whenever S3Object is returned, client code needs to close the internal stream to avoid resource leak. + public static S3Object getObject(final ClientOptions clientOptions, + final String bucketName, final String key) { + + assert clientOptions != null; + assert !isBlank(bucketName); + assert !isBlank(key); + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(format("Get S3 object %1$s in " + + "bucket %2$s", key, bucketName)); + } + + return acquireClient(clientOptions).getObject(bucketName, key); + + } + @SuppressWarnings("unchecked") public static File getFile(final ClientOptions clientOptions, final String bucketName, final String key, @@ -165,8 +236,15 @@ public final class S3Utils { key, bucketName, tempFile.getName())); } - connection.getObject(new GetObjectRequest(bucketName, key), - tempFile); + try { + connection.getObject(new GetObjectRequest(bucketName, key), tempFile); + } catch (AmazonClientException ex) { + // hack to handle different ETAG format generated from RiakCS for multi-part uploaded object + String msg = ex.getMessage(); + if (!msg.contains("verify integrity")){ + throw ex; + } + } final File targetFile = new File(targetDirectory, namingStrategy.determineFileName(key)); @@ -188,7 +266,8 @@ public final class S3Utils { targetDirectory.getAbsolutePath(), bucketName, key), e); - } finally { + } + finally { if (tempFile != null) { tempFile.delete(); @@ -225,6 +304,18 @@ public final class S3Utils { } + public static List getDirectory(final ClientOptions clientOptions, + final String bucketName, final String sourcePath){ + assert clientOptions != null; + assert isNotBlank(bucketName); + assert isNotBlank(sourcePath); + + final AmazonS3 connection = acquireClient(clientOptions); + + // List the objects in the source directory on S3 + return listDirectory(bucketName, sourcePath, connection); + } + private static List listDirectory(final String bucketName, final String directory, final AmazonS3 client) { @@ -239,6 +330,7 @@ public final class S3Utils { } + public static void putDirectory(final ClientOptions clientOptions, final String bucketName, final File directory, final FilenameFilter fileNameFilter, @@ -284,6 +376,8 @@ public final class S3Utils { } + + public static void deleteObject(final ClientOptions clientOptions, final String bucketName, final String key) { diff --git a/utils/src/com/cloud/utils/UriUtils.java b/utils/src/com/cloud/utils/UriUtils.java index 3bcee7aeac4..b9d54d5cbc4 100644 --- a/utils/src/com/cloud/utils/UriUtils.java +++ b/utils/src/com/cloud/utils/UriUtils.java @@ -18,16 +18,34 @@ package com.cloud.utils; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.net.HttpURLConnection; +import java.net.Inet6Address; +import java.net.InetAddress; import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; +import java.net.UnknownHostException; import javax.net.ssl.HttpsURLConnection; +import org.apache.commons.httpclient.Credentials; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; +import org.apache.commons.httpclient.UsernamePasswordCredentials; +import org.apache.commons.httpclient.auth.AuthScope; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.log4j.Logger; + import com.cloud.utils.exception.CloudRuntimeException; public class UriUtils { + + public static final Logger s_logger = Logger.getLogger(UriUtils.class.getName()); + public static String formNfsUri(String host, String path) { try { URI uri = new URI("nfs", host, path, null); @@ -111,4 +129,68 @@ public class UriUtils { } return remoteSize; } + + public static Pair validateUrl(String url) throws IllegalArgumentException { + try { + URI uri = new URI(url); + if ((uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("http") + && !uri.getScheme().equalsIgnoreCase("https") && !uri.getScheme().equalsIgnoreCase("file"))) { + throw new IllegalArgumentException("Unsupported scheme for url: " + url); + } + int port = uri.getPort(); + if (!(port == 80 || port == 8080 || port == 443 || port == -1)) { + throw new IllegalArgumentException("Only ports 80, 8080 and 443 are allowed"); + } + + if (port == -1 && uri.getScheme().equalsIgnoreCase("https")) { + port = 443; + } else if (port == -1 && uri.getScheme().equalsIgnoreCase("http")) { + port = 80; + } + + String host = uri.getHost(); + try { + InetAddress hostAddr = InetAddress.getByName(host); + if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress()) { + throw new IllegalArgumentException("Illegal host specified in url"); + } + if (hostAddr instanceof Inet6Address) { + throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")"); + } + return new Pair(host, port); + } catch (UnknownHostException uhe) { + throw new IllegalArgumentException("Unable to resolve " + host); + } + } catch (URISyntaxException use) { + throw new IllegalArgumentException("Invalid URL: " + url); + } + } + + public static InputStream getInputStreamFromUrl(String url, String user, String password) { + + try{ + Pair hostAndPort = validateUrl(url); + HttpClient httpclient = new HttpClient(new MultiThreadedHttpConnectionManager()); + if ((user != null) && (password != null)) { + httpclient.getParams().setAuthenticationPreemptive(true); + Credentials defaultcreds = new UsernamePasswordCredentials(user, password); + httpclient.getState().setCredentials(new AuthScope(hostAndPort.first(), hostAndPort.second(), AuthScope.ANY_REALM), defaultcreds); + s_logger.info("Added username=" + user + ", password=" + password + "for host " + hostAndPort.first() + ":" + hostAndPort.second()); + } + // Execute the method. + GetMethod method = new GetMethod(url); + int statusCode = httpclient.executeMethod(method); + + if (statusCode != HttpStatus.SC_OK) { + s_logger.error("Failed to read from URL: " + url); + return null; + } + + return method.getResponseBodyAsStream(); + } + catch (Exception ex){ + s_logger.error("Failed to read from URL: " + url); + return null; + } + } } diff --git a/utils/src/com/cloud/utils/script/Script.java b/utils/src/com/cloud/utils/script/Script.java index 3632bf5ad1b..d3a35916eaf 100755 --- a/utils/src/com/cloud/utils/script/Script.java +++ b/utils/src/com/cloud/utils/script/Script.java @@ -450,7 +450,15 @@ public class Script implements Callable { } - file = new File(System.getProperty("paths.script") + File.separator + path + File.separator + script); + search = System.getProperty("paths.script"); + + search += File.separatorChar + path + File.separator; + do { + search = search.substring(0, search.lastIndexOf(File.separator)); + file = new File(search + File.separator + script); + s_logger.debug("Looking for " + script + " in " + file.getAbsolutePath()); + } while (!file.exists() && search.lastIndexOf(File.separator) != -1); + if (file.exists()) { return file.getAbsolutePath(); }