Skip to content

Commit a9972ea

Browse files
abh1sarweizhouapache
authored andcommitted
feature: Shared Storage Filesystem as a First Class Feature (apache#9208)
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 <weizhou@apache.org>
1 parent 77dca4c commit a9972ea

95 files changed

Lines changed: 8939 additions & 611 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

api/src/main/java/com/cloud/event/EventTypes.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.apache.cloudstack.config.Configuration;
3131
import org.apache.cloudstack.ha.HAConfig;
3232
import org.apache.cloudstack.quota.QuotaTariff;
33+
import org.apache.cloudstack.storage.sharedfs.SharedFS;
3334
import org.apache.cloudstack.storage.object.Bucket;
3435
import org.apache.cloudstack.storage.object.ObjectStore;
3536
import org.apache.cloudstack.usage.Usage;
@@ -753,6 +754,18 @@ public class EventTypes {
753754
public static final String EVENT_QUOTA_TARIFF_DELETE = "QUOTA.TARIFF.DELETE";
754755
public static final String EVENT_QUOTA_TARIFF_UPDATE = "QUOTA.TARIFF.UPDATE";
755756

757+
// SharedFS
758+
public static final String EVENT_SHAREDFS_CREATE = "SHAREDFS.CREATE";
759+
public static final String EVENT_SHAREDFS_START = "SHAREDFS.START";
760+
public static final String EVENT_SHAREDFS_UPDATE = "SHAREDFS.UPDATE";
761+
public static final String EVENT_SHAREDFS_CHANGE_SERVICE_OFFERING = "SHAREDFS.CHANGE.SERVICE.OFFERING";
762+
public static final String EVENT_SHAREDFS_CHANGE_DISK_OFFERING = "SHAREDFS.CHANGE.DISK.OFFERING";
763+
public static final String EVENT_SHAREDFS_STOP = "SHAREDFS.STOP";
764+
public static final String EVENT_SHAREDFS_RESTART = "SHAREDFS.RESTART";
765+
public static final String EVENT_SHAREDFS_DESTROY = "SHAREDFS.DESTROY";
766+
public static final String EVENT_SHAREDFS_EXPUNGE = "SHAREDFS.EXPUNGE";
767+
public static final String EVENT_SHAREDFS_RECOVER = "SHAREDFS.RECOVER";
768+
756769
static {
757770

758771
// TODO: need a way to force author adding event types to declare the entity details as well, with out braking
@@ -1216,6 +1229,18 @@ public class EventTypes {
12161229
entityEventDetails.put(EVENT_QUOTA_TARIFF_CREATE, QuotaTariff.class);
12171230
entityEventDetails.put(EVENT_QUOTA_TARIFF_DELETE, QuotaTariff.class);
12181231
entityEventDetails.put(EVENT_QUOTA_TARIFF_UPDATE, QuotaTariff.class);
1232+
1233+
// SharedFS
1234+
entityEventDetails.put(EVENT_SHAREDFS_CREATE, SharedFS.class);
1235+
entityEventDetails.put(EVENT_SHAREDFS_START, SharedFS.class);
1236+
entityEventDetails.put(EVENT_SHAREDFS_STOP, SharedFS.class);
1237+
entityEventDetails.put(EVENT_SHAREDFS_UPDATE, SharedFS.class);
1238+
entityEventDetails.put(EVENT_SHAREDFS_CHANGE_SERVICE_OFFERING, SharedFS.class);
1239+
entityEventDetails.put(EVENT_SHAREDFS_CHANGE_DISK_OFFERING, SharedFS.class);
1240+
entityEventDetails.put(EVENT_SHAREDFS_RESTART, SharedFS.class);
1241+
entityEventDetails.put(EVENT_SHAREDFS_DESTROY, SharedFS.class);
1242+
entityEventDetails.put(EVENT_SHAREDFS_EXPUNGE, SharedFS.class);
1243+
entityEventDetails.put(EVENT_SHAREDFS_RECOVER, SharedFS.class);
12191244
}
12201245

12211246
public static boolean isNetworkEvent(String eventType) {

api/src/main/java/com/cloud/storage/VolumeApiService.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,12 @@ public interface VolumeApiService {
103103

104104
boolean deleteVolume(long volumeId, Account caller);
105105

106+
Volume changeDiskOfferingForVolumeInternal(Long volumeId, Long newDiskOfferingId, Long newSize, Long newMinIops, Long newMaxIops, boolean autoMigrateVolume, boolean shrinkOk) throws ResourceAllocationException;
107+
106108
Volume attachVolumeToVM(AttachVolumeCmd command);
107109

110+
Volume attachVolumeToVM(Long vmId, Long volumeId, Long deviceId, Boolean allowAttachForSharedFS);
111+
108112
Volume detachVolumeViaDestroyVM(long vmId, long volumeId);
109113

110114
Volume detachVolumeFromVM(DetachVolumeCmd cmd);

api/src/main/java/org/apache/cloudstack/api/ApiCommandResourceType.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ public enum ApiCommandResourceType {
8585
Bucket(org.apache.cloudstack.storage.object.Bucket.class),
8686
QuotaTariff(org.apache.cloudstack.quota.QuotaTariff.class),
8787
KubernetesCluster(null),
88-
KubernetesSupportedVersion(null);
88+
KubernetesSupportedVersion(null),
89+
SharedFS(org.apache.cloudstack.storage.sharedfs.SharedFS.class);
8990

9091
private final Class<?> clazz;
9192

api/src/main/java/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ public class ApiConstants {
188188
public static final String EXTERNAL_UUID = "externaluuid";
189189
public static final String FENCE = "fence";
190190
public static final String FETCH_LATEST = "fetchlatest";
191+
public static final String FILESYSTEM = "filesystem";
191192
public static final String FIRSTNAME = "firstname";
192193
public static final String FORCED = "forced";
193194
public static final String FORCED_DESTROY_LOCAL_STORAGE = "forcedestroylocalstorage";
@@ -434,6 +435,7 @@ public class ApiConstants {
434435
public static final String SIGNATURE_VERSION = "signatureversion";
435436
public static final String SINCE = "since";
436437
public static final String SIZE = "size";
438+
public static final String SIZEGB = "sizegb";
437439
public static final String SNAPSHOT = "snapshot";
438440
public static final String SNAPSHOT_ID = "snapshotid";
439441
public static final String SNAPSHOT_POLICY_ID = "snapshotpolicyid";
@@ -506,6 +508,7 @@ public class ApiConstants {
506508
public static final String VIRTUAL_MACHINE_ID_IP = "vmidipmap";
507509
public static final String VIRTUAL_MACHINE_COUNT = "virtualmachinecount";
508510
public static final String VIRTUAL_MACHINE_TYPE = "virtualmachinetype";
511+
public static final String VIRTUAL_MACHINE_STATE = "vmstate";
509512
public static final String VIRTUAL_MACHINES = "virtualmachines";
510513
public static final String USAGE_ID = "usageid";
511514
public static final String USAGE_TYPE = "usagetype";
@@ -1221,6 +1224,9 @@ public class ApiConstants {
12211224

12221225
public static final String NFS_MOUNT_OPTIONS = "nfsmountopts";
12231226

1227+
public static final String SHAREDFSVM_MIN_CPU_COUNT = "sharedfsvmmincpucount";
1228+
public static final String SHAREDFSVM_MIN_RAM_SIZE = "sharedfsvmminramsize";
1229+
12241230
public static final String PARAMETER_DESCRIPTION_ACTIVATION_RULE = "Quota tariff's activation rule. It can receive a JS script that results in either " +
12251231
"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 " +
12261232
"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 " +

api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import org.apache.cloudstack.api.response.DomainRouterResponse;
5555
import org.apache.cloudstack.api.response.EventResponse;
5656
import org.apache.cloudstack.api.response.ExtractResponse;
57+
import org.apache.cloudstack.api.response.SharedFSResponse;
5758
import org.apache.cloudstack.api.response.FirewallResponse;
5859
import org.apache.cloudstack.api.response.FirewallRuleResponse;
5960
import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse;
@@ -151,6 +152,7 @@
151152
import org.apache.cloudstack.region.PortableIpRange;
152153
import org.apache.cloudstack.region.Region;
153154
import org.apache.cloudstack.secstorage.heuristics.Heuristic;
155+
import org.apache.cloudstack.storage.sharedfs.SharedFS;
154156
import org.apache.cloudstack.storage.object.ObjectStore;
155157
import org.apache.cloudstack.usage.Usage;
156158
import org.apache.cloudstack.outofbandmanagement.OutOfBandManagement;
@@ -554,4 +556,6 @@ List<TemplateResponse> createTemplateResponses(ResponseView view, VirtualMachine
554556
ObjectStoreResponse createObjectStoreResponse(ObjectStore os);
555557

556558
BucketResponse createBucketResponse(Bucket bucket);
559+
560+
SharedFSResponse createSharedFSResponse(ResponseView view, SharedFS sharedFS);
557561
}

api/src/main/java/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ public void execute() {
8181
response.setInstancesStatsUserOnly((Boolean) capabilities.get(ApiConstants.INSTANCES_STATS_USER_ONLY));
8282
response.setInstancesDisksStatsRetentionEnabled((Boolean) capabilities.get(ApiConstants.INSTANCES_DISKS_STATS_RETENTION_ENABLED));
8383
response.setInstancesDisksStatsRetentionTime((Integer) capabilities.get(ApiConstants.INSTANCES_DISKS_STATS_RETENTION_TIME));
84+
response.setSharedFsVmMinCpuCount((Integer)capabilities.get(ApiConstants.SHAREDFSVM_MIN_CPU_COUNT));
85+
response.setSharedFsVmMinRamSize((Integer)capabilities.get(ApiConstants.SHAREDFSVM_MIN_RAM_SIZE));
8486
response.setObjectName("capability");
8587
response.setResponseName(getCommandName());
8688
this.setResponseObject(response);
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package org.apache.cloudstack.api.command.user.storage.sharedfs;
18+
19+
import javax.inject.Inject;
20+
21+
import org.apache.cloudstack.acl.RoleType;
22+
import org.apache.cloudstack.api.APICommand;
23+
import org.apache.cloudstack.api.ApiConstants;
24+
import org.apache.cloudstack.api.ApiErrorCode;
25+
import org.apache.cloudstack.api.BaseAsyncCmd;
26+
import org.apache.cloudstack.api.Parameter;
27+
import org.apache.cloudstack.api.ResponseObject;
28+
import org.apache.cloudstack.api.ServerApiException;
29+
import org.apache.cloudstack.api.command.user.UserCmd;
30+
import org.apache.cloudstack.api.response.DiskOfferingResponse;
31+
import org.apache.cloudstack.api.response.SharedFSResponse;
32+
import org.apache.cloudstack.context.CallContext;
33+
import org.apache.cloudstack.storage.sharedfs.SharedFS;
34+
import org.apache.cloudstack.storage.sharedfs.SharedFSService;
35+
36+
import com.cloud.event.EventTypes;
37+
import com.cloud.exception.ResourceAllocationException;
38+
import com.cloud.user.Account;
39+
40+
@APICommand(name = "changeSharedFileSystemDiskOffering",
41+
responseObject= SharedFSResponse.class,
42+
description = "Change Disk offering of a Shared FileSystem",
43+
responseView = ResponseObject.ResponseView.Restricted,
44+
entityType = SharedFS.class,
45+
requestHasSensitiveInfo = false,
46+
since = "4.20.0",
47+
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
48+
public class ChangeSharedFSDiskOfferingCmd extends BaseAsyncCmd implements UserCmd {
49+
50+
@Inject
51+
SharedFSService sharedFSService;
52+
53+
/////////////////////////////////////////////////////
54+
//////////////// API parameters /////////////////////
55+
/////////////////////////////////////////////////////
56+
57+
@Parameter(name = ApiConstants.ID,
58+
type = CommandType.UUID,
59+
required = true,
60+
entityType = SharedFSResponse.class,
61+
description = "the ID of the shared filesystem")
62+
private Long id;
63+
64+
@Parameter(name = ApiConstants.DISK_OFFERING_ID,
65+
type = CommandType.UUID,
66+
entityType = DiskOfferingResponse.class,
67+
description = "the disk offering to use for the underlying storage")
68+
private Long diskOfferingId;
69+
70+
@Parameter(name = ApiConstants.SIZE,
71+
type = CommandType.LONG,
72+
description = "the size of the shared filesystem in GiB")
73+
private Long size;
74+
75+
@Parameter(name = ApiConstants.MIN_IOPS,
76+
type = CommandType.LONG,
77+
description = "min iops")
78+
private Long minIops;
79+
80+
@Parameter(name = ApiConstants.MAX_IOPS,
81+
type = CommandType.LONG,
82+
description = "max iops")
83+
private Long maxIops;
84+
85+
/////////////////////////////////////////////////////
86+
/////////////////// Accessors ///////////////////////
87+
/////////////////////////////////////////////////////
88+
89+
public Long getId() {
90+
return id;
91+
}
92+
93+
public Long getSize() {
94+
return size;
95+
}
96+
97+
public Long getDiskOfferingId() {
98+
return diskOfferingId;
99+
}
100+
101+
public Long getMinIops() {
102+
return minIops;
103+
}
104+
105+
public Long getMaxIops() {
106+
return maxIops;
107+
}
108+
109+
/////////////////////////////////////////////////////
110+
/////////////// API Implementation///////////////////
111+
/////////////////////////////////////////////////////
112+
113+
@Override
114+
public String getEventType() {
115+
return EventTypes.EVENT_SHAREDFS_CHANGE_DISK_OFFERING;
116+
}
117+
118+
@Override
119+
public String getEventDescription() {
120+
return "Changing disk offering for the Shared FileSystem " + id;
121+
}
122+
123+
@Override
124+
public long getEntityOwnerId() {
125+
return CallContext.current().getCallingAccount().getId();
126+
}
127+
128+
@Override
129+
public void execute() throws ResourceAllocationException {
130+
SharedFS sharedFS = sharedFSService.changeSharedFSDiskOffering(this);
131+
if (sharedFS != null) {
132+
ResponseObject.ResponseView respView = getResponseView();
133+
Account caller = CallContext.current().getCallingAccount();
134+
if (_accountService.isRootAdmin(caller.getId())) {
135+
respView = ResponseObject.ResponseView.Full;
136+
}
137+
SharedFSResponse response = _responseGenerator.createSharedFSResponse(respView, sharedFS);
138+
response.setObjectName(SharedFS.class.getSimpleName().toLowerCase());
139+
response.setResponseName(getCommandName());
140+
setResponseObject(response);
141+
} else {
142+
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to change disk offering for the Shared FileSystem");
143+
}
144+
}
145+
}

0 commit comments

Comments
 (0)