Summary: add/remove/update default nics feature

Description: Adds API calls updateDefaultNicForVirtualMachine,
addNicToVirtualMachine, and removeNicFromVirtualMachine. These are
intended to allow a user to modify a VM's configuration post
deployment, to adjust the networks to which the VM belongs.

BUG-ID: CLOUDSTACK-645
Submitted-by: Brian Angus <blangus@betterservers.com>
Submitted-by: Ryan Dietrich <ryan@betterservers.com>
Signed-off-by: Marcus Sorensen <marcus@betterservers.com> 1359494800 -0700
This commit is contained in:
Marcus Sorensen 2013-01-30 17:40:20 -07:00
parent 99556a4f30
commit 15906c03ca
21 changed files with 1163 additions and 25 deletions

View File

@ -63,6 +63,11 @@ public class EventTypes {
public static final String EVENT_FIREWALL_OPEN = "FIREWALL.OPEN"; public static final String EVENT_FIREWALL_OPEN = "FIREWALL.OPEN";
public static final String EVENT_FIREWALL_CLOSE = "FIREWALL.CLOSE"; public static final String EVENT_FIREWALL_CLOSE = "FIREWALL.CLOSE";
//NIC Events
public static final String EVENT_NIC_CREATE = "NIC.CREATE";
public static final String EVENT_NIC_DELETE = "NIC.DELETE";
public static final String EVENT_NIC_UPDATE = "NIC.UPDATE";
// Load Balancers // Load Balancers
public static final String EVENT_ASSIGN_TO_LOAD_BALANCER_RULE = "LB.ASSIGN.TO.RULE"; public static final String EVENT_ASSIGN_TO_LOAD_BALANCER_RULE = "LB.ASSIGN.TO.RULE";
public static final String EVENT_REMOVE_FROM_LOAD_BALANCER_RULE = "LB.REMOVE.FROM.RULE"; public static final String EVENT_REMOVE_FROM_LOAD_BALANCER_RULE = "LB.REMOVE.FROM.RULE";

View File

@ -113,6 +113,27 @@ public interface UserVmService {
UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException; 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; UserVm recoverVirtualMachine(RecoverVMCmd cmd) throws ResourceAllocationException;
/** /**

View File

@ -224,6 +224,7 @@ public class ApiConstants {
public static final String NETWORK_OFFERING_ID = "networkofferingid"; public static final String NETWORK_OFFERING_ID = "networkofferingid";
public static final String NETWORK_IDS = "networkids"; public static final String NETWORK_IDS = "networkids";
public static final String NETWORK_ID = "networkid"; public static final String NETWORK_ID = "networkid";
public static final String NIC_ID = "nicid";
public static final String SPECIFY_VLAN = "specifyvlan"; public static final String SPECIFY_VLAN = "specifyvlan";
public static final String IS_DEFAULT = "isdefault"; public static final String IS_DEFAULT = "isdefault";
public static final String IS_SYSTEM = "issystem"; public static final String IS_SYSTEM = "issystem";

View File

@ -0,0 +1,121 @@
// 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 BaseAsyncCmd {
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 String getEventType() {
return EventTypes.EVENT_NIC_CREATE;
}
@Override
public String getEventDescription() {
return "Adding network " + getNetworkId() + " to user vm: " + getVmId();
}
@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() + " Network Id: " + getNetworkId());
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.");
}
}
}

View File

@ -0,0 +1,115 @@
// 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.NicResponse;
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 BaseAsyncCmd {
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.NIC_ID, type=CommandType.UUID, entityType=NicResponse.class,
required=true, description="NIC ID")
private Long nicId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getVmId() {
return vmId;
}
public Long getNicId() {
return nicId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
public static String getResultObjectName() {
return "virtualmachine";
}
@Override
public String getEventType() {
return EventTypes.EVENT_NIC_DELETE;
}
@Override
public String getEventDescription() {
return "Removing NIC " + getNicId() + " from user vm: " + getVmId();
}
@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() + " Nic Id: " + getNicId());
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");
}
}
}

View File

@ -0,0 +1,115 @@
// 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.NicResponse;
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 BaseAsyncCmd {
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.NIC_ID, type=CommandType.UUID, entityType=NicResponse.class,
required=true, description="NIC ID")
private Long nicId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getVmId() {
return vmId;
}
public Long getNicId() {
return nicId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
public static String getResultObjectName() {
return "virtualmachine";
}
@Override
public String getEventType() {
return EventTypes.EVENT_NIC_UPDATE;
}
@Override
public String getEventDescription() {
return "Updating NIC " + getNicId() + " on user vm: " + getVmId();
}
@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() + " Nic Id: " + getNicId());
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.");
}
}
}

View File

@ -17,11 +17,14 @@
package org.apache.cloudstack.api.response; package org.apache.cloudstack.api.response;
import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants;
import com.cloud.vm.Nic;
import com.cloud.serializer.Param; import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@EntityReference(value=Nic.class)
public class NicResponse extends BaseResponse { public class NicResponse extends BaseResponse {
@SerializedName("id") @Param(description="the ID of the nic") @SerializedName("id") @Param(description="the ID of the nic")

View File

@ -320,6 +320,11 @@ listNetworks=15
restartNetwork=15 restartNetwork=15
updateNetwork=15 updateNetwork=15
#### nic commands ####
addNicToVirtualMachine=15
removeNicFromVirtualMachine=15
updateDefaultNicForVirtualMachine=15
#### SSH key pair commands #### SSH key pair commands
registerSSHKeyPair=15 registerSSHKeyPair=15
createSSHKeyPair=15 createSSHKeyPair=15

View File

@ -262,7 +262,7 @@ public interface NetworkManager {
* @throws InsufficientCapacityException * @throws InsufficientCapacityException
* @throws ResourceUnavailableException * @throws ResourceUnavailableException
*/ */
NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context, VirtualMachineProfileImpl<VMInstanceVO> vmProfile, boolean prepare) throws InsufficientVirtualNetworkCapcityException, NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context, VirtualMachineProfile<? extends VMInstanceVO> vmProfile, boolean prepare) throws InsufficientVirtualNetworkCapcityException,
InsufficientAddressCapacityException, ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException; InsufficientAddressCapacityException, ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException;

