Merge remote-tracking branch 'origin/main' into add-description-for-secondary-ip-addresses

This commit is contained in:
Erik Böck 2026-04-14 13:18:07 -03:00
commit c19b7cbc73
340 changed files with 14777 additions and 3012 deletions

20
.codespellrc Normal file
View File

@ -0,0 +1,20 @@
# 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.
[codespell]
ignore-words = .github/linters/codespell.txt
skip = systemvm/agent/noVNC/*,ui/package.json,ui/package-lock.json,ui/public/js/less.min.js,ui/public/locales/*.json,server/src/test/java/org/apache/cloudstack/network/ssl/CertServiceTest.java,test/integration/smoke/test_ssl_offloading.py

1
.github/CODEOWNERS vendored
View File

@ -17,6 +17,7 @@
/plugins/storage/volume/linstor @rp-
/plugins/storage/volume/storpool @slavkap
/plugins/storage/volume/ontap @rajiv1 @sandeeplocharla @piyush5 @suryag
.pre-commit-config.yaml @jbampton
/.github/linters/ @jbampton

View File

@ -22,8 +22,19 @@
version: 2
updates:
- package-ecosystem: "maven" # See documentation for possible values
directory: "/" # Location of package manifests
- package-ecosystem: "github-actions"
directory: "/"
open-pull-requests-limit: 2
schedule:
interval: "weekly"
groups:
github-actions-dependencies:
patterns:
- "*"
cooldown:
default-days: 7
- package-ecosystem: "maven"
directory: "/"
schedule:
interval: "daily"
cooldown:

View File

@ -30,7 +30,7 @@ jobs:
build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- name: Set up JDK 17
uses: actions/setup-java@v5

View File

@ -217,7 +217,7 @@ jobs:
smoke/test_list_volumes"]
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
fetch-depth: 0

View File

@ -32,7 +32,7 @@ jobs:
name: codecov
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
fetch-depth: 0

View File

@ -35,7 +35,7 @@ jobs:
language: ["actions"]
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:

View File

@ -47,7 +47,7 @@ jobs:
- name: Set Docker repository name
run: echo "DOCKER_REPOSITORY=apache" >> $GITHUB_ENV
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- name: Set ACS version
run: echo "ACS_VERSION=$(grep '<version>' pom.xml | head -2 | tail -1 | cut -d'>' -f2 |cut -d'<' -f1)" >> $GITHUB_ENV

View File

@ -32,7 +32,7 @@ jobs:
name: Main Sonar JaCoCo Build
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
fetch-depth: 0

View File

@ -32,7 +32,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Check Out
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Install
run: |
python -m pip install --upgrade pip

View File

@ -30,7 +30,7 @@ jobs:
build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- name: Set up JDK 17
uses: actions/setup-java@v5
with:

View File

@ -33,7 +33,7 @@ jobs:
name: Sonar JaCoCo Coverage
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
ref: "refs/pull/${{ github.event.number }}/merge"
fetch-depth: 0

View File

@ -31,7 +31,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- name: Set up Node
uses: actions/setup-node@v5

View File

@ -162,17 +162,15 @@ repos:
- id: forbid-submodules
- id: mixed-line-ending
- id: trailing-whitespace
files: ^(LICENSE|NOTICE)$|\.(bat|cfg|cs|css|gitignore|header|in|install|java|md|properties|py|rb|rc|sh|sql|te|template|txt|ucls|vue|xml|xsl|yaml|yml)$|^cloud-cli/bindir/cloud-tool$|^debian/changelog$
files: ^(LICENSE|NOTICE)$|README$|\.(bat|cfg|config|cs|css|erb|gitignore|header|in|install|java|md|properties|py|rb|rc|sh|sql|svg|te|template|txt|ucls|vue|xml|xsl|yaml|yml)$|^cloud-cli/bindir/cloud-tool$|^debian/changelog$
args: [--markdown-linebreak-ext=md]
exclude: ^services/console-proxy/rdpconsole/src/test/doc/freerdp-debug-log\.txt$
- repo: https://github.com/codespell-project/codespell
rev: v2.4.1
rev: v2.4.2
hooks:
- id: codespell
name: run codespell
description: Check spelling with codespell
args: [--ignore-words=.github/linters/codespell.txt]
exclude: ^systemvm/agent/noVNC/|^ui/package\.json$|^ui/package-lock\.json$|^ui/public/js/less\.min\.js$|^ui/public/locales/.*[^n].*\.json$|^server/src/test/java/org/apache/cloudstack/network/ssl/CertServiceTest.java$|^test/integration/smoke/test_ssl_offloading.py$
- repo: https://github.com/pycqa/flake8
rev: 7.0.0
hooks:
@ -186,7 +184,7 @@ repos:
description: check Markdown files with markdownlint
args: [--config=.github/linters/.markdown-lint.yml]
types: [markdown]
files: \.(md|mdown|markdown)$
files: \.md$
- repo: https://github.com/adrienverge/yamllint
rev: v1.37.1
hooks:

View File

@ -457,3 +457,6 @@ iscsi.session.cleanup.enabled=false
# Instance conversion VIRT_V2V_TMPDIR env var
#convert.instance.env.virtv2v.tmpdir=
# Time, in seconds, to wait before retrying to rebase during the incremental snapshot process.
# incremental.snapshot.retry.rebase.wait=60

View File

@ -885,6 +885,11 @@ public class AgentProperties{
*/
public static final Property<Boolean> CREATE_FULL_CLONE = new Property<>("create.full.clone", false);
/**
* Time, in seconds, to wait before retrying to rebase during the incremental snapshot process.
* */
public static final Property<Integer> INCREMENTAL_SNAPSHOT_RETRY_REBASE_WAIT = new Property<>("incremental.snapshot.retry.rebase.wait", 60);
public static class Property <T>{
private String name;

View File

@ -26,10 +26,13 @@ public final class BucketTO {
private String secretKey;
private long accountId;
public BucketTO(Bucket bucket) {
this.name = bucket.getName();
this.accessKey = bucket.getAccessKey();
this.secretKey = bucket.getSecretKey();
this.accountId = bucket.getAccountId();
}
public BucketTO(String name) {
@ -47,4 +50,8 @@ public final class BucketTO {
public String getSecretKey() {
return this.secretKey;
}
public long getAccountId() {
return this.accountId;
}
}

View File

@ -33,6 +33,7 @@ public class NicTO extends NetworkTO {
boolean dpdkEnabled;
Integer mtu;
Long networkId;
boolean enabled;
String networkSegmentName;
@ -154,4 +155,12 @@ public class NicTO extends NetworkTO {
public void setNetworkSegmentName(String networkSegmentName) {
this.networkSegmentName = networkSegmentName;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View File

@ -82,7 +82,7 @@ public interface ProjectService {
Project updateProject(long id, String name, String displayText, String newOwnerName, Long userId, Role newRole) throws ResourceAllocationException;
boolean addAccountToProject(long projectId, String accountName, String email, Long projectRoleId, Role projectRoleType);
boolean addAccountToProject(long projectId, String accountName, String email, Long projectRoleId, Role projectRoleType) throws ResourceAllocationException;
boolean deleteAccountFromProject(long projectId, String accountName);
@ -100,6 +100,6 @@ public interface ProjectService {
Project findByProjectAccountIdIncludingRemoved(long projectAccountId);
boolean addUserToProject(Long projectId, String username, String email, Long projectRoleId, Role projectRole);
boolean addUserToProject(Long projectId, String username, String email, Long projectRoleId, Role projectRole) throws ResourceAllocationException;
}

View File

@ -71,7 +71,6 @@ import org.apache.cloudstack.api.command.user.vm.GetVMPasswordCmd;
import org.apache.cloudstack.api.command.user.vmgroup.UpdateVMGroupCmd;
import org.apache.cloudstack.config.Configuration;
import org.apache.cloudstack.config.ConfigurationGroup;
import org.apache.cloudstack.framework.config.ConfigKey;
import com.cloud.alert.Alert;
import com.cloud.capacity.Capacity;
@ -108,14 +107,6 @@ import com.cloud.vm.VirtualMachineProfile;
public interface ManagementService {
static final String Name = "management-server";
ConfigKey<Boolean> JsInterpretationEnabled = new ConfigKey<>("Hidden"
, Boolean.class
, "js.interpretation.enabled"
, "false"
, "Enable/Disable all JavaScript interpretation related functionalities to create or update Javascript rules."
, false
, ConfigKey.Scope.Global);
/**
* returns the a map of the names/values in the configuration table
*
@ -534,6 +525,4 @@ public interface ManagementService {
boolean removeManagementServer(RemoveManagementServerCmd cmd);
void checkJsInterpretationAllowedIfNeededForParameterValue(String paramName, boolean paramValue);
}

View File

@ -23,9 +23,10 @@ import org.apache.cloudstack.api.InternalIdentity;
public interface VMTemplateStorageResourceAssoc extends InternalIdentity {
public static enum Status {
UNKNOWN, DOWNLOAD_ERROR, NOT_DOWNLOADED, DOWNLOAD_IN_PROGRESS, DOWNLOADED, ABANDONED, UPLOADED, NOT_UPLOADED, UPLOAD_ERROR, UPLOAD_IN_PROGRESS, CREATING, CREATED, BYPASSED
UNKNOWN, DOWNLOAD_ERROR, NOT_DOWNLOADED, DOWNLOAD_IN_PROGRESS, DOWNLOADED, ABANDONED, LIMIT_REACHED, UPLOADED, NOT_UPLOADED, UPLOAD_ERROR, UPLOAD_IN_PROGRESS, CREATING, CREATED, BYPASSED
}
List<Status> ERROR_DOWNLOAD_STATES = List.of(Status.DOWNLOAD_ERROR, Status.ABANDONED, Status.LIMIT_REACHED, Status.UNKNOWN);
List<Status> PENDING_DOWNLOAD_STATES = List.of(Status.NOT_DOWNLOADED, Status.DOWNLOAD_IN_PROGRESS);
String getInstallPath();

View File

@ -138,6 +138,8 @@ public interface AccountService {
Long finalizeAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly);
Long finalizeAccountId(Long accountId, String accountName, Long domainId, Long projectId);
/**
* returns the user account object for a given user id
* @param userId user id

View File

@ -30,6 +30,7 @@ import com.cloud.exception.ResourceAllocationException;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.ServiceOffering;
import com.cloud.template.VirtualMachineTemplate;
import org.apache.cloudstack.resourcelimit.Reserver;
public interface ResourceLimitService {
@ -191,6 +192,7 @@ public interface ResourceLimitService {
*/
public void checkResourceLimit(Account account, ResourceCount.ResourceType type, long... count) throws ResourceAllocationException;
public void checkResourceLimitWithTag(Account account, ResourceCount.ResourceType type, String tag, long... count) throws ResourceAllocationException;
public void checkResourceLimitWithTag(Account account, Long domainId, boolean considerSystemAccount, ResourceCount.ResourceType type, String tag, long... count) throws ResourceAllocationException;
/**
* Gets the count of resources for a resource type and account
@ -251,12 +253,12 @@ public interface ResourceLimitService {
List<String> getResourceLimitStorageTags(DiskOffering diskOffering);
void updateTaggedResourceLimitsAndCountsForAccounts(List<AccountResponse> responses, String tag);
void updateTaggedResourceLimitsAndCountsForDomains(List<DomainResponse> responses, String tag);
void checkVolumeResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException;
void checkVolumeResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering, List<Reserver> reservations) throws ResourceAllocationException;
List<String> getResourceLimitStorageTagsForResourceCountOperation(Boolean display, DiskOffering diskOffering);
void checkVolumeResourceLimitForDiskOfferingChange(Account owner, Boolean display, Long currentSize, Long newSize,
DiskOffering currentOffering, DiskOffering newOffering) throws ResourceAllocationException;
DiskOffering currentOffering, DiskOffering newOffering, List<Reserver> reservations) throws ResourceAllocationException;
void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException;
void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering, List<Reserver> reservations) throws ResourceAllocationException;
void incrementVolumeResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
void decrementVolumeResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
@ -273,25 +275,23 @@ public interface ResourceLimitService {
void incrementVolumePrimaryStorageResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
void decrementVolumePrimaryStorageResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
void checkVmResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template) throws ResourceAllocationException;
void checkVmResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Reserver> reservations) throws ResourceAllocationException;
void incrementVmResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template);
void decrementVmResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template);
void checkVmResourceLimitsForServiceOfferingChange(Account owner, Boolean display, Long currentCpu, Long newCpu,
Long currentMemory, Long newMemory, ServiceOffering currentOffering, ServiceOffering newOffering, VirtualMachineTemplate template) throws ResourceAllocationException;
Long currentMemory, Long newMemory, ServiceOffering currentOffering, ServiceOffering newOffering, VirtualMachineTemplate template, List<Reserver> reservations) throws ResourceAllocationException;
void checkVmResourceLimitsForTemplateChange(Account owner, Boolean display, ServiceOffering offering,
VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate) throws ResourceAllocationException;
VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate, List<Reserver> reservations) throws ResourceAllocationException;
void checkVmCpuResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu) throws ResourceAllocationException;
void incrementVmCpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu);
void decrementVmCpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu);
void checkVmMemoryResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory) throws ResourceAllocationException;
void incrementVmMemoryResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory);
void decrementVmMemoryResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory);
void checkVmGpuResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long gpu) throws ResourceAllocationException;
void incrementVmGpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long gpu);
void decrementVmGpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long gpu);
long recalculateDomainResourceCount(final long domainId, final ResourceType type, String tag);
}

View File

@ -162,4 +162,6 @@ public interface Nic extends Identity, InternalIdentity {
String getIPv6Address();
Integer getMtu();
boolean isEnabled();
}

View File

@ -52,6 +52,7 @@ public class NicProfile implements InternalIdentity, Serializable {
boolean defaultNic;
Integer networkRate;
boolean isSecurityGroupEnabled;
boolean enabled;
Integer orderIndex;
@ -87,6 +88,7 @@ public class NicProfile implements InternalIdentity, Serializable {
broadcastType = network.getBroadcastDomainType();
trafficType = network.getTrafficType();
format = nic.getAddressFormat();
enabled = nic.isEnabled();
iPv4Address = nic.getIPv4Address();
iPv4Netmask = nic.getIPv4Netmask();
@ -414,6 +416,14 @@ public class NicProfile implements InternalIdentity, Serializable {
this.ipv4AllocationRaceCheck = ipv4AllocationRaceCheck;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
//
// OTHER METHODS
//

View File

@ -40,6 +40,7 @@ import org.apache.cloudstack.api.command.user.vm.ScaleVMCmd;
import org.apache.cloudstack.api.command.user.vm.StartVMCmd;
import org.apache.cloudstack.api.command.user.vm.UpdateDefaultNicForVMCmd;
import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd;
import org.apache.cloudstack.api.command.user.vm.UpdateVmNicCmd;
import org.apache.cloudstack.api.command.user.vm.UpdateVmNicIpCmd;
import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd;
import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd;
@ -152,6 +153,8 @@ public interface UserVmService {
*/
UserVm updateNicIpForVirtualMachine(UpdateVmNicIpCmd cmd);
UserVm updateVirtualMachineNic(UpdateVmNicCmd cmd);
UserVm recoverVirtualMachine(RecoverVMCmd cmd) throws ResourceAllocationException;
/**
@ -524,6 +527,7 @@ public interface UserVmService {
* @param userId user ID
* @param serviceOffering service offering for the imported VM
* @param sshPublicKey ssh key for the imported VM
* @param guestOsId guest OS ID for the imported VM (if not passed, then the guest OS of the template will be used)
* @param hostName the name for the imported VM
* @param hypervisorType hypervisor type for the imported VM
* @param customParameters details for the imported VM
@ -533,7 +537,7 @@ public interface UserVmService {
* @throws InsufficientCapacityException in case of errors
*/
UserVm importVM(final DataCenter zone, final Host host, final VirtualMachineTemplate template, final String instanceNameInternal, final String displayName, final Account owner, final String userData, final Account caller, final Boolean isDisplayVm, final String keyboard,
final long accountId, final long userId, final ServiceOffering serviceOffering, final String sshPublicKey,
final long accountId, final long userId, final ServiceOffering serviceOffering, final String sshPublicKey, final Long guestOsId,
final String hostName, final HypervisorType hypervisorType, final Map<String, String> customParameters,
final VirtualMachine.PowerState powerState, final LinkedHashMap<String, List<NicProfile>> networkNicMap) throws InsufficientCapacityException;

View File

@ -124,6 +124,9 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, Partition,
s_fsm.addTransition(new Transition<State, Event>(State.Stopping, VirtualMachine.Event.StopRequested, State.Stopping, null));
s_fsm.addTransition(new Transition<State, Event>(State.Stopping, VirtualMachine.Event.AgentReportShutdowned, State.Stopped, Arrays.asList(new Impact[]{Impact.USAGE})));
s_fsm.addTransition(new Transition<State, Event>(State.Expunging, VirtualMachine.Event.OperationFailed, State.Expunging,null));
// Note: In addition to the Stopped -> Error transition for failed VM creation,
// a VM can also transition from Expunging to Error on OperationFailedToError.
s_fsm.addTransition(new Transition<State, Event>(State.Expunging, VirtualMachine.Event.OperationFailedToError, State.Error, null));
s_fsm.addTransition(new Transition<State, Event>(State.Expunging, VirtualMachine.Event.ExpungeOperation, State.Expunging,null));
s_fsm.addTransition(new Transition<State, Event>(State.Error, VirtualMachine.Event.DestroyRequested, State.Expunging, null));
s_fsm.addTransition(new Transition<State, Event>(State.Error, VirtualMachine.Event.ExpungeOperation, State.Expunging, null));

View File

@ -127,8 +127,8 @@ public enum ApiCommandResourceType {
}
public static ApiCommandResourceType fromString(String value) {
if (StringUtils.isNotEmpty(value) && EnumUtils.isValidEnum(ApiCommandResourceType.class, value)) {
return valueOf(value);
if (StringUtils.isNotBlank(value) && EnumUtils.isValidEnumIgnoreCase(ApiCommandResourceType.class, value)) {
return EnumUtils.getEnumIgnoreCase(ApiCommandResourceType.class, value);
}
return null;
}

View File

@ -20,6 +20,7 @@ public class ApiConstants {
public static final String ACCOUNT = "account";
public static final String ACCOUNTS = "accounts";
public static final String ACCOUNT_NAME = "accountname";
public static final String ACCOUNT_STATE_TO_SHOW = "accountstatetoshow";
public static final String ACCOUNT_TYPE = "accounttype";
public static final String ACCOUNT_ID = "accountid";
public static final String ACCOUNT_IDS = "accountids";
@ -508,6 +509,7 @@ public class ApiConstants {
public static final String REPAIR = "repair";
public static final String REPETITION_ALLOWED = "repetitionallowed";
public static final String REQUIRES_HVM = "requireshvm";
public static final String RESERVED_RESOURCE_DETAILS = "reservedresourcedetails";
public static final String RESOURCES = "resources";
public static final String RESOURCE_COUNT = "resourcecount";
public static final String RESOURCE_NAME = "resourcename";

View File

@ -343,6 +343,8 @@ public interface ResponseGenerator {
UserVm findUserVmById(Long vmId);
UserVm findUserVmByNicId(Long nicId);
Volume findVolumeById(Long volumeId);
Account findAccountByNameDomain(String accountName, Long domainId);

View File

@ -30,6 +30,7 @@ import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ResponseObject;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.GuestOSResponse;
import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.api.response.NetworkResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
@ -171,6 +172,13 @@ public class ImportVmCmd extends ImportUnmanagedInstanceCmd {
description = "(only for importing VMs from VMware to KVM) optional - if true, forces virt-v2v conversions to write directly on the provided storage pool (avoid using temporary conversion pool).")
private Boolean forceConvertToPool;
@Parameter(name = ApiConstants.OS_ID,
type = CommandType.UUID,
entityType = GuestOSResponse.class,
since = "4.22.1",
description = "(only for importing VMs from VMware to KVM) optional - the ID of the guest OS for the imported VM.")
private Long guestOsId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -268,6 +276,10 @@ public class ImportVmCmd extends ImportUnmanagedInstanceCmd {
return BooleanUtils.toBooleanDefaultIfNull(forceConvertToPool, false);
}
public Long getGuestOsId() {
return guestOsId;
}
@Override
public String getEventDescription() {
String vmName = getName();

View File

@ -18,6 +18,7 @@ package org.apache.cloudstack.api.command.user.account;
import java.util.List;
import com.cloud.exception.ResourceAllocationException;
import org.apache.cloudstack.api.ApiArgValidator;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.BaseCmd;
@ -106,7 +107,7 @@ public class AddAccountToProjectCmd extends BaseAsyncCmd {
/////////////////////////////////////////////////////
@Override
public void execute() {
public void execute() throws ResourceAllocationException {
if (accountName == null && email == null) {
throw new InvalidParameterValueException("Either accountName or email is required");
}

View File

@ -17,6 +17,7 @@
package org.apache.cloudstack.api.command.user.account;
import com.cloud.exception.ResourceAllocationException;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiArgValidator;
@ -111,7 +112,7 @@ public class AddUserToProjectCmd extends BaseAsyncCmd {
/////////////////////////////////////////////////////
@Override
public void execute() {
public void execute() throws ResourceAllocationException {
validateInput();
boolean result = _projectService.addUserToProject(getProjectId(), getUsername(), getEmail(), getProjectRoleId(), getRoleType());
if (result) {

View File

@ -20,6 +20,7 @@ package org.apache.cloudstack.api.command.user.backup;
import javax.inject.Inject;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
@ -53,6 +54,7 @@ public class RestoreVolumeFromBackupAndAttachToVMCmd extends BaseAsyncCmd {
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ACL
@Parameter(name = ApiConstants.BACKUP_ID,
type = CommandType.UUID,
entityType = BackupResponse.class,
@ -60,12 +62,14 @@ public class RestoreVolumeFromBackupAndAttachToVMCmd extends BaseAsyncCmd {
description = "ID of the Instance backup")
private Long backupId;
@ACL
@Parameter(name = ApiConstants.VOLUME_ID,
type = CommandType.STRING,
required = true,
description = "ID of the volume backed up")
private String volumeUuid;
@ACL
@Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID,
type = CommandType.UUID,
entityType = UserVmResponse.class,

View File

@ -45,6 +45,11 @@ public class ListGuestOsCmd extends BaseListCmd {
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = GuestOSResponse.class, description = "List by OS type ID")
private Long id;
@Parameter(name = ApiConstants.IDS, type = CommandType.LIST, collectionType = CommandType.UUID,
entityType = GuestOSResponse.class, since = "4.22.1",
description = "Comma separated list of OS types")
private List<Long> ids;
@Parameter(name = ApiConstants.OS_CATEGORY_ID, type = CommandType.UUID, entityType = GuestOSCategoryResponse.class, description = "List by OS Category ID")
private Long osCategoryId;
@ -63,6 +68,10 @@ public class ListGuestOsCmd extends BaseListCmd {
return id;
}
public List<Long> getIds() {
return ids;
}
public Long getOsCategoryId() {
return osCategoryId;
}

View File

@ -19,6 +19,7 @@ package org.apache.cloudstack.api.command.user.job;
import java.util.Date;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiArgValidator;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListAccountResourcesCmd;
import org.apache.cloudstack.api.Parameter;
@ -40,6 +41,12 @@ public class ListAsyncJobsCmd extends BaseListAccountResourcesCmd {
@Parameter(name = ApiConstants.MANAGEMENT_SERVER_ID, type = CommandType.UUID, entityType = ManagementServerResponse.class, description = "The id of the management server", since="4.19")
private Long managementServerId;
@Parameter(name = ApiConstants.RESOURCE_ID, validations = {ApiArgValidator.UuidString}, type = CommandType.STRING, description = "the ID of the resource associated with the job", since="4.22.1")
private String resourceId;
@Parameter(name = ApiConstants.RESOURCE_TYPE, type = CommandType.STRING, description = "the type of the resource associated with the job", since="4.22.1")
private String resourceType;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -52,6 +59,14 @@ public class ListAsyncJobsCmd extends BaseListAccountResourcesCmd {
return managementServerId;
}
public String getResourceId() {
return resourceId;
}
public String getResourceType() {
return resourceType;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -16,8 +16,8 @@
// under the License.
package org.apache.cloudstack.api.command.user.job;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiArgValidator;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
@ -34,9 +34,15 @@ public class QueryAsyncJobResultCmd extends BaseCmd {
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.JOB_ID, type = CommandType.UUID, entityType = AsyncJobResponse.class, required = true, description = "The ID of the asynchronous job")
@Parameter(name = ApiConstants.JOB_ID, type = CommandType.UUID, entityType = AsyncJobResponse.class, description = "The ID of the asynchronous job")
private Long id;
@Parameter(name = ApiConstants.RESOURCE_ID, validations = {ApiArgValidator.UuidString}, type = CommandType.STRING, description = "the ID of the resource associated with the job", since="4.22.1")
private String resourceId;
@Parameter(name = ApiConstants.RESOURCE_TYPE, type = CommandType.STRING, description = "the type of the resource associated with the job", since="4.22.1")
private String resourceType;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -45,6 +51,14 @@ public class QueryAsyncJobResultCmd extends BaseCmd {
return id;
}
public String getResourceId() {
return resourceId;
}
public String getResourceType() {
return resourceType;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -51,6 +51,7 @@ public class CreateVMFromBackupCmd extends BaseDeployVMCmd {
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ACL
@Parameter(name = ApiConstants.BACKUP_ID,
type = CommandType.UUID,
entityType = BackupResponse.class,

View File

@ -0,0 +1,95 @@
// 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.vm;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.ACL;
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.response.NicResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.context.CallContext;
import com.cloud.event.EventTypes;
import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
import java.util.ArrayList;
import java.util.EnumSet;
@APICommand(name = "updateVmNic", description = "Updates the specified VM NIC", responseObject = NicResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
authorized = { RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User })
public class UpdateVmNicCmd extends BaseAsyncCmd {
@ACL
@Parameter(name = ApiConstants.NIC_ID, type = CommandType.UUID, entityType = NicResponse.class, required = true, description = "NIC ID")
private Long nicId;
@Parameter(name = ApiConstants.ENABLED, type = CommandType.BOOLEAN, description = "If true, sets the NIC state to UP; otherwise, sets the NIC state to DOWN")
private Boolean enabled;
public Long getNicId() {
return nicId;
}
public Boolean isEnabled() {
return enabled;
}
@Override
public String getEventType() {
return EventTypes.EVENT_NIC_UPDATE;
}
@Override
public String getEventDescription() {
return String.format("Updating NIC %s.", getResourceUuid(ApiConstants.NIC_ID));
}
@Override
public long getEntityOwnerId() {
UserVm vm = _responseGenerator.findUserVmByNicId(nicId);
if (vm == null) {
return Account.ACCOUNT_ID_SYSTEM;
}
return vm.getAccountId();
}
@Override
public void execute() {
CallContext.current().setEventDetails(String.format("NIC ID: %s", getResourceUuid(ApiConstants.NIC_ID)));
UserVm result = _userVmService.updateVirtualMachineNic(this);
ArrayList<ApiConstants.VMDetails> dc = new ArrayList<>();
dc.add(ApiConstants.VMDetails.valueOf("nics"));
EnumSet<ApiConstants.VMDetails> details = EnumSet.copyOf(dc);
if (result != null){
UserVmResponse response = _responseGenerator.createUserVmResponse(ResponseObject.ResponseView.Restricted, "virtualmachine", details, result).get(0);
response.setResponseName(getCommandName());
this.setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update NIC from VM.");
}
}
}

View File

@ -32,6 +32,7 @@ import org.apache.cloudstack.api.response.DiskOfferingResponse;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.ProjectResponse;
import org.apache.cloudstack.api.response.SnapshotResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.VolumeResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
@ -109,6 +110,13 @@ public class CreateVolumeCmd extends BaseAsyncCreateCustomIdCmd implements UserC
description = "The ID of the Instance; to be used with snapshot Id, Instance to which the volume gets attached after creation")
private Long virtualMachineId;
@Parameter(name = ApiConstants.STORAGE_ID,
type = CommandType.UUID,
entityType = StoragePoolResponse.class,
description = "Storage pool ID to create the volume in. Cannot be used with the snapshotid parameter.",
authorized = {RoleType.Admin})
private Long storageId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -153,6 +161,13 @@ public class CreateVolumeCmd extends BaseAsyncCreateCustomIdCmd implements UserC
return projectId;
}
public Long getStorageId() {
if (snapshotId != null && storageId != null) {
throw new IllegalArgumentException("StorageId parameter cannot be specified with the SnapshotId parameter.");
}
return storageId;
}
public Boolean getDisplayVolume() {
return displayVolume;
}

View File

@ -46,7 +46,6 @@ public class CreateStaticRouteCmd extends BaseAsyncCreateCmd {
@Parameter(name = ApiConstants.GATEWAY_ID,
type = CommandType.UUID,
entityType = PrivateGatewayResponse.class,
required = true,
description = "The gateway ID we are creating static route for. Mutually exclusive with the nexthop parameter")
private Long gatewayId;

View File

@ -85,6 +85,12 @@ public class ExtensionResponse extends BaseResponse {
@Param(description = "Removal timestamp of the extension, if applicable")
private Date removed;
@SerializedName(ApiConstants.RESERVED_RESOURCE_DETAILS)
@Param(description = "Resource detail names as comma separated string that should be reserved and not visible " +
"to end users",
since = "4.22.1")
protected String reservedResourceDetails;
public ExtensionResponse(String id, String name, String description, String type) {
this.id = id;
this.name = name;
@ -179,4 +185,8 @@ public class ExtensionResponse extends BaseResponse {
public void setRemoved(Date removed) {
this.removed = removed;
}
public void setReservedResourceDetails(String reservedResourceDetails) {
this.reservedResourceDetails = reservedResourceDetails;
}
}

View File

@ -146,6 +146,10 @@ public class NicResponse extends BaseResponse {
@Param(description = "Public IP address associated with this NIC via Static NAT rule")
private String publicIp;
@SerializedName(ApiConstants.ENABLED)
@Param(description = "whether the NIC is enabled or not")
private Boolean isEnabled;
public void setVmId(String vmId) {
this.vmId = vmId;
}
@ -416,4 +420,12 @@ public class NicResponse extends BaseResponse {
public void setPublicIp(String publicIp) {
this.publicIp = publicIp;
}
public Boolean getEnabled() {
return isEnabled;
}
public void setEnabled(Boolean enabled) {
isEnabled = enabled;
}
}

View File

@ -51,6 +51,14 @@ public class UnmanagedInstanceResponse extends BaseResponse {
@Param(description = "The name of the host to which Instance belongs")
private String hostName;
@SerializedName(ApiConstants.HYPERVISOR)
@Param(description = "The hypervisor to which Instance belongs")
private String hypervisor;
@SerializedName(ApiConstants.HYPERVISOR_VERSION)
@Param(description = "The hypervisor version of the host to which Instance belongs")
private String hypervisorVersion;
@SerializedName(ApiConstants.POWER_STATE)
@Param(description = "The power state of the Instance")
private String powerState;
@ -140,6 +148,22 @@ public class UnmanagedInstanceResponse extends BaseResponse {
this.hostName = hostName;
}
public String getHypervisor() {
return hypervisor;
}
public void setHypervisor(String hypervisor) {
this.hypervisor = hypervisor;
}
public String getHypervisorVersion() {
return hypervisorVersion;
}
public void setHypervisorVersion(String hypervisorVersion) {
this.hypervisorVersion = hypervisorVersion;
}
public String getPowerState() {
return powerState;
}

View File

@ -17,8 +17,11 @@
package org.apache.cloudstack.extension;
import java.util.List;
public interface ExtensionHelper {
Long getExtensionIdForCluster(long clusterId);
Extension getExtension(long id);
Extension getExtensionForCluster(long clusterId);
List<String> getExtensionReservedResourceDetails(long extensionId);
}

View File

@ -0,0 +1,30 @@
// 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.resourcelimit;
/**
* Interface implemented by <code>CheckedReservation</code>.
* </br></br>
* This is defined in <code>cloud-api</code> to allow methods declared in modules that do not depend on <code>cloud-server</code>
* to receive <code>CheckedReservations</code> as parameters.
*/
public interface Reserver extends AutoCloseable {
void close();
}

View File

@ -25,17 +25,28 @@ import org.apache.cloudstack.api.command.admin.volume.ImportVolumeCmd;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.VolumeForImportResponse;
import org.apache.cloudstack.api.response.VolumeResponse;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import java.util.Arrays;
import java.util.List;
public interface VolumeImportUnmanageService extends PluggableService {
public interface VolumeImportUnmanageService extends PluggableService, Configurable {
List<Hypervisor.HypervisorType> SUPPORTED_HYPERVISORS =
Arrays.asList(Hypervisor.HypervisorType.KVM, Hypervisor.HypervisorType.VMware);
List<Storage.StoragePoolType> SUPPORTED_STORAGE_POOL_TYPES_FOR_KVM = Arrays.asList(Storage.StoragePoolType.NetworkFilesystem,
Storage.StoragePoolType.Filesystem, Storage.StoragePoolType.RBD);
Storage.StoragePoolType.Filesystem, Storage.StoragePoolType.RBD, Storage.StoragePoolType.SharedMountPoint);
ConfigKey<Boolean> AllowImportVolumeWithBackingFile = new ConfigKey<>(Boolean.class,
"allow.import.volume.with.backing.file",
"Advanced",
"false",
"If enabled, allows QCOW2 volumes with backing files to be imported or unmanaged",
true,
ConfigKey.Scope.Global,
null);
ListResponse<VolumeForImportResponse> listVolumesForImport(ListVolumesForImportCmd cmd);

View File

@ -55,6 +55,9 @@ public class UnmanagedInstanceTO {
private String hostName;
private String hypervisorType;
private String hostHypervisorVersion;
private List<Disk> disks;
private List<Nic> nics;
@ -168,6 +171,22 @@ public class UnmanagedInstanceTO {
this.hostName = hostName;
}
public String getHypervisorType() {
return hypervisorType;
}
public void setHypervisorType(String hypervisorType) {
this.hypervisorType = hypervisorType;
}
public String getHostHypervisorVersion() {
return hostHypervisorVersion;
}
public void setHostHypervisorVersion(String hostHypervisorVersion) {
this.hostHypervisorVersion = hostHypervisorVersion;
}
public List<Disk> getDisks() {
return disks;
}

View File

@ -26,6 +26,8 @@ import static com.cloud.hypervisor.Hypervisor.HypervisorType.VMware;
public interface UnmanagedVMsManager extends VmImportService, UnmanageVMService, PluggableService, Configurable {
String VM_IMPORT_DEFAULT_TEMPLATE_NAME = "system-default-vm-import-dummy-template.iso";
String KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME = "kvm-default-vm-import-dummy-template";
ConfigKey<Boolean> UnmanageVMPreserveNic = new ConfigKey<>("Advanced", Boolean.class, "unmanage.vm.preserve.nics", "false",
"If set to true, do not remove VM nics (and its MAC addresses) when unmanaging a VM, leaving them allocated but not reserved. " +
"If set to false, nics are removed and MAC addresses can be reassigned", true, ConfigKey.Scope.Zone);

View File

@ -16,6 +16,7 @@
// under the License.
package org.apache.cloudstack.api.command.test;
import com.cloud.exception.ResourceAllocationException;
import junit.framework.Assert;
import junit.framework.TestCase;
@ -149,6 +150,8 @@ public class AddAccountToProjectCmdTest extends TestCase {
addAccountToProjectCmd.execute();
} catch (InvalidParameterValueException exception) {
Assert.assertEquals("Either accountName or email is required", exception.getLocalizedMessage());
} catch (ResourceAllocationException exception) {
Assert.fail();
}
}

View File

@ -121,6 +121,11 @@
<artifactId>cloud-plugin-storage-volume-adaptive</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-storage-volume-ontap</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-storage-volume-solidfire</artifactId>

View File

@ -0,0 +1,27 @@
// 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 com.cloud.agent.api;
public class UpdateVmNicAnswer extends Answer {
public UpdateVmNicAnswer() {
}
public UpdateVmNicAnswer(UpdateVmNicCommand cmd, boolean success, String result) {
super(cmd, success, result);
}
}

View File

@ -0,0 +1,51 @@
// 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 com.cloud.agent.api;
public class UpdateVmNicCommand extends Command {
String nicMacAddress;
String instanceName;
Boolean enabled;
@Override
public boolean executeInSequence() {
return true;
}
protected UpdateVmNicCommand() {
}
public UpdateVmNicCommand(String nicMacAdderss, String instanceName, Boolean enabled) {
this.nicMacAddress = nicMacAdderss;
this.instanceName = instanceName;
this.enabled = enabled;
}
public String getNicMacAddress() {
return nicMacAddress;
}
public String getVmName() {
return instanceName;
}
public Boolean isEnabled() {
return enabled;
}
}

View File

@ -140,7 +140,7 @@ public class DownloadAnswer extends Answer {
}
public Long getTemplateSize() {
return templateSize;
return templateSize == 0 ? templatePhySicalSize : templateSize;
}
public void setTemplatePhySicalSize(long templatePhySicalSize) {

View File

@ -52,6 +52,7 @@ import com.cloud.storage.StorageLayer;
import com.cloud.utils.Pair;
import com.cloud.utils.UriUtils;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.HttpClientCloudStackUserAgent;
import com.cloud.utils.net.Proxy;
/**
@ -125,6 +126,7 @@ public class HttpTemplateDownloader extends ManagedContextRunnable implements Te
GetMethod request = new GetMethod(downloadUrl);
request.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, myretryhandler);
request.setFollowRedirects(followRedirects);
request.getParams().setParameter(HttpMethodParams.USER_AGENT, HttpClientCloudStackUserAgent.CLOUDSTACK_USER_AGENT);
return request;
}

View File

@ -18,8 +18,11 @@
//
package com.cloud.storage.template;
import com.cloud.storage.StorageLayer;
import com.cloud.utils.UriUtils;
import com.cloud.utils.net.HttpClientCloudStackUserAgent;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpMethodRetryHandler;
@ -59,6 +62,7 @@ public class MetalinkTemplateDownloader extends TemplateDownloaderBase implement
GetMethod request = new GetMethod(downloadUrl);
request.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, myretryhandler);
request.setFollowRedirects(followRedirects);
request.getParams().setParameter(HttpMethodParams.USER_AGENT, HttpClientCloudStackUserAgent.CLOUDSTACK_USER_AGENT);
if (!toFileSet) {
String[] parts = downloadUrl.split("/");
String filename = parts[parts.length - 1];

View File

@ -44,6 +44,7 @@ import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.lang3.StringUtils;
import com.cloud.storage.StorageLayer;
import com.cloud.utils.net.HttpClientCloudStackUserAgent;
public class SimpleHttpMultiFileDownloader extends ManagedContextRunnable implements TemplateDownloader {
private static final MultiThreadedHttpConnectionManager s_httpClientManager = new MultiThreadedHttpConnectionManager();
@ -95,6 +96,7 @@ public class SimpleHttpMultiFileDownloader extends ManagedContextRunnable implem
GetMethod request = new GetMethod(downloadUrl);
request.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, retryHandler);
request.setFollowRedirects(followRedirects);
request.getParams().setParameter(HttpMethodParams.USER_AGENT, HttpClientCloudStackUserAgent.CLOUDSTACK_USER_AGENT);
return request;
}
@ -141,6 +143,7 @@ public class SimpleHttpMultiFileDownloader extends ManagedContextRunnable implem
continue;
}
HeadMethod headMethod = new HeadMethod(downloadUrl);
headMethod.getParams().setParameter(HttpMethodParams.USER_AGENT, HttpClientCloudStackUserAgent.CLOUDSTACK_USER_AGENT);
try {
if (client.executeMethod(headMethod) != HttpStatus.SC_OK) {
continue;

View File

@ -34,6 +34,7 @@ public class RestoreBackupCommand extends Command {
private List<String> backupVolumesUUIDs;
private List<PrimaryDataStoreTO> restoreVolumePools;
private List<String> restoreVolumePaths;
private List<Long> restoreVolumeSizes;
private List<String> backupFiles;
private String diskType;
private Boolean vmExists;
@ -92,6 +93,14 @@ public class RestoreBackupCommand extends Command {
this.restoreVolumePaths = restoreVolumePaths;
}
public List<Long> getRestoreVolumeSizes() {
return restoreVolumeSizes;
}
public void setRestoreVolumeSizes(List<Long> restoreVolumeSizes) {
this.restoreVolumeSizes = restoreVolumeSizes;
}
public List<String> getBackupFiles() {
return backupFiles;
}

View File

@ -21,6 +21,7 @@ package org.apache.cloudstack.direct.download;
import com.cloud.utils.UriUtils;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.utils.security.DigestHelper;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
@ -33,6 +34,7 @@ import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public abstract class DirectTemplateDownloaderImpl implements DirectTemplateDownloader {
@ -128,15 +130,14 @@ public abstract class DirectTemplateDownloaderImpl implements DirectTemplateDown
*/
protected File createTemporaryDirectoryAndFile(String downloadDir) {
createFolder(downloadDir);
return new File(downloadDir + File.separator + getFileNameFromUrl());
return new File(downloadDir + File.separator + getTemporaryFileName());
}
/**
* Return filename from url
* Return filename from the temporary download file
*/
public String getFileNameFromUrl() {
String[] urlParts = url.split("/");
return urlParts[urlParts.length - 1];
public String getTemporaryFileName() {
return String.format("%s.%s", UUID.randomUUID(), FilenameUtils.getExtension(url));
}
@Override

View File

@ -19,6 +19,7 @@
package org.apache.cloudstack.direct.download;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@ -32,6 +33,7 @@ import java.util.Map;
import com.cloud.utils.Pair;
import com.cloud.utils.UriUtils;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.HttpClientCloudStackUserAgent;
import com.cloud.utils.storage.QCOW2Utils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.httpclient.HttpClient;
@ -39,6 +41,7 @@ import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.HeadMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.io.IOUtils;
public class HttpDirectTemplateDownloader extends DirectTemplateDownloaderImpl {
@ -68,6 +71,7 @@ public class HttpDirectTemplateDownloader extends DirectTemplateDownloaderImpl {
protected GetMethod createRequest(String downloadUrl, Map<String, String> headers) {
GetMethod request = new GetMethod(downloadUrl);
request.setFollowRedirects(this.isFollowRedirects());
request.getParams().setParameter(HttpMethodParams.USER_AGENT, HttpClientCloudStackUserAgent.CLOUDSTACK_USER_AGENT);
if (MapUtils.isNotEmpty(headers)) {
for (String key : headers.keySet()) {
request.setRequestHeader(key, headers.get(key));
@ -111,6 +115,7 @@ public class HttpDirectTemplateDownloader extends DirectTemplateDownloaderImpl {
public boolean checkUrl(String url) {
HeadMethod httpHead = new HeadMethod(url);
httpHead.setFollowRedirects(this.isFollowRedirects());
httpHead.getParams().setParameter(HttpMethodParams.USER_AGENT, HttpClientCloudStackUserAgent.CLOUDSTACK_USER_AGENT);
try {
int responseCode = client.executeMethod(httpHead);
if (responseCode != HttpStatus.SC_OK) {

View File

@ -97,7 +97,7 @@ public class MetalinkDirectTemplateDownloader extends DirectTemplateDownloaderIm
DirectTemplateDownloader urlDownloader = createDownloaderForMetalinks(getUrl(), getTemplateId(), getDestPoolPath(),
getChecksum(), headers, connectTimeout, soTimeout, null, temporaryDownloadPath);
try {
setDownloadedFilePath(downloadDir + File.separator + getFileNameFromUrl());
setDownloadedFilePath(downloadDir + File.separator + getTemporaryFileName());
File f = new File(getDownloadedFilePath());
if (f.exists()) {
f.delete();

View File

@ -69,7 +69,7 @@ public class NfsDirectTemplateDownloader extends DirectTemplateDownloaderImpl {
String mount = String.format(mountCommand, srcHost + ":" + srcPath, "/mnt/" + mountSrcUuid);
Script.runSimpleBashScript(mount);
String downloadDir = getDestPoolPath() + File.separator + getDirectDownloadTempPath(getTemplateId());
setDownloadedFilePath(downloadDir + File.separator + getFileNameFromUrl());
setDownloadedFilePath(downloadDir + File.separator + getTemporaryFileName());
Script.runSimpleBashScript("cp /mnt/" + mountSrcUuid + srcPath + " " + getDownloadedFilePath());
Script.runSimpleBashScript("umount /mnt/" + mountSrcUuid);
return new Pair<>(true, getDownloadedFilePath());

View File

@ -19,6 +19,9 @@
package org.apache.cloudstack.storage.command;
import com.cloud.configuration.Resource;
import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
public class TemplateOrVolumePostUploadCommand {
long entityId;
@ -185,6 +188,11 @@ public class TemplateOrVolumePostUploadCommand {
this.description = description;
}
public void setDefaultMaxSecondaryStorageInBytes(long defaultMaxSecondaryStorageInBytes) {
this.defaultMaxSecondaryStorageInGB = defaultMaxSecondaryStorageInBytes != Resource.RESOURCE_UNLIMITED ?
ByteScaleUtils.bytesToGibibytes(defaultMaxSecondaryStorageInBytes) : Resource.RESOURCE_UNLIMITED;
}
public void setDefaultMaxSecondaryStorageInGB(long defaultMaxSecondaryStorageInGB) {
this.defaultMaxSecondaryStorageInGB = defaultMaxSecondaryStorageInGB;
}

View File

@ -28,6 +28,7 @@ public class UploadStatusCommand extends Command {
}
private String entityUuid;
private EntityType entityType;
private Boolean abort;
protected UploadStatusCommand() {
}
@ -37,6 +38,11 @@ public class UploadStatusCommand extends Command {
this.entityType = entityType;
}
public UploadStatusCommand(String entityUuid, EntityType entityType, Boolean abort) {
this(entityUuid, entityType);
this.abort = abort;
}
public String getEntityUuid() {
return entityUuid;
}
@ -45,6 +51,10 @@ public class UploadStatusCommand extends Command {
return entityType;
}
public Boolean getAbort() {
return abort;
}
@Override
public boolean executeInSequence() {
return false;

View File

@ -230,6 +230,8 @@ public interface VirtualMachineManager extends Manager {
Boolean updateDefaultNicForVM(VirtualMachine vm, Nic nic, Nic defaultNic);
boolean updateVmNic(VirtualMachine vm, Nic nic, Boolean enabled) throws ResourceUnavailableException;
/**
* @param vm
* @param network

View File

@ -310,7 +310,7 @@ public interface NetworkOrchestrationService {
void removeDhcpServiceInSubnet(Nic nic);
boolean resourceCountNeedsUpdate(NetworkOffering ntwkOff, ACLType aclType);
boolean isResourceCountUpdateNeeded(NetworkOffering networkOffering);
void prepareAllNicsForMigration(VirtualMachineProfile vm, DeployDestination dest);

View File

@ -120,7 +120,7 @@ public interface VolumeOrchestrationService {
void destroyVolume(Volume volume);
DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, Long minIops, Long maxIops, VirtualMachine vm, VirtualMachineTemplate template,
Account owner, Long deviceId);
Account owner, Long deviceId, boolean incrementResourceCount);
VolumeInfo createVolumeOnPrimaryStorage(VirtualMachine vm, VolumeInfo volume, HypervisorType rootDiskHyperType, StoragePool storagePool) throws NoTransitionException;

View File

@ -21,6 +21,7 @@ import static org.apache.cloudstack.framework.config.ConfigKey.Scope.Cluster;
import com.cloud.deploy.DeploymentPlanner;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.utils.component.Manager;
import com.cloud.vm.VMInstanceVO;
import org.apache.cloudstack.framework.config.ConfigKey;
@ -32,6 +33,8 @@ import java.util.List;
*/
public interface HighAvailabilityManager extends Manager {
List<StoragePoolType> LIBVIRT_STORAGE_POOL_TYPES_WITH_HA_SUPPORT = List.of(StoragePoolType.NetworkFilesystem, StoragePoolType.SharedMountPoint);
ConfigKey<Boolean> ForceHA = new ConfigKey<>("Advanced", Boolean.class, "force.ha", "false",
"Force High-Availability to happen even if the VM says no.", true, Cluster);

View File

@ -17,6 +17,7 @@
package com.cloud.vm;
import static com.cloud.configuration.ConfigurationManagerImpl.EXPOSE_ERRORS_TO_USER;
import static com.cloud.configuration.ConfigurationManagerImpl.MIGRATE_VM_ACROSS_CLUSTERS;
import java.lang.reflect.Field;
@ -49,7 +50,6 @@ import javax.inject.Inject;
import javax.naming.ConfigurationException;
import javax.persistence.EntityExistsException;
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
@ -153,6 +153,8 @@ import com.cloud.agent.api.UnPlugNicAnswer;
import com.cloud.agent.api.UnPlugNicCommand;
import com.cloud.agent.api.UnmanageInstanceCommand;
import com.cloud.agent.api.UnregisterVMCommand;
import com.cloud.agent.api.UpdateVmNicAnswer;
import com.cloud.agent.api.UpdateVmNicCommand;
import com.cloud.agent.api.VmDiskStatsEntry;
import com.cloud.agent.api.VmNetworkStatsEntry;
import com.cloud.agent.api.VmStatsEntry;
@ -307,7 +309,6 @@ import com.cloud.vm.snapshot.VMSnapshotVO;
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
import com.google.gson.Gson;
public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMachineManager, VmWorkJobHandler, Listener, Configurable {
public static final String VM_WORK_JOB_HANDLER = VirtualMachineManagerImpl.class.getSimpleName();
@ -585,7 +586,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
Long deviceId = dataDiskDeviceIds.get(index++);
String volumeName = deviceId == null ? "DATA-" + persistedVm.getId() : "DATA-" + persistedVm.getId() + "-" + String.valueOf(deviceId);
volumeMgr.allocateRawVolume(Type.DATADISK, volumeName, dataDiskOfferingInfo.getDiskOffering(), dataDiskOfferingInfo.getSize(),
dataDiskOfferingInfo.getMinIops(), dataDiskOfferingInfo.getMaxIops(), persistedVm, template, owner, deviceId);
dataDiskOfferingInfo.getMinIops(), dataDiskOfferingInfo.getMaxIops(), persistedVm, template, owner, deviceId, true);
}
}
if (datadiskTemplateToDiskOfferingMap != null && !datadiskTemplateToDiskOfferingMap.isEmpty()) {
@ -595,7 +596,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
long diskOfferingSize = diskOffering.getDiskSize() / (1024 * 1024 * 1024);
VMTemplateVO dataDiskTemplate = _templateDao.findById(dataDiskTemplateToDiskOfferingMap.getKey());
volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + persistedVm.getId() + "-" + String.valueOf( diskNumber), diskOffering, diskOfferingSize, null, null,
persistedVm, dataDiskTemplate, owner, diskNumber);
persistedVm, dataDiskTemplate, owner, diskNumber, true);
diskNumber++;
}
}
@ -625,7 +626,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
String rootVolumeName = String.format("ROOT-%s", vm.getId());
if (template.getFormat() == ImageFormat.ISO) {
volumeMgr.allocateRawVolume(Type.ROOT, rootVolumeName, rootDiskOfferingInfo.getDiskOffering(), rootDiskOfferingInfo.getSize(),
rootDiskOfferingInfo.getMinIops(), rootDiskOfferingInfo.getMaxIops(), vm, template, owner, null);
rootDiskOfferingInfo.getMinIops(), rootDiskOfferingInfo.getMaxIops(), vm, template, owner, null, true);
} else if (Arrays.asList(ImageFormat.BAREMETAL, ImageFormat.EXTERNAL).contains(template.getFormat())) {
logger.debug("{} has format [{}]. Skipping ROOT volume [{}] allocation.", template, template.getFormat(), rootVolumeName);
} else {
@ -931,10 +932,22 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
public void start(final String vmUuid, final Map<VirtualMachineProfile.Param, Object> params, final DeploymentPlan planToDeploy, final DeploymentPlanner planner) {
try {
advanceStart(vmUuid, params, planToDeploy, planner);
} catch (ConcurrentOperationException | InsufficientCapacityException e) {
throw new CloudRuntimeException(String.format("Unable to start a VM [%s] due to [%s].", vmUuid, e.getMessage()), e).add(VirtualMachine.class, vmUuid);
} catch (ConcurrentOperationException e) {
final CallContext cctxt = CallContext.current();
final Account account = cctxt.getCallingAccount();
if (canExposeError(account)) {
throw new CloudRuntimeException(String.format("Unable to start a VM [%s] due to [%s].", vmUuid, e.getMessage()), e).add(VirtualMachine.class, vmUuid);
}
throw new CloudRuntimeException(String.format("Unable to start a VM [%s] due to concurrent operation.", vmUuid), e).add(VirtualMachine.class, vmUuid);
} catch (final InsufficientCapacityException e) {
final CallContext cctxt = CallContext.current();
final Account account = cctxt.getCallingAccount();
if (canExposeError(account)) {
throw new CloudRuntimeException(String.format("Unable to start a VM [%s] due to [%s].", vmUuid, e.getMessage()), e).add(VirtualMachine.class, vmUuid);
}
throw new CloudRuntimeException(String.format("Unable to start a VM [%s] due to insufficient capacity.", vmUuid), e).add(VirtualMachine.class, vmUuid);
} catch (final ResourceUnavailableException e) {
if (e.getScope() != null && e.getScope().equals(VirtualRouter.class)){
if (e.getScope() != null && e.getScope().equals(VirtualRouter.class)) {
Account callingAccount = CallContext.current().getCallingAccount();
String errorSuffix = (callingAccount != null && callingAccount.getType() == Account.Type.ADMIN) ?
String.format("Failure: %s", e.getMessage()) :
@ -1365,6 +1378,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
final HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
Throwable lastKnownError = null;
boolean canRetry = true;
ExcludeList avoids = null;
try {
@ -1388,7 +1402,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
int retry = StartRetry.value();
while (retry-- != 0) {
logger.debug("Instance start attempt #{}", (StartRetry.value() - retry));
int attemptNumber = StartRetry.value() - retry;
logger.debug("Instance start attempt #{}", attemptNumber);
if (reuseVolume) {
final List<VolumeVO> vols = _volsDao.findReadyRootVolumesByInstance(vm.getId());
@ -1454,8 +1469,13 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
reuseVolume = false;
continue;
}
throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId(),
areAffinityGroupsAssociated(vmProfile));
String message = String.format("Unable to create a deployment for %s after %s attempts", vmProfile, attemptNumber);
if (canExposeError(account) && lastKnownError != null) {
message += String.format(" Last known error: %s", lastKnownError.getMessage());
throw new CloudRuntimeException(message, lastKnownError);
} else {
throw new InsufficientServerCapacityException(message, DataCenter.class, plan.getDataCenterId(), areAffinityGroupsAssociated(vmProfile));
}
}
avoids.addHost(dest.getHost().getId());
@ -1623,11 +1643,15 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
throw new ExecutionException("Unable to start VM:" + vm.getUuid() + " due to error in finalizeStart, not retrying");
}
}
logger.info("Unable to start VM on {} due to {}", dest.getHost(), (startAnswer == null ? " no start answer" : startAnswer.getDetails()));
String msg = String.format("Unable to start VM on %s due to %s", dest.getHost(), startAnswer == null ? "no start command answer" : startAnswer.getDetails());
lastKnownError = new ExecutionException(msg);
if (startAnswer != null && startAnswer.getContextParam("stopRetry") != null) {
logger.error(msg, lastKnownError);
break;
}
logger.debug(msg, lastKnownError);
} catch (OperationTimedoutException e) {
logger.debug("Unable to send the start command to host {} failed to start VM: {}", dest.getHost(), vm);
if (e.isActive()) {
@ -1637,6 +1661,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
throw new AgentUnavailableException("Unable to start " + vm.getHostName(), destHostId, e);
} catch (final ResourceUnavailableException e) {
logger.warn("Unable to contact resource.", e);
lastKnownError = e;
if (!avoids.add(e)) {
if (e.getScope() == Volume.class || e.getScope() == Nic.class) {
throw e;
@ -1693,10 +1718,22 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
}
if (startedVm == null) {
throw new CloudRuntimeException("Unable to start Instance '" + vm.getHostName() + "' (" + vm.getUuid() + "), see management server log for details");
String messageTmpl = "Unable to start Instance '%s' (%s)%s";
String details;
if (canExposeError(account) && lastKnownError != null) {
details = ": " + lastKnownError.getMessage();
} else {
details = ", see management server log for details";
}
String message = String.format(messageTmpl, vm.getHostName(), vm.getUuid(), details);
throw new CloudRuntimeException(message, lastKnownError);
}
}
private boolean canExposeError(Account account) {
return (account != null && account.getType() == Account.Type.ADMIN) || Boolean.TRUE.equals(EXPOSE_ERRORS_TO_USER.value());
}
protected void updateStartCommandWithExternalDetails(Host host, VirtualMachineTO vmTO, StartCommand command) {
if (!HypervisorType.External.equals(host.getHypervisorType())) {
return;
@ -2180,7 +2217,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
protected boolean sendStop(final VirtualMachineGuru guru, final VirtualMachineProfile profile, final boolean force, final boolean checkBeforeCleanup) {
final VirtualMachine vm = profile.getVirtualMachine();
Map<String, Boolean> vlanToPersistenceMap = getVlanToPersistenceMapForVM(vm.getId());
StopCommand stpCmd = new StopCommand(vm, getExecuteInSequence(vm.getHypervisorType()), checkBeforeCleanup);
updateStopCommandForExternalHypervisorType(vm.getHypervisorType(), profile, stpCmd);
if (MapUtils.isNotEmpty(vlanToPersistenceMap)) {
@ -5239,9 +5275,20 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
private void saveCustomOfferingDetails(long vmId, ServiceOffering serviceOffering) {
Map<String, String> details = vmInstanceDetailsDao.listDetailsKeyPairs(vmId);
details.put(UsageEventVO.DynamicParameters.cpuNumber.name(), serviceOffering.getCpu().toString());
details.put(UsageEventVO.DynamicParameters.cpuSpeed.name(), serviceOffering.getSpeed().toString());
details.put(UsageEventVO.DynamicParameters.memory.name(), serviceOffering.getRamSize().toString());
// We need to restore only the customizable parameters. If we save a parameter that is not customizable and attempt
// to restore a VM snapshot, com.cloud.vm.UserVmManagerImpl.validateCustomParameters will fail.
ServiceOffering unfilledOffering = _serviceOfferingDao.findByIdIncludingRemoved(serviceOffering.getId());
if (unfilledOffering.getCpu() == null) {
details.put(UsageEventVO.DynamicParameters.cpuNumber.name(), serviceOffering.getCpu().toString());
}
if (unfilledOffering.getSpeed() == null) {
details.put(UsageEventVO.DynamicParameters.cpuSpeed.name(), serviceOffering.getSpeed().toString());
}
if (unfilledOffering.getRamSize() == null) {
details.put(UsageEventVO.DynamicParameters.memory.name(), serviceOffering.getRamSize().toString());
}
List<VMInstanceDetailVO> detailList = new ArrayList<>();
for (Map.Entry<String, String> entry: details.entrySet()) {
VMInstanceDetailVO detailVO = new VMInstanceDetailVO(vmId, entry.getKey(), entry.getValue(), true);
@ -6270,6 +6317,80 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
_jobMgr.marshallResultObject(result));
}
@Override
public boolean updateVmNic(VirtualMachine vm, Nic nic, Boolean enabled) {
Outcome<VirtualMachine> outcome = updateVmNicThroughJobQueue(vm, nic, enabled);
retrieveVmFromJobOutcome(outcome, vm.getUuid(), "updateVmNic");
try {
Object jobResult = retrieveResultFromJobOutcomeAndThrowExceptionIfNeeded(outcome);
if (jobResult instanceof Boolean) {
return BooleanUtils.isTrue((Boolean) jobResult);
}
} catch (ResourceUnavailableException | InsufficientCapacityException ex) {
throw new CloudRuntimeException(String.format("Exception while updating VM [%s] NIC. Check the logs for more information.", vm.getUuid()));
}
throw new CloudRuntimeException("Unexpected job execution result.");
}
private boolean orchestrateUpdateVmNic(final VirtualMachine vm, final Nic nic, final Boolean enabled) throws ResourceUnavailableException {
if (vm.getState() == State.Running) {
try {
UpdateVmNicCommand updateVmNicCmd = new UpdateVmNicCommand(nic.getMacAddress(), vm.getName(), enabled);
Commands cmds = new Commands(Command.OnError.Stop);
cmds.addCommand("updatevmnic", updateVmNicCmd);
_agentMgr.send(vm.getHostId(), cmds);
UpdateVmNicAnswer updateVmNicAnswer = cmds.getAnswer(UpdateVmNicAnswer.class);
if (updateVmNicAnswer == null || !updateVmNicAnswer.getResult()) {
logger.warn("Unable to update VM %s NIC [{}].", vm.getName(), nic.getUuid());
return false;
}
} catch (final OperationTimedoutException e) {
throw new AgentUnavailableException(String.format("Unable to update NIC %s for VM %s.", nic.getUuid(), vm.getUuid()), vm.getHostId(), e);
}
}
NicVO nicVo = _nicsDao.findById(nic.getId());
nicVo.setEnabled(enabled);
_nicsDao.persist(nicVo);
return true;
}
public Outcome<VirtualMachine> updateVmNicThroughJobQueue(final VirtualMachine vm, final Nic nic, final Boolean isNicEnabled) {
Long vmId = vm.getId();
String commandName = VmWorkUpdateNic.class.getName();
Pair<VmWorkJobVO, Long> pendingWorkJob = retrievePendingWorkJob(vmId, commandName);
VmWorkJobVO workJob = pendingWorkJob.first();
if (workJob == null) {
Pair<VmWorkJobVO, VmWork> newVmWorkJobAndInfo = createWorkJobAndWorkInfo(commandName, vmId);
workJob = newVmWorkJobAndInfo.first();
VmWorkUpdateNic workInfo = new VmWorkUpdateNic(newVmWorkJobAndInfo.second(), nic.getId(), isNicEnabled);
setCmdInfoAndSubmitAsyncJob(workJob, workInfo, vmId);
}
AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(workJob.getId());
return new VmJobVirtualMachineOutcome(workJob, vmId);
}
@ReflectionUse
private Pair<JobInfo.Status, String> orchestrateUpdateVmNic(final VmWorkUpdateNic work) throws Exception {
VMInstanceVO vm = findVmById(work.getVmId());
final NicVO nic = _entityMgr.findById(NicVO.class, work.getNicId());
if (nic == null) {
throw new CloudRuntimeException(String.format("Unable to find NIC with ID %s.", work.getNicId()));
}
final boolean result = orchestrateUpdateVmNic(vm, nic, work.isEnabled());
return new Pair<>(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(result));
}
private Pair<Long, Long> findClusterAndHostIdForVmFromVolumes(long vmId) {
Long clusterId = null;
Long hostId = null;

View File

@ -0,0 +1,38 @@
// 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 com.cloud.vm;
public class VmWorkUpdateNic extends VmWork {
private static final long serialVersionUID = -8957066627929113278L;
Long nicId;
Boolean enabled;
public VmWorkUpdateNic(VmWork vmWork, Long nicId, Boolean enabled) {
super(vmWork);
this.nicId = nicId;
this.enabled = enabled;
}
public Long getNicId() {
return nicId;
}
public Boolean isEnabled() {
return enabled;
}
}

View File

@ -58,6 +58,7 @@ import org.apache.cloudstack.framework.messagebus.PublishScope;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.apache.cloudstack.network.dao.NetworkPermissionDao;
import org.apache.cloudstack.reservation.dao.ReservationDao;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.ObjectUtils;
@ -86,6 +87,7 @@ import com.cloud.api.query.dao.DomainRouterJoinDao;
import com.cloud.api.query.vo.DomainRouterJoinVO;
import com.cloud.bgp.BGPService;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.Resource;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.dc.ASNumberVO;
import com.cloud.dc.ClusterVO;
@ -214,6 +216,7 @@ import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.offerings.dao.NetworkOfferingDetailsDao;
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
import com.cloud.resource.ResourceManager;
import com.cloud.resourcelimit.CheckedReservation;
import com.cloud.server.ManagementServer;
import com.cloud.user.Account;
import com.cloud.user.ResourceLimitService;
@ -447,6 +450,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
ClusterDao clusterDao;
@Inject
RoutedIpv4Manager routedIpv4Manager;
@Inject
private ReservationDao reservationDao;
protected StateMachine2<Network.State, Network.Event, Network> _stateMachine;
ScheduledExecutorService _executor;
@ -2326,7 +2331,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
for (final NetworkElement element : networkElements) {
if (providersToImplement.contains(element.getProvider())) {
if (!_networkModel.isProviderEnabledInPhysicalNetwork(_networkModel.getPhysicalNetworkId(network), element.getProvider().getName())) {
throw new CloudRuntimeException(String.format("Service provider %s either doesn't exist or is not enabled in physical network: %s", element.getProvider().getName(), _physicalNetworkDao.findById(network.getPhysicalNetworkId())));
throw new CloudRuntimeException(String.format("Service provider %s either doesn't exist or is not enabled in physical network: %s",
element.getProvider().getName(), _physicalNetworkDao.findById(network.getPhysicalNetworkId())));
}
if (element instanceof NetworkMigrationResponder) {
if (!((NetworkMigrationResponder) element).prepareMigration(profile, network, vm, dest, context)) {
@ -2633,6 +2639,10 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
final NetworkGuru guru = AdapterBase.getAdapterByName(networkGurus, network.getGuruName());
guru.deallocate(network, profile, vm);
if (nic.getReservationStrategy() == Nic.ReservationStrategy.Create) {
applyProfileToNicForRelease(nic, profile);
_nicDao.update(nic.getId(), nic);
}
if (BooleanUtils.isNotTrue(preserveNics)) {
_nicDao.remove(nic.getId());
}
@ -2747,12 +2757,6 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
return null;
}
final boolean updateResourceCount = resourceCountNeedsUpdate(ntwkOff, aclType);
//check resource limits
if (updateResourceCount) {
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.network, isDisplayNetworkEnabled);
}
// Validate network offering
if (ntwkOff.getState() != NetworkOffering.State.Enabled) {
// see NetworkOfferingVO
@ -2771,6 +2775,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
boolean ipv6 = false;
try (CheckedReservation networkReservation = new CheckedReservation(owner, domainId, Resource.ResourceType.network, null, null, 1L, reservationDao, _resourceLimitMgr)) {
if (StringUtils.isNoneBlank(ip6Gateway, ip6Cidr)) {
ipv6 = true;
}
@ -3110,8 +3116,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
}
}
if (updateResourceCount) {
_resourceLimitMgr.incrementResourceCount(owner.getId(), ResourceType.network, isDisplayNetworkEnabled);
if (isResourceCountUpdateNeeded(ntwkOff)) {
changeAccountResourceCountOrRecalculateDomainResourceCount(owner.getAccountId(), domainId, isDisplayNetworkEnabled, true);
}
UsageEventUtils.publishNetworkCreation(network);
@ -3122,6 +3128,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
CallContext.current().setEventDetails("Network ID: " + network.getUuid());
CallContext.current().putContextParameter(Network.class, network.getUuid());
return network;
}
}
@Override
@ -3487,9 +3494,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
}
final NetworkOffering ntwkOff = _entityMgr.findById(NetworkOffering.class, networkFinal.getNetworkOfferingId());
final boolean updateResourceCount = resourceCountNeedsUpdate(ntwkOff, networkFinal.getAclType());
if (updateResourceCount) {
_resourceLimitMgr.decrementResourceCount(networkFinal.getAccountId(), ResourceType.network, networkFinal.getDisplayNetwork());
if (isResourceCountUpdateNeeded(ntwkOff)) {
changeAccountResourceCountOrRecalculateDomainResourceCount(networkFinal.getAccountId(), networkFinal.getDomainId(), networkFinal.getDisplayNetwork(), false);
}
}
return deletedVlans.second();
@ -3512,6 +3518,23 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
return success;
}
/**
* If it is a shared network with {@link ACLType#Domain}, it will belong to account {@link Account#ACCOUNT_ID_SYSTEM} and the resources will be not incremented for the
* domain. Therefore, we force the recalculation of the domain's resource count in this case. Otherwise, it will change the count for the account owner.
* @param incrementAccountResourceCount If true, the account resource count will be incremented by 1; otherwise, it will decremented by 1.
*/
private void changeAccountResourceCountOrRecalculateDomainResourceCount(Long accountId, Long domainId, boolean displayNetwork, boolean incrementAccountResourceCount) {
if (Account.ACCOUNT_ID_SYSTEM == accountId && ObjectUtils.isNotEmpty(domainId)) {
_resourceLimitMgr.recalculateDomainResourceCount(domainId, ResourceType.network, null);
} else {
if (incrementAccountResourceCount) {
_resourceLimitMgr.incrementResourceCount(accountId, ResourceType.network, displayNetwork);
} else {
_resourceLimitMgr.decrementResourceCount(accountId, ResourceType.network, displayNetwork);
}
}
}
private void publishDeletedVlanRanges(List<VlanVO> deletedVlanRangeToPublish) {
if (CollectionUtils.isNotEmpty(deletedVlanRangeToPublish)) {
for (VlanVO vlan : deletedVlanRangeToPublish) {
@ -3521,10 +3544,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
}
@Override
public boolean resourceCountNeedsUpdate(final NetworkOffering ntwkOff, final ACLType aclType) {
//Update resource count only for Isolated account specific non-system networks
final boolean updateResourceCount = ntwkOff.getGuestType() == GuestType.Isolated && !ntwkOff.isSystemOnly() && aclType == ACLType.Account;
return updateResourceCount;
public boolean isResourceCountUpdateNeeded(NetworkOffering networkOffering) {
return !networkOffering.isSystemOnly();
}
protected Pair<Boolean, List<VlanVO>> deleteVlansInNetwork(final NetworkVO network, final long userId, final Account callerAccount) {

View File

@ -40,6 +40,7 @@ import javax.naming.ConfigurationException;
import com.cloud.deploy.DeploymentClusterPlanner;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.resourcelimit.ReservationHelper;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.dao.VMTemplateDao;
@ -82,6 +83,7 @@ import org.apache.cloudstack.framework.jobs.AsyncJobManager;
import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
import org.apache.cloudstack.resourcedetail.DiskOfferingDetailVO;
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
import org.apache.cloudstack.resourcelimit.Reserver;
import org.apache.cloudstack.secret.PassphraseVO;
import org.apache.cloudstack.secret.dao.PassphraseDao;
import org.apache.cloudstack.snapshot.SnapshotHelper;
@ -862,7 +864,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_CREATE, eventDescription = "creating volume", create = true)
@Override
public DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, Long minIops, Long maxIops, VirtualMachine vm, VirtualMachineTemplate template, Account owner,
Long deviceId) {
Long deviceId, boolean incrementResourceCount) {
if (size == null) {
size = offering.getDiskSize();
} else {
@ -901,7 +903,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
saveVolumeDetails(offering.getId(), vol.getId());
// Save usage event and update resource count for user vm volumes
if (vm.getType() == VirtualMachine.Type.User) {
if (vm.getType() == VirtualMachine.Type.User && incrementResourceCount) {
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(), vol.getDataCenterId(), vol.getId(), vol.getName(), offering.getId(), null, size,
Volume.class.getName(), vol.getUuid(), vol.getInstanceId(), vol.isDisplayVolume());
_resourceLimitMgr.incrementVolumeResourceCount(vm.getAccountId(), vol.isDisplayVolume(), vol.getSize(), offering);
@ -1938,14 +1940,20 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
template == null ? null : template.getSize(),
vol.getPassphraseId() != null);
if (newSize != vol.getSize()) {
DiskOfferingVO diskOffering = diskOfferingDao.findByIdIncludingRemoved(vol.getDiskOfferingId());
if (newSize == vol.getSize()) {
return;
}
DiskOfferingVO diskOffering = diskOfferingDao.findByIdIncludingRemoved(vol.getDiskOfferingId());
List<Reserver> reservations = new ArrayList<>();
try {
VMInstanceVO vm = vol.getInstanceId() != null ? vmInstanceDao.findById(vol.getInstanceId()) : null;
if (vm == null || vm.getType() == VirtualMachine.Type.User) {
// Update resource count for user vm volumes when volume is attached
if (newSize > vol.getSize()) {
_resourceLimitMgr.checkPrimaryStorageResourceLimit(_accountMgr.getActiveAccountById(vol.getAccountId()),
vol.isDisplay(), newSize - vol.getSize(), diskOffering);
vol.isDisplay(), newSize - vol.getSize(), diskOffering, reservations);
_resourceLimitMgr.incrementVolumePrimaryStorageResourceCount(vol.getAccountId(), vol.isDisplay(),
newSize - vol.getSize(), diskOffering);
} else {
@ -1953,9 +1961,11 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
vol.getSize() - newSize, diskOffering);
}
}
vol.setSize(newSize);
_volsDao.persist(vol);
} finally {
ReservationHelper.closeAll(reservations);
}
vol.setSize(newSize);
_volsDao.persist(vol);
}
@Override

View File

@ -27,6 +27,6 @@ public interface AccountVlanMapDao extends GenericDao<AccountVlanMapVO, Long> {
public List<AccountVlanMapVO> listAccountVlanMapsByVlan(long vlanDbId);
public AccountVlanMapVO findAccountVlanMap(long accountId, long vlanDbId);
public AccountVlanMapVO findAccountVlanMap(Long accountId, long vlanDbId);
}

View File

@ -48,9 +48,9 @@ public class AccountVlanMapDaoImpl extends GenericDaoBase<AccountVlanMapVO, Long
}
@Override
public AccountVlanMapVO findAccountVlanMap(long accountId, long vlanDbId) {
public AccountVlanMapVO findAccountVlanMap(Long accountId, long vlanDbId) {
SearchCriteria<AccountVlanMapVO> sc = AccountVlanSearch.create();
sc.setParameters("accountId", accountId);
sc.setParametersIfNotNull("accountId", accountId);
sc.setParameters("vlanDbId", vlanDbId);
return findOneIncludingRemovedBy(sc);
}

View File

@ -24,5 +24,5 @@ import com.cloud.utils.db.GenericDao;
public interface DomainVlanMapDao extends GenericDao<DomainVlanMapVO, Long> {
public List<DomainVlanMapVO> listDomainVlanMapsByDomain(long domainId);
public List<DomainVlanMapVO> listDomainVlanMapsByVlan(long vlanDbId);
public DomainVlanMapVO findDomainVlanMap(long domainId, long vlanDbId);
public DomainVlanMapVO findDomainVlanMap(Long domainId, long vlanDbId);
}

View File

@ -46,9 +46,9 @@ public class DomainVlanMapDaoImpl extends GenericDaoBase<DomainVlanMapVO, Long>
}
@Override
public DomainVlanMapVO findDomainVlanMap(long domainId, long vlanDbId) {
public DomainVlanMapVO findDomainVlanMap(Long domainId, long vlanDbId) {
SearchCriteria<DomainVlanMapVO> sc = DomainVlanSearch.create();
sc.setParameters("domainId", domainId);
sc.setParametersIfNotNull("domainId", domainId);
sc.setParameters("vlanDbId", vlanDbId);
return findOneIncludingRemovedBy(sc);
}

View File

@ -262,7 +262,7 @@ public class DomainDaoImpl extends GenericDaoBase<DomainVO, Long> implements Dom
SearchCriteria<DomainVO> sc = DomainPairSearch.create();
sc.setParameters("id", parentId, childId);
List<DomainVO> domainPair = listBy(sc);
List<DomainVO> domainPair = listIncludingRemovedBy(sc);
if ((domainPair != null) && (domainPair.size() == 2)) {
DomainVO d1 = domainPair.get(0);

View File

@ -45,4 +45,9 @@ public interface HostTagsDao extends GenericDao<HostTagVO, Long> {
HostTagResponse newHostTagResponse(HostTagVO hostTag);
List<HostTagVO> searchByIds(Long... hostTagIds);
/**
* List all host tags defined on hosts within a cluster
*/
List<String> listByClusterId(Long clusterId);
}

View File

@ -23,6 +23,7 @@ import org.apache.cloudstack.api.response.HostTagResponse;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
@ -43,9 +44,12 @@ public class HostTagsDaoImpl extends GenericDaoBase<HostTagVO, Long> implements
private final SearchBuilder<HostTagVO> stSearch;
private final SearchBuilder<HostTagVO> tagIdsearch;
private final SearchBuilder<HostTagVO> ImplicitTagsSearch;
private final GenericSearchBuilder<HostTagVO, String> tagSearch;
@Inject
private ConfigurationDao _configDao;
@Inject
private HostDao hostDao;
public HostTagsDaoImpl() {
HostSearch = createSearchBuilder();
@ -72,6 +76,11 @@ public class HostTagsDaoImpl extends GenericDaoBase<HostTagVO, Long> implements
ImplicitTagsSearch.and("hostId", ImplicitTagsSearch.entity().getHostId(), SearchCriteria.Op.EQ);
ImplicitTagsSearch.and("isImplicit", ImplicitTagsSearch.entity().getIsImplicit(), SearchCriteria.Op.EQ);
ImplicitTagsSearch.done();
tagSearch = createSearchBuilder(String.class);
tagSearch.selectFields(tagSearch.entity().getTag());
tagSearch.and("hostIdIN", tagSearch.entity().getHostId(), SearchCriteria.Op.IN);
tagSearch.done();
}
@Override
@ -235,4 +244,15 @@ public class HostTagsDaoImpl extends GenericDaoBase<HostTagVO, Long> implements
return tagList;
}
@Override
public List<String> listByClusterId(Long clusterId) {
List<Long> hostIds = hostDao.listIdsByClusterId(clusterId);
if (CollectionUtils.isEmpty(hostIds)) {
return new ArrayList<>();
}
SearchCriteria<String> sc = tagSearch.create();
sc.setParameters("hostIdIN", hostIds.toArray());
return customSearch(sc, null);
}
}

View File

@ -193,6 +193,7 @@ public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long>implements Ne
PersistentNetworkSearch.and("id", PersistentNetworkSearch.entity().getId(), Op.NEQ);
PersistentNetworkSearch.and("guestType", PersistentNetworkSearch.entity().getGuestType(), Op.IN);
PersistentNetworkSearch.and("broadcastUri", PersistentNetworkSearch.entity().getBroadcastUri(), Op.EQ);
PersistentNetworkSearch.and("dc", PersistentNetworkSearch.entity().getDataCenterId(), Op.EQ);
PersistentNetworkSearch.and("removed", PersistentNetworkSearch.entity().getRemoved(), Op.NULL);
final SearchBuilder<NetworkOfferingVO> persistentNtwkOffJoin = _ntwkOffDao.createSearchBuilder();
persistentNtwkOffJoin.and("persistent", persistentNtwkOffJoin.entity().isPersistent(), Op.EQ);

View File

@ -35,7 +35,7 @@ public interface GuestOSDao extends GenericDao<GuestOSVO, Long> {
List<GuestOSVO> listByDisplayName(String displayName);
Pair<List<? extends GuestOS>, Integer> listGuestOSByCriteria(Long startIndex, Long pageSize, Long id, Long osCategoryId, String description, String keyword, Boolean forDisplay);
Pair<List<? extends GuestOS>, Integer> listGuestOSByCriteria(Long startIndex, Long pageSize, List<Long> ids, Long osCategoryId, String description, String keyword, Boolean forDisplay);
List<Long> listIdsByCategoryId(final long categoryId);
}

View File

@ -125,12 +125,12 @@ public class GuestOSDaoImpl extends GenericDaoBase<GuestOSVO, Long> implements G
return listBy(sc);
}
public Pair<List<? extends GuestOS>, Integer> listGuestOSByCriteria(Long startIndex, Long pageSize, Long id, Long osCategoryId, String description, String keyword, Boolean forDisplay) {
public Pair<List<? extends GuestOS>, Integer> listGuestOSByCriteria(Long startIndex, Long pageSize, List<Long> ids, Long osCategoryId, String description, String keyword, Boolean forDisplay) {
final Filter searchFilter = new Filter(GuestOSVO.class, "displayName", true, startIndex, pageSize);
final SearchCriteria<GuestOSVO> sc = createSearchCriteria();
if (id != null) {
sc.addAnd("id", SearchCriteria.Op.EQ, id);
if (CollectionUtils.isNotEmpty(ids)) {
sc.addAnd("id", SearchCriteria.Op.IN, ids.toArray());
}
if (osCategoryId != null) {

View File

@ -170,6 +170,7 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
CountSnapshotsByAccount.select(null, Func.COUNT, null);
CountSnapshotsByAccount.and("account", CountSnapshotsByAccount.entity().getAccountId(), SearchCriteria.Op.EQ);
CountSnapshotsByAccount.and("status", CountSnapshotsByAccount.entity().getState(), SearchCriteria.Op.NIN);
CountSnapshotsByAccount.and("snapshotTypeNEQ", CountSnapshotsByAccount.entity().getSnapshotType(), SearchCriteria.Op.NIN);
CountSnapshotsByAccount.and("removed", CountSnapshotsByAccount.entity().getRemoved(), SearchCriteria.Op.NULL);
CountSnapshotsByAccount.done();
@ -220,6 +221,7 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
SearchCriteria<Long> sc = CountSnapshotsByAccount.create();
sc.setParameters("account", accountId);
sc.setParameters("status", State.Error, State.Destroyed);
sc.setParameters("snapshotTypeNEQ", Snapshot.Type.GROUP.ordinal());
return customSearch(sc, null).get(0);
}

View File

@ -166,4 +166,12 @@ public interface VolumeDao extends GenericDao<VolumeVO, Long>, StateDao<Volume.S
int getVolumeCountByOfferingId(long diskOfferingId);
VolumeVO findByLastIdAndState(long lastVolumeId, Volume.State...states);
/**
* Retrieves volume by its externalId
*
* @param externalUuid
* @return Volume Object of matching search criteria
*/
VolumeVO findByExternalUuid(String externalUuid);
}

View File

@ -74,6 +74,7 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
private final SearchBuilder<VolumeVO> storeAndInstallPathSearch;
private final SearchBuilder<VolumeVO> volumeIdSearch;
protected GenericSearchBuilder<VolumeVO, Long> CountByAccount;
protected final SearchBuilder<VolumeVO> ExternalUuidSearch;
protected GenericSearchBuilder<VolumeVO, SumCount> primaryStorageSearch;
protected GenericSearchBuilder<VolumeVO, SumCount> primaryStorageSearch2;
protected GenericSearchBuilder<VolumeVO, SumCount> secondaryStorageSearch;
@ -459,6 +460,10 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
CountByAccount.and("idNIN", CountByAccount.entity().getId(), Op.NIN);
CountByAccount.done();
ExternalUuidSearch = createSearchBuilder();
ExternalUuidSearch.and("externalUuid", ExternalUuidSearch.entity().getExternalUuid(), Op.EQ);
ExternalUuidSearch.done();
primaryStorageSearch = createSearchBuilder(SumCount.class);
primaryStorageSearch.select("sum", Func.SUM, primaryStorageSearch.entity().getSize());
primaryStorageSearch.and("accountId", primaryStorageSearch.entity().getAccountId(), Op.EQ);
@ -934,4 +939,11 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
sc.and(sc.entity().getState(), SearchCriteria.Op.IN, (Object[]) states);
return sc.find();
}
@Override
public VolumeVO findByExternalUuid(String externalUuid) {
SearchCriteria<VolumeVO> sc = ExternalUuidSearch.create();
sc.setParameters("externalUuid", externalUuid);
return findOneBy(sc);
}
}

View File

@ -16,6 +16,14 @@
// under the License.
package com.cloud.upgrade.dao;
import org.apache.cloudstack.vm.UnmanagedVMsManager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class Upgrade42200to42210 extends DbUpgradeAbstractImpl implements DbUpgrade, DbUpgradeSystemVmTemplate {
@Override
@ -27,4 +35,47 @@ public class Upgrade42200to42210 extends DbUpgradeAbstractImpl implements DbUpgr
public String getUpgradedVersion() {
return "4.22.1.0";
}
@Override
public void performDataMigration(Connection conn) {
removeDuplicateKVMImportTemplates(conn);
}
private void removeDuplicateKVMImportTemplates(Connection conn) {
List<Long> templateIds = new ArrayList<>();
try (PreparedStatement selectStmt = conn.prepareStatement(String.format("SELECT id FROM cloud.vm_template WHERE name='%s' ORDER BY id ASC", UnmanagedVMsManager.KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME))) {
ResultSet rs = selectStmt.executeQuery();
while (rs.next()) {
templateIds.add(rs.getLong(1));
}
if (templateIds.size() <= 1) {
return;
}
logger.info("Removing duplicate template " + UnmanagedVMsManager.KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME + " entries");
Long firstTemplateId = templateIds.get(0);
String updateTemplateSql = "UPDATE cloud.vm_instance SET vm_template_id = ? WHERE vm_template_id = ?";
String deleteTemplateSql = "DELETE FROM cloud.vm_template WHERE id = ?";
try (PreparedStatement updateTemplateStmt = conn.prepareStatement(updateTemplateSql);
PreparedStatement deleteTemplateStmt = conn.prepareStatement(deleteTemplateSql)) {
for (int i = 1; i < templateIds.size(); i++) {
Long duplicateTemplateId = templateIds.get(i);
// Update VM references
updateTemplateStmt.setLong(1, firstTemplateId);
updateTemplateStmt.setLong(2, duplicateTemplateId);
updateTemplateStmt.executeUpdate();
// Delete duplicate dummy template
deleteTemplateStmt.setLong(1, duplicateTemplateId);
deleteTemplateStmt.executeUpdate();
}
}
} catch (Exception e) {
logger.warn("Failed to remove duplicate template " + UnmanagedVMsManager.KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME + " entries", e);
}
}
}

View File

@ -17,7 +17,12 @@
package com.cloud.upgrade.dao;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.exception.CloudRuntimeException;
public class Upgrade42210to42300 extends DbUpgradeAbstractImpl implements DbUpgrade, DbUpgradeSystemVmTemplate {
@ -42,4 +47,46 @@ public class Upgrade42210to42300 extends DbUpgradeAbstractImpl implements DbUpgr
return new InputStream[] {script};
}
@Override
public void performDataMigration(Connection conn) {
unhideJsInterpretationEnabled(conn);
}
protected void unhideJsInterpretationEnabled(Connection conn) {
String value = getJsInterpretationEnabled(conn);
if (value != null) {
updateJsInterpretationEnabledFields(conn, value);
}
}
protected String getJsInterpretationEnabled(Connection conn) {
String query = "SELECT value FROM cloud.configuration WHERE name = 'js.interpretation.enabled' AND category = 'Hidden';";
try (PreparedStatement pstmt = conn.prepareStatement(query)) {
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
return rs.getString("value");
}
logger.debug("Unable to retrieve value of hidden configuration 'js.interpretation.enabled'. The configuration may already be unhidden.");
return null;
} catch (SQLException e) {
throw new CloudRuntimeException("Error while retrieving value of hidden configuration 'js.interpretation.enabled'.", e);
}
}
protected void updateJsInterpretationEnabledFields(Connection conn, String encryptedValue) {
String query = "UPDATE cloud.configuration SET value = ?, category = 'System', component = 'JsInterpreter', is_dynamic = 1 WHERE name = 'js.interpretation.enabled';";
try (PreparedStatement pstmt = conn.prepareStatement(query)) {
String decryptedValue = DBEncryptionUtil.decrypt(encryptedValue);
logger.info("Updating setting 'js.interpretation.enabled' to decrypted value [{}], category 'System', component 'JsInterpreter', and is_dynamic '1'.", decryptedValue);
pstmt.setString(1, decryptedValue);
pstmt.executeUpdate();
} catch (SQLException e) {
throw new CloudRuntimeException("Error while unhiding configuration 'js.interpretation.enabled'.", e);
} catch (CloudRuntimeException e) {
logger.warn("Error while decrypting configuration 'js.interpretation.enabled'. The configuration may already be decrypted.");
}
}
}

View File

@ -131,6 +131,9 @@ public class NicVO implements Nic {
@Column(name = "mtu")
Integer mtu;
@Column(name = "enabled")
boolean enabled;
@Transient
transient String nsxLogicalSwitchUuid;
@ -143,6 +146,7 @@ public class NicVO implements Nic {
this.networkId = configurationId;
this.state = State.Allocated;
this.vmType = vmType;
this.enabled = true;
}
@Override
@ -397,6 +401,14 @@ public class NicVO implements Nic {
this.nsxLogicalSwitchPortUuid = nsxLogicalSwitchPortUuid;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 31).append(id).toHashCode();

View File

@ -21,6 +21,7 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.utils.Pair;
@ -192,4 +193,8 @@ public interface VMInstanceDao extends GenericDao<VMInstanceVO, Long>, StateDao<
int getVmCountByOfferingNotInDomain(Long serviceOfferingId, List<Long> domainIds);
List<VMInstanceVO> listByIdsIncludingRemoved(List<Long> ids);
List<VMInstanceVO> listDeleteProtectedVmsByAccountId(long accountId);
List<VMInstanceVO> listDeleteProtectedVmsByDomainIds(Set<Long> domainIds);
}

View File

@ -25,11 +25,13 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Component;
@ -106,6 +108,8 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
protected SearchBuilder<VMInstanceVO> IdsPowerStateSelectSearch;
GenericSearchBuilder<VMInstanceVO, Integer> CountByOfferingId;
GenericSearchBuilder<VMInstanceVO, Integer> CountUserVmNotInDomain;
SearchBuilder<VMInstanceVO> DeleteProtectedVmSearchByAccount;
SearchBuilder<VMInstanceVO> DeleteProtectedVmSearchByDomainIds;
@Inject
ResourceTagDao tagsDao;
@ -368,6 +372,19 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
CountUserVmNotInDomain.and("domainIdsNotIn", CountUserVmNotInDomain.entity().getDomainId(), Op.NIN);
CountUserVmNotInDomain.done();
DeleteProtectedVmSearchByAccount = createSearchBuilder();
DeleteProtectedVmSearchByAccount.selectFields(DeleteProtectedVmSearchByAccount.entity().getUuid());
DeleteProtectedVmSearchByAccount.and(ApiConstants.ACCOUNT_ID, DeleteProtectedVmSearchByAccount.entity().getAccountId(), Op.EQ);
DeleteProtectedVmSearchByAccount.and(ApiConstants.DELETE_PROTECTION, DeleteProtectedVmSearchByAccount.entity().isDeleteProtection(), Op.EQ);
DeleteProtectedVmSearchByAccount.and(ApiConstants.REMOVED, DeleteProtectedVmSearchByAccount.entity().getRemoved(), Op.NULL);
DeleteProtectedVmSearchByAccount.done();
DeleteProtectedVmSearchByDomainIds = createSearchBuilder();
DeleteProtectedVmSearchByDomainIds.selectFields(DeleteProtectedVmSearchByDomainIds.entity().getUuid());
DeleteProtectedVmSearchByDomainIds.and(ApiConstants.DOMAIN_IDS, DeleteProtectedVmSearchByDomainIds.entity().getDomainId(), Op.IN);
DeleteProtectedVmSearchByDomainIds.and(ApiConstants.DELETE_PROTECTION, DeleteProtectedVmSearchByDomainIds.entity().isDeleteProtection(), Op.EQ);
DeleteProtectedVmSearchByDomainIds.and(ApiConstants.REMOVED, DeleteProtectedVmSearchByDomainIds.entity().getRemoved(), Op.NULL);
DeleteProtectedVmSearchByDomainIds.done();
}
@Override
@ -1296,4 +1313,22 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
sc.setParameters("ids", ids.toArray());
return listIncludingRemovedBy(sc);
}
@Override
public List<VMInstanceVO> listDeleteProtectedVmsByAccountId(long accountId) {
SearchCriteria<VMInstanceVO> sc = DeleteProtectedVmSearchByAccount.create();
sc.setParameters(ApiConstants.ACCOUNT_ID, accountId);
sc.setParameters(ApiConstants.DELETE_PROTECTION, true);
Filter filter = new Filter(VMInstanceVO.class, null, false, 0L, 10L);
return listBy(sc, filter);
}
@Override
public List<VMInstanceVO> listDeleteProtectedVmsByDomainIds(Set<Long> domainIds) {
SearchCriteria<VMInstanceVO> sc = DeleteProtectedVmSearchByDomainIds.create();
sc.setParameters(ApiConstants.DOMAIN_IDS, domainIds.toArray());
sc.setParameters(ApiConstants.DELETE_PROTECTION, true);
Filter filter = new Filter(VMInstanceVO.class, null, false, 0L, 10L);
return listBy(sc, filter);
}
}

View File

@ -21,20 +21,14 @@ import java.util.Date;
import java.util.List;
import com.cloud.utils.DateUtil;
import org.apache.cloudstack.api.response.BackupScheduleResponse;
import org.apache.cloudstack.backup.BackupSchedule;
import org.apache.cloudstack.backup.BackupScheduleVO;
import com.cloud.utils.db.GenericDao;
public interface BackupScheduleDao extends GenericDao<BackupScheduleVO, Long> {
BackupScheduleVO findByVM(Long vmId);
List<BackupScheduleVO> listByVM(Long vmId);
BackupScheduleVO findByVMAndIntervalType(Long vmId, DateUtil.IntervalType intervalType);
List<BackupScheduleVO> getSchedulesToExecute(Date currentTimestamp);
BackupScheduleResponse newBackupScheduleResponse(BackupSchedule schedule);
}

View File

@ -17,28 +17,23 @@
package org.apache.cloudstack.backup.dao;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import com.cloud.utils.DateUtil;
import org.apache.cloudstack.api.response.BackupScheduleResponse;
import org.apache.cloudstack.backup.BackupSchedule;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.TransactionLegacy;
import org.apache.cloudstack.backup.BackupScheduleVO;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.dao.VMInstanceDao;
public class BackupScheduleDaoImpl extends GenericDaoBase<BackupScheduleVO, Long> implements BackupScheduleDao {
@Inject
VMInstanceDao vmInstanceDao;
private SearchBuilder<BackupScheduleVO> backupScheduleSearch;
private SearchBuilder<BackupScheduleVO> executableSchedulesSearch;
@ -59,13 +54,6 @@ public class BackupScheduleDaoImpl extends GenericDaoBase<BackupScheduleVO, Long
executableSchedulesSearch.done();
}
@Override
public BackupScheduleVO findByVM(Long vmId) {
SearchCriteria<BackupScheduleVO> sc = backupScheduleSearch.create();
sc.setParameters("vm_id", vmId);
return findOneBy(sc);
}
@Override
public List<BackupScheduleVO> listByVM(Long vmId) {
SearchCriteria<BackupScheduleVO> sc = backupScheduleSearch.create();
@ -88,21 +76,19 @@ public class BackupScheduleDaoImpl extends GenericDaoBase<BackupScheduleVO, Long
return listBy(sc);
}
@DB
@Override
public BackupScheduleResponse newBackupScheduleResponse(BackupSchedule schedule) {
VMInstanceVO vm = vmInstanceDao.findByIdIncludingRemoved(schedule.getVmId());
BackupScheduleResponse response = new BackupScheduleResponse();
response.setId(schedule.getUuid());
response.setVmId(vm.getUuid());
response.setVmName(vm.getHostName());
response.setIntervalType(schedule.getScheduleType());
response.setSchedule(schedule.getSchedule());
response.setTimezone(schedule.getTimezone());
response.setMaxBackups(schedule.getMaxBackups());
if (schedule.getQuiesceVM() != null) {
response.setQuiesceVM(schedule.getQuiesceVM());
public boolean remove(Long id) {
String sql = "UPDATE backups SET backup_schedule_id = NULL WHERE backup_schedule_id = ?";
TransactionLegacy transaction = TransactionLegacy.currentTxn();
try {
PreparedStatement preparedStatement = transaction.prepareAutoCloseStatement(sql);
preparedStatement.setLong(1, id);
preparedStatement.executeUpdate();
return super.remove(id);
} catch (SQLException e) {
logger.warn("Unable to clean up backup schedules references from the backups table.", e);
return false;
}
response.setObjectName("backupschedule");
return response;
}
}

View File

@ -51,6 +51,8 @@ StateDao<ObjectInDataStoreStateMachine.State, ObjectInDataStoreStateMachine.Even
SnapshotDataStoreVO findBySnapshotIdAndDataStoreRoleAndState(long snapshotId, DataStoreRole role, ObjectInDataStoreStateMachine.State state);
List<SnapshotDataStoreVO> listBySnapshotIdAndDataStoreRoleAndStateIn(long snapshotId, DataStoreRole role, ObjectInDataStoreStateMachine.State... state);
List<SnapshotDataStoreVO> listReadyByVolumeIdAndCheckpointPathNotNull(long volumeId);
SnapshotDataStoreVO findOneBySnapshotId(long snapshotId, long zoneId);

View File

@ -67,7 +67,8 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
private SearchBuilder<SnapshotDataStoreVO> searchFilteringStoreIdEqStoreRoleEqStateNeqRefCntNeq;
protected SearchBuilder<SnapshotDataStoreVO> searchFilteringStoreIdEqStateEqStoreRoleEqIdEqUpdateCountEqSnapshotIdEqVolumeIdEq;
private SearchBuilder<SnapshotDataStoreVO> stateSearch;
private SearchBuilder<SnapshotDataStoreVO> idStateNeqSearch;
private SearchBuilder<SnapshotDataStoreVO> idStateNinSearch;
private SearchBuilder<SnapshotDataStoreVO> idEqRoleEqStateInSearch;
protected SearchBuilder<SnapshotVO> snapshotVOSearch;
private SearchBuilder<SnapshotDataStoreVO> snapshotCreatedSearch;
private SearchBuilder<SnapshotDataStoreVO> dataStoreAndInstallPathSearch;
@ -146,10 +147,15 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
stateSearch.done();
idStateNeqSearch = createSearchBuilder();
idStateNeqSearch.and(SNAPSHOT_ID, idStateNeqSearch.entity().getSnapshotId(), SearchCriteria.Op.EQ);
idStateNeqSearch.and(STATE, idStateNeqSearch.entity().getState(), SearchCriteria.Op.NEQ);
idStateNeqSearch.done();
idStateNinSearch = createSearchBuilder();
idStateNinSearch.and(SNAPSHOT_ID, idStateNinSearch.entity().getSnapshotId(), SearchCriteria.Op.EQ);
idStateNinSearch.and(STATE, idStateNinSearch.entity().getState(), SearchCriteria.Op.NOTIN);
idStateNinSearch.done();
idEqRoleEqStateInSearch = createSearchBuilder();
idEqRoleEqStateInSearch.and(SNAPSHOT_ID, idEqRoleEqStateInSearch.entity().getSnapshotId(), SearchCriteria.Op.EQ);
idEqRoleEqStateInSearch.and(STORE_ROLE, idEqRoleEqStateInSearch.entity().getRole(), SearchCriteria.Op.EQ);
idEqRoleEqStateInSearch.and(STATE, idEqRoleEqStateInSearch.entity().getState(), SearchCriteria.Op.IN);
snapshotVOSearch = snapshotDao.createSearchBuilder();
snapshotVOSearch.and(VOLUME_ID, snapshotVOSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
@ -387,6 +393,15 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
return findOneBy(sc);
}
@Override
public List<SnapshotDataStoreVO> listBySnapshotIdAndDataStoreRoleAndStateIn(long snapshotId, DataStoreRole role, State... state) {
SearchCriteria<SnapshotDataStoreVO> sc = idEqRoleEqStateInSearch.create();
sc.setParameters(SNAPSHOT_ID, snapshotId);
sc.setParameters(STORE_ROLE, role);
sc.setParameters(STATE, (Object[])state);
return listBy(sc);
}
@Override
public SnapshotDataStoreVO findOneBySnapshotId(long snapshotId, long zoneId) {
try (TransactionLegacy transactionLegacy = TransactionLegacy.currentTxn()) {
@ -480,7 +495,7 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
@Override
public List<SnapshotDataStoreVO> findBySnapshotIdWithNonDestroyedState(long snapshotId) {
SearchCriteria<SnapshotDataStoreVO> sc = idStateNeqSearch.create();
SearchCriteria<SnapshotDataStoreVO> sc = idStateNinSearch.create();
sc.setParameters(SNAPSHOT_ID, snapshotId);
sc.setParameters(STATE, State.Destroyed.name());
return listBy(sc);
@ -488,7 +503,7 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
@Override
public List<SnapshotDataStoreVO> findBySnapshotIdAndNotInDestroyedHiddenState(long snapshotId) {
SearchCriteria<SnapshotDataStoreVO> sc = idStateNeqSearch.create();
SearchCriteria<SnapshotDataStoreVO> sc = idStateNinSearch.create();
sc.setParameters(SNAPSHOT_ID, snapshotId);
sc.setParameters(STATE, State.Destroyed.name(), State.Hidden.name());
return listBy(sc);

View File

@ -687,22 +687,23 @@ CREATE TABLE IF NOT EXISTS `cloud`.`backup_details` (
UPDATE `cloud`.`backups` b
INNER JOIN `cloud`.`vm_instance` vm ON b.vm_id = vm.id
SET b.backed_volumes = (
SELECT CONCAT("[",
GROUP_CONCAT(
CONCAT(
"{\"uuid\":\"", v.uuid, "\",",
"\"type\":\"", v.volume_type, "\",",
"\"size\":", v.`size`, ",",
"\"path\":\"", IFNULL(v.path, 'null'), "\",",
"\"deviceId\":", IFNULL(v.device_id, 'null'), ",",
"\"diskOfferingId\":\"", doff.uuid, "\",",
"\"minIops\":", IFNULL(v.min_iops, 'null'), ",",
"\"maxIops\":", IFNULL(v.max_iops, 'null'),
"}"
)
SEPARATOR ","
SELECT COALESCE(
CAST(
JSON_ARRAYAGG(
JSON_OBJECT(
'uuid', v.uuid,
'type', v.volume_type,
'size', v.size,
'path', v.path,
'deviceId', v.device_id,
'diskOfferingId', doff.uuid,
'minIops', v.min_iops,
'maxIops', v.max_iops
)
) AS CHAR
),
"]")
'[]'
)
FROM `cloud`.`volumes` v
LEFT JOIN `cloud`.`disk_offering` doff ON v.disk_offering_id = doff.id
WHERE v.instance_id = vm.id
@ -711,22 +712,23 @@ SET b.backed_volumes = (
-- Add diskOfferingId, deviceId, minIops and maxIops to backup_volumes in vm_instance table
UPDATE `cloud`.`vm_instance` vm
SET vm.backup_volumes = (
SELECT CONCAT("[",
GROUP_CONCAT(
CONCAT(
"{\"uuid\":\"", v.uuid, "\",",
"\"type\":\"", v.volume_type, "\",",
"\"size\":", v.`size`, ",",
"\"path\":\"", IFNULL(v.path, 'null'), "\",",
"\"deviceId\":", IFNULL(v.device_id, 'null'), ",",
"\"diskOfferingId\":\"", doff.uuid, "\",",
"\"minIops\":", IFNULL(v.min_iops, 'null'), ",",
"\"maxIops\":", IFNULL(v.max_iops, 'null'),
"}"
)
SEPARATOR ","
SELECT COALESCE(
CAST(
JSON_ARRAYAGG(
JSON_OBJECT(
'uuid', v.uuid,
'type', v.volume_type,
'size', v.size,
'path', v.path,
'deviceId', v.device_id,
'diskOfferingId', doff.uuid,
'minIops', v.min_iops,
'maxIops', v.max_iops
)
) AS CHAR
),
"]")
'[]'
)
FROM `cloud`.`volumes` v
LEFT JOIN `cloud`.`disk_offering` doff ON v.disk_offering_id = doff.id
WHERE v.instance_id = vm.id

View File

@ -33,3 +33,23 @@ UPDATE `cloud`.`alert` SET type = 34 WHERE name = 'ALERT.VR.PRIVATE.IFACE.MTU';
-- Update configuration 'kvm.ssh.to.agent' description and is_dynamic fields
UPDATE `cloud`.`configuration` SET description = 'True if the management server will restart the agent service via SSH into the KVM hosts after or during maintenance operations', is_dynamic = 1 WHERE name = 'kvm.ssh.to.agent';
-- Sanitize legacy network-level addressing fields for Public networks
UPDATE `cloud`.`networks`
SET `broadcast_uri` = NULL,
`gateway` = NULL,
`cidr` = NULL,
`ip6_gateway` = NULL,
`ip6_cidr` = NULL
WHERE `traffic_type` = 'Public';
UPDATE `cloud`.`vm_template` SET guest_os_id = 99 WHERE name = 'kvm-default-vm-import-dummy-template';
-- Update existing vm_template records with NULL type to "USER"
UPDATE `cloud`.`vm_template` SET `type` = 'USER' WHERE `type` IS NULL;
-- remove unused config item
DELETE FROM `cloud`.`configuration` WHERE name = 'consoleproxy.cmd.port';
-- Drops the unused "backup_interval_type" column of the "cloud.backups" table
ALTER TABLE `cloud`.`backups` DROP COLUMN `backup_interval_type`;

View File

@ -115,5 +115,8 @@ CALL `cloud`.`IDEMPOTENT_UPDATE_API_PERMISSION`('Resource Admin', 'deleteUserKey
-- Add conserve mode for VPC offerings
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc_offerings','conserve_mode', 'tinyint(1) unsigned NULL DEFAULT 0 COMMENT ''True if the VPC offering is IP conserve mode enabled, allowing public IP services to be used across multiple VPC tiers'' ');
--- Disable/enable NICs
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.nics','enabled', 'TINYINT(1) NOT NULL DEFAULT 1 COMMENT ''Indicates whether the NIC is enabled or not'' ');
-- Add description for secondary IP addresses
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.nic_secondary_ips','description', 'varchar(2048) DEFAULT NULL');

View File

@ -76,6 +76,7 @@ select
nics.broadcast_uri broadcast_uri,
nics.isolation_uri isolation_uri,
nics.mtu mtu,
nics.enabled is_nic_enabled,
vpc.id vpc_id,
vpc.uuid vpc_uuid,
vpc.name vpc_name,

View File

@ -79,6 +79,7 @@ SELECT
`vm_template`.`format` AS `template_format`,
`vm_template`.`display_text` AS `template_display_text`,
`vm_template`.`enable_password` AS `password_enabled`,
`vm_template`.`extension_id` AS `template_extension_id`,
`iso`.`id` AS `iso_id`,
`iso`.`uuid` AS `iso_uuid`,
`iso`.`name` AS `iso_name`,
@ -141,6 +142,7 @@ SELECT
`nics`.`mac_address` AS `mac_address`,
`nics`.`broadcast_uri` AS `broadcast_uri`,
`nics`.`isolation_uri` AS `isolation_uri`,
`nics`.`enabled` AS `is_nic_enabled`,
`vpc`.`id` AS `vpc_id`,
`vpc`.`uuid` AS `vpc_uuid`,
`networks`.`uuid` AS `network_uuid`,

View File

@ -0,0 +1,48 @@
-- 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.
-- cloud_usage.quota_summary_view source
-- Create view for quota summary
DROP VIEW IF EXISTS `cloud_usage`.`quota_summary_view`;
CREATE VIEW `cloud_usage`.`quota_summary_view` AS
SELECT
cloud_usage.quota_account.account_id AS account_id,
cloud_usage.quota_account.quota_balance AS quota_balance,
cloud_usage.quota_account.quota_balance_date AS quota_balance_date,
cloud_usage.quota_account.quota_enforce AS quota_enforce,
cloud_usage.quota_account.quota_min_balance AS quota_min_balance,
cloud_usage.quota_account.quota_alert_date AS quota_alert_date,
cloud_usage.quota_account.quota_alert_type AS quota_alert_type,
cloud_usage.quota_account.last_statement_date AS last_statement_date,
cloud.account.uuid AS account_uuid,
cloud.account.account_name AS account_name,
cloud.account.state AS account_state,
cloud.account.removed AS account_removed,
cloud.domain.id AS domain_id,
cloud.domain.uuid AS domain_uuid,
cloud.domain.name AS domain_name,
cloud.domain.path AS domain_path,
cloud.domain.removed AS domain_removed,
cloud.projects.uuid AS project_uuid,
cloud.projects.name AS project_name,
cloud.projects.removed AS project_removed
FROM
cloud_usage.quota_account
INNER JOIN cloud.account ON (cloud.account.id = cloud_usage.quota_account.account_id)
INNER JOIN cloud.domain ON (cloud.domain.id = cloud.account.domain_id)
LEFT JOIN cloud.projects ON (cloud.account.type = 5 AND cloud.account.id = cloud.projects.project_account_id);

Some files were not shown because too many files have changed in this diff Show More