Skip to content

Commit 605534b

Browse files
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 72d0546 commit 605534b

95 files changed

Lines changed: 8938 additions & 567 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;
@@ -744,6 +745,18 @@ public class EventTypes {
744745
public static final String EVENT_QUOTA_TARIFF_DELETE = "QUOTA.TARIFF.DELETE";
745746
public static final String EVENT_QUOTA_TARIFF_UPDATE = "QUOTA.TARIFF.UPDATE";
746747

748+
// SharedFS
749+
public static final String EVENT_SHAREDFS_CREATE = "SHAREDFS.CREATE";
750+
public static final String EVENT_SHAREDFS_START = "SHAREDFS.START";
751+
public static final String EVENT_SHAREDFS_UPDATE = "SHAREDFS.UPDATE";
752+
public static final String EVENT_SHAREDFS_CHANGE_SERVICE_OFFERING = "SHAREDFS.CHANGE.SERVICE.OFFERING";
753+
public static final String EVENT_SHAREDFS_CHANGE_DISK_OFFERING = "SHAREDFS.CHANGE.DISK.OFFERING";
754+
public static final String EVENT_SHAREDFS_STOP = "SHAREDFS.STOP";
755+
public static final String EVENT_SHAREDFS_RESTART = "SHAREDFS.RESTART";
756+
public static final String EVENT_SHAREDFS_DESTROY = "SHAREDFS.DESTROY";
757+
public static final String EVENT_SHAREDFS_EXPUNGE = "SHAREDFS.EXPUNGE";
758+
public static final String EVENT_SHAREDFS_RECOVER = "SHAREDFS.RECOVER";
759+
747760
static {
748761

749762
// TODO: need a way to force author adding event types to declare the entity details as well, with out braking
@@ -1203,6 +1216,18 @@ public class EventTypes {
12031216
entityEventDetails.put(EVENT_QUOTA_TARIFF_CREATE, QuotaTariff.class);
12041217
entityEventDetails.put(EVENT_QUOTA_TARIFF_DELETE, QuotaTariff.class);
12051218
entityEventDetails.put(EVENT_QUOTA_TARIFF_UPDATE, QuotaTariff.class);
1219+
1220+
// SharedFS
1221+
entityEventDetails.put(EVENT_SHAREDFS_CREATE, SharedFS.class);
1222+
entityEventDetails.put(EVENT_SHAREDFS_START, SharedFS.class);
1223+
entityEventDetails.put(EVENT_SHAREDFS_STOP, SharedFS.class);
1224+
entityEventDetails.put(EVENT_SHAREDFS_UPDATE, SharedFS.class);
1225+
entityEventDetails.put(EVENT_SHAREDFS_CHANGE_SERVICE_OFFERING, SharedFS.class);
1226+
entityEventDetails.put(EVENT_SHAREDFS_CHANGE_DISK_OFFERING, SharedFS.class);
1227+
entityEventDetails.put(EVENT_SHAREDFS_RESTART, SharedFS.class);
1228+
entityEventDetails.put(EVENT_SHAREDFS_DESTROY, SharedFS.class);
1229+
entityEventDetails.put(EVENT_SHAREDFS_EXPUNGE, SharedFS.class);
1230+
entityEventDetails.put(EVENT_SHAREDFS_RECOVER, SharedFS.class);
12061231
}
12071232

12081233
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
@@ -102,8 +102,12 @@ public interface VolumeApiService {
102102

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

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

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

109113
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";
@@ -432,6 +433,7 @@ public class ApiConstants {
432433
public static final String SIGNATURE_VERSION = "signatureversion";
433434
public static final String SINCE = "since";
434435
public static final String SIZE = "size";
436+
public static final String SIZEGB = "sizegb";
435437
public static final String SNAPSHOT = "snapshot";
436438
public static final String SNAPSHOT_ID = "snapshotid";
437439
public static final String SNAPSHOT_POLICY_ID = "snapshotpolicyid";
@@ -504,6 +506,7 @@ public class ApiConstants {
504506
public static final String VIRTUAL_MACHINE_ID_IP = "vmidipmap";
505507
public static final String VIRTUAL_MACHINE_COUNT = "virtualmachinecount";
506508
public static final String VIRTUAL_MACHINE_TYPE = "virtualmachinetype";
509+
public static final String VIRTUAL_MACHINE_STATE = "vmstate";
507510
public static final String VIRTUAL_MACHINES = "virtualmachines";
508511
public static final String USAGE_ID = "usageid";
509512
public static final String USAGE_TYPE = "usagetype";
@@ -1143,6 +1146,9 @@ public class ApiConstants {
11431146

11441147
public static final String NFS_MOUNT_OPTIONS = "nfsmountopts";
11451148

1149+
public static final String SHAREDFSVM_MIN_CPU_COUNT = "sharedfsvmmincpucount";
1150+
public static final String SHAREDFSVM_MIN_RAM_SIZE = "sharedfsvmminramsize";
1151+
11461152
public static final String PARAMETER_DESCRIPTION_ACTIVATION_RULE = "Quota tariff's activation rule. It can receive a JS script that results in either " +
11471153
"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 " +
11481154
"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

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

553555
BucketResponse createBucketResponse(Bucket bucket);
556+
557+
SharedFSResponse createSharedFSResponse(ResponseView view, SharedFS sharedFS);
554558
}

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
@@ -70,6 +70,8 @@ public void execute() {
7070
response.setInstancesStatsUserOnly((Boolean) capabilities.get(ApiConstants.INSTANCES_STATS_USER_ONLY));
7171
response.setInstancesDisksStatsRetentionEnabled((Boolean) capabilities.get(ApiConstants.INSTANCES_DISKS_STATS_RETENTION_ENABLED));
7272
response.setInstancesDisksStatsRetentionTime((Integer) capabilities.get(ApiConstants.INSTANCES_DISKS_STATS_RETENTION_TIME));
73+
response.setSharedFsVmMinCpuCount((Integer)capabilities.get(ApiConstants.SHAREDFSVM_MIN_CPU_COUNT));
74+
response.setSharedFsVmMinRamSize((Integer)capabilities.get(ApiConstants.SHAREDFSVM_MIN_RAM_SIZE));
7375
response.setObjectName("capability");
7476
response.setResponseName(getCommandName());
7577
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)