mirror of https://github.com/apache/cloudstack.git
resolve conflict with main
This commit is contained in:
commit
f524bbe0e2
|
|
@ -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
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ jobs:
|
|||
smoke/test_list_volumes"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -167,4 +167,6 @@ public interface Nic extends Identity, InternalIdentity {
|
|||
String getIPv6Address();
|
||||
|
||||
Integer getMtu();
|
||||
|
||||
boolean isEnabled();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
@SerializedName("dnsrecordurl")
|
||||
@Param(description = "Public IP address associated with this NIC via Static NAT rule")
|
||||
private String dnsRecordUrl;
|
||||
|
|
@ -421,6 +425,14 @@ public class NicResponse extends BaseResponse {
|
|||
this.publicIp = publicIp;
|
||||
}
|
||||
|
||||
public Boolean getEnabled() {
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
public void setEnabled(Boolean enabled) {
|
||||
isEnabled = enabled;
|
||||
}
|
||||
|
||||
public void setDnsRecordUrl(String dnsRecordUrl) {
|
||||
this.dnsRecordUrl = dnsRecordUrl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,11 +25,13 @@ 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);
|
||||
|
|
@ -37,6 +39,15 @@ public interface VolumeImportUnmanageService extends PluggableService {
|
|||
List<Storage.StoragePoolType> SUPPORTED_STORAGE_POOL_TYPES_FOR_KVM = Arrays.asList(Storage.StoragePoolType.NetworkFilesystem,
|
||||
Storage.StoragePoolType.Filesystem, Storage.StoragePoolType.RBD);
|
||||
|
||||
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);
|
||||
|
||||
VolumeResponse importVolume(ImportVolumeCmd cmd);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -231,6 +231,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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -6270,6 +6272,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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -2326,7 +2326,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 +2634,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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ 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;
|
||||
protected SearchBuilder<SnapshotVO> snapshotVOSearch;
|
||||
private SearchBuilder<SnapshotDataStoreVO> snapshotCreatedSearch;
|
||||
private SearchBuilder<SnapshotDataStoreVO> dataStoreAndInstallPathSearch;
|
||||
|
|
@ -146,10 +146,10 @@ 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();
|
||||
|
||||
snapshotVOSearch = snapshotDao.createSearchBuilder();
|
||||
snapshotVOSearch.and(VOLUME_ID, snapshotVOSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
|
||||
|
|
@ -480,7 +480,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 +488,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);
|
||||
|
|
|
|||
|
|
@ -18,3 +18,5 @@
|
|||
--;
|
||||
-- Schema upgrade cleanup from 4.22.0.0 to 4.22.1.0
|
||||
--;
|
||||
|
||||
DROP VIEW IF EXISTS `cloud`.`account_netstats_view`;
|
||||
|
|
|
|||
|
|
@ -33,3 +33,5 @@ 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';
|
||||
|
||||
UPDATE `cloud`.`vm_template` SET guest_os_id = 99 WHERE name = 'kvm-default-vm-import-dummy-template';
|
||||
|
|
|
|||
|
|
@ -115,6 +115,9 @@ 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'' ');
|
||||
|
||||
|
||||
-- ======================================================================
|
||||
-- DNS Framework Schema
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
-- 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.account_netstats_view source
|
||||
|
||||
|
||||
DROP VIEW IF EXISTS `cloud`.`account_netstats_view`;
|
||||
|
||||
CREATE VIEW `cloud`.`account_netstats_view` AS
|
||||
select
|
||||
`user_statistics`.`account_id` AS `account_id`,
|
||||
(sum(`user_statistics`.`net_bytes_received`) + sum(`user_statistics`.`current_bytes_received`)) AS `bytesReceived`,
|
||||
(sum(`user_statistics`.`net_bytes_sent`) + sum(`user_statistics`.`current_bytes_sent`)) AS `bytesSent`
|
||||
from
|
||||
`user_statistics`
|
||||
group by
|
||||
`user_statistics`.`account_id`;
|
||||
|
|
@ -39,8 +39,8 @@ select
|
|||
`data_center`.`id` AS `data_center_id`,
|
||||
`data_center`.`uuid` AS `data_center_uuid`,
|
||||
`data_center`.`name` AS `data_center_name`,
|
||||
`account_netstats_view`.`bytesReceived` AS `bytesReceived`,
|
||||
`account_netstats_view`.`bytesSent` AS `bytesSent`,
|
||||
`account_netstats`.`bytesReceived` AS `bytesReceived`,
|
||||
`account_netstats`.`bytesSent` AS `bytesSent`,
|
||||
`vmlimit`.`max` AS `vmLimit`,
|
||||
`vmcount`.`count` AS `vmTotal`,
|
||||
`runningvm`.`vmcount` AS `runningVms`,
|
||||
|
|
@ -89,8 +89,15 @@ from
|
|||
`cloud`.`domain` ON account.domain_id = domain.id
|
||||
left join
|
||||
`cloud`.`data_center` ON account.default_zone_id = data_center.id
|
||||
left join
|
||||
`cloud`.`account_netstats_view` ON account.id = account_netstats_view.account_id
|
||||
left join lateral (
|
||||
select
|
||||
coalesce(sum(`user_statistics`.`net_bytes_received` + `user_statistics`.`current_bytes_received`), 0) AS `bytesReceived`,
|
||||
coalesce(sum(`user_statistics`.`net_bytes_sent` + `user_statistics`.`current_bytes_sent`), 0) AS `bytesSent`
|
||||
from
|
||||
`cloud`.`user_statistics`
|
||||
where
|
||||
`user_statistics`.`account_id` = `account`.`id`
|
||||
) AS `account_netstats` ON TRUE
|
||||
left join
|
||||
`cloud`.`resource_limit` vmlimit ON account.id = vmlimit.account_id
|
||||
and vmlimit.type = 'user_vm' and vmlimit.tag IS NULL
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -141,6 +141,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`,
|
||||
`nic_details`.`value` AS `dns_record_url`,
|
||||
`vpc`.`id` AS `vpc_id`,
|
||||
`vpc`.`uuid` AS `vpc_uuid`,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -148,8 +148,8 @@ import java.util.HashSet;
|
|||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
import static org.apache.cloudstack.vm.UnmanagedVMsManagerImpl.KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME;
|
||||
import static org.apache.cloudstack.vm.UnmanagedVMsManagerImpl.VM_IMPORT_DEFAULT_TEMPLATE_NAME;
|
||||
import static org.apache.cloudstack.vm.UnmanagedVMsManager.KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME;
|
||||
import static org.apache.cloudstack.vm.UnmanagedVMsManager.VM_IMPORT_DEFAULT_TEMPLATE_NAME;
|
||||
|
||||
public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
protected Logger logger = LogManager.getLogger(getClass());
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ public class SequenceFetcher {
|
|||
try {
|
||||
return future.get();
|
||||
} catch (Exception e) {
|
||||
logger.warn("Unable to get sequeunce for " + tg.table() + ":" + tg.pkColumnValue(), e);
|
||||
logger.warn("Unable to get sequence for " + tg.table() + ":" + tg.pkColumnValue(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
// 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.quota;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public enum QuotaAccountStateFilter {
|
||||
ALL, ACTIVE, REMOVED;
|
||||
|
||||
public static QuotaAccountStateFilter getValue(String value) {
|
||||
if (StringUtils.isBlank(value)) {
|
||||
return null;
|
||||
}
|
||||
for (QuotaAccountStateFilter state : values()) {
|
||||
if (state.name().equalsIgnoreCase(value)) {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// 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.quota.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.quota.QuotaAccountStateFilter;
|
||||
import org.apache.cloudstack.quota.vo.QuotaSummaryVO;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface QuotaSummaryDao extends GenericDao<QuotaSummaryVO, Long> {
|
||||
|
||||
Pair<List<QuotaSummaryVO>, Integer> listQuotaSummariesForAccountAndOrDomain(Long accountId, String accountName, Long domainId, String domainPath,
|
||||
QuotaAccountStateFilter accountStateFilter, Long startIndex, Long pageSize);
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
// 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.quota.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.quota.QuotaAccountStateFilter;
|
||||
import org.apache.cloudstack.quota.vo.QuotaSummaryVO;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.db.TransactionCallback;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
|
||||
public class QuotaSummaryDaoImpl extends GenericDaoBase<QuotaSummaryVO, Long> implements QuotaSummaryDao {
|
||||
|
||||
@Override
|
||||
public Pair<List<QuotaSummaryVO>, Integer> listQuotaSummariesForAccountAndOrDomain(Long accountId, String accountName, Long domainId, String domainPath,
|
||||
QuotaAccountStateFilter accountStateFilter, Long startIndex, Long pageSize) {
|
||||
SearchCriteria<QuotaSummaryVO> searchCriteria = createListQuotaSummariesSearchCriteria(accountId, accountName, domainId, domainPath, accountStateFilter);
|
||||
Filter filter = new Filter(QuotaSummaryVO.class, "accountName", true, startIndex, pageSize);
|
||||
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<Pair<List<QuotaSummaryVO>, Integer>>) status -> searchAndCount(searchCriteria, filter));
|
||||
}
|
||||
|
||||
protected SearchCriteria<QuotaSummaryVO> createListQuotaSummariesSearchCriteria(Long accountId, String accountName, Long domainId, String domainPath,
|
||||
QuotaAccountStateFilter accountStateFilter) {
|
||||
SearchCriteria<QuotaSummaryVO> searchCriteria = createListQuotaSummariesSearchBuilder(accountStateFilter).create();
|
||||
|
||||
searchCriteria.setParametersIfNotNull("accountId", accountId);
|
||||
searchCriteria.setParametersIfNotNull("domainId", domainId);
|
||||
|
||||
if (accountName != null) {
|
||||
searchCriteria.setParameters("accountName", "%" + accountName + "%");
|
||||
}
|
||||
|
||||
if (domainPath != null) {
|
||||
searchCriteria.setParameters("domainPath", domainPath + "%");
|
||||
}
|
||||
|
||||
return searchCriteria;
|
||||
}
|
||||
|
||||
protected SearchBuilder<QuotaSummaryVO> createListQuotaSummariesSearchBuilder(QuotaAccountStateFilter accountStateFilter) {
|
||||
SearchBuilder<QuotaSummaryVO> searchBuilder = createSearchBuilder();
|
||||
|
||||
searchBuilder.and("accountId", searchBuilder.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
searchBuilder.and("accountName", searchBuilder.entity().getAccountName(), SearchCriteria.Op.LIKE);
|
||||
searchBuilder.and("domainId", searchBuilder.entity().getDomainId(), SearchCriteria.Op.EQ);
|
||||
searchBuilder.and("domainPath", searchBuilder.entity().getDomainPath(), SearchCriteria.Op.LIKE);
|
||||
|
||||
if (QuotaAccountStateFilter.REMOVED.equals(accountStateFilter)) {
|
||||
searchBuilder.and("accountRemoved", searchBuilder.entity().getAccountRemoved(), SearchCriteria.Op.NNULL);
|
||||
} else if (QuotaAccountStateFilter.ACTIVE.equals(accountStateFilter)) {
|
||||
searchBuilder.and("accountRemoved", searchBuilder.entity().getAccountRemoved(), SearchCriteria.Op.NULL);
|
||||
}
|
||||
|
||||
return searchBuilder;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
// 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.quota.vo;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@Entity
|
||||
@Table(name = "quota_summary_view")
|
||||
public class QuotaSummaryVO {
|
||||
|
||||
@Id
|
||||
@Column(name = "account_id")
|
||||
private Long accountId = null;
|
||||
|
||||
@Column(name = "quota_enforce")
|
||||
private Integer quotaEnforce = 0;
|
||||
|
||||
@Column(name = "quota_balance")
|
||||
private BigDecimal quotaBalance;
|
||||
|
||||
@Column(name = "quota_balance_date")
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date quotaBalanceDate = null;
|
||||
|
||||
@Column(name = "quota_min_balance")
|
||||
private BigDecimal quotaMinBalance;
|
||||
|
||||
@Column(name = "quota_alert_type")
|
||||
private Integer quotaAlertType = null;
|
||||
|
||||
@Column(name = "quota_alert_date")
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date quotaAlertDate = null;
|
||||
|
||||
@Column(name = "last_statement_date")
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date lastStatementDate = null;
|
||||
|
||||
@Column(name = "account_uuid")
|
||||
private String accountUuid;
|
||||
|
||||
@Column(name = "account_name")
|
||||
private String accountName;
|
||||
|
||||
@Column(name = "account_state")
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Account.State accountState;
|
||||
|
||||
@Column(name = "account_removed")
|
||||
private Date accountRemoved;
|
||||
|
||||
@Column(name = "domain_id")
|
||||
private Long domainId;
|
||||
|
||||
@Column(name = "domain_uuid")
|
||||
private String domainUuid;
|
||||
|
||||
@Column(name = "domain_name")
|
||||
private String domainName;
|
||||
|
||||
@Column(name = "domain_path")
|
||||
private String domainPath;
|
||||
|
||||
@Column(name = "domain_removed")
|
||||
private Date domainRemoved;
|
||||
|
||||
@Column(name = "project_uuid")
|
||||
private String projectUuid;
|
||||
|
||||
@Column(name = "project_name")
|
||||
private String projectName;
|
||||
|
||||
@Column(name = "project_removed")
|
||||
private Date projectRemoved;
|
||||
|
||||
public Long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public BigDecimal getQuotaBalance() {
|
||||
return quotaBalance;
|
||||
}
|
||||
|
||||
public String getAccountUuid() {
|
||||
return accountUuid;
|
||||
}
|
||||
|
||||
public String getAccountName() {
|
||||
return accountName;
|
||||
}
|
||||
|
||||
public Date getAccountRemoved() {
|
||||
return accountRemoved;
|
||||
}
|
||||
|
||||
public Account.State getAccountState() {
|
||||
return accountState;
|
||||
}
|
||||
|
||||
public Long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public String getDomainUuid() {
|
||||
return domainUuid;
|
||||
}
|
||||
|
||||
public String getDomainPath() {
|
||||
return domainPath;
|
||||
}
|
||||
|
||||
public Date getDomainRemoved() {
|
||||
return domainRemoved;
|
||||
}
|
||||
|
||||
public String getProjectUuid() {
|
||||
return projectUuid;
|
||||
}
|
||||
|
||||
public String getProjectName() {
|
||||
return projectName;
|
||||
}
|
||||
|
||||
public Date getProjectRemoved() {
|
||||
return projectRemoved;
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,8 @@
|
|||
|
||||
<bean id="presetVariableHelper" class="org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariableHelper" />
|
||||
<bean id="QuotaTariffDao" class="org.apache.cloudstack.quota.dao.QuotaTariffDaoImpl" />
|
||||
<bean id="QuotaAccountDao" class="org.apache.cloudstack.quota.dao.QuotaAccountDaoImpl" />
|
||||
<bean id="QuotaSummaryDao" class="org.apache.cloudstack.quota.dao.QuotaSummaryDaoImpl" />
|
||||
<bean id="QuotaAccountDao" class="org.apache.cloudstack.quota.dao.QuotaAccountDaoImpl" />
|
||||
<bean id="QuotaBalanceDao" class="org.apache.cloudstack.quota.dao.QuotaBalanceDaoImpl" />
|
||||
<bean id="QuotaCreditsDao" class="org.apache.cloudstack.quota.dao.QuotaCreditsDaoImpl" />
|
||||
<bean id="QuotaEmailTemplatesDao"
|
||||
|
|
|
|||
|
|
@ -16,61 +16,80 @@
|
|||
//under the License.
|
||||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
|
||||
import org.apache.cloudstack.api.ACL;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseListCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.AccountResponse;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.api.response.QuotaSummaryResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.api.response.ProjectResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.quota.QuotaAccountStateFilter;
|
||||
import org.apache.cloudstack.quota.QuotaService;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@APICommand(name = "quotaSummary", responseObject = QuotaSummaryResponse.class, description = "Lists balance and quota usage for all Accounts", since = "4.7.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
|
||||
httpMethod = "GET")
|
||||
@APICommand(name = "quotaSummary", responseObject = QuotaSummaryResponse.class, description = "Lists Quota balance summary of Accounts and Projects.", since = "4.7.0",
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, httpMethod = "GET")
|
||||
public class QuotaSummaryCmd extends BaseListCmd {
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, required = false, description = "Optional, Account Id for which statement needs to be generated")
|
||||
private String accountName;
|
||||
|
||||
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = false, entityType = DomainResponse.class, description = "Optional, If domain Id is given and the caller is domain admin then the statement is generated for domain.")
|
||||
private Long domainId;
|
||||
|
||||
@Parameter(name = ApiConstants.LIST_ALL, type = CommandType.BOOLEAN, required = false, description = "Optional, to list all Accounts irrespective of the quota activity")
|
||||
private Boolean listAll;
|
||||
@Inject
|
||||
QuotaResponseBuilder quotaResponseBuilder;
|
||||
|
||||
@Inject
|
||||
QuotaResponseBuilder _responseBuilder;
|
||||
QuotaService quotaService;
|
||||
|
||||
public QuotaSummaryCmd() {
|
||||
super();
|
||||
}
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class, description = "ID of the Account for which balance will be listed. Can not be specified with projectid.", since = "4.23.0")
|
||||
private Long accountId;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, required = false, description = "Name of the Account for which balance will be listed.")
|
||||
private String accountName;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = false, entityType = DomainResponse.class, description = "ID of the Domain for which balance will be listed. May be used individually or with accountname.")
|
||||
private Long domainId;
|
||||
|
||||
@Parameter(name = ApiConstants.LIST_ALL, type = CommandType.BOOLEAN, description = "False (default) lists the Quota balance summary for calling Account. True lists balance summary for " +
|
||||
"Accounts which the caller has access. If domain ID is informed, this parameter is considered as true.")
|
||||
private Boolean listAll;
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT_STATE_TO_SHOW, type = CommandType.STRING, description = "Possible values are [ALL, ACTIVE, REMOVED]. ALL will list summaries for " +
|
||||
"active and removed accounts; ACTIVE will list summaries only for active accounts; REMOVED will list summaries only for removed accounts. The default value is ACTIVE.",
|
||||
since = "4.23.0")
|
||||
private String accountStateToShow;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "ID of the Project for which balance will be listed. Can not be specified with accountId.", since = "4.23.0")
|
||||
private Long projectId;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
Pair<List<QuotaSummaryResponse>, Integer> responses;
|
||||
if (caller.getType() == Account.Type.ADMIN) {
|
||||
if (getAccountName() != null && getDomainId() != null)
|
||||
responses = _responseBuilder.createQuotaSummaryResponse(getAccountName(), getDomainId());
|
||||
else
|
||||
responses = _responseBuilder.createQuotaSummaryResponse(isListAll(), getKeyword(), getStartIndex(), getPageSizeVal());
|
||||
} else {
|
||||
responses = _responseBuilder.createQuotaSummaryResponse(caller.getAccountName(), caller.getDomainId());
|
||||
}
|
||||
final ListResponse<QuotaSummaryResponse> response = new ListResponse<QuotaSummaryResponse>();
|
||||
Pair<List<QuotaSummaryResponse>, Integer> responses = quotaResponseBuilder.createQuotaSummaryResponse(this);
|
||||
ListResponse<QuotaSummaryResponse> response = new ListResponse<>();
|
||||
response.setResponses(responses.first(), responses.second());
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(Long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public String getAccountName() {
|
||||
return accountName;
|
||||
}
|
||||
|
|
@ -88,16 +107,31 @@ public class QuotaSummaryCmd extends BaseListCmd {
|
|||
}
|
||||
|
||||
public Boolean isListAll() {
|
||||
return listAll == null ? false: listAll;
|
||||
// If a domain ID was specified, then allow listing all summaries of domain
|
||||
return ObjectUtils.defaultIfNull(listAll, Boolean.FALSE) || domainId != null;
|
||||
}
|
||||
|
||||
public void setListAll(Boolean listAll) {
|
||||
this.listAll = listAll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
public Long getProjectId() {
|
||||
return projectId;
|
||||
}
|
||||
|
||||
public QuotaAccountStateFilter getAccountStateToShow() {
|
||||
QuotaAccountStateFilter state = QuotaAccountStateFilter.getValue(accountStateToShow);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return QuotaAccountStateFilter.ACTIVE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
if (ObjectUtils.allNull(accountId, accountName, projectId)) {
|
||||
return -1;
|
||||
}
|
||||
return _accountService.finalizeAccountId(accountId, accountName, domainId, projectId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd;
|
|||
import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaPresetVariablesListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaStatementCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaSummaryCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffCreateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffUpdateCmd;
|
||||
|
|
@ -52,11 +53,7 @@ public interface QuotaResponseBuilder {
|
|||
|
||||
QuotaBalanceResponse createQuotaBalanceResponse(List<QuotaBalanceVO> quotaUsage, Date startDate, Date endDate);
|
||||
|
||||
Pair<List<QuotaSummaryResponse>, Integer> createQuotaSummaryResponse(Boolean listAll);
|
||||
|
||||
Pair<List<QuotaSummaryResponse>, Integer> createQuotaSummaryResponse(Boolean listAll, String keyword, Long startIndex, Long pageSize);
|
||||
|
||||
Pair<List<QuotaSummaryResponse>, Integer> createQuotaSummaryResponse(String accountName, Long domainId);
|
||||
Pair<List<QuotaSummaryResponse>, Integer> createQuotaSummaryResponse(QuotaSummaryCmd cmd);
|
||||
|
||||
QuotaBalanceResponse createQuotaLastBalanceResponse(List<QuotaBalanceVO> quotaBalance, Date startDate);
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,9 @@ import java.util.stream.Collectors;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.domain.Domain;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
import com.cloud.projects.dao.ProjectDao;
|
||||
import com.cloud.user.User;
|
||||
import com.cloud.user.UserVO;
|
||||
import com.cloud.utils.DateUtil;
|
||||
|
|
@ -56,6 +58,7 @@ import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd;
|
|||
import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaPresetVariablesListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaStatementCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaSummaryCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffCreateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffUpdateCmd;
|
||||
|
|
@ -74,11 +77,13 @@ import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariable
|
|||
import org.apache.cloudstack.quota.activationrule.presetvariables.Value;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
|
||||
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaBalanceDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaCreditsDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaEmailConfigurationDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaEmailTemplatesDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaSummaryDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaTariffDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
|
|
@ -86,10 +91,13 @@ import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
|||
import org.apache.cloudstack.quota.vo.QuotaCreditsVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailConfigurationVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaSummaryVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
import org.apache.cloudstack.utils.jsinterpreter.JsInterpreter;
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.compress.utils.Sets;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
|
|
@ -108,7 +116,6 @@ import com.cloud.user.AccountVO;
|
|||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.user.dao.UserDao;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.Filter;
|
||||
|
||||
@Component
|
||||
public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
||||
|
|
@ -121,7 +128,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
|||
@Inject
|
||||
private QuotaCreditsDao quotaCreditsDao;
|
||||
@Inject
|
||||
private QuotaUsageDao _quotaUsageDao;
|
||||
private QuotaUsageDao quotaUsageDao;
|
||||
@Inject
|
||||
private QuotaEmailTemplatesDao _quotaEmailTemplateDao;
|
||||
|
||||
|
|
@ -132,24 +139,30 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
|||
@Inject
|
||||
private AccountDao _accountDao;
|
||||
@Inject
|
||||
private ProjectDao projectDao;
|
||||
@Inject
|
||||
private QuotaAccountDao quotaAccountDao;
|
||||
@Inject
|
||||
private DomainDao _domainDao;
|
||||
private DomainDao domainDao;
|
||||
@Inject
|
||||
private AccountManager _accountMgr;
|
||||
@Inject
|
||||
private QuotaStatement _statement;
|
||||
private QuotaStatement quotaStatement;
|
||||
@Inject
|
||||
private QuotaManager _quotaManager;
|
||||
@Inject
|
||||
private QuotaEmailConfigurationDao quotaEmailConfigurationDao;
|
||||
@Inject
|
||||
private QuotaSummaryDao quotaSummaryDao;
|
||||
@Inject
|
||||
private JsInterpreterHelper jsInterpreterHelper;
|
||||
@Inject
|
||||
private ApiDiscoveryService apiDiscoveryService;
|
||||
|
||||
private final Class<?>[] assignableClasses = {GenericPresetVariable.class, ComputingResources.class};
|
||||
|
||||
private Set<Account.Type> accountTypesThatCanListAllQuotaSummaries = Sets.newHashSet(Account.Type.ADMIN, Account.Type.DOMAIN_ADMIN);
|
||||
|
||||
protected void checkActivationRulesAllowed(String activationRule) {
|
||||
if (!_quotaService.isJsInterpretationEnabled() && StringUtils.isNotEmpty(activationRule)) {
|
||||
throw new PermissionDeniedException("Quota Tariff Activation Rule cannot be set, as Javascript interpretation is disabled in the configuration.");
|
||||
|
|
@ -180,75 +193,113 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<QuotaSummaryResponse>, Integer> createQuotaSummaryResponse(final String accountName, final Long domainId) {
|
||||
List<QuotaSummaryResponse> result = new ArrayList<QuotaSummaryResponse>();
|
||||
public Pair<List<QuotaSummaryResponse>, Integer> createQuotaSummaryResponse(QuotaSummaryCmd cmd) {
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
if (accountName != null && domainId != null) {
|
||||
Account account = _accountDao.findActiveAccount(accountName, domainId);
|
||||
QuotaSummaryResponse qr = getQuotaSummaryResponse(account);
|
||||
result.add(qr);
|
||||
if (!accountTypesThatCanListAllQuotaSummaries.contains(caller.getType()) || !cmd.isListAll()) {
|
||||
return getQuotaSummaryResponse(cmd.getEntityOwnerId(), null, null, cmd);
|
||||
}
|
||||
|
||||
return new Pair<>(result, result.size());
|
||||
return getQuotaSummaryResponseWithListAll(cmd, caller);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<QuotaSummaryResponse>, Integer> createQuotaSummaryResponse(Boolean listAll) {
|
||||
return createQuotaSummaryResponse(listAll, null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<QuotaSummaryResponse>, Integer> createQuotaSummaryResponse(Boolean listAll, final String keyword, final Long startIndex, final Long pageSize) {
|
||||
List<QuotaSummaryResponse> result = new ArrayList<QuotaSummaryResponse>();
|
||||
Integer count = 0;
|
||||
if (listAll) {
|
||||
Filter filter = new Filter(AccountVO.class, "accountName", true, startIndex, pageSize);
|
||||
Pair<List<AccountVO>, Integer> data = _accountDao.findAccountsLike(keyword, filter);
|
||||
count = data.second();
|
||||
for (final AccountVO account : data.first()) {
|
||||
QuotaSummaryResponse qr = getQuotaSummaryResponse(account);
|
||||
result.add(qr);
|
||||
}
|
||||
} else {
|
||||
Pair<List<QuotaAccountVO>, Integer> data = quotaAccountDao.listAllQuotaAccount(startIndex, pageSize);
|
||||
count = data.second();
|
||||
for (final QuotaAccountVO quotaAccount : data.first()) {
|
||||
AccountVO account = _accountDao.findById(quotaAccount.getId());
|
||||
if (account == null) {
|
||||
continue;
|
||||
}
|
||||
QuotaSummaryResponse qr = getQuotaSummaryResponse(account);
|
||||
result.add(qr);
|
||||
protected Pair<List<QuotaSummaryResponse>, Integer> getQuotaSummaryResponseWithListAll(QuotaSummaryCmd cmd, Account caller) {
|
||||
Long domainId = cmd.getDomainId();
|
||||
if (domainId != null) {
|
||||
DomainVO domain = domainDao.findByIdIncludingRemoved(domainId);
|
||||
if (domain == null) {
|
||||
throw new InvalidParameterValueException(String.format("Domain [%s] does not exist.", domainId));
|
||||
}
|
||||
}
|
||||
return new Pair<>(result, count);
|
||||
|
||||
String domainPath = getDomainPathByDomainIdForDomainAdmin(caller);
|
||||
|
||||
Long accountId = cmd.getEntityOwnerId();
|
||||
if (accountId == -1) {
|
||||
accountId = cmd.isListAll() ? null : caller.getAccountId();
|
||||
}
|
||||
|
||||
return getQuotaSummaryResponse(accountId, domainId, domainPath, cmd);
|
||||
}
|
||||
|
||||
protected QuotaSummaryResponse getQuotaSummaryResponse(final Account account) {
|
||||
Calendar[] period = _statement.getCurrentStatementTime();
|
||||
|
||||
if (account != null) {
|
||||
QuotaSummaryResponse qr = new QuotaSummaryResponse();
|
||||
DomainVO domain = _domainDao.findById(account.getDomainId());
|
||||
BigDecimal curBalance = _quotaBalanceDao.lastQuotaBalance(account.getAccountId(), account.getDomainId(), period[1].getTime());
|
||||
BigDecimal quotaUsage = _quotaUsageDao.findTotalQuotaUsage(account.getAccountId(), account.getDomainId(), null, period[0].getTime(), period[1].getTime());
|
||||
|
||||
qr.setAccountId(account.getUuid());
|
||||
qr.setAccountName(account.getAccountName());
|
||||
qr.setDomainId(domain.getUuid());
|
||||
qr.setDomainName(domain.getName());
|
||||
qr.setBalance(curBalance);
|
||||
qr.setQuotaUsage(quotaUsage);
|
||||
qr.setState(account.getState());
|
||||
qr.setStartDate(period[0].getTime());
|
||||
qr.setEndDate(period[1].getTime());
|
||||
qr.setCurrency(QuotaConfig.QuotaCurrencySymbol.value());
|
||||
qr.setQuotaEnabled(QuotaConfig.QuotaAccountEnabled.valueIn(account.getId()));
|
||||
qr.setObjectName("summary");
|
||||
return qr;
|
||||
} else {
|
||||
return new QuotaSummaryResponse();
|
||||
/**
|
||||
* Retrieves the domain path of the caller's domain (if the caller is Domain Admin) for filtering in the quota summary query.
|
||||
* @return null if the caller is an Admin or the domain path of the caller's domain if the caller is a Domain Admin.
|
||||
* @throws InvalidParameterValueException if it cannot find the domain.
|
||||
*/
|
||||
protected String getDomainPathByDomainIdForDomainAdmin(Account caller) {
|
||||
if (caller.getType() != Account.Type.DOMAIN_ADMIN) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Long domainId = caller.getDomainId();
|
||||
Domain domain = domainDao.findById(domainId);
|
||||
_accountMgr.checkAccess(caller, domain);
|
||||
|
||||
if (domain == null) {
|
||||
throw new InvalidParameterValueException(String.format("Domain ID [%s] is invalid.", domainId));
|
||||
}
|
||||
|
||||
return domain.getPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>List</code> of <code>QuotaSummaryResponse</code> based on the provided parameters.
|
||||
* @param accountId ID of the Account to return the summaries for. If <code>-1</code>, either because no specific
|
||||
* Account was provided, or list all is disabled, then the summary is generated for the calling Account.
|
||||
* @param domainId ID of the Domain to return the summaries for.
|
||||
* @param domainPath path of the Domain to return the summaries for.
|
||||
*/
|
||||
protected Pair<List<QuotaSummaryResponse>, Integer> getQuotaSummaryResponse(Long accountId, Long domainId, String domainPath, QuotaSummaryCmd cmd) {
|
||||
if (accountId != null && accountId == -1) {
|
||||
accountId = CallContext.current().getCallingAccountId();
|
||||
}
|
||||
|
||||
Pair<List<QuotaSummaryVO>, Integer> pairSummaries = quotaSummaryDao.listQuotaSummariesForAccountAndOrDomain(accountId, cmd.getKeyword(), domainId, domainPath,
|
||||
cmd.getAccountStateToShow(), cmd.getStartIndex(), cmd.getPageSizeVal());
|
||||
List<QuotaSummaryVO> summaries = pairSummaries.first();
|
||||
|
||||
if (CollectionUtils.isEmpty(summaries)) {
|
||||
logger.info("There are no summaries to list for parameters [{}].", ReflectionToStringBuilderUtils.reflectOnlySelectedFields(cmd, "accountName", "domainId", "listAll", "page", "pageSize"));
|
||||
return new Pair<>(new ArrayList<>(), 0);
|
||||
}
|
||||
|
||||
List<QuotaSummaryResponse> responses = summaries.stream().map(this::getQuotaSummaryResponse).collect(Collectors.toList());
|
||||
|
||||
return new Pair<>(responses, pairSummaries.second());
|
||||
}
|
||||
|
||||
protected QuotaSummaryResponse getQuotaSummaryResponse(QuotaSummaryVO summary) {
|
||||
QuotaSummaryResponse response = new QuotaSummaryResponse();
|
||||
Account account = _accountDao.findByUuidIncludingRemoved(summary.getAccountUuid());
|
||||
|
||||
Calendar[] period = quotaStatement.getCurrentStatementTime();
|
||||
Date startDate = period[0].getTime();
|
||||
Date endDate = period[1].getTime();
|
||||
BigDecimal quotaUsage = quotaUsageDao.findTotalQuotaUsage(account.getAccountId(), account.getDomainId(), null, startDate, endDate);
|
||||
|
||||
response.setQuotaUsage(quotaUsage);
|
||||
response.setStartDate(startDate);
|
||||
response.setEndDate(endDate);
|
||||
response.setAccountId(summary.getAccountUuid());
|
||||
response.setAccountName(summary.getAccountName());
|
||||
response.setDomainId(summary.getDomainUuid());
|
||||
response.setDomainPath(summary.getDomainPath());
|
||||
response.setBalance(summary.getQuotaBalance());
|
||||
response.setState(summary.getAccountState());
|
||||
response.setCurrency(QuotaConfig.QuotaCurrencySymbol.value());
|
||||
response.setQuotaEnabled(QuotaConfig.QuotaAccountEnabled.valueIn(account.getId()));
|
||||
response.setDomainRemoved(summary.getDomainRemoved() != null);
|
||||
response.setAccountRemoved(summary.getAccountRemoved() != null);
|
||||
response.setObjectName("summary");
|
||||
|
||||
if (summary.getProjectUuid() != null) {
|
||||
response.setProjectId(summary.getProjectUuid());
|
||||
response.setProjectName(summary.getProjectName());
|
||||
response.setProjectRemoved(summary.getProjectRemoved() != null);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public boolean isUserAllowedToSeeActivationRules(User user) {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
package org.apache.cloudstack.api.response;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Date;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
|
@ -30,40 +29,48 @@ import com.cloud.user.Account.State;
|
|||
public class QuotaSummaryResponse extends BaseResponse {
|
||||
|
||||
@SerializedName("accountid")
|
||||
@Param(description = "Account ID")
|
||||
@Param(description = "Account's ID")
|
||||
private String accountId;
|
||||
|
||||
@SerializedName("account")
|
||||
@Param(description = "Account name")
|
||||
@Param(description = "Account's name")
|
||||
private String accountName;
|
||||
|
||||
@SerializedName("domainid")
|
||||
@Param(description = "Domain ID")
|
||||
@Param(description = "Domain's ID")
|
||||
private String domainId;
|
||||
|
||||
@SerializedName("domain")
|
||||
@Param(description = "Domain name")
|
||||
private String domainName;
|
||||
@Param(description = "Domain's path")
|
||||
private String domainPath;
|
||||
|
||||
@SerializedName("balance")
|
||||
@Param(description = "Account balance")
|
||||
@Param(description = "Account's balance")
|
||||
private BigDecimal balance;
|
||||
|
||||
@SerializedName("state")
|
||||
@Param(description = "Account state")
|
||||
@Param(description = "Account's state")
|
||||
private State state;
|
||||
|
||||
@SerializedName("domainremoved")
|
||||
@Param(description = "If the domain is removed or not", since = "4.23.0")
|
||||
private boolean domainRemoved;
|
||||
|
||||
@SerializedName("accountremoved")
|
||||
@Param(description = "If the account is removed or not", since = "4.23.0")
|
||||
private boolean accountRemoved;
|
||||
|
||||
@SerializedName("quota")
|
||||
@Param(description = "Quota usage of this period")
|
||||
@Param(description = "Quota consumed between the startdate and enddate")
|
||||
private BigDecimal quotaUsage;
|
||||
|
||||
@SerializedName("startdate")
|
||||
@Param(description = "Start date")
|
||||
private Date startDate = null;
|
||||
@Param(description = "Start date of the quota consumption")
|
||||
private Date startDate;
|
||||
|
||||
@SerializedName("enddate")
|
||||
@Param(description = "End date")
|
||||
private Date endDate = null;
|
||||
@Param(description = "End date of the quota consumption")
|
||||
private Date endDate;
|
||||
|
||||
@SerializedName("currency")
|
||||
@Param(description = "Currency")
|
||||
|
|
@ -73,9 +80,17 @@ public class QuotaSummaryResponse extends BaseResponse {
|
|||
@Param(description = "If the account has the quota config enabled")
|
||||
private boolean quotaEnabled;
|
||||
|
||||
public QuotaSummaryResponse() {
|
||||
super();
|
||||
}
|
||||
@SerializedName("projectname")
|
||||
@Param(description = "Name of the project", since = "4.23.0")
|
||||
private String projectName;
|
||||
|
||||
@SerializedName("projectid")
|
||||
@Param(description = "Project's id", since = "4.23.0")
|
||||
private String projectId;
|
||||
|
||||
@SerializedName("projectremoved")
|
||||
@Param(description = "Whether the project is removed or not", since = "4.23.0")
|
||||
private Boolean projectRemoved;
|
||||
|
||||
public String getAccountId() {
|
||||
return accountId;
|
||||
|
|
@ -101,28 +116,16 @@ public class QuotaSummaryResponse extends BaseResponse {
|
|||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
public String getDomainName() {
|
||||
return domainName;
|
||||
}
|
||||
|
||||
public void setDomainName(String domainName) {
|
||||
this.domainName = domainName;
|
||||
}
|
||||
|
||||
public BigDecimal getQuotaUsage() {
|
||||
return quotaUsage;
|
||||
}
|
||||
|
||||
public State getState() {
|
||||
return state;
|
||||
public void setDomainPath(String domainPath) {
|
||||
this.domainPath = domainPath;
|
||||
}
|
||||
|
||||
public void setState(State state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public void setQuotaUsage(BigDecimal startQuota) {
|
||||
this.quotaUsage = startQuota.setScale(2, RoundingMode.HALF_EVEN);
|
||||
public void setQuotaUsage(BigDecimal quotaUsage) {
|
||||
this.quotaUsage = quotaUsage;
|
||||
}
|
||||
|
||||
public BigDecimal getBalance() {
|
||||
|
|
@ -130,38 +133,42 @@ public class QuotaSummaryResponse extends BaseResponse {
|
|||
}
|
||||
|
||||
public void setBalance(BigDecimal balance) {
|
||||
this.balance = balance.setScale(2, RoundingMode.HALF_EVEN);
|
||||
}
|
||||
|
||||
public Date getStartDate() {
|
||||
return startDate == null ? null : new Date(startDate.getTime());
|
||||
this.balance = balance;
|
||||
}
|
||||
|
||||
public void setStartDate(Date startDate) {
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
public Date getEndDate() {
|
||||
return endDate == null ? null : new Date(endDate.getTime());
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
public String getCurrency() {
|
||||
return currency;
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public void setCurrency(String currency) {
|
||||
this.currency = currency;
|
||||
}
|
||||
|
||||
public boolean getQuotaEnabled() {
|
||||
return quotaEnabled;
|
||||
}
|
||||
|
||||
public void setQuotaEnabled(boolean quotaEnabled) {
|
||||
this.quotaEnabled = quotaEnabled;
|
||||
}
|
||||
|
||||
public void setProjectName(String projectName) {
|
||||
this.projectName = projectName;
|
||||
}
|
||||
|
||||
public void setProjectId(String projectId) {
|
||||
this.projectId = projectId;
|
||||
}
|
||||
|
||||
public void setProjectRemoved(Boolean projectRemoved) {
|
||||
this.projectRemoved = projectRemoved;
|
||||
}
|
||||
|
||||
public void setDomainRemoved(boolean domainRemoved) {
|
||||
this.domainRemoved = domainRemoved;
|
||||
}
|
||||
|
||||
public void setAccountRemoved(boolean accountRemoved) {
|
||||
this.accountRemoved = accountRemoved;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ import java.util.TimeZone;
|
|||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.projects.ProjectManager;
|
||||
import com.cloud.user.AccountService;
|
||||
import org.apache.cloudstack.api.command.QuotaBalanceCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaConfigureEmailCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaCreditsCmd;
|
||||
|
|
@ -75,6 +77,8 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi
|
|||
@Inject
|
||||
private AccountDao _accountDao;
|
||||
@Inject
|
||||
private AccountService accountService;
|
||||
@Inject
|
||||
private QuotaAccountDao _quotaAcc;
|
||||
@Inject
|
||||
private QuotaUsageDao _quotaUsageDao;
|
||||
|
|
@ -86,6 +90,8 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi
|
|||
private QuotaBalanceDao _quotaBalanceDao;
|
||||
@Inject
|
||||
private QuotaResponseBuilder _respBldr;
|
||||
@Inject
|
||||
private ProjectManager projectMgr;
|
||||
|
||||
private TimeZone _usageTimezone;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,13 +16,11 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.api.response;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
|
@ -31,6 +29,7 @@ import java.util.Set;
|
|||
import java.util.HashSet;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.cloud.domain.Domain;
|
||||
import com.cloud.domain.DomainVO;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
|
|
@ -43,10 +42,10 @@ import org.apache.cloudstack.api.command.QuotaConfigureEmailCmd;
|
|||
import org.apache.cloudstack.api.command.QuotaCreditsListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaSummaryCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaValidateActivationRuleCmd;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.discovery.ApiDiscoveryService;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.jsinterpreter.JsInterpreterHelper;
|
||||
import org.apache.cloudstack.quota.QuotaService;
|
||||
import org.apache.cloudstack.quota.QuotaStatement;
|
||||
|
|
@ -79,7 +78,10 @@ import org.junit.runner.RunWith;
|
|||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedConstruction;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.user.Account;
|
||||
|
|
@ -89,8 +91,7 @@ import com.cloud.user.dao.UserDao;
|
|||
import com.cloud.user.User;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuotaResponseBuilderImplTest extends TestCase {
|
||||
|
|
@ -153,7 +154,7 @@ public class QuotaResponseBuilderImplTest extends TestCase {
|
|||
Account accountMock;
|
||||
|
||||
@Mock
|
||||
DomainVO domainVOMock;
|
||||
DomainVO domainVoMock;
|
||||
|
||||
@Mock
|
||||
QuotaConfigureEmailCmd quotaConfigureEmailCmdMock;
|
||||
|
|
@ -161,6 +162,9 @@ public class QuotaResponseBuilderImplTest extends TestCase {
|
|||
@Mock
|
||||
QuotaAccountVO quotaAccountVOMock;
|
||||
|
||||
@Mock
|
||||
CallContext callContextMock;
|
||||
|
||||
@Mock
|
||||
QuotaEmailTemplatesVO quotaEmailTemplatesVoMock;
|
||||
|
||||
|
|
@ -184,17 +188,8 @@ public class QuotaResponseBuilderImplTest extends TestCase {
|
|||
CallContext.register(callerUserMock, callerAccountMock);
|
||||
}
|
||||
|
||||
private void overrideDefaultQuotaEnabledConfigValue(final Object value) throws IllegalAccessException, NoSuchFieldException {
|
||||
Field f = ConfigKey.class.getDeclaredField("_defaultValue");
|
||||
f.setAccessible(true);
|
||||
f.set(QuotaConfig.QuotaAccountEnabled, value);
|
||||
}
|
||||
|
||||
private Calendar[] createPeriodForQuotaSummary() {
|
||||
final Calendar calendar = Calendar.getInstance();
|
||||
calendar.set(Calendar.HOUR, 0);
|
||||
return new Calendar[] {calendar, calendar};
|
||||
}
|
||||
@Mock
|
||||
Pair<List<QuotaSummaryResponse>, Integer> quotaSummaryResponseMock1, quotaSummaryResponseMock2;
|
||||
|
||||
@Mock
|
||||
QuotaValidateActivationRuleCmd quotaValidateActivationRuleCmdMock = Mockito.mock(QuotaValidateActivationRuleCmd.class);
|
||||
|
|
@ -466,36 +461,6 @@ public class QuotaResponseBuilderImplTest extends TestCase {
|
|||
Mockito.verify(quotaTariffVoMock).setRemoved(Mockito.any(Date.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getQuotaSummaryResponseTestAccountIsNotNullQuotaIsDisabledShouldReturnFalse() throws NoSuchFieldException, IllegalAccessException {
|
||||
Calendar[] period = createPeriodForQuotaSummary();
|
||||
overrideDefaultQuotaEnabledConfigValue("false");
|
||||
|
||||
Mockito.doReturn(period).when(quotaStatementMock).getCurrentStatementTime();
|
||||
Mockito.doReturn(domainVOMock).when(domainDaoMock).findById(Mockito.anyLong());
|
||||
Mockito.doReturn(BigDecimal.ZERO).when(quotaBalanceDaoMock).lastQuotaBalance(Mockito.anyLong(), Mockito.anyLong(), Mockito.any(Date.class));
|
||||
Mockito.doReturn(BigDecimal.ZERO).when(quotaUsageDaoMock).findTotalQuotaUsage(Mockito.anyLong(), Mockito.anyLong(), Mockito.isNull(), Mockito.any(Date.class), Mockito.any(Date.class));
|
||||
|
||||
QuotaSummaryResponse quotaSummaryResponse = quotaResponseBuilderSpy.getQuotaSummaryResponse(accountMock);
|
||||
|
||||
assertFalse(quotaSummaryResponse.getQuotaEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getQuotaSummaryResponseTestAccountIsNotNullQuotaIsEnabledShouldReturnTrue() throws NoSuchFieldException, IllegalAccessException {
|
||||
Calendar[] period = createPeriodForQuotaSummary();
|
||||
overrideDefaultQuotaEnabledConfigValue("true");
|
||||
|
||||
Mockito.doReturn(period).when(quotaStatementMock).getCurrentStatementTime();
|
||||
Mockito.doReturn(domainVOMock).when(domainDaoMock).findById(Mockito.anyLong());
|
||||
Mockito.doReturn(BigDecimal.ZERO).when(quotaBalanceDaoMock).lastQuotaBalance(Mockito.anyLong(), Mockito.anyLong(), Mockito.any(Date.class));
|
||||
Mockito.doReturn(BigDecimal.ZERO).when(quotaUsageDaoMock).findTotalQuotaUsage(Mockito.anyLong(), Mockito.anyLong(), Mockito.isNull(), Mockito.any(Date.class), Mockito.any(Date.class));
|
||||
|
||||
QuotaSummaryResponse quotaSummaryResponse = quotaResponseBuilderSpy.getQuotaSummaryResponse(accountMock);
|
||||
|
||||
assertTrue(quotaSummaryResponse.getQuotaEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterSupportedTypesTestReturnWhenQuotaTypeDoesNotMatch() throws NoSuchFieldException {
|
||||
List<Pair<String, String>> variables = new ArrayList<>();
|
||||
|
|
@ -576,6 +541,63 @@ public class QuotaResponseBuilderImplTest extends TestCase {
|
|||
quotaResponseBuilderSpy.validateQuotaConfigureEmailCmdParameters(quotaConfigureEmailCmdMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createQuotaSummaryResponseTestNotListAllAndAllAccountTypesReturnsSingleRecord() {
|
||||
QuotaSummaryCmd cmd = new QuotaSummaryCmd();
|
||||
|
||||
try(MockedStatic<CallContext> callContextMocked = Mockito.mockStatic(CallContext.class)) {
|
||||
callContextMocked.when(CallContext::current).thenReturn(callContextMock);
|
||||
|
||||
Mockito.doReturn(accountMock).when(callContextMock).getCallingAccount();
|
||||
|
||||
Mockito.doReturn(quotaSummaryResponseMock1).when(quotaResponseBuilderSpy).getQuotaSummaryResponse(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
|
||||
for (Account.Type type : Account.Type.values()) {
|
||||
Mockito.doReturn(type).when(accountMock).getType();
|
||||
|
||||
Pair<List<QuotaSummaryResponse>, Integer> result = quotaResponseBuilderSpy.createQuotaSummaryResponse(cmd);
|
||||
Assert.assertEquals(quotaSummaryResponseMock1, result);
|
||||
}
|
||||
|
||||
Mockito.verify(quotaResponseBuilderSpy, Mockito.times(Account.Type.values().length)).getQuotaSummaryResponse(Mockito.any(), Mockito.any(), Mockito.any(),
|
||||
Mockito.any());
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDomainPathByDomainIdForDomainAdminTestAccountNotDomainAdminReturnsNull() {
|
||||
for (Account.Type type : Account.Type.values()) {
|
||||
if (Account.Type.DOMAIN_ADMIN.equals(type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Mockito.doReturn(type).when(accountMock).getType();
|
||||
Assert.assertNull(quotaResponseBuilderSpy.getDomainPathByDomainIdForDomainAdmin(accountMock));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void getDomainPathByDomainIdForDomainAdminTestDomainFromCallerIsNullThrowsInvalidParameterValueException() {
|
||||
Mockito.doReturn(Account.Type.DOMAIN_ADMIN).when(accountMock).getType();
|
||||
Mockito.doReturn(null).when(domainDaoMock).findById(Mockito.anyLong());
|
||||
Mockito.lenient().doNothing().when(accountManagerMock).checkAccess(Mockito.any(Account.class), Mockito.any(Domain.class));
|
||||
|
||||
quotaResponseBuilderSpy.getDomainPathByDomainIdForDomainAdmin(accountMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDomainPathByDomainIdForDomainAdminTestDomainFromCallerIsNotNullReturnsPath() {
|
||||
String expected = "/test/";
|
||||
|
||||
Mockito.doReturn(Account.Type.DOMAIN_ADMIN).when(accountMock).getType();
|
||||
Mockito.doReturn(domainVoMock).when(domainDaoMock).findById(Mockito.anyLong());
|
||||
Mockito.doNothing().when(accountManagerMock).checkAccess(Mockito.any(Account.class), Mockito.any(Domain.class));
|
||||
Mockito.doReturn(expected).when(domainVoMock).getPath();
|
||||
|
||||
String result = quotaResponseBuilderSpy.getDomainPathByDomainIdForDomainAdmin(accountMock);
|
||||
Assert.assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getQuotaEmailConfigurationVoTestTemplateNameIsNull() {
|
||||
Mockito.doReturn(null).when(quotaConfigureEmailCmdMock).getTemplateName();
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package org.apache.cloudstack.quota;
|
|||
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import junit.framework.TestCase;
|
||||
|
|
@ -33,8 +34,10 @@ import org.joda.time.DateTime;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
|
@ -48,7 +51,7 @@ import java.util.List;
|
|||
public class QuotaServiceImplTest extends TestCase {
|
||||
|
||||
@Mock
|
||||
AccountDao accountDao;
|
||||
AccountDao accountDaoMock;
|
||||
@Mock
|
||||
QuotaAccountDao quotaAcc;
|
||||
@Mock
|
||||
|
|
@ -61,8 +64,13 @@ public class QuotaServiceImplTest extends TestCase {
|
|||
QuotaBalanceDao quotaBalanceDao;
|
||||
@Mock
|
||||
QuotaResponseBuilder respBldr;
|
||||
@Mock
|
||||
private AccountVO accountVoMock;
|
||||
|
||||
@Spy
|
||||
@InjectMocks
|
||||
QuotaServiceImpl quotaServiceImplSpy;
|
||||
|
||||
QuotaServiceImpl quotaService = new QuotaServiceImpl();
|
||||
|
||||
@Before
|
||||
public void setup() throws IllegalAccessException, NoSuchFieldException, ConfigurationException {
|
||||
|
|
@ -71,34 +79,34 @@ public class QuotaServiceImplTest extends TestCase {
|
|||
|
||||
Field accountDaoField = QuotaServiceImpl.class.getDeclaredField("_accountDao");
|
||||
accountDaoField.setAccessible(true);
|
||||
accountDaoField.set(quotaService, accountDao);
|
||||
accountDaoField.set(quotaServiceImplSpy, accountDaoMock);
|
||||
|
||||
Field quotaAccountDaoField = QuotaServiceImpl.class.getDeclaredField("_quotaAcc");
|
||||
quotaAccountDaoField.setAccessible(true);
|
||||
quotaAccountDaoField.set(quotaService, quotaAcc);
|
||||
quotaAccountDaoField.set(quotaServiceImplSpy, quotaAcc);
|
||||
|
||||
Field quotaUsageDaoField = QuotaServiceImpl.class.getDeclaredField("_quotaUsageDao");
|
||||
quotaUsageDaoField.setAccessible(true);
|
||||
quotaUsageDaoField.set(quotaService, quotaUsageDao);
|
||||
quotaUsageDaoField.set(quotaServiceImplSpy, quotaUsageDao);
|
||||
|
||||
Field domainDaoField = QuotaServiceImpl.class.getDeclaredField("_domainDao");
|
||||
domainDaoField.setAccessible(true);
|
||||
domainDaoField.set(quotaService, domainDao);
|
||||
domainDaoField.set(quotaServiceImplSpy, domainDao);
|
||||
|
||||
Field configDaoField = QuotaServiceImpl.class.getDeclaredField("_configDao");
|
||||
configDaoField.setAccessible(true);
|
||||
configDaoField.set(quotaService, configDao);
|
||||
configDaoField.set(quotaServiceImplSpy, configDao);
|
||||
|
||||
Field balanceDaoField = QuotaServiceImpl.class.getDeclaredField("_quotaBalanceDao");
|
||||
balanceDaoField.setAccessible(true);
|
||||
balanceDaoField.set(quotaService, quotaBalanceDao);
|
||||
balanceDaoField.set(quotaServiceImplSpy, quotaBalanceDao);
|
||||
|
||||
Field QuotaResponseBuilderField = QuotaServiceImpl.class.getDeclaredField("_respBldr");
|
||||
QuotaResponseBuilderField.setAccessible(true);
|
||||
QuotaResponseBuilderField.set(quotaService, respBldr);
|
||||
QuotaResponseBuilderField.set(quotaServiceImplSpy, respBldr);
|
||||
|
||||
Mockito.when(configDao.getValue(Mockito.eq(Config.UsageAggregationTimezone.toString()))).thenReturn("IST");
|
||||
quotaService.configure("randomName", null);
|
||||
quotaServiceImplSpy.configure("randomName", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -120,9 +128,9 @@ public class QuotaServiceImplTest extends TestCase {
|
|||
Mockito.when(quotaBalanceDao.lastQuotaBalanceVO(Mockito.eq(accountId), Mockito.eq(domainId), Mockito.any(Date.class))).thenReturn(records);
|
||||
|
||||
// with enddate
|
||||
assertTrue(quotaService.findQuotaBalanceVO(accountId, accountName, domainId, startDate, endDate).get(0).equals(qb));
|
||||
assertTrue(quotaServiceImplSpy.findQuotaBalanceVO(accountId, accountName, domainId, startDate, endDate).get(0).equals(qb));
|
||||
// without enddate
|
||||
assertTrue(quotaService.findQuotaBalanceVO(accountId, accountName, domainId, startDate, null).get(0).equals(qb));
|
||||
assertTrue(quotaServiceImplSpy.findQuotaBalanceVO(accountId, accountName, domainId, startDate, null).get(0).equals(qb));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -133,7 +141,7 @@ public class QuotaServiceImplTest extends TestCase {
|
|||
final Date startDate = new DateTime().minusDays(2).toDate();
|
||||
final Date endDate = new Date();
|
||||
|
||||
quotaService.getQuotaUsage(accountId, accountName, domainId, QuotaTypes.IP_ADDRESS, startDate, endDate);
|
||||
quotaServiceImplSpy.getQuotaUsage(accountId, accountName, domainId, QuotaTypes.IP_ADDRESS, startDate, endDate);
|
||||
Mockito.verify(quotaUsageDao, Mockito.times(1)).findQuotaUsage(Mockito.eq(accountId), Mockito.eq(domainId), Mockito.eq(QuotaTypes.IP_ADDRESS), Mockito.any(Date.class), Mockito.any(Date.class));
|
||||
}
|
||||
|
||||
|
|
@ -142,13 +150,13 @@ public class QuotaServiceImplTest extends TestCase {
|
|||
// existing account
|
||||
QuotaAccountVO quotaAccountVO = new QuotaAccountVO();
|
||||
Mockito.when(quotaAcc.findByIdQuotaAccount(Mockito.anyLong())).thenReturn(quotaAccountVO);
|
||||
quotaService.setLockAccount(2L, true);
|
||||
quotaServiceImplSpy.setLockAccount(2L, true);
|
||||
Mockito.verify(quotaAcc, Mockito.times(0)).persistQuotaAccount(Mockito.any(QuotaAccountVO.class));
|
||||
Mockito.verify(quotaAcc, Mockito.times(1)).updateQuotaAccount(Mockito.anyLong(), Mockito.any(QuotaAccountVO.class));
|
||||
|
||||
// new account
|
||||
Mockito.when(quotaAcc.findByIdQuotaAccount(Mockito.anyLong())).thenReturn(null);
|
||||
quotaService.setLockAccount(2L, true);
|
||||
quotaServiceImplSpy.setLockAccount(2L, true);
|
||||
Mockito.verify(quotaAcc, Mockito.times(1)).persistQuotaAccount(Mockito.any(QuotaAccountVO.class));
|
||||
}
|
||||
|
||||
|
|
@ -160,13 +168,14 @@ public class QuotaServiceImplTest extends TestCase {
|
|||
// existing account setting
|
||||
QuotaAccountVO quotaAccountVO = new QuotaAccountVO();
|
||||
Mockito.when(quotaAcc.findByIdQuotaAccount(Mockito.anyLong())).thenReturn(quotaAccountVO);
|
||||
quotaService.setMinBalance(accountId, balance);
|
||||
quotaServiceImplSpy.setMinBalance(accountId, balance);
|
||||
Mockito.verify(quotaAcc, Mockito.times(0)).persistQuotaAccount(Mockito.any(QuotaAccountVO.class));
|
||||
Mockito.verify(quotaAcc, Mockito.times(1)).updateQuotaAccount(Mockito.anyLong(), Mockito.any(QuotaAccountVO.class));
|
||||
|
||||
// no account with limit set
|
||||
Mockito.when(quotaAcc.findByIdQuotaAccount(Mockito.anyLong())).thenReturn(null);
|
||||
quotaService.setMinBalance(accountId, balance);
|
||||
quotaServiceImplSpy.setMinBalance(accountId, balance);
|
||||
Mockito.verify(quotaAcc, Mockito.times(1)).persistQuotaAccount(Mockito.any(QuotaAccountVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
<appender-ref ref="EventLogAppender"/>
|
||||
</root>
|
||||
</log4net>
|
||||
|
||||
|
||||
<applicationSettings>
|
||||
<CloudStack.Plugin.AgentShell.AgentSettings>
|
||||
<setting name="cpus" serializeAs="String">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!--
|
||||
<!--
|
||||
Note: Add entries to the App.config file for configuration settings
|
||||
that apply only to the Test project.
|
||||
-->
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
<!--
|
||||
Note: Add entries to the App.config file for configuration settings
|
||||
that apply only to the Test project.
|
||||
-->
|
||||
|
|
|
|||
|
|
@ -275,6 +275,7 @@ public class BridgeVifDriver extends VifDriverBase {
|
|||
if (nic.getPxeDisable()) {
|
||||
intf.setPxeDisable(true);
|
||||
}
|
||||
intf.setLinkStateUp(nic.isEnabled());
|
||||
|
||||
return intf;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4851,6 +4851,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
}
|
||||
}
|
||||
|
||||
public InterfaceDef getInterface(final Connect conn, final String vmName, final String macAddress) {
|
||||
List<InterfaceDef> interfaces = getInterfaces(conn, vmName);
|
||||
return interfaces.stream().filter(interfaceDef -> interfaceDef.getMacAddress().equals(macAddress))
|
||||
.findFirst().orElseThrow(() -> new CloudRuntimeException(String.format("Unable to find NIC with MAC address %s.", macAddress)));
|
||||
}
|
||||
|
||||
public List<DiskDef> getDisks(final Connect conn, final String vmName) {
|
||||
final LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser();
|
||||
Domain dm = null;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ package com.cloud.hypervisor.kvm.resource.wrapper;
|
|||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.GetRemoteVmsAnswer;
|
||||
import com.cloud.agent.api.GetRemoteVmsCommand;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtConnection;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtDomainXMLParser;
|
||||
|
|
@ -97,6 +98,7 @@ public final class LibvirtGetRemoteVmsCommandWrapper extends CommandWrapper<GetR
|
|||
if (parser.getCpuTuneDef() !=null) {
|
||||
instance.setCpuSpeed(parser.getCpuTuneDef().getShares());
|
||||
}
|
||||
instance.setHypervisorType(Hypervisor.HypervisorType.KVM.name());
|
||||
instance.setPowerState(getPowerState(libvirtComputingResource.getVmState(conn,domain.getName())));
|
||||
instance.setNics(getUnmanagedInstanceNics(parser.getInterfaces()));
|
||||
instance.setDisks(getUnmanagedInstanceDisks(parser.getDisks(),libvirtComputingResource, domain));
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package com.cloud.hypervisor.kvm.resource.wrapper;
|
|||
|
||||
import com.cloud.agent.api.GetUnmanagedInstancesAnswer;
|
||||
import com.cloud.agent.api.GetUnmanagedInstancesCommand;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtDomainXMLParser;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef;
|
||||
|
|
@ -130,6 +131,7 @@ public final class LibvirtGetUnmanagedInstancesCommandWrapper extends CommandWra
|
|||
if (parser.getCpuModeDef() != null) {
|
||||
instance.setCpuCoresPerSocket(parser.getCpuModeDef().getCoresPerSocket());
|
||||
}
|
||||
instance.setHypervisorType(Hypervisor.HypervisorType.KVM.name());
|
||||
instance.setPowerState(getPowerState(libvirtComputingResource.getVmState(conn,domain.getName())));
|
||||
instance.setMemory((int) LibvirtComputingResource.getDomainMemory(domain) / 1024);
|
||||
instance.setNics(getUnmanagedInstanceNics(libvirtComputingResource, parser.getInterfaces()));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
//
|
||||
// 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.hypervisor.kvm.resource.wrapper;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.UpdateVmNicAnswer;
|
||||
import com.cloud.agent.api.UpdateVmNicCommand;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef;
|
||||
import com.cloud.resource.CommandWrapper;
|
||||
import com.cloud.resource.ResourceWrapper;
|
||||
import org.libvirt.Connect;
|
||||
import org.libvirt.Domain;
|
||||
import org.libvirt.LibvirtException;
|
||||
|
||||
@ResourceWrapper(handles = UpdateVmNicCommand.class)
|
||||
public final class LibvirtUpdateVmNicCommandWrapper extends CommandWrapper<UpdateVmNicCommand, Answer, LibvirtComputingResource> {
|
||||
|
||||
@Override
|
||||
public Answer execute(UpdateVmNicCommand command, LibvirtComputingResource libvirtComputingResource) {
|
||||
String nicMacAddress = command.getNicMacAddress();
|
||||
String vmName = command.getVmName();
|
||||
boolean isEnabled = command.isEnabled();
|
||||
|
||||
Domain vm = null;
|
||||
try {
|
||||
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(vmName);
|
||||
vm = libvirtComputingResource.getDomain(conn, vmName);
|
||||
|
||||
final InterfaceDef nic = libvirtComputingResource.getInterface(conn, vmName, nicMacAddress);
|
||||
nic.setLinkStateUp(isEnabled);
|
||||
vm.updateDeviceFlags(nic.toString(), Domain.DeviceModifyFlags.LIVE);
|
||||
|
||||
return new UpdateVmNicAnswer(command, true, "success");
|
||||
} catch (final LibvirtException e) {
|
||||
final String msg = String.format(" Update NIC failed due to %s.", e);
|
||||
logger.warn(msg, e);
|
||||
return new UpdateVmNicAnswer(command, false, msg);
|
||||
} finally {
|
||||
if (vm != null) {
|
||||
try {
|
||||
vm.free();
|
||||
} catch (final LibvirtException l) {
|
||||
logger.trace("Ignoring libvirt error.", l);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7203,4 +7203,35 @@ public class LibvirtComputingResourceTest {
|
|||
libvirtComputingResourceSpy.defineDiskForDefaultPoolType(diskDef, volume, false, false, false, physicalDisk, DEV_ID, DISK_BUS_TYPE, DISK_BUS_TYPE_DATA, null);
|
||||
Mockito.verify(diskDef).defFileBasedDisk(PHYSICAL_DISK_PATH, DEV_ID, DISK_BUS_TYPE_DATA, DiskDef.DiskFmtType.QCOW2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInterfaceTestValidMacAddressReturnInterface() {
|
||||
String macAddress = "a0:90:27:a9:9e:62";
|
||||
final String vmName = "Test";
|
||||
final InterfaceDef interfaceDef = Mockito.mock(InterfaceDef.class);
|
||||
final List<InterfaceDef> interfaces = new ArrayList<>();
|
||||
interfaces.add(interfaceDef);
|
||||
|
||||
Mockito.doReturn(macAddress).when(interfaceDef).getMacAddress();
|
||||
Mockito.doReturn(interfaces).when(libvirtComputingResourceSpy).getInterfaces(Mockito.any(), Mockito.anyString());
|
||||
|
||||
InterfaceDef result = libvirtComputingResourceSpy.getInterface(connMock, vmName, macAddress);
|
||||
|
||||
Assert.assertNotNull(result);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void getInterfaceTestInvalidMacAddressThrowCloudRuntimeException() {
|
||||
String invalidMacAddress = "ea:57:5d:f1:64:05";
|
||||
String macAddress = "a0:90:27:a9:9e:62";
|
||||
final String vmName = "Test";
|
||||
final InterfaceDef interfaceDef = Mockito.mock(InterfaceDef.class);
|
||||
final List<InterfaceDef> interfaces = new ArrayList<>();
|
||||
interfaces.add(interfaceDef);
|
||||
|
||||
Mockito.doReturn(macAddress).when(interfaceDef).getMacAddress();
|
||||
Mockito.doReturn(interfaces).when(libvirtComputingResourceSpy).getInterfaces(Mockito.any(), Mockito.anyString());
|
||||
|
||||
libvirtComputingResourceSpy.getInterface(connMock, vmName, invalidMacAddress);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,11 +171,20 @@ public class KubernetesClusterUtil {
|
|||
// Check if dashboard service is up running.
|
||||
while (System.currentTimeMillis() < timeoutTime) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(String.format("Checking dashboard service for the Kubernetes cluster: %s to come up", kubernetesCluster));
|
||||
LOGGER.debug(String.format("Checking dashboard service (Kubernetes Dashboard or Headlamp) for the Kubernetes cluster: %s to come up", kubernetesCluster));
|
||||
}
|
||||
// Check for Headlamp (new dashboard) in kube-system namespace
|
||||
if (isKubernetesClusterAddOnServiceRunning(kubernetesCluster, ipAddress, port, user, sshKeyFile, "kube-system", "headlamp")) {
|
||||
if (LOGGER.isInfoEnabled()) {
|
||||
LOGGER.info(String.format("Headlamp dashboard service for the Kubernetes cluster %s is in running state", kubernetesCluster));
|
||||
}
|
||||
running = true;
|
||||
break;
|
||||
}
|
||||
// For backward compatibility, check for Kubernetes Dashboard in kubernetes-dashboard namespace
|
||||
if (isKubernetesClusterAddOnServiceRunning(kubernetesCluster, ipAddress, port, user, sshKeyFile, "kubernetes-dashboard", "kubernetes-dashboard")) {
|
||||
if (LOGGER.isInfoEnabled()) {
|
||||
LOGGER.info(String.format("Dashboard service for the Kubernetes cluster %s is in running state", kubernetesCluster));
|
||||
LOGGER.info(String.format("Kubernetes Dashboard service for the Kubernetes cluster %s is in running state", kubernetesCluster));
|
||||
}
|
||||
running = true;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -331,16 +331,29 @@ write_files:
|
|||
if [[ ${EXTERNAL_CNI_PLUGIN} == false ]]; then
|
||||
/opt/bin/kubectl apply -f ${K8S_CONFIG_SCRIPTS_COPY_DIR}/network.yaml
|
||||
fi
|
||||
/opt/bin/kubectl apply -f ${K8S_CONFIG_SCRIPTS_COPY_DIR}/dashboard.yaml
|
||||
if [ -f "${K8S_CONFIG_SCRIPTS_COPY_DIR}/headlamp.yaml" ]; then
|
||||
echo "Installing Headlamp dashboard from ISO"
|
||||
/opt/bin/kubectl apply -f ${K8S_CONFIG_SCRIPTS_COPY_DIR}/headlamp.yaml
|
||||
elif [ -f "${K8S_CONFIG_SCRIPTS_COPY_DIR}/dashboard.yaml" ]; then
|
||||
echo "Installing Kubernetes Dashboard from ISO"
|
||||
/opt/bin/kubectl apply -f ${K8S_CONFIG_SCRIPTS_COPY_DIR}/dashboard.yaml
|
||||
/opt/bin/kubectl create rolebinding admin-binding --role=admin --user=admin || true
|
||||
/opt/bin/kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=admin || true
|
||||
/opt/bin/kubectl create clusterrolebinding kubernetes-dashboard-ui --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:kubernetes-dashboard || true
|
||||
else
|
||||
echo "Warning: No dashboard YAML found in ISO (neither headlamp.yaml nor dashboard.yaml)"
|
||||
fi
|
||||
rm -rf "${K8S_CONFIG_SCRIPTS_COPY_DIR}"
|
||||
else
|
||||
### Online installation - use Headlamp by default ###
|
||||
/opt/bin/kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(/opt/bin/kubectl version | base64 | tr -d '\n')"
|
||||
/opt/bin/kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta6/aio/deploy/recommended.yaml
|
||||
/opt/bin/kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/headlamp/v0.40.1/kubernetes-headlamp.yaml
|
||||
/opt/bin/kubectl create serviceaccount headlamp-admin -n kube-system || true
|
||||
/opt/bin/kubectl create clusterrolebinding headlamp-admin --clusterrole=cluster-admin --serviceaccount=kube-system:headlamp-admin || true
|
||||
fi
|
||||
|
||||
/opt/bin/kubectl create rolebinding admin-binding --role=admin --user=admin || true
|
||||
/opt/bin/kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=admin || true
|
||||
/opt/bin/kubectl create clusterrolebinding kubernetes-dashboard-ui --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:kubernetes-dashboard || true
|
||||
|
||||
sudo touch /home/cloud/success
|
||||
echo "true" > /home/cloud/success
|
||||
|
|
|
|||
|
|
@ -485,6 +485,12 @@ public class MockAccountManager extends ManagerBase implements AccountManager {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long finalizeAccountId(Long accountId, String accountName, Long domainId, Long projectId) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkAccess(Account account, ServiceOffering so, DataCenter zone) throws PermissionDeniedException {
|
||||
// TODO Auto-generated method stub
|
||||
|
|
|
|||
|
|
@ -335,6 +335,9 @@ public class SAMLUtils {
|
|||
resp.addCookie(newCookie(domain, path,"isSAML", URLEncoder.encode("true", HttpUtils.UTF_8)));
|
||||
resp.addCookie(newCookie(domain, path,"twoFaEnabled", URLEncoder.encode(loginResponse.is2FAenabled(), HttpUtils.UTF_8)));
|
||||
resp.addCookie(newCookie(domain, path,"userfullname", URLEncoder.encode(loginResponse.getFirstName() + " " + loginResponse.getLastName(), HttpUtils.UTF_8).replace("+", "%20")));
|
||||
if (StringUtils.isNotBlank(loginResponse.getManagementServerId())) {
|
||||
resp.addCookie(new Cookie(ApiConstants.MANAGEMENT_SERVER_ID, URLEncoder.encode(loginResponse.getManagementServerId(), HttpUtils.UTF_8)));
|
||||
}
|
||||
}
|
||||
|
||||
private static Cookie newCookie(final String domain, final String path, final String name, final String value) {
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@
|
|||
set -e
|
||||
|
||||
if [ $# -lt 6 ]; then
|
||||
echo "Invalid input. Valid usage: ./create-kubernetes-binaries-iso.sh OUTPUT_PATH KUBERNETES_VERSION CNI_VERSION CRICTL_VERSION WEAVENET_NETWORK_YAML_CONFIG DASHBOARD_YAML_CONFIG BUILD_NAME [ARCH] [ETCD_VERSION]"
|
||||
echo "eg: ./create-kubernetes-binaries-iso.sh ./ 1.11.4 0.7.1 1.11.1 https://github.com/weaveworks/weave/releases/download/latest_release/weave-daemonset-k8s-1.11.yaml https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.0/src/deploy/recommended/kubernetes-dashboard.yaml setup-v1.11.4 amd64"
|
||||
echo "Invalid input. Valid usage: ./create-kubernetes-binaries-iso.sh OUTPUT_PATH KUBERNETES_VERSION CNI_VERSION CRICTL_VERSION WEAVENET_NETWORK_YAML_CONFIG HEADLAMP_DASHBOARD_VERSION BUILD_NAME [ARCH] [ETCD_VERSION]"
|
||||
echo "eg: ./create-kubernetes-binaries-iso.sh ./ 1.11.4 0.7.1 1.11.1 https://github.com/weaveworks/weave/releases/download/latest_release/weave-daemonset-k8s-1.11.yaml 0.40.1 setup-v1.11.4 amd64"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
@ -96,10 +96,11 @@ echo "Downloading network config ${NETWORK_CONFIG_URL}"
|
|||
network_conf_file="${working_dir}/network.yaml"
|
||||
curl -sSL ${NETWORK_CONFIG_URL} -o ${network_conf_file}
|
||||
|
||||
DASHBORAD_CONFIG_URL="${6}"
|
||||
echo "Downloading dashboard config ${DASHBORAD_CONFIG_URL}"
|
||||
dashboard_conf_file="${working_dir}/dashboard.yaml"
|
||||
curl -sSL ${DASHBORAD_CONFIG_URL} -o ${dashboard_conf_file}
|
||||
HEADLAMP_DASHBOARD_VERSION="${6}"
|
||||
HEADLAMP_DASHBOARD_URL="https://raw.githubusercontent.com/kubernetes-sigs/headlamp/v${HEADLAMP_DASHBOARD_VERSION}/kubernetes-headlamp.yaml"
|
||||
echo "Downloading Headlamp manifest from ${HEADLAMP_DASHBOARD_URL}"
|
||||
headlamp_conf_file="${working_dir}/headlamp.yaml"
|
||||
curl -sSL ${HEADLAMP_DASHBOARD_URL} -o ${headlamp_conf_file}
|
||||
|
||||
# TODO : Change the url once merged
|
||||
AUTOSCALER_URL="https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/cloudstack/examples/cluster-autoscaler-standard.yaml"
|
||||
|
|
@ -135,7 +136,7 @@ mkdir -p "${working_dir}/docker"
|
|||
output=`${k8s_dir}/kubeadm config images list --kubernetes-version=${RELEASE}`
|
||||
|
||||
# Don't forget about the yaml images !
|
||||
for i in ${network_conf_file} ${dashboard_conf_file}
|
||||
for i in ${network_conf_file} ${headlamp_conf_file}
|
||||
do
|
||||
images=`grep "image:" $i | cut -d ':' -f2- | tr -d ' ' | tr -d "'"`
|
||||
output=`printf "%s\n" ${output} ${images}`
|
||||
|
|
|
|||
|
|
@ -2243,6 +2243,10 @@ public class ApiDBUtils {
|
|||
return s_nicSecondaryIpDao.listByNicId(nicId);
|
||||
}
|
||||
|
||||
public static NicVO findNicById(long nicId) {
|
||||
return s_nicDao.findById(nicId);
|
||||
}
|
||||
|
||||
public static TemplateResponse newTemplateUpdateResponse(TemplateJoinVO vr) {
|
||||
return s_templateJoinDao.newUpdateResponse(vr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1930,6 +1930,12 @@ public class ApiResponseHelper implements ResponseGenerator {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserVm findUserVmByNicId(Long nicId) {
|
||||
NicVO nic = ApiDBUtils.findNicById(nicId);
|
||||
return ApiDBUtils.findUserVmById(nic.getInstanceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public VolumeVO findVolumeById(Long volumeId) {
|
||||
return ApiDBUtils.findVolumeById(volumeId);
|
||||
|
|
@ -4853,6 +4859,8 @@ public class ApiResponseHelper implements ResponseGenerator {
|
|||
VpcVO vpc = _entityMgr.findByUuidIncludingRemoved(VpcVO.class, userVm.getVpcUuid());
|
||||
response.setVpcName(vpc.getName());
|
||||
}
|
||||
|
||||
response.setEnabled(result.isEnabled());
|
||||
return response;
|
||||
}
|
||||
|
||||
|
|
@ -5402,8 +5410,21 @@ public class ApiResponseHelper implements ResponseGenerator {
|
|||
if (host != null) {
|
||||
response.setHostId(host.getUuid());
|
||||
response.setHostName(host.getName());
|
||||
} else if (instance.getHostName() != null) {
|
||||
response.setHostName(instance.getHostName());
|
||||
if (host.getHypervisorType() != null) {
|
||||
response.setHypervisor(host.getHypervisorType().name());
|
||||
}
|
||||
response.setHypervisorVersion(host.getHypervisorVersion());
|
||||
} else {
|
||||
// In case the unmanaged instance is on an external host
|
||||
if (instance.getHostName() != null) {
|
||||
response.setHostName(instance.getHostName());
|
||||
}
|
||||
if (instance.getHypervisorType() != null) {
|
||||
response.setHypervisor(instance.getHypervisorType());
|
||||
}
|
||||
if (instance.getHostHypervisorVersion() != null) {
|
||||
response.setHypervisorVersion(instance.getHostHypervisorVersion());
|
||||
}
|
||||
}
|
||||
response.setPowerState((instance.getPowerState() != null)? instance.getPowerState().toString() : UnmanagedInstanceTO.PowerState.PowerUnknown.toString());
|
||||
response.setCpuCores(instance.getCpuCores());
|
||||
|
|
|
|||
|
|
@ -314,20 +314,7 @@ public class ParamProcessWorker implements DispatchWorker {
|
|||
|
||||
protected void doAccessChecks(BaseCmd cmd, Map<Object, AccessType> entitiesToAccess) {
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
List<Long> entityOwners = cmd.getEntityOwnerIds();
|
||||
Account[] owners = null;
|
||||
if (entityOwners != null) {
|
||||
owners = entityOwners.stream().map(id -> _accountMgr.getAccount(id)).toArray(Account[]::new);
|
||||
} else {
|
||||
if (cmd.getEntityOwnerId() == Account.ACCOUNT_ID_SYSTEM && cmd instanceof BaseAsyncCmd && ((BaseAsyncCmd)cmd).getApiResourceType() == ApiCommandResourceType.Network) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Skipping access check on the network owner if the owner is ROOT/system.");
|
||||
}
|
||||
owners = new Account[]{};
|
||||
} else {
|
||||
owners = new Account[]{_accountMgr.getAccount(cmd.getEntityOwnerId())};
|
||||
}
|
||||
}
|
||||
Account[] owners = getEntityOwners(cmd);
|
||||
|
||||
if (cmd instanceof BaseAsyncCreateCmd) {
|
||||
// check that caller can access the owner account.
|
||||
|
|
|
|||
|
|
@ -196,6 +196,7 @@ public class DomainRouterJoinDaoImpl extends GenericDaoBase<DomainRouterJoinVO,
|
|||
nicResponse.setMtu(router.getMtu());
|
||||
}
|
||||
nicResponse.setIsDefault(router.isDefaultNic());
|
||||
nicResponse.setEnabled(router.isNicEnabled());
|
||||
nicResponse.setObjectName("nic");
|
||||
routerResponse.addNic(nicResponse);
|
||||
}
|
||||
|
|
@ -289,6 +290,7 @@ public class DomainRouterJoinDaoImpl extends GenericDaoBase<DomainRouterJoinVO,
|
|||
nicResponse.setMtu(vr.getMtu());
|
||||
}
|
||||
nicResponse.setIsDefault(vr.isDefaultNic());
|
||||
nicResponse.setEnabled(vr.isNicEnabled());
|
||||
nicResponse.setObjectName("nic");
|
||||
vrData.addNic(nicResponse);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -359,6 +359,7 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
|
|||
nicResponse.setIp6Address(userVm.getIp6Address());
|
||||
nicResponse.setIp6Gateway(userVm.getIp6Gateway());
|
||||
nicResponse.setIp6Cidr(userVm.getIp6Cidr());
|
||||
nicResponse.setEnabled(userVm.isNicEnabled());
|
||||
nicResponse.setDnsRecordUrl(userVm.getDnsRecordUrl());
|
||||
if (userVm.getBroadcastUri() != null) {
|
||||
nicResponse.setBroadcastUri(userVm.getBroadcastUri().toString());
|
||||
|
|
@ -630,6 +631,7 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
|
|||
/*17: default*/
|
||||
nicResponse.setIsDefault(uvo.isDefaultNic());
|
||||
nicResponse.setDeviceId(String.valueOf(uvo.getNicDeviceId()));
|
||||
nicResponse.setEnabled(uvo.isNicEnabled());
|
||||
List<NicSecondaryIpVO> secondaryIps = ApiDBUtils.findNicSecondaryIps(uvo.getNicId());
|
||||
if (secondaryIps != null) {
|
||||
List<NicSecondaryIpResponse> ipList = new ArrayList<NicSecondaryIpResponse>();
|
||||
|
|
|
|||
|
|
@ -274,6 +274,9 @@ public class DomainRouterJoinVO extends BaseViewVO implements ControlledViewEnti
|
|||
@Column(name = "mtu")
|
||||
private Integer mtu;
|
||||
|
||||
@Column(name = "is_nic_enabled")
|
||||
private boolean isNicEnabled;
|
||||
|
||||
public DomainRouterJoinVO() {
|
||||
}
|
||||
|
||||
|
|
@ -577,4 +580,8 @@ public class DomainRouterJoinVO extends BaseViewVO implements ControlledViewEnti
|
|||
public Integer getMtu() {
|
||||
return mtu;
|
||||
}
|
||||
|
||||
public boolean isNicEnabled() {
|
||||
return isNicEnabled;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -346,6 +346,9 @@ public class UserVmJoinVO extends BaseViewWithTagInformationVO implements Contro
|
|||
@Column(name = "is_default_nic")
|
||||
private boolean isDefaultNic;
|
||||
|
||||
@Column(name = "is_nic_enabled")
|
||||
private boolean isNicEnabled;
|
||||
|
||||
@Column(name = "ip_address")
|
||||
private String ipAddress;
|
||||
|
||||
|
|
@ -1094,6 +1097,10 @@ public class UserVmJoinVO extends BaseViewWithTagInformationVO implements Contro
|
|||
return leaseActionExecution;
|
||||
}
|
||||
|
||||
public boolean isNicEnabled() {
|
||||
return isNicEnabled;
|
||||
}
|
||||
|
||||
public String getDnsRecordUrl() {
|
||||
return dnsRecordUrl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1714,7 +1714,7 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, Configurable {
|
|||
|
||||
@Override
|
||||
public void reorderHostsByPriority(Map<Long, Integer> priorities, List<Host> hosts) {
|
||||
logger.info("Re-ordering hosts {} by priorities {}", hosts, priorities);
|
||||
logger.debug("Re-ordering hosts {} by priorities {}", hosts, priorities);
|
||||
|
||||
hosts.removeIf(host -> DataCenterDeployment.PROHIBITED_HOST_PRIORITY.equals(getHostPriority(priorities, host.getId())));
|
||||
|
||||
|
|
@ -1727,7 +1727,7 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, Configurable {
|
|||
}
|
||||
);
|
||||
|
||||
logger.info("Hosts after re-ordering are: {}", hosts);
|
||||
logger.debug("Hosts after re-ordering are: {}", hosts);
|
||||
}
|
||||
|
||||
private Integer getHostPriority(Map<Long, Integer> priorities, Long hostId) {
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
|
|||
to.setIp6Dns1(profile.getIPv6Dns1());
|
||||
to.setIp6Dns2(profile.getIPv6Dns2());
|
||||
to.setNetworkId(profile.getNetworkId());
|
||||
to.setEnabled(profile.isEnabled());
|
||||
|
||||
NetworkVO network = networkDao.findById(profile.getNetworkId());
|
||||
to.setNetworkUuid(network.getUuid());
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ import javax.inject.Inject;
|
|||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.cloudstack.acl.ApiKeyPairVO;
|
||||
import com.cloud.api.query.MutualExclusiveIdsManagerBase;
|
||||
import com.cloud.network.vpc.VpcVO;
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
|
|
@ -566,6 +567,7 @@ import org.apache.cloudstack.api.command.user.vm.StartVMCmd;
|
|||
import org.apache.cloudstack.api.command.user.vm.StopVMCmd;
|
||||
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;
|
||||
|
|
@ -842,7 +844,6 @@ import com.cloud.utils.Pair;
|
|||
import com.cloud.utils.PasswordGenerator;
|
||||
import com.cloud.utils.Ternary;
|
||||
import com.cloud.utils.component.ComponentLifecycle;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||
import com.cloud.utils.crypt.DBEncryptionUtil;
|
||||
import com.cloud.utils.db.DB;
|
||||
|
|
@ -885,7 +886,7 @@ import com.cloud.vm.dao.UserVmDao;
|
|||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import com.cloud.vm.dao.VMInstanceDetailsDao;
|
||||
|
||||
public class ManagementServerImpl extends ManagerBase implements ManagementServer, Configurable {
|
||||
public class ManagementServerImpl extends MutualExclusiveIdsManagerBase implements ManagementServer, Configurable {
|
||||
protected StateMachine2<State, VirtualMachine.Event, VirtualMachine> _stateMachine;
|
||||
|
||||
static final String FOR_SYSTEMVMS = "forsystemvms";
|
||||
|
|
@ -2908,7 +2909,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
|||
|
||||
@Override
|
||||
public Pair<List<? extends GuestOS>, Integer> listGuestOSByCriteria(final ListGuestOsCmd cmd) {
|
||||
final Long id = cmd.getId();
|
||||
List<Long> ids = getIdsListFromCmd(cmd.getId(), cmd.getIds());
|
||||
final Long osCategoryId = cmd.getOsCategoryId();
|
||||
final String description = cmd.getDescription();
|
||||
final String keyword = cmd.getKeyword();
|
||||
|
|
@ -2916,7 +2917,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
|||
final Long pageSize = cmd.getPageSizeVal();
|
||||
Boolean forDisplay = cmd.getDisplay();
|
||||
|
||||
return _guestOSDao.listGuestOSByCriteria(startIndex, pageSize, id, osCategoryId, description, keyword, forDisplay);
|
||||
return _guestOSDao.listGuestOSByCriteria(startIndex, pageSize, ids, osCategoryId, description, keyword, forDisplay);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -3048,28 +3049,41 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
|||
throw new InvalidParameterValueException("Hypervisor version parameter cannot be used without specifying a hypervisor : XenServer, KVM or VMware");
|
||||
}
|
||||
|
||||
final SearchCriteria<GuestOSHypervisorVO> sc = _guestOSHypervisorDao.createSearchCriteria();
|
||||
SearchBuilder<GuestOSHypervisorVO> sb = _guestOSHypervisorDao.createSearchBuilder();
|
||||
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
|
||||
sb.and("guestOsName", sb.entity().getGuestOsName(), SearchCriteria.Op.LIKE);
|
||||
sb.and("hypervisorType", sb.entity().getHypervisorType(), SearchCriteria.Op.LIKE);
|
||||
sb.and("hypervisorVersion", sb.entity().getHypervisorVersion(), SearchCriteria.Op.LIKE);
|
||||
sb.and(guestOsId, sb.entity().getGuestOsId(), SearchCriteria.Op.EQ);
|
||||
SearchBuilder<GuestOSVO> guestOSSearch = _guestOSDao.createSearchBuilder();
|
||||
guestOSSearch.and("display", guestOSSearch.entity().isDisplay(), SearchCriteria.Op.LIKE);
|
||||
sb.join("guestOSSearch", guestOSSearch, sb.entity().getGuestOsId(), guestOSSearch.entity().getId(), JoinBuilder.JoinType.INNER);
|
||||
|
||||
final SearchCriteria<GuestOSHypervisorVO> sc = sb.create();
|
||||
|
||||
if (id != null) {
|
||||
sc.addAnd("id", SearchCriteria.Op.EQ, id);
|
||||
sc.setParameters("id", SearchCriteria.Op.EQ, id);
|
||||
}
|
||||
|
||||
if (osTypeId != null) {
|
||||
sc.addAnd(guestOsId, SearchCriteria.Op.EQ, osTypeId);
|
||||
sc.setParameters(guestOsId, osTypeId);
|
||||
}
|
||||
|
||||
if (osNameForHypervisor != null) {
|
||||
sc.addAnd("guestOsName", SearchCriteria.Op.LIKE, "%" + osNameForHypervisor + "%");
|
||||
sc.setParameters("guestOsName", "%" + osNameForHypervisor + "%");
|
||||
}
|
||||
|
||||
if (hypervisor != null) {
|
||||
sc.addAnd("hypervisorType", SearchCriteria.Op.LIKE, "%" + hypervisor + "%");
|
||||
sc.setParameters("hypervisorType", "%" + hypervisor + "%");
|
||||
}
|
||||
|
||||
if (hypervisorVersion != null) {
|
||||
sc.addAnd("hypervisorVersion", SearchCriteria.Op.LIKE, "%" + hypervisorVersion + "%");
|
||||
sc.setParameters("hypervisorVersion", "%" + hypervisorVersion + "%");
|
||||
}
|
||||
|
||||
// Exclude the mappings for guest OS marked as display = false
|
||||
sc.setJoinParameters("guestOSSearch", "display", true);
|
||||
|
||||
if (osDisplayName != null) {
|
||||
List<GuestOSVO> guestOSVOS = _guestOSDao.listLikeDisplayName(osDisplayName);
|
||||
if (CollectionUtils.isNotEmpty(guestOSVOS)) {
|
||||
|
|
@ -4152,6 +4166,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
|||
cmdList.add(StopVMCmd.class);
|
||||
cmdList.add(UpdateDefaultNicForVMCmd.class);
|
||||
cmdList.add(UpdateVMCmd.class);
|
||||
cmdList.add(UpdateVmNicCmd.class);
|
||||
cmdList.add(UpgradeVMCmd.class);
|
||||
cmdList.add(CreateVMGroupCmd.class);
|
||||
cmdList.add(DeleteVMGroupCmd.class);
|
||||
|
|
|
|||
|
|
@ -2381,6 +2381,9 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
|
||||
@Override
|
||||
public TemplateType validateTemplateType(BaseCmd cmd, boolean isAdmin, boolean isCrossZones, HypervisorType hypervisorType) {
|
||||
if (cmd instanceof GetUploadParamsForIsoCmd) {
|
||||
return TemplateType.USER;
|
||||
}
|
||||
if (!(cmd instanceof UpdateTemplateCmd) && !(cmd instanceof RegisterTemplateCmd) && !(cmd instanceof GetUploadParamsForTemplateCmd)) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,9 @@ import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
|
|||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseAsyncCmd;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.command.admin.account.CreateAccountCmd;
|
||||
import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd;
|
||||
import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd;
|
||||
|
|
@ -3889,6 +3891,48 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long finalizeAccountId(Long accountId, String accountName, Long domainId, Long projectId) {
|
||||
if (projectId != null) {
|
||||
if (ObjectUtils.anyNotNull(accountId, accountName)) {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Project and account can not be specified together.");
|
||||
}
|
||||
return getActiveProjectAccountByProjectId(projectId);
|
||||
}
|
||||
if (accountId != null) {
|
||||
if (getActiveAccountById(accountId) != null) {
|
||||
return accountId;
|
||||
}
|
||||
throw new InvalidParameterValueException(String.format("Unable to find account with ID [%s].", accountId));
|
||||
}
|
||||
|
||||
if (accountName == null && domainId == null) {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, String.format("Either %s or %s must be informed.", ApiConstants.ACCOUNT_ID, ApiConstants.PROJECT_ID));
|
||||
}
|
||||
|
||||
try {
|
||||
Account activeAccount = getActiveAccountByName(accountName, domainId);
|
||||
if (activeAccount != null) {
|
||||
return activeAccount.getId();
|
||||
}
|
||||
} catch (InvalidParameterValueException exception) {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, String.format("Both %s and %s are needed if using either. Consider using %s instead.",
|
||||
ApiConstants.ACCOUNT, ApiConstants.DOMAIN_ID, ApiConstants.ACCOUNT_ID));
|
||||
}
|
||||
throw new InvalidParameterValueException(String.format("Unable to find account by name [%s] on domain [%s].", accountName, domainId));
|
||||
}
|
||||
|
||||
protected long getActiveProjectAccountByProjectId(long projectId) {
|
||||
Project project = _projectMgr.getProject(projectId);
|
||||
if (project == null) {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, String.format("Unable to find project with ID [%s].", projectId));
|
||||
}
|
||||
if (project.getState() != Project.State.Active) {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, String.format("Project with ID [%s] is not active.", projectId));
|
||||
}
|
||||
return project.getProjectAccountId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserAccount getUserAccountById(Long userId) {
|
||||
UserAccount userAccount = userAccountDao.findById(userId);
|
||||
|
|
|
|||
|
|
@ -199,4 +199,9 @@ public interface UserVmManager extends UserVmService {
|
|||
|
||||
Boolean getDestroyRootVolumeOnVmDestruction(Long domainId);
|
||||
|
||||
/**
|
||||
* @return true if the VM is part of a CKS cluster, false otherwise.
|
||||
*/
|
||||
boolean isVMPartOfAnyCKSCluster(VMInstanceVO vm);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ import org.apache.cloudstack.api.command.user.vm.SecurityGroupAction;
|
|||
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;
|
||||
|
|
@ -1177,21 +1178,21 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
List<Long> vmNetworks = _vmNetworkMapDao.getNetworks(vmId);
|
||||
List<DomainRouterVO> routers = new ArrayList<>();
|
||||
//List the stopped routers
|
||||
for(long vmNetworkId : vmNetworks) {
|
||||
for (long vmNetworkId : vmNetworks) {
|
||||
List<DomainRouterVO> router = _routerDao.listStopped(vmNetworkId);
|
||||
routers.addAll(router);
|
||||
}
|
||||
//A vm may not have many nics attached and even fewer routers might be stopped (only in exceptional cases)
|
||||
//Safe to start the stopped router serially, this is consistent with the way how multiple networks are added to vm during deploy
|
||||
//and routers are started serially ,may revisit to make this process parallel
|
||||
for(DomainRouterVO routerToStart : routers) {
|
||||
for (DomainRouterVO routerToStart : routers) {
|
||||
logger.warn("Trying to start router {} as part of vm: {} reboot", routerToStart, vm);
|
||||
_virtualNetAppliance.startRouter(routerToStart.getId(),true);
|
||||
}
|
||||
}
|
||||
} catch (ConcurrentOperationException e) {
|
||||
throw new CloudRuntimeException("Concurrent operations on starting router. " + e);
|
||||
} catch (Exception ex){
|
||||
} catch (Exception ex) {
|
||||
throw new CloudRuntimeException("Router start failed due to" + ex);
|
||||
} finally {
|
||||
if (logger.isInfoEnabled()) {
|
||||
|
|
@ -1476,7 +1477,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
macAddress = validateOrReplaceMacAddress(macAddress, network);
|
||||
|
||||
if(_nicDao.findByNetworkIdAndMacAddress(networkId, macAddress) != null) {
|
||||
if (_nicDao.findByNetworkIdAndMacAddress(networkId, macAddress) != null) {
|
||||
throw new CloudRuntimeException("A NIC with this MAC address exists for network: " + network.getUuid());
|
||||
}
|
||||
|
||||
|
|
@ -1502,7 +1503,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
vmInstance, dc, network, dataCenterDao.findById(network.getDataCenterId())));
|
||||
}
|
||||
|
||||
if(_networkModel.getNicInNetwork(vmInstance.getId(),network.getId()) != null){
|
||||
if (_networkModel.getNicInNetwork(vmInstance.getId(),network.getId()) != null) {
|
||||
logger.debug("Instance {} already in network {} going to add another NIC", vmInstance, network);
|
||||
} else {
|
||||
//* get all vms hostNames in the network
|
||||
|
|
@ -1530,7 +1531,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
} catch (ConcurrentOperationException e) {
|
||||
throw new CloudRuntimeException("Concurrent operations on adding NIC to " + vmInstance + ": " + e);
|
||||
} finally {
|
||||
if(cleanUp) {
|
||||
if (cleanUp) {
|
||||
try {
|
||||
_itMgr.removeVmFromNetwork(vmInstance, network, null);
|
||||
} catch (ResourceUnavailableException e) {
|
||||
|
|
@ -1935,6 +1936,54 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
return vm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserVm updateVirtualMachineNic(UpdateVmNicCmd cmd) {
|
||||
Long nicId = cmd.getNicId();
|
||||
Boolean isNicEnabled = cmd.isEnabled();
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
NicVO nic = _nicDao.findById(nicId);
|
||||
if (nic == null) {
|
||||
throw new InvalidParameterValueException("Unable to find the specified NIC.");
|
||||
}
|
||||
|
||||
UserVmVO vmInstance = _vmDao.findById(nic.getInstanceId());
|
||||
if (vmInstance == null) {
|
||||
throw new InvalidParameterValueException("Unable to find a virtual machine associated with the specified NIC.");
|
||||
}
|
||||
|
||||
if (vmInstance.getHypervisorType() != HypervisorType.KVM) {
|
||||
throw new InvalidParameterValueException("Updating the VM NIC is only supported by the KVM hypervisor.");
|
||||
}
|
||||
|
||||
NetworkVO network = _networkDao.findById(nic.getNetworkId());
|
||||
if (network == null) {
|
||||
throw new InvalidParameterValueException("Unable to find NIC's network.");
|
||||
}
|
||||
|
||||
_accountMgr.checkAccess(caller, null, true, vmInstance);
|
||||
|
||||
if (isNicEnabled == null) {
|
||||
return vmInstance;
|
||||
}
|
||||
|
||||
boolean success = false;
|
||||
try {
|
||||
success = _itMgr.updateVmNic(vmInstance, nic, isNicEnabled);
|
||||
} catch (ResourceUnavailableException e) {
|
||||
throw new CloudRuntimeException(String.format("Unable to update NIC %s of VM %s in network %s due to: %s.", nic, vmInstance, network.getUuid(), e.getMessage()));
|
||||
} catch (ConcurrentOperationException e) {
|
||||
throw new CloudRuntimeException(String.format("Concurrent operations while updating NIC %s for VM %s: %s.", nic, vmInstance, e.getMessage()));
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
throw new CloudRuntimeException(String.format("Failed to update NIC %s of VM %s in network %s.", nic, vmInstance, network.getUuid()));
|
||||
}
|
||||
|
||||
logger.debug("Successfully updated NIC {} in network {} for VM {}.", nic, network.getUuid(), vmInstance);
|
||||
return vmInstance;
|
||||
}
|
||||
|
||||
private void updatePublicIpDnatVmIp(long vmId, long networkId, String oldIp, String newIp) {
|
||||
if (!_networkModel.areServicesSupportedInNetwork(networkId, Service.StaticNat)) {
|
||||
return;
|
||||
|
|
@ -2311,7 +2360,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
answer = _agentMgr.easySend(neighbor.getId(), cmd);
|
||||
}
|
||||
|
||||
if (answer != null && answer instanceof GetVolumeStatsAnswer){
|
||||
if (answer != null && answer instanceof GetVolumeStatsAnswer) {
|
||||
GetVolumeStatsAnswer volstats = (GetVolumeStatsAnswer)answer;
|
||||
if (volstats.getVolumeStats() != null) {
|
||||
volumeStatsByUuid.putAll(volstats.getVolumeStats());
|
||||
|
|
@ -2322,7 +2371,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
return volumeStatsByUuid.size() > 0 ? volumeStatsByUuid : null;
|
||||
}
|
||||
|
||||
private List<String> getVolumesByHost(HostVO host, StoragePool pool){
|
||||
private List<String> getVolumesByHost(HostVO host, StoragePool pool) {
|
||||
List<VMInstanceVO> vmsPerHost = _vmInstanceDao.listByHostId(host.getId());
|
||||
return vmsPerHost.stream()
|
||||
.flatMap(vm -> _volsDao.findNonDestroyedVolumesByInstanceIdAndPoolId(vm.getId(),pool.getId()).stream().map(vol ->
|
||||
|
|
@ -2594,6 +2643,22 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
}
|
||||
|
||||
private void transitionExpungingToError(long vmId) {
|
||||
UserVmVO vm = _vmDao.findById(vmId);
|
||||
if (vm != null && vm.getState() == State.Expunging) {
|
||||
try {
|
||||
boolean transitioned = _itMgr.stateTransitTo(vm, VirtualMachine.Event.OperationFailedToError, null);
|
||||
if (transitioned) {
|
||||
logger.info("Transitioned VM [{}] from Expunging to Error after failed expunge", vm.getUuid());
|
||||
} else {
|
||||
logger.warn("Failed to persist transition of VM [{}] from Expunging to Error after failed expunge, possibly due to concurrent update", vm.getUuid());
|
||||
}
|
||||
} catch (NoTransitionException e) {
|
||||
logger.warn("Failed to transition VM {} to Error state: {}", vm, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Release network resources, it was done on vm stop previously.
|
||||
* @param id vm id
|
||||
|
|
@ -2602,7 +2667,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
*/
|
||||
private void releaseNetworkResourcesOnExpunge(long id) throws ConcurrentOperationException, ResourceUnavailableException {
|
||||
final VMInstanceVO vmInstance = _vmDao.findById(id);
|
||||
if (vmInstance != null){
|
||||
if (vmInstance != null) {
|
||||
final VirtualMachineProfile profile = new VirtualMachineProfileImpl(vmInstance);
|
||||
_networkMgr.release(profile, false);
|
||||
}
|
||||
|
|
@ -2867,17 +2932,17 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
) {
|
||||
if (newCpu > currentCpu) {
|
||||
_resourceLimitMgr.incrementVmCpuResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, newCpu - currentCpu);
|
||||
} else if (newCpu > 0 && currentCpu > newCpu){
|
||||
} else if (newCpu > 0 && currentCpu > newCpu) {
|
||||
_resourceLimitMgr.decrementVmCpuResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, currentCpu - newCpu);
|
||||
}
|
||||
if (newMemory > currentMemory) {
|
||||
_resourceLimitMgr.incrementVmMemoryResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, newMemory - currentMemory);
|
||||
} else if (newMemory > 0 && currentMemory > newMemory){
|
||||
} else if (newMemory > 0 && currentMemory > newMemory) {
|
||||
_resourceLimitMgr.decrementVmMemoryResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, currentMemory - newMemory);
|
||||
}
|
||||
if (newGpu > currentGpu) {
|
||||
_resourceLimitMgr.incrementVmGpuResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, newGpu - currentGpu);
|
||||
} else if (newGpu > 0 && currentGpu > newGpu){
|
||||
} else if (newGpu > 0 && currentGpu > newGpu) {
|
||||
_resourceLimitMgr.decrementVmGpuResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, currentGpu - newGpu);
|
||||
}
|
||||
}
|
||||
|
|
@ -3008,7 +3073,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
if (userReadOnlySettings.contains(detailName)) {
|
||||
throw new InvalidParameterValueException("You're not allowed to add or edit the read-only setting: " + detailName);
|
||||
}
|
||||
if (existingDetails.stream().anyMatch(d -> Objects.equals(d.getName(), detailName) && !d.isDisplay())){
|
||||
if (existingDetails.stream().anyMatch(d -> Objects.equals(d.getName(), detailName) && !d.isDisplay())) {
|
||||
throw new InvalidParameterValueException("You're not allowed to add or edit the non-displayable setting: " + detailName);
|
||||
}
|
||||
}
|
||||
|
|
@ -3100,25 +3165,24 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
private void saveUsageEvent(UserVmVO vm) {
|
||||
|
||||
// If vm not destroyed
|
||||
if( vm.getState() != State.Destroyed && vm.getState() != State.Expunging && vm.getState() != State.Error){
|
||||
if (vm.getState() != State.Destroyed && vm.getState() != State.Expunging && vm.getState() != State.Error) {
|
||||
|
||||
if(vm.isDisplayVm()){
|
||||
if (vm.isDisplayVm()) {
|
||||
//1. Allocated VM Usage Event
|
||||
generateUsageEvent(vm, true, EventTypes.EVENT_VM_CREATE);
|
||||
|
||||
if(vm.getState() == State.Running || vm.getState() == State.Stopping){
|
||||
if (vm.getState() == State.Running || vm.getState() == State.Stopping) {
|
||||
//2. Running VM Usage Event
|
||||
generateUsageEvent(vm, true, EventTypes.EVENT_VM_START);
|
||||
|
||||
// 3. Network offering usage
|
||||
generateNetworkUsageForVm(vm, true, EventTypes.EVENT_NETWORK_OFFERING_ASSIGN);
|
||||
}
|
||||
|
||||
}else {
|
||||
} else {
|
||||
//1. Allocated VM Usage Event
|
||||
generateUsageEvent(vm, true, EventTypes.EVENT_VM_DESTROY);
|
||||
|
||||
if(vm.getState() == State.Running || vm.getState() == State.Stopping){
|
||||
if (vm.getState() == State.Running || vm.getState() == State.Stopping) {
|
||||
//2. Running VM Usage Event
|
||||
generateUsageEvent(vm, true, EventTypes.EVENT_VM_STOP);
|
||||
|
||||
|
|
@ -3130,8 +3194,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
}
|
||||
|
||||
private void generateNetworkUsageForVm(VirtualMachine vm, boolean isDisplay, String eventType){
|
||||
|
||||
private void generateNetworkUsageForVm(VirtualMachine vm, boolean isDisplay, String eventType) {
|
||||
List<NicVO> nics = _nicDao.listByVmId(vm.getId());
|
||||
for (NicVO nic : nics) {
|
||||
NetworkVO network = _networkDao.findById(nic.getNetworkId());
|
||||
|
|
@ -3156,9 +3219,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
throw new CloudRuntimeException("Unable to find virtual machine with id " + id);
|
||||
}
|
||||
|
||||
if(instanceName != null){
|
||||
if (instanceName != null) {
|
||||
VMInstanceVO vmInstance = _vmInstanceDao.findVMByInstanceName(instanceName);
|
||||
if(vmInstance != null && vmInstance.getId() != id){
|
||||
if (vmInstance != null && vmInstance.getId() != id) {
|
||||
throw new CloudRuntimeException("Instance name : " + instanceName + " is not unique");
|
||||
}
|
||||
}
|
||||
|
|
@ -3300,7 +3363,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
networkIds = networks.stream().map(Network::getId).collect(Collectors.toList());
|
||||
}
|
||||
} catch (InvalidParameterValueException e) {
|
||||
if(logger.isDebugEnabled()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(e.getMessage(),e);
|
||||
}
|
||||
}
|
||||
|
|
@ -3592,8 +3655,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
detachVolumesFromVm(vm, dataVols);
|
||||
|
||||
UserVm destroyedVm = destroyVm(vmId, expunge);
|
||||
if (expunge && !expunge(vm)) {
|
||||
throw new CloudRuntimeException("Failed to expunge vm " + destroyedVm);
|
||||
if (expunge) {
|
||||
boolean expunged = false;
|
||||
String errorMsg = "";
|
||||
try {
|
||||
expunged = expunge(vm);
|
||||
} catch (RuntimeException e) {
|
||||
logger.error("Failed to expunge VM [{}] due to: {}", vm, e.getMessage(), e);
|
||||
errorMsg = e.getMessage();
|
||||
}
|
||||
if (!expunged) {
|
||||
transitionExpungingToError(vm.getId());
|
||||
throw new CloudRuntimeException("Failed to expunge VM " + vm.getUuid() + (StringUtils.isNotBlank(errorMsg) ? " due to: " + errorMsg : ""));
|
||||
}
|
||||
}
|
||||
|
||||
autoScaleManager.removeVmFromVmGroup(vmId);
|
||||
|
|
@ -4439,7 +4513,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
}
|
||||
|
||||
if (template.getTemplateType().equals(TemplateType.SYSTEM) && !CKS_NODE.equals(vmType) && !SHAREDFSVM.equals(vmType)) {
|
||||
if (TemplateType.SYSTEM.equals(template.getTemplateType()) && !CKS_NODE.equals(vmType) && !SHAREDFSVM.equals(vmType)) {
|
||||
throw new InvalidParameterValueException(String.format("Unable to use system template %s to deploy a user vm", template));
|
||||
}
|
||||
|
||||
|
|
@ -4834,12 +4908,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
private UserVmVO commitUserVm(final boolean isImport, final DataCenter zone, final Host host, final Host lastHost, final VirtualMachineTemplate template, final String hostName, final String displayName, final Account owner,
|
||||
final Long diskOfferingId, final Long diskSize, final String userData, Long userDataId, String userDataDetails, final Boolean isDisplayVm, final String keyboard,
|
||||
final long accountId, final long userId, final ServiceOffering offering, final boolean isIso, final String sshPublicKeys, final LinkedHashMap<String, List<NicProfile>> networkNicMap,
|
||||
final long accountId, final long userId, final ServiceOffering offering, final boolean isIso, final Long guestOsId, final String sshPublicKeys, final LinkedHashMap<String, List<NicProfile>> networkNicMap,
|
||||
final long id, final String instanceName, final String uuidName, final HypervisorType hypervisorType, final Map<String, String> customParameters,
|
||||
final Map<String, Map<Integer, String>> extraDhcpOptionMap, final Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap,
|
||||
final Map<String, String> userVmOVFPropertiesMap, final VirtualMachine.PowerState powerState, final boolean dynamicScalingEnabled, String vmType, final Long rootDiskOfferingId, String sshkeypairs,
|
||||
List<VmDiskInfo> dataDiskInfoList, Volume volume, Snapshot snapshot) throws InsufficientCapacityException {
|
||||
UserVmVO vm = new UserVmVO(id, instanceName, displayName, template.getId(), hypervisorType, template.getGuestOSId(), offering.isOfferHA(),
|
||||
Long selectedGuestOsId = guestOsId != null ? guestOsId : template.getGuestOSId();
|
||||
UserVmVO vm = new UserVmVO(id, instanceName, displayName, template.getId(), hypervisorType, selectedGuestOsId, offering.isOfferHA(),
|
||||
offering.getLimitCpuUse(), owner.getDomainId(), owner.getId(), userId, offering.getId(), userData, userDataId, userDataDetails, hostName);
|
||||
vm.setUuid(uuidName);
|
||||
vm.setDynamicallyScalable(dynamicScalingEnabled);
|
||||
|
|
@ -4865,8 +4940,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
vm.setIsoId(template.getId());
|
||||
}
|
||||
|
||||
long guestOSId = template.getGuestOSId();
|
||||
GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
|
||||
GuestOSVO guestOS = _guestOSDao.findById(selectedGuestOsId);
|
||||
long guestOSCategoryId = guestOS.getCategoryId();
|
||||
GuestOSCategoryVO guestOSCategory = _guestOSCategoryDao.findById(guestOSCategoryId);
|
||||
if (hypervisorType.equals(HypervisorType.VMware)) {
|
||||
|
|
@ -5124,7 +5198,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
List<VmDiskInfo> dataDiskInfoList, Volume volume, Snapshot snapshot) throws InsufficientCapacityException {
|
||||
return commitUserVm(false, zone, null, null, template, hostName, displayName, owner,
|
||||
diskOfferingId, diskSize, userData, userDataId, userDataDetails, isDisplayVm, keyboard,
|
||||
accountId, userId, offering, isIso, sshPublicKeys, networkNicMap,
|
||||
accountId, userId, offering, isIso, null, sshPublicKeys, networkNicMap,
|
||||
id, instanceName, uuidName, hypervisorType, customParameters,
|
||||
extraDhcpOptionMap, dataDiskTemplateToDiskOfferingMap,
|
||||
userVmOVFPropertiesMap, null, dynamicScalingEnabled, vmType, rootDiskOfferingId, sshkeypairs, dataDiskInfoList, volume, snapshot);
|
||||
|
|
@ -5156,7 +5230,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
|
||||
@Override
|
||||
public void generateUsageEvent(VirtualMachine vm, boolean isDisplay, String eventType){
|
||||
public void generateUsageEvent(VirtualMachine vm, boolean isDisplay, String eventType) {
|
||||
ServiceOfferingVO serviceOffering = serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId());
|
||||
if (!serviceOffering.isDynamic()) {
|
||||
UsageEventUtils.publishUsageEvent(eventType, vm.getAccountId(), vm.getDataCenterId(), vm.getId(),
|
||||
|
|
@ -5414,7 +5488,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
// add userdata info into vm profile
|
||||
Nic defaultNic = _networkModel.getDefaultNic(vm.getId());
|
||||
if(defaultNic != null) {
|
||||
if (defaultNic != null) {
|
||||
Network network = _networkModel.getNetwork(defaultNic.getNetworkId());
|
||||
if (_networkModel.isSharedNetworkWithoutServices(network.getId())) {
|
||||
final String serviceOffering = serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()).getDisplayText();
|
||||
|
|
@ -5665,7 +5739,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
try {
|
||||
VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
|
||||
|
||||
if(forced) {
|
||||
if (forced) {
|
||||
status = vmEntity.stopForced(Long.toString(userId));
|
||||
} else {
|
||||
status = vmEntity.stop(Long.toString(userId));
|
||||
|
|
@ -5846,7 +5920,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
params = createParameterInParameterMap(params, additionalParams, VirtualMachineProfile.Param.VmPassword, password);
|
||||
}
|
||||
|
||||
if(additionalParams.containsKey(VirtualMachineProfile.Param.BootIntoSetup)) {
|
||||
if (additionalParams.containsKey(VirtualMachineProfile.Param.BootIntoSetup)) {
|
||||
if (! HypervisorType.VMware.equals(vm.getHypervisorType())) {
|
||||
throw new InvalidParameterValueException(ApiConstants.BOOT_INTO_SETUP + " makes no sense for " + vm.getHypervisorType());
|
||||
}
|
||||
|
|
@ -6324,8 +6398,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
|
||||
if (!serviceOffering.isDynamic()) {
|
||||
for(String detail: cmd.getDetails().keySet()) {
|
||||
if(detail.equalsIgnoreCase(VmDetailConstants.CPU_NUMBER) || detail.equalsIgnoreCase(VmDetailConstants.CPU_SPEED) || detail.equalsIgnoreCase(VmDetailConstants.MEMORY)) {
|
||||
for (String detail: cmd.getDetails().keySet()) {
|
||||
if (detail.equalsIgnoreCase(VmDetailConstants.CPU_NUMBER) || detail.equalsIgnoreCase(VmDetailConstants.CPU_SPEED) || detail.equalsIgnoreCase(VmDetailConstants.MEMORY)) {
|
||||
throw new InvalidParameterValueException("cpuNumber or cpuSpeed or memory should not be specified for static service offering");
|
||||
}
|
||||
}
|
||||
|
|
@ -6544,8 +6618,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
// check if this templateId has a child ISO
|
||||
List<VMTemplateVO> child_templates = _templateDao.listByParentTemplatetId(template.getId());
|
||||
for (VMTemplateVO tmpl: child_templates){
|
||||
if (tmpl.getFormat() == Storage.ImageFormat.ISO){
|
||||
for (VMTemplateVO tmpl: child_templates) {
|
||||
if (tmpl.getFormat() == Storage.ImageFormat.ISO) {
|
||||
logger.info("MDOV trying to attach disk {} to the VM {}", tmpl, vm);
|
||||
_tmplService.attachIso(tmpl.getId(), vm.getId(), true);
|
||||
}
|
||||
|
|
@ -7202,7 +7276,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
checkIfHostOfVMIsInPrepareForMaintenanceState(vm, "Migrate");
|
||||
|
||||
if(serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) {
|
||||
if (serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) {
|
||||
throw new InvalidParameterValueException("Live Migration of GPU enabled VM is not supported");
|
||||
}
|
||||
|
||||
|
|
@ -7817,7 +7891,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
throw ex;
|
||||
}
|
||||
|
||||
if(serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) {
|
||||
if (serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) {
|
||||
throw new InvalidParameterValueException("Live Migration of GPU enabled VM is not supported");
|
||||
}
|
||||
|
||||
|
|
@ -8794,6 +8868,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
throw new InvalidParameterValueException(String.format("Operation not supported for instance: %s",
|
||||
vm.getName()));
|
||||
}
|
||||
if (isVMPartOfAnyCKSCluster(vm)) {
|
||||
throw new UnsupportedServiceException("Cannot restore VM with id = " + vm.getUuid() +
|
||||
" as it belongs to a CKS cluster. Please remove the VM from the CKS cluster before restoring.");
|
||||
}
|
||||
_accountMgr.checkAccess(caller, null, true, vm);
|
||||
|
||||
VMTemplateVO template;
|
||||
|
|
@ -9228,8 +9306,14 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
Long hostId = vm.getHostId() != null ? vm.getHostId() : vm.getLastHostId();
|
||||
|
||||
if (hostId != null) {
|
||||
VolumeInfo volumeInfo = volFactory.getVolume(root.getId());
|
||||
// default findById() won't search entries with removed field not null
|
||||
Host host = _hostDao.findById(hostId);
|
||||
if (host == null) {
|
||||
logger.warn("Host {} not found", hostId);
|
||||
return;
|
||||
}
|
||||
|
||||
VolumeInfo volumeInfo = volFactory.getVolume(root.getId());
|
||||
|
||||
final Command cmd;
|
||||
|
||||
|
|
@ -9532,7 +9616,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
@Override
|
||||
public 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 sshPublicKeys,
|
||||
final long accountId, final long userId, final ServiceOffering serviceOffering, final String sshPublicKeys, 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 {
|
||||
return Transaction.execute((TransactionCallbackWithException<UserVm, InsufficientCapacityException>) status -> {
|
||||
|
|
@ -9558,7 +9642,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
final Boolean dynamicScalingEnabled = checkIfDynamicScalingCanBeEnabled(null, serviceOffering, template, zone.getId());
|
||||
return commitUserVm(true, zone, host, lastHost, template, hostName, displayName, owner,
|
||||
null, null, userData, null, null, isDisplayVm, keyboard,
|
||||
accountId, userId, serviceOffering, template.getFormat().equals(ImageFormat.ISO), sshPublicKeys, networkNicMap,
|
||||
accountId, userId, serviceOffering, template.getFormat().equals(ImageFormat.ISO), guestOsId, sshPublicKeys, networkNicMap,
|
||||
id, instanceName, uuidName, hypervisorType, customParameters,
|
||||
null, null, null, powerState, dynamicScalingEnabled, null, serviceOffering.getDiskOfferingId(), null, null, null, null);
|
||||
});
|
||||
|
|
@ -9985,10 +10069,15 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
}
|
||||
|
||||
public Boolean getDestroyRootVolumeOnVmDestruction(Long domainId){
|
||||
public Boolean getDestroyRootVolumeOnVmDestruction(Long domainId) {
|
||||
return DestroyRootVolumeOnVmDestruction.valueIn(domainId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVMPartOfAnyCKSCluster(VMInstanceVO vm) {
|
||||
return kubernetesServiceHelpers.get(0).findByVmId(vm.getId()) != null;
|
||||
}
|
||||
|
||||
private void setVncPasswordForKvmIfAvailable(Map<String, String> customParameters, UserVmVO vm) {
|
||||
if (customParameters.containsKey(VmDetailConstants.KVM_VNC_PASSWORD)
|
||||
&& StringUtils.isNotEmpty(customParameters.get(VmDetailConstants.KVM_VNC_PASSWORD))) {
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ import org.apache.cloudstack.api.response.VolumeForImportResponse;
|
|||
import org.apache.cloudstack.api.response.VolumeResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
|
|
@ -394,7 +395,7 @@ public class VolumeImportUnmanageManagerImpl implements VolumeImportUnmanageServ
|
|||
Map<VolumeOnStorageTO.Detail, String> volumeDetails = volume.getDetails();
|
||||
if (volumeDetails != null && volumeDetails.containsKey(VolumeOnStorageTO.Detail.BACKING_FILE)) {
|
||||
String backingFile = volumeDetails.get(VolumeOnStorageTO.Detail.BACKING_FILE);
|
||||
if (StringUtils.isNotBlank(backingFile)) {
|
||||
if (StringUtils.isNotBlank(backingFile) && !AllowImportVolumeWithBackingFile.value()) {
|
||||
logFailureAndThrowException("Volume with backing file cannot be imported or unmanaged.");
|
||||
}
|
||||
}
|
||||
|
|
@ -513,4 +514,16 @@ public class VolumeImportUnmanageManagerImpl implements VolumeImportUnmanageServ
|
|||
volume.setRemoved(new Date());
|
||||
volumeDao.update(volume.getId(), volume);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConfigComponentName() {
|
||||
return VolumeImportUnmanageManagerImpl.class.getSimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigKey<?>[] getConfigKeys() {
|
||||
return new ConfigKey<?>[]{
|
||||
AllowImportVolumeWithBackingFile
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,8 +155,6 @@ import org.apache.cloudstack.api.command.admin.vm.ListUnmanagedInstancesCmd;
|
|||
import org.apache.cloudstack.api.command.admin.vm.ListVmsForImportCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vm.UnmanageVMInstanceCmd;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.NicResponse;
|
||||
import org.apache.cloudstack.api.response.UnmanagedInstanceDiskResponse;
|
||||
import org.apache.cloudstack.api.response.UnmanagedInstanceResponse;
|
||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
|
|
@ -195,15 +193,15 @@ import java.util.stream.Collectors;
|
|||
|
||||
import static org.apache.cloudstack.api.ApiConstants.MAX_IOPS;
|
||||
import static org.apache.cloudstack.api.ApiConstants.MIN_IOPS;
|
||||
import static org.apache.cloudstack.storage.volume.VolumeImportUnmanageService.AllowImportVolumeWithBackingFile;
|
||||
import static org.apache.cloudstack.vm.ImportVmTask.Step.CloningInstance;
|
||||
import static org.apache.cloudstack.vm.ImportVmTask.Step.Completed;
|
||||
import static org.apache.cloudstack.vm.ImportVmTask.Step.ConvertingInstance;
|
||||
import static org.apache.cloudstack.vm.ImportVmTask.Step.Importing;
|
||||
|
||||
public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
||||
public static final String VM_IMPORT_DEFAULT_TEMPLATE_NAME = "system-default-vm-import-dummy-template.iso";
|
||||
public static final String KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME = "kvm-default-vm-import-dummy-template";
|
||||
protected Logger logger = LogManager.getLogger(UnmanagedVMsManagerImpl.class);
|
||||
private static final long OTHER_LINUX_64_GUEST_OS_ID = 99;
|
||||
private static final List<Hypervisor.HypervisorType> importUnmanagedInstancesSupportedHypervisors =
|
||||
Arrays.asList(Hypervisor.HypervisorType.VMware, Hypervisor.HypervisorType.KVM);
|
||||
|
||||
|
|
@ -326,7 +324,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
try {
|
||||
template = VMTemplateVO.createSystemIso(templateDao.getNextInSequence(Long.class, "id"), templateName, templateName, true,
|
||||
"", true, 64, Account.ACCOUNT_ID_SYSTEM, "",
|
||||
"VM Import Default Template", false, 1);
|
||||
"VM Import Default Template", false, OTHER_LINUX_64_GUEST_OS_ID);
|
||||
template.setState(VirtualMachineTemplate.State.Inactive);
|
||||
template = templateDao.persist(template);
|
||||
if (template == null) {
|
||||
|
|
@ -340,68 +338,6 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
return template;
|
||||
}
|
||||
|
||||
private UnmanagedInstanceResponse createUnmanagedInstanceResponse(UnmanagedInstanceTO instance, Cluster cluster, Host host) {
|
||||
UnmanagedInstanceResponse response = new UnmanagedInstanceResponse();
|
||||
response.setName(instance.getName());
|
||||
|
||||
if (cluster != null) {
|
||||
response.setClusterId(cluster.getUuid());
|
||||
}
|
||||
if (host != null) {
|
||||
response.setHostId(host.getUuid());
|
||||
response.setHostName(host.getName());
|
||||
}
|
||||
response.setPowerState(instance.getPowerState().toString());
|
||||
response.setCpuCores(instance.getCpuCores());
|
||||
response.setCpuSpeed(instance.getCpuSpeed());
|
||||
response.setCpuCoresPerSocket(instance.getCpuCoresPerSocket());
|
||||
response.setMemory(instance.getMemory());
|
||||
response.setOperatingSystemId(instance.getOperatingSystemId());
|
||||
response.setOperatingSystem(instance.getOperatingSystem());
|
||||
response.setObjectName("unmanagedinstance");
|
||||
|
||||
if (instance.getDisks() != null) {
|
||||
for (UnmanagedInstanceTO.Disk disk : instance.getDisks()) {
|
||||
UnmanagedInstanceDiskResponse diskResponse = new UnmanagedInstanceDiskResponse();
|
||||
diskResponse.setDiskId(disk.getDiskId());
|
||||
if (StringUtils.isNotEmpty(disk.getLabel())) {
|
||||
diskResponse.setLabel(disk.getLabel());
|
||||
}
|
||||
diskResponse.setCapacity(disk.getCapacity());
|
||||
diskResponse.setController(disk.getController());
|
||||
diskResponse.setControllerUnit(disk.getControllerUnit());
|
||||
diskResponse.setPosition(disk.getPosition());
|
||||
diskResponse.setImagePath(disk.getImagePath());
|
||||
diskResponse.setDatastoreName(disk.getDatastoreName());
|
||||
diskResponse.setDatastoreHost(disk.getDatastoreHost());
|
||||
diskResponse.setDatastorePath(disk.getDatastorePath());
|
||||
diskResponse.setDatastoreType(disk.getDatastoreType());
|
||||
response.addDisk(diskResponse);
|
||||
}
|
||||
}
|
||||
|
||||
if (instance.getNics() != null) {
|
||||
for (UnmanagedInstanceTO.Nic nic : instance.getNics()) {
|
||||
NicResponse nicResponse = new NicResponse();
|
||||
nicResponse.setId(nic.getNicId());
|
||||
nicResponse.setNetworkName(nic.getNetwork());
|
||||
nicResponse.setMacAddress(nic.getMacAddress());
|
||||
if (StringUtils.isNotEmpty(nic.getAdapterType())) {
|
||||
nicResponse.setAdapterType(nic.getAdapterType());
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(nic.getIpAddress())) {
|
||||
nicResponse.setIpAddresses(nic.getIpAddress());
|
||||
}
|
||||
nicResponse.setVlanId(nic.getVlan());
|
||||
nicResponse.setIsolatedPvlanId(nic.getPvlan());
|
||||
nicResponse.setIsolatedPvlanType(nic.getPvlanType());
|
||||
response.addNic(nicResponse);
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private List<String> getAdditionalNameFilters(Cluster cluster) {
|
||||
List<String> additionalNameFilter = new ArrayList<>();
|
||||
if (cluster == null) {
|
||||
|
|
@ -1145,7 +1081,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
private UserVm importVirtualMachineInternal(final UnmanagedInstanceTO unmanagedInstance, final String instanceNameInternal, final DataCenter zone, final Cluster cluster, final HostVO host,
|
||||
final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId,
|
||||
final ServiceOfferingVO serviceOffering, final Map<String, Long> dataDiskOfferingMap,
|
||||
final Map<String, Long> nicNetworkMap, final Map<String, Network.IpAddresses> callerNicIpAddressMap,
|
||||
final Map<String, Long> nicNetworkMap, final Map<String, Network.IpAddresses> callerNicIpAddressMap, final Long guestOsId,
|
||||
final Map<String, String> details, final boolean migrateAllowed, final boolean forced, final boolean isImportUnmanagedFromSameHypervisor) {
|
||||
logger.debug(LogUtils.logGsonWithoutException("Trying to import VM [%s] with name [%s], in zone [%s], cluster [%s], and host [%s], using template [%s], service offering [%s], disks map [%s], NICs map [%s] and details [%s].",
|
||||
unmanagedInstance, displayName, zone, cluster, host, template, serviceOffering, dataDiskOfferingMap, nicNetworkMap, details));
|
||||
|
|
@ -1231,7 +1167,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
try {
|
||||
userVm = userVmManager.importVM(zone, host, template, internalCSName, displayName, owner,
|
||||
null, caller, true, null, owner.getAccountId(), userId,
|
||||
validatedServiceOffering, null, hostName,
|
||||
validatedServiceOffering, null, guestOsId, hostName,
|
||||
cluster.getHypervisorType(), allDetails, powerState, null);
|
||||
} catch (InsufficientCapacityException ice) {
|
||||
String errorMsg = String.format("Failed to import VM [%s] due to [%s].", displayName, ice.getMessage());
|
||||
|
|
@ -1550,10 +1486,11 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
protected VMTemplateVO getTemplateForImportInstance(Long templateId, Hypervisor.HypervisorType hypervisorType) {
|
||||
VMTemplateVO template;
|
||||
if (templateId == null) {
|
||||
String templateName = (Hypervisor.HypervisorType.KVM.equals(hypervisorType)) ? KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME : VM_IMPORT_DEFAULT_TEMPLATE_NAME;
|
||||
boolean isKVMHypervisor = Hypervisor.HypervisorType.KVM.equals(hypervisorType);
|
||||
String templateName = (isKVMHypervisor) ? KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME : VM_IMPORT_DEFAULT_TEMPLATE_NAME;
|
||||
template = templateDao.findByName(templateName);
|
||||
if (template == null) {
|
||||
template = createDefaultDummyVmImportTemplate(Hypervisor.HypervisorType.KVM == hypervisorType);
|
||||
template = createDefaultDummyVmImportTemplate(isKVMHypervisor);
|
||||
if (template == null) {
|
||||
throw new InvalidParameterValueException(String.format("Default VM import template with unique name: %s for hypervisor: %s cannot be created. Please use templateid parameter for import", templateName, hypervisorType.toString()));
|
||||
}
|
||||
|
|
@ -1633,7 +1570,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
userVm = importVirtualMachineInternal(unmanagedInstance, instanceName, zone, cluster, host,
|
||||
template, displayName, hostName, CallContext.current().getCallingAccount(), owner, userId,
|
||||
serviceOffering, dataDiskOfferingMap,
|
||||
nicNetworkMap, nicIpAddressMap,
|
||||
nicNetworkMap, nicIpAddressMap, null,
|
||||
details, migrateAllowed, forced, true);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1713,6 +1650,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
Long convertStoragePoolId = cmd.getConvertStoragePoolId();
|
||||
String extraParams = cmd.getExtraParams();
|
||||
boolean forceConvertToPool = cmd.getForceConvertToPool();
|
||||
Long guestOsId = cmd.getGuestOsId();
|
||||
|
||||
if ((existingVcenterId == null && vcenter == null) || (existingVcenterId != null && vcenter != null)) {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR,
|
||||
|
|
@ -1800,7 +1738,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
UserVm userVm = importVirtualMachineInternal(convertedInstance, null, zone, destinationCluster, null,
|
||||
template, displayName, hostName, caller, owner, userId,
|
||||
serviceOffering, dataDiskOfferingMap,
|
||||
nicNetworkMap, nicIpAddressMap,
|
||||
nicNetworkMap, nicIpAddressMap, guestOsId,
|
||||
details, false, forced, false);
|
||||
long timeElapsedInSecs = (System.currentTimeMillis() - importStartTime) / 1000;
|
||||
logger.debug(String.format("VMware VM %s imported successfully to CloudStack instance %s (%s), Time taken: %d secs, OVF files imported from %s, Source VMware VM details - OS: %s, PowerState: %s, Disks: %s, NICs: %s",
|
||||
|
|
@ -2366,6 +2304,8 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
* Perform validations before attempting to unmanage a VM from CloudStack:
|
||||
* - VM must not have any associated volume snapshot
|
||||
* - VM must not have an attached ISO
|
||||
* - VM must not belong to any CKS cluster
|
||||
* @throws UnsupportedServiceException in case any of the validations above fail
|
||||
*/
|
||||
void performUnmanageVMInstancePrechecks(VMInstanceVO vmVO) {
|
||||
if (hasVolumeSnapshotsPriorToUnmanageVM(vmVO)) {
|
||||
|
|
@ -2377,6 +2317,11 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
throw new UnsupportedServiceException("Cannot unmanage VM with id = " + vmVO.getUuid() +
|
||||
" as there is an ISO attached. Please detach ISO before unmanaging.");
|
||||
}
|
||||
|
||||
if (userVmManager.isVMPartOfAnyCKSCluster(vmVO)) {
|
||||
throw new UnsupportedServiceException("Cannot unmanage VM with id = " + vmVO.getUuid() +
|
||||
" as it belongs to a CKS cluster. Please remove the VM from the CKS cluster before unmanaging.");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasVolumeSnapshotsPriorToUnmanageVM(VMInstanceVO vmVO) {
|
||||
|
|
@ -2677,7 +2622,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
try {
|
||||
userVm = userVmManager.importVM(zone, null, template, null, displayName, owner,
|
||||
null, caller, true, null, owner.getAccountId(), userId,
|
||||
serviceOffering, null, hostName,
|
||||
serviceOffering, null, null, hostName,
|
||||
Hypervisor.HypervisorType.KVM, allDetails, powerState, null);
|
||||
} catch (InsufficientCapacityException ice) {
|
||||
logger.error(String.format("Failed to import vm name: %s", instanceName), ice);
|
||||
|
|
@ -2815,7 +2760,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
try {
|
||||
userVm = userVmManager.importVM(zone, null, template, null, displayName, owner,
|
||||
null, caller, true, null, owner.getAccountId(), userId,
|
||||
serviceOffering, null, hostName,
|
||||
serviceOffering, null, null, hostName,
|
||||
Hypervisor.HypervisorType.KVM, allDetails, powerState, networkNicMap);
|
||||
} catch (InsufficientCapacityException ice) {
|
||||
logger.error(String.format("Failed to import vm name: %s", instanceName), ice);
|
||||
|
|
@ -2909,7 +2854,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
}
|
||||
if (volumeDetails.containsKey(VolumeOnStorageTO.Detail.BACKING_FILE)) {
|
||||
String backingFile = volumeDetails.get(VolumeOnStorageTO.Detail.BACKING_FILE);
|
||||
if (StringUtils.isNotBlank(backingFile)) {
|
||||
if (StringUtils.isNotBlank(backingFile) && !AllowImportVolumeWithBackingFile.value()) {
|
||||
logFailureAndThrowException("Volume with backing file cannot be imported or unmanaged.");
|
||||
}
|
||||
}
|
||||
|
|
@ -3000,9 +2945,8 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
!instance.getName().toLowerCase().contains(keyword)) {
|
||||
continue;
|
||||
}
|
||||
responses.add(createUnmanagedInstanceResponse(instance, null, null));
|
||||
responses.add(responseGenerator.createUnmanagedInstanceResponse(instance, null, null));
|
||||
}
|
||||
|
||||
ListResponse<UnmanagedInstanceResponse> listResponses = new ListResponse<>();
|
||||
listResponses.setResponses(responses, responses.size());
|
||||
return listResponses;
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ import org.apache.cloudstack.api.command.user.vm.ResetVMSSHKeyCmd;
|
|||
import org.apache.cloudstack.api.command.user.vm.ResetVMUserDataCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.RestoreVMCmd;
|
||||
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.volume.ResizeVolumeCmd;
|
||||
import org.apache.cloudstack.backup.BackupManager;
|
||||
import org.apache.cloudstack.backup.BackupVO;
|
||||
|
|
@ -198,6 +199,7 @@ import com.cloud.utils.db.EntityManager;
|
|||
import com.cloud.utils.db.UUIDManager;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.exception.ExceptionProxyObject;
|
||||
import com.cloud.utils.fsm.NoTransitionException;
|
||||
import com.cloud.vm.dao.NicDao;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.VMInstanceDetailsDao;
|
||||
|
|
@ -244,6 +246,9 @@ public class UserVmManagerImplTest {
|
|||
@Mock
|
||||
private UpdateVMCmd updateVmCommand;
|
||||
|
||||
@Mock
|
||||
private UpdateVmNicCmd updateVmNicCmd;
|
||||
|
||||
@Mock
|
||||
private AccountManager accountManager;
|
||||
|
||||
|
|
@ -271,6 +276,9 @@ public class UserVmManagerImplTest {
|
|||
@Mock
|
||||
private UserVO callerUser;
|
||||
|
||||
@Mock
|
||||
private NicVO nicMock;
|
||||
|
||||
@Mock
|
||||
private VMTemplateDao templateDao;
|
||||
|
||||
|
|
@ -454,6 +462,8 @@ public class UserVmManagerImplTest {
|
|||
private static final long vmId = 1l;
|
||||
private static final long zoneId = 2L;
|
||||
private static final long accountId = 3L;
|
||||
private static final long nicId = 4L;
|
||||
private static final long networkId = 5L;
|
||||
private static final long serviceOfferingId = 10L;
|
||||
private static final long templateId = 11L;
|
||||
private static final long volumeId = 1L;
|
||||
|
|
@ -1501,6 +1511,7 @@ public class UserVmManagerImplTest {
|
|||
when(cmd.getVmId()).thenReturn(vmId);
|
||||
when(cmd.getTemplateId()).thenReturn(2L);
|
||||
when(userVmDao.findById(vmId)).thenReturn(userVmVoMock);
|
||||
Mockito.doReturn(false).when(userVmManagerImpl).isVMPartOfAnyCKSCluster(userVmVoMock);
|
||||
|
||||
userVmManagerImpl.restoreVM(cmd);
|
||||
}
|
||||
|
|
@ -4251,4 +4262,111 @@ public class UserVmManagerImplTest {
|
|||
verify(vmInstanceDetailsDao, never()).removeDetailsWithPrefix(anyLong(), anyString());
|
||||
verify(userVmManagerImpl, never()).addExtraConfig(any(UserVmVO.class), anyString());
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void updateVirtualMachineNicTestInvalidNicThrowInvalidParameterValueException() {
|
||||
Long invalidId = -1L;
|
||||
Mockito.doReturn(invalidId).when(updateVmNicCmd).getNicId();
|
||||
|
||||
userVmManagerImpl.updateVirtualMachineNic(updateVmNicCmd);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void updateVirtualMachineNicTestInvalidNicUserVmThrowInvalidParameterValueException() {
|
||||
Mockito.doReturn(nicId).when(updateVmNicCmd).getNicId();
|
||||
Mockito.doReturn(nicMock).when(nicDao).findById(nicId);
|
||||
|
||||
userVmManagerImpl.updateVirtualMachineNic(updateVmNicCmd);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void updateVirtualMachineNicTestInvalidNicNetworkThrowInvalidParameterValueException() {
|
||||
Mockito.doReturn(nicId).when(updateVmNicCmd).getNicId();
|
||||
Mockito.doReturn(true).when(updateVmNicCmd).isEnabled();
|
||||
Mockito.doReturn(nicMock).when(nicDao).findById(nicId);
|
||||
Mockito.doReturn(vmId).when(nicMock).getInstanceId();
|
||||
Mockito.doReturn(userVmVoMock).when(userVmDao).findById(vmId);
|
||||
|
||||
userVmManagerImpl.updateVirtualMachineNic(updateVmNicCmd);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void updateVirtualMachineNicTestInvalidNicNetworkThrowCloudRuntimeException() {
|
||||
Mockito.doReturn(nicId).when(updateVmNicCmd).getNicId();
|
||||
Mockito.doReturn(true).when(updateVmNicCmd).isEnabled();
|
||||
Mockito.doReturn(nicMock).when(nicDao).findById(nicId);
|
||||
Mockito.doReturn(vmId).when(nicMock).getInstanceId();
|
||||
Mockito.doReturn(userVmVoMock).when(userVmDao).findById(vmId);
|
||||
|
||||
userVmManagerImpl.updateVirtualMachineNic(updateVmNicCmd);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateVirtualMachineNicTestValidInputReturnNicUserVm() throws ResourceUnavailableException {
|
||||
Mockito.doReturn(nicId).when(updateVmNicCmd).getNicId();
|
||||
Mockito.doReturn(true).when(updateVmNicCmd).isEnabled();
|
||||
Mockito.doReturn(nicMock).when(nicDao).findById(nicId);
|
||||
Mockito.doReturn(vmId).when(nicMock).getInstanceId();
|
||||
Mockito.doReturn(userVmVoMock).when(userVmDao).findById(vmId);
|
||||
Mockito.doReturn(Hypervisor.HypervisorType.KVM).when(userVmVoMock).getHypervisorType();
|
||||
Mockito.doReturn(networkId).when(nicMock).getNetworkId();
|
||||
Mockito.doReturn(networkMock).when(_networkDao).findById(networkId);
|
||||
Mockito.doReturn(true).when(virtualMachineManager).updateVmNic(Mockito.any(), Mockito.any(), Mockito.any());
|
||||
|
||||
UserVm result = userVmManagerImpl.updateVirtualMachineNic(updateVmNicCmd);
|
||||
|
||||
Assert.assertNotNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransitionExpungingToErrorVmInExpungingState() throws Exception {
|
||||
UserVmVO vm = mock(UserVmVO.class);
|
||||
when(vm.getState()).thenReturn(VirtualMachine.State.Expunging);
|
||||
when(vm.getUuid()).thenReturn("test-uuid");
|
||||
when(userVmDao.findById(vmId)).thenReturn(vm);
|
||||
when(virtualMachineManager.stateTransitTo(eq(vm), eq(VirtualMachine.Event.OperationFailedToError), eq(null))).thenReturn(true);
|
||||
|
||||
java.lang.reflect.Method method = UserVmManagerImpl.class.getDeclaredMethod("transitionExpungingToError", long.class);
|
||||
method.setAccessible(true);
|
||||
method.invoke(userVmManagerImpl, vmId);
|
||||
|
||||
Mockito.verify(virtualMachineManager).stateTransitTo(vm, VirtualMachine.Event.OperationFailedToError, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransitionExpungingToErrorVmNotInExpungingState() throws Exception {
|
||||
UserVmVO vm = mock(UserVmVO.class);
|
||||
when(vm.getState()).thenReturn(VirtualMachine.State.Stopped);
|
||||
when(userVmDao.findById(vmId)).thenReturn(vm);
|
||||
|
||||
java.lang.reflect.Method method = UserVmManagerImpl.class.getDeclaredMethod("transitionExpungingToError", long.class);
|
||||
method.setAccessible(true);
|
||||
method.invoke(userVmManagerImpl, vmId);
|
||||
|
||||
Mockito.verify(virtualMachineManager, Mockito.never()).stateTransitTo(any(VirtualMachine.class), any(VirtualMachine.Event.class), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransitionExpungingToErrorVmNotFound() throws Exception {
|
||||
when(userVmDao.findById(vmId)).thenReturn(null);
|
||||
|
||||
java.lang.reflect.Method method = UserVmManagerImpl.class.getDeclaredMethod("transitionExpungingToError", long.class);
|
||||
method.setAccessible(true);
|
||||
method.invoke(userVmManagerImpl, vmId);
|
||||
|
||||
Mockito.verify(virtualMachineManager, Mockito.never()).stateTransitTo(any(VirtualMachine.class), any(VirtualMachine.Event.class), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransitionExpungingToErrorHandlesNoTransitionException() throws Exception {
|
||||
UserVmVO vm = mock(UserVmVO.class);
|
||||
when(vm.getState()).thenReturn(VirtualMachine.State.Expunging);
|
||||
when(userVmDao.findById(vmId)).thenReturn(vm);
|
||||
when(virtualMachineManager.stateTransitTo(eq(vm), eq(VirtualMachine.Event.OperationFailedToError), eq(null)))
|
||||
.thenThrow(new NoTransitionException("no transition"));
|
||||
|
||||
java.lang.reflect.Method method = UserVmManagerImpl.class.getDeclaredMethod("transitionExpungingToError", long.class);
|
||||
method.setAccessible(true);
|
||||
method.invoke(userVmManagerImpl, vmId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
|
|
@ -39,6 +40,9 @@ import java.util.Map;
|
|||
import java.util.UUID;
|
||||
|
||||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.SnapshotVO;
|
||||
import com.cloud.storage.dao.SnapshotDao;
|
||||
import com.cloud.vm.ImportVMTaskVO;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ResponseGenerator;
|
||||
|
|
@ -241,6 +245,8 @@ public class UnmanagedVMsManagerImplTest {
|
|||
private StoragePoolHostDao storagePoolHostDao;
|
||||
@Mock
|
||||
private ImportVmTasksManager importVmTasksManager;
|
||||
@Mock
|
||||
private SnapshotDao snapshotDao;
|
||||
|
||||
@Mock
|
||||
private VMInstanceVO virtualMachine;
|
||||
|
|
@ -360,7 +366,7 @@ public class UnmanagedVMsManagerImplTest {
|
|||
when(primaryDataStoreDao.listPoolByHostPath(Mockito.anyString(), Mockito.anyString())).thenReturn(pools);
|
||||
when(userVmManager.importVM(nullable(DataCenter.class), nullable(Host.class), nullable(VirtualMachineTemplate.class), nullable(String.class), nullable(String.class),
|
||||
nullable(Account.class), nullable(String.class), nullable(Account.class), nullable(Boolean.class), nullable(String.class),
|
||||
nullable(Long.class), nullable(Long.class), nullable(ServiceOffering.class), nullable(String.class),
|
||||
nullable(Long.class), nullable(Long.class), nullable(ServiceOffering.class), nullable(String.class), nullable(Long.class),
|
||||
nullable(String.class), nullable(Hypervisor.HypervisorType.class), nullable(Map.class), nullable(VirtualMachine.PowerState.class), nullable(LinkedHashMap.class))).thenReturn(userVm);
|
||||
NetworkVO networkVO = Mockito.mock(NetworkVO.class);
|
||||
when(networkVO.getGuestType()).thenReturn(Network.GuestType.L2);
|
||||
|
|
@ -568,6 +574,53 @@ public class UnmanagedVMsManagerImplTest {
|
|||
unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedServiceException.class)
|
||||
public void testUnmanageVMInstanceWithVolumeSnapshotsFail() {
|
||||
when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User);
|
||||
when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
|
||||
when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped);
|
||||
when(virtualMachine.getId()).thenReturn(virtualMachineId);
|
||||
UserVmVO userVmVO = mock(UserVmVO.class);
|
||||
when(userVmDao.findById(anyLong())).thenReturn(userVmVO);
|
||||
when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine);
|
||||
VolumeVO volumeVO = mock(VolumeVO.class);
|
||||
long volumeId = 20L;
|
||||
when(volumeVO.getId()).thenReturn(volumeId);
|
||||
SnapshotVO snapshotVO = mock(SnapshotVO.class);
|
||||
when(snapshotVO.getState()).thenReturn(Snapshot.State.BackedUp);
|
||||
when(snapshotDao.listByVolumeId(volumeId)).thenReturn(Collections.singletonList(snapshotVO));
|
||||
when(volumeDao.findByInstance(virtualMachineId)).thenReturn(Collections.singletonList(volumeVO));
|
||||
unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedServiceException.class)
|
||||
public void testUnmanageVMInstanceWithAssociatedIsoFail() {
|
||||
when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User);
|
||||
when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
|
||||
when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped);
|
||||
when(virtualMachine.getId()).thenReturn(virtualMachineId);
|
||||
UserVmVO userVmVO = mock(UserVmVO.class);
|
||||
when(userVmVO.getIsoId()).thenReturn(null);
|
||||
when(userVmDao.findById(anyLong())).thenReturn(userVmVO);
|
||||
when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine);
|
||||
when(userVmVO.getIsoId()).thenReturn(1L);
|
||||
unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedServiceException.class)
|
||||
public void testUnmanageVMInstanceBelongingToCksClusterFail() {
|
||||
when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User);
|
||||
when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
|
||||
when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped);
|
||||
when(virtualMachine.getId()).thenReturn(virtualMachineId);
|
||||
UserVmVO userVmVO = mock(UserVmVO.class);
|
||||
when(userVmVO.getIsoId()).thenReturn(null);
|
||||
when(userVmDao.findById(anyLong())).thenReturn(userVmVO);
|
||||
when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine);
|
||||
when(userVmManager.isVMPartOfAnyCKSCluster(virtualMachine)).thenReturn(true);
|
||||
unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListRemoteInstancesTest() {
|
||||
ListVmsForImportCmd cmd = Mockito.mock(ListVmsForImportCmd.class);
|
||||
|
|
|
|||
|
|
@ -542,7 +542,7 @@ class TestRouters(cloudstackTestCase):
|
|||
|
||||
|
||||
# Validate the following
|
||||
# 1. PreReq: have rounters that are owned by other account
|
||||
# 1. PreReq: have routers that are owned by other account
|
||||
# 2. Create domain and create accounts in that domain
|
||||
# 3. Create one VM for each account
|
||||
# 4. Using Admin , run listRouters. It should return all the routers
|
||||
|
|
|
|||
|
|
@ -136,7 +136,11 @@ class TestSecStorageServices(cloudstackTestCase):
|
|||
'Up',
|
||||
"Check state of primary storage pools is Up or not"
|
||||
)
|
||||
for _ in range(2):
|
||||
# Poll until all SSVMs are Running, or timeout after 3 minutes
|
||||
timeout = 180
|
||||
interval = 15
|
||||
list_ssvm_response = []
|
||||
while timeout > 0:
|
||||
list_ssvm_response = list_ssvms(
|
||||
self.apiclient,
|
||||
systemvmtype='secondarystoragevm',
|
||||
|
|
@ -154,10 +158,12 @@ class TestSecStorageServices(cloudstackTestCase):
|
|||
"Check list System VMs response"
|
||||
)
|
||||
|
||||
for ssvm in list_ssvm_response:
|
||||
if ssvm.state != 'Running':
|
||||
time.sleep(30)
|
||||
continue
|
||||
if all(ssvm.state == 'Running' for ssvm in list_ssvm_response):
|
||||
break
|
||||
|
||||
time.sleep(interval)
|
||||
timeout -= interval
|
||||
|
||||
for ssvm in list_ssvm_response:
|
||||
self.assertEqual(
|
||||
ssvm.state,
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue