You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ra...@apache.org on 2017/02/09 06:32:52 UTC
[2/4] git commit: updated refs/heads/master to e02003d
CLOUDSTACK-7985: (1) allow migrate vm from/to project; (2) UI change for selecting account/project/network
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/a1d2fba1
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/a1d2fba1
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/a1d2fba1
Branch: refs/heads/master
Commit: a1d2fba1d292185aa46258abea7cca823183abe4
Parents: 0db4471
Author: Wei Zhou <w....@tech.leaseweb.com>
Authored: Wed Sep 16 14:43:55 2015 +0200
Committer: Wei Zhou <w....@tech.leaseweb.com>
Committed: Tue Dec 27 11:58:25 2016 +0100
----------------------------------------------------------------------
.../api/command/admin/vm/AssignVMCmd.java | 12 +-
.../api/response/ProjectResponse.java | 8 +
.../cloud/api/query/dao/ProjectJoinDaoImpl.java | 1 +
server/src/com/cloud/vm/UserVmManagerImpl.java | 12 +-
server/test/com/cloud/vm/UserVmManagerTest.java | 2 +-
ui/scripts/instances.js | 224 ++++++++++++++++++-
6 files changed, 239 insertions(+), 20 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a1d2fba1/api/src/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java
index 435b7f1..96ded26 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java
@@ -29,6 +29,7 @@ import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.NetworkResponse;
+import org.apache.cloudstack.api.response.ProjectResponse;
import org.apache.cloudstack.api.response.SecurityGroupResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
@@ -58,12 +59,15 @@ public class AssignVMCmd extends BaseCmd {
description = "id of the VM to be moved")
private Long virtualMachineId;
- @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, required = true, description = "account name of the new VM owner.")
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "account name of the new VM owner.")
private String accountName;
- @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, required = true, description = "domain id of the new VM owner.")
+ @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "domain id of the new VM owner.")
private Long domainId;
+ @Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "an optional project for the new VM owner.")
+ private Long projectId;
+
//Network information
@Parameter(name = ApiConstants.NETWORK_IDS,
type = CommandType.LIST,
@@ -98,6 +102,10 @@ public class AssignVMCmd extends BaseCmd {
return domainId;
}
+ public Long getProjectId() {
+ return projectId;
+ }
+
public List<Long> getNetworkIds() {
return networkIds;
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a1d2fba1/api/src/org/apache/cloudstack/api/response/ProjectResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/ProjectResponse.java b/api/src/org/apache/cloudstack/api/response/ProjectResponse.java
index ad29d2b..0ae9e18 100644
--- a/api/src/org/apache/cloudstack/api/response/ProjectResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/ProjectResponse.java
@@ -56,6 +56,10 @@ public class ProjectResponse extends BaseResponse implements ResourceLimitAndCou
@Param(description = "the account name of the project's owner")
private String ownerName;
+ @SerializedName("projectaccountname")
+ @Param(description="the project account name of the project")
+ private String projectAccountName;
+
@SerializedName(ApiConstants.STATE)
@Param(description = "the state of the project")
private String state;
@@ -228,6 +232,10 @@ public class ProjectResponse extends BaseResponse implements ResourceLimitAndCou
ownerName = owner;
}
+ public void setProjectAccountName(String projectAccountName) {
+ this.projectAccountName = projectAccountName;
+ }
+
public void setState(String state) {
this.state = state;
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a1d2fba1/server/src/com/cloud/api/query/dao/ProjectJoinDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/dao/ProjectJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/ProjectJoinDaoImpl.java
index 65330ac..25598b3 100644
--- a/server/src/com/cloud/api/query/dao/ProjectJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/ProjectJoinDaoImpl.java
@@ -93,6 +93,7 @@ public class ProjectJoinDaoImpl extends GenericDaoBase<ProjectJoinVO, Long> impl
Account account = _accountDao.findByIdIncludingRemoved(proj.getProjectAccountId());
AccountJoinVO accountJn = ApiDBUtils.newAccountView(account);
_accountJoinDao.setResourceLimits(accountJn, false, response);
+ response.setProjectAccountName(accountJn.getAccountName());
response.setObjectName("project");
return response;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a1d2fba1/server/src/com/cloud/vm/UserVmManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index 453800d..6f0d498 100644
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -5048,14 +5048,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
if (oldAccount == null) {
throw new InvalidParameterValueException("Invalid account for VM " + vm.getAccountId() + " in domain.");
}
- // don't allow to move the vm from the project
- if (oldAccount.getType() == Account.ACCOUNT_TYPE_PROJECT) {
- InvalidParameterValueException ex = new InvalidParameterValueException("Specified Vm id belongs to the project and can't be moved");
- ex.addProxyObject(vm.getUuid(), "vmId");
- throw ex;
- }
- final Account newAccount = _accountService.getActiveAccountByName(cmd.getAccountName(), cmd.getDomainId());
- if (newAccount == null || newAccount.getType() == Account.ACCOUNT_TYPE_PROJECT) {
+ final Account newAccount = _accountMgr.finalizeOwner(caller, cmd.getAccountName(), cmd.getDomainId(), cmd.getProjectId());
+ if (newAccount == null) {
throw new InvalidParameterValueException("Invalid accountid=" + cmd.getAccountName() + " in domain " + cmd.getDomainId());
}
@@ -5356,7 +5350,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
s_logger.debug("AssignVM: Advance virtual, adding networks no " + networks.size() + " to " + vm.getInstanceName());
} // END IF NON SEC GRP ENABLED
} // END IF ADVANCED
- s_logger.info("AssignVM: vm " + vm.getInstanceName() + " now belongs to account " + cmd.getAccountName());
+ s_logger.info("AssignVM: vm " + vm.getInstanceName() + " now belongs to account " + newAccount.getAccountName());
return vm;
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a1d2fba1/server/test/com/cloud/vm/UserVmManagerTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vm/UserVmManagerTest.java b/server/test/com/cloud/vm/UserVmManagerTest.java
index 9df3f68..294a93a 100644
--- a/server/test/com/cloud/vm/UserVmManagerTest.java
+++ b/server/test/com/cloud/vm/UserVmManagerTest.java
@@ -690,7 +690,7 @@ public class UserVmManagerTest {
when(_accountService.getActiveAccountById(anyLong())).thenReturn(oldAccount);
- when(_accountService.getActiveAccountByName(anyString(), anyLong())).thenReturn(newAccount);
+ when(_accountMgr.finalizeOwner(any(Account.class), anyString(), anyLong(), anyLong())).thenReturn(newAccount);
doThrow(new PermissionDeniedException("Access check failed")).when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class),
any(ControlledEntity.class));
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a1d2fba1/ui/scripts/instances.js
----------------------------------------------------------------------
diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js
index 19db257..132801d 100644
--- a/ui/scripts/instances.js
+++ b/ui/scripts/instances.js
@@ -1905,7 +1905,32 @@
label: 'label.assign.instance.another',
createForm: {
title: 'label.assign.instance.another',
+ desc: 'Please specify the account type, domain, account name and network (optional) of the new account. <br> If the default nic of the vm is on a shared network, CloudStack will check if the network can be used by the new account if you do not specify one network. <br> If the default nic of the vm is on a isolated network, and the new account has more one isolated networks, you should specify one.',
fields: {
+ accountType: {
+ label: 'Account Type',
+ select: function(args) {
+ var items = [];
+ items.push({id: 'account', description: 'Account'});
+ items.push({id: 'project', description: 'Project'});
+ args.response.success({data: items});
+
+ args.$select.change(function() {
+ var $form = $(this).closest('form');
+ var $account = $form.find('.form-item[rel=account]');
+ var $project = $form.find('.form-item[rel=project]');
+
+ var accountType = $(this).val();
+ if (accountType == 'account') { // Account
+ $account.css('display', 'inline-block');
+ $project.hide();
+ } else if (accountType == 'project') { // Project
+ $project.css('display', 'inline-block');
+ $account.hide();
+ }
+ });
+ }
+ },
domainid: {
label: 'label.domain',
validation: {
@@ -1941,20 +1966,203 @@
},
account: {
label: 'label.account',
+ dependsOn: 'domainid',
validation: {
required: true
- }
- }
+ },
+ select: function(args) {
+ var dataObj = {
+ domainId: args.domainid,
+ state: 'Enabled',
+ listAll: true,
+ };
+ $.ajax({
+ url: createURL('listAccounts', {
+ ignoreProject: true
+ }),
+ data: dataObj,
+ success: function(json) {
+ accountObjs = json.listaccountsresponse.account;
+ var items = [{
+ id: null,
+ description: ''
+ }];
+ $(accountObjs).each(function() {
+ items.push({
+ id: this.name,
+ description: this.name
+ });
+ })
+
+ args.response.success({
+ data: items
+ });
+ }
+ });
+ },
+ },
+ project: {
+ label: 'label.project',
+ dependsOn: 'domainid',
+ validation: {
+ required: true
+ },
+ select: function(args) {
+ var dataObj = {
+ domainId: args.domainid,
+ state: 'Active',
+ listAll: true,
+ };
+ $.ajax({
+ url: createURL('listProjects', {
+ ignoreProject: true
+ }),
+ data: dataObj,
+ success: function(json) {
+ projectObjs = json.listprojectsresponse.project;
+ var items = [{
+ id: null,
+ description: ''
+ }];
+ $(projectObjs).each(function() {
+ items.push({
+ id: this.id,
+ description: this.name
+ });
+ })
+
+ args.response.success({
+ data: items
+ });
+ }
+ });
+ },
+ },
+ network: {
+ label: 'label.network',
+ dependsOn: ['accountType', 'domainid', 'account', 'project'],
+ select: function(args) {
+ var dataObj = {
+ domainId: args.domainid,
+ listAll: true,
+ isrecursive: false
+ };
+ if (args.data.accountType == 'account' && args.data.account != null && args.data.account != '') {
+ $.extend(dataObj, {
+ account: args.data.account
+ });
+ } else if (args.data.accountType == 'project' && args.data.project != null && args.data.project != '') {
+ $.extend(dataObj, {
+ projectid: args.data.project
+ });
+ } else {
+ args.response.success({
+ data: null
+ });
+ return;
+ }
+ $.ajax({
+ url: createURL('listNetworks', {
+ ignoreProject: true
+ }),
+ data: dataObj,
+ success: function(json) {
+ var networkObjs = json.listnetworksresponse.network;
+ var items = [{
+ id: null,
+ description: ''
+ }];
+ $(networkObjs).each(function() {
+ items.push({
+ id: this.id,
+ description: this.name
+ });
+ })
+
+ args.response.success({
+ data: items
+ });
+ }
+ });
+ },
+ },
+ securitygroup: {
+ label: 'label.security.group',
+ dependsOn: ['accountType', 'domainid', 'account', 'project'],
+ select: function(args) {
+ var dataObj = {
+ domainId: args.domainid,
+ listAll: true,
+ isrecursive: false
+ };
+ if (args.data.accountType == 'account' && args.data.account != null && args.data.account != '') {
+ $.extend(dataObj, {
+ account: args.data.account
+ });
+ } else if (args.data.accountType == 'project' && args.data.project != null && args.data.project != '') {
+ $.extend(dataObj, {
+ projectid: args.data.project
+ });
+ } else {
+ args.response.success({
+ data: null
+ });
+ return;
+ }
+ $.ajax({
+ url: createURL('listSecurityGroups', {
+ ignoreProject: true
+ }),
+ data: dataObj,
+ success: function(json) {
+ var sgObjs = json.listsecuritygroupsresponse.securitygroup;
+ var items = [{
+ id: null,
+ description: ''
+ }];
+ $(sgObjs).each(function() {
+ items.push({
+ id: this.id,
+ description: this.name
+ });
+ })
+
+ args.response.success({
+ data: items
+ });
+ }
+ });
+ },
+ },
}
},
action: function(args) {
- $.ajax({
- url: createURL('assignVirtualMachine'),
- data: {
- virtualmachineid: args.context.instances[0].id,
- domainid: args.data.domainid,
+ var dataObj = {
+ virtualmachineid: args.context.instances[0].id,
+ domainid: args.data.domainid,
+ };
+ var ignoreProject = false;
+ if (args.data.accountType == 'account') {
+ ignoreProject = true;
+ $.extend(dataObj, {
account: args.data.account
- },
+ });
+ } else if (args.data.accountType == 'project') {
+ $.extend(dataObj, {
+ projectid: args.data.project
+ });
+ }
+ if (args.data.network != null && args.data.network != '') {
+ $.extend(dataObj, {
+ networkIds: args.data.network
+ });
+ }
+
+ $.ajax({
+ url: createURL('assignVirtualMachine', {
+ ignoreProject: ignoreProject
+ }),
+ data: dataObj,
success: function(json) {
var item = json.assignvirtualmachineresponse.virtualmachine;
args.response.success({