resolve merge conflict with main

This commit is contained in:
Manoj Kumar 2026-03-03 17:11:54 +05:30
commit 928db650e3
No known key found for this signature in database
GPG Key ID: E952B7234D2C6F88
136 changed files with 4347 additions and 1579 deletions

View File

@ -50,16 +50,10 @@ github:
rebase: false
collaborators:
- acs-robot
- gpordeus
- hsato03
- FelipeM525
- lucas-a-martins
- nicoschmdt
- abh1sar
- rosi-shapeblue
- sudo87
- erikbocks
- Imvedansh
- Damans227
protected_branches: ~

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
.github/workflows/*.lock.yml linguist-generated=true merge=ours

5
.github/aw/imports/.gitattributes generated vendored Normal file
View File

@ -0,0 +1,5 @@
# Mark all cached import files as generated
* linguist-generated=true
# Use 'ours' merge strategy to keep local cached versions
* merge=ours

View File

@ -0,0 +1,73 @@
---
# Report formatting guidelines
---
## Report Structure Guidelines
### 1. Header Levels
**Use h3 (###) or lower for all headers in your issue report to maintain proper document hierarchy.**
When creating GitHub issues or discussions:
- Use `###` (h3) for main sections (e.g., "### Test Summary")
- Use `####` (h4) for subsections (e.g., "#### Device-Specific Results")
- Never use `##` (h2) or `#` (h1) in reports - these are reserved for titles
### 2. Progressive Disclosure
**Wrap detailed test results in `<details><summary><b>Section Name</b></summary>` tags to improve readability and reduce scrolling.**
Use collapsible sections for:
- Verbose details (full test logs, raw data)
- Secondary information (minor warnings, extra context)
- Per-item breakdowns when there are many items
Always keep critical information visible (summary, critical issues, key metrics).
### 3. Report Structure Pattern
1. **Overview**: 1-2 paragraphs summarizing key findings
2. **Critical Information**: Show immediately (summary stats, critical issues)
3. **Details**: Use `<details><summary><b>Section Name</b></summary>` for expanded content
4. **Context**: Add helpful metadata (workflow run, date, trigger)
### Design Principles (Airbnb-Inspired)
Reports should:
- **Build trust through clarity**: Most important info immediately visible
- **Exceed expectations**: Add helpful context like trends, comparisons
- **Create delight**: Use progressive disclosure to reduce overwhelm
- **Maintain consistency**: Follow patterns across all reports
### Example Report Structure
```markdown
### Summary
- Key metric 1: value
- Key metric 2: value
- Status: ✅/⚠️/❌
### Critical Issues
[Always visible - these are important]
<details>
<summary><b>View Detailed Results</b></summary>
[Comprehensive details, logs, traces]
</details>
<details>
<summary><b>View All Warnings</b></summary>
[Minor issues and potential problems]
</details>
### Recommendations
[Actionable next steps - keep visible]
```
## Workflow Run References
- Format run IDs as links: `[§12345](https://github.com/owner/repo/actions/runs/12345)`
- Include up to 3 most relevant run URLs at end under `**References:**`
- Do NOT add footer attribution (system adds automatically)

1022
.github/workflows/daily-repo-status.lock.yml generated vendored Normal file

File diff suppressed because it is too large Load Diff

54
.github/workflows/daily-repo-status.md vendored Normal file
View File

@ -0,0 +1,54 @@
---
description: |
This workflow creates daily repo status reports. It gathers recent repository
activity (issues, PRs, discussions, releases, code changes) and generates
engaging GitHub issues with productivity insights, community highlights,
and project recommendations.
on:
schedule: daily
workflow_dispatch:
permissions:
contents: read
issues: read
pull-requests: read
network: defaults
tools:
github:
# If in a public repo, setting `lockdown: false` allows
# reading issues, pull requests and comments from 3rd-parties
# If in a private repo this has no particular effect.
lockdown: false
safe-outputs:
create-issue:
title-prefix: "[repo-status] "
labels: [report, daily-status]
source: githubnext/agentics/workflows/daily-repo-status.md@d19056381ba48cb1f7c78510c23069701fa7ae87
---
# Daily Repo Status
Create an upbeat daily status report for the repo as a GitHub issue.
## What to include
- Recent repository activity (issues, PRs, discussions, releases, code changes)
- Progress tracking, goal reminders and highlights
- Project status and recommendations
- Actionable next steps for maintainers
## Style
- Be positive, encouraging, and helpful 🌟
- Use emojis moderately for engagement
- Keep it concise - adjust length based on actual activity
## Process
1. Gather recent activity from the repository
2. Study the repository, its issues and its pull requests
3. Create a new GitHub issue with your findings and insights

1016
.github/workflows/issue-triage-agent.lock.yml generated vendored Normal file

File diff suppressed because it is too large Load Diff

78
.github/workflows/issue-triage-agent.md vendored Normal file
View File

@ -0,0 +1,78 @@
---
on:
schedule: 0 14 * * 1-5
workflow_dispatch: null
permissions:
issues: read
imports:
- github/gh-aw/.github/workflows/shared/reporting.md@94662b1dee8ce96c876ba9f33b3ab8be32de82a4
safe-outputs:
add-comment: {}
add-labels:
allowed:
- bug
- feature
- enhancement
- documentation
- question
- help-wanted
- good-first-issue
source: github/gh-aw/.github/workflows/issue-triage-agent.md@94662b1dee8ce96c876ba9f33b3ab8be32de82a4
strict: true
timeout-minutes: 5
tools:
github:
toolsets:
- issues
- labels
---
# Issue Triage Agent
List open issues in ${{ github.repository }} that have no labels. For each unlabeled issue, analyze the title and body, then add one of the allowed labels: `bug`, `feature`, `enhancement`, `documentation`, `question`, `help-wanted`, or `good-first-issue`.
Skip issues that:
- Already have any of these labels
- Have been assigned to any user (especially non-bot users)
After adding the label to an issue, mention the issue author in a comment using this format (follow shared/reporting.md guidelines):
**Comment Template**:
```markdown
### 🏷️ Issue Triaged
Hi @{author}! I've categorized this issue as **{label_name}** based on the following analysis:
**Reasoning**: {brief_explanation_of_why_this_label}
<details>
<summary><b>View Triage Details</b></summary>
#### Analysis
- **Keywords detected**: {list_of_keywords_that_matched}
- **Issue type indicators**: {what_made_this_fit_the_category}
- **Confidence**: {High/Medium/Low}
#### Recommended Next Steps
- {context_specific_suggestion_1}
- {context_specific_suggestion_2}
</details>
**References**: [Triage run §{run_id}](https://github.com/github/gh-aw/actions/runs/{run_id})
```
**Key formatting requirements**:
- Use h3 (###) for the main heading
- Keep reasoning visible for quick understanding
- Wrap detailed analysis in `<details>` tags
- Include workflow run reference
- Keep total comment concise (collapsed details prevent noise)
## Batch Comment Optimization
For efficiency, if multiple issues are triaged in a single run:
1. Add individual labels to each issue
2. Add a brief comment to each issue (using the template above)
3. Optionally: Create a discussion summarizing all triage actions for that run
This provides both per-issue context and batch visibility.

View File

@ -18,8 +18,8 @@
name: "PR Merge Conflict Check"
on:
push:
pull_request_target:
types: [synchronize]
pull_request:
types: [opened, synchronize, reopened]
permissions: # added using https://github.com/step-security/secure-workflows
contents: read

View File

@ -71,7 +71,7 @@ repos:
- --license-filepath
- .github/workflows/license-templates/LICENSE.txt
- --fuzzy-match-generates-todo
exclude: ^(CHANGES|ISSUE_TEMPLATE|PULL_REQUEST_TEMPLATE)\.md$|^ui/docs/(full|smoke)-test-plan\.template\.md$
exclude: ^(CHANGES|ISSUE_TEMPLATE|PULL_REQUEST_TEMPLATE)\.md$|^ui/docs/(full|smoke)-test-plan\.template\.md$|^\.github/workflows/.*\.md$|^\.github/aw/.*\.md$
- id: insert-license
name: add license for all properties files
description: automatically adds a licence header to all properties files that don't have a license header
@ -120,6 +120,7 @@ repos:
- --license-filepath
- .github/workflows/license-templates/LICENSE.txt
- --fuzzy-match-generates-todo
exclude: ^\.github/workflows/.*\.lock\.yml$
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
@ -195,4 +196,4 @@ repos:
args: [--config-file=.github/linters/.yamllint.yml]
types: [yaml]
files: \.ya?ml$
exclude: ^.*k8s-.*\.ya?ml$
exclude: ^.*k8s-.*\.ya?ml$|^.github/workflows/.*\.lock\.ya?ml$

View File

@ -59,6 +59,9 @@ public interface Host extends StateObject<Status>, Identity, Partition, HAResour
String HOST_INSTANCE_CONVERSION = "host.instance.conversion";
String HOST_OVFTOOL_VERSION = "host.ovftool.version";
String HOST_VIRTV2V_VERSION = "host.virtv2v.version";
String HOST_SSH_PORT = "host.ssh.port";
int DEFAULT_SSH_PORT = 22;
/**
* @return name of the machine.

View File

@ -59,7 +59,8 @@ public interface AccountService {
User getSystemUser();
User createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId, String userUUID);
User createUser(String userName, String password, String firstName, String lastName, String email, String timeZone,
String accountName, Long domainId, String userUUID, boolean isPasswordChangeRequired);
User createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId, String userUUID,
User.Source source);

View File

@ -1261,6 +1261,7 @@ public class ApiConstants {
public static final String PROVIDER_FOR_2FA = "providerfor2fa";
public static final String ISSUER_FOR_2FA = "issuerfor2fa";
public static final String MANDATE_2FA = "mandate2fa";
public static final String PASSWORD_CHANGE_REQUIRED = "passwordchangerequired";
public static final String SECRET_CODE = "secretcode";
public static final String LOGIN = "login";
public static final String LOGOUT = "logout";

View File

@ -60,7 +60,8 @@ public class AddHostCmd extends BaseCmd {
@Parameter(name = ApiConstants.POD_ID, type = CommandType.UUID, entityType = PodResponse.class, required = true, description = "The Pod ID for the host")
private Long podId;
@Parameter(name = ApiConstants.URL, type = CommandType.STRING, required = true, description = "The host URL")
@Parameter(name = ApiConstants.URL, type = CommandType.STRING, required = true, description = "The host URL, optionally add ssh port (format: 'host:port') for KVM hosts," +
" otherwise falls back to the port defined at the config 'kvm.host.discovery.ssh.port'")
private String url;
@Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, required = true, description = "The Zone ID for the host")

View File

@ -26,6 +26,7 @@ import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.UserResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import com.cloud.user.Account;
@ -78,6 +79,12 @@ public class CreateUserCmd extends BaseCmd {
@Parameter(name = ApiConstants.USER_ID, type = CommandType.STRING, description = "User UUID, required for adding account from external provisioning system")
private String userUUID;
@Parameter(name = ApiConstants.PASSWORD_CHANGE_REQUIRED,
type = CommandType.BOOLEAN,
description = "Provide true to mandate the User to reset password on next login.",
since = "4.23.0")
private Boolean passwordChangeRequired;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -118,6 +125,10 @@ public class CreateUserCmd extends BaseCmd {
return userUUID;
}
public Boolean isPasswordChangeRequired() {
return BooleanUtils.isTrue(passwordChangeRequired);
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@ -147,7 +158,7 @@ public class CreateUserCmd extends BaseCmd {
CallContext.current().setEventDetails("UserName: " + getUserName() + ", FirstName :" + getFirstName() + ", LastName: " + getLastName());
User user =
_accountService.createUser(getUserName(), getPassword(), getFirstName(), getLastName(), getEmail(), getTimezone(), getAccountName(), getDomainId(),
getUserUUID());
getUserUUID(), isPasswordChangeRequired());
if (user != null) {
UserResponse response = _responseGenerator.createUserResponse(user);
response.setResponseName(getCommandName());

View File

@ -29,6 +29,7 @@ import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.UserResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.region.RegionService;
import org.apache.commons.lang.BooleanUtils;
import com.cloud.user.Account;
import com.cloud.user.User;
@ -38,6 +39,8 @@ import com.cloud.user.UserAccount;
requestHasSensitiveInfo = true, responseHasSensitiveInfo = true)
public class UpdateUserCmd extends BaseCmd {
@Inject
private RegionService _regionService;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
@ -85,8 +88,11 @@ public class UpdateUserCmd extends BaseCmd {
"This parameter is only used to mandate 2FA, not to disable 2FA", since = "4.18.0.0")
private Boolean mandate2FA;
@Inject
private RegionService _regionService;
@Parameter(name = ApiConstants.PASSWORD_CHANGE_REQUIRED,
type = CommandType.BOOLEAN,
description = "Provide true to mandate the User to reset password on next login.",
since = "4.23.0")
private Boolean passwordChangeRequired;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
@ -193,4 +199,8 @@ public class UpdateUserCmd extends BaseCmd {
public ApiCommandResourceType getApiResourceType() {
return ApiCommandResourceType.User;
}
public Boolean isPasswordChangeRequired() {
return BooleanUtils.isTrue(passwordChangeRequired);
}
}

View File

@ -90,6 +90,10 @@ public class LoginCmdResponse extends AuthenticationCmdResponse {
@Param(description = "Management Server ID that the user logged to", since = "4.21.0.0")
private String managementServerId;
@SerializedName(value = ApiConstants.PASSWORD_CHANGE_REQUIRED)
@Param(description = "Indicates whether the User is required to change password on next login.", since = "4.23.0")
private Boolean passwordChangeRequired;
public String getUsername() {
return username;
}
@ -223,4 +227,12 @@ public class LoginCmdResponse extends AuthenticationCmdResponse {
public void setManagementServerId(String managementServerId) {
this.managementServerId = managementServerId;
}
public Boolean getPasswordChangeRequired() {
return passwordChangeRequired;
}
public void setPasswordChangeRequired(Boolean passwordChangeRequired) {
this.passwordChangeRequired = passwordChangeRequired;
}
}

View File

@ -32,6 +32,7 @@ import org.apache.cloudstack.api.command.user.backup.ListBackupScheduleCmd;
import org.apache.cloudstack.api.command.user.backup.ListBackupsCmd;
import org.apache.cloudstack.api.response.BackupResponse;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.ValidatedConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import com.cloud.exception.ResourceUnavailableException;
@ -53,10 +54,11 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer
"false",
"Is backup and recovery framework enabled.", false, ConfigKey.Scope.Zone);
ConfigKey<String> BackupProviderPlugin = new ConfigKey<>("Advanced", String.class,
ConfigKey<String> BackupProviderPlugin = new ValidatedConfigKey<>("Advanced", String.class,
"backup.framework.provider.plugin",
"dummy",
"The backup and recovery provider plugin. Valid plugin values: dummy, veeam, networker and nas", true, ConfigKey.Scope.Zone, BackupFrameworkEnabled.key());
"The backup and recovery provider plugin. Valid plugin values: dummy, veeam, networker and nas",
true, ConfigKey.Scope.Zone, BackupFrameworkEnabled.key(), value -> validateBackupProviderConfig((String)value));
ConfigKey<Long> BackupSyncPollingInterval = new ConfigKey<>("Advanced", Long.class,
"backup.framework.sync.interval",
@ -249,4 +251,14 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer
Capacity getBackupStorageUsedStats(Long zoneId);
void checkAndRemoveBackupOfferingBeforeExpunge(VirtualMachine vm);
static void validateBackupProviderConfig(String value) {
if (value != null && (value.contains(",") || value.trim().contains(" "))) {
throw new IllegalArgumentException("Multiple backup provider plugins are not supported. Please provide a single plugin value.");
}
List<String> validPlugins = List.of("dummy", "veeam", "networker", "nas");
if (value != null && !validPlugins.contains(value)) {
throw new IllegalArgumentException("Invalid backup provider plugin: " + value + ". Valid plugin values are: " + String.join(", ", validPlugins));
}
}
}

View File

@ -69,7 +69,7 @@ public class CreateUserCmdTest {
} catch (ServerApiException e) {
Assert.assertTrue("Received exception as the mock accountService createUser returns null user", true);
}
Mockito.verify(accountService, Mockito.times(1)).createUser(null, "Test", null, null, null, null, null, null, null);
Mockito.verify(accountService, Mockito.times(1)).createUser(null, "Test", null, null, null, null, null, null, null, false);
}
@Test
@ -82,7 +82,7 @@ public class CreateUserCmdTest {
Assert.assertEquals(ApiErrorCode.PARAM_ERROR,e.getErrorCode());
Assert.assertEquals("Empty passwords are not allowed", e.getMessage());
}
Mockito.verify(accountService, Mockito.never()).createUser(null, null, null, null, null, null, null, null, null);
Mockito.verify(accountService, Mockito.never()).createUser(null, null, null, null, null, null, null, null, null, false);
}
@Test
@ -95,6 +95,6 @@ public class CreateUserCmdTest {
Assert.assertEquals(ApiErrorCode.PARAM_ERROR,e.getErrorCode());
Assert.assertEquals("Empty passwords are not allowed", e.getMessage());
}
Mockito.verify(accountService, Mockito.never()).createUser(null, null, null, null, null, null, null, null, null);
Mockito.verify(accountService, Mockito.never()).createUser(null, null, null, null, null, null, null, null, null, true);
}
}

View File

@ -0,0 +1,64 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.cloudstack.api.command.admin.user;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
@RunWith(MockitoJUnitRunner.class)
public class UpdateUserCmdTest {
@InjectMocks
private UpdateUserCmd cmd;
@Test
public void testGetApiResourceId() {
Long userId = 99L;
cmd.setId(userId);
Assert.assertEquals(userId, cmd.getApiResourceId());
}
@Test
public void testGetApiResourceType() {
Assert.assertEquals(ApiCommandResourceType.User, cmd.getApiResourceType());
}
@Test
public void testIsPasswordChangeRequired_True() {
ReflectionTestUtils.setField(cmd, "passwordChangeRequired", Boolean.TRUE);
Assert.assertTrue(cmd.isPasswordChangeRequired());
}
@Test
public void testIsPasswordChangeRequired_False() {
ReflectionTestUtils.setField(cmd, "passwordChangeRequired", Boolean.FALSE);
Assert.assertFalse(cmd.isPasswordChangeRequired());
}
@Test
public void testIsPasswordChangeRequired_Null() {
ReflectionTestUtils.setField(cmd, "passwordChangeRequired", null);
Assert.assertFalse(cmd.isPasswordChangeRequired());
}
}

View File

@ -0,0 +1,87 @@
// 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.response;
import org.junit.Assert;
import org.junit.Test;
public class LoginCmdResponseTest {
@Test
public void testAllGettersAndSetters() {
LoginCmdResponse response = new LoginCmdResponse();
response.setUsername("user1");
response.setUserId("100");
response.setDomainId("200");
response.setTimeout(3600);
response.setAccount("account1");
response.setFirstName("John");
response.setLastName("Doe");
response.setType("admin");
response.setTimeZone("UTC");
response.setTimeZoneOffset("+00:00");
response.setRegistered("true");
response.setSessionKey("session-key");
response.set2FAenabled("true");
response.set2FAverfied("false");
response.setProviderFor2FA("totp");
response.setIssuerFor2FA("cloudstack");
response.setManagementServerId("ms-1");
Assert.assertEquals("user1", response.getUsername());
Assert.assertEquals("100", response.getUserId());
Assert.assertEquals("200", response.getDomainId());
Assert.assertEquals(Integer.valueOf(3600), response.getTimeout());
Assert.assertEquals("account1", response.getAccount());
Assert.assertEquals("John", response.getFirstName());
Assert.assertEquals("Doe", response.getLastName());
Assert.assertEquals("admin", response.getType());
Assert.assertEquals("UTC", response.getTimeZone());
Assert.assertEquals("+00:00", response.getTimeZoneOffset());
Assert.assertEquals("true", response.getRegistered());
Assert.assertEquals("session-key", response.getSessionKey());
Assert.assertEquals("true", response.is2FAenabled());
Assert.assertEquals("false", response.is2FAverfied());
Assert.assertEquals("totp", response.getProviderFor2FA());
Assert.assertEquals("cloudstack", response.getIssuerFor2FA());
Assert.assertEquals("ms-1", response.getManagementServerId());
}
@Test
public void testPasswordChangeRequired_True() {
LoginCmdResponse response = new LoginCmdResponse();
response.setPasswordChangeRequired(true);
Assert.assertTrue(response.getPasswordChangeRequired());
}
@Test
public void testPasswordChangeRequired_False() {
LoginCmdResponse response = new LoginCmdResponse();
response.setPasswordChangeRequired(false);
Assert.assertFalse(response.getPasswordChangeRequired());
}
@Test
public void testPasswordChangeRequired_Null() {
LoginCmdResponse response = new LoginCmdResponse();
response.setPasswordChangeRequired(null);
Assert.assertNull("Boolean.parseBoolean(null) should return null", response.getPasswordChangeRequired());
}
}

View File

@ -46,6 +46,10 @@ public class ModifyStoragePoolAnswer extends Answer {
templateInfo = tInfo;
}
public ModifyStoragePoolAnswer(final Command command, final boolean success, final String details) {
super(command, success, details);
}
public ModifyStoragePoolAnswer(ModifyStoragePoolCommand cmd, boolean success, String details) {
super(cmd, success, details);
}

View File

@ -34,9 +34,9 @@ public class RestoreBackupCommand extends Command {
private List<String> backupVolumesUUIDs;
private List<PrimaryDataStoreTO> restoreVolumePools;
private List<String> restoreVolumePaths;
private List<String> backupFiles;
private String diskType;
private Boolean vmExists;
private String restoreVolumeUUID;
private VirtualMachine.State vmState;
private Integer mountTimeout;
@ -92,6 +92,14 @@ public class RestoreBackupCommand extends Command {
this.restoreVolumePaths = restoreVolumePaths;
}
public List<String> getBackupFiles() {
return backupFiles;
}
public void setBackupFiles(List<String> backupFiles) {
this.backupFiles = backupFiles;
}
public Boolean isVmExists() {
return vmExists;
}
@ -116,14 +124,6 @@ public class RestoreBackupCommand extends Command {
this.mountOptions = mountOptions;
}
public String getRestoreVolumeUUID() {
return restoreVolumeUUID;
}
public void setRestoreVolumeUUID(String restoreVolumeUUID) {
this.restoreVolumeUUID = restoreVolumeUUID;
}
public VirtualMachine.State getVmState() {
return vmState;
}

View File

@ -54,6 +54,10 @@ public interface AgentManager {
"This timeout overrides the wait global config. This holds a comma separated key value pairs containing timeout (in seconds) for specific commands. " +
"For example: DhcpEntryCommand=600, SavePasswordCommand=300, VmDataCommand=300", false);
ConfigKey<Integer> KVMHostDiscoverySshPort = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED, Integer.class,
"kvm.host.discovery.ssh.port", String.valueOf(Host.DEFAULT_SSH_PORT), "SSH port used for KVM host discovery and any other operations on host (using SSH)." +
" Please note that this is applicable when port is not defined through host url while adding the KVM host.", true, ConfigKey.Scope.Cluster);
enum TapAgentsAction {
Add, Del, Contains,
}
@ -172,4 +176,6 @@ public interface AgentManager {
void propagateChangeToAgents(Map<String, String> params);
boolean transferDirectAgentsFromMS(String fromMsUuid, long fromMsId, long timeoutDurationInMs, boolean excludeHostsInMaintenance);
int getHostSshPort(HostVO host);
}

View File

@ -167,6 +167,8 @@ public interface ResourceManager extends ResourceService, Configurable {
public HostVO findHostByGuid(String guid);
HostVO findHostByGuidPrefix(String guid);
public HostVO findHostByName(String name);
HostStats getHostStatistics(Host host);

View File

@ -42,6 +42,7 @@ import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.utils.StringUtils;
import org.apache.cloudstack.agent.lb.IndirectAgentLB;
import org.apache.cloudstack.ca.CAManager;
import org.apache.cloudstack.command.ReconcileCommandService;
@ -64,7 +65,6 @@ import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToSt
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.ThreadContext;
import com.cloud.agent.AgentManager;
@ -2111,7 +2111,7 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl
return new ConfigKey<?>[] { CheckTxnBeforeSending, Workers, Port, Wait, AlertWait, DirectAgentLoadSize,
DirectAgentPoolSize, DirectAgentThreadCap, EnableKVMAutoEnableDisable, ReadyCommandWait,
GranularWaitTimeForCommands, RemoteAgentSslHandshakeTimeout, RemoteAgentMaxConcurrentNewConnections,
RemoteAgentNewConnectionsMonitorInterval };
RemoteAgentNewConnectionsMonitorInterval, KVMHostDiscoverySshPort };
}
protected class SetHostParamsListener implements Listener {
@ -2234,6 +2234,25 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl
return true;
}
@Override
public int getHostSshPort(HostVO host) {
if (host == null) {
return KVMHostDiscoverySshPort.value();
}
if (host.getHypervisorType() != HypervisorType.KVM) {
return Host.DEFAULT_SSH_PORT;
}
_hostDao.loadDetails(host);
String hostPort = host.getDetail(Host.HOST_SSH_PORT);
if (StringUtils.isBlank(hostPort)) {
return KVMHostDiscoverySshPort.valueIn(host.getClusterId());
}
return Integer.parseInt(hostPort);
}
private GlobalLock getHostJoinLock(Long hostId) {
return GlobalLock.getInternLock(String.format("%s-%s", "Host-Join", hostId));
}

View File

@ -22,6 +22,7 @@ import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.exception.ConnectionException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
@ -104,4 +105,36 @@ public class AgentManagerImplTest {
Assert.assertEquals(50, result);
}
@Test
public void testGetHostSshPortWithHostNull() {
int hostSshPort = mgr.getHostSshPort(null);
Assert.assertEquals(22, hostSshPort);
}
@Test
public void testGetHostSshPortWithNonKVMHost() {
HostVO host = Mockito.mock(HostVO.class);
Mockito.when(host.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.XenServer);
int hostSshPort = mgr.getHostSshPort(host);
Assert.assertEquals(22, hostSshPort);
}
@Test
public void testGetHostSshPortWithKVMHostDefaultPort() {
HostVO host = Mockito.mock(HostVO.class);
Mockito.when(host.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
Mockito.when(host.getClusterId()).thenReturn(1L);
int hostSshPort = mgr.getHostSshPort(host);
Assert.assertEquals(22, hostSshPort);
}
@Test
public void testGetHostSshPortWithKVMHostCustomPort() {
HostVO host = Mockito.mock(HostVO.class);
Mockito.when(host.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
Mockito.when(host.getDetail(Host.HOST_SSH_PORT)).thenReturn(String.valueOf(3922));
int hostSshPort = mgr.getHostSshPort(host);
Assert.assertEquals(3922, hostSshPort);
}
}

View File

@ -171,7 +171,7 @@ public class ClusterDetailsDaoImpl extends ResourceDetailsDaoBase<ClusterDetails
@Override
public String getConfigValue(long id, String key) {
ClusterDetailsVO vo = findDetail(id, key);
return vo == null ? null : vo.getValue();
return vo == null ? null : getActualValue(vo);
}
@Override

View File

@ -47,7 +47,7 @@ public class DataCenterDetailsDaoImpl extends ResourceDetailsDaoBase<DataCenterD
@Override
public String getConfigValue(long id, String key) {
ResourceDetail vo = findDetail(id, key);
return vo == null ? null : vo.getValue();
return vo == null ? null : getActualValue(vo);
}
@Override

View File

@ -1412,7 +1412,7 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
SearchCriteria<HostVO> sc = TypeStatusStateSearch.create();
sc.setParameters("type", Host.Type.Routing);
sc.setParameters("cluster", clusterId);
List<HostVO> list = listBy(sc, new Filter(1));
List<HostVO> list = listBy(sc, new Filter(1, true));
return list.isEmpty() ? null : list.get(0);
}

View File

@ -383,7 +383,7 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
public VolumeDaoImpl() {
AllFieldsSearch = createSearchBuilder();
AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), Op.EQ);
AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), Op.IN);
AllFieldsSearch.and("accountId", AllFieldsSearch.entity().getAccountId(), Op.EQ);
AllFieldsSearch.and("dcId", AllFieldsSearch.entity().getDataCenterId(), Op.EQ);
AllFieldsSearch.and("pod", AllFieldsSearch.entity().getPodId(), Op.EQ);
@ -581,17 +581,16 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
@Override
public List<VolumeVO> listVolumesToBeDestroyed() {
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
sc.setParameters("state", Volume.State.Destroy);
return listBy(sc);
return listVolumesToBeDestroyed(null);
}
@Override
public List<VolumeVO> listVolumesToBeDestroyed(Date date) {
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
sc.setParameters("state", Volume.State.Destroy);
sc.setParameters("updateTime", date);
sc.setParameters("state", Volume.State.Destroy, Volume.State.Expunging);
if (date != null) {
sc.setParameters("updateTime", date);
}
return listBy(sc);
}

View File

@ -123,8 +123,8 @@ public class UserVO implements User, Identity, InternalIdentity {
}
public UserVO(long id) {
this();
this.id = id;
this.uuid = UUID.randomUUID().toString();
}
public UserVO(long accountId, String username, String password, String firstName, String lastName, String email, String timezone, String uuid, Source source) {

View File

@ -21,13 +21,11 @@ import java.util.List;
import com.cloud.user.Account;
import com.cloud.user.AccountVO;
import com.cloud.user.User;
import com.cloud.utils.Pair;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDao;
public interface AccountDao extends GenericDao<AccountVO, Long> {
Pair<User, Account> findUserAccountByApiKey(String apiKey);
List<AccountVO> findAccountsLike(String accountName);

View File

@ -16,8 +16,6 @@
// under the License.
package com.cloud.user.dao;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Date;
import java.util.List;
@ -27,10 +25,7 @@ import org.springframework.stereotype.Component;
import com.cloud.user.Account;
import com.cloud.user.Account.State;
import com.cloud.user.AccountVO;
import com.cloud.user.User;
import com.cloud.user.UserVO;
import com.cloud.utils.Pair;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
@ -38,13 +33,9 @@ import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Func;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.TransactionLegacy;
@Component
public class AccountDaoImpl extends GenericDaoBase<AccountVO, Long> implements AccountDao {
private static final String FIND_USER_ACCOUNT_BY_API_KEY = "SELECT u.id, u.username, u.account_id, u.secret_key, u.state, u.api_key_access, "
+ "a.id, a.account_name, a.type, a.role_id, a.domain_id, a.state, a.api_key_access " + "FROM `cloud`.`user` u, `cloud`.`account` a "
+ "WHERE u.account_id = a.id AND u.api_key = ? and u.removed IS NULL";
protected final SearchBuilder<AccountVO> AllFieldsSearch;
protected final SearchBuilder<AccountVO> AccountTypeSearch;
@ -132,51 +123,6 @@ public class AccountDaoImpl extends GenericDaoBase<AccountVO, Long> implements A
return listBy(sc);
}
@Override
public Pair<User, Account> findUserAccountByApiKey(String apiKey) {
TransactionLegacy txn = TransactionLegacy.currentTxn();
PreparedStatement pstmt = null;
Pair<User, Account> userAcctPair = null;
try {
String sql = FIND_USER_ACCOUNT_BY_API_KEY;
pstmt = txn.prepareAutoCloseStatement(sql);
pstmt.setString(1, apiKey);
ResultSet rs = pstmt.executeQuery();
// TODO: make sure we don't have more than 1 result? ApiKey had better be unique
if (rs.next()) {
User u = new UserVO(rs.getLong(1));
u.setUsername(rs.getString(2));
u.setAccountId(rs.getLong(3));
u.setSecretKey(DBEncryptionUtil.decrypt(rs.getString(4)));
u.setState(State.getValueOf(rs.getString(5)));
boolean apiKeyAccess = rs.getBoolean(6);
if (rs.wasNull()) {
u.setApiKeyAccess(null);
} else {
u.setApiKeyAccess(apiKeyAccess);
}
AccountVO a = new AccountVO(rs.getLong(7));
a.setAccountName(rs.getString(8));
a.setType(Account.Type.getFromValue(rs.getInt(9)));
a.setRoleId(rs.getLong(10));
a.setDomainId(rs.getLong(11));
a.setState(State.getValueOf(rs.getString(12)));
apiKeyAccess = rs.getBoolean(13);
if (rs.wasNull()) {
a.setApiKeyAccess(null);
} else {
a.setApiKeyAccess(apiKeyAccess);
}
userAcctPair = new Pair<User, Account>(u, a);
}
} catch (Exception e) {
logger.warn("Exception finding user/acct by api key: " + apiKey, e);
}
return userAcctPair;
}
@Override
public List<AccountVO> findAccountsLike(String accountName) {
return findAccountsLike(accountName, null).first();
@ -341,11 +287,9 @@ public class AccountDaoImpl extends GenericDaoBase<AccountVO, Long> implements A
domain_id = account_vo.getDomainId();
}
catch (Exception e) {
logger.warn("getDomainIdForGivenAccountId: Exception :" + e.getMessage());
}
finally {
return domain_id;
logger.warn("Can not get DomainId for the given AccountId; exception message : {}", e.getMessage());
}
return domain_id;
}
@Override

View File

@ -48,6 +48,8 @@ public class UserDetailVO implements ResourceDetail {
public static final String Setup2FADetail = "2FASetupStatus";
public static final String PasswordResetToken = "PasswordResetToken";
public static final String PasswordResetTokenExpiryDate = "PasswordResetTokenExpiryDate";
public static final String PasswordChangeRequired = "PasswordChangeRequired";
public static final String OauthLogin = "OauthLogin";
public UserDetailVO() {
}

View File

@ -202,7 +202,7 @@ public class ImageStoreDaoImpl extends GenericDaoBase<ImageStoreVO, Long> implem
sc.setParameters("dataCenterId", dataCenterId);
sc.setParameters("protocol", protocol);
sc.setParameters("role", DataStoreRole.Image);
Filter filter = new Filter(1);
Filter filter = new Filter(1, true);
List<ImageStoreVO> results = listBy(sc, filter);
return results.size() == 0 ? null : results.get(0);
}

View File

@ -436,6 +436,9 @@ public class VolumeServiceImpl implements VolumeService {
// no need to change state in volumes table
volume.processEventOnly(Event.DestroyRequested);
} else if (volume.getDataStore().getRole() == DataStoreRole.Primary) {
if (vol.getState() == Volume.State.Expunging) {
logger.info("Volume {} is already in Expunging, retrying", volume);
}
volume.processEvent(Event.ExpungeRequested);
}

View File

@ -14,27 +14,25 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.framework.config;
package org.apache.cloudstack.quota.activationrule.presetvariables;
import java.util.function.Consumer;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
public class ValidatedConfigKey<T> extends ConfigKey<T> {
private final Consumer<T> validator;
@RunWith(MockitoJUnitRunner.class)
public class ResourceTest {
@Test
public void toStringTestReturnAJson() {
Resource variable = new Resource();
String expected = ToStringBuilder.reflectionToString(variable, ToStringStyle.JSON_STYLE);
String result = variable.toString();
Assert.assertEquals(expected, result);
public ValidatedConfigKey(String category, Class<T> type, String name, String defaultValue, String description, boolean dynamic, Scope scope, String parent, Consumer<T> validator) {
super(category, type, name, defaultValue, description, dynamic, scope, parent);
this.validator = validator;
}
public Consumer<T> getValidator() {
return validator;
}
public void validateValue(String value) {
if (validator != null) {
validator.accept((T) value);
}
}
}

View File

@ -57,7 +57,18 @@ public class Filter {
}
public Filter(long limit) {
_orderBy = " ORDER BY RAND()";
this(limit, false);
}
/**
* Constructor for creating a filter with random ordering
* @param limit the maximum number of results to return
* @param randomize if true, orders results randomly
*/
public Filter(long limit, boolean randomize) {
if (randomize) {
_orderBy = " ORDER BY RAND()" ;
}
_limit = limit;
}

