You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ml...@apache.org on 2013/01/17 21:02:29 UTC
git commit: Summary: Initial code commit,
applying https://reviews.apache.org/r/9011/
Updated Branches:
refs/heads/add_remove_nics [created] c093d650c
Summary: Initial code commit, applying https://reviews.apache.org/r/9011/
Signed-off-by: Marcus Sorensen <ma...@betterservers.com> 1358452852 -0700
Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/c093d650
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/c093d650
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/c093d650
Branch: refs/heads/add_remove_nics
Commit: c093d650c716e57a9e5f1aecd0b54d6e4b73e9be
Parents: e37a823
Author: Marcus Sorensen <ma...@betterservers.com>
Authored: Thu Jan 17 13:00:52 2013 -0700
Committer: Marcus Sorensen <ma...@betterservers.com>
Committed: Thu Jan 17 13:00:52 2013 -0700
----------------------------------------------------------------------
api/src/com/cloud/vm/UserVmService.java | 21 ++
.../api/command/user/vm/AddNicToVMCmd.java | 111 +++++++
.../api/command/user/vm/RemoveNicFromVMCmd.java | 104 +++++++
.../command/user/vm/UpdateDefaultNicForVMCmd.java | 104 +++++++
client/tomcatconf/commands.properties.in | 4 +
.../src/com/cloud/network/NetworkManagerImpl.java | 3 +
server/src/com/cloud/vm/UserVmManagerImpl.java | 226 +++++++++++++++
server/src/com/cloud/vm/VirtualMachineManager.java | 12 +
.../com/cloud/vm/VirtualMachineManagerImpl.java | 57 +++-
.../test/com/cloud/vm/MockUserVmManagerImpl.java | 21 ++
.../cloud/vm/MockVirtualMachineManagerImpl.java | 9 +
11 files changed, 663 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c093d650/api/src/com/cloud/vm/UserVmService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/vm/UserVmService.java b/api/src/com/cloud/vm/UserVmService.java
index b1ebe10..e211692 100755
--- a/api/src/com/cloud/vm/UserVmService.java
+++ b/api/src/com/cloud/vm/UserVmService.java
@@ -113,6 +113,27 @@ public interface UserVmService {
UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException;
+ /**
+ * Adds a NIC on the given network to the virtual machine
+ * @param cmd the command object that defines the vm and the given network
+ * @return the vm object if successful, null otherwise
+ */
+ UserVm addNicToVirtualMachine(AddNicToVMCmd cmd);
+
+ /**
+ * Removes a NIC on the given network from the virtual machine
+ * @param cmd the command object that defines the vm and the given network
+ * @return the vm object if successful, null otherwise
+ */
+ UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd);
+
+ /**
+ * Updates default Nic to the given network for given virtual machine
+ * @param cmd the command object that defines the vm and the given network
+ * @return the vm object if successful, null otherwise
+ */
+ UserVm updateDefaultNicForVirtualMachine(UpdateDefaultNicForVMCmd cmd);
+
UserVm recoverVirtualMachine(RecoverVMCmd cmd) throws ResourceAllocationException;
/**
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c093d650/api/src/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java
new file mode 100644
index 0000000..af73328
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java
@@ -0,0 +1,111 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command.user.vm;
+
+import java.util.ArrayList;
+import java.util.EnumSet;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.*;
+import org.apache.cloudstack.api.ApiConstants.VMDetails;
+import org.apache.cloudstack.api.response.UserVmResponse;
+import org.apache.cloudstack.api.response.NetworkResponse;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+import com.cloud.uservm.UserVm;
+
+@APICommand(name = "addNicToVirtualMachine", description="Adds VM to specified network by creating a NIC", responseObject=UserVmResponse.class)
+
+public class AddNicToVMCmd extends BaseCmd {
+ public static final Logger s_logger = Logger.getLogger(AddNicToVMCmd.class);
+ private static final String s_name = "addnictovirtualmachineresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID, entityType=UserVmResponse.class,
+ required=true, description="Virtual Machine ID")
+ private Long vmId;
+
+ @Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.UUID, entityType=NetworkResponse.class,
+ required=true, description="Network ID")
+ private Long netId;
+
+ @Parameter(name=ApiConstants.IP_ADDRESS, type=CommandType.STRING, description="IP Address for the new network")
+ private String ipaddr;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getVmId() {
+ return vmId;
+ }
+
+ public Long getNetworkId() {
+ return netId;
+ }
+
+ public String getIpAddress() {
+ return ipaddr;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ public static String getResultObjectName() {
+ return "virtualmachine";
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ UserVm vm = _responseGenerator.findUserVmById(getVmId());
+ if (vm == null) {
+ return Account.ACCOUNT_ID_SYSTEM; // bad id given, parent this command to SYSTEM so ERROR events are tracked
+ }
+ return vm.getAccountId();
+ }
+
+ @Override
+ public void execute(){
+ UserContext.current().setEventDetails("Vm Id: "+getVmId());
+ UserVm result = _userVmService.addNicToVirtualMachine(this);
+ ArrayList<VMDetails> dc = new ArrayList<VMDetails>();
+ dc.add(VMDetails.valueOf("nics"));
+ EnumSet<VMDetails> details = EnumSet.copyOf(dc);
+ if (result != null){
+ UserVmResponse response = _responseGenerator.createUserVmResponse("virtualmachine", details, result).get(0);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add NIC to vm. Refer to server logs for details.");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c093d650/api/src/org/apache/cloudstack/api/command/user/vm/RemoveNicFromVMCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/RemoveNicFromVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/RemoveNicFromVMCmd.java
new file mode 100644
index 0000000..aea953a
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/vm/RemoveNicFromVMCmd.java
@@ -0,0 +1,104 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command.user.vm;
+
+import java.util.ArrayList;
+import java.util.EnumSet;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.*;
+import org.apache.cloudstack.api.ApiConstants.VMDetails;
+import org.apache.cloudstack.api.response.UserVmResponse;
+import org.apache.cloudstack.api.response.NetworkResponse;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+import com.cloud.uservm.UserVm;
+
+@APICommand(name = "removeNicFromVirtualMachine", description="Removes VM from specified network by deleting a NIC", responseObject=UserVmResponse.class)
+
+public class RemoveNicFromVMCmd extends BaseCmd {
+ public static final Logger s_logger = Logger.getLogger(RemoveNicFromVMCmd.class);
+ private static final String s_name = "removenicfromvirtualmachineresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID, entityType=UserVmResponse.class,
+ required=true, description="Virtual Machine ID")
+ private Long vmId;
+
+ @Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.UUID, entityType=NetworkResponse.class,
+ required=true, description="Network ID")
+ private Long netId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getVmId() {
+ return vmId;
+ }
+
+ public Long getNetworkId() {
+ return netId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ public static String getResultObjectName() {
+ return "virtualmachine";
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ UserVm vm = _responseGenerator.findUserVmById(getVmId());
+ if (vm == null) {
+ return Account.ACCOUNT_ID_SYSTEM; // bad id given, parent this command to SYSTEM so ERROR events are tracked
+ }
+ return vm.getAccountId();
+ }
+
+ @Override
+ public void execute(){
+ UserContext.current().setEventDetails("Vm Id: "+getVmId());
+ UserVm result = _userVmService.removeNicFromVirtualMachine(this);
+ ArrayList<VMDetails> dc = new ArrayList<VMDetails>();
+ dc.add(VMDetails.valueOf("nics"));
+ EnumSet<VMDetails> details = EnumSet.copyOf(dc);
+ if (result != null){
+ UserVmResponse response = _responseGenerator.createUserVmResponse("virtualmachine", details, result).get(0);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove NIC from vm, see error log for details");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c093d650/api/src/org/apache/cloudstack/api/command/user/vm/UpdateDefaultNicForVMCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/UpdateDefaultNicForVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/UpdateDefaultNicForVMCmd.java
new file mode 100644
index 0000000..19d3bdb
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/vm/UpdateDefaultNicForVMCmd.java
@@ -0,0 +1,104 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command.user.vm;
+
+import java.util.ArrayList;
+import java.util.EnumSet;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.*;
+import org.apache.cloudstack.api.ApiConstants.VMDetails;
+import org.apache.cloudstack.api.response.UserVmResponse;
+import org.apache.cloudstack.api.response.NetworkResponse;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+import com.cloud.uservm.UserVm;
+
+@APICommand(name = "updateDefaultNicForVirtualMachine", description="Changes the default NIC on a VM", responseObject=UserVmResponse.class)
+
+public class UpdateDefaultNicForVMCmd extends BaseCmd {
+ public static final Logger s_logger = Logger.getLogger(UpdateDefaultNicForVMCmd.class);
+ private static final String s_name = "updatedefaultnicforvirtualmachineresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID, entityType=UserVmResponse.class,
+ required=true, description="Virtual Machine ID")
+ private Long vmId;
+
+ @Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.UUID, entityType=NetworkResponse.class,
+ required=true, description="Network ID")
+ private Long netId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getVmId() {
+ return vmId;
+ }
+
+ public Long getNetworkId() {
+ return netId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ public static String getResultObjectName() {
+ return "virtualmachine";
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ UserVm vm = _responseGenerator.findUserVmById(getVmId());
+ if (vm == null) {
+ return Account.ACCOUNT_ID_SYSTEM; // bad id given, parent this command to SYSTEM so ERROR events are tracked
+ }
+ return vm.getAccountId();
+ }
+
+ @Override
+ public void execute(){
+ UserContext.current().setEventDetails("Vm Id: "+getVmId());
+ UserVm result = _userVmService.updateDefaultNicForVirtualMachine(this);
+ ArrayList<VMDetails> dc = new ArrayList<VMDetails>();
+ dc.add(VMDetails.valueOf("nics"));
+ EnumSet<VMDetails> details = EnumSet.copyOf(dc);
+ if (result != null){
+ UserVmResponse response = _responseGenerator.createUserVmResponse("virtualmachine", details, result).get(0);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to set default nic for VM. Refer to server logs for details.");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c093d650/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index 182cbd8..91b99dd 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -257,6 +257,10 @@ extractVolume=15
migrateVolume=15
resizeVolume=15
+addNicToVirtualMachine=15
+removeNicFromVirtualMachine=15
+updateDefaultNicForVirtualMachine=15
+
#### registration command: FIXME -- this really should be something in management server that
#### generates a new key for the user and they just have to
#### use that key...the key is stored in the db associated w/
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c093d650/server/src/com/cloud/network/NetworkManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java
index 0a1fcd7..fbb019a 100755
--- a/server/src/com/cloud/network/NetworkManagerImpl.java
+++ b/server/src/com/cloud/network/NetworkManagerImpl.java
@@ -2227,6 +2227,9 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
} else {
nic = _nicDao.findByInstanceIdAndNetworkId(networkId, vm.getId());
}
+ if (nic == null) {
+ return null;
+ }
NetworkVO network = _networksDao.findById(networkId);
Integer networkRate = getNetworkRate(network.getId(), vm.getId());
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c093d650/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 a6fbdb1..81008ee 100755
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -914,6 +914,232 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
return _vmDao.findById(vmInstance.getId());
}
+ @Override
+ public UserVm addNicToVirtualMachine(AddNicToVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, CloudRuntimeException {
+ Long vmId = cmd.getVmId();
+ Long networkId = cmd.getNetworkId();
+ String ipAddress = cmd.getIpAddress();
+ Account caller = UserContext.current().getCaller();
+
+ UserVmVO vmInstance = _vmDao.findById(vmId);
+ NetworkVO network = _networkDao.findById(networkId);
+
+ NicProfile profile = new NicProfile(null);
+ if(ipAddress != null) {
+ profile = new NicProfile(ipAddress);
+ }
+
+ if(vmInstance == null) {
+ throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
+ }
+
+ if(network == null) {
+ throw new InvalidParameterValueException("unable to find a network with id " + networkId);
+ }
+
+ // Perform permission check on VM
+ _accountMgr.checkAccess(caller, null, true, vmInstance);
+
+ // Perform account permission check on network
+ if (network.getGuestType() != Network.GuestType.Shared) {
+ // Check account permissions
+ List<NetworkVO> networkMap = _networkDao.listBy(caller.getId(), network.getId());
+ if (networkMap == null || networkMap.isEmpty()) {
+ throw new PermissionDeniedException("Unable to create a vm using network with id " + network.getId() + ", permission denied");
+ }
+ }
+
+ if (vmInstance.getState() != State.Stopped) {
+ s_logger.warn("VM is running, needs to be stopped in order to add nic");
+ throw new CloudRuntimeException(vmInstance + " currently in " + vmInstance.getState() + " state, operation can only execute when VM is Stopped");
+ }
+
+ //todo: any security group related checks
+ //todo: ensure network belongs in zone
+ //todo: check other nics for VPC networks (can only belong to one?)
+ //todo: verify unique hostname in network domain?
+
+ //verify that there isn't a NIC attached to network
+ if(_networkMgr.getNicInNetwork(vmInstance.getId(),network.getId()) != null){
+ throw new CloudRuntimeException("Unable to add NIC to " + vmInstance + " because it already has a NIC attached to " + network);
+ }
+
+ NicProfile guestNic = null;
+
+ try {
+ guestNic = _itMgr.addUserVmToNetwork(vmInstance, network, profile);
+ } catch (ResourceUnavailableException e) {
+ throw new CloudRuntimeException("Unable to add NIC to " + vmInstance + ": " + e);
+ } catch (InsufficientCapacityException e) {
+ throw new CloudRuntimeException("Insufficient capacity when adding NIC to " + vmInstance + ": " + e);
+ } catch (ConcurrentOperationException e) {
+ throw new CloudRuntimeException("Concurrent operations on adding NIC to " + vmInstance + ": " +e);
+ }
+ if (guestNic == null) {
+ throw new CloudRuntimeException("Unable to add NIC to " + vmInstance);
+ }
+
+ s_logger.debug("Successful addition of " + network + " from " + vmInstance);
+ return _vmDao.findById(vmInstance.getId());
+ }
+
+ @Override
+ public UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, CloudRuntimeException {
+ Long vmId = cmd.getVmId();
+ Long networkId = cmd.getNetworkId();
+ Account caller = UserContext.current().getCaller();
+
+ UserVmVO vmInstance = _vmDao.findById(vmId);
+ NetworkVO network = _networkDao.findById(networkId);
+
+ if(vmInstance == null) {
+ throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
+ }
+
+ if(network == null) {
+ throw new InvalidParameterValueException("unable to find a network with id " + networkId);
+ }
+
+ // Perform permission check on VM
+ _accountMgr.checkAccess(caller, null, true, vmInstance);
+
+ // Perform account permission check on network
+ if (network.getGuestType() != Network.GuestType.Shared) {
+ // Check account permissions
+ List<NetworkVO> networkMap = _networkDao.listBy(caller.getId(), network.getId());
+ if (networkMap == null || networkMap.isEmpty()) {
+ throw new PermissionDeniedException("Unable to create a vm using network with id " + network.getId() + ", permission denied");
+ }
+ }
+
+ if (vmInstance.getState() != State.Stopped) {
+ s_logger.warn("VM is running, needs to be stopped in order to remove nic");
+ throw new CloudRuntimeException(vmInstance + " currently in " + vmInstance.getState() + " state, operation can only execute when VM is Stopped");
+ }
+
+ //todo: any security group related checks
+ //todo: ensure network belongs in zone
+ //todo: check other nics for VPC networks (can only belong to one?)
+ //todo: verify unique hostname in network domain?
+ boolean nicremoved = false;
+
+ try {
+ nicremoved = _itMgr.removeVmFromNetwork(vmInstance, network, null);
+ } catch (ResourceUnavailableException e) {
+ throw new CloudRuntimeException("Unable to remove " + network + " from " + vmInstance +": " + e);
+
+ } catch (ConcurrentOperationException e) {
+ throw new CloudRuntimeException("Concurrent operations on removing " + network + " from " + vmInstance + ": " + e);
+ }
+
+ if (!nicremoved) {
+ throw new CloudRuntimeException("Unable to remove " + network + " from " + vmInstance );
+ }
+
+ s_logger.debug("Successful removal of " + network + " from " + vmInstance);
+ return _vmDao.findById(vmInstance.getId());
+
+
+ }
+
+ @Override
+ public UserVm updateDefaultNicForVirtualMachine(UpdateDefaultNicForVMCmd cmd) throws InvalidParameterValueException, CloudRuntimeException {
+ Long vmId = cmd.getVmId();
+ Long networkId = cmd.getNetworkId();
+ Account caller = UserContext.current().getCaller();
+
+ UserVmVO vmInstance = _vmDao.findById(vmId);
+ NetworkVO network = _networkDao.findById(networkId);
+
+
+ if (vmInstance == null){
+ throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
+ }
+
+ if (network == null){
+ throw new InvalidParameterValueException("unable to find a network with id " + networkId);
+ }
+
+ // Perform permission check on VM
+ _accountMgr.checkAccess(caller, null, true, vmInstance);
+
+ if(vmInstance.getState() != State.Stopped){
+ s_logger.warn("VM is running, needs to be stopped in order to change default nic");
+ throw new CloudRuntimeException(vmInstance + " currently in " + vmInstance.getState() + " state, operation can only execute when VM is Stopped");
+ }
+
+ // no need to check permissions for network, we'll enumerate the ones they already have access to
+ Network existingdefaultnet = _networkMgr.getDefaultNetworkForVm(vmId);
+
+ // if current default equals chosen new default, return and do nothing
+ if (existingdefaultnet == network){
+ s_logger.warn("Skipping updateDefaultNicForVirtualMachine, selected network matches existing default");
+ return _vmDao.findById(vmInstance.getId());
+ }
+ else {
+ s_logger.debug("looks like we want to change from " + existingdefaultnet + " to " + network);
+ }
+
+ NicProfile chosen = _networkMgr.getNicProfile(vmInstance, network.getId(), null);
+ NicProfile existing = _networkMgr.getNicProfile(vmInstance, existingdefaultnet.getId(), null);
+
+ // if we can't find the chosen nic, fail!
+ if (chosen == null){
+ throw new CloudRuntimeException("Failed to find an existing nic for " + vmInstance +" on " + network);
+ }
+ else if (chosen.id == existing.id){
+ throw new CloudRuntimeException("refusing to set default nic because chosen network is already the default");
+ }
+ else {
+ s_logger.debug("chosen nic profile found was "+chosen+" with dev id "+chosen.deviceId+" and nic id "+chosen.id);
+ }
+ if (existing == null){
+ s_logger.warn("Failed to update default nic, no nic profile found for existing default network");
+ throw new CloudRuntimeException("Failed to find a nic profile for the existing default network. This is bad and probably means some sort of configuration corruption");
+ }
+
+ NicVO chosenVO = _nicDao.findById(chosen.id);
+ NicVO existingVO = _nicDao.findById(existing.id);
+ Integer chosenID = chosen.getDeviceId();
+ Integer existingID = existing.getDeviceId();
+
+ chosenVO.setDefaultNic(true);
+ chosenVO.setDeviceId(existingID);
+ existingVO.setDefaultNic(false);
+ existingVO.setDeviceId(chosenID);
+
+ chosenVO = _nicDao.persist(chosenVO);
+ existingVO = _nicDao.persist(existingVO);
+
+ Network newdefault = null;
+ newdefault = _networkMgr.getDefaultNetworkForVm(vmId);
+
+ if (newdefault == null){
+ chosenVO.setDefaultNic(false);
+ chosenVO.setDeviceId(chosenID);
+ existingVO.setDefaultNic(true);
+ existingVO.setDeviceId(existingID);
+
+ chosenVO = _nicDao.persist(chosenVO);
+ existingVO = _nicDao.persist(existingVO);
+
+ newdefault = _networkMgr.getDefaultNetworkForVm(vmId);
+ if (newdefault.getId() == existingdefaultnet.getId()) {
+ throw new CloudRuntimeException("Setting a default nic failed, and we had no default nic, but we were able to set it back to the original");
+ }
+ throw new CloudRuntimeException("Failed to change default nic to " + network + " and now we have no default");
+ } else if (newdefault.getId() != networkId){
+ if(newdefault.getId() == existingdefaultnet.getId()) {
+ throw new CloudRuntimeException("Default nic did not change from previous setting");
+ }
+ throw new CloudRuntimeException("Failed to change default nic to " + network + " with id "+ networkId + ", current default is " + newdefault+ " id " + newdefault.getId());
+ } else if (newdefault.getId() == networkId ) {
+ s_logger.debug("successfully set default network to " + network + " for " + vmInstance);
+ return _vmDao.findById(vmInstance.getId());
+ }
+
+ throw new CloudRuntimeException("something strange happened, new default net is not null, not equal to chosen network, not NOT equal to chosen net");
+ }
@Override
public HashMap<Long, VmStatsEntry> getVirtualMachineStatistics(long hostId, String hostName, List<Long> vmIds) throws CloudRuntimeException {
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c093d650/server/src/com/cloud/vm/VirtualMachineManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/VirtualMachineManager.java b/server/src/com/cloud/vm/VirtualMachineManager.java
index 4f04617..aa7e166 100644
--- a/server/src/com/cloud/vm/VirtualMachineManager.java
+++ b/server/src/com/cloud/vm/VirtualMachineManager.java
@@ -155,6 +155,18 @@ public interface VirtualMachineManager extends Manager {
/**
* @param vm
* @param network
+ * @param requested TODO
+ * @return
+ * @throws ConcurrentOperationException
+ * @throws ResourceUnavailableException
+ * @throws InsufficientCapacityException
+ */
+ NicProfile addUserVmToNetwork(VirtualMachine vm, Network network, NicProfile requested) throws ConcurrentOperationException,
+ ResourceUnavailableException, InsufficientCapacityException;
+
+ /**
+ * @param vm
+ * @param network
* @param broadcastUri TODO
* @return
* @throws ResourceUnavailableException
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c093d650/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 4d94fc5..c1a9b3a 100755
--- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -2503,6 +2503,27 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
}
}
+ @Override
+ public NicProfile addUserVmToNetwork(VirtualMachine vm, Network network, NicProfile requested) throws ConcurrentOperationException,
+ ResourceUnavailableException, InsufficientCapacityException {
+
+ s_logger.debug("Adding vm " + vm + " to network " + network + "; requested nic profile " + requested);
+ VMInstanceVO vmVO = _vmDao.findById(vm.getId());
+ ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM),
+ _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM));
+
+ VirtualMachineProfileImpl<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(vmVO, null,
+ null, null, null);
+
+ if (vm.getState() == State.Stopped) {
+ //1) allocate nic
+ return _networkMgr.createNicForVm(network, requested, context, vmProfile, false);
+ } else {
+ s_logger.warn("Unable to add vm " + vm + " to network " + network);
+ throw new ResourceUnavailableException("Unable to add vm " + vm + " to network, is not in the right state",
+ DataCenter.class, vm.getDataCenterIdToDeployIn());
+ }
+ }
@Override
public NicTO toNicTO(NicProfile nic, HypervisorType hypervisorType) {
@@ -2535,21 +2556,38 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
} else {
nic = _networkMgr.getNicInNetwork(vm.getId(), network.getId());
}
+
+ if (nic == null){
+ s_logger.warn("Could not get a nic with " + network);
+ return false;
+ }
+ // don't delete default NIC on a user VM
+ if (nic.isDefaultNic() && vm.getType() == VirtualMachine.Type.User ) {
+ s_logger.warn("Failed to remove nic from " + vm + " in " + network + ", nic is default.");
+ throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + ", nic is default.");
+ }
+
NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(),
_networkMgr.getNetworkRate(network.getId(), vm.getId()),
_networkMgr.isSecurityGroupSupportedInNetwork(network),
_networkMgr.getNetworkTag(vmProfile.getVirtualMachine().getHypervisorType(), network));
//1) Unplug the nic
- NicTO nicTO = toNicTO(nicProfile, vmProfile.getVirtualMachine().getHypervisorType());
- s_logger.debug("Un-plugging nic for vm " + vm + " from network " + network);
- boolean result = vmGuru.unplugNic(network, nicTO, vmTO, context, dest);
- if (result) {
- s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network );
- } else {
- s_logger.warn("Failed to unplug nic for the vm " + vm + " from network " + network);
- return false;
+ if (vm.getState() == State.Running) {
+ NicTO nicTO = toNicTO(nicProfile, vmProfile.getVirtualMachine().getHypervisorType());
+ s_logger.debug("Un-plugging nic for vm " + vm + " from network " + network);
+ boolean result = vmGuru.unplugNic(network, nicTO, vmTO, context, dest);
+ if (result) {
+ s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network );
+ } else {
+ s_logger.warn("Failed to unplug nic for the vm " + vm + " from network " + network);
+ return false;
+ }
+ } else if (vm.getState() != State.Stopped) {
+ s_logger.warn("Unable to remove vm " + vm + " from network " + network);
+ throw new ResourceUnavailableException("Unable to remove vm " + vm + " from network, is not in the right state",
+ DataCenter.class, vm.getDataCenterIdToDeployIn());
}
//2) Release the nic
@@ -2558,7 +2596,8 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
//3) Remove the nic
_networkMgr.removeNic(vmProfile, nic);
- return result;
+ _nicsDao.expunge(nic.getId());
+ return true;
}
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c093d650/server/test/com/cloud/vm/MockUserVmManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vm/MockUserVmManagerImpl.java b/server/test/com/cloud/vm/MockUserVmManagerImpl.java
index 27508b1..f424e65 100644
--- a/server/test/com/cloud/vm/MockUserVmManagerImpl.java
+++ b/server/test/com/cloud/vm/MockUserVmManagerImpl.java
@@ -55,6 +55,8 @@ import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.exception.VirtualMachineMigrationException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.PermissionDeniedException;
import com.cloud.host.Host;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
@@ -69,6 +71,7 @@ import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair;
import com.cloud.utils.component.Manager;
import com.cloud.utils.exception.ExecutionException;
+import com.cloud.utils.exception.CloudRuntimeException;
@Local(value = { UserVmManager.class, UserVmService.class })
public class MockUserVmManagerImpl implements UserVmManager, UserVmService, Manager {
@@ -277,6 +280,24 @@ public class MockUserVmManagerImpl implements UserVmManager, UserVmService, Mana
}
@Override
+ public UserVm addNicToVirtualMachine(AddNicToVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, CloudRuntimeException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, CloudRuntimeException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public UserVm updateDefaultNicForVirtualMachine(UpdateDefaultNicForVMCmd cmd) throws InvalidParameterValueException, CloudRuntimeException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
public UserVm recoverVirtualMachine(RecoverVMCmd cmd) throws ResourceAllocationException {
// TODO Auto-generated method stub
return null;
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c093d650/server/test/com/cloud/vm/MockVirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vm/MockVirtualMachineManagerImpl.java b/server/test/com/cloud/vm/MockVirtualMachineManagerImpl.java
index 6723198..75d90aa 100755
--- a/server/test/com/cloud/vm/MockVirtualMachineManagerImpl.java
+++ b/server/test/com/cloud/vm/MockVirtualMachineManagerImpl.java
@@ -271,6 +271,15 @@ public class MockVirtualMachineManagerImpl implements VirtualMachineManager {
}
/* (non-Javadoc)
+ * @see com.cloud.vm.VirtualMachineManager#addVmToNetwork(com.cloud.vm.VirtualMachine, com.cloud.network.Network, com.cloud.vm.NicProfile)
+ */
+ @Override
+ public NicProfile addUserVmToNetwork(VirtualMachine vm, Network network, NicProfile requested) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
* @see com.cloud.vm.VirtualMachineManager#removeVmFromNetwork(com.cloud.vm.VirtualMachine, com.cloud.network.Network, java.net.URI)
*/
@Override