Skip to content

Commit

Permalink
feature: Shared Storage Filesystem as a First Class Feature (#9208)
Browse files Browse the repository at this point in the history
This PR implements Storage filesystem as a first class feature.
https://cwiki.apache.org/confluence/display/CLOUDSTACK/Storage+Filesystem+as+a+First+Class+Feature

Documentation PR: apache/cloudstack-documentation#420

Co-authored-by: Wei Zhou <[email protected]>
  • Loading branch information
abh1sar and weizhouapache committed Sep 5, 2024
1 parent 72d0546 commit 605534b
Show file tree
Hide file tree
Showing 95 changed files with 8,938 additions and 567 deletions.
25 changes: 25 additions & 0 deletions api/src/main/java/com/cloud/event/EventTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.apache.cloudstack.config.Configuration;
import org.apache.cloudstack.ha.HAConfig;
import org.apache.cloudstack.quota.QuotaTariff;
import org.apache.cloudstack.storage.sharedfs.SharedFS;
import org.apache.cloudstack.storage.object.Bucket;
import org.apache.cloudstack.storage.object.ObjectStore;
import org.apache.cloudstack.usage.Usage;
Expand Down Expand Up @@ -744,6 +745,18 @@ public class EventTypes {
public static final String EVENT_QUOTA_TARIFF_DELETE = "QUOTA.TARIFF.DELETE";
public static final String EVENT_QUOTA_TARIFF_UPDATE = "QUOTA.TARIFF.UPDATE";

// SharedFS
public static final String EVENT_SHAREDFS_CREATE = "SHAREDFS.CREATE";
public static final String EVENT_SHAREDFS_START = "SHAREDFS.START";
public static final String EVENT_SHAREDFS_UPDATE = "SHAREDFS.UPDATE";
public static final String EVENT_SHAREDFS_CHANGE_SERVICE_OFFERING = "SHAREDFS.CHANGE.SERVICE.OFFERING";
public static final String EVENT_SHAREDFS_CHANGE_DISK_OFFERING = "SHAREDFS.CHANGE.DISK.OFFERING";
public static final String EVENT_SHAREDFS_STOP = "SHAREDFS.STOP";
public static final String EVENT_SHAREDFS_RESTART = "SHAREDFS.RESTART";
public static final String EVENT_SHAREDFS_DESTROY = "SHAREDFS.DESTROY";
public static final String EVENT_SHAREDFS_EXPUNGE = "SHAREDFS.EXPUNGE";
public static final String EVENT_SHAREDFS_RECOVER = "SHAREDFS.RECOVER";

static {

// TODO: need a way to force author adding event types to declare the entity details as well, with out braking
Expand Down Expand Up @@ -1203,6 +1216,18 @@ public class EventTypes {
entityEventDetails.put(EVENT_QUOTA_TARIFF_CREATE, QuotaTariff.class);
entityEventDetails.put(EVENT_QUOTA_TARIFF_DELETE, QuotaTariff.class);
entityEventDetails.put(EVENT_QUOTA_TARIFF_UPDATE, QuotaTariff.class);

// SharedFS
entityEventDetails.put(EVENT_SHAREDFS_CREATE, SharedFS.class);
entityEventDetails.put(EVENT_SHAREDFS_START, SharedFS.class);
entityEventDetails.put(EVENT_SHAREDFS_STOP, SharedFS.class);
entityEventDetails.put(EVENT_SHAREDFS_UPDATE, SharedFS.class);
entityEventDetails.put(EVENT_SHAREDFS_CHANGE_SERVICE_OFFERING, SharedFS.class);
entityEventDetails.put(EVENT_SHAREDFS_CHANGE_DISK_OFFERING, SharedFS.class);
entityEventDetails.put(EVENT_SHAREDFS_RESTART, SharedFS.class);
entityEventDetails.put(EVENT_SHAREDFS_DESTROY, SharedFS.class);
entityEventDetails.put(EVENT_SHAREDFS_EXPUNGE, SharedFS.class);
entityEventDetails.put(EVENT_SHAREDFS_RECOVER, SharedFS.class);
}

public static boolean isNetworkEvent(String eventType) {
Expand Down
4 changes: 4 additions & 0 deletions api/src/main/java/com/cloud/storage/VolumeApiService.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,12 @@ public interface VolumeApiService {

boolean deleteVolume(long volumeId, Account caller);

Volume changeDiskOfferingForVolumeInternal(Long volumeId, Long newDiskOfferingId, Long newSize, Long newMinIops, Long newMaxIops, boolean autoMigrateVolume, boolean shrinkOk) throws ResourceAllocationException;

Volume attachVolumeToVM(AttachVolumeCmd command);

Volume attachVolumeToVM(Long vmId, Long volumeId, Long deviceId, Boolean allowAttachForSharedFS);

Volume detachVolumeViaDestroyVM(long vmId, long volumeId);

Volume detachVolumeFromVM(DetachVolumeCmd cmd);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ public enum ApiCommandResourceType {
Bucket(org.apache.cloudstack.storage.object.Bucket.class),
QuotaTariff(org.apache.cloudstack.quota.QuotaTariff.class),
KubernetesCluster(null),
KubernetesSupportedVersion(null);
KubernetesSupportedVersion(null),
SharedFS(org.apache.cloudstack.storage.sharedfs.SharedFS.class);

private final Class<?> clazz;

Expand Down
6 changes: 6 additions & 0 deletions api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ public class ApiConstants {
public static final String EXTERNAL_UUID = "externaluuid";
public static final String FENCE = "fence";
public static final String FETCH_LATEST = "fetchlatest";
public static final String FILESYSTEM = "filesystem";
public static final String FIRSTNAME = "firstname";
public static final String FORCED = "forced";
public static final String FORCED_DESTROY_LOCAL_STORAGE = "forcedestroylocalstorage";
Expand Down Expand Up @@ -432,6 +433,7 @@ public class ApiConstants {
public static final String SIGNATURE_VERSION = "signatureversion";
public static final String SINCE = "since";
public static final String SIZE = "size";
public static final String SIZEGB = "sizegb";
public static final String SNAPSHOT = "snapshot";
public static final String SNAPSHOT_ID = "snapshotid";
public static final String SNAPSHOT_POLICY_ID = "snapshotpolicyid";
Expand Down Expand Up @@ -504,6 +506,7 @@ public class ApiConstants {
public static final String VIRTUAL_MACHINE_ID_IP = "vmidipmap";
public static final String VIRTUAL_MACHINE_COUNT = "virtualmachinecount";
public static final String VIRTUAL_MACHINE_TYPE = "virtualmachinetype";
public static final String VIRTUAL_MACHINE_STATE = "vmstate";
public static final String VIRTUAL_MACHINES = "virtualmachines";
public static final String USAGE_ID = "usageid";
public static final String USAGE_TYPE = "usagetype";
Expand Down Expand Up @@ -1143,6 +1146,9 @@ public class ApiConstants {

public static final String NFS_MOUNT_OPTIONS = "nfsmountopts";

public static final String SHAREDFSVM_MIN_CPU_COUNT = "sharedfsvmmincpucount";
public static final String SHAREDFSVM_MIN_RAM_SIZE = "sharedfsvmminramsize";

public static final String PARAMETER_DESCRIPTION_ACTIVATION_RULE = "Quota tariff's activation rule. It can receive a JS script that results in either " +
"a boolean or a numeric value: if it results in a boolean value, the tariff value will be applied according to the result; if it results in a numeric value, the " +
"numeric value will be applied; if the result is neither a boolean nor a numeric value, the tariff will not be applied. If the rule is not informed, the tariff " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import org.apache.cloudstack.api.response.DomainRouterResponse;
import org.apache.cloudstack.api.response.EventResponse;
import org.apache.cloudstack.api.response.ExtractResponse;
import org.apache.cloudstack.api.response.SharedFSResponse;
import org.apache.cloudstack.api.response.FirewallResponse;
import org.apache.cloudstack.api.response.FirewallRuleResponse;
import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse;
Expand Down Expand Up @@ -151,6 +152,7 @@
import org.apache.cloudstack.region.PortableIpRange;
import org.apache.cloudstack.region.Region;
import org.apache.cloudstack.secstorage.heuristics.Heuristic;
import org.apache.cloudstack.storage.sharedfs.SharedFS;
import org.apache.cloudstack.storage.object.ObjectStore;
import org.apache.cloudstack.usage.Usage;

Expand Down Expand Up @@ -551,4 +553,6 @@ List<TemplateResponse> createTemplateResponses(ResponseView view, VirtualMachine
ObjectStoreResponse createObjectStoreResponse(ObjectStore os);

BucketResponse createBucketResponse(Bucket bucket);

SharedFSResponse createSharedFSResponse(ResponseView view, SharedFS sharedFS);
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ public void execute() {
response.setInstancesStatsUserOnly((Boolean) capabilities.get(ApiConstants.INSTANCES_STATS_USER_ONLY));
response.setInstancesDisksStatsRetentionEnabled((Boolean) capabilities.get(ApiConstants.INSTANCES_DISKS_STATS_RETENTION_ENABLED));
response.setInstancesDisksStatsRetentionTime((Integer) capabilities.get(ApiConstants.INSTANCES_DISKS_STATS_RETENTION_TIME));
response.setSharedFsVmMinCpuCount((Integer)capabilities.get(ApiConstants.SHAREDFSVM_MIN_CPU_COUNT));
response.setSharedFsVmMinRamSize((Integer)capabilities.get(ApiConstants.SHAREDFSVM_MIN_RAM_SIZE));
response.setObjectName("capability");
response.setResponseName(getCommandName());
this.setResponseObject(response);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// 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.user.storage.sharedfs;

import javax.inject.Inject;

import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ResponseObject;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.command.user.UserCmd;
import org.apache.cloudstack.api.response.DiskOfferingResponse;
import org.apache.cloudstack.api.response.SharedFSResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.storage.sharedfs.SharedFS;
import org.apache.cloudstack.storage.sharedfs.SharedFSService;

import com.cloud.event.EventTypes;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.user.Account;

@APICommand(name = "changeSharedFileSystemDiskOffering",
responseObject= SharedFSResponse.class,
description = "Change Disk offering of a Shared FileSystem",
responseView = ResponseObject.ResponseView.Restricted,
entityType = SharedFS.class,
requestHasSensitiveInfo = false,
since = "4.20.0",
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
public class ChangeSharedFSDiskOfferingCmd extends BaseAsyncCmd implements UserCmd {

@Inject
SharedFSService sharedFSService;

/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////

@Parameter(name = ApiConstants.ID,
type = CommandType.UUID,
required = true,
entityType = SharedFSResponse.class,
description = "the ID of the shared filesystem")
private Long id;

@Parameter(name = ApiConstants.DISK_OFFERING_ID,
type = CommandType.UUID,
entityType = DiskOfferingResponse.class,
description = "the disk offering to use for the underlying storage")
private Long diskOfferingId;

@Parameter(name = ApiConstants.SIZE,
type = CommandType.LONG,
description = "the size of the shared filesystem in GiB")
private Long size;

@Parameter(name = ApiConstants.MIN_IOPS,
type = CommandType.LONG,
description = "min iops")
private Long minIops;

@Parameter(name = ApiConstants.MAX_IOPS,
type = CommandType.LONG,
description = "max iops")
private Long maxIops;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////

public Long getId() {
return id;
}

public Long getSize() {
return size;
}

public Long getDiskOfferingId() {
return diskOfferingId;
}

public Long getMinIops() {
return minIops;
}

public Long getMaxIops() {
return maxIops;
}

/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

@Override
public String getEventType() {
return EventTypes.EVENT_SHAREDFS_CHANGE_DISK_OFFERING;
}

@Override
public String getEventDescription() {
return "Changing disk offering for the Shared FileSystem " + id;
}

@Override
public long getEntityOwnerId() {
return CallContext.current().getCallingAccount().getId();
}

@Override
public void execute() throws ResourceAllocationException {
SharedFS sharedFS = sharedFSService.changeSharedFSDiskOffering(this);
if (sharedFS != null) {
ResponseObject.ResponseView respView = getResponseView();
Account caller = CallContext.current().getCallingAccount();
if (_accountService.isRootAdmin(caller.getId())) {
respView = ResponseObject.ResponseView.Full;
}
SharedFSResponse response = _responseGenerator.createSharedFSResponse(respView, sharedFS);
response.setObjectName(SharedFS.class.getSimpleName().toLowerCase());
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to change disk offering for the Shared FileSystem");
}
}
}
Loading

0 comments on commit 605534b

Please sign in to comment.