View File

@ -3355,20 +3355,19 @@ public class NetworkManagerImpl implements NetworkManager, Manager, Listener {
} }
@Override @Override
public NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context, VirtualMachineProfileImpl<VMInstanceVO> vmProfile, boolean prepare) public NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context, VirtualMachineProfile<? extends VMInstanceVO> vmProfile, boolean prepare)
throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException,
ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
VirtualMachine vm = vmProfile.getVirtualMachine(); VirtualMachine vm = vmProfile.getVirtualMachine();
NetworkVO networkVO = _networksDao.findById(network.getId());
DataCenter dc = _configMgr.getZone(network.getDataCenterId()); DataCenter dc = _configMgr.getZone(network.getDataCenterId());
Host host = _hostDao.findById(vm.getHostId()); Host host = _hostDao.findById(vm.getHostId());
DeployDestination dest = new DeployDestination(dc, null, null, host); DeployDestination dest = new DeployDestination(dc, null, null, host);
NicProfile nic = getNicProfileForVm(network, requested, vm); NicProfile nic = getNicProfileForVm(network, requested, vm);
//1) allocate nic (if needed) //1) allocate nic (if needed) Always allocate if it is a user vm
if (nic == null) { if (nic == null || (vmProfile.getType() == VirtualMachine.Type.User)) {
int deviceId = _nicDao.countNics(vm.getId()); int deviceId = _nicDao.countNics(vm.getId());
nic = allocateNic(requested, network, false, nic = allocateNic(requested, network, false,
@ -3383,6 +3382,7 @@ public class NetworkManagerImpl implements NetworkManager, Manager, Listener {
//2) prepare nic //2) prepare nic
if (prepare) { if (prepare) {
NetworkVO networkVO = _networksDao.findById(network.getId());
nic = prepareNic(vmProfile, dest, context, nic.getId(), networkVO); nic = prepareNic(vmProfile, dest, context, nic.getId(), networkVO);
s_logger.debug("Nic is prepared successfully for vm " + vm + " in network " + network); s_logger.debug("Nic is prepared successfully for vm " + vm + " in network " + network);
} }

View File

@ -1692,6 +1692,9 @@ public class NetworkModelImpl implements NetworkModel, Manager{
} else { } else {
nic = _nicDao.findByInstanceIdAndNetworkId(networkId, vm.getId()); nic = _nicDao.findByInstanceIdAndNetworkId(networkId, vm.getId());
} }
if (nic == null) {
return null;
}
NetworkVO network = _networksDao.findById(networkId); NetworkVO network = _networksDao.findById(networkId);
Integer networkRate = getNetworkRate(network.getId(), vm.getId()); Integer networkRate = getNetworkRate(network.getId(), vm.getId());

View File

@ -860,8 +860,8 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
// for Basic zone, add all Running routers - we have to send Dhcp/vmData/password info to them when // for Basic zone, add all Running routers - we have to send Dhcp/vmData/password info to them when
// network.dns.basiczone.updates is set to "all" // network.dns.basiczone.updates is set to "all"
Long podId = dest.getPod().getId();
if (isPodBased && _routerMgr.getDnsBasicZoneUpdate().equalsIgnoreCase("all")) { if (isPodBased && _routerMgr.getDnsBasicZoneUpdate().equalsIgnoreCase("all")) {
Long podId = dest.getPod().getId();
List<DomainRouterVO> allRunningRoutersOutsideThePod = _routerDao.findByNetworkOutsideThePod(network.getId(), List<DomainRouterVO> allRunningRoutersOutsideThePod = _routerDao.findByNetworkOutsideThePod(network.getId(),
podId, State.Running, Role.VIRTUAL_ROUTER); podId, State.Running, Role.VIRTUAL_ROUTER);
routers.addAll(allRunningRoutersOutsideThePod); routers.addAll(allRunningRoutersOutsideThePod);

View File

@ -17,11 +17,16 @@
package com.cloud.vm; package com.cloud.vm;
import com.cloud.agent.AgentManager; import com.cloud.agent.AgentManager;
import com.cloud.agent.AgentManager.OnError;
import com.cloud.agent.api.*; import com.cloud.agent.api.*;
import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer; import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.api.to.VolumeTO; import com.cloud.agent.api.to.VolumeTO;
import com.cloud.agent.api.PlugNicAnswer;
import com.cloud.agent.api.PlugNicCommand;
import com.cloud.agent.api.UnPlugNicAnswer;
import com.cloud.agent.api.UnPlugNicCommand;
import com.cloud.agent.manager.Commands; import com.cloud.agent.manager.Commands;
import com.cloud.alert.AlertManager; import com.cloud.alert.AlertManager;
import com.cloud.api.ApiDBUtils; import com.cloud.api.ApiDBUtils;
@ -916,6 +921,237 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
return _vmDao.findById(vmInstance.getId()); 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);
if(vmInstance == null) {
throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
}
NetworkVO network = _networkDao.findById(networkId);
if(network == null) {
throw new InvalidParameterValueException("unable to find a network with id " + networkId);
}
NicProfile profile = new NicProfile(null);
if(ipAddress != null) {
profile = new NicProfile(ipAddress);
}
// Perform permission check on VM
_accountMgr.checkAccess(caller, null, true, vmInstance);
// Verify that zone is not Basic
DataCenterVO dc = _dcDao.findById(vmInstance.getDataCenterIdToDeployIn());
if (dc.getNetworkType() == DataCenter.NetworkType.Basic) {
throw new CloudRuntimeException("Zone " + vmInstance.getDataCenterIdToDeployIn() + ", has a NetworkType of Basic. Can't add a new NIC to a VM on a Basic Network");
}
// 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() ) && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) {
throw new PermissionDeniedException("Unable to modify a vm using network with id " + network.getId() + ", permission denied");
}
}
//ensure network belongs in zone
if (network.getDataCenterId() != vmInstance.getDataCenterIdToDeployIn()) {
throw new CloudRuntimeException(vmInstance + " is in zone:" + vmInstance.getDataCenterIdToDeployIn() + " but " + network + " is in zone:" + network.getDataCenterId());
}
if(_networkModel.getNicInNetwork(vmInstance.getId(),network.getId()) != null){
s_logger.debug(vmInstance + " already in " + network + " going to add another NIC");
} else {
//* get all vms hostNames in the network
List<String> hostNames = _vmInstanceDao.listDistinctHostNames(network.getId());
//* verify that there are no duplicates
if (hostNames.contains(vmInstance.getHostName())) {
throw new CloudRuntimeException(network + " already has a vm with host name: '" + vmInstance.getHostName());
}
}
NicProfile guestNic = null;
try {
guestNic = _itMgr.addVmToNetwork(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 nicId = cmd.getNicId();
Account caller = UserContext.current().getCaller();
UserVmVO vmInstance = _vmDao.findById(vmId);
if(vmInstance == null) {
throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
}
NicVO nic = _nicDao.findById(nicId);
if (nic == null){
throw new InvalidParameterValueException("unable to find a nic with id " + nicId);
}
NetworkVO network = _networkDao.findById(nic.getNetworkId());
if(network == null) {
throw new InvalidParameterValueException("unable to find a network with id " + nic.getNetworkId());
}
// Perform permission check on VM
_accountMgr.checkAccess(caller, null, true, vmInstance);
// Verify that zone is not Basic
DataCenterVO dc = _dcDao.findById(vmInstance.getDataCenterIdToDeployIn());
if (dc.getNetworkType() == DataCenter.NetworkType.Basic) {
throw new CloudRuntimeException("Zone " + vmInstance.getDataCenterIdToDeployIn() + ", has a NetworkType of Basic. Can't remove a NIC from a VM on a Basic Network");
}
//check to see if nic is attached to VM
if (nic.getInstanceId() != vmId) {
throw new InvalidParameterValueException(nic + " is not a nic on " + 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() ) && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) {
throw new PermissionDeniedException("Unable to modify a vm using network with id " + network.getId() + ", permission denied");
}
}
boolean nicremoved = false;
try {
nicremoved = _itMgr.removeNicFromVm(vmInstance, nic);
} 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 nicId = cmd.getNicId();
Account caller = UserContext.current().getCaller();
UserVmVO vmInstance = _vmDao.findById(vmId);
if (vmInstance == null){
throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
}
NicVO nic = _nicDao.findById(nicId);
if (nic == null){
throw new InvalidParameterValueException("unable to find a nic with id " + nicId);
}
NetworkVO network = _networkDao.findById(nic.getNetworkId());
if (network == null){
throw new InvalidParameterValueException("unable to find a network with id " + nic.getNetworkId());
}
// Perform permission check on VM
_accountMgr.checkAccess(caller, null, true, vmInstance);
// Verify that zone is not Basic
DataCenterVO dc = _dcDao.findById(vmInstance.getDataCenterIdToDeployIn());
if (dc.getNetworkType() == DataCenter.NetworkType.Basic) {
throw new CloudRuntimeException("Zone " + vmInstance.getDataCenterIdToDeployIn() + ", has a NetworkType of Basic. Can't change default NIC on a Basic Network");
}
// no need to check permissions for network, we'll enumerate the ones they already have access to
Network existingdefaultnet = _networkModel.getDefaultNetworkForVm(vmId);
//check to see if nic is attached to VM
if (nic.getInstanceId() != vmId) {
throw new InvalidParameterValueException(nic + " is not a nic on " + vmInstance);
}
// if current default equals chosen new default, Throw an exception
if (nic.isDefaultNic()){
throw new CloudRuntimeException("refusing to set default nic because chosen nic is already the default");
}
//make sure the VM is Running or Stopped
if ((vmInstance.getState() != State.Running) && (vmInstance.getState() != State.Stopped)) {
throw new CloudRuntimeException("refusing to set default " + vmInstance + " is not Running or Stopped");
}
NicProfile existing = null;
List<NicProfile> nicProfiles = _networkMgr.getNicProfiles(vmInstance);
for (NicProfile nicProfile : nicProfiles) {
if(nicProfile.isDefaultNic() && nicProfile.getNetworkId() == existingdefaultnet.getId()){
existing = nicProfile;
continue;
}
}
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 existingVO = _nicDao.findById(existing.id);
Integer chosenID = nic.getDeviceId();
Integer existingID = existing.getDeviceId();
nic.setDefaultNic(true);
nic.setDeviceId(existingID);
existingVO.setDefaultNic(false);
existingVO.setDeviceId(chosenID);
nic = _nicDao.persist(nic);
existingVO = _nicDao.persist(existingVO);
Network newdefault = null;
newdefault = _networkModel.getDefaultNetworkForVm(vmId);
if (newdefault == null){
nic.setDefaultNic(false);
nic.setDeviceId(chosenID);
existingVO.setDefaultNic(true);
existingVO.setDeviceId(existingID);
nic = _nicDao.persist(nic);
existingVO = _nicDao.persist(existingVO);
newdefault = _networkModel.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 " + nic + " and now we have no default");
} else if (newdefault.getId() == nic.getNetworkId()) {
s_logger.debug("successfully set default network to " + network + " for " + vmInstance);
return _vmDao.findById(vmInstance.getId());
}
throw new CloudRuntimeException("something strange happened, new default network(" + newdefault.getId() + ") is not null, and is not equal to the network(" + nic.getNetworkId() + ") of the chosen nic");
}
@Override @Override
public HashMap<Long, VmStatsEntry> getVirtualMachineStatistics(long hostId, String hostName, List<Long> vmIds) throws CloudRuntimeException { public HashMap<Long, VmStatsEntry> getVirtualMachineStatistics(long hostId, String hostName, List<Long> vmIds) throws CloudRuntimeException {
@ -3671,16 +3907,58 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
public boolean plugNic(Network network, NicTO nic, VirtualMachineTO vm, public boolean plugNic(Network network, NicTO nic, VirtualMachineTO vm,
ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException, ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException,
InsufficientCapacityException { InsufficientCapacityException {
//not supported UserVmVO vmVO = _vmDao.findById(vm.getId());
throw new UnsupportedOperationException("Plug nic is not supported for vm of type " + vm.getType()); if (vmVO.getState() == State.Running) {
try {
PlugNicCommand plugNicCmd = new PlugNicCommand(nic,vm.getName());
Commands cmds = new Commands(OnError.Stop);
cmds.addCommand("plugnic",plugNicCmd);
_agentMgr.send(dest.getHost().getId(),cmds);
PlugNicAnswer plugNicAnswer = cmds.getAnswer(PlugNicAnswer.class);
if (!(plugNicAnswer != null && plugNicAnswer.getResult())) {
s_logger.warn("Unable to plug nic for " + vmVO);
return false;
}
} catch (OperationTimedoutException e) {
throw new AgentUnavailableException("Unable to plug nic for " + vmVO + " in network " + network, dest.getHost().getId(), e);
}
} else if (vmVO.getState() == State.Stopped || vmVO.getState() == State.Stopping) {
s_logger.warn(vmVO + " is Stopped, not sending PlugNicCommand. Currently " + vmVO.getState());
} else {
s_logger.warn("Unable to plug nic, " + vmVO + " is not in the right state " + vmVO.getState());
throw new ResourceUnavailableException("Unable to plug nic on the backend," +
vmVO + " is not in the right state", DataCenter.class, vmVO.getDataCenterIdToDeployIn());
}
return true;
} }
@Override @Override
public boolean unplugNic(Network network, NicTO nic, VirtualMachineTO vm, public boolean unplugNic(Network network, NicTO nic, VirtualMachineTO vm,
ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException { ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException {
//not supported UserVmVO vmVO = _vmDao.findById(vm.getId());
throw new UnsupportedOperationException("Unplug nic is not supported for vm of type " + vm.getType()); if (vmVO.getState() == State.Running) {
try {
UnPlugNicCommand unplugNicCmd = new UnPlugNicCommand(nic,vm.getName());
Commands cmds = new Commands(OnError.Stop);
cmds.addCommand("unplugnic",unplugNicCmd);
_agentMgr.send(dest.getHost().getId(),cmds);
UnPlugNicAnswer unplugNicAnswer = cmds.getAnswer(UnPlugNicAnswer.class);
if (!(unplugNicAnswer != null && unplugNicAnswer.getResult())) {
s_logger.warn("Unable to unplug nic for " + vmVO);
return false;
}
} catch (OperationTimedoutException e) {
throw new AgentUnavailableException("Unable to unplug nic for " + vmVO + " in network " + network, dest.getHost().getId(), e);
}
} else if (vmVO.getState() == State.Stopped || vmVO.getState() == State.Stopping) {
s_logger.warn(vmVO + " is Stopped, not sending UnPlugNicCommand. Currently " + vmVO.getState());
} else {
s_logger.warn("Unable to unplug nic, " + vmVO + " is not in the right state " + vmVO.getState());
throw new ResourceUnavailableException("Unable to unplug nic on the backend," +
vmVO + " is not in the right state", DataCenter.class, vmVO.getDataCenterIdToDeployIn());
}
return true;
} }
@Override @Override

View File

@ -152,6 +152,15 @@ public interface VirtualMachineManager extends Manager {
NicProfile addVmToNetwork(VirtualMachine vm, Network network, NicProfile requested) throws ConcurrentOperationException, NicProfile addVmToNetwork(VirtualMachine vm, Network network, NicProfile requested) throws ConcurrentOperationException,
ResourceUnavailableException, InsufficientCapacityException; ResourceUnavailableException, InsufficientCapacityException;
/**
* @param vm
* @param nic
* @return
* @throws ResourceUnavailableException
* @throws ConcurrentOperationException
*/
boolean removeNicFromVm(VirtualMachine vm, NicVO nic) throws ConcurrentOperationException, ResourceUnavailableException;
/** /**
* @param vm * @param vm
* @param network * @param network

View File

@ -2462,7 +2462,12 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
ResourceUnavailableException, InsufficientCapacityException { ResourceUnavailableException, InsufficientCapacityException {
s_logger.debug("Adding vm " + vm + " to network " + network + "; requested nic profile " + requested); s_logger.debug("Adding vm " + vm + " to network " + network + "; requested nic profile " + requested);
VMInstanceVO vmVO = _vmDao.findById(vm.getId()); VMInstanceVO vmVO;
if (vm.getType() == VirtualMachine.Type.User) {
vmVO = _userVmDao.findById(vm.getId());
} else {
vmVO = _vmDao.findById(vm.getId());
}
ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM),
_accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM)); _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM));
@ -2506,7 +2511,6 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
} }
} }
@Override @Override
public NicTO toNicTO(NicProfile nic, HypervisorType hypervisorType) { public NicTO toNicTO(NicProfile nic, HypervisorType hypervisorType) {
HypervisorGuru hvGuru = _hvGuruMgr.getGuru(hypervisorType); HypervisorGuru hvGuru = _hvGuruMgr.getGuru(hypervisorType);
@ -2515,6 +2519,61 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
return nicTO; return nicTO;
} }
@Override
public boolean removeNicFromVm(VirtualMachine vm, NicVO nic) throws ConcurrentOperationException, ResourceUnavailableException {
VMInstanceVO vmVO = _vmDao.findById(vm.getId());
NetworkVO network = _networkDao.findById(nic.getNetworkId());
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);
DataCenter dc = _configMgr.getZone(network.getDataCenterId());
Host host = _hostDao.findById(vm.getHostId());
DeployDestination dest = new DeployDestination(dc, null, null, host);
VirtualMachineGuru<VMInstanceVO> vmGuru = getVmGuru(vmVO);
HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vmProfile.getVirtualMachine().getHypervisorType());
VirtualMachineTO vmTO = hvGuru.implement(vmProfile);
// 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(),
_networkModel.getNetworkRate(network.getId(), vm.getId()),
_networkModel.isSecurityGroupSupportedInNetwork(network),
_networkModel.getNetworkTag(vmProfile.getVirtualMachine().getHypervisorType(), network));
//1) Unplug the nic
if (vm.getState() == State.Running) {
NicTO nicTO = toNicTO(nicProfile, vmProfile.getVirtualMachine().getHypervisorType());
s_logger.debug("Un-plugging nic " + 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
_networkMgr.releaseNic(vmProfile, nic);
s_logger.debug("Successfully released nic " + nic + "for vm " + vm);
//3) Remove the nic
_networkMgr.removeNic(vmProfile, nic);
_nicsDao.expunge(nic.getId());
return true;
}
@Override @Override
public boolean removeVmFromNetwork(VirtualMachine vm, Network network, URI broadcastUri) throws ConcurrentOperationException, ResourceUnavailableException { public boolean removeVmFromNetwork(VirtualMachine vm, Network network, URI broadcastUri) throws ConcurrentOperationException, ResourceUnavailableException {
VMInstanceVO vmVO = _vmDao.findById(vm.getId()); VMInstanceVO vmVO = _vmDao.findById(vm.getId());
@ -2539,12 +2598,24 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
nic = _networkModel.getNicInNetwork(vm.getId(), network.getId()); nic = _networkModel.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(), NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(),
_networkModel.getNetworkRate(network.getId(), vm.getId()), _networkModel.getNetworkRate(network.getId(), vm.getId()),
_networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.isSecurityGroupSupportedInNetwork(network),
_networkModel.getNetworkTag(vmProfile.getVirtualMachine().getHypervisorType(), network)); _networkModel.getNetworkTag(vmProfile.getVirtualMachine().getHypervisorType(), network));
//1) Unplug the nic //1) Unplug the nic
if (vm.getState() == State.Running) {
NicTO nicTO = toNicTO(nicProfile, vmProfile.getVirtualMachine().getHypervisorType()); NicTO nicTO = toNicTO(nicProfile, vmProfile.getVirtualMachine().getHypervisorType());
s_logger.debug("Un-plugging nic for vm " + vm + " from network " + network); s_logger.debug("Un-plugging nic for vm " + vm + " from network " + network);
boolean result = vmGuru.unplugNic(network, nicTO, vmTO, context, dest); boolean result = vmGuru.unplugNic(network, nicTO, vmTO, context, dest);
@ -2554,6 +2625,11 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
s_logger.warn("Failed to unplug nic for the vm " + vm + " from network " + network); s_logger.warn("Failed to unplug nic for the vm " + vm + " from network " + network);
return false; 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 //2) Release the nic
_networkMgr.releaseNic(vmProfile, nic); _networkMgr.releaseNic(vmProfile, nic);
@ -2561,7 +2637,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
//3) Remove the nic //3) Remove the nic
_networkMgr.removeNic(vmProfile, nic); _networkMgr.removeNic(vmProfile, nic);
return result; return true;
} }
} }

View File

@ -733,7 +733,7 @@ public class MockNetworkManagerImpl implements NetworkManager, Manager, NetworkS
*/ */
@Override @Override
public NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context, public NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context,
VirtualMachineProfileImpl<VMInstanceVO> vmProfile, boolean prepare) VirtualMachineProfile<? extends VMInstanceVO> vmProfile, boolean prepare)
throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException,
ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
// TODO Auto-generated method stub // TODO Auto-generated method stub

View File

@ -55,6 +55,8 @@ import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.ResourceUnavailableException;
import com.cloud.exception.StorageUnavailableException; import com.cloud.exception.StorageUnavailableException;
import com.cloud.exception.VirtualMachineMigrationException; import com.cloud.exception.VirtualMachineMigrationException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.host.Host; import com.cloud.host.Host;
import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network; import com.cloud.network.Network;
@ -69,6 +71,7 @@ import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair; import com.cloud.utils.Pair;
import com.cloud.utils.component.Manager; import com.cloud.utils.component.Manager;
import com.cloud.utils.exception.ExecutionException; import com.cloud.utils.exception.ExecutionException;
import com.cloud.utils.exception.CloudRuntimeException;
@Local(value = { UserVmManager.class, UserVmService.class }) @Local(value = { UserVmManager.class, UserVmService.class })
public class MockUserVmManagerImpl implements UserVmManager, UserVmService, Manager { public class MockUserVmManagerImpl implements UserVmManager, UserVmService, Manager {
@ -276,6 +279,24 @@ public class MockUserVmManagerImpl implements UserVmManager, UserVmService, Mana
return null; return null;
} }
@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 @Override
public UserVm recoverVirtualMachine(RecoverVMCmd cmd) throws ResourceAllocationException { public UserVm recoverVirtualMachine(RecoverVMCmd cmd) throws ResourceAllocationException {
// TODO Auto-generated method stub // TODO Auto-generated method stub

View File

@ -270,6 +270,15 @@ public class MockVirtualMachineManagerImpl implements VirtualMachineManager {
return null; return null;
} }
/* (non-Javadoc)
* @see com.cloud.vm.VirtualMachineManager#removeVmFromNetwork(com.cloud.vm.VirtualMachine, com.cloud.network.Network, java.net.URI)
*/
@Override
public boolean removeNicFromVm(VirtualMachine vm, NicVO nic) throws ConcurrentOperationException, ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
/* (non-Javadoc) /* (non-Javadoc)
* @see com.cloud.vm.VirtualMachineManager#removeVmFromNetwork(com.cloud.vm.VirtualMachine, com.cloud.network.Network, java.net.URI) * @see com.cloud.vm.VirtualMachineManager#removeVmFromNetwork(com.cloud.vm.VirtualMachine, com.cloud.network.Network, java.net.URI)
*/ */

View File

@ -1123,11 +1123,11 @@ public class MockNetworkManagerImpl implements NetworkManager, NetworkService, M
/* (non-Javadoc) /* (non-Javadoc)
* @see com.cloud.network.NetworkManager#createNicForVm(com.cloud.network.Network, com.cloud.vm.NicProfile, com.cloud.vm.ReservationContext, com.cloud.vm.VirtualMachineProfileImpl, boolean) * @see com.cloud.network.NetworkManager#createNicForVm(com.cloud.network.Network, com.cloud.vm.NicProfile, com.cloud.vm.ReservationContext, com.cloud.vm.VirtualMachineProfileImpl, boolean, boolean)
*/ */
@Override @Override
public NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context, public NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context,
VirtualMachineProfileImpl<VMInstanceVO> vmProfile, boolean prepare) VirtualMachineProfile<? extends VMInstanceVO> vmProfile, boolean prepare)
throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException,
ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
// TODO Auto-generated method stub // TODO Auto-generated method stub

View File

@ -0,0 +1,335 @@
""" NIC tests for VM """
import marvin
from marvin.cloudstackTestCase import *
from marvin.cloudstackAPI import *
from marvin.remoteSSHClient import remoteSSHClient
from marvin.integration.lib.utils import *
from marvin.integration.lib.base import *
from marvin.integration.lib.common import *
from nose.plugins.attrib import attr
import signal
import sys
import time
class Services:
def __init__(self):
self.services = {
"disk_offering":{
"displaytext": "Small",
"name": "Small",
"disksize": 1
},
"account": {
"email": "test@test.com",
"firstname": "Test",
"lastname": "User",
"username": "test",
# Random characters are appended in create account to
# ensure unique username generated each time
"password": "password",
},
# Create a small virtual machine instance with disk offering
"small": {
"displayname": "testserver",
"username": "root", # VM creds for SSH
"password": "password",
"ssh_port": 22,
"hypervisor": 'XenServer',
"privateport": 22,
"publicport": 22,
"protocol": 'TCP',
},
"service_offerings": {
"tiny": {
"name": "Tiny Instance",
"displaytext": "Tiny Instance",
"cpunumber": 1,
"cpuspeed": 100, # in MHz
"memory": 128, # In MBs
},
},
"network_offering": {
"name": 'Test Network offering',
"displaytext": 'Test Network offering',
"guestiptype": 'Isolated',
"supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding',
"traffictype": 'GUEST',
"availability": 'Optional',
"serviceProviderList" : {
"Dhcp": 'VirtualRouter',
"Dns": 'VirtualRouter',
"SourceNat": 'VirtualRouter',
"PortForwarding": 'VirtualRouter',
},
},
"network": {
"name": "Test Network",
"displaytext": "Test Network",
"acltype": "Account",
},
# ISO settings for Attach/Detach ISO tests
"iso": {
"displaytext": "Test ISO",
"name": "testISO",
"url": "http://iso.linuxquestions.org/download/504/1819/http/gd4.tuwien.ac.at/dsl-4.4.10.iso",
# Source URL where ISO is located
"ostype": 'CentOS 5.3 (64-bit)',
"mode": 'HTTP_DOWNLOAD', # Downloading existing ISO
},
"template": {
"displaytext": "Cent OS Template",
"name": "Cent OS Template",
"passwordenabled": True,
},
"diskdevice": '/dev/xvdd',
# Disk device where ISO is attached to instance
"mount_dir": "/mnt/tmp",
"sleep": 60,
"timeout": 10,
#Migrate VM to hostid
"ostype": 'CentOS 5.3 (64-bit)',
# CentOS 5.3 (64-bit)
}
class TestDeployVM(cloudstackTestCase):
def setUp(self):
self.cleanup = []
self.cleaning_up = 0
def signal_handler(signal, frame):
self.tearDown()
sys.exit(0)
# assign the signal handler immediately
signal.signal(signal.SIGINT, signal_handler)
try:
self.apiclient = self.testClient.getApiClient()
self.dbclient = self.testClient.getDbConnection()
self.services = Services().services
# Get Zone, Domain and templates
domain = get_domain(self.apiclient, self.services)
zone = get_zone(self.apiclient, self.services)
self.services['mode'] = zone.networktype
if self.services['mode'] != 'Advanced':
self.debug("Cannot run this test with a basic zone, please use advanced!")
return
#if local storage is enabled, alter the offerings to use localstorage
#this step is needed for devcloud
if zone.localstorageenabled == True:
self.services["service_offerings"]["tiny"]["storagetype"] = 'local'
template = get_template(
self.apiclient,
zone.id,
self.services["ostype"]
)
# Set Zones and disk offerings
self.services["small"]["zoneid"] = zone.id
self.services["small"]["template"] = template.id
self.services["iso"]["zoneid"] = zone.id
self.services["network"]["zoneid"] = zone.id
# Create Account, VMs, NAT Rules etc
self.account = Account.create(
self.apiclient,
self.services["account"],
domainid=domain.id
)
self.cleanup.insert(0, self.account)
self.service_offering = ServiceOffering.create(
self.apiclient,
self.services["service_offerings"]["tiny"]
)
self.cleanup.insert(0, self.service_offering)
####################
### Network offering
self.network_offering = NetworkOffering.create(
self.apiclient,
self.services["network_offering"],
)
self.cleanup.insert(0, self.network_offering)
self.network_offering.update(self.apiclient, state='Enabled') # Enable Network offering
self.services["network"]["networkoffering"] = self.network_offering.id
################
### Test Network
self.test_network = Network.create(
self.apiclient,
self.services["network"],
self.account.account.name,
self.account.account.domainid,
)
self.cleanup.insert(0, self.test_network)
except Exception as ex:
self.debug("Exception during NIC test SETUP!: " + str(ex))
self.assertEqual(True, False, "Exception during NIC test SETUP!: " + str(ex))
@attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"])
def test_01_nic(self):
if self.services['mode'] != 'Advanced':
self.debug("Cannot run this test with a basic zone, please use advanced!")
return
try:
self.virtual_machine = VirtualMachine.create(
self.apiclient,
self.services["small"],
accountid=self.account.account.name,
domainid=self.account.account.domainid,
serviceofferingid=self.service_offering.id,
mode=self.services['mode']
)
self.cleanup.insert(0, self.virtual_machine)
list_vm_response = list_virtual_machines(
self.apiclient,
id=self.virtual_machine.id
)
self.debug(
"Verify listVirtualMachines response for virtual machine: %s" \
% self.virtual_machine.id
)
self.assertEqual(
isinstance(list_vm_response, list),
True,
"Check list response returns a valid list"
)
self.assertNotEqual(
len(list_vm_response),
0,
"Check VM available in List Virtual Machines"
)
vm_response = list_vm_response[0]
self.assertEqual(
vm_response.id,
self.virtual_machine.id,
"Check virtual machine id in listVirtualMachines"
)
self.assertEqual(
vm_response.name,
self.virtual_machine.name,
"Check virtual machine name in listVirtualMachines"
)
self.assertEqual(
len(vm_response.nic),
1,
"Verify we only start with one nic"
)
self.assertEqual(
vm_response.nic[0].isdefault,
True,
"Verify initial adapter is set to default"
)
existing_nic_ip = vm_response.nic[0].ipaddress
existing_nic_id = vm_response.nic[0].id
# 1. add a nic
add_response = self.virtual_machine.add_nic(self.apiclient, self.test_network.id)
time.sleep(5)
# now go get the vm list?
list_vm_response = list_virtual_machines(
self.apiclient,
id=self.virtual_machine.id
)
self.assertEqual(
len(list_vm_response[0].nic),
2,
"Verify we have 2 NIC's now"
)
new_nic_id = ""
for nc in list_vm_response[0].nic:
if nc.ipaddress != existing_nic_ip:
new_nic_id = nc.id
self.virtual_machine.update_default_nic(self.apiclient, new_nic_id)
time.sleep(5)
list_vm_response = list_virtual_machines(
self.apiclient,
id=self.virtual_machine.id
)
# iterate as we don't know for sure what order our NIC's will be returned to us.
for nc in list_vm_response[0].nic:
if nc.ipaddress == existing_nic_ip:
self.assertEqual(
nc.isdefault,
False,
"Verify initial adapter is NOT set to default"
)
else:
self.assertEqual(
nc.isdefault,
True,
"Verify second adapter is set to default"
)
sawException = False
try:
self.virtual_machine.remove_nic(self.apiclient, new_nic_id)
except Exception as ex:
sawException = True
self.assertEqual(sawException, True, "Make sure we cannot delete the default NIC")
self.virtual_machine.remove_nic(self.apiclient, existing_nic_id)
time.sleep(5)
list_vm_response = list_virtual_machines(
self.apiclient,
id=self.virtual_machine.id
)
self.assertEqual(
len(list_vm_response[0].nic),
1,
"Verify we are back to a signle NIC"
)
return
except Exception as ex:
self.debug("Exception during NIC test!: " + str(ex))
self.assertEqual(True, False, "Exception during NIC test!: " + str(ex))
def tearDown(self):
if self.services['mode'] != 'Advanced':
self.debug("Cannot run this test with a basic zone, please use advanced!")
return
if self.cleaning_up == 1:
return
self.cleaning_up = 1
try:
for obj in self.cleanup:
try:
obj.delete(self.apiclient)
time.sleep(10)
except Exception as ex:
self.debug("Error deleting: " + str(obj) + ", exception: " + str(ex))
except Exception as e:
self.debug("Warning! Exception in tearDown: %s" % e)
self.cleaning_up = 0

View File

@ -389,6 +389,27 @@ class VirtualMachine:
cmd.id = volume.id cmd.id = volume.id
return apiclient.detachVolume(cmd) return apiclient.detachVolume(cmd)
def add_nic(self, apiclient, networkId):
"""Add a NIC to a VM"""
cmd = addNicToVirtualMachine.addNicToVirtualMachineCmd();
cmd.virtualmachineid = self.id
cmd.networkid = networkId
return apiclient.addNicToVirtualMachine(cmd)
def remove_nic(self, apiclient, nicId):
"""Remove a NIC to a VM"""
cmd = removeNicFromVirtualMachine.removeNicFromVirtualMachineCmd()
cmd.nicid = nicId
cmd.virtualmachineid = self.id
return apiclient.removeNicFromVirtualMachine(cmd)
def update_default_nic(self, apiclient, nicId):
"""Set a NIC to be the default network adapter for a VM"""
cmd = updateDefaultNicForVirtualMachine.updateDefaultNicForVirtualMachineCmd()
cmd.nicid = nicId
cmd.virtualmachineid = self.id
return apiclient.updateDefaultNicForVirtualMachine(cmd)
@classmethod @classmethod
def list(cls, apiclient, **kwargs): def list(cls, apiclient, **kwargs):
"""List all VMs matching criteria""" """List all VMs matching criteria"""