Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dynamic secondary storage selection #7659

Merged
merged 16 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
397a3aa
Add dynamic secondary storage selection
BryanMLima Jun 20, 2023
a412315
Add missing newlines at the end of files
BryanMLima Jun 21, 2023
55dc636
Add account preset variable with domain details
BryanMLima Aug 2, 2023
266ca31
Merge branch 'main' of github.com:apache/cloudstack into dynamic-ss-s…
BryanMLima Aug 3, 2023
2dee071
Fix unit tests
BryanMLima Aug 3, 2023
ad8a94c
Merge branch 'main' of github.com:apache/cloudstack into dynamic-ss-s…
BryanMLima Aug 15, 2023
54c5b87
Merge branch 'main' of github.com:apache/cloudstack into dynamic-ss-s…
BryanMLima Sep 26, 2023
a746a3f
Merge branch 'main' of github.com:apache/cloudstack into dynamic-ss-s…
BryanMLima Oct 23, 2023
0d5782c
Merge branch 'dynamic-ss-selection' of github.com:scclouds/cloudstack…
BryanMLima Oct 23, 2023
ee6efaa
Merge branch 'main' of github.com:apache/cloudstack into dynamic-ss-s…
BryanMLima Oct 27, 2023
ebb7d37
Merge branch 'main' of github.com:apache/cloudstack into dynamic-ss-s…
BryanMLima Nov 10, 2023
2f45694
Address reviews
BryanMLima Nov 10, 2023
829c070
Address reviews and change heuristic purpose to heuristic type
BryanMLima Nov 13, 2023
f0d734f
Merge branch 'main' of github.com:apache/cloudstack into dynamic-ss-s…
BryanMLima Nov 14, 2023
a77a828
Merge branch 'main' of github.com:apache/cloudstack into dynamic-ss-s…
BryanMLima Nov 17, 2023
70e1705
Merge branch 'main' of github.com:apache/cloudstack into dynamic-ss-s…
BryanMLima Dec 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions api/src/main/java/com/cloud/storage/StorageService.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceInUseException;
import com.cloud.exception.ResourceUnavailableException;
import org.apache.cloudstack.api.command.admin.storage.heuristics.CreateSecondaryStorageSelectorCmd;
import org.apache.cloudstack.api.command.admin.storage.heuristics.RemoveSecondaryStorageSelectorCmd;
import org.apache.cloudstack.api.command.admin.storage.heuristics.UpdateSecondaryStorageSelectorCmd;
import org.apache.cloudstack.secstorage.heuristics.Heuristic;

