mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-9051: update nic IP address of stopped vm
This commit is contained in:
parent
20dcc25884
commit
b79d338f29
@ -34,6 +34,7 @@ import org.apache.cloudstack.api.command.user.vm.ScaleVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.StartVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateDefaultNicForVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateVmNicIpCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd;
|
||||
import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd;
|
||||
@ -129,6 +130,13 @@ public interface UserVmService {
|
||||
*/
|
||||
UserVm updateDefaultNicForVirtualMachine(UpdateDefaultNicForVMCmd cmd);
|
||||
|
||||
/**
|
||||
* Updated the ip address on the given NIC to the virtual machine
|
||||
* @param cmd the command object that defines the ip address and the given nic
|
||||
* @return the vm object if successful, null otherwise
|
||||
*/
|
||||
UserVm updateNicIpForVirtualMachine(UpdateVmNicIpCmd cmd);
|
||||
|
||||
UserVm recoverVirtualMachine(RecoverVMCmd cmd) throws ResourceAllocationException;
|
||||
|
||||
/**
|
||||
|
||||
@ -0,0 +1,186 @@
|
||||
// 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.APICommand;
|
||||
import org.apache.cloudstack.api.ApiCommandJobType;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseAsyncCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.ApiConstants.VMDetails;
|
||||
import org.apache.cloudstack.api.ResponseObject.ResponseView;
|
||||
import org.apache.cloudstack.api.response.NicResponse;
|
||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.dc.DataCenter.NetworkType;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.uservm.UserVm;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
import com.cloud.vm.Nic;
|
||||
|
||||
@APICommand(name = "updateVmNicIp", description = "Update the default Ip of a VM Nic", responseObject = UserVmResponse.class)
|
||||
public class UpdateVmNicIpCmd extends BaseAsyncCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(AddIpToVmNicCmd.class.getName());
|
||||
private static final String s_name = "updatevmnicipresponse";
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
@Parameter(name=ApiConstants.NIC_ID, type=CommandType.UUID, entityType = NicResponse.class, required = true,
|
||||
description="the ID of the nic to which you want to assign private IP")
|
||||
private Long nicId;
|
||||
|
||||
@Parameter(name = ApiConstants.IP_ADDRESS, type = CommandType.STRING, required = false,
|
||||
description = "Secondary IP Address")
|
||||
private String ipAddr;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public String getEntityTable() {
|
||||
return "nic_secondary_ips";
|
||||
}
|
||||
|
||||
public String getAccountName() {
|
||||
return CallContext.current().getCallingAccount().getAccountName();
|
||||
}
|
||||
|
||||
public long getDomainId() {
|
||||
return CallContext.current().getCallingAccount().getDomainId();
|
||||
}
|
||||
|
||||
private long getZoneId() {
|
||||
Network ntwk = _entityMgr.findById(Network.class, getNetworkId());
|
||||
if (ntwk == null) {
|
||||
throw new InvalidParameterValueException("Can't find zone id for specified");
|
||||
}
|
||||
return ntwk.getDataCenterId();
|
||||
}
|
||||
|
||||
public Long getNetworkId() {
|
||||
Nic nic = _entityMgr.findById(Nic.class, nicId);
|
||||
if (nic == null) {
|
||||
throw new InvalidParameterValueException("Can't find network id for specified nic");
|
||||
}
|
||||
Long networkId = nic.getNetworkId();
|
||||
return networkId;
|
||||
}
|
||||
|
||||
public Long getNicId() {
|
||||
return nicId;
|
||||
}
|
||||
|
||||
public String getIpaddress () {
|
||||
if (ipAddr != null) {
|
||||
return ipAddr;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public NetworkType getNetworkType() {
|
||||
Network ntwk = _entityMgr.findById(Network.class, getNetworkId());
|
||||
DataCenter dc = _entityMgr.findById(DataCenter.class, ntwk.getDataCenterId());
|
||||
return dc.getNetworkType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return CallContext.current().getCallingAccountId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType() {
|
||||
return EventTypes.EVENT_NET_IP_ASSIGN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventDescription() {
|
||||
return "associating ip to nic id: " + getNetworkId() + " in zone " + getZoneId();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
public static String getResultObjectName() {
|
||||
return "addressinfo";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws ResourceUnavailableException, ResourceAllocationException,
|
||||
ConcurrentOperationException, InsufficientCapacityException {
|
||||
|
||||
CallContext.current().setEventDetails("Nic Id: " + getNicId() );
|
||||
String ip;
|
||||
if ((ip = getIpaddress()) != null) {
|
||||
if (!NetUtils.isValidIp(ip)) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Invalid ip address " + ip);
|
||||
}
|
||||
}
|
||||
|
||||
UserVm vm = _userVmService.updateNicIpForVirtualMachine(this);
|
||||
ArrayList<VMDetails> dc = new ArrayList<VMDetails>();
|
||||
dc.add(VMDetails.valueOf("nics"));
|
||||
EnumSet<VMDetails> details = EnumSet.copyOf(dc);
|
||||
if (vm != null){
|
||||
UserVmResponse response = _responseGenerator.createUserVmResponse(ResponseView.Restricted, "virtualmachine", details, vm).get(0);
|
||||
response.setResponseName(getCommandName());
|
||||
this.setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update ip address on vm NIC. Refer to server logs for details.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSyncObjType() {
|
||||
return BaseAsyncCmd.networkSyncObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getSyncObjId() {
|
||||
return getNetworkId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiCommandJobType getInstanceType() {
|
||||
return ApiCommandJobType.IpAddress;
|
||||
}
|
||||
|
||||
}
|
||||
@ -441,6 +441,7 @@ label.capacity=Capacity
|
||||
label.capacity.bytes=Capacity Bytes
|
||||
label.capacity.iops=Capacity IOPS
|
||||
label.certificate=Server certificate
|
||||
label.change.ipaddress=Change IP address for NIC
|
||||
label.change.service.offering=Change service offering
|
||||
label.change.value=Change value
|
||||
label.character=Character
|
||||
@ -1783,6 +1784,7 @@ message.apply.snapshot.policy=You have successfully updated your current snapsho
|
||||
message.attach.iso.confirm=Please confirm that you want to attach the ISO to this virtual instance.
|
||||
message.attach.volume=Please fill in the following data to attach a new volume. If you are attaching a disk volume to a Windows based virtual machine, you will need to reboot the instance to see the attached disk.
|
||||
message.basic.mode.desc=Choose this network model if you do <b>*<u>not</u>*</b> want to enable any VLAN support. All virtual instances created under this network model will be assigned an IP directly from the network and security groups are used to provide security and segregation.
|
||||
message.change.ipaddress=Please confirm that you would like to change the IP address for this NIC on VM.
|
||||
message.change.offering.confirm=Please confirm that you wish to change the service offering of this virtual instance.
|
||||
message.change.password=Please change your password.
|
||||
message.configure.all.traffic.types=You have multiple physical networks; please configure labels for each traffic type by clicking on the Edit button.
|
||||
|
||||
@ -402,6 +402,7 @@ updateDefaultNicForVirtualMachine=15
|
||||
####
|
||||
addIpToNic=15
|
||||
removeIpFromNic=15
|
||||
updateVmNicIp=15
|
||||
listNics=15
|
||||
|
||||
#### SSH key pair commands
|
||||
|
||||
@ -667,137 +667,137 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
IPAddressVO addr = Transaction.execute(new TransactionCallbackWithException<IPAddressVO, InsufficientAddressCapacityException>() {
|
||||
@Override
|
||||
public IPAddressVO doInTransaction(TransactionStatus status) throws InsufficientAddressCapacityException {
|
||||
StringBuilder errorMessage = new StringBuilder("Unable to get ip adress in ");
|
||||
boolean fetchFromDedicatedRange = false;
|
||||
List<Long> dedicatedVlanDbIds = new ArrayList<Long>();
|
||||
List<Long> nonDedicatedVlanDbIds = new ArrayList<Long>();
|
||||
StringBuilder errorMessage = new StringBuilder("Unable to get ip adress in ");
|
||||
boolean fetchFromDedicatedRange = false;
|
||||
List<Long> dedicatedVlanDbIds = new ArrayList<Long>();
|
||||
List<Long> nonDedicatedVlanDbIds = new ArrayList<Long>();
|
||||
|
||||
SearchCriteria<IPAddressVO> sc = null;
|
||||
if (podId != null) {
|
||||
sc = AssignIpAddressFromPodVlanSearch.create();
|
||||
sc.setJoinParameters("podVlanMapSB", "podId", podId);
|
||||
errorMessage.append(" pod id=" + podId);
|
||||
} else {
|
||||
sc = AssignIpAddressSearch.create();
|
||||
errorMessage.append(" zone id=" + dcId);
|
||||
}
|
||||
SearchCriteria<IPAddressVO> sc = null;
|
||||
if (podId != null) {
|
||||
sc = AssignIpAddressFromPodVlanSearch.create();
|
||||
sc.setJoinParameters("podVlanMapSB", "podId", podId);
|
||||
errorMessage.append(" pod id=" + podId);
|
||||
} else {
|
||||
sc = AssignIpAddressSearch.create();
|
||||
errorMessage.append(" zone id=" + dcId);
|
||||
}
|
||||
|
||||
// If owner has dedicated Public IP ranges, fetch IP from the dedicated range
|
||||
// Otherwise fetch IP from the system pool
|
||||
List<AccountVlanMapVO> maps = _accountVlanMapDao.listAccountVlanMapsByAccount(owner.getId());
|
||||
for (AccountVlanMapVO map : maps) {
|
||||
if (vlanDbIds == null || vlanDbIds.contains(map.getVlanDbId()))
|
||||
dedicatedVlanDbIds.add(map.getVlanDbId());
|
||||
}
|
||||
List<DomainVlanMapVO> domainMaps = _domainVlanMapDao.listDomainVlanMapsByDomain(owner.getDomainId());
|
||||
for (DomainVlanMapVO map : domainMaps) {
|
||||
if (vlanDbIds == null || vlanDbIds.contains(map.getVlanDbId()))
|
||||
dedicatedVlanDbIds.add(map.getVlanDbId());
|
||||
}
|
||||
List<VlanVO> nonDedicatedVlans = _vlanDao.listZoneWideNonDedicatedVlans(dcId);
|
||||
for (VlanVO nonDedicatedVlan : nonDedicatedVlans) {
|
||||
if (vlanDbIds == null || vlanDbIds.contains(nonDedicatedVlan.getId()))
|
||||
nonDedicatedVlanDbIds.add(nonDedicatedVlan.getId());
|
||||
}
|
||||
if (dedicatedVlanDbIds != null && !dedicatedVlanDbIds.isEmpty()) {
|
||||
fetchFromDedicatedRange = true;
|
||||
sc.setParameters("vlanId", dedicatedVlanDbIds.toArray());
|
||||
errorMessage.append(", vlanId id=" + Arrays.toString(dedicatedVlanDbIds.toArray()));
|
||||
} else if (nonDedicatedVlanDbIds != null && !nonDedicatedVlanDbIds.isEmpty()) {
|
||||
sc.setParameters("vlanId", nonDedicatedVlanDbIds.toArray());
|
||||
errorMessage.append(", vlanId id=" + Arrays.toString(nonDedicatedVlanDbIds.toArray()));
|
||||
} else {
|
||||
if (podId != null) {
|
||||
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Insufficient address capacity", Pod.class, podId);
|
||||
ex.addProxyObject(ApiDBUtils.findPodById(podId).getUuid());
|
||||
throw ex;
|
||||
}
|
||||
s_logger.warn(errorMessage.toString());
|
||||
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Insufficient address capacity", DataCenter.class, dcId);
|
||||
ex.addProxyObject(ApiDBUtils.findZoneById(dcId).getUuid());
|
||||
throw ex;
|
||||
}
|
||||
// If owner has dedicated Public IP ranges, fetch IP from the dedicated range
|
||||
// Otherwise fetch IP from the system pool
|
||||
List<AccountVlanMapVO> maps = _accountVlanMapDao.listAccountVlanMapsByAccount(owner.getId());
|
||||
for (AccountVlanMapVO map : maps) {
|
||||
if (vlanDbIds == null || vlanDbIds.contains(map.getVlanDbId()))
|
||||
dedicatedVlanDbIds.add(map.getVlanDbId());
|
||||
}
|
||||
List<DomainVlanMapVO> domainMaps = _domainVlanMapDao.listDomainVlanMapsByDomain(owner.getDomainId());
|
||||
for (DomainVlanMapVO map : domainMaps) {
|
||||
if (vlanDbIds == null || vlanDbIds.contains(map.getVlanDbId()))
|
||||
dedicatedVlanDbIds.add(map.getVlanDbId());
|
||||
}
|
||||
List<VlanVO> nonDedicatedVlans = _vlanDao.listZoneWideNonDedicatedVlans(dcId);
|
||||
for (VlanVO nonDedicatedVlan : nonDedicatedVlans) {
|
||||
if (vlanDbIds == null || vlanDbIds.contains(nonDedicatedVlan.getId()))
|
||||
nonDedicatedVlanDbIds.add(nonDedicatedVlan.getId());
|
||||
}
|
||||
if (dedicatedVlanDbIds != null && !dedicatedVlanDbIds.isEmpty()) {
|
||||
fetchFromDedicatedRange = true;
|
||||
sc.setParameters("vlanId", dedicatedVlanDbIds.toArray());
|
||||
errorMessage.append(", vlanId id=" + Arrays.toString(dedicatedVlanDbIds.toArray()));
|
||||
} else if (nonDedicatedVlanDbIds != null && !nonDedicatedVlanDbIds.isEmpty()) {
|
||||
sc.setParameters("vlanId", nonDedicatedVlanDbIds.toArray());
|
||||
errorMessage.append(", vlanId id=" + Arrays.toString(nonDedicatedVlanDbIds.toArray()));
|
||||
} else {
|
||||
if (podId != null) {
|
||||
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Insufficient address capacity", Pod.class, podId);
|
||||
ex.addProxyObject(ApiDBUtils.findPodById(podId).getUuid());
|
||||
throw ex;
|
||||
}
|
||||
s_logger.warn(errorMessage.toString());
|
||||
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Insufficient address capacity", DataCenter.class, dcId);
|
||||
ex.addProxyObject(ApiDBUtils.findZoneById(dcId).getUuid());
|
||||
throw ex;
|
||||
}
|
||||
|
||||
sc.setParameters("dc", dcId);
|
||||
sc.setParameters("dc", dcId);
|
||||
|
||||
DataCenter zone = _entityMgr.findById(DataCenter.class, dcId);
|
||||
DataCenter zone = _entityMgr.findById(DataCenter.class, dcId);
|
||||
|
||||
// for direct network take ip addresses only from the vlans belonging to the network
|
||||
if (vlanUse == VlanType.DirectAttached) {
|
||||
sc.setJoinParameters("vlan", "networkId", guestNetworkId);
|
||||
errorMessage.append(", network id=" + guestNetworkId);
|
||||
}
|
||||
sc.setJoinParameters("vlan", "type", vlanUse);
|
||||
// for direct network take ip addresses only from the vlans belonging to the network
|
||||
if (vlanUse == VlanType.DirectAttached) {
|
||||
sc.setJoinParameters("vlan", "networkId", guestNetworkId);
|
||||
errorMessage.append(", network id=" + guestNetworkId);
|
||||
}
|
||||
sc.setJoinParameters("vlan", "type", vlanUse);
|
||||
|
||||
if (requestedIp != null) {
|
||||
sc.addAnd("address", SearchCriteria.Op.EQ, requestedIp);
|
||||
errorMessage.append(": requested ip " + requestedIp + " is not available");
|
||||
}
|
||||
if (requestedIp != null) {
|
||||
sc.addAnd("address", SearchCriteria.Op.EQ, requestedIp);
|
||||
errorMessage.append(": requested ip " + requestedIp + " is not available");
|
||||
}
|
||||
|
||||
Filter filter = new Filter(IPAddressVO.class, "vlanId", true, 0l, 1l);
|
||||
Filter filter = new Filter(IPAddressVO.class, "vlanId", true, 0l, 1l);
|
||||
|
||||
List<IPAddressVO> addrs = _ipAddressDao.lockRows(sc, filter, true);
|
||||
List<IPAddressVO> addrs = _ipAddressDao.lockRows(sc, filter, true);
|
||||
|
||||
// If all the dedicated IPs of the owner are in use fetch an IP from the system pool
|
||||
if (addrs.size() == 0 && fetchFromDedicatedRange) {
|
||||
// Verify if account is allowed to acquire IPs from the system
|
||||
boolean useSystemIps = UseSystemPublicIps.valueIn(owner.getId());
|
||||
if (useSystemIps && nonDedicatedVlanDbIds != null && !nonDedicatedVlanDbIds.isEmpty()) {
|
||||
fetchFromDedicatedRange = false;
|
||||
sc.setParameters("vlanId", nonDedicatedVlanDbIds.toArray());
|
||||
errorMessage.append(", vlanId id=" + Arrays.toString(nonDedicatedVlanDbIds.toArray()));
|
||||
addrs = _ipAddressDao.lockRows(sc, filter, true);
|
||||
}
|
||||
}
|
||||
// If all the dedicated IPs of the owner are in use fetch an IP from the system pool
|
||||
if (addrs.size() == 0 && fetchFromDedicatedRange) {
|
||||
// Verify if account is allowed to acquire IPs from the system
|
||||
boolean useSystemIps = UseSystemPublicIps.valueIn(owner.getId());
|
||||
if (useSystemIps && nonDedicatedVlanDbIds != null && !nonDedicatedVlanDbIds.isEmpty()) {
|
||||
fetchFromDedicatedRange = false;
|
||||
sc.setParameters("vlanId", nonDedicatedVlanDbIds.toArray());
|
||||
errorMessage.append(", vlanId id=" + Arrays.toString(nonDedicatedVlanDbIds.toArray()));
|
||||
addrs = _ipAddressDao.lockRows(sc, filter, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (addrs.size() == 0) {
|
||||
if (podId != null) {
|
||||
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Insufficient address capacity", Pod.class, podId);
|
||||
// for now, we hardcode the table names, but we should ideally do a lookup for the tablename from the VO object.
|
||||
ex.addProxyObject(ApiDBUtils.findPodById(podId).getUuid());
|
||||
throw ex;
|
||||
}
|
||||
s_logger.warn(errorMessage.toString());
|
||||
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Insufficient address capacity", DataCenter.class, dcId);
|
||||
ex.addProxyObject(ApiDBUtils.findZoneById(dcId).getUuid());
|
||||
throw ex;
|
||||
}
|
||||
if (addrs.size() == 0) {
|
||||
if (podId != null) {
|
||||
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Insufficient address capacity", Pod.class, podId);
|
||||
// for now, we hardcode the table names, but we should ideally do a lookup for the tablename from the VO object.
|
||||
ex.addProxyObject(ApiDBUtils.findPodById(podId).getUuid());
|
||||
throw ex;
|
||||
}
|
||||
s_logger.warn(errorMessage.toString());
|
||||
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Insufficient address capacity", DataCenter.class, dcId);
|
||||
ex.addProxyObject(ApiDBUtils.findZoneById(dcId).getUuid());
|
||||
throw ex;
|
||||
}
|
||||
|
||||
assert (addrs.size() == 1) : "Return size is incorrect: " + addrs.size();
|
||||
assert (addrs.size() == 1) : "Return size is incorrect: " + addrs.size();
|
||||
|
||||
if (!fetchFromDedicatedRange && VlanType.VirtualNetwork.equals(vlanUse)) {
|
||||
// Check that the maximum number of public IPs for the given accountId will not be exceeded
|
||||
try {
|
||||
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.public_ip);
|
||||
} catch (ResourceAllocationException ex) {
|
||||
s_logger.warn("Failed to allocate resource of type " + ex.getResourceType() + " for account " + owner);
|
||||
throw new AccountLimitException("Maximum number of public IP addresses for account: " + owner.getAccountName() + " has been exceeded.");
|
||||
}
|
||||
}
|
||||
if (!fetchFromDedicatedRange && VlanType.VirtualNetwork.equals(vlanUse)) {
|
||||
// Check that the maximum number of public IPs for the given accountId will not be exceeded
|
||||
try {
|
||||
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.public_ip);
|
||||
} catch (ResourceAllocationException ex) {
|
||||
s_logger.warn("Failed to allocate resource of type " + ex.getResourceType() + " for account " + owner);
|
||||
throw new AccountLimitException("Maximum number of public IP addresses for account: " + owner.getAccountName() + " has been exceeded.");
|
||||
}
|
||||
}
|
||||
|
||||
IPAddressVO addr = addrs.get(0);
|
||||
addr.setSourceNat(sourceNat);
|
||||
addr.setAllocatedTime(new Date());
|
||||
addr.setAllocatedInDomainId(owner.getDomainId());
|
||||
addr.setAllocatedToAccountId(owner.getId());
|
||||
addr.setSystem(isSystem);
|
||||
IPAddressVO addr = addrs.get(0);
|
||||
addr.setSourceNat(sourceNat);
|
||||
addr.setAllocatedTime(new Date());
|
||||
addr.setAllocatedInDomainId(owner.getDomainId());
|
||||
addr.setAllocatedToAccountId(owner.getId());
|
||||
addr.setSystem(isSystem);
|
||||
if (displayIp != null) {
|
||||
addr.setDisplay(displayIp);
|
||||
}
|
||||
|
||||
if (assign) {
|
||||
markPublicIpAsAllocated(addr);
|
||||
} else {
|
||||
addr.setState(IpAddress.State.Allocating);
|
||||
}
|
||||
addr.setState(assign ? IpAddress.State.Allocated : IpAddress.State.Allocating);
|
||||
if (assign) {
|
||||
markPublicIpAsAllocated(addr);
|
||||
} else {
|
||||
addr.setState(IpAddress.State.Allocating);
|
||||
}
|
||||
addr.setState(assign ? IpAddress.State.Allocated : IpAddress.State.Allocating);
|
||||
|
||||
if (vlanUse != VlanType.DirectAttached) {
|
||||
addr.setAssociatedWithNetworkId(guestNetworkId);
|
||||
addr.setVpcId(vpcId);
|
||||
}
|
||||
if (vlanUse != VlanType.DirectAttached) {
|
||||
addr.setAssociatedWithNetworkId(guestNetworkId);
|
||||
addr.setVpcId(vpcId);
|
||||
}
|
||||
|
||||
_ipAddressDao.update(addr.getId(), addr);
|
||||
_ipAddressDao.update(addr.getId(), addr);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
@ -442,6 +442,7 @@ import org.apache.cloudstack.api.command.user.vm.StartVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.StopVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateDefaultNicForVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateVmNicIpCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd;
|
||||
import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd;
|
||||
@ -2895,6 +2896,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
cmdList.add(DeleteVMSnapshotCmd.class);
|
||||
cmdList.add(AddIpToVmNicCmd.class);
|
||||
cmdList.add(RemoveIpFromVmNicCmd.class);
|
||||
cmdList.add(UpdateVmNicIpCmd.class);
|
||||
cmdList.add(ListNicsCmd.class);
|
||||
cmdList.add(ArchiveAlertsCmd.class);
|
||||
cmdList.add(DeleteAlertsCmd.class);
|
||||
|
||||
@ -58,6 +58,7 @@ import org.apache.cloudstack.api.command.user.vm.ScaleVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.StartVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateDefaultNicForVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateVmNicIpCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd;
|
||||
import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd;
|
||||
@ -142,6 +143,7 @@ import com.cloud.event.dao.UsageEventDao;
|
||||
import com.cloud.exception.AgentUnavailableException;
|
||||
import com.cloud.exception.CloudException;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientAddressCapacityException;
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.ManagementServerException;
|
||||
@ -159,6 +161,7 @@ import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.hypervisor.HypervisorCapabilitiesVO;
|
||||
import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
|
||||
import com.cloud.network.IpAddressManager;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.Network.IpAddresses;
|
||||
import com.cloud.network.Network.Provider;
|
||||
@ -472,6 +475,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
||||
DomainRouterDao _routerDao;
|
||||
@Inject
|
||||
protected VMNetworkMapDao _vmNetworkMapDao;
|
||||
@Inject
|
||||
protected IpAddressManager _ipAddrMgr;
|
||||
|
||||
protected ScheduledExecutorService _executor = null;
|
||||
protected int _expungeInterval;
|
||||
@ -1408,6 +1413,96 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
||||
+ nic.getNetworkId() + ") of the chosen nic");
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserVm updateNicIpForVirtualMachine(UpdateVmNicIpCmd cmd) {
|
||||
Long nicId = cmd.getNicId();
|
||||
String ipaddr = cmd.getIpaddress();
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
//check whether the nic belongs to user vm.
|
||||
NicVO nicVO = _nicDao.findById(nicId);
|
||||
if (nicVO == null) {
|
||||
throw new InvalidParameterValueException("There is no nic for the " + nicId);
|
||||
}
|
||||
|
||||
if (nicVO.getVmType() != VirtualMachine.Type.User) {
|
||||
throw new InvalidParameterValueException("The nic is not belongs to user vm");
|
||||
}
|
||||
|
||||
UserVm vm = _vmDao.findById(nicVO.getInstanceId());
|
||||
if (vm == null) {
|
||||
throw new InvalidParameterValueException("There is no vm with the nic");
|
||||
}
|
||||
if (vm.getState() != State.Stopped) {
|
||||
throw new InvalidParameterValueException("The vm is not Stopped, please stop it before update Vm nic Ip");
|
||||
}
|
||||
|
||||
if (!_networkModel.listNetworkOfferingServices(nicVO.getNetworkId()).isEmpty() && vm.getState() != State.Stopped) {
|
||||
InvalidParameterValueException ex = new InvalidParameterValueException(
|
||||
"VM is not Stopped, unable to update the vm nic having the specified id");
|
||||
ex.addProxyObject(vm.getUuid(), "vmId");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
// verify permissions
|
||||
_accountMgr.checkAccess(caller, null, true, vm);
|
||||
Account ipOwner = _accountDao.findByIdIncludingRemoved(vm.getAccountId());
|
||||
|
||||
// verify ip address
|
||||
s_logger.debug("Calling the ip allocation ...");
|
||||
Network network = _networkDao.findById(nicVO.getNetworkId());
|
||||
DataCenter dc = _dcDao.findById(network.getDataCenterId());
|
||||
if (dc.getNetworkType() == NetworkType.Advanced && network.getGuestType() == Network.GuestType.Isolated) {
|
||||
try {
|
||||
ipaddr = _ipAddrMgr.allocateGuestIP(network, ipaddr);
|
||||
} catch (InsufficientAddressCapacityException e) {
|
||||
throw new InvalidParameterValueException("Allocating ip to guest nic " + nicVO.getUuid() + " failed, for insufficient address capacity");
|
||||
}
|
||||
if (ipaddr == null) {
|
||||
throw new InvalidParameterValueException("Allocating ip to guest nic " + nicVO.getUuid() + " failed, please choose another ip");
|
||||
}
|
||||
} else if (dc.getNetworkType() == NetworkType.Basic || network.getGuestType() == Network.GuestType.Shared) {
|
||||
//handle the basic networks here
|
||||
//for basic zone, need to provide the podId to ensure proper ip alloation
|
||||
Long podId = null;
|
||||
if (dc.getNetworkType() == NetworkType.Basic) {
|
||||
podId = vm.getPodIdToDeployIn();
|
||||
if (podId == null) {
|
||||
throw new InvalidParameterValueException("vm pod id is null in Basic zone; can't decide the range for ip allocation");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
ipaddr = _ipAddrMgr.allocatePublicIpForGuestNic(network, podId, ipOwner, ipaddr);
|
||||
if (ipaddr == null) {
|
||||
throw new InvalidParameterValueException("Allocating ip to guest nic " + nicVO.getUuid() + " failed, please choose another ip");
|
||||
}
|
||||
final IPAddressVO ip = _ipAddressDao.findByIpAndSourceNetworkId(nicVO.getNetworkId(), nicVO.getIPv4Address());
|
||||
if (ip != null) {
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
_ipAddrMgr.markIpAsUnavailable(ip.getId());
|
||||
_ipAddressDao.unassignIpAddress(ip.getId());
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (InsufficientAddressCapacityException e) {
|
||||
s_logger.error("Allocating ip to guest nic " + nicVO.getUuid() + " failed, for insufficient address capacity");
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
s_logger.error("UpdateVmNicIpCmd is not supported in this network...");
|
||||
return null;
|
||||
}
|
||||
|
||||
// update nic ipaddress
|
||||
nicVO.setIPv4Address(ipaddr);
|
||||
_nicDao.persist(nicVO);
|
||||
|
||||
return vm;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_VM_UPGRADE, eventDescription = "Upgrading VM", async = true)
|
||||
public UserVm upgradeVirtualMachine(ScaleVMCmd cmd) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException,
|
||||
|
||||
@ -151,6 +151,7 @@ known_categories = {
|
||||
'Detail': 'Resource metadata',
|
||||
'addIpToNic': 'Nic',
|
||||
'removeIpFromNic': 'Nic',
|
||||
'updateVmNicIp': 'Nic',
|
||||
'listNics':'Nic',
|
||||
'AffinityGroup': 'Affinity Group',
|
||||
'addImageStore': 'Image Store',
|
||||
|
||||
@ -2308,6 +2308,7 @@ div.detail-group.actions td {
|
||||
height: 35px;
|
||||
float: right;
|
||||
padding: 0;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.details.group-multiple div.detail-group.actions .detail-actions .action {
|
||||
@ -12908,12 +12909,14 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it
|
||||
|
||||
.replaceacllist .icon,
|
||||
.replaceACL .icon,
|
||||
.updateIpaddr .icon,
|
||||
.changeAffinity .icon {
|
||||
background-position: -264px -2px;
|
||||
}
|
||||
|
||||
.replaceacllist:hover .icon,
|
||||
.replaceACL:hover .icon,
|
||||
.updateIpaddr:hover .icon,
|
||||
.changeAffinity:hover .icon {
|
||||
background-position: -263px -583px;
|
||||
}
|
||||
|
||||
@ -458,6 +458,7 @@ dictionary = {
|
||||
'label.cancel': '<fmt:message key="label.cancel" />',
|
||||
'label.capacity': '<fmt:message key="label.capacity" />',
|
||||
'label.certificate': '<fmt:message key="label.certificate" />',
|
||||
'label.change.ipaddress': '<fmt:message key="label.change.ipaddress" />',
|
||||
'label.change.service.offering': '<fmt:message key="label.change.service.offering" />',
|
||||
'label.change.value': '<fmt:message key="label.change.value" />',
|
||||
'label.character': '<fmt:message key="label.character" />',
|
||||
|
||||
@ -449,6 +449,7 @@ under the License.
|
||||
'message.attach.iso.confirm': '<fmt:message key="message.attach.iso.confirm" />',
|
||||
'message.attach.volume': '<fmt:message key="message.attach.volume" />',
|
||||
'message.basic.mode.desc': '<fmt:message key="message.basic.mode.desc" />',
|
||||
'message.change.ipaddress': '<fmt:message key="message.change.ipaddress" />',
|
||||
'message.change.offering.confirm': '<fmt:message key="message.change.offering.confirm" />',
|
||||
'message.change.password': '<fmt:message key="message.change.password" />',
|
||||
'message.configure.all.traffic.types': '<fmt:message key="message.configure.all.traffic.types" />',
|
||||
|
||||
@ -2364,6 +2364,103 @@
|
||||
}
|
||||
},
|
||||
|
||||
updateIpaddr: {
|
||||
label: 'label.change.ipaddress',
|
||||
messages: {
|
||||
confirm: function() {
|
||||
return 'message.change.ipaddress';
|
||||
},
|
||||
notification: function(args) {
|
||||
return 'label.change.ipaddress';
|
||||
}
|
||||
},
|
||||
createForm: {
|
||||
title: 'label.change.ipaddress',
|
||||
desc: 'message.change.ipaddress',
|
||||
preFilter: function(args) {
|
||||
if (args.context.nics != null && args.context.nics[0].type == 'Isolated') {
|
||||
args.$form.find('.form-item[rel=ipaddress1]').css('display', 'inline-block'); //shown text
|
||||
args.$form.find('.form-item[rel=ipaddress2]').hide();
|
||||
} else if (args.context.nics != null && args.context.nics[0].type == 'Shared') {
|
||||
args.$form.find('.form-item[rel=ipaddress2]').css('display', 'inline-block'); //shown list
|
||||
args.$form.find('.form-item[rel=ipaddress1]').hide();
|
||||
}
|
||||
},
|
||||
fields: {
|
||||
ipaddress1: {
|
||||
label: 'label.ip.address'
|
||||
},
|
||||
ipaddress2: {
|
||||
label: 'label.ip.address',
|
||||
select: function(args) {
|
||||
if (args.context.nics != null && args.context.nics[0].type == 'Shared') {
|
||||
$.ajax({
|
||||
url: createURL('listPublicIpAddresses'),
|
||||
data: {
|
||||
allocatedonly: false,
|
||||
networkid: args.context.nics[0].networkid,
|
||||
forvirtualnetwork: false
|
||||
},
|
||||
success: function(json) {
|
||||
var ips = json.listpublicipaddressesresponse.publicipaddress;
|
||||
var items = [{
|
||||
id: -1,
|
||||
description: ''
|
||||
}];
|
||||
$(ips).each(function() {
|
||||
if (this.state == "Free") {
|
||||
items.push({
|
||||
id: this.ipaddress,
|
||||
description: this.ipaddress
|
||||
});
|
||||
}
|
||||
});
|
||||
args.response.success({
|
||||
data: items
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
args.response.success({
|
||||
data: null
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
action: function(args) {
|
||||
var dataObj = {
|
||||
nicId: args.context.nics[0].id
|
||||
};
|
||||
|
||||
if (args.data.ipaddress1) {
|
||||
dataObj.ipaddress = args.data.ipaddress1;
|
||||
} else if (args.data.ipaddress2 != -1) {
|
||||
dataObj.ipaddress = args.data.ipaddress2;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: createURL('updateVmNicIp'),
|
||||
data: dataObj,
|
||||
success: function(json) {
|
||||
args.response.success({
|
||||
_custom: {
|
||||
jobId: json.updatevmnicipresponse.jobid,
|
||||
getUpdatedItem: function(json) {
|
||||
return json.queryasyncjobresultresponse.jobresult.virtualmachine;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
notification: {
|
||||
poll: pollAsyncJobResult
|
||||
}
|
||||
},
|
||||
|
||||
// Remove NIC/Network from VM
|
||||
remove: {
|
||||
label: 'label.action.delete.nic',
|
||||
@ -2463,9 +2560,9 @@
|
||||
args.response.success({
|
||||
actionFilter: function(args) {
|
||||
if (args.context.item.isdefault) {
|
||||
return [];
|
||||
return ['updateIpaddr'];
|
||||
} else {
|
||||
return ['remove', 'makeDefault'];
|
||||
return ['remove', 'makeDefault', 'updateIpaddr'];
|
||||
}
|
||||
},
|
||||
data: $.map(json.listvirtualmachinesresponse.virtualmachine[0].nic, function(nic, index) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user