Skip to content

Commit b0910fc

Browse files
authored
Add dynamic secondary storage selection (#7659)
1 parent 108651a commit b0910fc

File tree

46 files changed

+2452
-206
lines changed

Some content is hidden

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

46 files changed

+2452
-206
lines changed

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

+10
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@
3636
import com.cloud.exception.InvalidParameterValueException;
3737
import com.cloud.exception.ResourceInUseException;
3838
import com.cloud.exception.ResourceUnavailableException;
39+
import org.apache.cloudstack.api.command.admin.storage.heuristics.CreateSecondaryStorageSelectorCmd;
40+
import org.apache.cloudstack.api.command.admin.storage.heuristics.RemoveSecondaryStorageSelectorCmd;
41+
import org.apache.cloudstack.api.command.admin.storage.heuristics.UpdateSecondaryStorageSelectorCmd;
42+
import org.apache.cloudstack.secstorage.heuristics.Heuristic;
3943
import org.apache.cloudstack.storage.object.ObjectStore;
4044

4145
public interface StorageService {
@@ -112,6 +116,12 @@ public interface StorageService {
112116

113117
StoragePool syncStoragePool(SyncStoragePoolCmd cmd);
114118

119+
Heuristic createSecondaryStorageHeuristic(CreateSecondaryStorageSelectorCmd cmd);
120+
121+
Heuristic updateSecondaryStorageHeuristic(UpdateSecondaryStorageSelectorCmd cmd);
122+
123+
void removeSecondaryStorageHeuristic(RemoveSecondaryStorageSelectorCmd cmd);
124+
115125
ObjectStore discoverObjectStore(String name, String url, String providerName, Map details) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException;
116126

117127
boolean deleteObjectStore(DeleteObjectStoragePoolCmd cmd);

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

+3
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,9 @@ public class ApiConstants {
10611061
public static final String HAS_RULES = "hasrules";
10621062
public static final String OBJECT_STORAGE = "objectstore";
10631063

1064+
public static final String HEURISTIC_RULE = "heuristicrule";
1065+
public static final String HEURISTIC_TYPE_VALID_OPTIONS = "Valid options are: ISO, SNAPSHOT, TEMPLATE and VOLUME.";
1066+
10641067
public static final String MANAGEMENT = "management";
10651068
public static final String IS_VNF = "isvnf";
10661069
public static final String VNF_NICS = "vnfnics";

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

+4
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
import org.apache.cloudstack.api.response.RollingMaintenanceResponse;
105105
import org.apache.cloudstack.api.response.RouterHealthCheckResultResponse;
106106
import org.apache.cloudstack.api.response.SSHKeyPairResponse;
107+
import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse;
107108
import org.apache.cloudstack.api.response.SecurityGroupResponse;
108109
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
109110
import org.apache.cloudstack.api.response.ServiceResponse;
@@ -148,6 +149,7 @@
148149
import org.apache.cloudstack.region.PortableIp;
149150
import org.apache.cloudstack.region.PortableIpRange;
150151
import org.apache.cloudstack.region.Region;
152+
import org.apache.cloudstack.secstorage.heuristics.Heuristic;
151153
import org.apache.cloudstack.storage.object.ObjectStore;
152154
import org.apache.cloudstack.usage.Usage;
153155

@@ -536,6 +538,8 @@ List<TemplateResponse> createTemplateResponses(ResponseView view, VirtualMachine
536538

537539
FirewallResponse createIpv6FirewallRuleResponse(FirewallRule acl);
538540

541+
SecondaryStorageHeuristicsResponse createSecondaryStorageSelectorResponse(Heuristic heuristic);
542+
539543
IpQuarantineResponse createQuarantinedIpsResponse(PublicIpQuarantine publicIp);
540544

541545
ObjectStoreResponse createObjectStoreResponse(ObjectStore os);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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.admin.storage.heuristics;
18+
19+
import com.cloud.user.Account;
20+
import org.apache.cloudstack.acl.RoleType;
21+
import org.apache.cloudstack.api.APICommand;
22+
import org.apache.cloudstack.api.ApiConstants;
23+
import org.apache.cloudstack.api.ApiErrorCode;
24+
import org.apache.cloudstack.api.BaseCmd;
25+
import org.apache.cloudstack.api.Parameter;
26+
import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse;
27+
import org.apache.cloudstack.api.response.ZoneResponse;
28+
import org.apache.cloudstack.api.ServerApiException;
29+
import org.apache.cloudstack.secstorage.heuristics.Heuristic;
30+
31+
import static org.apache.cloudstack.api.ApiConstants.HEURISTIC_TYPE_VALID_OPTIONS;
32+
33+
@APICommand(name = "createSecondaryStorageSelector", description = "Creates a secondary storage selector, described by the heuristic rule.", since = "4.19.0", responseObject =
34+
SecondaryStorageHeuristicsResponse.class, entityType = {Heuristic.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = {RoleType.Admin})
35+
public class CreateSecondaryStorageSelectorCmd extends BaseCmd{
36+
37+
@Parameter(name = ApiConstants.NAME, required = true, type = CommandType.STRING, description = "The name identifying the heuristic rule.")
38+
private String name;
39+
40+
@Parameter(name = ApiConstants.DESCRIPTION, required = true, type = BaseCmd.CommandType.STRING, description = "The description of the heuristic rule.")
41+
private String description;
42+
43+
@Parameter(name = ApiConstants.ZONE_ID, required = true, entityType = ZoneResponse.class, type = BaseCmd.CommandType.UUID, description = "The zone in which the heuristic " +
44+
"rule will be applied.")
45+
private Long zoneId;
46+
47+
@Parameter(name = ApiConstants.TYPE, required = true, type = BaseCmd.CommandType.STRING, description =
48+
"The resource type directed to a specific secondary storage by the selector. " + HEURISTIC_TYPE_VALID_OPTIONS)
49+
private String type;
50+
51+
@Parameter(name = ApiConstants.HEURISTIC_RULE, required = true, type = BaseCmd.CommandType.STRING, description = "The heuristic rule, in JavaScript language. It is required " +
52+
"that it returns the UUID of a secondary storage pool. An example of a rule is `if (snapshot.hypervisorType === 'KVM') { '7832f261-c602-4e8e-8580-2496ffbbc45d'; " +
53+
"}` would allocate all snapshots with the KVM hypervisor to the specified secondary storage UUID.", length = 65535)
54+
private String heuristicRule;
55+
56+
public String getName() {
57+
return name;
58+
}
59+
60+
public String getDescription() {
61+
return description;
62+
}
63+
64+
public Long getZoneId() {
65+
return zoneId;
66+
}
67+
68+
public String getType() {
69+
return type;
70+
}
71+
72+
public String getHeuristicRule() {
73+
return heuristicRule;
74+
}
75+
76+
@Override
77+
public void execute() {
78+
Heuristic heuristic = _storageService.createSecondaryStorageHeuristic(this);
79+
80+
if (heuristic == null) {
81+
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create a secondary storage selector.");
82+
}
83+
84+
SecondaryStorageHeuristicsResponse response = _responseGenerator.createSecondaryStorageSelectorResponse(heuristic);
85+
response.setResponseName(getCommandName());
86+
this.setResponseObject(response);
87+
}
88+
89+
@Override
90+
public long getEntityOwnerId() {
91+
return Account.ACCOUNT_ID_SYSTEM;
92+
}
93+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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.admin.storage.heuristics;
18+
19+
import org.apache.cloudstack.acl.RoleType;
20+
import org.apache.cloudstack.api.APICommand;
21+
import org.apache.cloudstack.api.ApiConstants;
22+
import org.apache.cloudstack.api.BaseListCmd;
23+
import org.apache.cloudstack.api.Parameter;
24+
import org.apache.cloudstack.api.response.ListResponse;
25+
import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse;
26+
import org.apache.cloudstack.api.response.ZoneResponse;
27+
import org.apache.cloudstack.secstorage.heuristics.Heuristic;
28+
29+
import static org.apache.cloudstack.api.ApiConstants.HEURISTIC_TYPE_VALID_OPTIONS;
30+
31+
@APICommand(name = "listSecondaryStorageSelectors", description = "Lists the secondary storage selectors and their rules.", since = "4.19.0", responseObject =
32+
SecondaryStorageHeuristicsResponse.class, requestHasSensitiveInfo = false, entityType = {Heuristic.class}, responseHasSensitiveInfo = false, authorized = {RoleType.Admin})
33+
public class ListSecondaryStorageSelectorsCmd extends BaseListCmd {
34+
35+
@Parameter(name = ApiConstants.ZONE_ID, required = true, entityType = ZoneResponse.class, type = CommandType.UUID, description = "The zone ID to be used in the search filter.")
36+
private Long zoneId;
37+
38+
@Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, description =
39+
"Whether to filter the selectors by type and, if so, which one. " + HEURISTIC_TYPE_VALID_OPTIONS)
40+
private String type;
41+
42+
@Parameter(name = ApiConstants.SHOW_REMOVED, type = CommandType.BOOLEAN, description = "Show removed heuristics.")
43+
private boolean showRemoved = false;
44+
45+
public Long getZoneId() {
46+
return zoneId;
47+
}
48+
49+
public String getType() {
50+
return type;
51+
}
52+
53+
public boolean isShowRemoved() {
54+
return showRemoved;
55+
}
56+
57+
@Override
58+
public void execute() {
59+
ListResponse<SecondaryStorageHeuristicsResponse> response = _queryService.listSecondaryStorageSelectors(this);
60+
response.setResponseName(getCommandName());
61+
this.setResponseObject(response);
62+
}
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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.admin.storage.heuristics;
18+
19+
import com.cloud.user.Account;
20+
import org.apache.cloudstack.acl.RoleType;
21+
import org.apache.cloudstack.api.APICommand;
22+
import org.apache.cloudstack.api.ApiConstants;
23+
import org.apache.cloudstack.api.BaseCmd;
24+
import org.apache.cloudstack.api.Parameter;
25+
import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse;
26+
import org.apache.cloudstack.api.response.SuccessResponse;
27+
import org.apache.cloudstack.secstorage.heuristics.Heuristic;
28+
29+
@APICommand(name = "removeSecondaryStorageSelector", description = "Removes an existing secondary storage selector.", since = "4.19.0", responseObject =
30+
SecondaryStorageHeuristicsResponse.class, requestHasSensitiveInfo = false, entityType = {Heuristic.class}, responseHasSensitiveInfo = false, authorized = {RoleType.Admin})
31+
public class RemoveSecondaryStorageSelectorCmd extends BaseCmd {
32+
@Parameter(name = ApiConstants.ID, type = BaseCmd.CommandType.UUID, entityType = SecondaryStorageHeuristicsResponse.class, required = true,
33+
description = "The unique identifier of the secondary storage selector to be removed.")
34+
private Long id;
35+
36+
public Long getId() {
37+
return id;
38+
}
39+
40+
@Override
41+
public void execute() {
42+
_storageService.removeSecondaryStorageHeuristic(this);
43+
final SuccessResponse response = new SuccessResponse();
44+
response.setResponseName(getCommandName());
45+
response.setSuccess(true);
46+
setResponseObject(response);
47+
}
48+
49+
@Override
50+
public long getEntityOwnerId() {
51+
return Account.ACCOUNT_ID_SYSTEM;
52+
}
53+
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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.admin.storage.heuristics;
18+
19+
import com.cloud.user.Account;
20+
import org.apache.cloudstack.acl.RoleType;
21+
import org.apache.cloudstack.api.APICommand;
22+
import org.apache.cloudstack.api.ApiConstants;
23+
import org.apache.cloudstack.api.ApiErrorCode;
24+
import org.apache.cloudstack.api.BaseCmd;
25+
import org.apache.cloudstack.api.Parameter;
26+
import org.apache.cloudstack.api.ServerApiException;
27+
import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse;
28+
import org.apache.cloudstack.secstorage.heuristics.Heuristic;
29+
30+
@APICommand(name = "updateSecondaryStorageSelector", description = "Updates an existing secondary storage selector.", since = "4.19.0", responseObject =
31+
SecondaryStorageHeuristicsResponse.class, requestHasSensitiveInfo = false, entityType = {Heuristic.class}, responseHasSensitiveInfo = false, authorized = {RoleType.Admin})
32+
public class UpdateSecondaryStorageSelectorCmd extends BaseCmd {
33+
@Parameter(name = ApiConstants.ID, type = BaseCmd.CommandType.UUID, entityType = SecondaryStorageHeuristicsResponse.class, required = true,
34+
description = "The unique identifier of the secondary storage selector.")
35+
private Long id;
36+
37+
@Parameter(name = ApiConstants.HEURISTIC_RULE, required = true, type = BaseCmd.CommandType.STRING, description = "The heuristic rule, in JavaScript language. It is required " +
38+
"that it returns the UUID of a secondary storage pool. An example of a rule is `if (snapshot.hypervisorType === 'KVM') { '7832f261-c602-4e8e-8580-2496ffbbc45d'; " +
39+
"}` would allocate all snapshots with the KVM hypervisor to the specified secondary storage UUID.", length = 65535)
40+
private String heuristicRule;
41+
42+
public Long getId() {
43+
return id;
44+
}
45+
46+
public String getHeuristicRule() {
47+
return heuristicRule;
48+
}
49+
50+
@Override
51+
public void execute() {
52+
Heuristic heuristic = _storageService.updateSecondaryStorageHeuristic(this);
53+
54+
if (heuristic == null) {
55+
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update the secondary storage selector.");
56+
}
57+
58+
SecondaryStorageHeuristicsResponse response = _responseGenerator.createSecondaryStorageSelectorResponse(heuristic);
59+
response.setResponseName(getCommandName());
60+
this.setResponseObject(response);
61+
}
62+
63+
@Override
64+
public long getEntityOwnerId() {
65+
return Account.ACCOUNT_ID_SYSTEM;
66+
}
67+
}

0 commit comments

Comments
 (0)