View File

@ -347,7 +347,7 @@ public abstract class GenericDaoBase<T, ID extends Serializable> extends Compone
@Override
@DB()
public T lockOneRandomRow(final SearchCriteria<T> sc, final boolean exclusive) {
final Filter filter = new Filter(1);
final Filter filter = new Filter(1, true);
final List<T> beans = search(sc, filter, exclusive, true);
return beans.isEmpty() ? null : beans.get(0);
}
@ -927,7 +927,7 @@ public abstract class GenericDaoBase<T, ID extends Serializable> extends Compone
@DB()
protected T findOneIncludingRemovedBy(final SearchCriteria<T> sc) {
Filter filter = new Filter(1);
Filter filter = new Filter(1, true);
List<T> results = searchIncludingRemoved(sc, filter, null, false);
assert results.size() <= 1 : "Didn't the limiting worked?";
return results.size() == 0 ? null : results.get(0);
@ -1335,7 +1335,7 @@ public abstract class GenericDaoBase<T, ID extends Serializable> extends Compone
Filter filter = null;
final long batchSizeFinal = ObjectUtils.defaultIfNull(batchSize, 0L);
if (batchSizeFinal > 0) {
filter = new Filter(null, batchSizeFinal);
filter = new Filter(batchSizeFinal);
}
int expunged = 0;
int currentExpunged = 0;

View File

@ -41,4 +41,62 @@ public class FilterTest {
Assert.assertTrue(filter.getOrderBy().split(",").length == 3);
Assert.assertTrue(filter.getOrderBy().split(",")[2].trim().toLowerCase().equals("test.fld_int asc"));
}
@Test
public void testFilterWithLimitOnly() {
Filter filter = new Filter(5);
Assert.assertEquals(Long.valueOf(5), filter.getLimit());
Assert.assertNull(filter.getOrderBy());
Assert.assertNull(filter.getOffset());
}
@Test
public void testFilterWithLimitAndRandomizeFalse() {
Filter filter = new Filter(10, false);
Assert.assertEquals(Long.valueOf(10), filter.getLimit());
Assert.assertNull(filter.getOrderBy());
Assert.assertNull(filter.getOffset());
}
@Test
public void testFilterWithLimitAndRandomizeTrue() {
Filter filter = new Filter(3, true);
Assert.assertNull(filter.getLimit());
Assert.assertNotNull(filter.getOrderBy());
Assert.assertTrue(filter.getOrderBy().contains("ORDER BY RAND()"));
Assert.assertTrue(filter.getOrderBy().contains("LIMIT 3"));
Assert.assertEquals(" ORDER BY RAND() LIMIT 3", filter.getOrderBy());
}
@Test
public void testFilterRandomizeWithDifferentLimits() {
Filter filter1 = new Filter(1, true);
Filter filter10 = new Filter(10, true);
Filter filter100 = new Filter(100, true);
Assert.assertEquals(" ORDER BY RAND() LIMIT 1", filter1.getOrderBy());
Assert.assertEquals(" ORDER BY RAND() LIMIT 10", filter10.getOrderBy());
Assert.assertEquals(" ORDER BY RAND() LIMIT 100", filter100.getOrderBy());
}
@Test
public void testFilterConstructorBackwardsCompatibility() {
// Test that Filter(long) behaves differently now (no ORDER BY RAND())
// compared to Filter(long, true) which preserves old behavior
Filter simpleLimitFilter = new Filter(1);
Filter randomFilter = new Filter(1, true);
// Simple limit filter should just set limit
Assert.assertEquals(Long.valueOf(1), simpleLimitFilter.getLimit());
Assert.assertNull(simpleLimitFilter.getOrderBy());
// Random filter should set orderBy with RAND()
Assert.assertNull(randomFilter.getLimit());
Assert.assertNotNull(randomFilter.getOrderBy());
Assert.assertTrue(randomFilter.getOrderBy().contains("RAND()"));
}
}

View File

@ -20,6 +20,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Before;
@ -263,4 +264,71 @@ public class GenericDaoBaseTest {
" INNER JOIN tableA tableA2Alias ON tableC.column3=tableA2Alias.column2 " +
" INNER JOIN tableA tableA3Alias ON tableD.column4=tableA3Alias.column3 AND tableD.column5=? ", joinString.toString());
}
@Test
public void testLockOneRandomRowUsesRandomFilter() {
// Create a mock DAO to test lockOneRandomRow behavior
GenericDaoBase<DbTestVO, Long> testDao = Mockito.mock(GenericDaoBase.class);
// Capture the filter passed to the search method
final Filter[] capturedFilter = new Filter[1];
Mockito.when(testDao.lockOneRandomRow(Mockito.any(SearchCriteria.class), Mockito.anyBoolean()))
.thenCallRealMethod();
Mockito.when(testDao.search(Mockito.any(SearchCriteria.class), Mockito.any(Filter.class),
Mockito.anyBoolean(), Mockito.anyBoolean()))
.thenAnswer(invocation -> {
capturedFilter[0] = invocation.getArgument(1);
return new ArrayList<DbTestVO>();
});
SearchCriteria<DbTestVO> sc = Mockito.mock(SearchCriteria.class);
testDao.lockOneRandomRow(sc, true);
// Verify that the filter uses random ordering
Assert.assertNotNull(capturedFilter[0]);
Assert.assertNotNull(capturedFilter[0].getOrderBy());
Assert.assertTrue(capturedFilter[0].getOrderBy().contains("ORDER BY RAND()"));
Assert.assertTrue(capturedFilter[0].getOrderBy().contains("LIMIT 1"));
}
@Test
public void testLockOneRandomRowReturnsNullOnEmptyResult() {
GenericDaoBase<DbTestVO, Long> testDao = Mockito.mock(GenericDaoBase.class);
Mockito.when(testDao.lockOneRandomRow(Mockito.any(SearchCriteria.class), Mockito.anyBoolean()))
.thenCallRealMethod();
Mockito.when(testDao.search(Mockito.any(SearchCriteria.class), Mockito.any(Filter.class),
Mockito.anyBoolean(), Mockito.anyBoolean()))
.thenReturn(new ArrayList<DbTestVO>());
SearchCriteria<DbTestVO> sc = Mockito.mock(SearchCriteria.class);
DbTestVO result = testDao.lockOneRandomRow(sc, true);
Assert.assertNull(result);
}
@Test
public void testLockOneRandomRowReturnsFirstElement() {
GenericDaoBase<DbTestVO, Long> testDao = Mockito.mock(GenericDaoBase.class);
DbTestVO expectedResult = new DbTestVO();
List<DbTestVO> resultList = new ArrayList<>();
resultList.add(expectedResult);
Mockito.when(testDao.lockOneRandomRow(Mockito.any(SearchCriteria.class), Mockito.anyBoolean()))
.thenCallRealMethod();
Mockito.when(testDao.search(Mockito.any(SearchCriteria.class), Mockito.any(Filter.class),
Mockito.anyBoolean(), Mockito.anyBoolean()))
.thenReturn(resultList);
SearchCriteria<DbTestVO> sc = Mockito.mock(SearchCriteria.class);
DbTestVO result = testDao.lockOneRandomRow(sc, true);
Assert.assertNotNull(result);
Assert.assertEquals(expectedResult, result);
}
}

View File

@ -429,7 +429,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
}
injectPresetVariablesIntoJsInterpreter(jsInterpreter, presetVariables);
jsInterpreter.injectVariable("lastTariffs", lastAppliedTariffsList.toString());
jsInterpreter.injectVariable("lastTariffs", lastAppliedTariffsList);
String scriptResult = jsInterpreter.executeScript(activationRule).toString();
@ -459,12 +459,12 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
protected void injectPresetVariablesIntoJsInterpreter(JsInterpreter jsInterpreter, PresetVariables presetVariables) {
jsInterpreter.discardCurrentVariables();
jsInterpreter.injectVariable("account", presetVariables.getAccount().toString());
jsInterpreter.injectVariable("domain", presetVariables.getDomain().toString());
jsInterpreter.injectVariable("account", presetVariables.getAccount());
jsInterpreter.injectVariable("domain", presetVariables.getDomain());
GenericPresetVariable project = presetVariables.getProject();
if (project != null) {
jsInterpreter.injectVariable("project", project.toString());
jsInterpreter.injectVariable("project", project);
}
@ -474,8 +474,8 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
}
jsInterpreter.injectVariable("resourceType", presetVariables.getResourceType());
jsInterpreter.injectVariable("value", presetVariables.getValue().toString());
jsInterpreter.injectVariable("zone", presetVariables.getZone().toString());
jsInterpreter.injectVariable("value", presetVariables.getValue());
jsInterpreter.injectVariable("zone", presetVariables.getZone());
}
/**

View File

@ -36,7 +36,6 @@ public class Account extends GenericPresetVariable {
public void setRole(Role role) {
this.role = role;
fieldNamesToIncludeInToString.add("role");
}
public String getCreated() {
@ -45,6 +44,5 @@ public class Account extends GenericPresetVariable {
public void setCreated(Date created) {
this.created = DateUtil.displayDateInTimezone(TimeZone.getTimeZone("GMT"), created);
fieldNamesToIncludeInToString.add("created");
}
}

View File

@ -29,6 +29,5 @@ public class BackupOffering extends GenericPresetVariable {
public void setExternalId(String externalId) {
this.externalId = externalId;
fieldNamesToIncludeInToString.add("externalId");
}
}

View File

@ -32,7 +32,6 @@ public class ComputeOffering extends GenericPresetVariable {
public void setCustomized(boolean customized) {
this.customized = customized;
fieldNamesToIncludeInToString.add("customized");
}
public boolean offerHa() {
@ -41,7 +40,5 @@ public class ComputeOffering extends GenericPresetVariable {
public void setOfferHa(boolean offerHa) {
this.offerHa = offerHa;
fieldNamesToIncludeInToString.add("offerHa");
}
}

View File

@ -30,6 +30,5 @@ public class Configuration extends GenericPresetVariable{
public void setForceHa(boolean forceHa) {
this.forceHa = forceHa;
fieldNamesToIncludeInToString.add("forceHa");
}
}

View File

@ -61,7 +61,6 @@ public class DiskOfferingPresetVariables extends GenericPresetVariable {
public void setBytesReadRate(Long bytesReadRate) {
this.bytesReadRate = bytesReadRate;
fieldNamesToIncludeInToString.add("bytesReadRate");
}
public Long getBytesReadBurst() {
@ -70,7 +69,6 @@ public class DiskOfferingPresetVariables extends GenericPresetVariable {
public void setBytesReadBurst(Long bytesReadBurst) {
this.bytesReadBurst = bytesReadBurst;
fieldNamesToIncludeInToString.add("bytesReadBurst");
}
public Long getBytesReadBurstLength() {
@ -79,7 +77,6 @@ public class DiskOfferingPresetVariables extends GenericPresetVariable {
public void setBytesReadBurstLength(Long bytesReadBurstLength) {
this.bytesReadBurstLength = bytesReadBurstLength;
fieldNamesToIncludeInToString.add("bytesReadBurstLength");
}
public Long getBytesWriteRate() {
@ -88,7 +85,6 @@ public class DiskOfferingPresetVariables extends GenericPresetVariable {
public void setBytesWriteRate(Long bytesWriteRate) {
this.bytesWriteRate = bytesWriteRate;
fieldNamesToIncludeInToString.add("bytesWriteRate");
}
public Long getBytesWriteBurst() {
@ -97,7 +93,6 @@ public class DiskOfferingPresetVariables extends GenericPresetVariable {
public void setBytesWriteBurst(Long bytesWriteBurst) {
this.bytesWriteBurst = bytesWriteBurst;
fieldNamesToIncludeInToString.add("bytesWriteBurst");
}
public Long getBytesWriteBurstLength() {
@ -106,7 +101,6 @@ public class DiskOfferingPresetVariables extends GenericPresetVariable {
public void setBytesWriteBurstLength(Long bytesWriteBurstLength) {
this.bytesWriteBurstLength = bytesWriteBurstLength;
fieldNamesToIncludeInToString.add("bytesWriteBurstLength");
}
public Long getIopsReadRate() {
@ -115,7 +109,6 @@ public class DiskOfferingPresetVariables extends GenericPresetVariable {
public void setIopsReadRate(Long iopsReadRate) {
this.iopsReadRate = iopsReadRate;
fieldNamesToIncludeInToString.add("iopsReadRate");
}
public Long getIopsReadBurst() {
@ -124,7 +117,6 @@ public class DiskOfferingPresetVariables extends GenericPresetVariable {
public void setIopsReadBurst(Long iopsReadBurst) {
this.iopsReadBurst = iopsReadBurst;
fieldNamesToIncludeInToString.add("iopsReadBurst");
}
public Long getIopsReadBurstLength() {
@ -133,7 +125,6 @@ public class DiskOfferingPresetVariables extends GenericPresetVariable {
public void setIopsReadBurstLength(Long iopsReadBurstLength) {
this.iopsReadBurstLength = iopsReadBurstLength;
fieldNamesToIncludeInToString.add("iopsReadBurstLength");
}
public Long getIopsWriteRate() {
@ -142,7 +133,6 @@ public class DiskOfferingPresetVariables extends GenericPresetVariable {
public void setIopsWriteRate(Long iopsWriteRate) {
this.iopsWriteRate = iopsWriteRate;
fieldNamesToIncludeInToString.add("iopsWriteRate");
}
public Long getIopsWriteBurst() {
@ -151,7 +141,6 @@ public class DiskOfferingPresetVariables extends GenericPresetVariable {
public void setIopsWriteBurst(Long iopsWriteBurst) {
this.iopsWriteBurst = iopsWriteBurst;
fieldNamesToIncludeInToString.add("iopsWriteBurst");
}
public Long getIopsWriteBurstLength() {
@ -160,6 +149,5 @@ public class DiskOfferingPresetVariables extends GenericPresetVariable {
public void setIopsWriteBurstLength(Long iopsWriteBurstLength) {
this.iopsWriteBurstLength = iopsWriteBurstLength;
fieldNamesToIncludeInToString.add("iopsWriteBurstLength");
}
}

View File

@ -27,7 +27,6 @@ public class Domain extends GenericPresetVariable {
public void setPath(String path) {
this.path = path;
fieldNamesToIncludeInToString.add("path");
}
}

View File

@ -17,10 +17,8 @@
package org.apache.cloudstack.quota.activationrule.presetvariables;
import java.util.HashSet;
import java.util.Set;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
public class GenericPresetVariable {
@PresetVariableDefinition(description = "ID of the resource.")
@ -29,15 +27,12 @@ public class GenericPresetVariable {
@PresetVariableDefinition(description = "Name of the resource.")
private String name;
protected transient Set<String> fieldNamesToIncludeInToString = new HashSet<>();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
fieldNamesToIncludeInToString.add("id");
}
public String getName() {
@ -46,15 +41,10 @@ public class GenericPresetVariable {
public void setName(String name) {
this.name = name;
fieldNamesToIncludeInToString.add("name");
}
/***
* Converts the preset variable into a valid JSON object that will be injected into the JS interpreter.
* This method should not be overridden or changed.
*/
@Override
public final String toString() {
return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, fieldNamesToIncludeInToString.toArray(new String[0]));
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
}
}

