mirror of https://github.com/apache/cloudstack.git
694 lines
32 KiB
Java
694 lines
32 KiB
Java
// 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 com.cloud.network;
|
|
|
|
import java.util.List;
|
|
|
|
import javax.inject.Inject;
|
|
|
|
import org.apache.log4j.Logger;
|
|
|
|
import org.apache.cloudstack.context.CallContext;
|
|
import org.apache.cloudstack.engine.cloud.entity.api.db.VMNetworkMapVO;
|
|
import org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMNetworkMapDao;
|
|
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
|
import org.apache.cloudstack.resourcedetail.FirewallRuleDetailVO;
|
|
import org.apache.cloudstack.resourcedetail.VpcDetailVO;
|
|
import org.apache.cloudstack.resourcedetail.dao.FirewallRuleDetailsDao;
|
|
import org.apache.cloudstack.resourcedetail.dao.VpcDetailsDao;
|
|
|
|
import com.cloud.configuration.Resource;
|
|
import com.cloud.dc.DataCenter;
|
|
import com.cloud.dc.dao.DataCenterDao;
|
|
import com.cloud.deploy.DataCenterDeployment;
|
|
import com.cloud.deploy.DeployDestination;
|
|
import com.cloud.exception.InsufficientAddressCapacityException;
|
|
import com.cloud.exception.InsufficientCapacityException;
|
|
import com.cloud.exception.InsufficientVirtualNetworkCapacityException;
|
|
import com.cloud.exception.InvalidParameterValueException;
|
|
import com.cloud.exception.ResourceAllocationException;
|
|
import com.cloud.exception.ResourceUnavailableException;
|
|
import com.cloud.host.Host;
|
|
import com.cloud.host.dao.HostDao;
|
|
import com.cloud.network.dao.FirewallRulesCidrsDao;
|
|
import com.cloud.network.dao.FirewallRulesCidrsVO;
|
|
import com.cloud.network.dao.FirewallRulesDao;
|
|
import com.cloud.network.dao.IPAddressDao;
|
|
import com.cloud.network.dao.IPAddressVO;
|
|
import com.cloud.network.dao.NetworkDao;
|
|
import com.cloud.network.dao.NetworkDetailVO;
|
|
import com.cloud.network.dao.NetworkDetailsDao;
|
|
import com.cloud.network.dao.NetworkDomainDao;
|
|
import com.cloud.network.dao.NetworkDomainVO;
|
|
import com.cloud.network.dao.NetworkVO;
|
|
import com.cloud.network.dao.RouterNetworkDao;
|
|
import com.cloud.network.dao.RouterNetworkVO;
|
|
import com.cloud.network.guru.NetworkGuru;
|
|
import com.cloud.network.router.VirtualRouter;
|
|
import com.cloud.network.rules.FirewallRule;
|
|
import com.cloud.network.rules.FirewallRuleVO;
|
|
import com.cloud.network.rules.RulesManager;
|
|
import com.cloud.network.vpc.NetworkACLVO;
|
|
import com.cloud.network.vpc.Vpc;
|
|
import com.cloud.network.vpc.VpcGatewayVO;
|
|
import com.cloud.network.vpc.VpcManager;
|
|
import com.cloud.network.vpc.VpcService;
|
|
import com.cloud.network.vpc.VpcVO;
|
|
import com.cloud.network.vpc.dao.NetworkACLDao;
|
|
import com.cloud.network.vpc.dao.VpcDao;
|
|
import com.cloud.network.vpc.dao.VpcGatewayDao;
|
|
import com.cloud.offering.NetworkOffering;
|
|
import com.cloud.offerings.dao.NetworkOfferingDao;
|
|
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
|
|
import com.cloud.server.ResourceTag;
|
|
import com.cloud.tags.ResourceTagVO;
|
|
import com.cloud.tags.dao.ResourceTagDao;
|
|
import com.cloud.user.Account;
|
|
import com.cloud.user.AccountVO;
|
|
import com.cloud.user.ResourceLimitService;
|
|
import com.cloud.user.dao.AccountDao;
|
|
import com.cloud.utils.db.DB;
|
|
import com.cloud.utils.db.EntityManager;
|
|
import com.cloud.utils.db.Transaction;
|
|
import com.cloud.utils.db.TransactionCallback;
|
|
import com.cloud.utils.exception.CloudRuntimeException;
|
|
import com.cloud.vm.DomainRouterVO;
|
|
import com.cloud.vm.Nic;
|
|
import com.cloud.vm.NicDetailVO;
|
|
import com.cloud.vm.NicProfile;
|
|
import com.cloud.vm.NicVO;
|
|
import com.cloud.vm.ReservationContext;
|
|
import com.cloud.vm.ReservationContextImpl;
|
|
import com.cloud.vm.UserVmVO;
|
|
import com.cloud.vm.VirtualMachine;
|
|
import com.cloud.vm.VirtualMachineManager;
|
|
import com.cloud.vm.VirtualMachineProfile;
|
|
import com.cloud.vm.VirtualMachineProfileImpl;
|
|
import com.cloud.vm.dao.DomainRouterDao;
|
|
import com.cloud.vm.dao.NicDao;
|
|
import com.cloud.vm.dao.NicDetailsDao;
|
|
import com.cloud.vm.dao.NicIpAliasDao;
|
|
import com.cloud.vm.dao.NicSecondaryIpDao;
|
|
import com.cloud.vm.dao.UserVmDao;
|
|
|
|
public class NetworkMigrationManagerImpl implements NetworkMigrationManager {
|
|
public static final Logger s_logger = Logger.getLogger(NetworkMigrationManagerImpl.class.getName());
|
|
|
|
@Inject
|
|
private DataCenterDao _dcDao = null;
|
|
@Inject
|
|
private NetworkDetailsDao _networkDetailsDao = null;
|
|
@Inject
|
|
private AccountDao _accountDao = null;
|
|
@Inject
|
|
private NetworkDomainDao _networkDomainDao = null;
|
|
@Inject
|
|
private NetworkOrchestrationService _networkMgr = null;
|
|
@Inject
|
|
private ResourceLimitService _resourceLimitMgr = null;
|
|
@Inject
|
|
private NetworkDao _networksDao = null;
|
|
@Inject
|
|
private NetworkOfferingDao _networkOfferingDao = null;
|
|
@Inject
|
|
private NetworkOfferingServiceMapDao _networkOfferingServiceDao = null;
|
|
@Inject
|
|
private NicDao _nicDao = null;
|
|
@Inject
|
|
private NicSecondaryIpDao _nicSecondaryIpDao = null;
|
|
@Inject
|
|
private NicIpAliasDao _nicIpAliasDao = null;
|
|
@Inject
|
|
private NicDetailsDao _nicDetailsDao = null;
|
|
@Inject
|
|
private FirewallRulesDao _firewallDao = null;
|
|
@Inject
|
|
private FirewallRulesCidrsDao _firewallRulesCidrDao = null;
|
|
@Inject
|
|
private FirewallRuleDetailsDao _firewallRuleDetailsDao = null;
|
|
@Inject
|
|
private EntityManager _entityMgr = null;
|
|
@Inject
|
|
private RouterNetworkDao _routerNetworkDao = null;
|
|
@Inject
|
|
private DomainRouterDao _routerDao = null;
|
|
@Inject
|
|
private NetworkService _networkService = null;
|
|
@Inject
|
|
private UserVmDao _vmDao = null;
|
|
@Inject
|
|
private NetworkModel _networkModel= null;
|
|
@Inject
|
|
private VMNetworkMapDao _vmNetworkMapDao = null;
|
|
@Inject
|
|
private HostDao _hostDao = null;
|
|
@Inject
|
|
private VirtualMachineManager _itMgr = null;
|
|
@Inject
|
|
private IPAddressDao _ipAddressDao = null;
|
|
@Inject
|
|
private RulesManager _rulesMgr = null;
|
|
@Inject
|
|
private VpcDao _vpcDao = null;
|
|
@Inject
|
|
private VpcDetailsDao _vpcDetailsDao = null;
|
|
@Inject
|
|
private IpAddressManager _ipAddressManager = null;
|
|
@Inject
|
|
private VpcService _vpcService = null;
|
|
@Inject
|
|
private NetworkACLDao _networkACLDao = null;
|
|
@Inject
|
|
private VpcManager _vpcManager = null;
|
|
@Inject
|
|
private VpcGatewayDao _vpcGatewayDao = null;
|
|
@Inject
|
|
private ResourceTagDao _resourceTagDao = null;
|
|
|
|
@Override public long makeCopyOfNetwork(Network network, NetworkOffering networkOffering, Long vpcId) {
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Making a copy of network with uuid " + network.getUuid() + " and id " + network.getId() + " for migration.");
|
|
}
|
|
long originalNetworkId = network.getId();
|
|
NetworkDomainVO domainNetworkMapByNetworkId = _networkDomainDao.getDomainNetworkMapByNetworkId(originalNetworkId);
|
|
AccountVO networkAccount = _accountDao.findById(network.getAccountId());
|
|
|
|
boolean subdomainAccess = true;
|
|
if (domainNetworkMapByNetworkId != null) {
|
|
subdomainAccess = domainNetworkMapByNetworkId.isSubdomainAccess();
|
|
}
|
|
DataCenterDeployment plan = new DataCenterDeployment(network.getDataCenterId(), null, null, null, null, network.getPhysicalNetworkId());
|
|
|
|
List<? extends Network> networks = _networkMgr.setupNetwork(networkAccount, networkOffering, network, plan, network.getName(), network.getDisplayText(), true,
|
|
network.getDomainId(), network.getAclType(), subdomainAccess,
|
|
vpcId, true);
|
|
_resourceLimitMgr.incrementResourceCount(network.getAccountId(), Resource.ResourceType.network, network.isDisplay());
|
|
|
|
long networkCopyId;
|
|
if (networks == null || networks.isEmpty()) {
|
|
throw new CloudRuntimeException("Fail to create a network");
|
|
} else {
|
|
DataCenter zone = _dcDao.findById(network.getDataCenterId());
|
|
String guestNetworkCidr = zone.getGuestNetworkCidr();
|
|
|
|
if (networks.get(0).getGuestType() == Network.GuestType.Isolated
|
|
&& networks.get(0).getTrafficType() == Networks.TrafficType.Guest) {
|
|
Network networkCopy = networks.get(0);
|
|
for (final Network nw : networks) {
|
|
if (nw.getCidr() != null && nw.getCidr().equals(guestNetworkCidr)) {
|
|
networkCopy = nw;
|
|
}
|
|
}
|
|
networkCopyId = networkCopy.getId();
|
|
} else {
|
|
// For shared network
|
|
networkCopyId = networks.get(0).getId();
|
|
}
|
|
}
|
|
|
|
//Update the related network
|
|
NetworkVO originalNetwork = _networksDao.findById(originalNetworkId);
|
|
originalNetwork.setRelated(networkCopyId);
|
|
_networksDao.update(originalNetworkId, originalNetwork);
|
|
|
|
NetworkVO copiedNetwork = _networksDao.findById(networkCopyId);
|
|
copiedNetwork.setRelated(originalNetworkId);
|
|
copiedNetwork.setDisplayNetwork(false);
|
|
copiedNetwork.setBroadcastUri(network.getBroadcastUri());
|
|
copiedNetwork.setState(network.getState());
|
|
_networksDao.update(networkCopyId, copiedNetwork);
|
|
|
|
copyNetworkDetails(originalNetworkId, networkCopyId);
|
|
copyFirewallRulesToNewNetwork(network, networkCopyId);
|
|
assignUserNicsToNewNetwork(originalNetworkId, networkCopyId);
|
|
assignRouterNicsToNewNetwork(network.getId(), networkCopyId);
|
|
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Succesfully created a copy of network " + originalNetwork.getName() + "(" + originalNetwork.getUuid() + ") id is " + originalNetwork.getId() + " for migration. The network copy has uuid " + network.getUuid() + " and id " + network.getId());
|
|
}
|
|
return networkCopyId;
|
|
}
|
|
|
|
@DB
|
|
private void copyNetworkDetails(long srcNetworkId, long dstNetworkId) {
|
|
List<NetworkDetailVO> networkDetails = _networkDetailsDao.listDetails(srcNetworkId);
|
|
|
|
for (NetworkDetailVO networkDetail : networkDetails) {
|
|
_networkDetailsDao.persist(new NetworkDetailVO(dstNetworkId, networkDetail.getName(), networkDetail.getValue(), networkDetail.isDisplay()));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* reassigns the nics to the new network from the src network.
|
|
* @param srcNetworkId
|
|
* @param dstNetworkId
|
|
*/
|
|
private void assignUserNicsToNewNetwork(long srcNetworkId, long dstNetworkId) {
|
|
List<NicVO> nics = _nicDao.listByNetworkId(srcNetworkId);
|
|
|
|
for (NicVO nic : nics) {
|
|
if (nic.getVmType() == VirtualMachine.Type.User) {
|
|
nic.setNetworkId(dstNetworkId);
|
|
_nicDao.persist(nic);
|
|
|
|
//update the number of active nics in both networks after migration.
|
|
if (nic.getState() == Nic.State.Reserved) {
|
|
_networksDao.changeActiveNicsBy(srcNetworkId, -1);
|
|
_networksDao.changeActiveNicsBy(dstNetworkId, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
List<? extends IPAddressVO> publicIps = _ipAddressDao.listByAssociatedNetwork(srcNetworkId, null);
|
|
|
|
for (IPAddressVO ipAddress : publicIps) {
|
|
ipAddress.setAssociatedWithNetworkId(dstNetworkId);
|
|
_ipAddressDao.persist(ipAddress);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Long makeCopyOfVpc(long vpcId, long vpcOfferingId) {
|
|
VpcVO vpc = _vpcDao.findById(vpcId);
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Making a copy of vpc with uuid " + vpc.getUuid() + " and id " + vpc.getId() + " for migration.");
|
|
}
|
|
if (vpc == null) {
|
|
InvalidParameterValueException ex = new InvalidParameterValueException("Specified vpc id doesn't exist in the system");
|
|
ex.addProxyObject(String.valueOf(vpcId), "vpcId");
|
|
throw ex;
|
|
}
|
|
|
|
Vpc copyOfVpc;
|
|
long copyOfVpcId;
|
|
try {
|
|
copyOfVpc = _vpcService.createVpc(vpc.getZoneId(), vpcOfferingId, vpc.getAccountId(), vpc.getName(), vpc.getDisplayText(), vpc.getCidr(),
|
|
vpc.getNetworkDomain(), vpc.isDisplay());
|
|
copyOfVpcId = copyOfVpc.getId();
|
|
//on resume of migration the uuid will be swapped already. So the copy will have the value of the original vpcid.
|
|
_resourceTagDao.persist(new ResourceTagVO(MIGRATION, Long.toString(vpcId), vpc.getAccountId(), vpc.getDomainId(), copyOfVpcId, ResourceTag.ResourceObjectType.Vpc, null, vpc.getUuid()));
|
|
VpcVO copyVpcVO = _vpcDao.findById(copyOfVpcId);
|
|
vpc.setDisplay(false);
|
|
swapUuids(vpc, copyVpcVO);
|
|
reassignACLRulesToNewVpc(vpcId, copyOfVpcId);
|
|
reassignPublicIpsToNewVpc(vpcId, copyOfVpc);
|
|
copyVpcDetails(vpcId, copyOfVpcId);
|
|
reassignGatewayToNewVpc(vpcId, copyOfVpcId);
|
|
copyVpcResourceTagsToNewVpc(vpcId, copyOfVpcId);
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Succesfully created a copy of network " + vpc.getName() + "(" + vpc.getUuid() + ") id is " + vpc.getId() + " for migration. The network copy has uuid " + copyVpcVO.getUuid() + " and id " + copyOfVpc.getId());
|
|
}
|
|
} catch (ResourceAllocationException e) {
|
|
throw new CloudRuntimeException(e.getMessage());
|
|
}
|
|
|
|
return copyOfVpcId;
|
|
}
|
|
|
|
@Override
|
|
public void startVpc(Vpc vpc) {
|
|
if (vpc.getState() != Vpc.State.Enabled) {
|
|
try {
|
|
_vpcService.startVpc(vpc.getId(), true);
|
|
} catch (ResourceUnavailableException | InsufficientCapacityException e) {
|
|
s_logger.error("Vpc can not be started. Aborting migration process");
|
|
throw new CloudRuntimeException("Vpc can not be started.", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
private void copyVpcDetails(long srcVpcId, long dstVpcId) {
|
|
List<VpcDetailVO> vpcDetails = _vpcDetailsDao.listDetails(srcVpcId);
|
|
|
|
for (VpcDetailVO vpcDetail : vpcDetails) {
|
|
_vpcDetailsDao.persist(new VpcDetailVO(dstVpcId, vpcDetail.getName(), vpcDetail.getValue(), vpcDetail.isDisplay()));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reassign the ACL rules from the original vpc to the new VPC
|
|
* @param srcVpcId
|
|
* @param dstVpcId
|
|
*/
|
|
private void reassignACLRulesToNewVpc(long srcVpcId, long dstVpcId){
|
|
List<NetworkACLVO> networkACL = _networkACLDao.listByVpcId(srcVpcId);
|
|
|
|
for (NetworkACLVO aclList : networkACL) {
|
|
aclList.setVpcId(dstVpcId);
|
|
_networkACLDao.persist(aclList);
|
|
}
|
|
}
|
|
|
|
private void reassignPublicIpsToNewVpc(long srcVpcId, Vpc dstVpc) {
|
|
List<? extends IPAddressVO> publicIps = _ipAddressDao.listByAssociatedVpc(srcVpcId, _vpcManager.isSrcNatIpRequired(dstVpc.getVpcOfferingId()) ? null : false);
|
|
|
|
for(IPAddressVO publicIp : publicIps) {
|
|
publicIp.setVpcId(dstVpc.getId());
|
|
_ipAddressDao.persist(publicIp);
|
|
}
|
|
}
|
|
|
|
private void reassignGatewayToNewVpc(long srcVpcId, long dstVpcId){
|
|
List<VpcGatewayVO> vpcGateways = _vpcGatewayDao.listByVpcId(srcVpcId);
|
|
for (VpcGatewayVO vpcGateway : vpcGateways) {
|
|
vpcGateway.setVpcId(dstVpcId);
|
|
_vpcGatewayDao.persist(vpcGateway);
|
|
}
|
|
}
|
|
|
|
private void copyVpcResourceTagsToNewVpc(long srcVpcId, long dstVpcId){
|
|
List<? extends ResourceTag> resourceTags = _resourceTagDao.listBy(srcVpcId, ResourceTag.ResourceObjectType.Vpc);
|
|
for (ResourceTag resourceTag : resourceTags) {
|
|
resourceTag.setResourceId(dstVpcId);
|
|
_resourceTagDao.persist(
|
|
new ResourceTagVO(
|
|
resourceTag.getKey(),
|
|
resourceTag.getValue(),
|
|
resourceTag.getAccountId(),
|
|
resourceTag.getDomainId(),
|
|
dstVpcId,
|
|
resourceTag.getResourceType(),
|
|
resourceTag.getCustomer(),
|
|
resourceTag.getResourceUuid()));
|
|
}
|
|
}
|
|
|
|
private void copyFirewallRulesToNewNetwork(Network srcNetwork, long dstNetworkId) {
|
|
List<FirewallRuleVO> firewallRules = _firewallDao.listByNetworkPurposeTrafficType(srcNetwork.getId(), FirewallRule.Purpose.Firewall, FirewallRule.TrafficType.Egress);
|
|
firewallRules.addAll(_firewallDao.listByNetworkPurposeTrafficType(srcNetwork.getId(), FirewallRule.Purpose.Firewall, FirewallRule.TrafficType.Ingress));
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Copying firewall rules from network with id " + srcNetwork.getId() + " to network with id " + dstNetworkId);
|
|
}
|
|
|
|
//Loop over all the firewall rules in the original network and copy all values to a new firewall rule
|
|
//Copy all objects that are dependant on the firewall rules
|
|
for (FirewallRuleVO originalFirewallRule : firewallRules) {
|
|
FirewallRuleVO ruleVO = new FirewallRuleVO(originalFirewallRule.getXid(),
|
|
originalFirewallRule.getSourceIpAddressId(),
|
|
originalFirewallRule.getSourcePortStart(),
|
|
originalFirewallRule.getSourcePortEnd(),
|
|
originalFirewallRule.getProtocol(),
|
|
dstNetworkId,
|
|
srcNetwork.getAccountId(),
|
|
srcNetwork.getDomainId(),
|
|
originalFirewallRule.getPurpose(),
|
|
originalFirewallRule.getSourceCidrList(),
|
|
originalFirewallRule.getDestinationCidrList(),
|
|
originalFirewallRule.getIcmpCode(),
|
|
originalFirewallRule.getIcmpType(),
|
|
originalFirewallRule.getRelated(),
|
|
originalFirewallRule.getTrafficType(),
|
|
originalFirewallRule.getType());
|
|
|
|
ruleVO = _firewallDao.persist(ruleVO);
|
|
|
|
//Firewall rule cidrs
|
|
List<FirewallRulesCidrsVO> firewallRulesCidrsVOS = _firewallRulesCidrDao.listByFirewallRuleId(originalFirewallRule.getId());
|
|
for (FirewallRulesCidrsVO firewallRulesCidrVO: firewallRulesCidrsVOS) {
|
|
_firewallRulesCidrDao.persist(new FirewallRulesCidrsVO(ruleVO.getId(), firewallRulesCidrVO.getSourceCidrList()));
|
|
}
|
|
|
|
//Firewall rules details
|
|
List<FirewallRuleDetailVO> originalFirewallRuleDetails = _firewallRuleDetailsDao.listDetails(originalFirewallRule.getId());
|
|
for (FirewallRuleDetailVO originalFirewallRuleDetail : originalFirewallRuleDetails) {
|
|
_firewallRuleDetailsDao.persist(new FirewallRuleDetailVO(ruleVO.getId(), originalFirewallRuleDetail.getName(), originalFirewallRuleDetail.getValue(), originalFirewallRuleDetail.isDisplay()));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void assignRouterNicsToNewNetwork(long srcNetworkId, long dstNetworkId) {
|
|
final List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(srcNetworkId, VirtualRouter.Role.VIRTUAL_ROUTER);
|
|
for (DomainRouterVO domainRouter : routers) {
|
|
NicVO vrNic = _nicDao.findByNetworkIdAndType(srcNetworkId, VirtualMachine.Type.DomainRouter);
|
|
vrNic.setNetworkId(dstNetworkId);
|
|
_nicDao.update(vrNic.getId(), vrNic);
|
|
|
|
RouterNetworkVO routerNetwork = _routerNetworkDao.findByRouterAndNetwork(domainRouter.getId(), srcNetworkId);
|
|
routerNetwork.setNetworkId(dstNetworkId);
|
|
_routerNetworkDao.persist(routerNetwork);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Network upgradeNetworkToNewNetworkOffering(long networkId, long newPhysicalNetworkId, long networkOfferingId, Long vpcId) {
|
|
s_logger.debug("upgrading network to network with new offering.");
|
|
NetworkVO network = _networksDao.findById(networkId);
|
|
NetworkOffering newOffering = _networkOfferingDao.findByIdIncludingRemoved(networkOfferingId);
|
|
long gurusImplementing = 0;
|
|
network.setBroadcastUri(null);
|
|
AccountVO networkAccount = _accountDao.findById(network.getAccountId());
|
|
DataCenterDeployment plan = new DataCenterDeployment(network.getDataCenterId(), null, null, null, null, newPhysicalNetworkId);
|
|
for (final NetworkGuru guru : _networkMgr.getNetworkGurus()) {
|
|
|
|
final Network designedNetwork = guru.design(newOffering, plan, network, networkAccount);
|
|
if (designedNetwork == null) {
|
|
continue;
|
|
}
|
|
|
|
gurusImplementing++;
|
|
if (gurusImplementing > 1) {
|
|
throw new CloudRuntimeException("Failed to migrate network to new physical network. Multiple network guru's for the same network are currently not supported.");
|
|
}
|
|
|
|
network.setTrafficType(designedNetwork.getTrafficType());
|
|
network.setMode(designedNetwork.getMode());
|
|
network.setBroadcastDomainType(designedNetwork.getBroadcastDomainType());
|
|
network.setBroadcastUri(designedNetwork.getBroadcastUri());
|
|
network.setNetworkOfferingId(designedNetwork.getNetworkOfferingId());
|
|
network.setState(designedNetwork.getState());
|
|
network.setPhysicalNetworkId(designedNetwork.getPhysicalNetworkId());
|
|
network.setRedundant(designedNetwork.isRedundant());
|
|
network.setGateway(designedNetwork.getGateway());
|
|
network.setCidr(designedNetwork.getCidr());
|
|
network.setGuruName(guru.getName());
|
|
network.setVpcId(vpcId);
|
|
}
|
|
_networksDao.update(network.getId(), network, _networkMgr.finalizeServicesAndProvidersForNetwork(_entityMgr.findById(NetworkOffering.class, networkOfferingId), newPhysicalNetworkId));
|
|
return network;
|
|
}
|
|
|
|
@Override
|
|
public void deleteCopyOfNetwork(long networkCopyId, long originalNetworkId) {
|
|
NetworkVO networkCopy = _networksDao.findById(networkCopyId);
|
|
|
|
NicVO userNic = _nicDao.findByNetworkIdAndType(networkCopyId, VirtualMachine.Type.User);
|
|
if (userNic != null) {
|
|
s_logger.error("Something went wrong while migrating nics from the old network to the new network. Failed to delete copy of network. There are still user nics present in the network.");
|
|
throw new CloudRuntimeException("Failed to delete copy of network. There are still user nics present in the network.");
|
|
}
|
|
|
|
NetworkVO originalNetwork = _networksDao.findById(originalNetworkId);
|
|
|
|
swapUuids(originalNetwork, networkCopy);
|
|
try {
|
|
if (!_networkService.deleteNetwork(networkCopy.getId(), true)) {
|
|
throw new CloudRuntimeException("Failed to delete network. Clean up not successful.");
|
|
}
|
|
} finally {
|
|
swapUuids(networkCopy, originalNetwork);
|
|
}
|
|
originalNetwork.setRelated(originalNetworkId);
|
|
_networksDao.persist(originalNetwork);
|
|
}
|
|
|
|
@Override
|
|
public void deleteCopyOfVpc(long vpcCopyId, long originalVpcId) {
|
|
VpcVO copyOfvpc = _vpcDao.findById(vpcCopyId);
|
|
VpcVO originalVpc = _vpcDao.findById(originalVpcId);
|
|
|
|
//Be sure that when we delete the vpc, it has the uuid with what it was created.
|
|
swapUuids(copyOfvpc, originalVpc);
|
|
try {
|
|
if(!_vpcService.deleteVpc(vpcCopyId)) {
|
|
throw new CloudRuntimeException("Deletion of VPC failed. Clean up was not successful.");
|
|
}
|
|
} catch (ResourceUnavailableException e) {
|
|
throw new CloudRuntimeException(e.getMessage());
|
|
} finally {
|
|
swapUuids(originalVpc, copyOfvpc);
|
|
}
|
|
_resourceTagDao.removeByResourceIdAndKey(originalVpcId, ResourceTag.ResourceObjectType.Vpc, MIGRATION);
|
|
}
|
|
|
|
private Boolean migrateNicsInDB(NicVO originalNic, Network networkInNewPhysicalNet, DataCenter dc, ReservationContext context) {
|
|
s_logger.debug("migrating nics in database.");
|
|
UserVmVO vmVO = _vmDao.findById(originalNic.getInstanceId());
|
|
VirtualMachineProfile vmProfile = new VirtualMachineProfileImpl(vmVO, null, null, null, null);
|
|
NicProfile nicProfile = new NicProfile(originalNic, networkInNewPhysicalNet, null, null, null, _networkModel.isSecurityGroupSupportedInNetwork(networkInNewPhysicalNet), null);
|
|
try {
|
|
nicProfile = _networkMgr.allocateNic(nicProfile, networkInNewPhysicalNet, originalNic.isDefaultNic(), nicProfile.getDeviceId(), vmProfile).first();
|
|
} catch (InsufficientVirtualNetworkCapacityException | InsufficientAddressCapacityException e) {
|
|
throw new CloudRuntimeException("Allocation of new nicProfile failed during migration", e);
|
|
}
|
|
|
|
//Update vm_network_map table
|
|
if (vmProfile.getType() == VirtualMachine.Type.User) {
|
|
final VMNetworkMapVO vno = new VMNetworkMapVO(vmVO.getId(), networkInNewPhysicalNet.getId());
|
|
_vmNetworkMapDao.persist(vno);
|
|
}
|
|
|
|
NicVO newNic = _nicDao.findById(nicProfile.getId());
|
|
|
|
copyNicDetails(originalNic.getId(), newNic.getId());
|
|
//Update nic uuid here
|
|
moveServices(originalNic, newNic);
|
|
|
|
if (originalNic.getState() == Nic.State.Reserved) {
|
|
final VirtualMachine vm = vmProfile.getVirtualMachine();
|
|
final Host host = _hostDao.findById(vm.getHostId());
|
|
final DeployDestination dest = new DeployDestination(dc, null, null, host);
|
|
|
|
try {
|
|
nicProfile = _networkMgr.prepareNic(vmProfile, dest, context, nicProfile.getId(), networkInNewPhysicalNet);
|
|
_itMgr.replugNic(networkInNewPhysicalNet, _itMgr.toNicTO(nicProfile, host.getHypervisorType()), _itMgr.toVmTO(vmProfile), context, dest);
|
|
} catch (ResourceUnavailableException | InsufficientCapacityException e) {
|
|
throw new CloudRuntimeException("Migration of Nic failed", e);
|
|
}
|
|
}
|
|
|
|
//Mark the old nic as removed
|
|
markAsNonDefault(originalNic);
|
|
_networkMgr.removeNic(vmProfile, originalNic);
|
|
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Nic is migrated successfully for vm " + vmVO + " to " + networkInNewPhysicalNet);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public void assignNicsToNewPhysicalNetwork(Network srcNetwork, Network networkInNewPhysicalNet) {
|
|
List<NicVO> nics = _nicDao.listByNetworkId(srcNetwork.getId());
|
|
|
|
final CallContext cctx = CallContext.current();
|
|
final ReservationContext context = new ReservationContextImpl(null, null, cctx.getCallingUser(), cctx.getCallingAccount());
|
|
final DataCenter dc = _entityMgr.findById(DataCenter.class, networkInNewPhysicalNet.getDataCenterId());
|
|
|
|
//For each nic in the old network check if the nic belongs to a guest vm and migrate it to the new network.
|
|
for (NicVO originalNic : nics) {
|
|
if (originalNic.getVmType() != VirtualMachine.Type.User) {
|
|
continue;
|
|
}
|
|
|
|
Transaction.execute((TransactionCallback<Boolean>)
|
|
(status) -> migrateNicsInDB(originalNic, networkInNewPhysicalNet, dc, context));
|
|
}
|
|
|
|
//Now that nics are migrated we can migrate the static nats on those nics
|
|
reapplyPublicIps(srcNetwork, networkInNewPhysicalNet);
|
|
}
|
|
|
|
private void reapplyPublicIps(Network networkInOldPhysicalNetwork, Network networkInNewPhysicalNet) {
|
|
CallContext ctx = CallContext.current();
|
|
long callerUserId = ctx.getCallingUserId();
|
|
Account caller = ctx.getCallingAccount();
|
|
|
|
AccountVO networkAccount = _accountDao.findById(networkInNewPhysicalNet.getAccountId());
|
|
List<? extends IPAddressVO> staticNatIps = _ipAddressDao.listStaticNatPublicIps(networkInOldPhysicalNetwork.getId());
|
|
|
|
List<String> providers = _networkOfferingServiceDao.listProvidersForServiceForNetworkOffering(networkInNewPhysicalNet.getNetworkOfferingId(), Network.Service.SourceNat);
|
|
boolean isSrcNatIpNeeded = providers.stream().anyMatch(provider -> provider.contains(Network.Provider.VirtualRouter.getName()));
|
|
|
|
for (IPAddressVO ipAddress : staticNatIps) {
|
|
if (!ipAddress.isSourceNat() || isSrcNatIpNeeded) {
|
|
ipAddress.setAssociatedWithNetworkId(networkInNewPhysicalNet.getId());
|
|
_ipAddressDao.persist(ipAddress);
|
|
} else {
|
|
_ipAddressManager.disassociatePublicIpAddress(ipAddress.getId(), callerUserId, caller);
|
|
}
|
|
}
|
|
|
|
_rulesMgr.applyStaticNatsForNetwork(networkInNewPhysicalNet.getId(), false, networkAccount);
|
|
}
|
|
|
|
private void copyNicDetails(long originalNicId, long dstNicId) {
|
|
List<NicDetailVO> nicDetails = _nicDetailsDao.listDetails(originalNicId);
|
|
|
|
for (NicDetailVO nicDetail : nicDetails) {
|
|
_nicDetailsDao.persist(new NicDetailVO(dstNicId, nicDetail.getName(), nicDetail.getValue(), nicDetail.isDisplay()));
|
|
}
|
|
}
|
|
|
|
private void moveServices(NicVO originalNic, NicVO newNic) {
|
|
_nicIpAliasDao.moveIpAliases(originalNic.getId(), newNic.getId());
|
|
_nicSecondaryIpDao.moveSecondaryIps(originalNic.getId(), newNic.getId());
|
|
swapUuids(originalNic, newNic);
|
|
}
|
|
|
|
private void markAsNonDefault(NicVO nic) {
|
|
nic.setDefaultNic(false);
|
|
_nicDao.persist(nic);
|
|
}
|
|
|
|
/**
|
|
* Swaps the UUID's of the given nics's
|
|
* @param oldNic
|
|
* @param newNic
|
|
*/
|
|
private void swapUuids(NicVO oldNic, NicVO newNic) {
|
|
final String realUuid = oldNic.getUuid();
|
|
final String dummyUuid = newNic.getUuid();
|
|
|
|
oldNic.setUuid(dummyUuid.replace("-", "+"));
|
|
newNic.setUuid(realUuid);
|
|
_nicDao.persist(oldNic);
|
|
_nicDao.persist(newNic);
|
|
|
|
oldNic.setUuid(dummyUuid);
|
|
_nicDao.persist(oldNic);
|
|
}
|
|
|
|
/**
|
|
* Swaps the UUID's of the given networks
|
|
* @param oldNetwork
|
|
* @param newNetwork
|
|
*/
|
|
private void swapUuids(NetworkVO oldNetwork, NetworkVO newNetwork) {
|
|
String realUuid = oldNetwork.getUuid();
|
|
String dummyUuid = newNetwork.getUuid();
|
|
|
|
oldNetwork.setUuid(dummyUuid.replace("-","+"));
|
|
newNetwork.setUuid(realUuid);
|
|
_networksDao.update(oldNetwork.getId(), oldNetwork);
|
|
_networksDao.update(newNetwork.getId(), newNetwork);
|
|
|
|
oldNetwork.setUuid(dummyUuid);
|
|
_networksDao.update(oldNetwork.getId(), oldNetwork);
|
|
}
|
|
|
|
/**
|
|
* Swaps the UUID's of the given vpcs
|
|
* @param oldVpc
|
|
* @param newVpc
|
|
*/
|
|
private void swapUuids(VpcVO oldVpc, VpcVO newVpc) {
|
|
String realUuid = oldVpc.getUuid();
|
|
String dummyUuid = newVpc.getUuid();
|
|
|
|
oldVpc.setUuid(dummyUuid.replace("-","+"));
|
|
newVpc.setUuid(realUuid);
|
|
_vpcDao.update(oldVpc.getId(), oldVpc);
|
|
_vpcDao.update(newVpc.getId(), newVpc);
|
|
|
|
oldVpc.setUuid(dummyUuid);
|
|
_vpcDao.update(oldVpc.getId(), oldVpc);
|
|
}
|
|
|
|
}
|