public interface StorageService {
/**
Expand Down Expand Up @@ -109,4 +113,9 @@ public interface StorageService {

StoragePool syncStoragePool(SyncStoragePoolCmd cmd);

Heuristic createSecondaryStorageHeuristic(CreateSecondaryStorageSelectorCmd cmd);

Heuristic updateSecondaryStorageHeuristic(UpdateSecondaryStorageSelectorCmd cmd);

void removeSecondaryStorageHeuristic(RemoveSecondaryStorageSelectorCmd cmd);
}
4 changes: 4 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 @@ -1036,6 +1036,10 @@ public class ApiConstants {
public static final String SOURCE_NAT_IP_ID = "sourcenatipaddressid";
public static final String HAS_RULES = "hasrules";

public static final String HEURISTIC_RULE = "heuristicrule";

public static final String HEURISTIC_PURPOSE_VALID_OPTIONS = "Valid options are: ISO, SNAPSHOT, TEMPLATE and VOLUME.";

/**
* This enum specifies IO Drivers, each option controls specific policies on I/O.
* Qemu guests support "threads" and "native" options Since 0.8.8 ; "io_uring" is supported Since 6.3.0 (QEMU 5.0).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
import org.apache.cloudstack.api.response.RollingMaintenanceResponse;
import org.apache.cloudstack.api.response.RouterHealthCheckResultResponse;
import org.apache.cloudstack.api.response.SSHKeyPairResponse;
import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse;
import org.apache.cloudstack.api.response.SecurityGroupResponse;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import org.apache.cloudstack.api.response.ServiceResponse;
Expand Down Expand Up @@ -143,6 +144,7 @@
import org.apache.cloudstack.region.PortableIp;
import org.apache.cloudstack.region.PortableIpRange;
import org.apache.cloudstack.region.Region;
import org.apache.cloudstack.secstorage.heuristics.Heuristic;
import org.apache.cloudstack.usage.Usage;

import com.cloud.capacity.Capacity;
Expand Down Expand Up @@ -526,4 +528,6 @@ List<TemplateResponse> createTemplateResponses(ResponseView view, VirtualMachine
DirectDownloadCertificateHostStatusResponse createDirectDownloadCertificateProvisionResponse(Long certificateId, Long hostId, Pair<Boolean, String> result);

FirewallResponse createIpv6FirewallRuleResponse(FirewallRule acl);

SecondaryStorageHeuristicsResponse createSecondaryStorageSelectorResponse(Heuristic heuristic);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// 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.heuristics;

import com.cloud.user.Account;
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.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.secstorage.heuristics.Heuristic;

import static org.apache.cloudstack.api.ApiConstants.HEURISTIC_PURPOSE_VALID_OPTIONS;

@APICommand(name = "createSecondaryStorageSelector", description = "Creates a secondary storage selector, described by the heuristic rule.", responseObject =
BryanMLima marked this conversation as resolved.
Show resolved Hide resolved
SecondaryStorageHeuristicsResponse.class, entityType = {Heuristic.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = {RoleType.Admin})
public class CreateSecondaryStorageSelectorCmd extends BaseCmd{

@Parameter(name = ApiConstants.NAME, required = true, type = CommandType.STRING, description = "The name identifying the heuristic rule.")
private String name;

@Parameter(name = ApiConstants.DESCRIPTION, required = true, type = BaseCmd.CommandType.STRING, description = "The description of the heuristic rule.")
private String description;

@Parameter(name = ApiConstants.ZONE_ID, required = true, entityType = ZoneResponse.class, type = BaseCmd.CommandType.UUID, description = "The zone in which the heuristic " +
"rule will be applied.")
private Long zoneId;

@Parameter(name = ApiConstants.PURPOSE, required = true, type = BaseCmd.CommandType.STRING, description =
BryanMLima marked this conversation as resolved.
Show resolved Hide resolved
"The resource type directed to a specific secondary storage by the selector. " + HEURISTIC_PURPOSE_VALID_OPTIONS)
private String purpose;

@Parameter(name = ApiConstants.HEURISTIC_RULE, required = true, type = BaseCmd.CommandType.STRING, description = "The heuristic rule, in JavaScript language. It is required " +
"that it returns the UUID of a secondary storage pool.", length = 65535)
BryanMLima marked this conversation as resolved.
Show resolved Hide resolved
private String heuristicRule;

public String getName() {
return name;
}

public String getDescription() {
return description;
}

public Long getZoneId() {
return zoneId;
}

public String getPurpose() {
return purpose;
}

public String getHeuristicRule() {
return heuristicRule;
}

@Override
public void execute() {
Heuristic heuristic = _storageService.createSecondaryStorageHeuristic(this);

if (heuristic == null) {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create a secondary storage selector.");
}

SecondaryStorageHeuristicsResponse response = _responseGenerator.createSecondaryStorageSelectorResponse(heuristic);
response.setResponseName(getCommandName());
this.setResponseObject(response);
}

@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
}
}
DaanHoogland marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// 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.heuristics;

import org.apache.cloudstack.acl.RoleType;
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.SecondaryStorageHeuristicsResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.secstorage.heuristics.Heuristic;

import static org.apache.cloudstack.api.ApiConstants.HEURISTIC_PURPOSE_VALID_OPTIONS;

@APICommand(name = "listSecondaryStorageSelectors", description = "Lists the secondary storage selectors and their rules.", responseObject = SecondaryStorageHeuristicsResponse.class,
BryanMLima marked this conversation as resolved.
Show resolved Hide resolved
requestHasSensitiveInfo = false, entityType = {Heuristic.class}, responseHasSensitiveInfo = false, authorized = {RoleType.Admin})
public class ListSecondaryStorageSelectorsCmd extends BaseListCmd {

@Parameter(name = ApiConstants.ZONE_ID, required = true, entityType = ZoneResponse.class, type = CommandType.UUID, description = "The zone ID to be used in the search filter.")
private Long zoneId;

@Parameter(name = ApiConstants.PURPOSE, type = CommandType.STRING, description =
"Whether to filter the selectors by purpose and, if so, which one. " + HEURISTIC_PURPOSE_VALID_OPTIONS)
private String purpose;

@Parameter(name = ApiConstants.SHOW_REMOVED, type = CommandType.BOOLEAN, description = "Show removed heuristics.")
private boolean showRemoved = false;

public Long getZoneId() {
return zoneId;
}

public String getPurpose() {
return purpose;
}

public boolean isShowRemoved() {
return showRemoved;
}

@Override
public void execute() {
ListResponse<SecondaryStorageHeuristicsResponse> response = _queryService.listSecondaryStorageSelectors(this);
response.setResponseName(getCommandName());
this.setResponseObject(response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// 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.heuristics;

import com.cloud.user.Account;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.secstorage.heuristics.Heuristic;

@APICommand(name = "removeSecondaryStorageSelector", description = "Removes an existing secondary storage selector.", responseObject = SecondaryStorageHeuristicsResponse.class,
BryanMLima marked this conversation as resolved.
Show resolved Hide resolved
requestHasSensitiveInfo = false, entityType = {Heuristic.class}, responseHasSensitiveInfo = false, authorized = {RoleType.Admin})
public class RemoveSecondaryStorageSelectorCmd extends BaseCmd {
@Parameter(name = ApiConstants.ID, type = BaseCmd.CommandType.UUID, entityType = SecondaryStorageHeuristicsResponse.class, required = true,
description = "The unique identifier of the secondary storage selector to be removed.")
private Long id;

public Long getId() {
return id;
}

@Override
public void execute() {
_storageService.removeSecondaryStorageHeuristic(this);
final SuccessResponse response = new SuccessResponse();
response.setResponseName(getCommandName());
response.setSuccess(true);
setResponseObject(response);
}

@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// 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.heuristics;

import com.cloud.user.Account;
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.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse;
import org.apache.cloudstack.secstorage.heuristics.Heuristic;

@APICommand(name = "updateSecondaryStorageSelector", description = "Updates an existing secondary storage selector.", responseObject = SecondaryStorageHeuristicsResponse.class,
BryanMLima marked this conversation as resolved.
Show resolved Hide resolved
requestHasSensitiveInfo = false, entityType = {Heuristic.class}, responseHasSensitiveInfo = false, authorized = {RoleType.Admin})
public class UpdateSecondaryStorageSelectorCmd extends BaseCmd {
@Parameter(name = ApiConstants.ID, type = BaseCmd.CommandType.UUID, entityType = SecondaryStorageHeuristicsResponse.class, required = true,
description = "The unique identifier of the secondary storage selector.")
private Long id;

@Parameter(name = ApiConstants.HEURISTIC_RULE, required = true, type = BaseCmd.CommandType.STRING, description = "The heuristic rule, in JavaScript language. It is required " +
"that it returns the UUID of a secondary storage pool.", length = 65535)
private String heuristicRule;

public Long getId() {
return id;
}

public String getHeuristicRule() {
return heuristicRule;
}

@Override
public void execute() {
Heuristic heuristic = _storageService.updateSecondaryStorageHeuristic(this);

if (heuristic == null) {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update the secondary storage selector.");
}

SecondaryStorageHeuristicsResponse response = _responseGenerator.createSecondaryStorageSelectorResponse(heuristic);
response.setResponseName(getCommandName());
this.setResponseObject(response);
}

@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
}
}
DaanHoogland marked this conversation as resolved.
Show resolved Hide resolved
Loading