View File

@ -32,7 +32,6 @@ public class Host extends GenericPresetVariable {
public void setTags(List<String> tags) {
this.tags = tags;
fieldNamesToIncludeInToString.add("tags");
}
public Boolean getIsTagARule() {
@ -41,6 +40,5 @@ public class Host extends GenericPresetVariable {
public void setIsTagARule(Boolean isTagARule) {
this.isTagARule = isTagARule;
fieldNamesToIncludeInToString.add("isTagARule");
}
}

View File

@ -254,7 +254,7 @@ public class PresetVariableHelper {
Role role = new Role();
role.setId(roleVo.getUuid());
role.setName(roleVo.getName());
role.setType(roleVo.getRoleType());
role.setType(roleVo.getRoleType().toString());
return role;
}
@ -538,8 +538,8 @@ public class PresetVariableHelper {
value.setDiskOffering(getPresetVariableValueDiskOffering(volumeVo.getDiskOfferingId()));
value.setId(volumeVo.getUuid());
value.setName(volumeVo.getName());
value.setProvisioningType(volumeVo.getProvisioningType());
value.setVolumeType(volumeVo.getVolumeType());
value.setVolumeType(volumeVo.getVolumeType().toString());
value.setProvisioningType(volumeVo.getProvisioningType().toString());
Long poolId = volumeVo.getPoolId();
if (poolId == null) {
@ -594,7 +594,7 @@ public class PresetVariableHelper {
storage = new Storage();
storage.setId(storagePoolVo.getUuid());
storage.setName(storagePoolVo.getName());
storage.setScope(storagePoolVo.getScope());
storage.setScope(storagePoolVo.getScope().toString());
List<StoragePoolTagVO> storagePoolTagVOList = storagePoolTagsDao.findStoragePoolTags(storageId);
List<String> storageTags = new ArrayList<>();
boolean isTagARule = false;
@ -663,7 +663,7 @@ public class PresetVariableHelper {
value.setId(snapshotVo.getUuid());
value.setName(snapshotVo.getName());
value.setSize(ByteScaleUtils.bytesToMebibytes(snapshotVo.getSize()));
value.setSnapshotType(Snapshot.Type.values()[snapshotVo.getSnapshotType()]);
value.setSnapshotType(Snapshot.Type.values()[snapshotVo.getSnapshotType()].toString());
value.setStorage(getPresetVariableValueStorage(getSnapshotDataStoreId(snapshotId, usageRecord.getZoneId()), usageType));
value.setTags(getPresetVariableValueResourceTags(snapshotId, ResourceObjectType.Snapshot));
Hypervisor.HypervisorType hypervisorType = snapshotVo.getHypervisorType();
@ -732,7 +732,7 @@ public class PresetVariableHelper {
value.setId(vmSnapshotVo.getUuid());
value.setName(vmSnapshotVo.getName());
value.setTags(getPresetVariableValueResourceTags(vmSnapshotId, ResourceObjectType.VMSnapshot));
value.setVmSnapshotType(vmSnapshotVo.getType());
value.setVmSnapshotType(vmSnapshotVo.getType().toString());
VMInstanceVO vmVo = vmInstanceDao.findByIdIncludingRemoved(vmSnapshotVo.getVmId());
if (vmVo != null && vmVo.getHypervisorType() != null) {

View File

@ -17,19 +17,16 @@
package org.apache.cloudstack.quota.activationrule.presetvariables;
import org.apache.cloudstack.acl.RoleType;
public class Role extends GenericPresetVariable {
@PresetVariableDefinition(description = "Role type of the resource's owner.")
private RoleType type;
private String type;
public RoleType getType() {
public String getType() {
return type;
}
public void setType(RoleType type) {
public void setType(String type) {
this.type = type;
fieldNamesToIncludeInToString.add("type");
}
}

View File

@ -19,8 +19,6 @@ package org.apache.cloudstack.quota.activationrule.presetvariables;
import java.util.List;
import com.cloud.storage.ScopeType;
public class Storage extends GenericPresetVariable {
@PresetVariableDefinition(description = "List of string representing the tags of the storage where the volume is (i.e.: [\"a\", \"b\"]).")
private List<String> tags;
@ -29,7 +27,7 @@ public class Storage extends GenericPresetVariable {
private Boolean isTagARule;
@PresetVariableDefinition(description = "Scope of the storage where the volume is. Values can be: ZONE, CLUSTER or HOST. Applicable only for primary storages.")
private ScopeType scope;
private String scope;
public List<String> getTags() {
return tags;
@ -37,7 +35,6 @@ public class Storage extends GenericPresetVariable {
public void setTags(List<String> tags) {
this.tags = tags;
fieldNamesToIncludeInToString.add("tags");
}
public Boolean getIsTagARule() {
@ -46,16 +43,14 @@ public class Storage extends GenericPresetVariable {
public void setIsTagARule(Boolean isTagARule) {
this.isTagARule = isTagARule;
fieldNamesToIncludeInToString.add("isTagARule");
}
public ScopeType getScope() {
public String getScope() {
return scope;
}
public void setScope(ScopeType scope) {
public void setScope(String scope) {
this.scope = scope;
fieldNamesToIncludeInToString.add("scope");
}
}

View File

@ -28,6 +28,5 @@ public class Tariff extends GenericPresetVariable {
public void setValue(BigDecimal value) {
this.value = value;
fieldNamesToIncludeInToString.add("value");
}
}

View File

@ -20,10 +20,6 @@ package org.apache.cloudstack.quota.activationrule.presetvariables;
import java.util.List;
import java.util.Map;
import com.cloud.storage.Snapshot;
import com.cloud.storage.Storage.ProvisioningType;
import com.cloud.storage.Volume;
import com.cloud.vm.snapshot.VMSnapshot;
import org.apache.cloudstack.quota.constant.QuotaTypes;
public class Value extends GenericPresetVariable {
@ -61,13 +57,13 @@ public class Value extends GenericPresetVariable {
private Long virtualSize;
@PresetVariableDefinition(description = "Provisioning type of the resource. Values can be: thin, sparse or fat.", supportedTypes = {QuotaTypes.VOLUME})
private ProvisioningType provisioningType;
private String provisioningType;
@PresetVariableDefinition(description = "Type of the snapshot. Values can be: MANUAL, RECURRING, HOURLY, DAILY, WEEKLY and MONTHLY.", supportedTypes = {QuotaTypes.SNAPSHOT})
private Snapshot.Type snapshotType;
private String snapshotType;
@PresetVariableDefinition(description = "Type of the VM snapshot. Values can be: Disk or DiskAndMemory.", supportedTypes = {QuotaTypes.VM_SNAPSHOT})
private VMSnapshot.Type vmSnapshotType;
private String vmSnapshotType;
@PresetVariableDefinition(description = "Computing offering of the VM.", supportedTypes = {QuotaTypes.RUNNING_VM, QuotaTypes.ALLOCATED_VM})
private ComputeOffering computeOffering;
@ -96,7 +92,7 @@ public class Value extends GenericPresetVariable {
private String volumeFormat;
@PresetVariableDefinition(description = "The volume type. Values can be: UNKNOWN, ROOT, SWAP, DATADISK and ISO.", supportedTypes = {QuotaTypes.VOLUME})
private Volume.Type volumeType;
private String volumeType;
private String state;
@ -106,7 +102,6 @@ public class Value extends GenericPresetVariable {
public void setHost(Host host) {
this.host = host;
fieldNamesToIncludeInToString.add("host");
}
public String getOsName() {
@ -115,7 +110,6 @@ public class Value extends GenericPresetVariable {
public void setOsName(String osName) {
this.osName = osName;
fieldNamesToIncludeInToString.add("osName");
}
public List<Resource> getAccountResources() {
@ -124,7 +118,6 @@ public class Value extends GenericPresetVariable {
public void setAccountResources(List<Resource> accountResources) {
this.accountResources = accountResources;
fieldNamesToIncludeInToString.add("accountResources");
}
public Map<String, String> getTags() {
@ -133,7 +126,6 @@ public class Value extends GenericPresetVariable {
public void setTags(Map<String, String> tags) {
this.tags = tags;
fieldNamesToIncludeInToString.add("tags");
}
public String getTag() {
@ -142,7 +134,6 @@ public class Value extends GenericPresetVariable {
public void setTag(String tag) {
this.tag = tag;
fieldNamesToIncludeInToString.add("tag");
}
public Long getSize() {
@ -151,34 +142,30 @@ public class Value extends GenericPresetVariable {
public void setSize(Long size) {
this.size = size;
fieldNamesToIncludeInToString.add("size");
}
public ProvisioningType getProvisioningType() {
public String getProvisioningType() {
return provisioningType;
}
public void setProvisioningType(ProvisioningType provisioningType) {
public void setProvisioningType(String provisioningType) {
this.provisioningType = provisioningType;
fieldNamesToIncludeInToString.add("provisioningType");
}
public Snapshot.Type getSnapshotType() {
public String getSnapshotType() {
return snapshotType;
}
public void setSnapshotType(Snapshot.Type snapshotType) {
public void setSnapshotType(String snapshotType) {
this.snapshotType = snapshotType;
fieldNamesToIncludeInToString.add("snapshotType");
}
public VMSnapshot.Type getVmSnapshotType() {
public String getVmSnapshotType() {
return vmSnapshotType;
}
public void setVmSnapshotType(VMSnapshot.Type vmSnapshotType) {
public void setVmSnapshotType(String vmSnapshotType) {
this.vmSnapshotType = vmSnapshotType;
fieldNamesToIncludeInToString.add("vmSnapshotType");
}
public ComputeOffering getComputeOffering() {
@ -187,7 +174,6 @@ public class Value extends GenericPresetVariable {
public void setComputeOffering(ComputeOffering computeOffering) {
this.computeOffering = computeOffering;
fieldNamesToIncludeInToString.add("computeOffering");
}
public GenericPresetVariable getTemplate() {
@ -196,7 +182,6 @@ public class Value extends GenericPresetVariable {
public void setTemplate(GenericPresetVariable template) {
this.template = template;
fieldNamesToIncludeInToString.add("template");
}
public DiskOfferingPresetVariables getDiskOffering() {
@ -205,7 +190,6 @@ public class Value extends GenericPresetVariable {
public void setDiskOffering(DiskOfferingPresetVariables diskOffering) {
this.diskOffering = diskOffering;
fieldNamesToIncludeInToString.add("diskOffering");
}
public Storage getStorage() {
@ -214,7 +198,6 @@ public class Value extends GenericPresetVariable {
public void setStorage(Storage storage) {
this.storage = storage;
fieldNamesToIncludeInToString.add("storage");
}
public ComputingResources getComputingResources() {
@ -223,7 +206,6 @@ public class Value extends GenericPresetVariable {
public void setComputingResources(ComputingResources computingResources) {
this.computingResources = computingResources;
fieldNamesToIncludeInToString.add("computingResources");
}
public Long getVirtualSize() {
@ -232,7 +214,6 @@ public class Value extends GenericPresetVariable {
public void setVirtualSize(Long virtualSize) {
this.virtualSize = virtualSize;
fieldNamesToIncludeInToString.add("virtualSize");
}
public BackupOffering getBackupOffering() {
@ -241,12 +222,10 @@ public class Value extends GenericPresetVariable {
public void setBackupOffering(BackupOffering backupOffering) {
this.backupOffering = backupOffering;
fieldNamesToIncludeInToString.add("backupOffering");
}
public void setHypervisorType(String hypervisorType) {
this.hypervisorType = hypervisorType;
fieldNamesToIncludeInToString.add("hypervisorType");
}
public String getHypervisorType() {
@ -255,20 +234,18 @@ public class Value extends GenericPresetVariable {
public void setVolumeFormat(String volumeFormat) {
this.volumeFormat = volumeFormat;
fieldNamesToIncludeInToString.add("volumeFormat");
}
public String getVolumeFormat() {
return volumeFormat;
}
public Volume.Type getVolumeType() {
public String getVolumeType() {
return volumeType;
}
public void setVolumeType(Volume.Type volumeType) {
public void setVolumeType(String volumeType) {
this.volumeType = volumeType;
fieldNamesToIncludeInToString.add("volumeType");
}
public String getState() {
@ -277,6 +254,5 @@ public class Value extends GenericPresetVariable {
public void setState(String state) {
this.state = state;
fieldNamesToIncludeInToString.add("state");
}
}

View File

@ -267,12 +267,12 @@ public class QuotaManagerImplTest {
quotaManagerImplSpy.injectPresetVariablesIntoJsInterpreter(jsInterpreterMock, presetVariablesMock);
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("account"), Mockito.anyString());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("domain"), Mockito.anyString());
Mockito.verify(jsInterpreterMock, Mockito.never()).injectVariable(Mockito.eq("project"), Mockito.anyString());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("resourceType"), Mockito.anyString());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("value"), Mockito.anyString());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("zone"), Mockito.anyString());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("account"), Mockito.any());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("domain"), Mockito.any());
Mockito.verify(jsInterpreterMock, Mockito.never()).injectVariable(Mockito.eq("project"), Mockito.any());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("resourceType"), Mockito.any());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("value"), Mockito.any());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("zone"), Mockito.any());
}
@Test
@ -288,12 +288,12 @@ public class QuotaManagerImplTest {
quotaManagerImplSpy.injectPresetVariablesIntoJsInterpreter(jsInterpreterMock, presetVariablesMock);
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("account"), Mockito.anyString());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("domain"), Mockito.anyString());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("project"), Mockito.anyString());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("resourceType"), Mockito.anyString());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("value"), Mockito.anyString());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("zone"), Mockito.anyString());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("account"), Mockito.any());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("domain"), Mockito.any());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("project"), Mockito.any());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("resourceType"), Mockito.any());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("value"), Mockito.any());
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("zone"), Mockito.any());
}
@Test

View File

@ -1,34 +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.
package org.apache.cloudstack.quota.activationrule.presetvariables;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class AccountTest {
@Test
public void setRoleTestAddFieldRoleToCollection() {
Account variable = new Account();
variable.setRole(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("role"));
}
}

View File

@ -1,36 +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.
*/
package org.apache.cloudstack.quota.activationrule.presetvariables;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class BackupOfferingTest {
@Test
public void setExternalIdTestAddFieldExternalIdToCollection() {
BackupOffering backupOffering = new BackupOffering();
backupOffering.setExternalId("any-external-id");
Assert.assertTrue(backupOffering.fieldNamesToIncludeInToString.contains("externalId"));
}
}

View File

@ -1,35 +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.
package org.apache.cloudstack.quota.activationrule.presetvariables;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ComputeOfferingTest {
@Test
public void setCustomizedTestAddFieldCustomizedToCollection() {
ComputeOffering variable = new ComputeOffering();
variable.setCustomized(true);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("customized"));
}
}

View File

@ -1,40 +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.
package org.apache.cloudstack.quota.activationrule.presetvariables;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ComputingResourcesTest {
@Test
public void toStringTestReturnAJson() {
ComputingResources variable = new ComputingResources();
String expected = ToStringBuilder.reflectionToString(variable, ToStringStyle.JSON_STYLE);
String result = variable.toString();
Assert.assertEquals(expected, result);
}
}

View File

@ -1,35 +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.
package org.apache.cloudstack.quota.activationrule.presetvariables;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class DomainTest {
@Test
public void setPathTestAddFieldPathToCollection() {
Domain variable = new Domain();
variable.setPath("test path");
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("path"));
}
}

View File

@ -1,73 +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.
package org.apache.cloudstack.quota.activationrule.presetvariables;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class GenericPresetVariableTest {
@Test
public void setIdTestAddFieldIdToCollection() {
GenericPresetVariable variable = new GenericPresetVariable();
variable.setId("test");
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("id"));
}
@Test
public void setNameTestAddFieldNameToCollection() {
GenericPresetVariable variable = new GenericPresetVariable();
variable.setName("test");
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("name"));
}
@Test
public void toStringTestSetAllFieldsAndReturnAJson() {
GenericPresetVariable variable = new GenericPresetVariable();
variable.setId("test id");
variable.setName("test name");
String expected = ReflectionToStringBuilderUtils.reflectOnlySelectedFields(variable, "id", "name");
String result = variable.toString();
Assert.assertEquals(expected, result);
}
@Test
public void toStringTestSetSomeFieldsAndReturnAJson() {
GenericPresetVariable variable = new GenericPresetVariable();
variable.setId("test id");
String expected = ReflectionToStringBuilderUtils.reflectOnlySelectedFields(variable, "id");
String result = variable.toString();
Assert.assertEquals(expected, result);
variable = new GenericPresetVariable();
variable.setName("test name");
expected = ReflectionToStringBuilderUtils.reflectOnlySelectedFields(variable, "name");
result = variable.toString();
Assert.assertEquals(expected, result);
}
}

View File

@ -1,34 +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.
package org.apache.cloudstack.quota.activationrule.presetvariables;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class HostTest {
@Test
public void setTagsTestAddFieldTagsToCollection() {
Host variable = new Host();
variable.setTags(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("tags"));
}
}

View File

@ -215,14 +215,14 @@ public class PresetVariableHelperTest {
value.setTags(Collections.singletonMap("tag1", "value1"));
value.setTemplate(getGenericPresetVariableForTests());
value.setDiskOffering(getDiskOfferingForTests());
value.setProvisioningType(ProvisioningType.THIN);
value.setProvisioningType(ProvisioningType.THIN.toString());
value.setStorage(getStorageForTests());
value.setSize(ByteScaleUtils.GiB);
value.setSnapshotType(Snapshot.Type.HOURLY);
value.setSnapshotType(Snapshot.Type.HOURLY.toString());
value.setTag("tag_test");
value.setVmSnapshotType(VMSnapshot.Type.Disk);
value.setVmSnapshotType(VMSnapshot.Type.Disk.toString());
value.setComputingResources(getComputingResourcesForTests());
value.setVolumeType(Volume.Type.DATADISK);
value.setVolumeType(Volume.Type.DATADISK.toString());
return value;
}
@ -272,7 +272,7 @@ public class PresetVariableHelperTest {
storage.setId("storage_id");
storage.setName("storage_name");
storage.setTags(Arrays.asList("tag1", "tag2"));
storage.setScope(ScopeType.ZONE);
storage.setScope(ScopeType.ZONE.toString());
return storage;
}
@ -298,9 +298,9 @@ public class PresetVariableHelperTest {
private List<VMInstanceDetailVO> getVmDetailsForTests() {
List<VMInstanceDetailVO> details = new LinkedList<>();
details.add(new VMInstanceDetailVO(1l, "test_with_value", "277", false));
details.add(new VMInstanceDetailVO(1l, "test_with_invalid_value", "invalid", false));
details.add(new VMInstanceDetailVO(1l, "test_with_null", null, false));
details.add(new VMInstanceDetailVO(1L, "test_with_value", "277", false));
details.add(new VMInstanceDetailVO(1L, "test_with_invalid_value", "invalid", false));
details.add(new VMInstanceDetailVO(1L, "test_with_null", null, false));
return details;
}
@ -309,13 +309,6 @@ public class PresetVariableHelperTest {
Assert.assertEquals(expected.getName(), result.getName());
}
private void validateFieldNamesToIncludeInToString(List<String> expected, GenericPresetVariable resultObject) {
List<String> result = new ArrayList<>(resultObject.fieldNamesToIncludeInToString);
Collections.sort(expected);
Collections.sort(result);
Assert.assertEquals(expected, result);
}
private BackupOffering getBackupOfferingForTests() {
BackupOffering backupOffering = new BackupOffering();
backupOffering.setId("backup_offering_id");
@ -415,7 +408,6 @@ public class PresetVariableHelperTest {
Assert.assertNotNull(result.getProject());
assertPresetVariableIdAndName(account, result.getProject());
validateFieldNamesToIncludeInToString(Arrays.asList("id", "name"), result.getProject());
}
@Test
@ -430,10 +422,9 @@ public class PresetVariableHelperTest {
Mockito.doReturn(account.getName()).when(accountVoMock).getName();
Mockito.doReturn(account.getCreated()).when(accountVoMock).getCreated();
Account result = presetVariableHelperSpy.getPresetVariableAccount(1l);
Account result = presetVariableHelperSpy.getPresetVariableAccount(1L);
assertPresetVariableIdAndName(account, result);
validateFieldNamesToIncludeInToString(Arrays.asList("created", "id", "name"), result);
}
@Test
@ -463,18 +454,16 @@ public class PresetVariableHelperTest {
Role role = new Role();
role.setId("test_id");
role.setName("test_name");
role.setType(roleType);
role.setType(roleType.toString());
Mockito.doReturn(role.getId()).when(roleVoMock).getUuid();
Mockito.doReturn(role.getName()).when(roleVoMock).getName();
Mockito.doReturn(role.getType()).when(roleVoMock).getRoleType();
Mockito.doReturn(RoleType.fromString(role.getType())).when(roleVoMock).getRoleType();
Role result = presetVariableHelperSpy.getPresetVariableRole(1l);
Role result = presetVariableHelperSpy.getPresetVariableRole(1L);
assertPresetVariableIdAndName(role, result);
Assert.assertEquals(role.getType(), result.getType());
validateFieldNamesToIncludeInToString(Arrays.asList("id", "name", "type"), result);
});
}
@ -489,12 +478,10 @@ public class PresetVariableHelperTest {
Mockito.doReturn(domain.getName()).when(domainVoMock).getName();
Mockito.doReturn(domain.getPath()).when(domainVoMock).getPath();
Domain result = presetVariableHelperSpy.getPresetVariableDomain(1l);
Domain result = presetVariableHelperSpy.getPresetVariableDomain(1L);
assertPresetVariableIdAndName(domain, result);
Assert.assertEquals(domain.getPath(), result.getPath());
validateFieldNamesToIncludeInToString(Arrays.asList("id", "name", "path"), result);
}
@Test
@ -507,10 +494,9 @@ public class PresetVariableHelperTest {
Mockito.doReturn(expected.getId()).when(dataCenterVoMock).getUuid();
Mockito.doReturn(expected.getName()).when(dataCenterVoMock).getName();
GenericPresetVariable result = presetVariableHelperSpy.getPresetVariableZone(1l);
GenericPresetVariable result = presetVariableHelperSpy.getPresetVariableZone(1L);
assertPresetVariableIdAndName(expected, result);
validateFieldNamesToIncludeInToString(Arrays.asList("id", "name"), result);
}
@Test
@ -531,7 +517,6 @@ public class PresetVariableHelperTest {
Value result = presetVariableHelperSpy.getPresetVariableValue(usageVoMock);
Assert.assertEquals(resources, result.getAccountResources());
validateFieldNamesToIncludeInToString(Arrays.asList("accountResources"), result);
}
@Test
@ -541,7 +526,7 @@ public class PresetVariableHelperTest {
Mockito.doReturn(new Date()).when(usageVoMock).getEndDate();
Mockito.doReturn(expected).when(usageDaoMock).listAccountResourcesInThePeriod(Mockito.anyLong(), Mockito.anyInt(), Mockito.any(Date.class), Mockito.any(Date.class));
List<Resource> result = presetVariableHelperSpy.getPresetVariableAccountResources(usageVoMock, 1l, 0);
List<Resource> result = presetVariableHelperSpy.getPresetVariableAccountResources(usageVoMock, 1L, 0);
for (int i = 0; i < expected.size(); i++) {
Assert.assertEquals(expected.get(i).first(), result.get(i).getZoneId());
@ -590,8 +575,6 @@ public class PresetVariableHelperTest {
Assert.assertEquals(expected.getTags(), result.getTags());
Assert.assertEquals(expected.getTemplate(), result.getTemplate());
Assert.assertEquals(hypervisorType.name(), result.getHypervisorType());
validateFieldNamesToIncludeInToString(Arrays.asList("id", "name", "osName", "tags", "template", "hypervisorType"), result);
});
}
@ -614,7 +597,6 @@ public class PresetVariableHelperTest {
public void setPresetVariableHostInValueIfUsageTypeIsRunningVmTestQuotaTypeIsRunningVmSetHost() {
Value result = new Value();
Host expectedHost = getHostForTests();
List<HostTagVO> expectedHostTags = getHostTagsForTests();
Mockito.doReturn(expectedHost).when(presetVariableHelperSpy).getPresetVariableValueHost(Mockito.anyLong());
presetVariableHelperSpy.setPresetVariableHostInValueIfUsageTypeIsRunningVm(result, UsageTypes.RUNNING_VM, vmInstanceVoMock);
@ -623,7 +605,6 @@ public class PresetVariableHelperTest {
assertPresetVariableIdAndName(expectedHost, result.getHost());
Assert.assertEquals(expectedHost.getTags(), result.getHost().getTags());
validateFieldNamesToIncludeInToString(Arrays.asList("host"), result);
}
@Test
@ -638,11 +619,10 @@ public class PresetVariableHelperTest {
Mockito.doReturn(expected.getName()).when(hostVoMock).getName();
Mockito.doReturn(hostTagVOListMock).when(hostTagsDaoMock).getHostTags(Mockito.anyLong());
Host result = presetVariableHelperSpy.getPresetVariableValueHost(1l);
Host result = presetVariableHelperSpy.getPresetVariableValueHost(1L);
assertPresetVariableIdAndName(expected, result);
Assert.assertEquals(expected.getTags(), result.getTags());
validateFieldNamesToIncludeInToString(Arrays.asList("id", "isTagARule", "name", "tags"), result);
}
@Test
@ -657,12 +637,11 @@ public class PresetVariableHelperTest {
Mockito.doReturn(expected.getName()).when(hostVoMock).getName();
Mockito.doReturn(hostTagVOListMock).when(hostTagsDaoMock).getHostTags(Mockito.anyLong());
Host result = presetVariableHelperSpy.getPresetVariableValueHost(1l);
Host result = presetVariableHelperSpy.getPresetVariableValueHost(1L);
assertPresetVariableIdAndName(expected, result);
Assert.assertEquals(new ArrayList<>(), result.getTags());
Assert.assertTrue(result.getIsTagARule());
validateFieldNamesToIncludeInToString(Arrays.asList("id", "isTagARule", "name", "tags"), result);
}
@Test
@ -674,7 +653,7 @@ public class PresetVariableHelperTest {
String expected = "os_display_name";
Mockito.doReturn(expected).when(guestOsVoMock).getDisplayName();
String result = presetVariableHelperSpy.getPresetVariableValueOsName(1l);
String result = presetVariableHelperSpy.getPresetVariableValueOsName(1L);
Assert.assertEquals(expected, result);
}
@ -692,7 +671,6 @@ public class PresetVariableHelperTest {
assertPresetVariableIdAndName(expected, result);
Assert.assertEquals(expected.isCustomized(), result.isCustomized());
Assert.assertEquals(expected.offerHa(), result.offerHa());
validateFieldNamesToIncludeInToString(Arrays.asList("id", "name", "customized", "offerHa"), result);
}
@Test
@ -706,10 +684,8 @@ public class PresetVariableHelperTest {
assertPresetVariableIdAndName(expected, result);
Assert.assertEquals(expected.isCustomized(), result.isCustomized());
validateFieldNamesToIncludeInToString(Arrays.asList("id", "name", "customized"), result);
}
@Test
public void getPresetVariableValueTemplateTestSetValuesAndReturnObject() {
VMTemplateVO vmTemplateVoMock = Mockito.mock(VMTemplateVO.class);
@ -720,10 +696,9 @@ public class PresetVariableHelperTest {
Mockito.doReturn(expected.getId()).when(vmTemplateVoMock).getUuid();
Mockito.doReturn(expected.getName()).when(vmTemplateVoMock).getName();
GenericPresetVariable result = presetVariableHelperSpy.getPresetVariableValueTemplate(1l);
GenericPresetVariable result = presetVariableHelperSpy.getPresetVariableValueTemplate(1L);
assertPresetVariableIdAndName(expected, result);
validateFieldNamesToIncludeInToString(Arrays.asList("id", "name"), result);
}
@Test
@ -735,7 +710,7 @@ public class PresetVariableHelperTest {
Mockito.doReturn(listExpected).when(resourceTagDaoMock).listBy(Mockito.anyLong(), Mockito.any(ResourceObjectType.class));
Arrays.asList(ResourceObjectType.values()).forEach(type -> {
Map<String, String> result = presetVariableHelperSpy.getPresetVariableValueResourceTags(1l, type);
Map<String, String> result = presetVariableHelperSpy.getPresetVariableValueResourceTags(1L, type);
for (ResourceTag expected: listExpected) {
Assert.assertEquals(expected.getValue(), result.get(expected.getKey()));
@ -760,15 +735,15 @@ public class PresetVariableHelperTest {
VolumeVO volumeVoMock = Mockito.mock(VolumeVO.class);
Mockito.doReturn(volumeVoMock).when(volumeDaoMock).findByIdIncludingRemoved(Mockito.anyLong());
Mockito.doReturn(1l).when(volumeVoMock).getPoolId();
Mockito.doReturn(1L).when(volumeVoMock).getPoolId();
mockMethodValidateIfObjectIsNull();
Mockito.doReturn(expected.getId()).when(volumeVoMock).getUuid();
Mockito.doReturn(expected.getName()).when(volumeVoMock).getName();
Mockito.doReturn(expected.getDiskOffering()).when(presetVariableHelperSpy).getPresetVariableValueDiskOffering(Mockito.anyLong());
Mockito.doReturn(expected.getProvisioningType()).when(volumeVoMock).getProvisioningType();
Mockito.doReturn(expected.getVolumeType()).when(volumeVoMock).getVolumeType();
Mockito.doReturn(ProvisioningType.getProvisioningType(expected.getProvisioningType())).when(volumeVoMock).getProvisioningType();
Mockito.doReturn(Volume.Type.valueOf(expected.getVolumeType())).when(volumeVoMock).getVolumeType();
Mockito.doReturn(expected.getStorage()).when(presetVariableHelperSpy).getPresetVariableValueStorage(Mockito.anyLong(), Mockito.anyInt());
Mockito.doReturn(expected.getTags()).when(presetVariableHelperSpy).getPresetVariableValueResourceTags(Mockito.anyLong(), Mockito.any(ResourceObjectType.class));
Mockito.doReturn(expected.getSize()).when(volumeVoMock).getSize();
@ -789,8 +764,6 @@ public class PresetVariableHelperTest {
Assert.assertEquals(expected.getTags(), result.getTags());
Assert.assertEquals(expectedSize, result.getSize());
Assert.assertEquals(imageFormat.name(), result.getVolumeFormat());
validateFieldNamesToIncludeInToString(Arrays.asList("id", "name", "diskOffering", "provisioningType", "volumeType", "storage", "tags", "size", "volumeFormat"), result);
}
Mockito.verify(presetVariableHelperSpy, Mockito.times(ImageFormat.values().length)).getPresetVariableValueResourceTags(Mockito.anyLong(),
@ -811,8 +784,8 @@ public class PresetVariableHelperTest {
Mockito.doReturn(expected.getId()).when(volumeVoMock).getUuid();
Mockito.doReturn(expected.getName()).when(volumeVoMock).getName();
Mockito.doReturn(expected.getDiskOffering()).when(presetVariableHelperSpy).getPresetVariableValueDiskOffering(Mockito.anyLong());
Mockito.doReturn(expected.getProvisioningType()).when(volumeVoMock).getProvisioningType();
Mockito.doReturn(expected.getVolumeType()).when(volumeVoMock).getVolumeType();
Mockito.doReturn(Volume.Type.valueOf(expected.getVolumeType())).when(volumeVoMock).getVolumeType();
Mockito.doReturn(ProvisioningType.getProvisioningType(expected.getProvisioningType())).when(volumeVoMock).getProvisioningType();
Mockito.doReturn(expected.getTags()).when(presetVariableHelperSpy).getPresetVariableValueResourceTags(Mockito.anyLong(), Mockito.any(ResourceObjectType.class));
Mockito.doReturn(expected.getSize()).when(volumeVoMock).getSize();
Mockito.doReturn(imageFormat).when(volumeVoMock).getFormat();
@ -832,8 +805,6 @@ public class PresetVariableHelperTest {
Assert.assertEquals(expected.getTags(), result.getTags());
Assert.assertEquals(expectedSize, result.getSize());
Assert.assertEquals(imageFormat.name(), result.getVolumeFormat());
validateFieldNamesToIncludeInToString(Arrays.asList("id", "name", "diskOffering", "provisioningType", "volumeType", "tags", "size", "volumeFormat"), result);
}
Mockito.verify(presetVariableHelperSpy, Mockito.times(ImageFormat.values().length)).getPresetVariableValueResourceTags(Mockito.anyLong(),
@ -850,11 +821,9 @@ public class PresetVariableHelperTest {
Mockito.doReturn(expected.getId()).when(diskOfferingVoMock).getUuid();
Mockito.doReturn(expected.getName()).when(diskOfferingVoMock).getName();
GenericPresetVariable result = presetVariableHelperSpy.getPresetVariableValueDiskOffering(1l);
GenericPresetVariable result = presetVariableHelperSpy.getPresetVariableValueDiskOffering(1L);
assertPresetVariableIdAndName(expected, result);
validateFieldNamesToIncludeInToString(Arrays.asList("bytesReadBurst", "bytesReadBurstLength", "bytesReadRate", "bytesWriteBurst", "bytesWriteBurstLength", "bytesWriteRate",
"id", "iopsReadBurst", "iopsReadBurstLength", "iopsReadRate", "iopsWriteBurst", "iopsWriteBurstLength", "iopsWriteRate", "name"), result);
}
@Test
@ -862,7 +831,7 @@ public class PresetVariableHelperTest {
Storage expected = getStorageForTests();
Mockito.doReturn(expected).when(presetVariableHelperSpy).getSecondaryStorageForSnapshot(Mockito.anyLong(), Mockito.anyInt());
Storage result = presetVariableHelperSpy.getPresetVariableValueStorage(1l, 2);
Storage result = presetVariableHelperSpy.getPresetVariableValueStorage(1L, 2);
Assert.assertEquals(expected, result);
Mockito.verify(primaryStorageDaoMock, Mockito.never()).findByIdIncludingRemoved(Mockito.anyLong());
@ -880,16 +849,14 @@ public class PresetVariableHelperTest {
Mockito.doReturn(expected.getId()).when(storagePoolVoMock).getUuid();
Mockito.doReturn(expected.getName()).when(storagePoolVoMock).getName();
Mockito.doReturn(expected.getScope()).when(storagePoolVoMock).getScope();
Mockito.doReturn(ScopeType.validateAndGetScopeType(expected.getScope())).when(storagePoolVoMock).getScope();
Mockito.doReturn(storageTagVOListMock).when(storagePoolTagsDaoMock).findStoragePoolTags(Mockito.anyLong());
Storage result = presetVariableHelperSpy.getPresetVariableValueStorage(1l, 2);
Storage result = presetVariableHelperSpy.getPresetVariableValueStorage(1L, 2);
assertPresetVariableIdAndName(expected, result);
Assert.assertEquals(expected.getScope(), result.getScope());
Assert.assertEquals(expected.getTags(), result.getTags());
validateFieldNamesToIncludeInToString(Arrays.asList("id", "isTagARule", "name", "scope", "tags"), result);
}
@Test
@ -904,24 +871,22 @@ public class PresetVariableHelperTest {
Mockito.doReturn(expected.getId()).when(storagePoolVoMock).getUuid();
Mockito.doReturn(expected.getName()).when(storagePoolVoMock).getName();
Mockito.doReturn(expected.getScope()).when(storagePoolVoMock).getScope();
Mockito.doReturn(ScopeType.validateAndGetScopeType(expected.getScope())).when(storagePoolVoMock).getScope();
Mockito.doReturn(storageTagVOListMock).when(storagePoolTagsDaoMock).findStoragePoolTags(Mockito.anyLong());
Storage result = presetVariableHelperSpy.getPresetVariableValueStorage(1l, 2);
Storage result = presetVariableHelperSpy.getPresetVariableValueStorage(1L, 2);
assertPresetVariableIdAndName(expected, result);
Assert.assertEquals(expected.getScope(), result.getScope());
Assert.assertEquals(new ArrayList<>(), result.getTags());
Assert.assertTrue(result.getIsTagARule());
validateFieldNamesToIncludeInToString(Arrays.asList("id", "isTagARule", "name", "scope", "tags"), result);
}
@Test
public void getSecondaryStorageForSnapshotTestAllTypesAndDoNotBackupSnapshotReturnNull() {
presetVariableHelperSpy.backupSnapshotAfterTakingSnapshot = false;
getQuotaTypesForTests().forEach(type -> {
Storage result = presetVariableHelperSpy.getSecondaryStorageForSnapshot(1l, type.getKey());
Storage result = presetVariableHelperSpy.getSecondaryStorageForSnapshot(1L, type.getKey());
Assert.assertNull(result);
});
}
@ -930,7 +895,7 @@ public class PresetVariableHelperTest {
public void getSecondaryStorageForSnapshotTestAllTypesExceptSnapshotAndBackupSnapshotReturnNull() {
presetVariableHelperSpy.backupSnapshotAfterTakingSnapshot = true;
getQuotaTypesForTests(UsageTypes.SNAPSHOT).forEach(type -> {
Storage result = presetVariableHelperSpy.getSecondaryStorageForSnapshot(1l, type.getKey());
Storage result = presetVariableHelperSpy.getSecondaryStorageForSnapshot(1L, type.getKey());
Assert.assertNull(result);
});
}
@ -947,10 +912,9 @@ public class PresetVariableHelperTest {
Mockito.doReturn(expected.getName()).when(imageStoreVoMock).getName();
presetVariableHelperSpy.backupSnapshotAfterTakingSnapshot = true;
Storage result = presetVariableHelperSpy.getSecondaryStorageForSnapshot(1l, UsageTypes.SNAPSHOT);
Storage result = presetVariableHelperSpy.getSecondaryStorageForSnapshot(1L, UsageTypes.SNAPSHOT);
assertPresetVariableIdAndName(expected, result);
validateFieldNamesToIncludeInToString(Arrays.asList("id", "name"), result);
}
@Test
@ -991,8 +955,6 @@ public class PresetVariableHelperTest {
Assert.assertEquals(expected.getOsName(), result.getOsName());
Assert.assertEquals(expected.getTags(), result.getTags());
Assert.assertEquals(expectedSize, result.getSize());
validateFieldNamesToIncludeInToString(Arrays.asList("id", "name", "osName", "tags", "size"), result);
});
Mockito.verify(presetVariableHelperSpy).getPresetVariableValueResourceTags(Mockito.anyLong(), Mockito.eq(ResourceObjectType.Template));
@ -1025,7 +987,7 @@ public class PresetVariableHelperTest {
Mockito.doReturn(expected.getName()).when(snapshotVoMock).getName();
Mockito.doReturn(expected.getSize()).when(snapshotVoMock).getSize();
Mockito.doReturn((short) 3).when(snapshotVoMock).getSnapshotType();
Mockito.doReturn(1l).when(presetVariableHelperSpy).getSnapshotDataStoreId(Mockito.anyLong(), Mockito.anyLong());
Mockito.doReturn(1L).when(presetVariableHelperSpy).getSnapshotDataStoreId(Mockito.anyLong(), Mockito.anyLong());
Mockito.doReturn(expected.getStorage()).when(presetVariableHelperSpy).getPresetVariableValueStorage(Mockito.anyLong(), Mockito.anyInt());
Mockito.doReturn(expected.getTags()).when(presetVariableHelperSpy).getPresetVariableValueResourceTags(Mockito.anyLong(), Mockito.any(ResourceObjectType.class));
Mockito.doReturn(hypervisorType).when(snapshotVoMock).getHypervisorType();
@ -1043,8 +1005,6 @@ public class PresetVariableHelperTest {
Assert.assertEquals(expected.getTags(), result.getTags());
Assert.assertEquals(expectedSize, result.getSize());
Assert.assertEquals(hypervisorType.name(), result.getHypervisorType());
validateFieldNamesToIncludeInToString(Arrays.asList("id", "name", "snapshotType", "storage", "tags", "size", "hypervisorType"), result);
}
Mockito.verify(presetVariableHelperSpy, Mockito.times(Hypervisor.HypervisorType.values().length)).getPresetVariableValueResourceTags(Mockito.anyLong(),
@ -1056,12 +1016,12 @@ public class PresetVariableHelperTest {
public void getSnapshotDataStoreIdTestDoNotBackupSnapshotToSecondaryRetrievePrimaryStorage() {
SnapshotDataStoreVO snapshotDataStoreVoMock = Mockito.mock(SnapshotDataStoreVO.class);
Long expected = 1l;
Long expected = 1L;
Mockito.doReturn(snapshotDataStoreVoMock).when(snapshotDataStoreDaoMock).findOneBySnapshotAndDatastoreRole(Mockito.anyLong(), Mockito.any(DataStoreRole.class));
Mockito.doReturn(expected).when(snapshotDataStoreVoMock).getDataStoreId();
presetVariableHelperSpy.backupSnapshotAfterTakingSnapshot = false;
Long result = presetVariableHelperSpy.getSnapshotDataStoreId(1l, 1l);
Long result = presetVariableHelperSpy.getSnapshotDataStoreId(1L, 1L);
Assert.assertEquals(expected, result);
@ -1078,7 +1038,7 @@ public class PresetVariableHelperTest {
public void getSnapshotDataStoreIdTestBackupSnapshotToSecondaryRetrieveSecondaryStorage() {
SnapshotDataStoreVO snapshotDataStoreVoMock = Mockito.mock(SnapshotDataStoreVO.class);
Long expected = 2l;
Long expected = 2L;
ImageStoreVO imageStore = Mockito.mock(ImageStoreVO.class);
Mockito.when(imageStoreDaoMock.findById(Mockito.anyLong())).thenReturn(imageStore);
Mockito.when(imageStore.getDataCenterId()).thenReturn(1L);
@ -1086,7 +1046,7 @@ public class PresetVariableHelperTest {
Mockito.doReturn(expected).when(snapshotDataStoreVoMock).getDataStoreId();
presetVariableHelperSpy.backupSnapshotAfterTakingSnapshot = true;
Long result = presetVariableHelperSpy.getSnapshotDataStoreId(2l, 1L);
Long result = presetVariableHelperSpy.getSnapshotDataStoreId(2L, 1L);
Assert.assertEquals(expected, result);
@ -1129,8 +1089,6 @@ public class PresetVariableHelperTest {
assertPresetVariableIdAndName(expected, result);
Assert.assertEquals(expected.getTag(), result.getTag());
validateFieldNamesToIncludeInToString(Arrays.asList("id", "name", "tag"), result);
}
@Test
@ -1155,7 +1113,7 @@ public class PresetVariableHelperTest {
Mockito.doReturn(expected.getId()).when(vmSnapshotVoMock).getUuid();
Mockito.doReturn(expected.getName()).when(vmSnapshotVoMock).getName();
Mockito.doReturn(expected.getTags()).when(presetVariableHelperSpy).getPresetVariableValueResourceTags(Mockito.anyLong(), Mockito.any(ResourceObjectType.class));
Mockito.doReturn(expected.getVmSnapshotType()).when(vmSnapshotVoMock).getType();
Mockito.doReturn(VMSnapshot.Type.valueOf(expected.getVmSnapshotType())).when(vmSnapshotVoMock).getType();
Mockito.doReturn(UsageTypes.VM_SNAPSHOT).when(usageVoMock).getUsageType();
@ -1166,8 +1124,6 @@ public class PresetVariableHelperTest {
Assert.assertEquals(expected.getTags(), result.getTags());
Assert.assertEquals(expected.getVmSnapshotType(), result.getVmSnapshotType());
validateFieldNamesToIncludeInToString(Arrays.asList("id", "name", "tags", "vmSnapshotType"), result);
Mockito.verify(presetVariableHelperSpy).getPresetVariableValueResourceTags(Mockito.anyLong(), Mockito.eq(ResourceObjectType.VMSnapshot));
}
@ -1200,9 +1156,6 @@ public class PresetVariableHelperTest {
if (typeInt == UsageTypes.RUNNING_VM) {
Assert.assertEquals(expected.getComputingResources(), result.getComputingResources());
validateFieldNamesToIncludeInToString(Arrays.asList("computeOffering", "computingResources"), result);
} else {
validateFieldNamesToIncludeInToString(Arrays.asList("computeOffering"), result);
}
});
}
@ -1228,7 +1181,7 @@ public class PresetVariableHelperTest {
@Test
public void getDetailByNameTestReturnsValue() {
int expected = Integer.valueOf(getVmDetailsForTests().get(0).getValue());
int expected = Integer.parseInt(getVmDetailsForTests().get(0).getValue());
int result = presetVariableHelperSpy.getDetailByName(getVmDetailsForTests(), "test_with_value", expected);
Assert.assertEquals(expected, result);
}
@ -1295,8 +1248,6 @@ public class PresetVariableHelperTest {
Assert.assertEquals(expected.getVirtualSize(), result.getVirtualSize());
Assert.assertEquals(expected.getBackupOffering(), result.getBackupOffering());
validateFieldNamesToIncludeInToString(Arrays.asList("size", "virtualSize", "backupOffering"), result);
Mockito.verify(presetVariableHelperSpy).getPresetVariableValueBackupOffering(Mockito.anyLong());
}
@ -1311,11 +1262,10 @@ public class PresetVariableHelperTest {
Mockito.doReturn(expected.getName()).when(backupOfferingVoMock).getName();
Mockito.doReturn(expected.getExternalId()).when(backupOfferingVoMock).getExternalId();
BackupOffering result = presetVariableHelperSpy.getPresetVariableValueBackupOffering(1l);
BackupOffering result = presetVariableHelperSpy.getPresetVariableValueBackupOffering(1L);
assertPresetVariableIdAndName(expected, result);
Assert.assertEquals(expected.getExternalId(), result.getExternalId());
validateFieldNamesToIncludeInToString(Arrays.asList("id", "name", "externalId"), result);
}
@Test

View File

@ -1,34 +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.
package org.apache.cloudstack.quota.activationrule.presetvariables;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class RoleTest {
@Test
public void setTagsTestAddFieldTagsToCollection() {
Role variable = new Role();
variable.setType(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("type"));
}
}

View File

@ -1,41 +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.
package org.apache.cloudstack.quota.activationrule.presetvariables;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class StorageTest {
@Test
public void setTagsTestAddFieldTagsToCollection() {
Storage variable = new Storage();
variable.setTags(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("tags"));
}
@Test
public void setScopeTestAddFieldScopeToCollection() {
Storage variable = new Storage();
variable.setScope(null);;
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("scope"));
}
}

View File

@ -1,175 +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.
package org.apache.cloudstack.quota.activationrule.presetvariables;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ValueTest {
@Test
public void setIdTestAddFieldIdToCollection() {
Value variable = new Value();
variable.setId(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("id"));
}
@Test
public void setNameTestAddFieldNameToCollection() {
Value variable = new Value();
variable.setName(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("name"));
}
@Test
public void setHostTestAddFieldHostToCollection() {
Value variable = new Value();
variable.setHost(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("host"));
}
@Test
public void setOsNameTestAddFieldOsNameToCollection() {
Value variable = new Value();
variable.setOsName(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("osName"));
}
@Test
public void setAccountResourcesTestAddFieldAccountResourcesToCollection() {
Value variable = new Value();
variable.setAccountResources(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("accountResources"));
}
@Test
public void setTagsTestAddFieldTagsToCollection() {
Value variable = new Value();
variable.setTags(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("tags"));
}
@Test
public void setTagTestAddFieldTagToCollection() {
Value variable = new Value();
variable.setTag(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("tag"));
}
@Test
public void setSizeTestAddFieldSizeToCollection() {
Value variable = new Value();
variable.setSize(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("size"));
}
@Test
public void setProvisioningTypeTestAddFieldProvisioningTypeToCollection() {
Value variable = new Value();
variable.setProvisioningType(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("provisioningType"));
}
@Test
public void setSnapshotTypeTestAddFieldSnapshotTypeToCollection() {
Value variable = new Value();
variable.setSnapshotType(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("snapshotType"));
}
@Test
public void setVmSnapshotTypeTestAddFieldVmSnapshotTypeToCollection() {
Value variable = new Value();
variable.setVmSnapshotType(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("vmSnapshotType"));
}
@Test
public void setComputeOfferingTestAddFieldComputeOfferingToCollection() {
Value variable = new Value();
variable.setComputeOffering(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("computeOffering"));
}
@Test
public void setTemplateTestAddFieldTemplateToCollection() {
Value variable = new Value();
variable.setTemplate(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("template"));
}
@Test
public void setDiskOfferingTestAddFieldDiskOfferingToCollection() {
Value variable = new Value();
variable.setDiskOffering(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("diskOffering"));
}
@Test
public void setStorageTestAddFieldStorageToCollection() {
Value variable = new Value();
variable.setStorage(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("storage"));
}
@Test
public void setComputingResourcesTestAddFieldComputingResourcesToCollection() {
Value variable = new Value();
variable.setComputingResources(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("computingResources"));
}
@Test
public void setVirtualSizeTestAddFieldVirtualSizeToCollection() {
Value variable = new Value();
variable.setVirtualSize(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("virtualSize"));
}
@Test
public void setBackupOfferingTestAddFieldBackupOfferingToCollection() {
Value variable = new Value();
variable.setBackupOffering(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("backupOffering"));
}
@Test
public void setHypervisorTypeTestAddFieldHypervisorTypeToCollection() {
Value variable = new Value();
variable.setHypervisorType(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("hypervisorType"));
}
@Test
public void setVolumeFormatTestAddFieldVolumeFormatToCollection() {
Value variable = new Value();
variable.setVolumeFormat(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("volumeFormat"));
}
@Test
public void setStateTestAddFieldStateToCollection() {
Value variable = new Value();
variable.setState(null);
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("state"));
}
}

View File

@ -44,8 +44,10 @@ import org.apache.cloudstack.api.response.ApiDiscoveryResponse;
import org.apache.cloudstack.api.response.ApiParameterResponse;
import org.apache.cloudstack.api.response.ApiResponseResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.resourcedetail.UserDetailVO;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.reflections.ReflectionUtils;
import org.springframework.stereotype.Component;
@ -56,6 +58,7 @@ import com.cloud.serializer.Param;
import com.cloud.user.Account;
import com.cloud.user.AccountService;
import com.cloud.user.User;
import com.cloud.user.UserAccount;
import com.cloud.utils.ReflectUtil;
import com.cloud.utils.component.ComponentLifecycleBase;
import com.cloud.utils.component.PluggableService;
@ -67,6 +70,7 @@ public class ApiDiscoveryServiceImpl extends ComponentLifecycleBase implements A
List<APIChecker> _apiAccessCheckers = null;
List<PluggableService> _services = null;
protected static Map<String, ApiDiscoveryResponse> s_apiNameDiscoveryResponseMap = null;
public static final List<String> APIS_ALLOWED_FOR_PASSWORD_CHANGE = Arrays.asList("login", "logout", "updateUser", "listApis");
@Inject
AccountService accountService;
@ -287,12 +291,20 @@ public class ApiDiscoveryServiceImpl extends ComponentLifecycleBase implements A
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(account, "accountName", "uuid")));
}
if (role.getRoleType() == RoleType.Admin && role.getId() == RoleType.Admin.getId()) {
logger.info(String.format("Account [%s] is Root Admin, all APIs are allowed.",
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(account, "accountName", "uuid")));
// Limit APIs on first login requiring password change
UserAccount userAccount = accountService.getUserAccountById(user.getId());
Map<String, String> userAccDetails = userAccount.getDetails();
if (MapUtils.isNotEmpty(userAccDetails) && !userAccDetails.containsKey(UserDetailVO.OauthLogin) &&
"true".equalsIgnoreCase(userAccDetails.get(UserDetailVO.PasswordChangeRequired))) {
apisAllowed = APIS_ALLOWED_FOR_PASSWORD_CHANGE;
} else {
for (APIChecker apiChecker : _apiAccessCheckers) {
apisAllowed = apiChecker.getApisAllowedToUser(role, user, apisAllowed);
if (role.getRoleType() == RoleType.Admin && role.getId() == RoleType.Admin.getId()) {
logger.info(String.format("Account [%s] is Root Admin, all APIs are allowed.",
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(account, "accountName", "uuid")));
} else {
for (APIChecker apiChecker : _apiAccessCheckers) {
apisAllowed = apiChecker.getApisAllowedToUser(role, user, apisAllowed);
}
}
}

View File

@ -21,6 +21,8 @@ import com.cloud.user.Account;
import com.cloud.user.AccountService;
import com.cloud.user.AccountVO;
import com.cloud.user.User;
import com.cloud.user.UserAccount;
import com.cloud.user.UserAccountVO;
import com.cloud.user.UserVO;
import org.apache.cloudstack.acl.APIChecker;
@ -29,6 +31,8 @@ import org.apache.cloudstack.acl.RoleService;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.acl.RoleVO;
import org.apache.cloudstack.api.response.ApiDiscoveryResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -39,11 +43,15 @@ import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.apache.cloudstack.resourcedetail.UserDetailVO.PasswordChangeRequired;
import static org.apache.cloudstack.resourcedetail.UserDetailVO.Setup2FADetail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyLong;
@RunWith(MockitoJUnitRunner.class)
public class ApiDiscoveryTest {
@ -66,12 +74,17 @@ public class ApiDiscoveryTest {
@InjectMocks
ApiDiscoveryServiceImpl discoveryServiceSpy;
@Mock
UserAccount mockUserAccount;
@Before
public void setup() {
discoveryServiceSpy.s_apiNameDiscoveryResponseMap = apiNameDiscoveryResponseMapMock;
discoveryServiceSpy._apiAccessCheckers = apiAccessCheckersMock;
Mockito.when(discoveryServiceSpy._apiAccessCheckers.iterator()).thenReturn(Arrays.asList(apiCheckerMock).iterator());
Mockito.when(mockUserAccount.getDetails()).thenReturn(null);
Mockito.when(accountServiceMock.getUserAccountById(anyLong())).thenReturn(mockUserAccount);
}
private User getTestUser() {
@ -131,4 +144,29 @@ public class ApiDiscoveryTest {
Mockito.verify(apiCheckerMock, Mockito.times(1)).getApisAllowedToUser(any(Role.class), any(User.class), anyList());
}
@Test
public void listApisForUserWithoutEnforcedPwdChange() throws PermissionDeniedException {
RoleVO userRoleVO = new RoleVO(4L, "name", RoleType.User, "description");
Map<String, String> userDetails = new HashMap<>();
userDetails.put(Setup2FADetail, UserAccountVO.Setup2FAstatus.ENABLED.name());
Mockito.when(mockUserAccount.getDetails()).thenReturn(userDetails);
Mockito.when(accountServiceMock.getAccount(Mockito.anyLong())).thenReturn(getNormalAccount());
Mockito.when(roleServiceMock.findRole(Mockito.anyLong())).thenReturn(userRoleVO);
discoveryServiceSpy.listApis(getTestUser(), null);
Mockito.verify(apiCheckerMock, Mockito.times(1)).getApisAllowedToUser(any(Role.class), any(User.class), anyList());
}
@Test
public void listApisForUserEnforcedPwdChange() throws PermissionDeniedException {
RoleVO userRoleVO = new RoleVO(4L, "name", RoleType.User, "description");
Map<String, String> userDetails = new HashMap<>();
userDetails.put(PasswordChangeRequired, "true");
Mockito.when(mockUserAccount.getDetails()).thenReturn(userDetails);
Mockito.when(accountServiceMock.getAccount(Mockito.anyLong())).thenReturn(getNormalAccount());
Mockito.when(roleServiceMock.findRole(Mockito.anyLong())).thenReturn(userRoleVO);
Mockito.when(apiNameDiscoveryResponseMapMock.get(Mockito.anyString())).thenReturn(Mockito.mock(ApiDiscoveryResponse.class));
ListResponse<ApiDiscoveryResponse> response = (ListResponse<ApiDiscoveryResponse>) discoveryServiceSpy.listApis(getTestUser(), null);
Assert.assertEquals(4, response.getResponses().size());
}
}

View File

@ -70,7 +70,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
@ -297,7 +296,8 @@ public class NASBackupProvider extends AdapterBase implements BackupProvider, Co
}
private Pair<Boolean, String> restoreVMBackup(VirtualMachine vm, Backup backup) {
List<String> backedVolumesUUIDs = backup.getBackedUpVolumes().stream()
List<Backup.VolumeInfo> backedVolumes = backup.getBackedUpVolumes();
List<String> backedVolumesUUIDs = backedVolumes.stream()
.sorted(Comparator.comparingLong(Backup.VolumeInfo::getDeviceId))
.map(Backup.VolumeInfo::getUuid)
.collect(Collectors.toList());
@ -320,6 +320,7 @@ public class NASBackupProvider extends AdapterBase implements BackupProvider, Co
Pair<List<PrimaryDataStoreTO>, List<String>> volumePoolsAndPaths = getVolumePoolsAndPaths(restoreVolumes);
restoreCommand.setRestoreVolumePools(volumePoolsAndPaths.first());
restoreCommand.setRestoreVolumePaths(volumePoolsAndPaths.second());
restoreCommand.setBackupFiles(getBackupFiles(backedVolumes));
restoreCommand.setVmExists(vm.getRemoved() == null);
restoreCommand.setVmState(vm.getState());
restoreCommand.setMountTimeout(NASBackupRestoreMountTimeout.value());
@ -335,6 +336,14 @@ public class NASBackupProvider extends AdapterBase implements BackupProvider, Co
return new Pair<>(answer.getResult(), answer.getDetails());
}
private List<String> getBackupFiles(List<Backup.VolumeInfo> backedVolumes) {
List<String> backupFiles = new ArrayList<>();
for (Backup.VolumeInfo backedVolume : backedVolumes) {
backupFiles.add(backedVolume.getPath());
}
return backupFiles;
}
private Pair<List<PrimaryDataStoreTO>, List<String>> getVolumePoolsAndPaths(List<VolumeVO> volumes) {
List<PrimaryDataStoreTO> volumePools = new ArrayList<>();
List<String> volumePaths = new ArrayList<>();
@ -373,7 +382,13 @@ public class NASBackupProvider extends AdapterBase implements BackupProvider, Co
final StoragePoolVO pool = primaryDataStoreDao.findByUuid(dataStoreUuid);
final HostVO hostVO = hostDao.findByIp(hostIp);
LOG.debug("Restoring vm volume {} from backup {} on the NAS Backup Provider", backupVolumeInfo, backup);
Backup.VolumeInfo matchingVolume = getBackedUpVolumeInfo(backup.getBackedUpVolumes(), volume.getUuid());
if (matchingVolume == null) {
throw new CloudRuntimeException(String.format("Unable to find volume %s in the list of backed up volumes for backup %s, cannot proceed with restore", volume.getUuid(), backup));
}
Long backedUpVolumeSize = matchingVolume.getSize();
LOG.debug("Restoring vm volume {} from backup {} on the NAS Backup Provider", volume, backup);
BackupRepository backupRepository = getBackupRepository(backup);
VolumeVO restoredVolume = new VolumeVO(Volume.Type.DATADISK, null, backup.getZoneId(),
@ -391,7 +406,7 @@ public class NASBackupProvider extends AdapterBase implements BackupProvider, Co
restoredVolume.setPoolType(pool.getPoolType());
restoredVolume.setPath(restoredVolume.getUuid());
restoredVolume.setState(Volume.State.Copying);
restoredVolume.setSize(backupVolumeInfo.getSize());
restoredVolume.setSize(backedUpVolumeSize);
restoredVolume.setDiskOfferingId(diskOffering.getId());
if (pool.getPoolType() != Storage.StoragePoolType.RBD) {
restoredVolume.setFormat(Storage.ImageFormat.QCOW2);
@ -411,8 +426,8 @@ public class NASBackupProvider extends AdapterBase implements BackupProvider, Co
restoreCommand.setMountOptions(backupRepository.getMountOptions());
restoreCommand.setVmExists(null);
restoreCommand.setVmState(vmNameAndState.second());
restoreCommand.setRestoreVolumeUUID(backupVolumeInfo.getUuid());
restoreCommand.setMountTimeout(NASBackupRestoreMountTimeout.value());
restoreCommand.setBackupFiles(Collections.singletonList(matchingVolume.getPath()));
BackupAnswer answer;
try {
@ -442,10 +457,11 @@ public class NASBackupProvider extends AdapterBase implements BackupProvider, Co
return backupRepository;
}
private Optional<Backup.VolumeInfo> getBackedUpVolumeInfo(List<Backup.VolumeInfo> backedUpVolumes, String volumeUuid) {
private Backup.VolumeInfo getBackedUpVolumeInfo(List<Backup.VolumeInfo> backedUpVolumes, String volumeUuid) {
return backedUpVolumes.stream()
.filter(v -> v.getUuid().equals(volumeUuid))
.findFirst();
.findFirst()
.orElse(null);
}
@Override

View File

@ -16,6 +16,7 @@
// under the License.
package org.apache.cloudstack.backup;
import com.cloud.agent.AgentManager;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
@ -134,6 +135,9 @@ public class NetworkerBackupProvider extends AdapterBase implements BackupProvid
@Inject
private DiskOfferingDao diskOfferingDao;
@Inject
private AgentManager agentMgr;
private static String getUrlDomain(String url) throws URISyntaxException {
URI uri;
try {
@ -251,8 +255,13 @@ public class NetworkerBackupProvider extends AdapterBase implements BackupProvid
String nstRegex = "\\bcompleted savetime=([0-9]{10})";
Pattern saveTimePattern = Pattern.compile(nstRegex);
if (host == null) {
LOG.warn("Unable to take backup, host is null");
return null;
}
try {
Pair<Boolean, String> response = SshHelper.sshExecute(host.getPrivateIpAddress(), 22,
Pair<Boolean, String> response = SshHelper.sshExecute(host.getPrivateIpAddress(), agentMgr.getHostSshPort(host),
username, null, password, command, 120000, 120000, 3600000);
if (!response.first()) {
LOG.error("Backup Script failed on HYPERVISOR {} due to: {}", host, response.second());
@ -271,9 +280,13 @@ public class NetworkerBackupProvider extends AdapterBase implements BackupProvid
return null;
}
private boolean executeRestoreCommand(HostVO host, String username, String password, String command) {
if (host == null) {
LOG.warn("Unable to restore backup, host is null");
return false;
}
try {
Pair<Boolean, String> response = SshHelper.sshExecute(host.getPrivateIpAddress(), 22,
Pair<Boolean, String> response = SshHelper.sshExecute(host.getPrivateIpAddress(), agentMgr.getHostSshPort(host),
username, null, password, command, 120000, 120000, 3600000);
if (!response.first()) {

View File

@ -493,7 +493,7 @@ public class RabbitMQEventBus extends ManagerBase implements EventBus {
@Override
public synchronized boolean stop() {
if (s_connection.isOpen()) {
if (s_connection != null && s_connection.isOpen()) {
for (String subscriberId : s_subscribers.keySet()) {
Ternary<String, Channel, EventSubscriber> subscriberDetails = s_subscribers.get(subscriberId);
Channel channel = subscriberDetails.second();

View File

@ -72,10 +72,10 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper<RestoreBa
List<String> backedVolumeUUIDs = command.getBackupVolumesUUIDs();
List<PrimaryDataStoreTO> restoreVolumePools = command.getRestoreVolumePools();
List<String> restoreVolumePaths = command.getRestoreVolumePaths();
String restoreVolumeUuid = command.getRestoreVolumeUUID();
Integer mountTimeout = command.getMountTimeout() * 1000;
int timeout = command.getWait();
KVMStoragePoolManager storagePoolMgr = serverResource.getStoragePoolMgr();
List<String> backupFiles = command.getBackupFiles();
String newVolumeId = null;
try {
@ -83,14 +83,15 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper<RestoreBa
if (Objects.isNull(vmExists)) {
PrimaryDataStoreTO volumePool = restoreVolumePools.get(0);
String volumePath = restoreVolumePaths.get(0);
String backupFile = backupFiles.get(0);
int lastIndex = volumePath.lastIndexOf("/");
newVolumeId = volumePath.substring(lastIndex + 1);
restoreVolume(storagePoolMgr, backupPath, volumePool, volumePath, diskType, restoreVolumeUuid,
restoreVolume(storagePoolMgr, backupPath, volumePool, volumePath, diskType, backupFile,
new Pair<>(vmName, command.getVmState()), mountDirectory, timeout);
} else if (Boolean.TRUE.equals(vmExists)) {
restoreVolumesOfExistingVM(storagePoolMgr, restoreVolumePools, restoreVolumePaths, backedVolumeUUIDs, backupPath, mountDirectory, timeout);
restoreVolumesOfExistingVM(storagePoolMgr, restoreVolumePools, restoreVolumePaths, backedVolumeUUIDs, backupPath, backupFiles, mountDirectory, timeout);
} else {
restoreVolumesOfDestroyedVMs(storagePoolMgr, restoreVolumePools, restoreVolumePaths, vmName, backupPath, mountDirectory, timeout);
restoreVolumesOfDestroyedVMs(storagePoolMgr, restoreVolumePools, restoreVolumePaths, backupPath, backupFiles, mountDirectory, timeout);
}
} catch (CloudRuntimeException e) {
String errorMessage = e.getMessage() != null ? e.getMessage() : "";
@ -109,19 +110,22 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper<RestoreBa
}
}
private void restoreVolumesOfExistingVM(KVMStoragePoolManager storagePoolMgr, List<PrimaryDataStoreTO> restoreVolumePools, List<String> restoreVolumePaths, List<String> backedVolumesUUIDs,
String backupPath, String mountDirectory, int timeout) {
private void restoreVolumesOfExistingVM(KVMStoragePoolManager storagePoolMgr, List<PrimaryDataStoreTO> restoreVolumePools,
List<String> restoreVolumePaths, List<String> backedVolumesUUIDs,
String backupPath, List<String> backupFiles, String mountDirectory, int timeout) {
String diskType = "root";
try {
for (int idx = 0; idx < restoreVolumePaths.size(); idx++) {
PrimaryDataStoreTO restoreVolumePool = restoreVolumePools.get(idx);
String restoreVolumePath = restoreVolumePaths.get(idx);
String backupFile = backupFiles.get(idx);
String backupVolumeUuid = backedVolumesUUIDs.get(idx);
Pair<String, String> bkpPathAndVolUuid = getBackupPath(mountDirectory, null, backupPath, diskType, backupVolumeUuid);
String fullPath = getBackupPath(mountDirectory, backupPath, backupFile, diskType);
diskType = "datadisk";
verifyBackupFile(bkpPathAndVolUuid.first(), bkpPathAndVolUuid.second());
if (!replaceVolumeWithBackup(storagePoolMgr, restoreVolumePool, restoreVolumePath, bkpPathAndVolUuid.first(), timeout)) {
throw new CloudRuntimeException(String.format("Unable to restore contents from the backup volume [%s].", bkpPathAndVolUuid.second()));
verifyBackupFile(fullPath, backupVolumeUuid);
if (!replaceVolumeWithBackup(storagePoolMgr, restoreVolumePool, restoreVolumePath, fullPath, timeout)) {
throw new CloudRuntimeException(String.format("Unable to restore contents from the backup volume [%s].", backupVolumeUuid));
}
}
} finally {
@ -130,17 +134,20 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper<RestoreBa
}
}
private void restoreVolumesOfDestroyedVMs(KVMStoragePoolManager storagePoolMgr, List<PrimaryDataStoreTO> volumePools, List<String> volumePaths, String vmName, String backupPath, String mountDirectory, int timeout) {
private void restoreVolumesOfDestroyedVMs(KVMStoragePoolManager storagePoolMgr, List<PrimaryDataStoreTO> volumePools,
List<String> volumePaths, String backupPath, List<String> backupFiles, String mountDirectory, int timeout) {
String diskType = "root";
try {
for (int i = 0; i < volumePaths.size(); i++) {
PrimaryDataStoreTO volumePool = volumePools.get(i);
String volumePath = volumePaths.get(i);
Pair<String, String> bkpPathAndVolUuid = getBackupPath(mountDirectory, volumePath, backupPath, diskType, null);
String backupFile = backupFiles.get(i);
String bkpPath = getBackupPath(mountDirectory, backupPath, backupFile, diskType);
String volumeUuid = volumePath.substring(volumePath.lastIndexOf(File.separator) + 1);
diskType = "datadisk";
verifyBackupFile(bkpPathAndVolUuid.first(), bkpPathAndVolUuid.second());
if (!replaceVolumeWithBackup(storagePoolMgr, volumePool, volumePath, bkpPathAndVolUuid.first(), timeout)) {
throw new CloudRuntimeException(String.format("Unable to restore contents from the backup volume [%s].", bkpPathAndVolUuid.second()));
verifyBackupFile(bkpPath, volumeUuid);
if (!replaceVolumeWithBackup(storagePoolMgr, volumePool, volumePath, bkpPath, timeout)) {
throw new CloudRuntimeException(String.format("Unable to restore contents from the backup volume [%s].", volumeUuid));
}
}
} finally {
@ -149,14 +156,17 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper<RestoreBa
}
}
private void restoreVolume(KVMStoragePoolManager storagePoolMgr, String backupPath, PrimaryDataStoreTO volumePool, String volumePath, String diskType, String volumeUUID,
private void restoreVolume(KVMStoragePoolManager storagePoolMgr, String backupPath, PrimaryDataStoreTO volumePool, String volumePath, String diskType, String backupFile,
Pair<String, VirtualMachine.State> vmNameAndState, String mountDirectory, int timeout) {
Pair<String, String> bkpPathAndVolUuid;
String bkpPath;
String volumeUuid;
try {
bkpPathAndVolUuid = getBackupPath(mountDirectory, volumePath, backupPath, diskType, volumeUUID);
verifyBackupFile(bkpPathAndVolUuid.first(), bkpPathAndVolUuid.second());
if (!replaceVolumeWithBackup(storagePoolMgr, volumePool, volumePath, bkpPathAndVolUuid.first(), timeout, true)) {
throw new CloudRuntimeException(String.format("Unable to restore contents from the backup volume [%s].", bkpPathAndVolUuid.second()));
bkpPath = getBackupPath(mountDirectory, backupPath, backupFile, diskType);
volumeUuid = volumePath.substring(volumePath.lastIndexOf(File.separator) + 1);
verifyBackupFile(bkpPath, volumeUuid);
if (!replaceVolumeWithBackup(storagePoolMgr, volumePool, volumePath, bkpPath, timeout, true)) {
throw new CloudRuntimeException(String.format("Unable to restore contents from the backup volume [%s].", volumeUuid));
}
if (VirtualMachine.State.Running.equals(vmNameAndState.second())) {
if (!attachVolumeToVm(storagePoolMgr, vmNameAndState.first(), volumePool, volumePath)) {
@ -177,7 +187,7 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper<RestoreBa
try {
mountDirectory = Files.createTempDirectory(mountDirectory).toString();
} catch (IOException e) {
logger.error(String.format("Failed to create the tmp mount directory {} for restore", mountDirectory), e);
logger.error("Failed to create the tmp mount directory {} for restore", mountDirectory, e);
throw new CloudRuntimeException("Failed to create the tmp mount directory for restore on the KVM host");
}
@ -195,7 +205,7 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper<RestoreBa
int exitValue = Script.runSimpleBashScriptForExitValue(mount, mountTimeout, false);
if (exitValue != 0) {
logger.error(String.format("Failed to mount repository {} of type {} to the directory {}", backupRepoAddress, backupRepoType, mountDirectory));
logger.error("Failed to mount repository {} of type {} to the directory {}", backupRepoAddress, backupRepoType, mountDirectory);
throw new CloudRuntimeException("Failed to mount the backup repository on the KVM host");
}
return mountDirectory;
@ -205,7 +215,7 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper<RestoreBa
String umountCmd = String.format(UMOUNT_COMMAND, backupDirectory);
int exitValue = Script.runSimpleBashScriptForExitValue(umountCmd);
if (exitValue != 0) {
logger.error(String.format("Failed to unmount backup directory {}", backupDirectory));
logger.error("Failed to unmount backup directory {}", backupDirectory);
throw new CloudRuntimeException("Failed to unmount the backup directory");
}
}
@ -214,17 +224,16 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper<RestoreBa
try {
Files.deleteIfExists(Paths.get(backupDirectory));
} catch (IOException e) {
logger.error(String.format("Failed to delete backup directory: %s", backupDirectory), e);
logger.error("Failed to delete backup directory: {}}", backupDirectory, e);
throw new CloudRuntimeException("Failed to delete the backup directory");
}
}
private Pair<String, String> getBackupPath(String mountDirectory, String volumePath, String backupPath, String diskType, String volumeUuid) {
private String getBackupPath(String mountDirectory, String backupPath, String backupFile, String diskType) {
String bkpPath = String.format(FILE_PATH_PLACEHOLDER, mountDirectory, backupPath);
String volUuid = Objects.isNull(volumeUuid) ? volumePath.substring(volumePath.lastIndexOf(File.separator) + 1) : volumeUuid;
String backupFileName = String.format("%s.%s.qcow2", diskType.toLowerCase(Locale.ROOT), volUuid);
String backupFileName = String.format("%s.%s.qcow2", diskType.toLowerCase(Locale.ROOT), backupFile);
bkpPath = String.format(FILE_PATH_PLACEHOLDER, bkpPath, backupFileName);
return new Pair<>(bkpPath, volUuid);
return bkpPath;
}
private boolean checkBackupFileImage(String backupPath) {

View File

@ -69,7 +69,7 @@ public class LibvirtRestoreBackupCommandWrapperTest {
PrimaryDataStoreTO primaryDataStore = Mockito.mock(PrimaryDataStoreTO.class);
when(command.getRestoreVolumePools()).thenReturn(Arrays.asList(primaryDataStore));
when(command.getRestoreVolumePaths()).thenReturn(Arrays.asList("/var/lib/libvirt/images/volume-123"));
when(command.getRestoreVolumeUUID()).thenReturn("volume-123");
when(command.getBackupFiles()).thenReturn(Arrays.asList("volume-123"));
when(command.getVmState()).thenReturn(VirtualMachine.State.Running);
when(command.getMountTimeout()).thenReturn(30);
@ -112,6 +112,7 @@ public class LibvirtRestoreBackupCommandWrapperTest {
when(command.getRestoreVolumePools()).thenReturn(Arrays.asList(primaryDataStore));
when(command.getRestoreVolumePaths()).thenReturn(Arrays.asList("/var/lib/libvirt/images/volume-123"));
when(command.getBackupVolumesUUIDs()).thenReturn(Arrays.asList("volume-123"));
when(command.getBackupFiles()).thenReturn(Arrays.asList("volume-123"));
when(command.getMountTimeout()).thenReturn(30);
try (MockedStatic<Files> filesMock = mockStatic(Files.class)) {
@ -149,6 +150,7 @@ public class LibvirtRestoreBackupCommandWrapperTest {
PrimaryDataStoreTO primaryDataStore = Mockito.mock(PrimaryDataStoreTO.class);
when(command.getRestoreVolumePools()).thenReturn(Arrays.asList(primaryDataStore));
when(command.getRestoreVolumePaths()).thenReturn(Arrays.asList("/var/lib/libvirt/images/volume-123"));
when(command.getBackupFiles()).thenReturn(Arrays.asList("volume-123"));
when(command.getMountTimeout()).thenReturn(30);
try (MockedStatic<Files> filesMock = mockStatic(Files.class)) {
@ -186,7 +188,7 @@ public class LibvirtRestoreBackupCommandWrapperTest {
PrimaryDataStoreTO primaryDataStore = Mockito.mock(PrimaryDataStoreTO.class);
when(command.getRestoreVolumePools()).thenReturn(Arrays.asList(primaryDataStore));
when(command.getRestoreVolumePaths()).thenReturn(Arrays.asList("/var/lib/libvirt/images/volume-123"));
when(command.getRestoreVolumeUUID()).thenReturn("volume-123");
when(command.getBackupFiles()).thenReturn(Arrays.asList("volume-123"));
when(command.getVmState()).thenReturn(VirtualMachine.State.Running);
when(command.getMountTimeout()).thenReturn(30);
@ -227,7 +229,7 @@ public class LibvirtRestoreBackupCommandWrapperTest {
PrimaryDataStoreTO primaryDataStore = Mockito.mock(PrimaryDataStoreTO.class);
when(command.getRestoreVolumePools()).thenReturn(Arrays.asList(primaryDataStore));
lenient().when(command.getRestoreVolumePaths()).thenReturn(Arrays.asList("/var/lib/libvirt/images/volume-123"));
lenient().when(command.getRestoreVolumeUUID()).thenReturn("volume-123");
when(command.getBackupFiles()).thenReturn(Arrays.asList("volume-123"));
lenient().when(command.getVmState()).thenReturn(VirtualMachine.State.Running);
lenient().when(command.getMountTimeout()).thenReturn(30);
@ -263,7 +265,7 @@ public class LibvirtRestoreBackupCommandWrapperTest {
PrimaryDataStoreTO primaryDataStore = Mockito.mock(PrimaryDataStoreTO.class);
when(command.getRestoreVolumePools()).thenReturn(Arrays.asList(primaryDataStore));
when(command.getRestoreVolumePaths()).thenReturn(Arrays.asList("/var/lib/libvirt/images/volume-123"));
when(command.getRestoreVolumeUUID()).thenReturn("volume-123");
when(command.getBackupFiles()).thenReturn(Arrays.asList("volume-123"));
when(command.getVmState()).thenReturn(VirtualMachine.State.Running);
when(command.getMountTimeout()).thenReturn(30);
@ -309,7 +311,7 @@ public class LibvirtRestoreBackupCommandWrapperTest {
PrimaryDataStoreTO primaryDataStore = Mockito.mock(PrimaryDataStoreTO.class);
when(command.getRestoreVolumePools()).thenReturn(Arrays.asList(primaryDataStore));
when(command.getRestoreVolumePaths()).thenReturn(Arrays.asList("/var/lib/libvirt/images/volume-123"));
when(command.getRestoreVolumeUUID()).thenReturn("volume-123");
when(command.getBackupFiles()).thenReturn(Arrays.asList("volume-123"));
when(command.getVmState()).thenReturn(VirtualMachine.State.Running);
when(command.getMountTimeout()).thenReturn(30);
@ -357,7 +359,7 @@ public class LibvirtRestoreBackupCommandWrapperTest {
PrimaryDataStoreTO primaryDataStore = Mockito.mock(PrimaryDataStoreTO.class);
when(command.getRestoreVolumePools()).thenReturn(Arrays.asList(primaryDataStore));
when(command.getRestoreVolumePaths()).thenReturn(Arrays.asList("/var/lib/libvirt/images/volume-123"));
when(command.getRestoreVolumeUUID()).thenReturn("volume-123");
when(command.getBackupFiles()).thenReturn(Arrays.asList("volume-123"));
when(command.getVmState()).thenReturn(VirtualMachine.State.Running);
when(command.getMountTimeout()).thenReturn(30);
@ -407,7 +409,7 @@ public class LibvirtRestoreBackupCommandWrapperTest {
PrimaryDataStoreTO primaryDataStore = Mockito.mock(PrimaryDataStoreTO.class);
when(command.getRestoreVolumePools()).thenReturn(Arrays.asList(primaryDataStore));
when(command.getRestoreVolumePaths()).thenReturn(Arrays.asList("/var/lib/libvirt/images/volume-123"));
when(command.getRestoreVolumeUUID()).thenReturn("volume-123");
when(command.getBackupFiles()).thenReturn(Arrays.asList("volume-123"));
when(command.getVmState()).thenReturn(VirtualMachine.State.Running);
when(command.getMountTimeout()).thenReturn(30);
@ -461,7 +463,7 @@ public class LibvirtRestoreBackupCommandWrapperTest {
PrimaryDataStoreTO primaryDataStore = Mockito.mock(PrimaryDataStoreTO.class);
when(command.getRestoreVolumePools()).thenReturn(Arrays.asList(primaryDataStore));
lenient().when(command.getRestoreVolumePaths()).thenReturn(Arrays.asList("/var/lib/libvirt/images/volume-123"));
lenient().when(command.getRestoreVolumeUUID()).thenReturn("volume-123");
when(command.getBackupFiles()).thenReturn(Arrays.asList("volume-123"));
lenient().when(command.getVmState()).thenReturn(VirtualMachine.State.Running);
lenient().when(command.getMountTimeout()).thenReturn(30);
@ -499,6 +501,7 @@ public class LibvirtRestoreBackupCommandWrapperTest {
"/var/lib/libvirt/images/volume-456"
));
when(command.getBackupVolumesUUIDs()).thenReturn(Arrays.asList("volume-123", "volume-456"));
when(command.getBackupFiles()).thenReturn(Arrays.asList("volume-123", "volume-456"));
when(command.getMountTimeout()).thenReturn(30);
try (MockedStatic<Files> filesMock = mockStatic(Files.class)) {

View File

@ -59,7 +59,7 @@ public final class CitrixModifyStoragePoolCommandWrapper extends CommandWrapper<
if (capacity == -1) {
final String msg = "Pool capacity is -1! pool: " + pool.getHost() + pool.getPath();
logger.warn(msg);
return new Answer(command, false, msg);
return new ModifyStoragePoolAnswer(command, false, msg);
}
final Map<String, TemplateProp> tInfo = new HashMap<String, TemplateProp>();
final ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(command, capacity, available, tInfo);
@ -68,12 +68,12 @@ public final class CitrixModifyStoragePoolCommandWrapper extends CommandWrapper<
final String msg = "ModifyStoragePoolCommand add XenAPIException:" + e.toString() + " host:" + citrixResourceBase.getHost().getUuid() + " pool: " + pool.getHost()
+ pool.getPath();
logger.warn(msg, e);
return new Answer(command, false, msg);
return new ModifyStoragePoolAnswer(command, false, msg);
} catch (final Exception e) {
final String msg = "ModifyStoragePoolCommand add XenAPIException:" + e.getMessage() + " host:" + citrixResourceBase.getHost().getUuid() + " pool: "
+ pool.getHost() + pool.getPath();
logger.warn(msg, e);
return new Answer(command, false, msg);
return new ModifyStoragePoolAnswer(command, false, msg);
}
} else {
try {
@ -85,17 +85,17 @@ public final class CitrixModifyStoragePoolCommandWrapper extends CommandWrapper<
if (result == null || !result.split("#")[1].equals("0")) {
throw new CloudRuntimeException("Unable to remove heartbeat file entry for SR " + srUuid + " due to " + result);
}
return new Answer(command, true, "success");
return new ModifyStoragePoolAnswer(command, true, "success");
} catch (final XenAPIException e) {
final String msg = "ModifyStoragePoolCommand remove XenAPIException:" + e.toString() + " host:" + citrixResourceBase.getHost().getUuid() + " pool: "
+ pool.getHost() + pool.getPath();
logger.warn(msg, e);
return new Answer(command, false, msg);
return new ModifyStoragePoolAnswer(command, false, msg);
} catch (final Exception e) {
final String msg = "ModifyStoragePoolCommand remove XenAPIException:" + e.getMessage() + " host:" + citrixResourceBase.getHost().getUuid() + " pool: "
+ pool.getHost() + pool.getPath();
logger.warn(msg, e);
return new Answer(command, false, msg);
return new ModifyStoragePoolAnswer(command, false, msg);
}
}
}

View File

@ -17,6 +17,7 @@
package org.apache.cloudstack.metrics;
import java.math.BigDecimal;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@ -26,6 +27,7 @@ import java.util.stream.Collectors;
import javax.inject.Inject;
import org.apache.cloudstack.ca.CAManager;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
import org.apache.commons.lang3.StringUtils;
@ -133,6 +135,8 @@ public class PrometheusExporterImpl extends ManagerBase implements PrometheusExp
private ResourceCountDao _resourceCountDao;
@Inject
private HostTagsDao _hostTagsDao;
@Inject
private CAManager caManager;
public PrometheusExporterImpl() {
super();
@ -216,6 +220,9 @@ public class PrometheusExporterImpl extends ManagerBase implements PrometheusExp
}
metricsList.add(new ItemHostVM(zoneName, zoneUuid, host.getName(), host.getUuid(), host.getPrivateIpAddress(), vmDao.listByHostId(host.getId()).size()));
addSSLCertificateExpirationMetrics(metricsList, zoneName, zoneUuid, host);
final CapacityVO coreCapacity = capacityDao.findByHostIdType(host.getId(), Capacity.CAPACITY_TYPE_CPU_CORE);
if (coreCapacity == null && !host.isInMaintenanceStates()){
@ -253,6 +260,18 @@ public class PrometheusExporterImpl extends ManagerBase implements PrometheusExp
addHostTagsMetrics(metricsList, dcId, zoneName, zoneUuid, totalHosts, upHosts, downHosts, total, up, down);
}
private void addSSLCertificateExpirationMetrics(List<Item> metricsList, String zoneName, String zoneUuid, HostVO host) {
if (caManager == null || caManager.getActiveCertificatesMap() == null) {
return;
}
X509Certificate cert = caManager.getActiveCertificatesMap().getOrDefault(host.getPrivateIpAddress(), null);
if (cert == null) {
return;
}
long certExpiryEpoch = cert.getNotAfter().getTime() / 1000; // Convert to epoch seconds
metricsList.add(new ItemHostCertExpiry(zoneName, zoneUuid, host.getName(), host.getUuid(), host.getPrivateIpAddress(), certExpiryEpoch));
}
private String markTagMaps(HostVO host, Map<String, Integer> totalHosts, Map<String, Integer> upHosts, Map<String, Integer> downHosts) {
List<HostTagVO> hostTagVOS = _hostTagsDao.getHostTags(host.getId());
List<String> hostTags = new ArrayList<>();
@ -1137,4 +1156,28 @@ public class PrometheusExporterImpl extends ManagerBase implements PrometheusExp
return String.format("%s{zone=\"%s\",cpu=\"%d\",memory=\"%d\"} %d", name, zoneName, cpu, memory, total);
}
}
class ItemHostCertExpiry extends Item {
String zoneName;
String zoneUuid;
String hostName;
String hostUuid;
String hostIp;
long expiryTimestamp;
public ItemHostCertExpiry(final String zoneName, final String zoneUuid, final String hostName, final String hostUuid, final String hostIp, final long expiry) {
super("cloudstack_host_cert_expiry_timestamp", "Host certificate expiry timestamp in seconds since epoch", "gauge");
this.zoneName = zoneName;
this.zoneUuid = zoneUuid;
this.hostName = hostName;
this.hostUuid = hostUuid;
this.hostIp = hostIp;
this.expiryTimestamp = expiry;
}
@Override
public String toMetricsString() {
return String.format("%s{zone=\"%s\",hostname=\"%s\",ip=\"%s\"} %d", name, zoneName, hostName, hostIp, expiryTimestamp);
}
}
}

View File

@ -0,0 +1,108 @@
// 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.metrics;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class PrometheusExporterImplTest {
private static final String TEST_ZONE_NAME = "zone1";
private static final String TEST_ZONE_UUID = "zone-uuid-1";
private static final String TEST_HOST_NAME = "host1";
private static final String TEST_HOST_UUID = "host-uuid-1";
private static final String TEST_HOST_IP = "192.168.1.10";
private static final long CERT_EXPIRY_TIME = 1735689600000L; // 2025-01-01 00:00:00 UTC
private static final long CERT_EXPIRY_EPOCH = CERT_EXPIRY_TIME / 1000;
@Test
public void testItemHostCertExpiryFormat() {
PrometheusExporterImpl exporter = new PrometheusExporterImpl();
PrometheusExporterImpl.ItemHostCertExpiry item = exporter.new ItemHostCertExpiry(
TEST_ZONE_NAME,
TEST_ZONE_UUID,
TEST_HOST_NAME,
TEST_HOST_UUID,
TEST_HOST_IP,
CERT_EXPIRY_EPOCH
);
String metricsString = item.toMetricsString();
String expected = String.format(
"cloudstack_host_cert_expiry_timestamp{zone=\"%s\",hostname=\"%s\",ip=\"%s\"} %d",
TEST_ZONE_NAME,
TEST_HOST_NAME,
TEST_HOST_IP,
CERT_EXPIRY_EPOCH
);
assertEquals("Certificate expiry metric format should match expected format", expected, metricsString);
}
@Test
public void testItemHostCertExpiryContainsCorrectMetricName() {
PrometheusExporterImpl exporter = new PrometheusExporterImpl();
PrometheusExporterImpl.ItemHostCertExpiry item = exporter.new ItemHostCertExpiry(
TEST_ZONE_NAME,
TEST_ZONE_UUID,
TEST_HOST_NAME,
TEST_HOST_UUID,
TEST_HOST_IP,
CERT_EXPIRY_EPOCH
);
String metricsString = item.toMetricsString();
assertTrue("Metric should contain correct metric name",
metricsString.contains("cloudstack_host_cert_expiry_timestamp"));
}
@Test
public void testItemHostCertExpiryContainsAllLabels() {
PrometheusExporterImpl exporter = new PrometheusExporterImpl();
PrometheusExporterImpl.ItemHostCertExpiry item = exporter.new ItemHostCertExpiry(
TEST_ZONE_NAME,
TEST_ZONE_UUID,
TEST_HOST_NAME,
TEST_HOST_UUID,
TEST_HOST_IP,
CERT_EXPIRY_EPOCH
);
String metricsString = item.toMetricsString();
assertTrue("Metric should contain zone label", metricsString.contains("zone=\"" + TEST_ZONE_NAME + "\""));
assertTrue("Metric should contain hostname label", metricsString.contains("hostname=\"" + TEST_HOST_NAME + "\""));
assertTrue("Metric should contain ip label", metricsString.contains("ip=\"" + TEST_HOST_IP + "\""));
}
@Test
public void testItemHostCertExpiryContainsTimestampValue() {
PrometheusExporterImpl exporter = new PrometheusExporterImpl();
PrometheusExporterImpl.ItemHostCertExpiry item = exporter.new ItemHostCertExpiry(
TEST_ZONE_NAME,
TEST_ZONE_UUID,
TEST_HOST_NAME,
TEST_HOST_UUID,
TEST_HOST_IP,
CERT_EXPIRY_EPOCH
);
String metricsString = item.toMetricsString();
assertTrue("Metric should contain correct timestamp value",
metricsString.endsWith(" " + CERT_EXPIRY_EPOCH));
}
}

View File

@ -131,7 +131,7 @@ public class MockAccountManager extends ManagerBase implements AccountManager {
}
@Override
public User createUser(String arg0, String arg1, String arg2, String arg3, String arg4, String arg5, String arg6, Long arg7, String arg8) {
public User createUser(String arg0, String arg1, String arg2, String arg3, String arg4, String arg5, String arg6, Long arg7, String arg8, boolean arg9) {
// TODO Auto-generated method stub
return null;
}

View File

@ -34,6 +34,8 @@ import org.apache.cloudstack.api.auth.APIAuthenticationType;
import org.apache.cloudstack.api.auth.APIAuthenticator;
import org.apache.cloudstack.api.auth.PluggableAPIAuthenticator;
import org.apache.cloudstack.api.response.LoginCmdResponse;
import org.apache.cloudstack.resourcedetail.UserDetailVO;
import org.apache.cloudstack.resourcedetail.dao.UserDetailsDao;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.Nullable;
@ -74,6 +76,9 @@ public class OauthLoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent
@Inject
ApiServerService _apiServer;
@Inject
UserDetailsDao userDetailsDao;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -157,8 +162,10 @@ public class OauthLoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent
if (userAccount != null && User.Source.SAML2 == userAccount.getSource()) {
throw new CloudAuthenticationException("User is not allowed CloudStack login");
}
return ApiResponseSerializer.toSerializedString(_apiServer.loginUser(session, userAccount.getUsername(), null, domainId, domain, remoteAddress, params),
serializedResponse = ApiResponseSerializer.toSerializedString(_apiServer.loginUser(session, userAccount.getUsername(), null, domainId, domain, remoteAddress, params),
responseType);
userDetailsDao.addDetail(userAccount.getId(), UserDetailVO.OauthLogin, "true", false);
return serializedResponse;
} catch (final CloudAuthenticationException ex) {
ApiServlet.invalidateHttpSession(session, "fall through to API key,");
String msg = String.format("%s", ex.getMessage() != null ?
@ -177,12 +184,8 @@ public class OauthLoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent
protected Long getDomainIdFromParams(Map<String, Object[]> params, StringBuilder auditTrailSb, String responseType) {
String[] domainIdArr = (String[])params.get(ApiConstants.DOMAIN_ID);
if (domainIdArr == null) {
domainIdArr = (String[])params.get(ApiConstants.DOMAIN__ID);
}
Long domainId = null;
if ((domainIdArr != null) && (domainIdArr.length > 0)) {
if (domainIdArr != null && domainIdArr.length > 0) {
try {
//check if UUID is passed in for domain
domainId = _apiServer.fetchDomainId(domainIdArr[0]);

View File

@ -158,11 +158,17 @@ public class SAML2LoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent
String domainPath = null;
if (params.containsKey(ApiConstants.IDP_ID)) {
idpId = ((String[])params.get(ApiConstants.IDP_ID))[0];
String[] idpIds = (String[])params.get(ApiConstants.IDP_ID);
if (idpIds != null && idpIds.length > 0) {
idpId = idpIds[0];
}
}
if (params.containsKey(ApiConstants.DOMAIN)) {
domainPath = ((String[])params.get(ApiConstants.DOMAIN))[0];
String[] domainPaths = (String[])params.get(ApiConstants.DOMAIN);
if (domainPaths != null && domainPaths.length > 0) {
domainPath = domainPaths[0];
}
}
if (domainPath != null && !domainPath.isEmpty()) {

View File

@ -1087,6 +1087,10 @@
<exclude>utils/testsmallfileinactive</exclude>
<exclude>**/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker</exclude>
<exclude>.github/workflows/dependabot.yaml</exclude>
<exclude>.gitattributes</exclude>
<exclude>.github/workflows/*.md</exclude>
<exclude>.github/workflows/*.lock.ya?ml</exclude>
<exclude>.github/aw/**</exclude>
</excludes>
</configuration>
</plugin>

View File

@ -116,9 +116,11 @@ import org.apache.cloudstack.framework.messagebus.MessageBus;
import org.apache.cloudstack.framework.messagebus.MessageDispatcher;
import org.apache.cloudstack.framework.messagebus.MessageHandler;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.resourcedetail.UserDetailVO;
import org.apache.cloudstack.user.UserPasswordResetManager;
import org.apache.cloudstack.utils.identity.ManagementServerNode;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.EnumUtils;
import org.apache.http.ConnectionClosedException;
import org.apache.http.HttpException;
@ -194,6 +196,7 @@ import com.cloud.utils.net.NetUtils;
import com.google.gson.reflect.TypeToken;
import static com.cloud.user.AccountManagerImpl.apiKeyAccess;
import static org.apache.cloudstack.api.ApiConstants.PASSWORD_CHANGE_REQUIRED;
import static org.apache.cloudstack.user.UserPasswordResetManager.UserPasswordResetEnabled;
@Component
@ -1227,6 +1230,9 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
if (ApiConstants.MANAGEMENT_SERVER_ID.equalsIgnoreCase(attrName)) {
response.setManagementServerId(attrObj.toString());
}
if (PASSWORD_CHANGE_REQUIRED.equalsIgnoreCase(attrName) && attrObj instanceof Boolean) {
response.setPasswordChangeRequired((Boolean) attrObj);
}
}
}
response.setResponseName("loginresponse");
@ -1327,6 +1333,13 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
final String sessionKey = Base64.encodeBase64URLSafeString(sessionKeyBytes);
session.setAttribute(ApiConstants.SESSIONKEY, sessionKey);
Map<String, String> userAccDetails = userAcct.getDetails();
if (MapUtils.isNotEmpty(userAccDetails)) {
String needPwdChangeStr = userAccDetails.get(UserDetailVO.PasswordChangeRequired);
if ("true".equalsIgnoreCase(needPwdChangeStr)) {
session.setAttribute(PASSWORD_CHANGE_REQUIRED, true);
}
}
return createLoginResponse(session);
}
throw new CloudAuthenticationException("Failed to authenticate user " + username + " in domain " + domainId + "; please provide valid credentials");

View File

@ -38,6 +38,7 @@ import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.cloudstack.api.APICommand;
import com.cloud.api.auth.DefaultForgotPasswordAPIAuthenticatorCmd;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.ApiServerService;
@ -200,7 +201,6 @@ public class ApiServlet extends HttpServlet {
LOGGER.warn(message);
}
});
}
void processRequestInContext(final HttpServletRequest req, final HttpServletResponse resp) {
@ -273,7 +273,6 @@ public class ApiServlet extends HttpServlet {
}
if (command != null && !command.equals(ValidateUserTwoFactorAuthenticationCodeCmd.APINAME)) {
APIAuthenticator apiAuthenticator = authManager.getAPIAuthenticator(command);
if (apiAuthenticator != null) {
auditTrailSb.append("command=");
@ -309,7 +308,9 @@ public class ApiServlet extends HttpServlet {
} catch (ServerApiException e) {
httpResponseCode = e.getErrorCode().getHttpCode();
responseString = e.getMessage();
LOGGER.debug("Authentication failure: " + e.getMessage());
if (!DefaultForgotPasswordAPIAuthenticatorCmd.APINAME.equalsIgnoreCase(command) || StringUtils.isNotBlank(username)) {
LOGGER.debug("Authentication failure: {}", e.getMessage());
}
}
if (apiAuthenticator.getAPIType() == APIAuthenticationType.LOGOUT_API) {
@ -390,7 +391,7 @@ public class ApiServlet extends HttpServlet {
}
}
if (! requestChecksoutAsSane(resp, auditTrailSb, responseType, params, session, command, userId, account, accountObj))
if (!requestChecksoutAsSane(resp, auditTrailSb, responseType, params, session, command, userId, account, accountObj))
return;
} else {
CallContext.register(accountMgr.getSystemUser(), accountMgr.getSystemAccount());
@ -422,7 +423,6 @@ public class ApiServlet extends HttpServlet {
apiServer.getSerializedApiError(HttpServletResponse.SC_UNAUTHORIZED, "unable to verify user credentials and/or request signature", params,
responseType);
HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_UNAUTHORIZED, responseType, ApiServer.JSONcontentType.value());
}
} catch (final ServerApiException se) {
final String serializedResponseText = apiServer.getSerializedApiError(se, params, responseType);
@ -653,6 +653,9 @@ public class ApiServlet extends HttpServlet {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(msg);
}
if (session == null) {
return;
}
session.invalidate();
} catch (final IllegalStateException ise) {
if (LOGGER.isTraceEnabled()) {

View File

@ -44,13 +44,13 @@ import java.net.InetAddress;
import java.util.List;
import java.util.Map;
@APICommand(name = "forgotPassword",
@APICommand(name = DefaultForgotPasswordAPIAuthenticatorCmd.APINAME,
description = "Sends an email to the user with a token to reset the password using resetPassword command.",
since = "4.20.0.0",
requestHasSensitiveInfo = true,
responseObject = SuccessResponse.class)
public class DefaultForgotPasswordAPIAuthenticatorCmd extends BaseCmd implements APIAuthenticator {
public static final String APINAME = "forgotPassword";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
@ -108,10 +108,12 @@ public class DefaultForgotPasswordAPIAuthenticatorCmd extends BaseCmd implements
if (userDomain != null) {
domainId = userDomain.getId();
} else {
logger.debug("Unable to find the domain from the path {}", domain);
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, String.format("Unable to find the domain from the path %s", domain));
}
final UserAccount userAccount = _accountService.getActiveUserAccount(username[0], domainId);
if (userAccount != null && List.of(User.Source.SAML2, User.Source.OAUTH2, User.Source.LDAP).contains(userAccount.getSource())) {
logger.debug("Forgot Password is not allowed for the user {} from source {}", username[0], userAccount.getSource());
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Forgot Password is not allowed for this user");
}
boolean success = _apiServer.forgotPassword(userAccount, userDomain);

View File

@ -34,6 +34,8 @@ import org.apache.cloudstack.api.auth.APIAuthenticationType;
import org.apache.cloudstack.api.auth.APIAuthenticator;
import org.apache.cloudstack.api.auth.PluggableAPIAuthenticator;
import org.apache.cloudstack.api.response.LoginCmdResponse;
import org.apache.cloudstack.resourcedetail.UserDetailVO;
import org.apache.cloudstack.resourcedetail.dao.UserDetailsDao;
import org.jetbrains.annotations.Nullable;
import javax.inject.Inject;
@ -47,7 +49,6 @@ import java.net.InetAddress;
@APICommand(name = "login", description = "Logs a user into the CloudStack. A successful login attempt will generate a JSESSIONID cookie value that can be passed in subsequent Query command calls until the \"logout\" command has been issued or the session has expired.", requestHasSensitiveInfo = true, responseObject = LoginCmdResponse.class, entityType = {})
public class DefaultLoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthenticator {
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ -66,6 +67,9 @@ public class DefaultLoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthe
@Inject
ApiServerService _apiServer;
@Inject
UserDetailsDao userDetailsDao;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -107,17 +111,13 @@ public class DefaultLoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthe
if (HTTPMethod.valueOf(req.getMethod()) != HTTPMethod.POST) {
throw new ServerApiException(ApiErrorCode.METHOD_NOT_ALLOWED, "Please use HTTP POST to authenticate using this API");
}
// FIXME: ported from ApiServlet, refactor and cleanup
final String[] username = (String[])params.get(ApiConstants.USERNAME);
final String[] password = (String[])params.get(ApiConstants.PASSWORD);
String[] domainIdArr = (String[])params.get(ApiConstants.DOMAIN_ID);
if (domainIdArr == null) {
domainIdArr = (String[])params.get(ApiConstants.DOMAIN__ID);
}
final String[] domainName = (String[])params.get(ApiConstants.DOMAIN);
final String[] domainIdArr = (String[])params.get(ApiConstants.DOMAIN_ID);
Long domainId = null;
if ((domainIdArr != null) && (domainIdArr.length > 0)) {
if (domainIdArr != null && domainIdArr.length > 0) {
try {
//check if UUID is passed in for domain
domainId = _apiServer.fetchDomainId(domainIdArr[0]);
@ -135,6 +135,7 @@ public class DefaultLoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthe
}
String domain = null;
final String[] domainName = (String[])params.get(ApiConstants.DOMAIN);
domain = getDomainName(auditTrailSb, domainName, domain);
String serializedResponse = null;
@ -151,8 +152,10 @@ public class DefaultLoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthe
if (userAccount != null && User.Source.SAML2 == userAccount.getSource()) {
throw new CloudAuthenticationException("User is not allowed CloudStack login");
}
return ApiResponseSerializer.toSerializedString(_apiServer.loginUser(session, username[0], pwd, domainId, domain, remoteAddress, params),
serializedResponse = ApiResponseSerializer.toSerializedString(_apiServer.loginUser(session, username[0], pwd, domainId, domain, remoteAddress, params),
responseType);
userDetailsDao.removeDetail(userAccount.getId(), UserDetailVO.OauthLogin);
return serializedResponse;
} catch (final CloudAuthenticationException ex) {
ApiServlet.invalidateHttpSession(session, "fall through to API key,");
// TODO: fall through to API key, or just fail here w/ auth error? (HTTP 401)

View File

@ -53,7 +53,6 @@ import java.util.Map;
responseObject = SuccessResponse.class)
public class DefaultResetPasswordAPIAuthenticatorCmd extends BaseCmd implements APIAuthenticator {
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////

View File

@ -107,6 +107,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.framework.config.ConfigDepot;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.framework.config.ValidatedConfigKey;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDao;
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDao;
@ -764,6 +765,12 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
throw new InvalidParameterValueException(validationMsg);
}
ConfigKey<?> configKey = _configDepot.get(name);
if (configKey instanceof ValidatedConfigKey) {
ValidatedConfigKey<?> validatedConfigKey = (ValidatedConfigKey<?>) configKey;
validatedConfigKey.validateValue(value);
}
// If scope of the parameter is given then it needs to be updated in the
// corresponding details table,
// if scope is mentioned as global or not mentioned then it is normal

View File

@ -272,7 +272,12 @@ public abstract class LibvirtServerDiscoverer extends DiscovererBase implements
}
}
sshConnection = new Connection(agentIp, 22);
int port = uri.getPort();
if (port <= 0) {
port = AgentManager.KVMHostDiscoverySshPort.valueIn(clusterId);
}
sshConnection = new Connection(agentIp, port);
sshConnection.connect(null, 60000, 60000);
@ -380,6 +385,9 @@ public abstract class LibvirtServerDiscoverer extends DiscovererBase implements
Map<String, String> hostDetails = connectedHost.getDetails();
hostDetails.put("password", password);
hostDetails.put("username", username);
if (uri.getPort() > 0) {
hostDetails.put(Host.HOST_SSH_PORT, String.valueOf(uri.getPort()));
}
_hostDao.saveDetails(connectedHost);
return resources;
} catch (DiscoveredWithErrorException e) {

View File

@ -851,7 +851,6 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
_clusterDetailsDao.persist(cluster_cpu_detail);
_clusterDetailsDao.persist(cluster_memory_detail);
}
}
uri = validatedHostUrl(url, hypervisorType);
@ -945,7 +944,6 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
hosts.add(host);
}
discoverer.postDiscovery(hosts, _nodeId);
}
logger.info("server resources successfully discovered by " + discoverer.getName());
return hosts;
@ -3149,15 +3147,26 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
private HostVO getNewHost(StartupCommand[] startupCommands) {
StartupCommand startupCommand = startupCommands[0];
HostVO host = findHostByGuid(startupCommand.getGuid());
String fullGuid = startupCommand.getGuid();
logger.debug(String.format("Trying to find Host by guid %s", fullGuid));
HostVO host = findHostByGuid(fullGuid);
if (host != null) {
logger.debug(String.format("Found Host by guid %s: %s", fullGuid, host));
return host;
}
host = findHostByGuid(startupCommand.getGuidWithoutResource());
String guidPrefix = startupCommand.getGuidWithoutResource();
logger.debug(String.format("Trying to find Host by guid prefix %s", guidPrefix));
host = findHostByGuidPrefix(guidPrefix);
return host; // even when host == null!
if (host != null) {
logger.debug(String.format("Found Host by guid prefix %s: %s", guidPrefix, host));
return host;
}
logger.debug(String.format("Could not find Host by guid %s", fullGuid));
return null;
}
protected HostVO createHostVO(final StartupCommand[] cmds, final ServerResource resource, final Map<String, String> details, List<String> hostTags,
@ -3862,7 +3871,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
*/
protected void connectAndRestartAgentOnHost(HostVO host, String username, String password, String privateKey) {
final com.trilead.ssh2.Connection connection = SSHCmdHelper.acquireAuthorizedConnection(
host.getPrivateIpAddress(), 22, username, password, privateKey);
host.getPrivateIpAddress(), _agentMgr.getHostSshPort(host), username, password, privateKey);
if (connection == null) {
throw new CloudRuntimeException(String.format("SSH to agent is enabled, but failed to connect to %s via IP address [%s].", host, host.getPrivateIpAddress()));
}
@ -4209,6 +4218,15 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
public HostVO findHostByGuid(final String guid) {
final QueryBuilder<HostVO> sc = QueryBuilder.create(HostVO.class);
sc.and(sc.entity().getGuid(), Op.EQ, guid);
sc.and(sc.entity().getRemoved(), Op.NULL);
return sc.find();
}
@Override
public HostVO findHostByGuidPrefix(String guid) {
final QueryBuilder<HostVO> sc = QueryBuilder.create(HostVO.class);
sc.and(sc.entity().getGuid(), Op.LIKE, guid + "%");
sc.and(sc.entity().getRemoved(), Op.NULL);
return sc.find();
}
@ -4216,6 +4234,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
public HostVO findHostByName(final String name) {
final QueryBuilder<HostVO> sc = QueryBuilder.create(HostVO.class);
sc.and(sc.entity().getName(), Op.EQ, name);
sc.and(sc.entity().getRemoved(), Op.NULL);
return sc.find();
}

View File

@ -43,6 +43,7 @@ import javax.crypto.spec.SecretKeySpec;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.network.vpc.VpcVO;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.affinity.AffinityGroupProcessor;
@ -2651,12 +2652,21 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
}
if (associatedNetworkId != null) {
_accountMgr.checkAccess(caller, null, false, networkDao.findById(associatedNetworkId));
sc.setParameters("associatedNetworkIdEq", associatedNetworkId);
NetworkVO associatedNetwork = networkDao.findById(associatedNetworkId);
if (associatedNetwork != null) {
_accountMgr.checkAccess(caller, null, false, associatedNetwork);
sc.setParameters("associatedNetworkIdEq", associatedNetworkId);
}
}
if (vpcId != null) {
_accountMgr.checkAccess(caller, null, false, _vpcDao.findById(vpcId));
sc.setParameters("vpcId", vpcId);
VpcVO vpc = _vpcDao.findById(vpcId);
if (vpc != null) {
_accountMgr.checkAccess(caller, null, false, vpc);
sc.setParameters("vpcId", vpcId);
}
}
addrs = _publicIpAddressDao.search(sc, searchFilter); // Allocated
@ -2673,12 +2683,15 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
}
if (associatedNetworkId != null) {
NetworkVO guestNetwork = networkDao.findById(associatedNetworkId);
if (zoneId == null) {
zoneId = guestNetwork.getDataCenterId();
} else if (zoneId != guestNetwork.getDataCenterId()) {
throw new InvalidParameterValueException("Please specify a valid associated network id in the specified zone.");
if (guestNetwork != null) {
if (zoneId == null) {
zoneId = guestNetwork.getDataCenterId();
} else if (zoneId != guestNetwork.getDataCenterId()) {
throw new InvalidParameterValueException("Please specify a valid associated network id in the specified zone.");
}
owner = _accountDao.findById(guestNetwork.getAccountId());
}
owner = _accountDao.findById(guestNetwork.getAccountId());
}
List<DataCenterVO> dcList = new ArrayList<>();
if (zoneId == null){

View File

@ -221,7 +221,6 @@ import com.cloud.vm.VirtualMachineProfileImpl;
import com.cloud.vm.VmDetailConstants;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.google.common.base.Joiner;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@ -1395,9 +1394,16 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
else {
vmInstanceVOList = _vmInstanceDao.listNonExpungedByTemplate(templateId);
}
if(!cmd.isForced() && CollectionUtils.isNotEmpty(vmInstanceVOList)) {
final String message = String.format("Unable to delete Template: %s because Instance: [%s] are using it.", template, Joiner.on(",").join(vmInstanceVOList));
logger.warn(message);
if (!cmd.isForced() && CollectionUtils.isNotEmpty(vmInstanceVOList)) {
String message = String.format("Unable to delete template [%s] because there are [%d] VM instances using it.", template, vmInstanceVOList.size());
String instancesListMessage = String.format(" Instances list: [%s].", StringUtils.join(vmInstanceVOList, ","));
logger.warn("{}{}", message, instancesListMessage);
if (_accountMgr.isRootAdmin(caller.getAccountId())) {
message += instancesListMessage;
}
throw new InvalidParameterValueException(message);
}

View File

@ -16,6 +16,8 @@
// under the License.
package com.cloud.user;
import static org.apache.cloudstack.resourcedetail.UserDetailVO.PasswordChangeRequired;
import java.net.InetAddress;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
@ -87,7 +89,6 @@ import org.apache.cloudstack.webhook.WebhookHelper;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
@ -180,6 +181,7 @@ import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
import com.cloud.utils.UuidUtils;
import com.cloud.utils.StringUtils;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.ManagerBase;
@ -227,7 +229,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
@Inject
private InstanceGroupDao _vmGroupDao;
@Inject
private UserAccountDao _userAccountDao;
private UserAccountDao userAccountDao;
@Inject
private VolumeDao _volumeDao;
@Inject
@ -591,11 +593,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
if (acct == null) {
return false; //account is deleted or does not exist
}
if ((isRootAdmin(accountId)) || (isDomainAdmin(accountId)) || (isResourceDomainAdmin(accountId))) {
return true;
} else if (acct.getType() == Account.Type.READ_ONLY_ADMIN) {
return true;
}
return (isRootAdmin(accountId)) || (isDomainAdmin(accountId)) || (isResourceDomainAdmin(accountId)) || (acct.getType() == Account.Type.READ_ONLY_ADMIN);
}
return false;
@ -650,10 +648,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
@Override
public boolean isNormalUser(long accountId) {
AccountVO acct = _accountDao.findById(accountId);
if (acct != null && acct.getType() == Account.Type.NORMAL) {
return true;
}
return false;
return acct != null && acct.getType() == Account.Type.NORMAL;
}
@Override
@ -684,10 +679,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
if (account == null) {
return false; //account is deleted or does not exist
}
if (isRootAdmin(accountId) || (account.getType() == Account.Type.ADMIN)) {
return true;
}
return false;
return isRootAdmin(accountId) || (account.getType() == Account.Type.ADMIN);
}
@Override
@ -718,7 +710,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
for (ControlledEntity entity : entities) {
if (ownerId == null) {
ownerId = entity.getAccountId();
} else if (ownerId.longValue() != entity.getAccountId()) {
} else if (! ownerId.equals(entity.getAccountId())) {
throw new PermissionDeniedException("Entity " + entity + " and entity " + prevEntity + " belong to different accounts");
}
prevEntity = entity;
@ -744,7 +736,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
domainId = account != null ? account.getDomainId() : -1;
}
if (entity.getAccountId() != -1 && domainId != -1 && !(entity instanceof VirtualMachineTemplate)
&& !(entity instanceof Network && accessType != null && (accessType == AccessType.UseEntry || accessType == AccessType.OperateEntry))
&& !(entity instanceof Network && (accessType == AccessType.UseEntry || accessType == AccessType.OperateEntry))
&& !(entity instanceof AffinityGroup) && !(entity instanceof VirtualRouter)
&& !(entity instanceof DnsServer)) {
List<ControlledEntity> toBeChecked = domains.get(entity.getDomainId());
@ -828,7 +820,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
// Currently just for resource domain admin
List<DataCenterVO> dcList = _dcDao.findZonesByDomainId(account.getDomainId());
if (dcList != null && dcList.size() != 0) {
if (CollectionUtils.isNotEmpty(dcList)) {
return dcList.get(0).getId();
} else {
throw new CloudRuntimeException("Failed to find any private zone for Resource domain admin.");
@ -843,23 +835,23 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
UserAccountVO user = null;
user = _userAccountDao.lockRow(id, true);
user = userAccountDao.lockRow(id, true);
user.setLoginAttempts(attempts);
if (toDisable) {
user.setState(State.DISABLED.toString());
}
_userAccountDao.update(id, user);
userAccountDao.update(id, user);
}
});
} catch (Exception e) {
logger.error("Failed to update login attempts for user {}", () -> _userAccountDao.findById(id));
logger.error("Failed to update login attempts for user {}", () -> userAccountDao.findById(id));
}
}
private boolean doSetUserStatus(long userId, State state) {
UserVO userForUpdate = _userDao.createForUpdate();
userForUpdate.setState(state);
return _userDao.update(Long.valueOf(userId), userForUpdate);
return _userDao.update(userId, userForUpdate);
}
@Override
@ -868,7 +860,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
AccountVO acctForUpdate = _accountDao.createForUpdate();
acctForUpdate.setState(State.ENABLED);
acctForUpdate.setNeedsCleanup(false);
success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
success = _accountDao.update(accountId, acctForUpdate);
return success;
}
@ -881,7 +873,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
} else if (account.getState().equals(State.ENABLED)) {
AccountVO acctForUpdate = _accountDao.createForUpdate();
acctForUpdate.setState(State.LOCKED);
success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
success = _accountDao.update(accountId, acctForUpdate);
} else {
if (logger.isInfoEnabled()) {
logger.info("Attempting to lock a non-enabled account {}, current state is {}, locking failed.", account, account.getState());
@ -995,7 +987,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
}
// Destroy VM Snapshots
List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.listByAccountId(Long.valueOf(accountId));
List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.listByAccountId(accountId);
for (VMSnapshot vmSnapshot : vmSnapshots) {
try {
_vmSnapshotMgr.deleteVMSnapshot(vmSnapshot.getId());
@ -1017,8 +1009,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
try {
_vmMgr.destroyVm(vm.getId(), false);
} catch (Exception e) {
e.printStackTrace();
logger.warn("Failed destroying instance {} as part of account deletion.", vm);
logger.warn("Failed destroying instance {} as part of account deletion.", vm, e);
}
}
// no need to catch exception at this place as expunging vm
@ -1076,7 +1067,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
logger.debug("Deleting networks for account {}", account);
List<NetworkVO> networks = _networkDao.listByOwner(accountId);
if (networks != null) {
Collections.sort(networks, new Comparator<>() {
networks.sort(new Comparator<>() {
@Override
public int compare(NetworkVO network1, NetworkVO network2) {
if (network1.getGuestType() != network2.getGuestType() && Network.GuestType.Isolated.equals(network2.getGuestType())) {
@ -1247,7 +1238,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
} else {
AccountVO acctForUpdate = _accountDao.createForUpdate();
acctForUpdate.setState(State.DISABLED);
success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
success = _accountDao.update(accountId, acctForUpdate);
if (success) {
boolean disableAccountResult = false;
@ -1341,11 +1332,11 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
// Check permissions
checkAccess(getCurrentCallingAccount(), domain);
if (!userAllowMultipleAccounts.valueInScope(ConfigKey.Scope.Domain, domainId) && !_userAccountDao.validateUsernameInDomain(userName, domainId)) {
if (!userAllowMultipleAccounts.valueInScope(ConfigKey.Scope.Domain, domainId) && !userAccountDao.validateUsernameInDomain(userName, domainId)) {
throw new InvalidParameterValueException(String.format("The user %s already exists in domain %s", userName, domain));
}
if (networkDomain != null && networkDomain.length() > 0) {
if (StringUtils.isNotEmpty(networkDomain)) {
if (!NetUtils.verifyDomainName(networkDomain)) {
throw new InvalidParameterValueException(
"Invalid network domain. Total length shouldn't exceed 190 chars. Each domain label must be between 1 and 63 characters long, can contain ASCII letters 'a' through 'z', the digits '0' through '9', "
@ -1397,7 +1388,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
CallContext.current().putContextParameter(User.class, userId);
// check success
return _userAccountDao.findById(userId);
return userAccountDao.findById(userId);
}
/*
@ -1511,12 +1502,24 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
@Override
@ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User")
public UserVO createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId, String userUUID,
User.Source source) {
User.Source source) {
return createUser(userName, password, firstName, lastName, email, timeZone, accountName, domainId, userUUID, source, false);
}
@ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User")
public UserVO createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId, String userUUID,
User.Source source, boolean isPasswordChangeRequired) {
// default domain to ROOT if not specified
if (domainId == null) {
domainId = Domain.ROOT_DOMAIN;
}
if (isPasswordChangeRequired && (source == User.Source.SAML2 || source == User.Source.SAML2DISABLED || source == User.Source.LDAP)) {
logger.warn("Enforcing password change is not permitted for source [{}].", source);
throw new InvalidParameterValueException("CloudStack does not support enforcing password change for SAML or LDAP users.");
}
Domain domain = _domainMgr.getDomain(domainId);
if (domain == null) {
throw new CloudRuntimeException("The domain " + domainId + " does not exist; unable to create user");
@ -1535,7 +1538,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
throw new PermissionDeniedException(String.format("Account: %s is a system account, can't add a user to it", account));
}
if (!userAllowMultipleAccounts.valueInScope(ConfigKey.Scope.Domain, domainId) && !_userAccountDao.validateUsernameInDomain(userName, domainId)) {
if (!userAllowMultipleAccounts.valueInScope(ConfigKey.Scope.Domain, domainId) && !userAccountDao.validateUsernameInDomain(userName, domainId)) {
throw new CloudRuntimeException("The user " + userName + " already exists in domain " + domainId);
}
List<UserVO> duplicatedUsers = _userDao.findUsersByName(userName);
@ -1547,14 +1550,21 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
verifyCallerPrivilegeForUserOrAccountOperations(account);
UserVO user;
user = createUser(account.getId(), userName, password, firstName, lastName, email, timeZone, userUUID, source);
if (isPasswordChangeRequired) {
long callerAccountId = CallContext.current().getCallingAccountId();
if ((isRootAdmin(callerAccountId) || isDomainAdmin(callerAccountId))) {
_userDetailsDao.addDetail(user.getId(), PasswordChangeRequired, "true", false);
}
}
return user;
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User")
public UserVO createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId, String userUUID) {
public UserVO createUser(String userName, String password, String firstName, String lastName, String email,
String timeZone, String accountName, Long domainId, String userUUID, boolean isPasswordChangeRequired) {
return createUser(userName, password, firstName, lastName, email, timeZone, accountName, domainId, userUUID, User.Source.UNKNOWN);
return createUser(userName, password, firstName, lastName, email, timeZone, accountName, domainId, userUUID, User.Source.UNKNOWN, isPasswordChangeRequired);
}
@Override
@ -1588,8 +1598,39 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
if (mandate2FA != null && mandate2FA) {
user.setUser2faEnabled(true);
}
validateAndUpdatePasswordChangeRequired(caller, updateUserCmd, user, account);
_userDao.update(user.getId(), user);
return _userAccountDao.findById(user.getId());
return userAccountDao.findById(user.getId());
}
private void validateAndUpdatePasswordChangeRequired(User caller, UpdateUserCmd updateUserCmd, UserVO user, Account account) {
if (updateUserCmd.isPasswordChangeRequired()) {
if (user.getState() != State.ENABLED || account.getState() != State.ENABLED) {
throw new CloudRuntimeException("CloudStack does not support enforcing password change for locked/disabled User or Account.");
}
User.Source userSource = user.getSource();
if (userSource == User.Source.SAML2 || userSource == User.Source.SAML2DISABLED || userSource == User.Source.LDAP) {
logger.warn("Enforcing password change is not permitted for source [{}].", user.getSource());
throw new InvalidParameterValueException("CloudStack does not support enforcing password change for SAML or LDAP users.");
}
}
boolean isCallerSameAsUser = user.getId() == caller.getId();
boolean isPasswordResetRequired = updateUserCmd.isPasswordChangeRequired() && !isCallerSameAsUser;
// Admins only can enforce passwordChangeRequired for user
if (isRootAdmin(caller.getAccountId()) || isDomainAdmin(caller.getAccountId())) {
if (isPasswordResetRequired) {
_userDetailsDao.addDetail(user.getId(), PasswordChangeRequired, "true", false);
}
}
if (StringUtils.isNotBlank(updateUserCmd.getPassword())) {
// Remove passwordChangeRequired if user updating own pwd or admin has not enforced it
if (isCallerSameAsUser || !isPasswordResetRequired) {
_userDetailsDao.removeDetail(user.getId(), PasswordChangeRequired);
}
}
}
@Override
@ -1871,10 +1912,9 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
if (isApiKeyBlank && isSecretKeyBlank) {
return;
}
Pair<User, Account> apiKeyOwner = _accountDao.findUserAccountByApiKey(apiKey);
UserAccount apiKeyOwner = userAccountDao.getUserByApiKey(apiKey);
if (apiKeyOwner != null) {
User userThatHasTheProvidedApiKey = apiKeyOwner.first();
if (userThatHasTheProvidedApiKey.getId() != user.getId()) {
if (apiKeyOwner.getId() != user.getId()) {
throw new InvalidParameterValueException(String.format("The API key [%s] already exists in the system. Please provide a unique key.", apiKey));
}
}
@ -1962,7 +2002,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
CallContext.current().putContextParameter(User.class, user.getUuid());
// user successfully disabled
return _userAccountDao.findById(userId);
return userAccountDao.findById(userId);
} else {
throw new CloudRuntimeException(String.format("Unable to disable user %s", user));
}
@ -2016,7 +2056,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
CallContext.current().putContextParameter(User.class, user.getUuid());
return _userAccountDao.findById(userId);
return userAccountDao.findById(userId);
} else {
throw new CloudRuntimeException(String.format("Unable to enable user %s", user));
}
@ -2057,7 +2097,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
boolean success;
if (user.getState().equals(State.LOCKED)) {
// already locked...no-op
return _userAccountDao.findById(userId);
return userAccountDao.findById(userId);
} else if (user.getState().equals(State.ENABLED)) {
success = doSetUserStatus(user.getId(), State.LOCKED);
@ -2084,7 +2124,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
CallContext.current().putContextParameter(User.class, user.getUuid());
return _userAccountDao.findById(userId);
return userAccountDao.findById(userId);
} else {
throw new CloudRuntimeException(String.format("Unable to lock user %s", user));
}
@ -2612,7 +2652,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
return owner;
} else if (!isAdmin(caller.getId()) && accountName != null && domainId != null) {
if (!accountName.equals(caller.getAccountName()) || domainId.longValue() != caller.getDomainId()) {
if (!accountName.equals(caller.getAccountName()) || domainId != caller.getDomainId()) {
throw new PermissionDeniedException("Can't create/list resources for account " + accountName + " in domain " + domainId + ", permission denied");
} else {
return caller;
@ -2637,12 +2677,12 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
@Override
public UserAccount getActiveUserAccount(String username, Long domainId) {
return _userAccountDao.getUserAccount(username, domainId);
return userAccountDao.getUserAccount(username, domainId);
}
@Override
public List<UserAccount> getActiveUserAccountByEmail(String email, Long domainId) {
List<UserAccountVO> userAccountByEmail = _userAccountDao.getUserAccountByEmail(email, domainId);
List<UserAccountVO> userAccountByEmail = userAccountDao.getUserAccountByEmail(email, domainId);
List<UserAccount> userAccounts = userAccountByEmail.stream()
.map(userAccountVO -> (UserAccount) userAccountVO)
.collect(Collectors.toList());
@ -2686,7 +2726,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
public void markUserRegistered(long userId) {
UserVO userForUpdate = _userDao.createForUpdate();
userForUpdate.setRegistered(true);
_userDao.update(Long.valueOf(userId), userForUpdate);
_userDao.update(userId, userForUpdate);
}
@Override
@ -2741,7 +2781,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
throw new CloudRuntimeException(String.format("Failed to create account name %s in domain id=%s", accountName, _domainMgr.getDomain(domainId)));
}
Long accountId = account.getId();
long accountId = account.getId();
if (details != null) {
_accountDetailsDao.persist(accountId, details);
@ -2790,7 +2830,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
@Override
public void logoutUser(long userId) {
UserAccount userAcct = _userAccountDao.findById(userId);
UserAccount userAcct = userAccountDao.findById(userId);
if (userAcct != null) {
ActionEventUtils.onActionEvent(userId, userAcct.getAccountId(), userAcct.getDomainId(), EventTypes.EVENT_USER_LOGOUT, "user has logged out", userId, ApiCommandResourceType.User.toString());
} // else log some kind of error event? This likely means the user doesn't exist, or has been deleted...
@ -2832,11 +2872,11 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
final Boolean ApiSourceCidrChecksEnabled = ApiServiceConfiguration.ApiSourceCidrChecksEnabled.value();
if (ApiSourceCidrChecksEnabled) {
logger.debug("CIDRs from which account '" + account.toString() + "' is allowed to perform API calls: " + accessAllowedCidrs);
logger.debug("CIDRs from which account '{}' is allowed to perform API calls: {}", account.toString(), accessAllowedCidrs);
// Block when is not in the list of allowed IPs
if (!NetUtils.isIpInCidrList(loginIpAddress, accessAllowedCidrs.split(","))) {
logger.warn("Request by account '" + account.toString() + "' was denied since " + loginIpAddress.toString().replace("/", "") + " does not match " + accessAllowedCidrs);
logger.warn("Request by account '{}' was denied since {} does not match {}", account.toString(), loginIpAddress.toString().replace("/", ""), accessAllowedCidrs);
throw new CloudAuthenticationException("Failed to authenticate user '" + username + "' in domain '" + domain.getPath() + "' from ip "
+ loginIpAddress.toString().replace("/", "") + "; please provide valid credentials");
}
@ -2850,6 +2890,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
logger.debug(String.format("User: %s in domain %d has successfully logged in, auth time duration - %d ms", username, domainId, validUserLastAuthTimeDurationInMs));
}
user.setDetails(_userDetailsDao.listDetailsKeyPairs(user.getId()));
return user;
} else {
if (logger.isDebugEnabled()) {
@ -2868,6 +2910,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
try {
Thread.sleep(waitTimeDurationInMs);
} catch (final InterruptedException e) {
// ignored
}
}
@ -2879,7 +2922,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
if (logger.isDebugEnabled()) {
logger.debug("Attempting to log in user: " + username + " in domain " + domainId);
}
UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId);
UserAccount userAccount = userAccountDao.getUserAccount(username, domainId);
boolean authenticated = false;
HashSet<ActionOnFailedAuthentication> actionsOnFailedAuthenticaion = new HashSet<>();
@ -2909,11 +2952,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
if (authenticated) {
Domain domain = _domainMgr.getDomain(domainId);
String domainName = null;
if (domain != null) {
domainName = domain.getName();
}
userAccount = _userAccountDao.getUserAccount(username, domainId);
userAccount = userAccountDao.getUserAccount(username, domainId);
if (!userAccount.getState().equalsIgnoreCase(Account.State.ENABLED.toString()) || !userAccount.getAccountState().equalsIgnoreCase(Account.State.ENABLED.toString())) {
if (logger.isInfoEnabled()) {
@ -2973,11 +3012,9 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
// - build a request string with sorted params, make sure it's all lowercase
// - sign the request, verify the signature is the same
List<String> parameterNames = new ArrayList<>();
for (Object paramNameObj : requestParameters.keySet()) {
parameterNames.add((String)paramNameObj); // put the name in a list that we'll sort later
}
// put the name in a list that we'll sort later
List<String> parameterNames = new ArrayList<>(requestParameters.keySet());
Collections.sort(parameterNames);
@ -3009,7 +3046,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
if (unsignedRequestBuffer.length() != 0) {
unsignedRequestBuffer.append("&");
}
unsignedRequestBuffer.append(paramName).append("=").append(URLEncoder.encode(paramValue, "UTF-8"));
unsignedRequestBuffer.append(paramName).append("=").append(URLEncoder.encode(paramValue, com.cloud.utils.StringUtils.getPreferredCharset()));
}
}
@ -3032,7 +3069,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
if (!equalSig) {
logger.info("User signature: " + signature + " is not equaled to computed signature: " + computedSignature);
} else {
user = _userAccountDao.getUserAccount(username, domainId);
user = userAccountDao.getUserAccount(username, domainId);
}
} catch (Exception ex) {
logger.error("Exception authenticating user", ex);
@ -3060,7 +3097,14 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
@Override
public Pair<User, Account> findUserByApiKey(String apiKey) {
return _accountDao.findUserAccountByApiKey(apiKey);
UserAccount userAccount = userAccountDao.getUserByApiKey(apiKey);
if (userAccount != null) {
User user = _userDao.getUser(userAccount.getId());
Account account = _accountDao.findById(userAccount.getAccountId());
return new Pair<>(user, account);
} else {
return null;
}
}
@Override
@ -3194,14 +3238,14 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
UserVO updatedUser = _userDao.createForUpdate();
String encodedKey;
Pair<User, Account> userAcct;
UserAccount userAcct;
int retryLimit = 10;
do {
// FIXME: what algorithm should we use for API keys?
KeyGenerator generator = KeyGenerator.getInstance("HmacSHA1");
SecretKey key = generator.generateKey();
encodedKey = Base64.encodeBase64URLSafeString(key.getEncoded());
userAcct = _accountDao.findUserAccountByApiKey(encodedKey);
userAcct = userAccountDao.getUserByApiKey(encodedKey);
retryLimit--;
} while ((userAcct != null) && (retryLimit >= 0));
@ -3212,7 +3256,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
_userDao.update(userId, updatedUser);
return encodedKey;
} catch (NoSuchAlgorithmException ex) {
logger.error("error generating secret key for user {}", _userAccountDao.findById(userId), ex);
logger.error("error generating secret key for user {}", userAccountDao.findById(userId), ex);
}
return null;
}
@ -3239,7 +3283,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
_userDao.update(userId, updatedUser);
return encodedKey;
} catch (NoSuchAlgorithmException ex) {
logger.error("error generating secret key for user {}", _userAccountDao.findById(userId), ex);
logger.error("error generating secret key for user {}", userAccountDao.findById(userId), ex);
}
return null;
}
@ -3450,12 +3494,12 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
@Override
public UserAccount getUserByApiKey(String apiKey) {
return _userAccountDao.getUserByApiKey(apiKey);
return userAccountDao.getUserByApiKey(apiKey);
}
@Override
public List<String> listAclGroupsByAccount(Long accountId) {
if (_querySelectors == null || _querySelectors.size() == 0) {
if (CollectionUtils.isEmpty(_querySelectors)) {
return new ArrayList<>();
}
@ -3510,7 +3554,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
@Override
public UserAccount getUserAccountById(Long userId) {
UserAccount userAccount = _userAccountDao.findById(userId);
UserAccount userAccount = userAccountDao.findById(userId);
Map<String, String> details = _userDetailsDao.listDetailsKeyPairs(userId);
userAccount.setDetails(details);
@ -3699,7 +3743,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
}
protected UserTwoFactorAuthenticationSetupResponse enableTwoFactorAuthentication(Long userId, String providerName) {
UserAccountVO userAccount = _userAccountDao.findById(userId);
UserAccountVO userAccount = userAccountDao.findById(userId);
UserVO userVO = _userDao.findById(userId);
Long domainId = userAccount.getDomainId();
if (Boolean.FALSE.equals(enableUserTwoFactorAuthentication.valueIn(domainId)) && Boolean.FALSE.equals(mandateUserTwoFactorAuthentication.valueIn(domainId))) {
@ -3791,11 +3835,11 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
if (userDetailVO != null) {
_userDetailsDao.remove(userDetailVO.getId());
}
UserAccountVO userAccountVO = _userAccountDao.findById(user.getId());
UserAccountVO userAccountVO = userAccountDao.findById(user.getId());
userAccountVO.setUser2faEnabled(false);
userAccountVO.setUser2faProvider(null);
userAccountVO.setKeyFor2fa(null);
_userAccountDao.update(user.getId(), userAccountVO);
userAccountDao.update(user.getId(), userAccountVO);
return userAccountVO;
});
}

View File

@ -1728,10 +1728,10 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
if (StringUtils.isEmpty(name)) {
throw new CloudRuntimeException("Invalid backup provider name provided");
}
if (!backupProvidersMap.containsKey(name)) {
throw new CloudRuntimeException("Failed to find backup provider by the name: " + name);
}
return backupProvidersMap.get(name);
if (!backupProvidersMap.containsKey(name)) {
throw new CloudRuntimeException("Failed to find backup provider by the name: " + name);
}
return backupProvidersMap.get(name);
}
@Override

View File

@ -139,23 +139,23 @@ public class HeuristicRuleHelper {
* @param presetVariables used for injecting in the JS interpreter.
*/
protected void injectPresetVariables(JsInterpreter jsInterpreter, PresetVariables presetVariables) {
jsInterpreter.injectVariable("secondaryStorages", presetVariables.getSecondaryStorages().toString());
jsInterpreter.injectVariable("secondaryStorages", presetVariables.getSecondaryStorages());
if (presetVariables.getTemplate() != null) {
jsInterpreter.injectVariable("template", presetVariables.getTemplate().toString());
jsInterpreter.injectVariable("iso", presetVariables.getTemplate().toString());
jsInterpreter.injectVariable("template", presetVariables.getTemplate());
jsInterpreter.injectVariable("iso", presetVariables.getTemplate());
}
if (presetVariables.getSnapshot() != null) {
jsInterpreter.injectVariable("snapshot", presetVariables.getSnapshot().toString());
jsInterpreter.injectVariable("snapshot", presetVariables.getSnapshot());
}
if (presetVariables.getVolume() != null) {
jsInterpreter.injectVariable("volume", presetVariables.getVolume().toString());
jsInterpreter.injectVariable("volume", presetVariables.getVolume());
}
if (presetVariables.getAccount() != null) {
jsInterpreter.injectVariable("account", presetVariables.getAccount().toString());
jsInterpreter.injectVariable("account", presetVariables.getAccount());
}
}
@ -185,8 +185,8 @@ public class HeuristicRuleHelper {
Template template = new Template();
template.setName(templateVO.getName());
template.setFormat(templateVO.getFormat());
template.setHypervisorType(templateVO.getHypervisorType());
template.setFormat(templateVO.getFormat().toString());
template.setHypervisorType(templateVO.getHypervisorType().toString());
return template;
}
@ -195,7 +195,7 @@ public class HeuristicRuleHelper {
Volume volumePresetVariable = new Volume();
volumePresetVariable.setName(volumeVO.getName());
volumePresetVariable.setFormat(volumeVO.getFormat());
volumePresetVariable.setFormat(volumeVO.getFormat().toString());
volumePresetVariable.setSize(volumeVO.getSize());
return volumePresetVariable;
@ -206,7 +206,7 @@ public class HeuristicRuleHelper {
snapshot.setName(snapshotInfo.getName());
snapshot.setSize(snapshotInfo.getSize());
snapshot.setHypervisorType(snapshotInfo.getHypervisorType());
snapshot.setHypervisorType(snapshotInfo.getHypervisorType().toString());
return snapshot;
}

View File

@ -27,7 +27,6 @@ public class Account extends GenericHeuristicPresetVariable {
public void setId(String id) {
this.id = id;
fieldNamesToIncludeInToString.add("id");
}
public Domain getDomain() {
@ -36,6 +35,5 @@ public class Account extends GenericHeuristicPresetVariable {
public void setDomain(Domain domain) {
this.domain = domain;
fieldNamesToIncludeInToString.add("domain");
}
}

View File

@ -25,6 +25,5 @@ public class Domain extends GenericHeuristicPresetVariable {
public void setId(String id) {
this.id = id;
fieldNamesToIncludeInToString.add("id");
}
}

View File

@ -16,15 +16,11 @@
// under the License.
package org.apache.cloudstack.storage.heuristics.presetvariables;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
public class GenericHeuristicPresetVariable {
protected transient Set<String> fieldNamesToIncludeInToString = new HashSet<>();
private String name;
public String getName() {
@ -33,15 +29,10 @@ public class GenericHeuristicPresetVariable {
public void setName(String name) {
this.name = name;
fieldNamesToIncludeInToString.add("name");
}
/***
* Converts the preset variable into a valid JSON object that will be injected into the JS interpreter.
* This method should not be overridden or changed.
*/
@Override
public final String toString() {
return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, fieldNamesToIncludeInToString.toArray(new String[0]));
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
}
}

View File

@ -32,7 +32,6 @@ public class SecondaryStorage extends GenericHeuristicPresetVariable {
public void setId(String id) {
this.id = id;
fieldNamesToIncludeInToString.add("id");
}
public Long getUsedDiskSize() {
@ -41,7 +40,6 @@ public class SecondaryStorage extends GenericHeuristicPresetVariable {
public void setUsedDiskSize(Long usedDiskSize) {
this.usedDiskSize = usedDiskSize;
fieldNamesToIncludeInToString.add("usedDiskSize");
}
public Long getTotalDiskSize() {
@ -50,7 +48,6 @@ public class SecondaryStorage extends GenericHeuristicPresetVariable {
public void setTotalDiskSize(Long totalDiskSize) {
this.totalDiskSize = totalDiskSize;
fieldNamesToIncludeInToString.add("totalDiskSize");
}
public String getProtocol() {
@ -59,6 +56,5 @@ public class SecondaryStorage extends GenericHeuristicPresetVariable {
public void setProtocol(String protocol) {
this.protocol = protocol;
fieldNamesToIncludeInToString.add("protocol");
}
}

View File

@ -16,13 +16,11 @@
// under the License.
package org.apache.cloudstack.storage.heuristics.presetvariables;
import com.cloud.hypervisor.Hypervisor;
public class Snapshot extends GenericHeuristicPresetVariable {
private Long size;
private Hypervisor.HypervisorType hypervisorType;
private String hypervisorType;
public Long getSize() {
return size;
@ -30,15 +28,13 @@ public class Snapshot extends GenericHeuristicPresetVariable {
public void setSize(Long size) {
this.size = size;
fieldNamesToIncludeInToString.add("size");
}
public Hypervisor.HypervisorType getHypervisorType() {
public String getHypervisorType() {
return hypervisorType;
}
public void setHypervisorType(Hypervisor.HypervisorType hypervisorType) {
public void setHypervisorType(String hypervisorType) {
this.hypervisorType = hypervisorType;
fieldNamesToIncludeInToString.add("hypervisorType");
}
}

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