diff --git a/api/src/main/java/com/cloud/storage/Bucket.java b/api/src/main/java/com/cloud/storage/Bucket.java new file mode 100644 index 000000000000..e3cfd513474c --- /dev/null +++ b/api/src/main/java/com/cloud/storage/Bucket.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; + +import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +import java.util.Date; + +public interface Bucket extends ControlledEntity, Identity, InternalIdentity { + long getObjectStoreId(); + + Date getCreated(); + + State getState(); + + void setName(String name); + + public enum State { + Allocated, Created, Destroyed; + @Override + public String toString() { + return this.name(); + } + + public boolean equals(String status) { + return this.toString().equalsIgnoreCase(status); + } + } +} \ No newline at end of file diff --git a/api/src/main/java/com/cloud/storage/DataStoreRole.java b/api/src/main/java/com/cloud/storage/DataStoreRole.java index cc20cc0ce963..185e370159ca 100644 --- a/api/src/main/java/com/cloud/storage/DataStoreRole.java +++ b/api/src/main/java/com/cloud/storage/DataStoreRole.java @@ -21,7 +21,7 @@ import com.cloud.utils.exception.CloudRuntimeException; public enum DataStoreRole { - Primary("primary"), Image("image"), ImageCache("imagecache"), Backup("backup"); + Primary("primary"), Image("image"), ImageCache("imagecache"), Backup("backup"), Object("object"); public boolean isImageStore() { return (role.equalsIgnoreCase("image") || role.equalsIgnoreCase("imagecache")) ? true : false; @@ -45,6 +45,8 @@ public static DataStoreRole getRole(String role) { return ImageCache; } else if (role.equalsIgnoreCase("backup")) { return Backup; + } else if (role.equalsIgnoreCase("object")) { + return Object; } else { throw new CloudRuntimeException("can't identify the role"); } diff --git a/api/src/main/java/com/cloud/storage/ObjectStore.java b/api/src/main/java/com/cloud/storage/ObjectStore.java new file mode 100644 index 000000000000..07df08855a9b --- /dev/null +++ b/api/src/main/java/com/cloud/storage/ObjectStore.java @@ -0,0 +1,46 @@ +// 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 object store provider name + */ + String getProviderName(); + + /** + * + * @return data store protocol + */ + String getProtocol(); + + /** + * + * @return uri + */ + String getUrl(); + +} diff --git a/api/src/main/java/com/cloud/storage/StorageService.java b/api/src/main/java/com/cloud/storage/StorageService.java index bb086ad05cbf..ef033ca6898f 100644 --- a/api/src/main/java/com/cloud/storage/StorageService.java +++ b/api/src/main/java/com/cloud/storage/StorageService.java @@ -109,4 +109,5 @@ public interface StorageService { StoragePool syncStoragePool(SyncStoragePoolCmd cmd); + ObjectStore discoverObjectStore(String name, String url, String providerName, Map details) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException; } diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index c1438251b858..b0eeb786b0ea 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -1028,6 +1028,7 @@ public class ApiConstants { public static final String MTU = "mtu"; public static final String AUTO_ENABLE_KVM_HOST = "autoenablekvmhost"; public static final String LIST_APIS = "listApis"; + public static final String OBJECT_STORAGE_ID = "objectstorageid"; /** * This enum specifies IO Drivers, each option controls specific policies on I/O. diff --git a/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java index 31f06dfc2625..972650c3134d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java @@ -22,6 +22,7 @@ import java.util.Map; import java.util.Set; +import com.cloud.storage.ObjectStore; import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.ApiConstants.HostDetails; @@ -80,6 +81,7 @@ 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.OvsProviderResponse; import org.apache.cloudstack.api.response.PhysicalNetworkResponse; import org.apache.cloudstack.api.response.PodResponse; @@ -526,4 +528,6 @@ List createTemplateResponses(ResponseView view, VirtualMachine DirectDownloadCertificateHostStatusResponse createDirectDownloadCertificateProvisionResponse(Long certificateId, Long hostId, Pair result); FirewallResponse createIpv6FirewallRuleResponse(FirewallRule acl); + + ObjectStoreResponse createObjectStoreResponse(ObjectStore os); } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddObjectStoragePoolCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddObjectStoragePoolCmd.java new file mode 100644 index 000000000000..58f4edc3c0ee --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddObjectStoragePoolCmd.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.api.command.admin.storage; + +import com.cloud.exception.DiscoveryException; +import com.cloud.storage.ObjectStore; +import com.cloud.user.Account; +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.ObjectStoreResponse; +import org.apache.log4j.Logger; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +@APICommand(name = "addObjectStoragePool", description = "Adds a object storage pool", responseObject = ObjectStoreResponse.class, since = "4.19.0", + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +public class AddObjectStoragePoolCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(AddObjectStoragePoolCmd.class.getName()); + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "the name for the object store") + private String name; + + @Parameter(name = ApiConstants.URL, type = CommandType.STRING, length = 2048, required = true, description = "the URL for the object store") + private String url; + + @Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING, required = true, description = "the object store provider name") + private String providerName; + + @Parameter(name = ApiConstants.DETAILS, + type = CommandType.MAP, + description = "the details for the object 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 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 providerName; + } + + public void setUrl(String url) { + this.url = url; + } + + public void setProviderName(String providerName) { + this.providerName = providerName; + } + + public void setDetails(Map details) { + this.details = details; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute(){ + try{ + ObjectStore result = _storageService.discoverObjectStore(getName(), getUrl(), getProviderName(), getDetails()); + ObjectStoreResponse storeResponse = null; + if (result != null) { + storeResponse = _responseGenerator.createObjectStoreResponse(result); + storeResponse.setResponseName(getCommandName()); + storeResponse.setObjectName("objectstore"); + setResponseObject(storeResponse); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add object storage"); + } + } catch (DiscoveryException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); + } + } +} \ No newline at end of file diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListObjectStoragePoolsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListObjectStoragePoolsCmd.java new file mode 100644 index 000000000000..d91549c99cc1 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListObjectStoragePoolsCmd.java @@ -0,0 +1,84 @@ +// 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.ListResponse; +import org.apache.cloudstack.api.response.ObjectStoreResponse; +import org.apache.log4j.Logger; + +@APICommand(name = "listObjectStoragePools", description = "Lists object storage pools.", responseObject = ObjectStoreResponse.class, since = "4.19.0", + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +public class ListObjectStoragePoolsCmd extends BaseListCmd { + public static final Logger s_logger = Logger.getLogger(ListObjectStoragePoolsCmd.class.getName()); + + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "the name of the object store") + private String storeName; + + @Parameter(name = ApiConstants.PROTOCOL, type = CommandType.STRING, description = "the object store protocol") + private String protocol; + + @Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING, description = "the object store provider") + private String provider; + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ObjectStoreResponse.class, description = "the ID of the storage pool") + private Long id; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + + 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 void execute() { + ListResponse response = _queryService.searchForObjectStores(this); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/BucketResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/BucketResponse.java new file mode 100644 index 000000000000..ff0765050be0 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/BucketResponse.java @@ -0,0 +1,150 @@ +// 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 com.cloud.serializer.Param; +import com.cloud.storage.Bucket; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponseWithTagInformation; +import org.apache.cloudstack.api.EntityReference; + +import java.util.Date; +import java.util.LinkedHashSet; +import java.util.Set; + +@EntityReference(value = Bucket.class) +@SuppressWarnings("unused") +public class BucketResponse extends BaseResponseWithTagInformation implements ControlledViewEntityResponse { + @SerializedName(ApiConstants.ID) + @Param(description = "ID of the Bucket") + private String id; + @SerializedName(ApiConstants.NAME) + @Param(description = "name of the Bucket") + private String name; + @SerializedName(ApiConstants.CREATED) + @Param(description = "the date the Bucket was created") + private Date created; + @SerializedName(ApiConstants.ACCOUNT) + @Param(description = "the account associated with the Bucket") + private String accountName; + @SerializedName(ApiConstants.PROJECT_ID) + @Param(description = "the project id of the bucket") + private String projectId; + @SerializedName(ApiConstants.PROJECT) + @Param(description = "the project name of the bucket") + private String projectName; + @SerializedName(ApiConstants.DOMAIN_ID) + @Param(description = "the ID of the domain associated with the bucket") + private String domainId; + @SerializedName(ApiConstants.DOMAIN) + @Param(description = "the domain associated with the bucket") + private String domainName; + @SerializedName(ApiConstants.OBJECT_STORAGE_ID) + @Param(description = "id of the object storage hosting the Bucket; returned to admin user only") + private String objectStoragePoolId; + + public BucketResponse() { + tags = new LinkedHashSet(); + } + + @Override + public String getObjectId() { + return this.getId(); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + + public void setCreated(Date created) { + this.created = created; + } + + @Override + public void setAccountName(String accountName) { + this.accountName = accountName; + } + + @Override + public void setDomainId(String domainId) { + this.domainId = domainId; + } + + @Override + public void setDomainName(String domainName) { + this.domainName = domainName; + } + + @Override + public void setProjectId(String projectId) { + this.projectId = projectId; + } + + @Override + public void setProjectName(String projectName) { + this.projectName = projectName; + } + + public void setTags(Set tags) { + this.tags = tags; + } + + public void setObjectStoragePoolId(String objectStoragePoolId) { + this.objectStoragePoolId = objectStoragePoolId; + } + + public String getName() { + return name; + } + + public Date getCreated() { + return created; + } + + public String getAccountName() { + return accountName; + } + + public String getProjectId() { + return projectId; + } + + public String getProjectName() { + return projectName; + } + + public String getDomainId() { + return domainId; + } + + public String getDomainName() { + return domainName; + } + + public String getObjectStoragePoolId() { + return objectStoragePoolId; + } +} \ No newline at end of file diff --git a/api/src/main/java/org/apache/cloudstack/api/response/ObjectStoreResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/ObjectStoreResponse.java new file mode 100644 index 000000000000..bb5848bc6bb4 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/ObjectStoreResponse.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.api.response; + +import com.cloud.serializer.Param; +import com.cloud.storage.ObjectStore; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.BaseResponseWithAnnotations; +import org.apache.cloudstack.api.EntityReference; + +@EntityReference(value = ObjectStore.class) +public class ObjectStoreResponse extends BaseResponseWithAnnotations { + @SerializedName("id") + @Param(description = "the ID of the object store") + private String id; + + @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("protocol") + @Param(description = "the protocol of the object store") + private String protocol; + + @SerializedName("providername") + @Param(description = "the provider name of the object store") + private String providerName; + + @SerializedName("storagetotal") + @Param(description = "the total size of the object store") + private Long storageTotal; + + @SerializedName("storageused") + @Param(description = "the object store currently used size") + private Long storageUsed; + + public ObjectStoreResponse() { + } + + @Override + public String getObjectId() { + return this.getId(); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + 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 String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public Long getStorageTotal() { + return storageTotal; + } + + public void setStorageTotal(Long storageTotal) { + this.storageTotal = storageTotal; + } + + public Long getStorageUsed() { + return storageUsed; + } + + public void setStorageUsed(Long storageUsed) { + this.storageUsed = storageUsed; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/query/QueryService.java b/api/src/main/java/org/apache/cloudstack/query/QueryService.java index 0587294a826f..af417084db83 100644 --- a/api/src/main/java/org/apache/cloudstack/query/QueryService.java +++ b/api/src/main/java/org/apache/cloudstack/query/QueryService.java @@ -28,6 +28,7 @@ import org.apache.cloudstack.api.command.admin.router.GetRouterHealthCheckResultsCmd; 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.ListObjectStoragePoolsCmd; import org.apache.cloudstack.api.command.admin.storage.ListSecondaryStagingStoresCmd; import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd; import org.apache.cloudstack.api.command.admin.storage.ListStorageTagsCmd; @@ -64,6 +65,7 @@ import org.apache.cloudstack.api.response.InstanceGroupResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ManagementServerResponse; +import org.apache.cloudstack.api.response.ObjectStoreResponse; import org.apache.cloudstack.api.response.ProjectAccountResponse; import org.apache.cloudstack.api.response.ProjectInvitationResponse; import org.apache.cloudstack.api.response.ProjectResponse; @@ -179,4 +181,6 @@ public interface QueryService { ListResponse listManagementServers(ListMgmtsCmd cmd); List listRouterHealthChecks(GetRouterHealthCheckResultsCmd cmd); + + ListResponse searchForObjectStores(ListObjectStoragePoolsCmd listObjectStoragePoolsCmd); } diff --git a/client/pom.xml b/client/pom.xml index a548d676a671..23c09b8726ff 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -557,6 +557,21 @@ cloud-plugin-shutdown ${project.version} + + org.apache.cloudstack + cloud-engine-storage-object + ${project.version} + + + org.apache.cloudstack + cloud-plugin-storage-object-minio + ${project.version} + + + org.apache.cloudstack + cloud-plugin-storage-object-simulator + ${project.version} + diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/BucketInfo.java b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/BucketInfo.java new file mode 100644 index 000000000000..cd97ac834ef7 --- /dev/null +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/BucketInfo.java @@ -0,0 +1,30 @@ +/* + * 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 com.cloud.storage.Bucket; + +public interface BucketInfo extends DataObject, Bucket { + + void addPayload(Object data); + + Object getPayload(); + + Bucket getBucket(); +} \ No newline at end of file diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreProvider.java b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreProvider.java index 3e5761ef37ff..41c1d9407454 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreProvider.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreProvider.java @@ -31,7 +31,7 @@ public interface DataStoreProvider { String DEFAULT_PRIMARY = "DefaultPrimary"; enum DataStoreProviderType { - PRIMARY, IMAGE, ImageCache + PRIMARY, IMAGE, ImageCache, OBJECT } DataStoreLifeCycle getDataStoreLifeCycle(); diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/ObjectStorageService.java b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/ObjectStorageService.java new file mode 100644 index 000000000000..691da7ecc8d8 --- /dev/null +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/ObjectStorageService.java @@ -0,0 +1,22 @@ +// 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 ObjectStorageService { + +} diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/ObjectStoreProvider.java b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/ObjectStoreProvider.java new file mode 100644 index 000000000000..71b3762b4414 --- /dev/null +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/ObjectStoreProvider.java @@ -0,0 +1,23 @@ +/* + * 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 ObjectStoreProvider extends DataStoreProvider { + +} diff --git a/engine/api/src/main/java/org/apache/cloudstack/storage/object/ObjectStoreEntity.java b/engine/api/src/main/java/org/apache/cloudstack/storage/object/ObjectStoreEntity.java new file mode 100644 index 000000000000..7f0f95d92b48 --- /dev/null +++ b/engine/api/src/main/java/org/apache/cloudstack/storage/object/ObjectStoreEntity.java @@ -0,0 +1,27 @@ +/* + * 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.object; + +import com.cloud.storage.Bucket; +import com.cloud.storage.ObjectStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; + +public interface ObjectStoreEntity extends DataStore, ObjectStore { + Bucket createBucket(String bucketName); +} diff --git a/engine/pom.xml b/engine/pom.xml index 608affec3929..5fdf62d5982e 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -56,6 +56,7 @@ storage/configdrive storage/datamotion storage/image + storage/object storage/snapshot storage/volume diff --git a/engine/schema/src/main/java/com/cloud/storage/BucketVO.java b/engine/schema/src/main/java/com/cloud/storage/BucketVO.java new file mode 100644 index 000000000000..686ca7e70ad7 --- /dev/null +++ b/engine/schema/src/main/java/com/cloud/storage/BucketVO.java @@ -0,0 +1,159 @@ +// 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.utils.db.GenericDao; +import com.google.gson.annotations.Expose; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +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 java.util.Date; +import java.util.UUID; + +@Entity +@Table(name = "bucket") +public class BucketVO implements Bucket { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + + @Column(name = "account_id") + long accountId; + + @Column(name = "domain_id") + long domainId; + + @Column(name = "object_store_id") + long objectStoreId; + + @Expose + @Column(name = "name") + String name; + + @Expose + @Column(name = "state", updatable = true, nullable = false) + @Enumerated(value = EnumType.STRING) + private State state; + + @Column(name = "size") + long size; + + @Column(name = GenericDao.CREATED_COLUMN) + Date created; + + @Column(name = GenericDao.REMOVED_COLUMN) + Date removed; + + @Column(name = "uuid") + String uuid; + + public BucketVO() { + uuid = UUID.randomUUID().toString(); + } + + public BucketVO(long accountId, long domainId, long objectStoreId, String name) + { + this.accountId = accountId; + this.domainId = domainId; + this.objectStoreId = objectStoreId; + this.name = name; + state = State.Allocated; + uuid = UUID.randomUUID().toString(); + } + + @Override + public long getId() { + return id; + } + + @Override + public long getAccountId() { + return accountId; + } + + @Override + public long getDomainId() { + return domainId; + } + + @Override + public long getObjectStoreId() { + return objectStoreId; + } + + @Override + public String getName() { + return name; + } + + public long getSize() { + return size; + } + + @Override + public Date getCreated() { + return created; + } + + public Date getRemoved() { + return removed; + } + + @Override + public State getState() { + return state; + } + + @Override + public void setName(String name) { + this.name = name; + } + + public void setState(State state) { + this.state = state; + } + + @Override + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + @Override + public Class getEntityType() { + return Bucket.class; + } + + @Override + public String toString() { + return String.format("Bucket %s", new ToStringBuilder(this, ToStringStyle.JSON_STYLE).append("uuid", getUuid()).append("name", getName()) + .append("ObjectStoreId", getObjectStoreId()).toString()); + } +} \ No newline at end of file diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/BucketDao.java b/engine/schema/src/main/java/com/cloud/storage/dao/BucketDao.java new file mode 100644 index 000000000000..7608174a022b --- /dev/null +++ b/engine/schema/src/main/java/com/cloud/storage/dao/BucketDao.java @@ -0,0 +1,29 @@ +// 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 com.cloud.storage.BucketVO; +import com.cloud.utils.db.GenericDao; +import org.apache.cloudstack.api.response.BucketResponse; + +import java.util.List; + +public interface BucketDao extends GenericDao { + List listByObjectStoreId(long objectStoreId); + + BucketResponse newBucketResponse(BucketVO bucket); +} \ No newline at end of file diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/BucketDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/BucketDaoImpl.java new file mode 100644 index 000000000000..ab5e6e1a815c --- /dev/null +++ b/engine/schema/src/main/java/com/cloud/storage/dao/BucketDaoImpl.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 com.cloud.storage.BucketVO; +import com.cloud.utils.db.GenericDaoBase; +import org.apache.cloudstack.api.response.BucketResponse; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class BucketDaoImpl extends GenericDaoBase implements BucketDao { + public static final Logger s_logger = Logger.getLogger(BucketDaoImpl.class.getName()); + + public BucketDaoImpl() { + + } + @Override + public List listByObjectStoreId(long objectStoreId) { + return null; + } + + @Override + public BucketResponse newBucketResponse(BucketVO bucket) { + BucketResponse bucketResponse = new BucketResponse(); + bucketResponse.setName(bucket.getName()); + bucketResponse.setId(bucket.getUuid()); + //ToDo change to UUID + bucketResponse.setObjectStoragePoolId(""+bucket.getObjectStoreId()); + bucketResponse.setObjectName("bucket"); + return bucketResponse; + } +} \ No newline at end of file diff --git a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ObjectStoreDao.java b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ObjectStoreDao.java new file mode 100644 index 000000000000..1c86cfc22a62 --- /dev/null +++ b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ObjectStoreDao.java @@ -0,0 +1,38 @@ +/* + * 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 com.cloud.utils.db.GenericDao; +import org.apache.cloudstack.api.response.ObjectStoreResponse; + +import java.util.List; + +public interface ObjectStoreDao extends GenericDao { + ObjectStoreVO findByName(String name); + + List findByProvider(String provider); + + List listObjectStores(); + + List searchByIds(Long[] osIds); + + ObjectStoreResponse newObjectStoreResponse(ObjectStoreVO store); + + ObjectStoreResponse setObjectStoreResponse(ObjectStoreResponse storeData, ObjectStoreVO store); +} diff --git a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ObjectStoreDaoImpl.java b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ObjectStoreDaoImpl.java new file mode 100644 index 000000000000..e7badcf89876 --- /dev/null +++ b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ObjectStoreDaoImpl.java @@ -0,0 +1,144 @@ +/* + * 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 com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import org.apache.cloudstack.api.response.ObjectStoreResponse; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@Component +public class ObjectStoreDaoImpl extends GenericDaoBase implements ObjectStoreDao { + private SearchBuilder nameSearch; + private SearchBuilder providerSearch; + @Inject + private ConfigurationDao _configDao; + private final SearchBuilder osSearch; + + protected ObjectStoreDaoImpl() { + osSearch = createSearchBuilder(); + osSearch.and("idIN", osSearch.entity().getId(), SearchCriteria.Op.IN); + osSearch.done(); + } + + @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.done(); + + providerSearch = createSearchBuilder(); + providerSearch.and("providerName", providerSearch.entity().getProviderName(), SearchCriteria.Op.EQ); + providerSearch.done(); + + return true; + } + + @Override + public ObjectStoreVO 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); + return listBy(sc); + } + + @Override + public List listObjectStores() { + SearchCriteria sc = createSearchCriteria(); + return listBy(sc); + } + + @Override + public List searchByIds(Long[] osIds) { + // 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 osList = new ArrayList<>(); + // query details by batches + int curr_index = 0; + if (osIds.length > DETAILS_BATCH_SIZE) { + while ((curr_index + DETAILS_BATCH_SIZE) <= osIds.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] = osIds[j]; + } + SearchCriteria sc = osSearch.create(); + sc.setParameters("idIN", ids); + List stores = searchIncludingRemoved(sc, null, null, false); + if (stores != null) { + osList.addAll(stores); + } + curr_index += DETAILS_BATCH_SIZE; + } + } + if (curr_index < osIds.length) { + int batch_size = (osIds.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] = osIds[j]; + } + SearchCriteria sc = osSearch.create(); + sc.setParameters("idIN", ids); + List stores = searchIncludingRemoved(sc, null, null, false); + if (stores != null) { + osList.addAll(stores); + } + } + return osList; + } + + @Override + public ObjectStoreResponse newObjectStoreResponse(ObjectStoreVO store) { + ObjectStoreResponse osResponse = new ObjectStoreResponse(); + osResponse.setId(store.getUuid()); + osResponse.setName(store.getName()); + osResponse.setProviderName(store.getProviderName()); + osResponse.setProtocol(store.getProtocol()); + String url = store.getUrl(); + osResponse.setUrl(url); + osResponse.setObjectName("objectstore"); + return osResponse; + } + + @Override + public ObjectStoreResponse setObjectStoreResponse(ObjectStoreResponse storeData, ObjectStoreVO store) { + return storeData; + } +} \ No newline at end of file diff --git a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ObjectStoreDetailVO.java b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ObjectStoreDetailVO.java new file mode 100644 index 000000000000..f00366aafeb1 --- /dev/null +++ b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ObjectStoreDetailVO.java @@ -0,0 +1,83 @@ +// 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.ResourceDetail; + +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 = "object_store_details") +public class ObjectStoreDetailVO implements ResourceDetail { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + long id; + + @Column(name = "store_id") + long resourceId; + + @Column(name = "name") + String name; + + @Column(name = "value") + String value; + + @Column(name = "display") + private boolean display = true; + + public ObjectStoreDetailVO() { + } + + public ObjectStoreDetailVO(long storeId, String name, String value, boolean display) { + this.resourceId = storeId; + this.name = name; + this.value = value; + this.display = display; + } + + @Override + public long getId() { + return id; + } + + @Override + public long getResourceId() { + return resourceId; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getValue() { + return value; + } + + @Override + public boolean isDisplay() { + return display; + } + +} diff --git a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ObjectStoreDetailsDao.java b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ObjectStoreDetailsDao.java new file mode 100644 index 000000000000..170a28af5023 --- /dev/null +++ b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ObjectStoreDetailsDao.java @@ -0,0 +1,31 @@ +// 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 com.cloud.utils.db.GenericDao; +import org.apache.cloudstack.resourcedetail.ResourceDetailsDao; + +import java.util.Map; + +public interface ObjectStoreDetailsDao extends GenericDao, ResourceDetailsDao { + + void update(long storeId, Map details); + + Map getDetails(long storeId); + + void deleteDetails(long storeId); +} diff --git a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ObjectStoreDetailsDaoImpl.java b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ObjectStoreDetailsDaoImpl.java new file mode 100644 index 000000000000..e532fb7a594a --- /dev/null +++ b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ObjectStoreDetailsDaoImpl.java @@ -0,0 +1,103 @@ +// 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 com.cloud.utils.crypt.DBEncryptionUtil; +import com.cloud.utils.db.QueryBuilder; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.TransactionLegacy; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class ObjectStoreDetailsDaoImpl extends ResourceDetailsDaoBase implements ObjectStoreDetailsDao { + + protected final SearchBuilder storeSearch; + + public ObjectStoreDetailsDaoImpl() { + super(); + storeSearch = createSearchBuilder(); + storeSearch.and("store", storeSearch.entity().getResourceId(), Op.EQ); + storeSearch.done(); + } + + @Override + public void update(long storeId, Map details) { + TransactionLegacy txn = TransactionLegacy.currentTxn(); + SearchCriteria sc = storeSearch.create(); + sc.setParameters("store", storeId); + + txn.start(); + expunge(sc); + for (Map.Entry entry : details.entrySet()) { + ObjectStoreDetailVO detail = new ObjectStoreDetailVO(storeId, entry.getKey(), entry.getValue(), true); + 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 (ObjectStoreDetailVO detail : details) { + String name = detail.getName(); + String value = detail.getValue(); + if (name.equals(ApiConstants.KEY)) { + value = DBEncryptionUtil.decrypt(value); + } + detailsMap.put(name, value); + } + + return detailsMap; + } + + @Override + public void deleteDetails(long storeId) { + SearchCriteria sc = storeSearch.create(); + sc.setParameters("store", storeId); + + List results = search(sc, null); + for (ObjectStoreDetailVO result : results) { + remove(result.getId()); + } + } + + @Override + public ObjectStoreDetailVO findDetail(long storeId, String name) { + QueryBuilder sc = QueryBuilder.create(ObjectStoreDetailVO.class); + sc.and(sc.entity().getResourceId(), Op.EQ, storeId); + sc.and(sc.entity().getName(), Op.EQ, name); + return sc.find(); + } + + @Override + public void addDetail(long resourceId, String key, String value, boolean display) { + super.addDetail(new ObjectStoreDetailVO(resourceId, key, value, display)); + } + +} diff --git a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ObjectStoreVO.java b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ObjectStoreVO.java new file mode 100644 index 000000000000..2535c8856411 --- /dev/null +++ b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ObjectStoreVO.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.db; + +import com.cloud.storage.ObjectStore; +import com.cloud.utils.db.GenericDao; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.TableGenerator; +import javax.persistence.Transient; +import java.util.Date; +import java.util.Map; + +@Entity +@Table(name = "object_store") +public class ObjectStoreVO implements ObjectStore { + @Id + @TableGenerator(name = "object_store_sq", table = "sequence", pkColumnName = "name", valueColumnName = "value", pkColumnValue = "object_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, length = 2048) + private String url; + + @Column(name = "object_provider_name", nullable = false) + private String providerName; + + @Column(name = GenericDao.CREATED_COLUMN) + private Date created; + + @Column(name = GenericDao.REMOVED_COLUMN) + private Date removed; + + @Column(name = "total_size") + private Long totalSize; + + @Column(name = "used_bytes") + private Long usedBytes; + + @Transient + Map details; + + @Override + public long getId() { + return this.id; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public String getProviderName() { + return this.providerName; + } + + public void setName(String name) { + this.name = name; + } + + public void setProviderName(String provider) { + this.providerName = provider; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + @Override + public String getProtocol() { + return this.protocol; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + @Override + 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 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; + } + + public void setDetails(Map details) { + this.details = details; + } +} diff --git a/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml b/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml index 51e557f0c52c..c126639b6e3d 100644 --- a/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml +++ b/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml @@ -275,4 +275,5 @@ + diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41810to41900.sql b/engine/schema/src/main/resources/META-INF/db/schema-41810to41900.sql index 541d3dbacac3..becb9f4c79e9 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41810to41900.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41810to41900.sql @@ -131,3 +131,43 @@ CREATE VIEW `cloud`.`async_job_view` AS left join `cloud`.`autoscale_vmgroups` ON async_job.instance_id = autoscale_vmgroups.id; +DROP TABLE IF EXISTS `cloud`.`object_store`; +CREATE TABLE `cloud`.`object_store` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `name` varchar(255) NOT NULL COMMENT 'name of object store', + `object_provider_name` varchar(255) NOT NULL COMMENT 'id of object_store_provider', + `protocol` varchar(255) NOT NULL COMMENT 'protocol of object store', + `url` varchar(255) NOT NULL COMMENT 'url of the object store', + `uuid` varchar(255) COMMENT 'uuid of object store', + `created` datetime COMMENT 'date the object 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; + +DROP TABLE IF EXISTS `cloud`.`object_store_details`; +CREATE TABLE `cloud`.`object_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_object_store_details__store_id` FOREIGN KEY `fk_object_store__store_id`(`store_id`) REFERENCES `object_store`(`id`) ON DELETE CASCADE, + INDEX `i_object_store__name__value`(`name`(128), `value`(128)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `cloud`.`bucket`; +CREATE TABLE `cloud`.`bucket` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `name` varchar(255) NOT NULL COMMENT 'name of bucket', + `object_store_id` varchar(255) NOT NULL COMMENT 'id of object_store', + `state` varchar(255) NOT NULL COMMENT 'state of the bucket', + `uuid` varchar(255) COMMENT 'uuid of bucket', + `domain_id` bigint unsigned NOT NULL COMMENT 'domain the bucket belongs to', + `account_id` bigint unsigned NOT NULL COMMENT 'owner of this bucket', + `size` bigint unsigned COMMENT 'total size of bucket objects', + `created` datetime COMMENT 'date the bucket was created', + `removed` datetime COMMENT 'date removed if not null', + PRIMARY KEY(`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/TemplateServiceImpl.java b/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/TemplateServiceImpl.java index 6baccb3526aa..2575b3692da6 100644 --- a/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/TemplateServiceImpl.java +++ b/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/TemplateServiceImpl.java @@ -18,58 +18,6 @@ */ package org.apache.cloudstack.storage.image; -import java.io.File; -import java.util.ArrayList; -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.concurrent.ExecutionException; - -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.ObjectInDataStoreStateMachine.State; -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.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.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.AsyncRpcContext; -import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.cloudstack.framework.messagebus.MessageBus; -import org.apache.cloudstack.framework.messagebus.PublishScope; -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.datastore.ImageStoreEntity; -import org.apache.cloudstack.storage.image.store.TemplateObject; -import org.apache.cloudstack.storage.to.TemplateObjectTO; -import org.apache.commons.lang3.StringUtils; -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; @@ -111,14 +59,59 @@ import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.fsm.StateMachine2; import com.cloud.vm.VmDetailConstants; +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.ObjectInDataStoreStateMachine.State; +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.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.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.AsyncRpcContext; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.framework.messagebus.MessageBus; +import org.apache.cloudstack.framework.messagebus.PublishScope; +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.image.datastore.ImageStoreEntity; +import org.apache.cloudstack.storage.image.store.TemplateObject; +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.io.File; +import java.util.ArrayList; +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.concurrent.ExecutionException; @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 diff --git a/engine/storage/integration-test/src/test/resources/storageContext.xml b/engine/storage/integration-test/src/test/resources/storageContext.xml index fc24753127ef..7c95345f6734 100644 --- a/engine/storage/integration-test/src/test/resources/storageContext.xml +++ b/engine/storage/integration-test/src/test/resources/storageContext.xml @@ -87,4 +87,8 @@ + + + + diff --git a/engine/storage/object/pom.xml b/engine/storage/object/pom.xml new file mode 100644 index 000000000000..5bad4e8a3d68 --- /dev/null +++ b/engine/storage/object/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + cloud-engine-storage-object + Apache CloudStack Engine Storage Object Component + + org.apache.cloudstack + cloud-engine + 4.19.0.0-SNAPSHOT + ../../pom.xml + + + + org.apache.cloudstack + cloud-engine-storage + ${project.version} + + + diff --git a/engine/storage/object/src/main/java/org/apache/cloudstack/storage/object/BucketObject.java b/engine/storage/object/src/main/java/org/apache/cloudstack/storage/object/BucketObject.java new file mode 100644 index 000000000000..9e4b8784b5bb --- /dev/null +++ b/engine/storage/object/src/main/java/org/apache/cloudstack/storage/object/BucketObject.java @@ -0,0 +1,157 @@ +// 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.object; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataTO; +import com.cloud.storage.Bucket; +import org.apache.cloudstack.engine.subsystem.api.storage.BucketInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; + +import java.util.Date; + +public class BucketObject implements BucketInfo { + + private String name; + + @Override + public long getDomainId() { + return 0; + } + + @Override + public long getAccountId() { + return 0; + } + + @Override + public Class getEntityType() { + return null; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public void setName(String name) { + this.name = name; + } + + @Override + public void addPayload(Object data) { + + } + + @Override + public Object getPayload() { + return null; + } + + @Override + public Bucket getBucket() { + return null; + } + + @Override + public long getId() { + return 0; + } + + @Override + public String getUri() { + return null; + } + + @Override + public DataTO getTO() { + return null; + } + + @Override + public DataStore getDataStore() { + return null; + } + + @Override + public Long getSize() { + return null; + } + + @Override + public long getPhysicalSize() { + return 0; + } + + @Override + public DataObjectType getType() { + return null; + } + + @Override + public String getUuid() { + return null; + } + + @Override + public boolean delete() { + return false; + } + + @Override + public void processEvent(ObjectInDataStoreStateMachine.Event event) { + + } + + @Override + public void processEvent(ObjectInDataStoreStateMachine.Event event, Answer answer) { + + } + + @Override + public void incRefCount() { + + } + + @Override + public void decRefCount() { + + } + + @Override + public Long getRefCount() { + return null; + } + + @Override + public long getObjectStoreId() { + return 0; + } + + @Override + public Date getCreated() { + return null; + } + + @Override + public State getState() { + return null; + } +} \ No newline at end of file diff --git a/engine/storage/object/src/main/java/org/apache/cloudstack/storage/object/ObjectStorageServiceImpl.java b/engine/storage/object/src/main/java/org/apache/cloudstack/storage/object/ObjectStorageServiceImpl.java new file mode 100644 index 000000000000..a0db89bad4e1 --- /dev/null +++ b/engine/storage/object/src/main/java/org/apache/cloudstack/storage/object/ObjectStorageServiceImpl.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.object; + +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectStorageService; +import org.apache.log4j.Logger; + +public class ObjectStorageServiceImpl implements ObjectStorageService { + + private static final Logger s_logger = Logger.getLogger(ObjectStorageServiceImpl.class); + + +} diff --git a/engine/storage/object/src/main/java/org/apache/cloudstack/storage/object/manager/ObjectStoreProviderManagerImpl.java b/engine/storage/object/src/main/java/org/apache/cloudstack/storage/object/manager/ObjectStoreProviderManagerImpl.java new file mode 100644 index 000000000000..40f503692e18 --- /dev/null +++ b/engine/storage/object/src/main/java/org/apache/cloudstack/storage/object/manager/ObjectStoreProviderManagerImpl.java @@ -0,0 +1,111 @@ +/* + * 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.object.manager; + +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.ObjectStoreProvider; +import org.apache.cloudstack.framework.config.ConfigKey; +import org.apache.cloudstack.framework.config.Configurable; +import org.apache.cloudstack.storage.datastore.db.ObjectStoreDao; +import org.apache.cloudstack.storage.datastore.db.ObjectStoreVO; +import org.apache.cloudstack.storage.object.ObjectStoreDriver; +import org.apache.cloudstack.storage.object.ObjectStoreEntity; +import org.apache.cloudstack.storage.object.datastore.ObjectStoreProviderManager; +import org.apache.cloudstack.storage.object.store.ObjectStoreImpl; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class ObjectStoreProviderManagerImpl implements ObjectStoreProviderManager, Configurable { + private static final Logger s_logger = Logger.getLogger(ObjectStoreProviderManagerImpl.class); + @Inject + ObjectStoreDao objectStoreDao; + + @Inject + DataStoreProviderManager providerManager; + + Map driverMaps; + + @PostConstruct + public void config() { + driverMaps = new HashMap(); + } + + @Override + public ObjectStoreEntity getObjectStore(long objectStoreId) { + ObjectStoreVO objectStore = objectStoreDao.findById(objectStoreId); + String providerName = objectStore.getProviderName(); + ObjectStoreProvider provider = (ObjectStoreProvider)providerManager.getDataStoreProvider(providerName); + ObjectStoreEntity objStore = ObjectStoreImpl.getDataStore(objectStore, driverMaps.get(provider.getName()), provider); + return objStore; + } + + @Override + public boolean registerDriver(String providerName, ObjectStoreDriver driver) { + if (driverMaps.containsKey(providerName)) { + return false; + } + driverMaps.put(providerName, driver); + return true; + } + + @Override + public ObjectStoreEntity getObjectStore(String uuid) { + ObjectStoreVO objectStore = objectStoreDao.findByUuid(uuid); + return getObjectStore(objectStore.getId()); + } + + @Override + public List listObjectStores() { + List stores = objectStoreDao.listObjectStores(); + List ObjectStores = new ArrayList(); + for (ObjectStoreVO store : stores) { + ObjectStores.add(getObjectStore(store.getId())); + } + return ObjectStores; + } + + @Override + public List listObjectStoreByProvider(String provider) { + List stores = objectStoreDao.findByProvider(provider); + List ObjectStores = new ArrayList(); + for (ObjectStoreVO store : stores) { + ObjectStores.add(getObjectStore(store.getId())); + } + return ObjectStores; + } + + @Override + public String getConfigComponentName() { + return ObjectStoreProviderManager.class.getSimpleName(); + } + + @Override + public ConfigKey[] getConfigKeys() { + return new ConfigKey[] { }; + } +} diff --git a/engine/storage/object/src/main/java/org/apache/cloudstack/storage/object/store/ObjectStoreImpl.java b/engine/storage/object/src/main/java/org/apache/cloudstack/storage/object/store/ObjectStoreImpl.java new file mode 100644 index 000000000000..5c0436dff508 --- /dev/null +++ b/engine/storage/object/src/main/java/org/apache/cloudstack/storage/object/store/ObjectStoreImpl.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.object.store; + +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.storage.Bucket; +import com.cloud.storage.DataStoreRole; +import com.cloud.utils.component.ComponentContext; +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.ObjectStoreProvider; +import org.apache.cloudstack.engine.subsystem.api.storage.Scope; +import org.apache.cloudstack.storage.datastore.db.ObjectStoreVO; +import org.apache.cloudstack.storage.object.ObjectStoreDriver; +import org.apache.cloudstack.storage.object.ObjectStoreEntity; +import org.apache.log4j.Logger; + +import java.util.Date; + +public class ObjectStoreImpl implements ObjectStoreEntity { + private static final Logger s_logger = Logger.getLogger(ObjectStoreImpl.class); + + protected ObjectStoreDriver driver; + protected ObjectStoreVO objectStoreVO; + protected ObjectStoreProvider provider; + + public ObjectStoreImpl() { + super(); + } + + protected void configure(ObjectStoreVO objectStoreVO, ObjectStoreDriver objectStoreDriver, ObjectStoreProvider provider) { + this.driver = objectStoreDriver; + this.objectStoreVO = objectStoreVO; + this.provider = provider; + } + + public static ObjectStoreEntity getDataStore(ObjectStoreVO objectStoreVO, ObjectStoreDriver objectStoreDriver, ObjectStoreProvider provider) { + ObjectStoreImpl instance = ComponentContext.inject(ObjectStoreImpl.class); + instance.configure(objectStoreVO, objectStoreDriver, provider); + return instance; + } + + @Override + public DataStoreDriver getDriver() { + return this.driver; + } + + @Override + public DataStoreRole getRole() { + return null; + } + + @Override + public long getId() { + return this.objectStoreVO.getId(); + } + + @Override + public String getUri() { + return this.objectStoreVO.getUrl(); + } + + @Override + public Scope getScope() { + return null; + } + + + @Override + public String getUuid() { + return this.objectStoreVO.getUuid(); + } + + public Date getCreated() { + return this.objectStoreVO.getCreated(); + } + + @Override + public String getName() { + return objectStoreVO.getName(); + } + + @Override + public DataObject create(DataObject obj) { + driver.createBucket("name", objectStoreVO.getId()); + return null; + } + + @Override + public Bucket createBucket(String bucketName) { + return driver.createBucket(bucketName, objectStoreVO.getId()); + } + + @Override + public boolean delete(DataObject obj) { + return false; + } + + @Override + public DataStoreTO getTO() { + return null; + } + + @Override + public String getProviderName() { + return objectStoreVO.getProviderName(); + } + + @Override + public String getProtocol() { + return objectStoreVO.getProtocol(); + } + + @Override + public String getUrl() { + return objectStoreVO.getUrl(); + } + +} diff --git a/engine/storage/object/src/main/java/org/apache/cloudstack/storage/object/store/lifecycle/ObjectStoreLifeCycle.java b/engine/storage/object/src/main/java/org/apache/cloudstack/storage/object/store/lifecycle/ObjectStoreLifeCycle.java new file mode 100644 index 000000000000..ff88262c4ba6 --- /dev/null +++ b/engine/storage/object/src/main/java/org/apache/cloudstack/storage/object/store/lifecycle/ObjectStoreLifeCycle.java @@ -0,0 +1,24 @@ +/* + * 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.object.store.lifecycle; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle; + +public interface ObjectStoreLifeCycle extends DataStoreLifeCycle { +} diff --git a/engine/storage/object/src/main/resources/META-INF/cloudstack/core/spring-engine-storage-object-core-context.xml b/engine/storage/object/src/main/resources/META-INF/cloudstack/core/spring-engine-storage-object-core-context.xml new file mode 100644 index 000000000000..57bd9f877498 --- /dev/null +++ b/engine/storage/object/src/main/resources/META-INF/cloudstack/core/spring-engine-storage-object-core-context.xml @@ -0,0 +1,36 @@ + + + + + + + + diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java index da97b22946e1..9e464a3da4e5 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java @@ -16,11 +16,20 @@ // under the License. package org.apache.cloudstack.storage.datastore; -import javax.inject.Inject; - -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.exception.ConcurrentOperationException; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.SnapshotVO; +import com.cloud.storage.VMTemplateStoragePoolVO; +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.template.TemplateConstants; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.fsm.NoTransitionException; +import com.cloud.utils.fsm.StateMachine2; 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; @@ -39,22 +48,10 @@ 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.log4j.Logger; +import org.springframework.stereotype.Component; -import com.cloud.agent.api.to.DataObjectType; -import com.cloud.agent.api.to.S3TO; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.storage.DataStoreRole; -import com.cloud.storage.SnapshotVO; -import com.cloud.storage.VMTemplateStoragePoolVO; -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.template.TemplateConstants; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.fsm.NoTransitionException; -import com.cloud.utils.fsm.StateMachine2; +import javax.inject.Inject; @Component public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager { @@ -76,8 +73,6 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager { @Inject SnapshotDataFactory snapshotFactory; @Inject - ObjectInDataStoreDao objInStoreDao; - @Inject VMTemplateDao templateDao; @Inject SnapshotDao snapshotDao; diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/object/BaseObjectStoreDriverImpl.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/object/BaseObjectStoreDriverImpl.java new file mode 100644 index 000000000000..e6027a1959f8 --- /dev/null +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/object/BaseObjectStoreDriverImpl.java @@ -0,0 +1,81 @@ +/* + * 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.object; + +import com.cloud.agent.api.to.DataTO; +import com.cloud.host.Host; +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.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.framework.async.AsyncRpcContext; +import org.apache.cloudstack.storage.command.CommandResult; +import org.apache.log4j.Logger; + +import java.util.Map; + +public abstract class BaseObjectStoreDriverImpl implements ObjectStoreDriver { + private static final Logger LOGGER = Logger.getLogger(BaseObjectStoreDriverImpl.class); + + @Override + public Map getCapabilities() { + return null; + } + + @Override + public DataTO getTO(DataObject data) { + return null; + } + + protected class CreateContext extends AsyncRpcContext { + final DataObject data; + + public CreateContext(AsyncCompletionCallback callback, DataObject data) { + super(callback); + this.data = data; + } + } + + @Override + public void createAsync(DataStore dataStore, DataObject data, AsyncCompletionCallback callback) { + } + + @Override + public void deleteAsync(DataStore dataStore, DataObject data, AsyncCompletionCallback callback) { + } + + @Override + public void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback callback) { + } + + @Override + public void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback callback) { + copyAsync(srcData, destData, 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/main/java/org/apache/cloudstack/storage/object/ObjectStoreDriver.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/object/ObjectStoreDriver.java new file mode 100644 index 000000000000..f93faa6c0966 --- /dev/null +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/object/ObjectStoreDriver.java @@ -0,0 +1,44 @@ +/* + * 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.object; + +import com.amazonaws.services.s3.model.AccessControlList; +import com.amazonaws.services.s3.model.BucketPolicy; +import com.cloud.storage.Bucket; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver; + +import java.util.List; + +public interface ObjectStoreDriver extends DataStoreDriver { + Bucket createBucket(String bucketName, long storeId); + + List listBuckets(long storeId); + + void deleteBucket(String bucketName,long storeId); + + AccessControlList getBucketAcl(String bucketName, long storeId); + + void setBucketAcl(String bucketName, AccessControlList acl, long storeId); + + void setBucketPolicy(String bucketName, String policyText, long storeId); + + BucketPolicy getBucketPolicy(String bucketName, long storeId); + + void deleteBucketPolicy(String bucketName, long storeId); +} diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/object/datastore/ObjectStoreHelper.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/object/datastore/ObjectStoreHelper.java new file mode 100644 index 000000000000..c9858b4af0a1 --- /dev/null +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/object/datastore/ObjectStoreHelper.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.object.datastore; + +import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.cloudstack.storage.datastore.db.ObjectStoreDao; +import org.apache.cloudstack.storage.datastore.db.ObjectStoreDetailVO; +import org.apache.cloudstack.storage.datastore.db.ObjectStoreDetailsDao; +import org.apache.cloudstack.storage.datastore.db.ObjectStoreVO; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.util.Iterator; +import java.util.Map; +import java.util.UUID; + +@Component +public class ObjectStoreHelper { + @Inject + ObjectStoreDao ObjectStoreDao; + @Inject + ObjectStoreDetailsDao ObjectStoreDetailsDao; + + public ObjectStoreVO createObjectStore(Map params) { + ObjectStoreVO store = ObjectStoreDao.findByName((String)params.get("name")); + if (store != null) { + return store; + } + store = new ObjectStoreVO(); + store.setProtocol((String)params.get("protocol")); + store.setProviderName((String)params.get("providerName")); + 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 = ObjectStoreDao.persist(store); + return store; + } + + public ObjectStoreVO createObjectStore(Map params, Map details) { + ObjectStoreVO store = ObjectStoreDao.findByName((String)params.get("name")); + if (store != null) { + return store; + } + store = new ObjectStoreVO(); + store.setProtocol((String)params.get("protocol")); + store.setProviderName((String)params.get("providerName")); + 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 = ObjectStoreDao.persist(store); + + // persist details + if (details != null) { + Iterator keyIter = details.keySet().iterator(); + while (keyIter.hasNext()) { + String key = keyIter.next().toString(); + String value = details.get(key); + ObjectStoreDetailVO detail = new ObjectStoreDetailVO(store.getId(), key, value, true); + ObjectStoreDetailsDao.persist(detail); + } + } + return store; + } + + public boolean deleteObjectStore(long id) { + ObjectStoreVO store = ObjectStoreDao.findById(id); + if (store == null) { + throw new CloudRuntimeException("can't find Object store:" + id); + } + + ObjectStoreDao.remove(id); + return true; + } +} \ No newline at end of file diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/object/datastore/ObjectStoreProviderManager.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/object/datastore/ObjectStoreProviderManager.java new file mode 100644 index 000000000000..b23f31941393 --- /dev/null +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/object/datastore/ObjectStoreProviderManager.java @@ -0,0 +1,38 @@ +/* + * 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.object.datastore; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.storage.object.ObjectStoreDriver; +import org.apache.cloudstack.storage.object.ObjectStoreEntity; + +import java.util.List; + +public interface ObjectStoreProviderManager { + ObjectStoreEntity getObjectStore(String uuid); + + List listObjectStores(); + + List listObjectStoreByProvider(String provider); + + ObjectStoreEntity getObjectStore(long objectStoreId); + + boolean registerDriver(String uuid, ObjectStoreDriver driver); + +} diff --git a/plugins/pom.xml b/plugins/pom.xml old mode 100755 new mode 100644 index d0661c01a2c4..bbda64a76d7f --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -130,6 +130,7 @@ storage/volume/scaleio storage/volume/linstor storage/volume/storpool + storage/object/minio storage-allocators/random @@ -183,6 +184,24 @@ test-jar test + + org.apache.cloudstack + cloud-engine-storage + 4.19.0.0-SNAPSHOT + compile + + + io.minio + minio + 8.5.2 + compile + + + io.minio + minio-admin + 8.5.2 + compile + diff --git a/plugins/storage/object/minio/pom.xml b/plugins/storage/object/minio/pom.xml new file mode 100644 index 000000000000..f739651eb573 --- /dev/null +++ b/plugins/storage/object/minio/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + cloud-plugin-storage-object-minio + Apache CloudStack Plugin - MinIO object storage provider + + org.apache.cloudstack + cloudstack-plugins + 4.19.0.0-SNAPSHOT + ../../../pom.xml + + + + org.apache.cloudstack + cloud-engine-storage + ${project.version} + + + org.apache.cloudstack + cloud-engine-storage-object + ${project.version} + + + io.minio + minio + 8.5.2 + + + io.minio + minio-admin + 8.5.2 + + + diff --git a/plugins/storage/object/minio/src/main/java/org/apache/cloudstack/storage/datastore/driver/MinIOObjectStoreDriverImpl.java b/plugins/storage/object/minio/src/main/java/org/apache/cloudstack/storage/datastore/driver/MinIOObjectStoreDriverImpl.java new file mode 100644 index 000000000000..619bff51142b --- /dev/null +++ b/plugins/storage/object/minio/src/main/java/org/apache/cloudstack/storage/datastore/driver/MinIOObjectStoreDriverImpl.java @@ -0,0 +1,220 @@ +/* + * 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.amazonaws.services.s3.model.AccessControlList; +import com.amazonaws.services.s3.model.BucketPolicy; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.storage.Bucket; +import com.cloud.utils.exception.CloudRuntimeException; +import io.minio.BucketExistsArgs; +import io.minio.MakeBucketArgs; +import io.minio.MinioClient; +import io.minio.RemoveBucketArgs; +import io.minio.admin.MinioAdminClient; +import io.minio.admin.UserInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.storage.datastore.db.ObjectStoreDao; +import org.apache.cloudstack.storage.datastore.db.ObjectStoreDetailsDao; +import org.apache.cloudstack.storage.datastore.db.ObjectStoreVO; +import org.apache.cloudstack.storage.object.BaseObjectStoreDriverImpl; +import org.apache.cloudstack.storage.object.BucketObject; +import org.apache.log4j.Logger; +import org.bouncycastle.crypto.InvalidCipherTextException; + +import javax.inject.Inject; +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class MinIOObjectStoreDriverImpl extends BaseObjectStoreDriverImpl { + private static final Logger s_logger = Logger.getLogger(MinIOObjectStoreDriverImpl.class); + + @Inject + ObjectStoreDao _storeDao; + + @Inject + ObjectStoreDetailsDao _storeDetailsDao; + + private static final String ACCESS_KEY = "accesskey"; + private static final String SECRET_KEY = "secretkey"; + + @Override + public DataStoreTO getStoreTO(DataStore store) { + return null; + } + + @Override + public Bucket createBucket(String bucketName, long storeId) { + //ToDo Client pool mgmt + MinioClient minioClient = getMinIOClient(storeId); + try { + if(minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) { + throw new CloudRuntimeException("Bucket already exists with name "+ bucketName); + } + } catch (Exception e) { + throw new CloudRuntimeException(e); + } + try { + minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build()); + } catch (Exception e) { + throw new CloudRuntimeException(e); + } + Bucket bucket = new BucketObject(); + bucket.setName(bucketName); + return bucket; + } + + @Override + public List listBuckets(long storeId) { + MinioClient minioClient = getMinIOClient(storeId); + List bucketsList = new ArrayList<>(); + try { + List minIOBuckets = minioClient.listBuckets(); + for(io.minio.messages.Bucket minIObucket : minIOBuckets) { + Bucket bucket = new BucketObject(); + bucket.setName(minIObucket.name()); + bucketsList.add(bucket); + } + } catch (Exception e) { + throw new CloudRuntimeException(e); + } + return bucketsList; + } + + @Override + public void deleteBucket(String bucketName, long storeId) { + MinioClient minioClient = getMinIOClient(storeId); + try { + if(minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) { + throw new CloudRuntimeException("Bucket with name %s doesn't exist "+ bucketName); + } + } catch (Exception e) { + throw new CloudRuntimeException(e); + } + //ToDo: check bucket empty + try { + minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build()); + } catch (Exception e) { + throw new CloudRuntimeException(e); + } + } + + @Override + public AccessControlList getBucketAcl(String bucketName, long storeId) { + return null; + } + + @Override + public void setBucketAcl(String bucketName, AccessControlList acl, long storeId) { + + } + + @Override + public void setBucketPolicy(String bucketName, String policyText, long storeId) { + + } + + @Override + public BucketPolicy getBucketPolicy(String bucketName, long storeId) { + return null; + } + + @Override + public void deleteBucketPolicy(String bucketName, long storeId) { + + } + + private MinioClient getMinIOClient(long storeId) { + ObjectStoreVO store = _storeDao.findById(storeId); + Map storeDetails = _storeDetailsDao.getDetails(storeId); + String url = store.getUrl(); + String accessKey = storeDetails.get(ACCESS_KEY); + String secretKey = storeDetails.get(SECRET_KEY); + MinioClient minioClient = + MinioClient.builder() + .endpoint(url) + .credentials(accessKey,secretKey) + .build(); + return minioClient; + } + + private MinioAdminClient getMinIOAdminClient(long storeId) { + ObjectStoreVO store = _storeDao.findById(storeId); + Map storeDetails = _storeDetailsDao.getDetails(storeId); + String url = store.getUrl(); + String accessKey = storeDetails.get(ACCESS_KEY); + String secretKey = storeDetails.get(SECRET_KEY); + MinioAdminClient minioAdminClient = + MinioAdminClient.builder() + .endpoint("http://192.168.29.3:9000") + .credentials("AgbZ4Rk9xltCyax1","aHp8Q2IB2WiUAZG6ef0Hork3fytJOsfT") + .build(); + return minioAdminClient; + } + + private void createUser(long storeId) { + MinioAdminClient minioAdminClient = getMinIOAdminClient(storeId); + String accessKey = "abcd"; + try { + minioAdminClient.addUser(accessKey, UserInfo.Status.ENABLED, "", "", new ArrayList()); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } catch (InvalidKeyException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } catch (InvalidCipherTextException e) { + throw new RuntimeException(e); + } + + } + + private MinioAdminClient getMinIOAdminClient1() { + String url = "http://192.168.29.3:9000"; + String accessKey = "AgbZ4Rk9xltCyax1"; + String secretKey = "aHp8Q2IB2WiUAZG6ef0Hork3fytJOsfT"; + MinioAdminClient minioAdminClient = + MinioAdminClient.builder() + .endpoint(url) + .credentials(accessKey,secretKey) + .build(); + return minioAdminClient; + } + + private void createUser() { + MinioAdminClient minioAdminClient = getMinIOAdminClient1(); + String accessKey = "abcd"; + try { + minioAdminClient.addUser(accessKey, UserInfo.Status.ENABLED, "", "", new ArrayList()); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } catch (InvalidKeyException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } catch (InvalidCipherTextException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/plugins/storage/object/minio/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/MinIOObjectStoreLifeCycleImpl.java b/plugins/storage/object/minio/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/MinIOObjectStoreLifeCycleImpl.java new file mode 100644 index 000000000000..85366924d2a7 --- /dev/null +++ b/plugins/storage/object/minio/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/MinIOObjectStoreLifeCycleImpl.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 org.apache.cloudstack.storage.datastore.lifecycle; + +import com.cloud.agent.api.StoragePoolInfo; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.resource.Discoverer; +import com.cloud.resource.ResourceManager; +import io.minio.MinioClient; +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.ObjectStoreDao; +import org.apache.cloudstack.storage.datastore.db.ObjectStoreVO; +import org.apache.cloudstack.storage.object.datastore.ObjectStoreHelper; +import org.apache.cloudstack.storage.object.datastore.ObjectStoreProviderManager; +import org.apache.cloudstack.storage.object.store.lifecycle.ObjectStoreLifeCycle; +import org.apache.log4j.Logger; + +import javax.inject.Inject; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MinIOObjectStoreLifeCycleImpl implements ObjectStoreLifeCycle { + + private static final Logger s_logger = Logger.getLogger(MinIOObjectStoreLifeCycleImpl.class); + @Inject + protected ResourceManager _resourceMgr; + @Inject + protected ObjectStoreDao objectStoreDao; + @Inject + ObjectStoreHelper objectStoreHelper; + @Inject + ObjectStoreProviderManager objectStoreMgr; + + protected List _discoverers; + + public List getDiscoverers() { + return _discoverers; + } + + public void setDiscoverers(List discoverers) { + this._discoverers = discoverers; + } + + public MinIOObjectStoreLifeCycleImpl() { + } + + @SuppressWarnings("unchecked") + @Override + public DataStore initialize(Map dsInfos) { + + String url = (String)dsInfos.get("url"); + String name = (String)dsInfos.get("name"); + String providerName = (String)dsInfos.get("providerName"); + Map details = (Map)dsInfos.get("details"); + + + Map objectStoreParameters = new HashMap(); + objectStoreParameters.put("name", name); + objectStoreParameters.put("url", url); + String protocol = "http"; + + objectStoreParameters.put("protocol", protocol); + objectStoreParameters.put("providerName", providerName); + + //check credentials + MinioClient minioClient = + MinioClient.builder() + .endpoint("http://172.23.22.219:9000") + .credentials("Gw0Ib6dqvFV4E755","B80AclQmt19XQ3LSES3jiZyWFogcpY4U") + .build(); + try { + // Test connection by listing buckets + minioClient.listBuckets(); + s_logger.debug("Successfully connected to MinIO EndPoint: "+url); + } catch (Exception e) { + throw new RuntimeException(e); + } + + ObjectStoreVO ids = objectStoreHelper.createObjectStore(objectStoreParameters, details); + return objectStoreMgr.getObjectStore(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; + } + + /* (non-Javadoc) + * @see org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle#migrateToObjectStore(org.apache.cloudstack.engine.subsystem.api.storage.DataStore) + */ + @Override + public boolean migrateToObjectStore(DataStore store) { + return false; + } + +} diff --git a/plugins/storage/object/minio/src/main/java/org/apache/cloudstack/storage/datastore/provider/MinIOObjectStoreProviderImpl.java b/plugins/storage/object/minio/src/main/java/org/apache/cloudstack/storage/datastore/provider/MinIOObjectStoreProviderImpl.java new file mode 100644 index 000000000000..abcc4996b884 --- /dev/null +++ b/plugins/storage/object/minio/src/main/java/org/apache/cloudstack/storage/datastore/provider/MinIOObjectStoreProviderImpl.java @@ -0,0 +1,85 @@ +/* + * 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 com.cloud.utils.component.ComponentContext; +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.ObjectStoreProvider; +import org.apache.cloudstack.storage.datastore.driver.MinIOObjectStoreDriverImpl; +import org.apache.cloudstack.storage.datastore.lifecycle.MinIOObjectStoreLifeCycleImpl; +import org.apache.cloudstack.storage.object.ObjectStoreDriver; +import org.apache.cloudstack.storage.object.datastore.ObjectStoreHelper; +import org.apache.cloudstack.storage.object.datastore.ObjectStoreProviderManager; +import org.apache.cloudstack.storage.object.store.lifecycle.ObjectStoreLifeCycle; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +@Component +public class MinIOObjectStoreProviderImpl implements ObjectStoreProvider { + + @Inject + ObjectStoreProviderManager storeMgr; + @Inject + ObjectStoreHelper helper; + + private final String providerName = "MinIO"; + protected ObjectStoreLifeCycle lifeCycle; + protected ObjectStoreDriver driver; + + @Override + public DataStoreLifeCycle getDataStoreLifeCycle() { + return lifeCycle; + } + + @Override + public String getName() { + return this.providerName; + } + + @Override + public boolean configure(Map params) { + lifeCycle = ComponentContext.inject(MinIOObjectStoreLifeCycleImpl.class); + driver = ComponentContext.inject(MinIOObjectStoreDriverImpl.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.OBJECT); + return types; + } +} diff --git a/plugins/storage/object/minio/src/main/resources/META-INF/cloudstack/storage-object-minio/module.properties b/plugins/storage/object/minio/src/main/resources/META-INF/cloudstack/storage-object-minio/module.properties new file mode 100644 index 000000000000..29f2cec82df2 --- /dev/null +++ b/plugins/storage/object/minio/src/main/resources/META-INF/cloudstack/storage-object-minio/module.properties @@ -0,0 +1,18 @@ +# 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. +name=storage-object-minio +parent=storage \ No newline at end of file diff --git a/plugins/storage/object/minio/src/main/resources/META-INF/cloudstack/storage-object-minio/spring-storage-object-minio-context.xml b/plugins/storage/object/minio/src/main/resources/META-INF/cloudstack/storage-object-minio/spring-storage-object-minio-context.xml new file mode 100644 index 000000000000..30876de2e0aa --- /dev/null +++ b/plugins/storage/object/minio/src/main/resources/META-INF/cloudstack/storage-object-minio/spring-storage-object-minio-context.xml @@ -0,0 +1,31 @@ + + + + diff --git a/plugins/storage/object/simulator/pom.xml b/plugins/storage/object/simulator/pom.xml new file mode 100644 index 000000000000..c85c5e6e6aae --- /dev/null +++ b/plugins/storage/object/simulator/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + cloud-plugin-storage-object-simulator + Apache CloudStack Plugin - simulator object storage provider + + org.apache.cloudstack + cloudstack-plugins + 4.19.0.0-SNAPSHOT + ../../../pom.xml + + + + org.apache.cloudstack + cloud-engine-storage + ${project.version} + + + org.apache.cloudstack + cloud-engine-storage-object + ${project.version} + + + diff --git a/plugins/storage/object/simulator/src/main/java/org/apache/cloudstack/storage/datastore/driver/SimulatorObjectStoreDriverImpl.java b/plugins/storage/object/simulator/src/main/java/org/apache/cloudstack/storage/datastore/driver/SimulatorObjectStoreDriverImpl.java new file mode 100644 index 000000000000..4546d3e2d13e --- /dev/null +++ b/plugins/storage/object/simulator/src/main/java/org/apache/cloudstack/storage/datastore/driver/SimulatorObjectStoreDriverImpl.java @@ -0,0 +1,94 @@ +/* + * 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.amazonaws.services.s3.model.AccessControlList; +import com.amazonaws.services.s3.model.BucketPolicy; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.storage.Bucket; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.storage.datastore.db.ObjectStoreDao; +import org.apache.cloudstack.storage.datastore.db.ObjectStoreDetailsDao; +import org.apache.cloudstack.storage.object.BaseObjectStoreDriverImpl; +import org.apache.cloudstack.storage.object.BucketObject; +import org.apache.log4j.Logger; + +import javax.inject.Inject; +import java.util.ArrayList; +import java.util.List; + +public class SimulatorObjectStoreDriverImpl extends BaseObjectStoreDriverImpl { + private static final Logger s_logger = Logger.getLogger(SimulatorObjectStoreDriverImpl.class); + + @Inject + ObjectStoreDao _storeDao; + + @Inject + ObjectStoreDetailsDao _storeDetailsDao; + + private static final String ACCESS_KEY = "accesskey"; + private static final String SECRET_KEY = "secretkey"; + + @Override + public DataStoreTO getStoreTO(DataStore store) { + return null; + } + + @Override + public Bucket createBucket(String bucketName, long storeId) { + Bucket bucket = new BucketObject(); + bucket.setName(bucketName); + return bucket; + } + + @Override + public List listBuckets(long storeId) { + List bucketsList = new ArrayList<>(); + return bucketsList; + } + + @Override + public void deleteBucket(String bucketName, long storeId) { + + } + + @Override + public AccessControlList getBucketAcl(String bucketName, long storeId) { + return null; + } + + @Override + public void setBucketAcl(String bucketName, AccessControlList acl, long storeId) { + + } + + @Override + public void setBucketPolicy(String bucketName, String policyText, long storeId) { + + } + + @Override + public BucketPolicy getBucketPolicy(String bucketName, long storeId) { + return null; + } + + @Override + public void deleteBucketPolicy(String bucketName, long storeId) { + } +} diff --git a/plugins/storage/object/simulator/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/SimulatorObjectStoreLifeCycleImpl.java b/plugins/storage/object/simulator/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/SimulatorObjectStoreLifeCycleImpl.java new file mode 100644 index 000000000000..fe3c8a07dcb6 --- /dev/null +++ b/plugins/storage/object/simulator/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/SimulatorObjectStoreLifeCycleImpl.java @@ -0,0 +1,124 @@ +// 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.Discoverer; +import com.cloud.resource.ResourceManager; +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.ObjectStoreDao; +import org.apache.cloudstack.storage.datastore.db.ObjectStoreVO; +import org.apache.cloudstack.storage.object.datastore.ObjectStoreHelper; +import org.apache.cloudstack.storage.object.datastore.ObjectStoreProviderManager; +import org.apache.cloudstack.storage.object.store.lifecycle.ObjectStoreLifeCycle; +import org.apache.log4j.Logger; + +import javax.inject.Inject; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class SimulatorObjectStoreLifeCycleImpl implements ObjectStoreLifeCycle { + + private static final Logger s_logger = Logger.getLogger(SimulatorObjectStoreLifeCycleImpl.class); + @Inject + protected ResourceManager _resourceMgr; + @Inject + protected ObjectStoreDao objectStoreDao; + @Inject + ObjectStoreHelper objectStoreHelper; + @Inject + ObjectStoreProviderManager objectStoreMgr; + + protected List _discoverers; + + public List getDiscoverers() { + return _discoverers; + } + + public void setDiscoverers(List discoverers) { + this._discoverers = discoverers; + } + + public SimulatorObjectStoreLifeCycleImpl() { + } + + @SuppressWarnings("unchecked") + @Override + public DataStore initialize(Map dsInfos) { + + String url = (String)dsInfos.get("url"); + String name = (String)dsInfos.get("name"); + String providerName = (String)dsInfos.get("providerName"); + Map details = (Map)dsInfos.get("details"); + + + Map objectStoreParameters = new HashMap(); + objectStoreParameters.put("name", name); + objectStoreParameters.put("url", url); + String protocol = "http"; + + objectStoreParameters.put("protocol", protocol); + objectStoreParameters.put("providerName", providerName); + + ObjectStoreVO ids = objectStoreHelper.createObjectStore(objectStoreParameters, details); + return objectStoreMgr.getObjectStore(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; + } + + /* (non-Javadoc) + * @see org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle#migrateToObjectStore(org.apache.cloudstack.engine.subsystem.api.storage.DataStore) + */ + @Override + public boolean migrateToObjectStore(DataStore store) { + return false; + } + +} diff --git a/plugins/storage/object/simulator/src/main/java/org/apache/cloudstack/storage/datastore/provider/SimulatorObjectStoreProviderImpl.java b/plugins/storage/object/simulator/src/main/java/org/apache/cloudstack/storage/datastore/provider/SimulatorObjectStoreProviderImpl.java new file mode 100644 index 000000000000..651fac4d1f13 --- /dev/null +++ b/plugins/storage/object/simulator/src/main/java/org/apache/cloudstack/storage/datastore/provider/SimulatorObjectStoreProviderImpl.java @@ -0,0 +1,85 @@ +/* + * 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 com.cloud.utils.component.ComponentContext; +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.ObjectStoreProvider; +import org.apache.cloudstack.storage.datastore.driver.SimulatorObjectStoreDriverImpl; +import org.apache.cloudstack.storage.datastore.lifecycle.SimulatorObjectStoreLifeCycleImpl; +import org.apache.cloudstack.storage.object.ObjectStoreDriver; +import org.apache.cloudstack.storage.object.datastore.ObjectStoreHelper; +import org.apache.cloudstack.storage.object.datastore.ObjectStoreProviderManager; +import org.apache.cloudstack.storage.object.store.lifecycle.ObjectStoreLifeCycle; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +@Component +public class SimulatorObjectStoreProviderImpl implements ObjectStoreProvider { + + @Inject + ObjectStoreProviderManager storeMgr; + @Inject + ObjectStoreHelper helper; + + private final String providerName = "Simulator"; + protected ObjectStoreLifeCycle lifeCycle; + protected ObjectStoreDriver driver; + + @Override + public DataStoreLifeCycle getDataStoreLifeCycle() { + return lifeCycle; + } + + @Override + public String getName() { + return this.providerName; + } + + @Override + public boolean configure(Map params) { + lifeCycle = ComponentContext.inject(SimulatorObjectStoreLifeCycleImpl.class); + driver = ComponentContext.inject(SimulatorObjectStoreDriverImpl.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.OBJECT); + return types; + } +} diff --git a/plugins/storage/object/simulator/src/main/resources/META-INF/cloudstack/storage-object-simulator/module.properties b/plugins/storage/object/simulator/src/main/resources/META-INF/cloudstack/storage-object-simulator/module.properties new file mode 100644 index 000000000000..da315a6d644f --- /dev/null +++ b/plugins/storage/object/simulator/src/main/resources/META-INF/cloudstack/storage-object-simulator/module.properties @@ -0,0 +1,18 @@ +# 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. +name=storage-object-simulator +parent=storage \ No newline at end of file diff --git a/plugins/storage/object/simulator/src/main/resources/META-INF/cloudstack/storage-object-simulator/spring-storage-object-simulator-context.xml b/plugins/storage/object/simulator/src/main/resources/META-INF/cloudstack/storage-object-simulator/spring-storage-object-simulator-context.xml new file mode 100644 index 000000000000..863b881d7f1d --- /dev/null +++ b/plugins/storage/object/simulator/src/main/resources/META-INF/cloudstack/storage-object-simulator/spring-storage-object-simulator-context.xml @@ -0,0 +1,31 @@ + + + + diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java index 8fffebb33034..a223c805688d 100644 --- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java +++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java @@ -37,6 +37,7 @@ import javax.inject.Inject; +import com.cloud.storage.ObjectStore; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.affinity.AffinityGroup; @@ -114,6 +115,7 @@ import org.apache.cloudstack.api.response.NicExtraDhcpOptionResponse; 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.OvsProviderResponse; import org.apache.cloudstack.api.response.PhysicalNetworkResponse; import org.apache.cloudstack.api.response.PodResponse; @@ -4965,4 +4967,15 @@ public FirewallResponse createIpv6FirewallRuleResponse(FirewallRule fwRule) { response.setObjectName("firewallrule"); return response; } + + @Override + public ObjectStoreResponse createObjectStoreResponse(ObjectStore os) { + ObjectStoreResponse objectStoreResponse = new ObjectStoreResponse(); + objectStoreResponse.setId(os.getUuid()); + objectStoreResponse.setName(os.getName()); + objectStoreResponse.setProtocol(os.getProtocol()); + objectStoreResponse.setProviderName(os.getProviderName()); + objectStoreResponse.setObjectName("objectstore"); + return objectStoreResponse; + } } diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java index ce5b9db574dd..2a73a6095a08 100644 --- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java @@ -62,6 +62,7 @@ import org.apache.cloudstack.api.command.admin.router.GetRouterHealthCheckResultsCmd; 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.ListObjectStoragePoolsCmd; import org.apache.cloudstack.api.command.admin.storage.ListSecondaryStagingStoresCmd; import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd; import org.apache.cloudstack.api.command.admin.storage.ListStorageTagsCmd; @@ -100,6 +101,7 @@ import org.apache.cloudstack.api.response.InstanceGroupResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ManagementServerResponse; +import org.apache.cloudstack.api.response.ObjectStoreResponse; import org.apache.cloudstack.api.response.ProjectAccountResponse; import org.apache.cloudstack.api.response.ProjectInvitationResponse; import org.apache.cloudstack.api.response.ProjectResponse; @@ -4434,6 +4436,12 @@ public List listRouterHealthChecks(GetRouterHea return responseGenerator.createHealthCheckResponse(_routerDao.findById(routerId), result); } + @Override + public ListResponse searchForObjectStores(ListObjectStoragePoolsCmd cmd) { + ListResponse response = new ListResponse(); + return response; + } + @Override public String getConfigComponentName() { return QueryService.class.getSimpleName(); diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 964cca71f1cc..3cac963162e6 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -211,6 +211,7 @@ import org.apache.cloudstack.api.command.admin.router.UpgradeRouterTemplateCmd; import org.apache.cloudstack.api.command.admin.storage.AddImageStoreCmd; import org.apache.cloudstack.api.command.admin.storage.AddImageStoreS3CMD; +import org.apache.cloudstack.api.command.admin.storage.AddObjectStoragePoolCmd; import org.apache.cloudstack.api.command.admin.storage.CancelPrimaryStorageMaintenanceCmd; import org.apache.cloudstack.api.command.admin.storage.CreateSecondaryStagingStoreCmd; import org.apache.cloudstack.api.command.admin.storage.CreateStoragePoolCmd; @@ -219,6 +220,7 @@ import org.apache.cloudstack.api.command.admin.storage.DeleteSecondaryStagingStoreCmd; 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.ListObjectStoragePoolsCmd; import org.apache.cloudstack.api.command.admin.storage.ListSecondaryStagingStoresCmd; import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd; import org.apache.cloudstack.api.command.admin.storage.ListStorageProvidersCmd; @@ -3798,6 +3800,10 @@ public List> getCommands() { cmdList.add(DeleteUserDataCmd.class); cmdList.add(ListUserDataCmd.class); cmdList.add(LinkUserDataToTemplateCmd.class); + + //object store APIs + cmdList.add(AddObjectStoragePoolCmd.class); + cmdList.add(ListObjectStoragePoolsCmd.class); return cmdList; } diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java index c1d17cc8f70b..a2967e26c167 100644 --- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java @@ -3436,4 +3436,34 @@ private void setVolumeObjectTOThrottling(VolumeObjectTO volumeTO, final ServiceO volumeTO.setIopsWriteRate(getDiskIopsWriteRate(offering, diskOffering)); } + @Override + public ObjectStore discoverObjectStore(String name, String url, String providerName, Map details) + throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException { + DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(providerName); + + if (storeProvider == null) { + throw new InvalidParameterValueException("can't find object store provider: " + providerName); + } + + + Map params = new HashMap<>(); + params.put("url", url); + params.put("name", name); + params.put("providerName", storeProvider.getName()); + params.put("role", DataStoreRole.Object); + + DataStoreLifeCycle lifeCycle = storeProvider.getDataStoreLifeCycle(); + + DataStore store; + try { + store = lifeCycle.initialize(params); + } catch (Exception e) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Failed to add object store: " + e.getMessage(), e); + } + throw new CloudRuntimeException("Failed to add object store: " + e.getMessage(), e); + } + + return (ObjectStore)_dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Object); + } }