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({