From 86a384041211457861d25081c01e4bc9f3a125e9 Mon Sep 17 00:00:00 2001 From: Min Chen Date: Tue, 2 Apr 2013 11:19:49 -0700 Subject: [PATCH] Fix AddSecondaryStorageCmd to use CloudStack default secondary storage store plugin. --- .../com/cloud/resource/ResourceService.java | 6 +- api/src/com/cloud/storage/ObjectStore.java | 51 ++++++ .../src/com/cloud}/storage/ScopeType.java | 2 +- .../cloudstack/api/ResponseGenerator.java | 4 +- .../admin/host/AddSecondaryStorageCmd.java | 56 +++++-- .../response/ObjectStoreDetailResponse.java | 48 ++++++ .../api/response/ObjectStoreResponse.java | 156 ++++++++++++++++++ .../subsystem/api/storage/ClusterScope.java | 2 + .../api/storage/DataStoreProviderManager.java | 1 + .../subsystem/api/storage/HostScope.java | 2 + .../engine/subsystem/api/storage/Scope.java | 2 + .../subsystem/api/storage/ZoneScope.java | 2 + .../datastore/db/PrimaryDataStoreDao.java | 2 +- .../datastore/db/PrimaryDataStoreDaoImpl.java | 2 +- .../storage/datastore/db/StoragePoolVO.java | 2 +- .../image/store/ImageDataStoreImpl.java | 35 +++- .../allocator/StorageAllocatorTest.java | 2 +- .../storage/test/volumeServiceTest.java | 2 +- .../DataStoreProviderManagerImpl.java | 6 + .../endpoint/DefaultEndPointSelector.java | 2 +- .../image/datastore/ImageDataStore.java | 4 +- .../image/datastore/ImageDataStoreHelper.java | 7 +- .../storage/image/db/ImageDataStoreVO.java | 63 +++++-- .../datastore/PrimaryDataStoreHelper.java | 2 +- .../datastore/PrimaryDataStoreImpl.java | 2 +- .../allocator/RandomStoragePoolAllocator.java | 2 +- .../CloudStackImageDataStoreLifeCycle.java | 72 +++++++- .../CloudStackImageDataStoreProvider.java | 2 +- ...oudStackPrimaryDataStoreLifeCycleImpl.java | 2 +- .../src/com/cloud/api/ApiResponseHelper.java | 25 ++- .../cloud/resource/ResourceManagerImpl.java | 115 ++++++++++++- .../com/cloud/storage/StorageManagerImpl.java | 1 - .../com/cloud/storage/VolumeManagerImpl.java | 1 - .../storage/listener/StoragePoolMonitor.java | 2 +- .../resource/MockResourceManagerImpl.java | 9 + setup/db/db/schema-410to420.sql | 2 + 36 files changed, 634 insertions(+), 62 deletions(-) create mode 100644 api/src/com/cloud/storage/ObjectStore.java rename {engine/api/src/org/apache/cloudstack/engine/subsystem/api => api/src/com/cloud}/storage/ScopeType.java (93%) create mode 100644 api/src/org/apache/cloudstack/api/response/ObjectStoreDetailResponse.java create mode 100644 api/src/org/apache/cloudstack/api/response/ObjectStoreResponse.java diff --git a/api/src/com/cloud/resource/ResourceService.java b/api/src/com/cloud/resource/ResourceService.java index 08e2585d1a7..dbed36e3a82 100755 --- a/api/src/com/cloud/resource/ResourceService.java +++ b/api/src/com/cloud/resource/ResourceService.java @@ -38,6 +38,7 @@ import com.cloud.exception.ResourceInUseException; import com.cloud.host.Host; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.org.Cluster; +import com.cloud.storage.ObjectStore; import com.cloud.storage.S3; import com.cloud.storage.Swift; import com.cloud.utils.Pair; @@ -100,7 +101,10 @@ public interface ResourceService { Swift discoverSwift(AddSwiftCmd addSwiftCmd) throws DiscoveryException; S3 discoverS3(AddS3Cmd cmd) throws DiscoveryException; - + + ObjectStore discoverObjectStore(AddSecondaryStorageCmd cmd) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException; + + List getSupportedHypervisorTypes(long zoneId, boolean forVirtualRouter, Long podId); Pair, Integer> listSwifts(ListSwiftsCmd cmd); diff --git a/api/src/com/cloud/storage/ObjectStore.java b/api/src/com/cloud/storage/ObjectStore.java new file mode 100644 index 00000000000..636537f8437 --- /dev/null +++ b/api/src/com/cloud/storage/ObjectStore.java @@ -0,0 +1,51 @@ +// 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 org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +public interface ObjectStore extends Identity, InternalIdentity { + + /** + * @return name of the object store. + */ + String getName(); + + /** + * @return availability zone. + */ + Long getDataCenterId(); + + /** + * @return region id. + * @return + */ + Long getRegionId(); + + /** + * @return object store provider name + */ + String getProviderName(); + + + /** + * + * @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/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java index d1e13023117..b85f2c5f7ed 100644 --- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java @@ -326,6 +326,8 @@ public interface ResponseGenerator { RegionResponse createRegionResponse(Region region); + ObjectStoreResponse createObjectStoreResponse(ObjectStore os); + /** * @param resourceTag * @param keyValueOnly TODO @@ -384,7 +386,7 @@ public interface ResponseGenerator { GuestOSResponse createGuestOSResponse(GuestOS os); SnapshotScheduleResponse createSnapshotScheduleResponse(SnapshotSchedule sched); - + UsageRecordResponse createUsageResponse(Usage usageRecord); TrafficMonitorResponse createTrafficMonitorResponse(Host trafficMonitor); 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..663750edcc8 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 @@ -17,6 +17,7 @@ package org.apache.cloudstack.api.command.admin.host; import java.util.List; +import java.util.Map; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -24,12 +25,16 @@ 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.HostResponse; +import org.apache.cloudstack.api.response.ObjectStoreResponse; +import org.apache.cloudstack.api.response.RegionResponse; 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.ObjectStore; import com.cloud.user.Account; @APICommand(name = "addSecondaryStorage", description="Adds secondary storage.", responseObject=HostResponse.class) @@ -48,6 +53,21 @@ public class AddSecondaryStorageCmd extends BaseCmd { description="the Zone ID for the secondary storage") private Long zoneId; + @Parameter(name=ApiConstants.REGION_ID, type=CommandType.UUID, entityType=RegionResponse.class, + description="the Region ID for the secondary storage") + private Long regionId; + + @Parameter(name=ApiConstants.DETAILS, type=CommandType.MAP, description="the details for the secondary storage data store") + private Map details; + + @Parameter(name=ApiConstants.SCOPE, type=CommandType.STRING, + required=false, description="the scope of the secondary storage data store: zone or region or global") + private String scope; + + @Parameter(name=ApiConstants.PROVIDER, type=CommandType.STRING, + required=false, description="the secondary storage store provider name") + private String imageProviderName; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -60,6 +80,23 @@ public class AddSecondaryStorageCmd extends BaseCmd { return zoneId; } + public Long getRegionId() { + return regionId; + } + + public Map getDetails() { + return details; + } + + public String getScope() { + return this.scope; + } + + public String getImageProviderName() { + return this.imageProviderName; + } + + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -76,17 +113,14 @@ 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); - } + try{ + ObjectStore result = _resourceService.discoverObjectStore(this); + ObjectStoreResponse storeResponse = null; + if (result != null ) { + storeResponse = _responseGenerator.createObjectStoreResponse(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/response/ObjectStoreDetailResponse.java b/api/src/org/apache/cloudstack/api/response/ObjectStoreDetailResponse.java new file mode 100644 index 00000000000..b532c2848a7 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/ObjectStoreDetailResponse.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.api.response; + +import org.apache.cloudstack.api.BaseResponse; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +public class ObjectStoreDetailResponse extends BaseResponse { + @SerializedName("name") @Param(description="detail property name of the object store") + private String name; + + @SerializedName("value") @Param(description="detail property value of the object store") + private String value; + + 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/api/src/org/apache/cloudstack/api/response/ObjectStoreResponse.java b/api/src/org/apache/cloudstack/api/response/ObjectStoreResponse.java new file mode 100644 index 00000000000..de3a26f27d6 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/ObjectStoreResponse.java @@ -0,0 +1,156 @@ +// 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.Date; + +import javax.persistence.Column; + +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.ObjectStore; +import com.cloud.storage.ScopeType; +import com.cloud.storage.StoragePool; +import com.cloud.storage.StoragePoolStatus; +import com.google.gson.annotations.SerializedName; + +@EntityReference(value=ObjectStore.class) +public class ObjectStoreResponse extends BaseResponse { + @SerializedName("id") @Param(description="the ID of the object store") + private String id; + + @SerializedName("zoneid") @Param(description="the Zone ID of the object store") + private String zoneId; + + @SerializedName(ApiConstants.ZONE_NAME) @Param(description="the Zone name of the object store") + private String zoneName; + + @SerializedName("regionid") @Param(description="the Region ID of the object store") + private String regionId; + + @SerializedName("regionname") @Param(description="the Region name of the object store") + private String regionName; + + @SerializedName("name") @Param(description="the name of the object store") + private String name; + + @SerializedName("url") @Param(description="the url of the object store") + private String url; + + @SerializedName("providername") @Param(description="the provider name of the object store") + private String providerName; + + @SerializedName("scope") @Param(description="the scope of the object store") + private ScopeType type; + + @SerializedName("details") @Param(description="the details of the object store") + private String details; + + + + @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 getRegionId() { + return regionId; + } + + public void setRegionId(String regionId) { + this.regionId = regionId; + } + + public String getRegionName() { + return regionName; + } + + public void setRegionName(String regionName) { + this.regionName = regionName; + } + + 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 getType() { + return type; + } + + public void setType(ScopeType type) { + this.type = type; + } + + public String getDetails() { + return details; + } + + public void setDetails(String details) { + this.details = details; + } + + + +} 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..938f055b2d9 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,6 +18,8 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; +import com.cloud.storage.ScopeType; + public class ClusterScope extends AbstractScope { private ScopeType type = ScopeType.CLUSTER; 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..8dd8c3a0824 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 @@ -26,6 +26,7 @@ import com.cloud.utils.component.Manager; public interface DataStoreProviderManager extends Manager, DataStoreProviderApiService { public DataStoreProvider getDataStoreProvider(String name); public DataStoreProvider getDefaultPrimaryDataStoreProvider(); + public DataStoreProvider getDefaultImageDataStoreProvider(); public List getDataStoreProviders(); } 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..57a448ff2db 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,6 +18,8 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; +import com.cloud.storage.ScopeType; + public class HostScope extends AbstractScope { private ScopeType type = ScopeType.HOST; 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..25226f984ea 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,6 +18,8 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; +import com.cloud.storage.ScopeType; + public interface Scope { public ScopeType getScopeType(); public boolean isSameScope(Scope scope); 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..a71a9c7ffb5 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,6 +18,8 @@ */ package org.apache.cloudstack.engine.subsystem.api.storage; +import com.cloud.storage.ScopeType; + public class ZoneScope extends AbstractScope { private ScopeType type = ScopeType.ZONE; 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 4d845252f57..16fed3586aa 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 @@ -20,8 +20,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; +import com.cloud.storage.ScopeType; import com.cloud.storage.StoragePoolStatus; import com.cloud.utils.db.GenericDao; /** 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 7fcddf1940f..7e7e6fd4002 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,11 +28,11 @@ 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.storage.ScopeType; import com.cloud.storage.StoragePoolStatus; import com.cloud.utils.db.DB; 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 55b2314f0fd..6a7c8544c53 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,9 +29,9 @@ import javax.persistence.TableGenerator; import javax.persistence.Temporal; import javax.persistence.TemporalType; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; 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; diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageDataStoreImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageDataStoreImpl.java index 5761033c351..4a6016c699d 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageDataStoreImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageDataStoreImpl.java @@ -52,9 +52,9 @@ public class ImageDataStoreImpl implements ImageDataStore { boolean needDownloadToCacheStorage = false; public ImageDataStoreImpl() { - + } - + protected void configure(ImageDataStoreVO dataStoreVO, ImageDataStoreDriver imageDataStoreDriver, ImageDataStoreProvider provider) { this.driver = imageDataStoreDriver; @@ -99,7 +99,7 @@ public class ImageDataStoreImpl implements ImageDataStore { @Override public Scope getScope() { - return new ZoneScope(imageDataStoreVO.getDcId()); + return new ZoneScope(imageDataStoreVO.getDataCenterId()); } @Override @@ -142,4 +142,33 @@ public class ImageDataStoreImpl implements ImageDataStore { // TODO Auto-generated method stub return false; } + + @Override + public String getName() { + return imageDataStoreVO.getName(); + } + + @Override + public Long getDataCenterId() { + return imageDataStoreVO.getDataCenterId(); + } + + @Override + public Long getRegionId() { + return imageDataStoreVO.getRegionId(); + } + + @Override + public String getProviderName() { + return imageDataStoreVO.getProviderName(); + } + + @Override + public String getProtocol() { + return imageDataStoreVO.getProtocol(); + } + + + + } 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 c6ebf2e7fb5..b369459a9a8 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 @@ -28,7 +28,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; @@ -55,6 +54,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; 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 b542e85be22..293d7fb11c8 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 @@ -40,7 +40,6 @@ 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.TemplateInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; @@ -74,6 +73,7 @@ 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.ScopeType; import com.cloud.storage.Storage; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Storage.TemplateType; 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 c6911df31d3..aa1ace21a76 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 @@ -139,6 +139,12 @@ public class DataStoreProviderManagerImpl extends ManagerBase implements DataSto return this.getDataStoreProvider("cloudstack primary data store provider"); } + + @Override + public DataStoreProvider getDefaultImageDataStoreProvider() { + return this.getDataStoreProvider("cloudstack image data store provider"); + } + @Override public List getDataStoreProviders(String type) { if (type == null) { diff --git a/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java b/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java index c385abe9624..772a8f29aef 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java +++ b/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java @@ -31,7 +31,6 @@ 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.EndPoint; 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.disktype.DiskFormat; import org.apache.cloudstack.storage.HypervisorHostEndPoint; import org.apache.log4j.Logger; @@ -40,6 +39,7 @@ import org.springframework.stereotype.Component; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; +import com.cloud.storage.ScopeType; import com.cloud.utils.db.DB; import com.cloud.utils.db.SearchCriteria2; import com.cloud.utils.db.SearchCriteriaService; diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageDataStore.java b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageDataStore.java index ed2274e3d40..a9b7e9bc5aa 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageDataStore.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageDataStore.java @@ -26,7 +26,9 @@ 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.ObjectStore; + +public interface ImageDataStore extends DataStore, ObjectStore { TemplateInfo getTemplate(long templateId); VolumeInfo getVolume(long volumeId); SnapshotInfo getSnapshot(long snapshotId); 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 index 3f1632cf13c..e31a644d1c9 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageDataStoreHelper.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageDataStoreHelper.java @@ -22,11 +22,11 @@ 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.storage.ScopeType; import com.cloud.utils.exception.CloudRuntimeException; @Component @@ -44,16 +44,17 @@ public class ImageDataStoreHelper { store.setProviderName((String)params.get("providerName")); store.setScope((ScopeType)params.get("scope")); store.setUuid((String)params.get("uuid")); + store.setUrl((String)params.get("url")); 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/db/ImageDataStoreVO.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDataStoreVO.java index 4cb402a1271..3e0d8386d9c 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDataStoreVO.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageDataStoreVO.java @@ -26,11 +26,13 @@ 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.ObjectStore; +import com.cloud.storage.ScopeType; @Entity @Table(name = "image_data_store") -public class ImageDataStoreVO { +public class ImageDataStoreVO implements ObjectStore { @Id @TableGenerator(name = "image_data_store_sq", table = "sequence", pkColumnName = "name", valueColumnName = "value", pkColumnValue = "image_data_store_seq", allocationSize = 1) @Column(name = "id", nullable = false) @@ -38,24 +40,30 @@ public class ImageDataStoreVO { @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; - + + @Column(name = "region_id") + private long regionId; + @Column(name = "scope") @Enumerated(value = EnumType.STRING) private ScopeType scope; - - + + public long getId() { return this.id; } @@ -75,36 +83,55 @@ 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 Long getRegionId() { + return regionId; + } + + public void setRegionId(long regionId) { + this.regionId = regionId; + } + 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; + } + + } 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 5f8daf42bb3..c5f7a1b2352 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 @@ -28,7 +28,6 @@ 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.command.AttachPrimaryDataStoreCmd; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; @@ -42,6 +41,7 @@ import com.cloud.alert.AlertManager; import com.cloud.capacity.Capacity; import com.cloud.capacity.CapacityVO; import com.cloud.capacity.dao.CapacityDao; +import com.cloud.storage.ScopeType; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolHostVO; diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java index b695ff09c2e..3266eaf5631 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java @@ -35,7 +35,6 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreState 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; @@ -49,6 +48,7 @@ import org.apache.log4j.Logger; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.storage.ScopeType; import com.cloud.storage.StoragePoolHostVO; import com.cloud.storage.StoragePoolStatus; import com.cloud.storage.VMTemplateStoragePoolVO; 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..5de3f6be796 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,13 +21,13 @@ 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; diff --git a/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackImageDataStoreLifeCycle.java b/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackImageDataStoreLifeCycle.java index dce40d97dbc..f111dfaf8df 100644 --- a/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackImageDataStoreLifeCycle.java +++ b/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackImageDataStoreLifeCycle.java @@ -16,6 +16,11 @@ // under the License. package org.apache.cloudstack.storage.datastore.lifecycle; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; import java.util.Map; import javax.inject.Inject; @@ -29,23 +34,88 @@ import org.apache.cloudstack.storage.image.datastore.ImageDataStoreProviderManag import org.apache.cloudstack.storage.image.db.ImageDataStoreDao; import org.apache.cloudstack.storage.image.db.ImageDataStoreVO; import org.apache.cloudstack.storage.image.store.lifecycle.ImageDataStoreLifeCycle; +import org.apache.log4j.Logger; import com.cloud.agent.api.StoragePoolInfo; +import com.cloud.exception.DiscoveryException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.hypervisor.kvm.discoverer.KvmDummyResourceBase; +import com.cloud.resource.Discoverer; +import com.cloud.resource.ResourceListener; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ServerResource; +import com.cloud.storage.ScopeType; +import com.cloud.utils.UriUtils; public class CloudStackImageDataStoreLifeCycle implements ImageDataStoreLifeCycle { + + private static final Logger s_logger = Logger + .getLogger(CloudStackImageDataStoreLifeCycle.class); + @Inject + protected ResourceManager _resourceMgr; @Inject protected ImageDataStoreDao imageStoreDao; @Inject ImageDataStoreHelper imageStoreHelper; @Inject ImageDataStoreProviderManager imageStoreMgr; + + protected List _discoverers; + public List getDiscoverers() { + return _discoverers; + } + public void setDiscoverers(List _discoverers) { + this._discoverers = _discoverers; + } + public CloudStackImageDataStoreLifeCycle() { } @Override public DataStore initialize(Map dsInfos) { - ImageDataStoreVO ids = imageStoreHelper.createImageDataStore(dsInfos); + + Long dcId = (Long) dsInfos.get("zoneId"); + String url = (String) dsInfos.get("url"); + String providerName = (String)dsInfos.get("providerName"); + + 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", url); + imageStoreParameters.put("zoneId", dcId); + imageStoreParameters.put("url", url); + imageStoreParameters.put("protocol", uri.getScheme().toLowerCase()); + imageStoreParameters.put("scope", ScopeType.ZONE); + imageStoreParameters.put("providerName", providerName); + + ImageDataStoreVO ids = imageStoreHelper.createImageDataStore(imageStoreParameters); return imageStoreMgr.getImageDataStore(ids.getId()); } diff --git a/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/provider/CloudStackImageDataStoreProvider.java b/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/provider/CloudStackImageDataStoreProvider.java index c91aa1e3af2..1e88da3f583 100644 --- a/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/provider/CloudStackImageDataStoreProvider.java +++ b/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/provider/CloudStackImageDataStoreProvider.java @@ -30,7 +30,6 @@ 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.ImageDataStoreProvider; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; import org.apache.cloudstack.storage.datastore.driver.CloudStackImageDataStoreDriverImpl; import org.apache.cloudstack.storage.datastore.lifecycle.CloudStackImageDataStoreLifeCycle; import org.apache.cloudstack.storage.image.ImageDataStoreDriver; @@ -39,6 +38,7 @@ import org.apache.cloudstack.storage.image.datastore.ImageDataStoreProviderManag import org.apache.cloudstack.storage.image.store.lifecycle.ImageDataStoreLifeCycle; import org.springframework.stereotype.Component; +import com.cloud.storage.ScopeType; import com.cloud.utils.component.ComponentContext; @Component 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 51ea2126756..4308558bf0c 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 @@ -35,7 +35,6 @@ import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreParameters; -import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; 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; @@ -62,6 +61,7 @@ import com.cloud.resource.ResourceManager; import com.cloud.server.ManagementServer; import com.cloud.storage.OCFS2Manager; import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.storage.ScopeType; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolAutomation; diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 64be7f8758a..90543316cf5 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -80,6 +80,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.ObjectStoreResponse; import org.apache.cloudstack.api.response.PhysicalNetworkResponse; import org.apache.cloudstack.api.response.PodResponse; import org.apache.cloudstack.api.response.PrivateGatewayResponse; @@ -235,6 +236,7 @@ import com.cloud.service.ServiceOfferingVO; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.GuestOS; import com.cloud.storage.GuestOSCategoryVO; +import com.cloud.storage.ObjectStore; import com.cloud.storage.S3; import com.cloud.storage.Snapshot; import com.cloud.storage.SnapshotVO; @@ -439,7 +441,7 @@ public class ApiResponseHelper implements ResponseGenerator { vmSnapshotResponse.setCreated(vmSnapshot.getCreated()); vmSnapshotResponse.setDescription(vmSnapshot.getDescription()); vmSnapshotResponse.setDisplayName(vmSnapshot.getDisplayName()); - UserVm vm = ApiDBUtils.findUserVmById(vmSnapshot.getVmId()); + UserVm vm = ApiDBUtils.findUserVmById(vmSnapshot.getVmId()); if(vm!=null) vmSnapshotResponse.setVirtualMachineid(vm.getUuid()); if(vmSnapshot.getParent() != null) @@ -449,7 +451,7 @@ public class ApiResponseHelper implements ResponseGenerator { vmSnapshotResponse.setObjectName("vmsnapshot"); return vmSnapshotResponse; } - + @Override public SnapshotPolicyResponse createSnapshotPolicyResponse(SnapshotPolicy policy) { SnapshotPolicyResponse policyResponse = new SnapshotPolicyResponse(); @@ -546,7 +548,7 @@ public class ApiResponseHelper implements ResponseGenerator { vlanResponse.setIp6Gateway(vlan.getIp6Gateway()); vlanResponse.setIp6Cidr(vlan.getIp6Cidr()); - + String ip6Range = vlan.getIp6Range(); if (ip6Range != null) { String[] range = ip6Range.split("-"); @@ -887,6 +889,15 @@ public class ApiResponseHelper implements ResponseGenerator { } + + @Override + public ObjectStoreResponse createObjectStoreResponse(ObjectStore os) { + // TODO Auto-generated method stub + return null; + } + + + @Override public ClusterResponse createClusterResponse(Cluster cluster, Boolean showCapacities) { ClusterResponse clusterResponse = new ClusterResponse(); @@ -2249,7 +2260,7 @@ public class ApiResponseHelper implements ResponseGenerator { if (((network.getCidr()) != null) && (network.getNetworkCidr() == null)) { response.setNetmask(NetUtils.cidr2Netmask(network.getCidr())); } - + response.setIp6Gateway(network.getIp6Gateway()); response.setIp6Cidr(network.getIp6Cidr()); @@ -2444,7 +2455,7 @@ public class ApiResponseHelper implements ResponseGenerator { List cidrs = ApiDBUtils.findFirewallSourceCidrs(fwRule.getId()); response.setCidrList(StringUtils.join(cidrs, ",")); - + if (fwRule.getTrafficType() == FirewallRule.TrafficType.Ingress) { IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId()); response.setPublicIpAddressId(ip.getId()); @@ -3475,7 +3486,7 @@ public class ApiResponseHelper implements ResponseGenerator { return usageRecResponse; } - + public String getDateStringInternal(Date inputDate) { if (inputDate == null) return null; @@ -3559,7 +3570,7 @@ public class ApiResponseHelper implements ResponseGenerator { return sb.toString(); } - + @Override public TrafficMonitorResponse createTrafficMonitorResponse(Host trafficMonitor) { Map tmDetails = ApiDBUtils.findHostDetailsById(trafficMonitor.getId()); diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index 82bca5194bf..e9b0c827ab7 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -45,6 +45,17 @@ 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.engine.subsystem.api.storage.ClusterScope; +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.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.PrimaryDataStoreInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; +import org.apache.cloudstack.region.RegionVO; +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; @@ -107,8 +118,10 @@ import com.cloud.org.Grouping.AllocationState; import com.cloud.org.Managed; import com.cloud.service.ServiceOfferingVO; import com.cloud.storage.GuestOSCategoryVO; +import com.cloud.storage.ObjectStore; import com.cloud.storage.S3; import com.cloud.storage.S3VO; +import com.cloud.storage.ScopeType; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolHostVO; @@ -167,7 +180,10 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, StorageManager _storageMgr; @Inject protected SecondaryStorageVmManager _secondaryStorageMgr; - + @Inject + DataStoreProviderManager _dataStoreProviderMgr; + @Inject + protected RegionDao _regionDao; @Inject protected DataCenterDao _dcDao; @Inject @@ -206,6 +222,9 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, protected HighAvailabilityManager _haMgr; @Inject protected StorageService _storageSvr; + @Inject + DataStoreManager _dataStoreMgr; + protected List _discoverers; public List getDiscoverers() { @@ -639,6 +658,10 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, return discoverHostsFull(dcId, podId, clusterId, clusterName, url, username, password, cmd.getHypervisor(), hostTags, cmd.getFullUrlParams(), true); } + + + + @Override public List discoverHosts(AddSecondaryStorageCmd cmd) throws IllegalArgumentException, DiscoveryException, @@ -669,6 +692,96 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, return this._s3Mgr.listS3s(cmd); } + @Override + public ObjectStore discoverObjectStore(AddSecondaryStorageCmd cmd) throws IllegalArgumentException, DiscoveryException, + InvalidParameterValueException { + String providerName = cmd.getImageProviderName(); + DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(providerName); + + if (storeProvider == null) { + storeProvider = _dataStoreProviderMgr.getDefaultImageDataStoreProvider(); + if (storeProvider == null) { + throw new InvalidParameterValueException( + "can't find image store provider: " + providerName); + } + } + + Long dcId = cmd.getZoneId(); + Long regionId = cmd.getRegionId(); + String url = cmd.getUrl(); + Map details = cmd.getDetails(); + + ScopeType scopeType = ScopeType.ZONE; + 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 && dcId == null) { + throw new InvalidParameterValueException( + "zone id can't be null, if scope is zone"); + } else if (scopeType == ScopeType.REGION && regionId == null) { + throw new InvalidParameterValueException( + "region id can't be null, if scope is region"); + } + + 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, dcId, "dcId"); + throw ex; + } + } + + if ( regionId != null ){ + // Check if the region exists in the system + RegionVO region = _regionDao.findById(regionId.intValue()); + if (region == null) { + throw new InvalidParameterValueException("Can't find region by id " + + regionId); + } + } + + Map params = new HashMap(); + params.put("zoneId", dcId); + params.put("regionId", regionId); + params.put("url", cmd.getUrl()); + params.put("name", cmd.getUrl()); + params.put("details", details); + params.put("providerName", storeProvider.getName()); + + DataStoreLifeCycle lifeCycle = storeProvider.getDataStoreLifeCycle(); + DataStore store = null; + try { + store = lifeCycle.initialize(params); + + if (scopeType == ScopeType.ZONE) { + ZoneScope zoneScope = new ZoneScope(dcId); + lifeCycle.attachZone(store, zoneScope); + } + } catch (Exception e) { + s_logger.debug("Failed to add data store", e); + throw new CloudRuntimeException("Failed to add data store", e); + } + + return (ObjectStore)_dataStoreMgr.getDataStore(store.getId(), + DataStoreRole.Image); + } + 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; diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 4e410e4b41e..72a0e0741f2 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -55,7 +55,6 @@ 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.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.VolumeDataFactory; diff --git a/server/src/com/cloud/storage/VolumeManagerImpl.java b/server/src/com/cloud/storage/VolumeManagerImpl.java index 1e8edafe4e2..ddd6ff00b83 100644 --- a/server/src/com/cloud/storage/VolumeManagerImpl.java +++ b/server/src/com/cloud/storage/VolumeManagerImpl.java @@ -49,7 +49,6 @@ 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; diff --git a/server/src/com/cloud/storage/listener/StoragePoolMonitor.java b/server/src/com/cloud/storage/listener/StoragePoolMonitor.java index f957ca31ada..e035fd7c26f 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; @@ -38,6 +37,7 @@ 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; diff --git a/server/test/com/cloud/resource/MockResourceManagerImpl.java b/server/test/com/cloud/resource/MockResourceManagerImpl.java index 5202c317e56..df62d2e6bc9 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.ObjectStore; import com.cloud.storage.S3; import com.cloud.storage.Swift; import com.cloud.template.VirtualMachineTemplate; @@ -608,4 +609,12 @@ public class MockResourceManagerImpl extends ManagerBase implements ResourceMana return null; } + @Override + public ObjectStore discoverObjectStore(AddSecondaryStorageCmd cmd) throws IllegalArgumentException, DiscoveryException, + InvalidParameterValueException { + // TODO Auto-generated method stub + return null; + } + + } diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index c48cb5e72af..da5d5d5dcdb 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -73,7 +73,9 @@ CREATE TABLE `cloud`.`image_data_store` ( `name` varchar(255) NOT NULL COMMENT 'name of data store', `image_provider_name` varchar(255) NOT NULL COMMENT 'id of image_data_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', + `region_id` bigint unsigned COMMENT 'region id of data store', `scope` varchar(255) COMMENT 'scope of data store', `uuid` varchar(255) COMMENT 'uuid of data store', PRIMARY KEY(`id`)