mirror of https://github.com/apache/cloudstack.git
Merge pull request #866 from bvbharatk/CLOUDSTACK-8751
CLOUDSTACK-8751 minimise downtime of network when network update is in progress.more info in the bug link below. https://issues.apache.org/jira/browse/CLOUDSTACK-8751 * pr/866: Added license headders Added a test to test update router in sequence Do not update network if one of the router's state is unknown CLOUDSTACK-8751 Added tests CLOUDSTACK-8751 Signed-off-by: Rajani Karuturi <rajani.karuturi@accelerite.com>
This commit is contained in:
commit
2acb0b7608
|
|
@ -41,6 +41,8 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
|
|||
Shared, Isolated
|
||||
}
|
||||
|
||||
public String updatingInSequence ="updatingInSequence";
|
||||
|
||||
public static class Service {
|
||||
private static List<Service> supportedServices = new ArrayList<Service>();
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ public interface NetworkService {
|
|||
IpAddress getIp(long id);
|
||||
|
||||
Network updateGuestNetwork(long networkId, String name, String displayText, Account callerAccount, User callerUser, String domainSuffix, Long networkOfferingId,
|
||||
Boolean changeCidr, String guestVmCidr, Boolean displayNetwork, String newUUID);
|
||||
Boolean changeCidr, String guestVmCidr, Boolean displayNetwork, String newUUID, boolean updateInSequence, boolean forced);
|
||||
|
||||
PhysicalNetwork createPhysicalNetwork(Long zoneId, String vnetRange, String networkSpeed, List<String> isolationMethods, String broadcastDomainRange, Long domainId,
|
||||
List<String> tags, String name);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
// 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.element;
|
||||
|
||||
import com.cloud.network.Network;
|
||||
|
||||
/**
|
||||
* Created by bharat on 11/08/15.
|
||||
*/
|
||||
public interface RedundantResource {
|
||||
public void configureResource(Network network);
|
||||
public int getResourceCount(Network network);
|
||||
}
|
||||
|
|
@ -26,6 +26,10 @@ public interface VirtualRouter extends VirtualMachine {
|
|||
VIRTUAL_ROUTER, LB, INTERNAL_LB_VM
|
||||
}
|
||||
|
||||
public enum UpdateState {
|
||||
UPDATE_NEEDED, UPDATE_IN_PROGRESS, UPDATE_COMPLETE, UPDATE_FAILED
|
||||
}
|
||||
|
||||
Role getRole();
|
||||
|
||||
boolean getIsRedundantRouter();
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public interface RemoteAccessVpnService {
|
|||
|
||||
RemoteAccessVpn createRemoteAccessVpn(long vpnServerAddressId, String ipRange, boolean openFirewall, Boolean forDisplay) throws NetworkRuleConflictException;
|
||||
|
||||
boolean destroyRemoteAccessVpnForIp(long ipId, Account caller) throws ResourceUnavailableException;
|
||||
boolean destroyRemoteAccessVpnForIp(long ipId, Account caller, boolean forceCleanup) throws ResourceUnavailableException;
|
||||
|
||||
RemoteAccessVpn startRemoteAccessVpn(long vpnServerAddressId, boolean openFirewall) throws ResourceUnavailableException;
|
||||
|
||||
|
|
|
|||
|
|
@ -272,6 +272,7 @@ public class ApiConstants {
|
|||
public static final String USERNAME = "username";
|
||||
public static final String USER_SECURITY_GROUP_LIST = "usersecuritygrouplist";
|
||||
public static final String USE_VIRTUAL_NETWORK = "usevirtualnetwork";
|
||||
public static final String Update_IN_SEQUENCE ="updateinsequence";
|
||||
public static final String VALUE = "value";
|
||||
public static final String VIRTUAL_MACHINE_ID = "virtualmachineid";
|
||||
public static final String VIRTUAL_MACHINE_IDS = "virtualmachineids";
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ public class UpdateNetworkCmdByAdmin extends UpdateNetworkCmd {
|
|||
}
|
||||
|
||||
Network result = _networkService.updateGuestNetwork(getId(), getNetworkName(), getDisplayText(), callerAccount,
|
||||
callerUser, getNetworkDomain(), getNetworkOfferingId(), getChangeCidr(), getGuestVmCidr(), getDisplayNetwork(), getCustomId());
|
||||
callerUser, getNetworkDomain(), getNetworkOfferingId(), getChangeCidr(), getGuestVmCidr(), getDisplayNetwork(), getCustomId(), getUpdateInSequence(),getForced());
|
||||
|
||||
|
||||
if (result != null) {
|
||||
|
|
|
|||
|
|
@ -75,11 +75,17 @@ public class UpdateNetworkCmd extends BaseAsyncCustomIdCmd {
|
|||
@Parameter(name = ApiConstants.GUEST_VM_CIDR, type = CommandType.STRING, description = "CIDR for guest VMs, CloudStack allocates IPs to guest VMs only from this CIDR")
|
||||
private String guestVmCidr;
|
||||
|
||||
@Parameter(name =ApiConstants.Update_IN_SEQUENCE, type=CommandType.BOOLEAN, description = "if true, we will update the routers one after the other. applicable only for redundant router based networks using virtual router as provider")
|
||||
private Boolean updateInSequence;
|
||||
|
||||
@Parameter(name = ApiConstants.DISPLAY_NETWORK,
|
||||
type = CommandType.BOOLEAN,
|
||||
description = "an optional field, whether to the display the network to the end user or not.", authorized = {RoleType.Admin})
|
||||
private Boolean displayNetwork;
|
||||
|
||||
@Parameter(name= ApiConstants.FORCED, type = CommandType.BOOLEAN, description = "Setting this to true will cause a forced network update,", authorized = {RoleType.Admin})
|
||||
private Boolean forced;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -119,6 +125,19 @@ public class UpdateNetworkCmd extends BaseAsyncCustomIdCmd {
|
|||
return displayNetwork;
|
||||
}
|
||||
|
||||
public Boolean getUpdateInSequence(){
|
||||
if(updateInSequence ==null)
|
||||
return false;
|
||||
else
|
||||
return updateInSequence;
|
||||
}
|
||||
|
||||
public boolean getForced(){
|
||||
if(forced==null){
|
||||
return false;
|
||||
}
|
||||
return forced;
|
||||
}
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -149,7 +168,7 @@ public class UpdateNetworkCmd extends BaseAsyncCustomIdCmd {
|
|||
|
||||
Network result =
|
||||
_networkService.updateGuestNetwork(getId(), getNetworkName(), getDisplayText(), callerAccount, callerUser, getNetworkDomain(), getNetworkOfferingId(),
|
||||
getChangeCidr(), getGuestVmCidr(), getDisplayNetwork(), getCustomId());
|
||||
getChangeCidr(), getGuestVmCidr(), getDisplayNetwork(), getCustomId(), getUpdateInSequence(), getForced());
|
||||
|
||||
if (result != null) {
|
||||
NetworkResponse response = _responseGenerator.createNetworkResponse(ResponseView.Restricted, result);
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ public class DeleteRemoteAccessVpnCmd extends BaseAsyncCmd {
|
|||
|
||||
@Override
|
||||
public void execute() throws ResourceUnavailableException {
|
||||
if (! _ravService.destroyRemoteAccessVpnForIp(publicIpId, CallContext.current().getCallingAccount())) {
|
||||
if (! _ravService.destroyRemoteAccessVpnForIp(publicIpId, CallContext.current().getCallingAccount(), false)) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete remote access vpn");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -224,4 +224,14 @@ public interface NetworkOrchestrationService {
|
|||
boolean resourceCountNeedsUpdate(NetworkOffering ntwkOff, ACLType aclType);
|
||||
|
||||
void prepareAllNicsForMigration(VirtualMachineProfile vm, DeployDestination dest);
|
||||
|
||||
boolean canUpdateInSequence(Network network);
|
||||
|
||||
List<String> getServicesNotSupportedInNewOffering(Network network, long newNetworkOfferingId);
|
||||
|
||||
void cleanupConfigForServicesInNetwork(List<String> services, Network network);
|
||||
|
||||
void configureUpdateInSequence(Network network);
|
||||
|
||||
int getResourceCount(Network network);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,15 @@ import java.util.concurrent.TimeUnit;
|
|||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.network.Networks;
|
||||
|
||||
import com.cloud.network.dao.NetworkDetailsDao;
|
||||
import com.cloud.network.dao.RemoteAccessVpnDao;
|
||||
import com.cloud.network.dao.RemoteAccessVpnVO;
|
||||
import com.cloud.network.dao.VpnUserDao;
|
||||
import com.cloud.network.element.RedundantResource;
|
||||
import com.cloud.vm.dao.DomainRouterDao;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.engine.cloud.entity.api.db.VMNetworkMapVO;
|
||||
|
|
@ -50,7 +59,6 @@ import org.apache.cloudstack.framework.messagebus.MessageBus;
|
|||
import org.apache.cloudstack.framework.messagebus.PublishScope;
|
||||
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
|
||||
import org.apache.cloudstack.region.PortableIpDao;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.AgentManager;
|
||||
import com.cloud.agent.Listener;
|
||||
|
|
@ -107,7 +115,6 @@ import com.cloud.network.NetworkMigrationResponder;
|
|||
import com.cloud.network.NetworkModel;
|
||||
import com.cloud.network.NetworkProfile;
|
||||
import com.cloud.network.NetworkStateListener;
|
||||
import com.cloud.network.Networks;
|
||||
import com.cloud.network.Networks.BroadcastDomainType;
|
||||
import com.cloud.network.Networks.TrafficType;
|
||||
import com.cloud.network.PhysicalNetwork;
|
||||
|
|
@ -265,9 +272,16 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
MessageBus _messageBus;
|
||||
@Inject
|
||||
VMNetworkMapDao _vmNetworkMapDao;
|
||||
@Inject
|
||||
DomainRouterDao _rotuerDao;
|
||||
@Inject
|
||||
RemoteAccessVpnDao _remoteAccessVpnDao;
|
||||
@Inject
|
||||
VpnUserDao _vpnUserDao;
|
||||
|
||||
List<NetworkGuru> networkGurus;
|
||||
|
||||
|
||||
public List<NetworkGuru> getNetworkGurus() {
|
||||
return networkGurus;
|
||||
}
|
||||
|
|
@ -350,6 +364,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
PortableIpDao _portableIpDao;
|
||||
@Inject
|
||||
ConfigDepot _configDepot;
|
||||
@Inject
|
||||
NetworkDetailsDao _networkDetailsDao;
|
||||
|
||||
protected StateMachine2<Network.State, Network.Event, Network> _stateMachine;
|
||||
ScheduledExecutorService _executor;
|
||||
|
|
@ -1271,6 +1287,152 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUpdateInSequence(Network network){
|
||||
List<Provider> providers = getNetworkProviders(network.getId());
|
||||
|
||||
//check if the there are no service provider other than virtualrouter.
|
||||
for(Provider provider :providers){
|
||||
if(provider!=Provider.VirtualRouter)
|
||||
throw new UnsupportedOperationException("Cannot update the network resources in sequence when providers other than virtualrouter are used");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getServicesNotSupportedInNewOffering(Network network,long newNetworkOfferingId){
|
||||
NetworkOffering offering =_networkOfferingDao.findById(newNetworkOfferingId);
|
||||
List<String> services=_ntwkOfferingSrvcDao.listServicesForNetworkOffering(offering.getId());
|
||||
List<NetworkServiceMapVO> serviceMap= _ntwkSrvcDao.getServicesInNetwork(network.getId());
|
||||
List<String> servicesNotInNewOffering=new ArrayList<>();
|
||||
for(NetworkServiceMapVO serviceVO :serviceMap){
|
||||
boolean inlist=false;
|
||||
for(String service: services){
|
||||
if(serviceVO.getService().equalsIgnoreCase(service)){
|
||||
inlist=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!inlist){
|
||||
//ignore Gateway service as this has no effect on the
|
||||
//behaviour of network.
|
||||
if(!serviceVO.getService().equalsIgnoreCase(Service.Gateway.getName()))
|
||||
servicesNotInNewOffering.add(serviceVO.getService());
|
||||
}
|
||||
}
|
||||
return servicesNotInNewOffering;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanupConfigForServicesInNetwork(List<String> services, final Network network){
|
||||
long networkId=network.getId();
|
||||
Account caller=_accountDao.findById(Account.ACCOUNT_ID_SYSTEM);
|
||||
long userId=User.UID_SYSTEM;
|
||||
//remove all PF/Static Nat rules for the network
|
||||
s_logger.info("Services:"+services+" are no longer supported in network:"+network.getUuid()+
|
||||
" after applying new network offering:"+network.getNetworkOfferingId()+" removing the related configuration");
|
||||
if(services.contains(Service.StaticNat.getName())|| services.contains(Service.PortForwarding.getName())) {
|
||||
try {
|
||||
if (_rulesMgr.revokeAllPFStaticNatRulesForNetwork(networkId, userId, caller)) {
|
||||
s_logger.debug("Successfully cleaned up portForwarding/staticNat rules for network id=" + networkId);
|
||||
} else {
|
||||
s_logger.warn("Failed to release portForwarding/StaticNat rules as a part of network id=" + networkId + " cleanup");
|
||||
}
|
||||
if(services.contains(Service.StaticNat.getName())){
|
||||
//removing static nat configured on ips.
|
||||
//optimizing the db operations using transaction.
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
List<IPAddressVO> ips = _ipAddressDao.listStaticNatPublicIps(network.getId());
|
||||
for (IPAddressVO ip : ips) {
|
||||
ip.setOneToOneNat(false);
|
||||
ip.setAssociatedWithVmId(null);
|
||||
ip.setVmIp(null);
|
||||
_ipAddressDao.update(ip.getId(),ip);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (ResourceUnavailableException ex) {
|
||||
s_logger.warn("Failed to release portForwarding/StaticNat rules as a part of network id=" + networkId + " cleanup due to resourceUnavailable ", ex);
|
||||
}
|
||||
}
|
||||
if(services.contains(Service.SourceNat.getName())){
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
List<IPAddressVO> ips = _ipAddressDao.listByAssociatedNetwork(network.getId(),true);
|
||||
//removing static nat configured on ips.
|
||||
for (IPAddressVO ip : ips) {
|
||||
ip.setSourceNat(false);
|
||||
_ipAddressDao.update(ip.getId(),ip);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if(services.contains(Service.Lb.getName())){
|
||||
//remove all LB rules for the network
|
||||
if (_lbMgr.removeAllLoadBalanacersForNetwork(networkId, caller, userId)) {
|
||||
s_logger.debug("Successfully cleaned up load balancing rules for network id=" + networkId);
|
||||
} else {
|
||||
s_logger.warn("Failed to cleanup LB rules as a part of network id=" + networkId + " cleanup");
|
||||
}
|
||||
}
|
||||
|
||||
if(services.contains(Service.Firewall.getName())){
|
||||
//revoke all firewall rules for the network
|
||||
try {
|
||||
if (_firewallMgr.revokeAllFirewallRulesForNetwork(networkId, userId, caller)) {
|
||||
s_logger.debug("Successfully cleaned up firewallRules rules for network id=" + networkId);
|
||||
} else {
|
||||
s_logger.warn("Failed to cleanup Firewall rules as a part of network id=" + networkId + " cleanup");
|
||||
}
|
||||
} catch (ResourceUnavailableException ex) {
|
||||
s_logger.warn("Failed to cleanup Firewall rules as a part of network id=" + networkId + " cleanup due to resourceUnavailable ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
//do not remove vpn service for vpc networks.
|
||||
if(services.contains(Service.Vpn.getName()) && network.getVpcId()==null){
|
||||
RemoteAccessVpnVO vpn = _remoteAccessVpnDao.findByAccountAndNetwork(network.getAccountId(),networkId);
|
||||
try {
|
||||
_vpnMgr.destroyRemoteAccessVpnForIp(vpn.getServerAddressId(), caller, true);
|
||||
} catch (ResourceUnavailableException ex) {
|
||||
s_logger.warn("Failed to cleanup remote access vpn resources of network:"+network.getUuid() + " due to Exception: ", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureUpdateInSequence(Network network) {
|
||||
List<Provider> providers = getNetworkProviders(network.getId());
|
||||
for (NetworkElement element : networkElements) {
|
||||
if (providers.contains(element.getProvider())) {
|
||||
if (element instanceof RedundantResource) {
|
||||
((RedundantResource) element).configureResource(network);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getResourceCount(Network network){
|
||||
List<Provider> providers = getNetworkProviders(network.getId());
|
||||
int resourceCount=0;
|
||||
for (NetworkElement element : networkElements) {
|
||||
if (providers.contains(element.getProvider())) {
|
||||
//currently only one element implements the redundant resource interface
|
||||
if (element instanceof RedundantResource) {
|
||||
resourceCount= ((RedundantResource) element).getResourceCount(network);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return resourceCount;
|
||||
}
|
||||
|
||||
|
||||
@DB
|
||||
protected void updateNic(final NicVO nic, final long networkId, final int count) {
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
|
|
|
|||
|
|
@ -69,6 +69,11 @@ public class DomainRouterVO extends VMInstanceVO implements VirtualRouter {
|
|||
@Column(name = "vpc_id")
|
||||
private Long vpcId;
|
||||
|
||||
|
||||
@Column(name= "update_state")
|
||||
@Enumerated(EnumType.STRING)
|
||||
private UpdateState updateState;
|
||||
|
||||
public DomainRouterVO(final long id, final long serviceOfferingId, final long elementId, final String name, final long templateId, final HypervisorType hypervisorType, final long guestOSId, final long domainId,
|
||||
final long accountId, final long userId, final boolean isRedundantRouter, final RedundantState redundantState, final boolean haEnabled, final boolean stopPending,
|
||||
final Long vpcId) {
|
||||
|
|
@ -193,4 +198,13 @@ public class DomainRouterVO extends VMInstanceVO implements VirtualRouter {
|
|||
return vpcId;
|
||||
}
|
||||
|
||||
public UpdateState getUpdateState() {
|
||||
return updateState;
|
||||
}
|
||||
|
||||
public void setUpdateState(UpdateState updateState) {
|
||||
this.updateState = updateState;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -562,7 +562,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
|||
// the code would be triggered
|
||||
s_logger.debug("Cleaning up remote access vpns as a part of public IP id=" + ipId + " release...");
|
||||
try {
|
||||
_vpnMgr.destroyRemoteAccessVpnForIp(ipId, caller);
|
||||
_vpnMgr.destroyRemoteAccessVpnForIp(ipId, caller,false);
|
||||
} catch (ResourceUnavailableException e) {
|
||||
s_logger.warn("Unable to destroy remote access vpn for ip id=" + ipId + " as a part of ip release", e);
|
||||
success = false;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import java.util.UUID;
|
|||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.network.router.VirtualRouter;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
|
|
@ -108,6 +109,8 @@ import com.cloud.network.dao.IPAddressDao;
|
|||
import com.cloud.network.dao.IPAddressVO;
|
||||
import com.cloud.network.dao.LoadBalancerVMMapDao;
|
||||
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.NetworkServiceMapDao;
|
||||
|
|
@ -178,6 +181,7 @@ import com.cloud.utils.db.TransactionStatus;
|
|||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.exception.ExceptionUtil;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
import com.cloud.vm.DomainRouterVO;
|
||||
import com.cloud.vm.Nic;
|
||||
import com.cloud.vm.NicSecondaryIp;
|
||||
import com.cloud.vm.NicVO;
|
||||
|
|
@ -187,6 +191,7 @@ import com.cloud.vm.SecondaryStorageVmVO;
|
|||
import com.cloud.vm.UserVmVO;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.dao.DomainRouterDao;
|
||||
import com.cloud.vm.dao.NicDao;
|
||||
import com.cloud.vm.dao.NicSecondaryIpDao;
|
||||
import com.cloud.vm.dao.NicSecondaryIpVO;
|
||||
|
|
@ -324,6 +329,12 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
|
|||
@Inject
|
||||
MessageBus _messageBus;
|
||||
|
||||
@Inject
|
||||
DomainRouterDao _routerDao;
|
||||
|
||||
@Inject
|
||||
NetworkDetailsDao _networkDetailsDao;
|
||||
|
||||
int _cidrLimit;
|
||||
boolean _allowSubdomainNetworkAccess;
|
||||
|
||||
|
|
@ -1992,8 +2003,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
|
|||
@DB
|
||||
@ActionEvent(eventType = EventTypes.EVENT_NETWORK_UPDATE, eventDescription = "updating network", async = true)
|
||||
public Network updateGuestNetwork(final long networkId, String name, String displayText, Account callerAccount, User callerUser, String domainSuffix,
|
||||
final Long networkOfferingId, Boolean changeCidr, String guestVmCidr, Boolean displayNetwork, String customId) {
|
||||
|
||||
final Long networkOfferingId, Boolean changeCidr, String guestVmCidr, Boolean displayNetwork, String customId, boolean updateInSequence, boolean forced) {
|
||||
boolean restartNetwork = false;
|
||||
|
||||
// verify input parameters
|
||||
|
|
@ -2239,130 +2249,178 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
|
|||
ReservationContext context = new ReservationContextImpl(null, null, callerUser, callerAccount);
|
||||
// 1) Shutdown all the elements and cleanup all the rules. Don't allow to shutdown network in intermediate
|
||||
// states - Shutdown and Implementing
|
||||
boolean validStateToShutdown = (network.getState() == Network.State.Implemented || network.getState() == Network.State.Setup || network.getState() == Network.State.Allocated);
|
||||
if (restartNetwork) {
|
||||
if (validStateToShutdown) {
|
||||
if (!changeCidr) {
|
||||
s_logger.debug("Shutting down elements and resources for network id=" + networkId + " as a part of network update");
|
||||
int resourceCount=1;
|
||||
if(updateInSequence && restartNetwork && _networkOfferingDao.findById(network.getNetworkOfferingId()).getRedundantRouter()
|
||||
&& (networkOfferingId==null || _networkOfferingDao.findById(networkOfferingId).getRedundantRouter()) && network.getVpcId()==null) {
|
||||
_networkMgr.canUpdateInSequence(network);
|
||||
NetworkDetailVO networkDetail =new NetworkDetailVO(network.getId(),Network.updatingInSequence,"true",true);
|
||||
_networkDetailsDao.persist(networkDetail);
|
||||
_networkMgr.configureUpdateInSequence(network);
|
||||
resourceCount=_networkMgr.getResourceCount(network);
|
||||
//check if routers are in correct state before proceeding with the update
|
||||
List<DomainRouterVO> routers=_routerDao.listByNetworkAndRole(networkId, VirtualRouter.Role.VIRTUAL_ROUTER);
|
||||
for(DomainRouterVO router :routers){
|
||||
if(router.getRedundantState()== VirtualRouter.RedundantState.UNKNOWN){
|
||||
if(!forced){
|
||||
throw new CloudRuntimeException("Domain router: "+router.getInstanceName()+" is in unknown state, Cannot update network. set parameter forced to true for forcing an update");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
List<String > servicesNotInNewOffering = null;
|
||||
if(networkOfferingId != null)
|
||||
servicesNotInNewOffering = _networkMgr.getServicesNotSupportedInNewOffering(network,networkOfferingId);
|
||||
if(!forced && servicesNotInNewOffering != null && !servicesNotInNewOffering.isEmpty()){
|
||||
NetworkOfferingVO newOffering = _networkOfferingDao.findById(networkOfferingId);
|
||||
throw new CloudRuntimeException("The new offering:"+newOffering.getUniqueName()
|
||||
+" will remove the following services "+servicesNotInNewOffering +"along with all the related configuration currently in use. will not proceed with the network update." +
|
||||
"set forced parameter to true for forcing an update.");
|
||||
}
|
||||
try{
|
||||
if(servicesNotInNewOffering!=null && !servicesNotInNewOffering.isEmpty()){
|
||||
_networkMgr.cleanupConfigForServicesInNetwork(servicesNotInNewOffering,network);
|
||||
}
|
||||
}catch (Throwable e){
|
||||
s_logger.debug("failed to cleanup config related to unused services error:"+e.getMessage());
|
||||
}
|
||||
|
||||
if (!_networkMgr.shutdownNetworkElementsAndResources(context, true, network)) {
|
||||
s_logger.warn("Failed to shutdown the network elements and resources as a part of network restart: " + network);
|
||||
CloudRuntimeException ex = new CloudRuntimeException("Failed to shutdown the network elements and resources as a part of update to network of specified id");
|
||||
boolean validStateToShutdown = (network.getState() == Network.State.Implemented || network.getState() == Network.State.Setup || network.getState() == Network.State.Allocated);
|
||||
try {
|
||||
|
||||
do {
|
||||
if (restartNetwork) {
|
||||
if (validStateToShutdown) {
|
||||
if (!changeCidr) {
|
||||
s_logger.debug("Shutting down elements and resources for network id=" + networkId + " as a part of network update");
|
||||
|
||||
if (!_networkMgr.shutdownNetworkElementsAndResources(context, true, network)) {
|
||||
s_logger.warn("Failed to shutdown the network elements and resources as a part of network restart: " + network);
|
||||
CloudRuntimeException ex = new CloudRuntimeException("Failed to shutdown the network elements and resources as a part of update to network of specified id");
|
||||
ex.addProxyObject(network.getUuid(), "networkId");
|
||||
throw ex;
|
||||
}
|
||||
} else {
|
||||
// We need to shutdown the network, since we want to re-implement the network.
|
||||
s_logger.debug("Shutting down network id=" + networkId + " as a part of network update");
|
||||
|
||||
//check if network has reservation
|
||||
if (NetUtils.isNetworkAWithinNetworkB(network.getCidr(), network.getNetworkCidr())) {
|
||||
s_logger.warn("Existing IP reservation will become ineffective for the network with id = " + networkId
|
||||
+ " You need to reapply reservation after network reimplementation.");
|
||||
//set cidr to the newtork cidr
|
||||
network.setCidr(network.getNetworkCidr());
|
||||
//set networkCidr to null to bring network back to no IP reservation state
|
||||
network.setNetworkCidr(null);
|
||||
}
|
||||
|
||||
if (!_networkMgr.shutdownNetwork(network.getId(), context, true)) {
|
||||
s_logger.warn("Failed to shutdown the network as a part of update to network with specified id");
|
||||
CloudRuntimeException ex = new CloudRuntimeException("Failed to shutdown the network as a part of update of specified network id");
|
||||
ex.addProxyObject(network.getUuid(), "networkId");
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CloudRuntimeException ex = new CloudRuntimeException(
|
||||
"Failed to shutdown the network elements and resources as a part of update to network with specified id; network is in wrong state: " + network.getState());
|
||||
ex.addProxyObject(network.getUuid(), "networkId");
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
// 2) Only after all the elements and rules are shutdown properly, update the network VO
|
||||
// get updated network
|
||||
Network.State networkState = _networksDao.findById(networkId).getState();
|
||||
boolean validStateToImplement = (networkState == Network.State.Implemented || networkState == Network.State.Setup || networkState == Network.State.Allocated);
|
||||
if (restartNetwork && !validStateToImplement) {
|
||||
CloudRuntimeException ex = new CloudRuntimeException(
|
||||
"Failed to implement the network elements and resources as a part of update to network with specified id; network is in wrong state: " + networkState);
|
||||
ex.addProxyObject(network.getUuid(), "networkId");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if (networkOfferingId != null) {
|
||||
if (networkOfferingChanged) {
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
network.setNetworkOfferingId(networkOfferingId);
|
||||
_networksDao.update(networkId, network, newSvcProviders);
|
||||
// get all nics using this network
|
||||
// log remove usage events for old offering
|
||||
// log assign usage events for new offering
|
||||
List<NicVO> nics = _nicDao.listByNetworkId(networkId);
|
||||
for (NicVO nic : nics) {
|
||||
long vmId = nic.getInstanceId();
|
||||
VMInstanceVO vm = _vmDao.findById(vmId);
|
||||
if (vm == null) {
|
||||
s_logger.error("Vm for nic " + nic.getId() + " not found with Vm Id:" + vmId);
|
||||
continue;
|
||||
}
|
||||
long isDefault = (nic.isDefaultNic()) ? 1 : 0;
|
||||
String nicIdString = Long.toString(nic.getId());
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), nicIdString,
|
||||
oldNetworkOfferingId, null, isDefault, VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplay());
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), nicIdString,
|
||||
networkOfferingId, null, isDefault, VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplay());
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
network.setNetworkOfferingId(networkOfferingId);
|
||||
_networksDao.update(networkId, network,
|
||||
_networkMgr.finalizeServicesAndProvidersForNetwork(_entityMgr.findById(NetworkOffering.class, networkOfferingId), network.getPhysicalNetworkId()));
|
||||
}
|
||||
} else {
|
||||
// We need to shutdown the network, since we want to re-implement the network.
|
||||
s_logger.debug("Shutting down network id=" + networkId + " as a part of network update");
|
||||
_networksDao.update(networkId, network);
|
||||
}
|
||||
|
||||
//check if network has reservation
|
||||
if (NetUtils.isNetworkAWithinNetworkB(network.getCidr(), network.getNetworkCidr())) {
|
||||
s_logger.warn("Existing IP reservation will become ineffective for the network with id = " + networkId
|
||||
+ " You need to reapply reservation after network reimplementation.");
|
||||
//set cidr to the newtork cidr
|
||||
network.setCidr(network.getNetworkCidr());
|
||||
//set networkCidr to null to bring network back to no IP reservation state
|
||||
network.setNetworkCidr(null);
|
||||
}
|
||||
|
||||
if (!_networkMgr.shutdownNetwork(network.getId(), context, true)) {
|
||||
s_logger.warn("Failed to shutdown the network as a part of update to network with specified id");
|
||||
CloudRuntimeException ex = new CloudRuntimeException("Failed to shutdown the network as a part of update of specified network id");
|
||||
ex.addProxyObject(network.getUuid(), "networkId");
|
||||
throw ex;
|
||||
// 3) Implement the elements and rules again
|
||||
if (restartNetwork) {
|
||||
if (network.getState() != Network.State.Allocated) {
|
||||
DeployDestination dest = new DeployDestination(_dcDao.findById(network.getDataCenterId()), null, null, null);
|
||||
s_logger.debug("Implementing the network " + network + " elements and resources as a part of network update");
|
||||
try {
|
||||
if (!changeCidr) {
|
||||
_networkMgr.implementNetworkElementsAndResources(dest, context, network, _networkOfferingDao.findById(network.getNetworkOfferingId()));
|
||||
} else {
|
||||
_networkMgr.implementNetwork(network.getId(), dest, context);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
s_logger.warn("Failed to implement network " + network + " elements and resources as a part of network update due to ", ex);
|
||||
CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified id) elements and resources as a part of network update");
|
||||
e.addProxyObject(network.getUuid(), "networkId");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CloudRuntimeException ex = new CloudRuntimeException(
|
||||
"Failed to shutdown the network elements and resources as a part of update to network with specified id; network is in wrong state: " + network.getState());
|
||||
ex.addProxyObject(network.getUuid(), "networkId");
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
// 2) Only after all the elements and rules are shutdown properly, update the network VO
|
||||
// get updated network
|
||||
Network.State networkState = _networksDao.findById(networkId).getState();
|
||||
boolean validStateToImplement = (networkState == Network.State.Implemented || networkState == Network.State.Setup || networkState == Network.State.Allocated);
|
||||
if (restartNetwork && !validStateToImplement) {
|
||||
CloudRuntimeException ex = new CloudRuntimeException(
|
||||
"Failed to implement the network elements and resources as a part of update to network with specified id; network is in wrong state: " + networkState);
|
||||
ex.addProxyObject(network.getUuid(), "networkId");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if (networkOfferingId != null) {
|
||||
if (networkOfferingChanged) {
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
network.setNetworkOfferingId(networkOfferingId);
|
||||
_networksDao.update(networkId, network, newSvcProviders);
|
||||
// get all nics using this network
|
||||
// log remove usage events for old offering
|
||||
// log assign usage events for new offering
|
||||
List<NicVO> nics = _nicDao.listByNetworkId(networkId);
|
||||
for (NicVO nic : nics) {
|
||||
long vmId = nic.getInstanceId();
|
||||
VMInstanceVO vm = _vmDao.findById(vmId);
|
||||
if (vm == null) {
|
||||
s_logger.error("Vm for nic " + nic.getId() + " not found with Vm Id:" + vmId);
|
||||
continue;
|
||||
// 4) if network has been upgraded from a non persistent ntwk offering to a persistent ntwk offering,
|
||||
// implement the network if its not already
|
||||
if (networkOfferingChanged && !oldNtwkOff.getIsPersistent() && networkOffering.getIsPersistent()) {
|
||||
if (network.getState() == Network.State.Allocated) {
|
||||
try {
|
||||
DeployDestination dest = new DeployDestination(_dcDao.findById(network.getDataCenterId()), null, null, null);
|
||||
_networkMgr.implementNetwork(network.getId(), dest, context);
|
||||
} catch (Exception ex) {
|
||||
s_logger.warn("Failed to implement network " + network + " elements and resources as a part o" + "f network update due to ", ex);
|
||||
CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified" + " id) elements and resources as a part of network update");
|
||||
e.addProxyObject(network.getUuid(), "networkId");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
long isDefault = (nic.isDefaultNic()) ? 1 : 0;
|
||||
String nicIdString = Long.toString(nic.getId());
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), nicIdString,
|
||||
oldNetworkOfferingId, null, isDefault, VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplay());
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), nicIdString,
|
||||
networkOfferingId, null, isDefault, VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplay());
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
network.setNetworkOfferingId(networkOfferingId);
|
||||
_networksDao.update(networkId, network,
|
||||
_networkMgr.finalizeServicesAndProvidersForNetwork(_entityMgr.findById(NetworkOffering.class, networkOfferingId), network.getPhysicalNetworkId()));
|
||||
}
|
||||
} else {
|
||||
_networksDao.update(networkId, network);
|
||||
}
|
||||
|
||||
// 3) Implement the elements and rules again
|
||||
if (restartNetwork) {
|
||||
if (network.getState() != Network.State.Allocated) {
|
||||
DeployDestination dest = new DeployDestination(_dcDao.findById(network.getDataCenterId()), null, null, null);
|
||||
s_logger.debug("Implementing the network " + network + " elements and resources as a part of network update");
|
||||
try {
|
||||
if (!changeCidr) {
|
||||
_networkMgr.implementNetworkElementsAndResources(dest, context, network, _networkOfferingDao.findById(network.getNetworkOfferingId()));
|
||||
} else {
|
||||
_networkMgr.implementNetwork(network.getId(), dest, context);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
s_logger.warn("Failed to implement network " + network + " elements and resources as a part of network update due to ", ex);
|
||||
CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified id) elements and resources as a part of network update");
|
||||
e.addProxyObject(network.getUuid(), "networkId");
|
||||
throw e;
|
||||
resourceCount--;
|
||||
} while(updateInSequence && resourceCount>0);
|
||||
}catch (Exception exception){
|
||||
throw new CloudRuntimeException("failed to update network "+network.getUuid()+"due to "+exception.getMessage());
|
||||
}finally {
|
||||
if(updateInSequence){
|
||||
if( _networkDetailsDao.findDetail(networkId,Network.updatingInSequence)!=null){
|
||||
_networkDetailsDao.removeDetail(networkId,Network.updatingInSequence);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4) if network has been upgraded from a non persistent ntwk offering to a persistent ntwk offering,
|
||||
// implement the network if its not already
|
||||
if (networkOfferingChanged && !oldNtwkOff.getIsPersistent() && networkOffering.getIsPersistent()) {
|
||||
if (network.getState() == Network.State.Allocated) {
|
||||
try {
|
||||
DeployDestination dest = new DeployDestination(_dcDao.findById(network.getDataCenterId()), null, null, null);
|
||||
_networkMgr.implementNetwork(network.getId(), dest, context);
|
||||
} catch (Exception ex) {
|
||||
s_logger.warn("Failed to implement network " + network + " elements and resources as a part o" + "f network update due to ", ex);
|
||||
CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified" + " id) elements and resources as a part of network update");
|
||||
e.addProxyObject(network.getUuid(), "networkId");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return getNetwork(network.getId());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ import java.util.Set;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.network.dao.NetworkDetailVO;
|
||||
import com.cloud.network.dao.NetworkDetailsDao;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.agent.api.to.LoadBalancerTO;
|
||||
import com.cloud.configuration.ConfigurationManager;
|
||||
import com.cloud.dc.DataCenter;
|
||||
|
|
@ -109,7 +112,7 @@ import org.cloud.network.router.deployment.RouterDeploymentDefinitionBuilder;
|
|||
|
||||
public class VirtualRouterElement extends AdapterBase implements VirtualRouterElementService, DhcpServiceProvider, UserDataServiceProvider, SourceNatServiceProvider,
|
||||
StaticNatServiceProvider, FirewallServiceProvider, LoadBalancingServiceProvider, PortForwardingServiceProvider, RemoteAccessVPNServiceProvider, IpDeployer,
|
||||
NetworkMigrationResponder, AggregatedCommandExecutor {
|
||||
NetworkMigrationResponder, AggregatedCommandExecutor, RedundantResource {
|
||||
private static final Logger s_logger = Logger.getLogger(VirtualRouterElement.class);
|
||||
public static final AutoScaleCounterType AutoScaleCounterCpu = new AutoScaleCounterType("cpu");
|
||||
public static final AutoScaleCounterType AutoScaleCounterMemory = new AutoScaleCounterType("memory");
|
||||
|
|
@ -159,6 +162,9 @@ NetworkMigrationResponder, AggregatedCommandExecutor {
|
|||
@Inject
|
||||
NetworkTopologyContext networkTopologyContext;
|
||||
|
||||
@Inject
|
||||
NetworkDetailsDao _networkDetailsDao;
|
||||
|
||||
@Inject
|
||||
protected RouterDeploymentDefinitionBuilder routerDeploymentDefinitionBuilder;
|
||||
|
||||
|
|
@ -262,7 +268,7 @@ NetworkMigrationResponder, AggregatedCommandExecutor {
|
|||
public boolean applyFWRules(final Network network, final List<? extends FirewallRule> rules) throws ResourceUnavailableException {
|
||||
boolean result = true;
|
||||
if (canHandle(network, Service.Firewall)) {
|
||||
final List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER);
|
||||
final List<DomainRouterVO> routers = getRouters(network);
|
||||
if (routers == null || routers.isEmpty()) {
|
||||
s_logger.debug("Virtual router elemnt doesn't need to apply firewall rules on the backend; virtual " + "router doesn't exist in the network " + network.getId());
|
||||
return true;
|
||||
|
|
@ -407,7 +413,7 @@ NetworkMigrationResponder, AggregatedCommandExecutor {
|
|||
return false;
|
||||
}
|
||||
|
||||
final List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER);
|
||||
final List<DomainRouterVO> routers = getRouters(network);
|
||||
if (routers == null || routers.isEmpty()) {
|
||||
s_logger.debug("Virtual router elemnt doesn't need to apply lb rules on the backend; virtual " + "router doesn't exist in the network " + network.getId());
|
||||
return true;
|
||||
|
|
@ -498,7 +504,7 @@ NetworkMigrationResponder, AggregatedCommandExecutor {
|
|||
}
|
||||
boolean result = true;
|
||||
if (canHandle) {
|
||||
final List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER);
|
||||
final List<DomainRouterVO> routers = getRouters(network);
|
||||
if (routers == null || routers.isEmpty()) {
|
||||
s_logger.debug("Virtual router elemnt doesn't need to associate ip addresses on the backend; virtual " + "router doesn't exist in the network " + network.getId());
|
||||
return true;
|
||||
|
|
@ -657,7 +663,7 @@ NetworkMigrationResponder, AggregatedCommandExecutor {
|
|||
public boolean applyStaticNats(final Network network, final List<? extends StaticNat> rules) throws ResourceUnavailableException {
|
||||
boolean result = true;
|
||||
if (canHandle(network, Service.StaticNat)) {
|
||||
final List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER);
|
||||
final List<DomainRouterVO> routers = getRouters(network);
|
||||
if (routers == null || routers.isEmpty()) {
|
||||
s_logger.debug("Virtual router elemnt doesn't need to apply static nat on the backend; virtual " + "router doesn't exist in the network " + network.getId());
|
||||
return true;
|
||||
|
|
@ -673,6 +679,46 @@ NetworkMigrationResponder, AggregatedCommandExecutor {
|
|||
return result;
|
||||
}
|
||||
|
||||
public List<DomainRouterVO> getRouters(Network network){
|
||||
List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER);
|
||||
if (routers !=null && routers.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
NetworkDetailVO updateInSequence=_networkDetailsDao.findDetail(network.getId(), Network.updatingInSequence);
|
||||
if(network.isRedundant() && updateInSequence!=null && "true".equalsIgnoreCase(updateInSequence.getValue())){
|
||||
List<DomainRouterVO> masterRouters=new ArrayList<DomainRouterVO>();
|
||||
int noOfrouters=routers.size();
|
||||
while (noOfrouters>0){
|
||||
DomainRouterVO router = routers.get(0);
|
||||
if(router.getUpdateState()== VirtualRouter.UpdateState.UPDATE_IN_PROGRESS){
|
||||
ArrayList<DomainRouterVO> routerList = new ArrayList<DomainRouterVO>();
|
||||
routerList.add(router);
|
||||
return routerList;
|
||||
}
|
||||
if(router.getUpdateState()== VirtualRouter.UpdateState.UPDATE_COMPLETE) {
|
||||
routers.remove(router);
|
||||
noOfrouters--;
|
||||
continue;
|
||||
}
|
||||
if(router.getRedundantState()!=VirtualRouter.RedundantState.BACKUP) {
|
||||
masterRouters.add(router);
|
||||
routers.remove(router);
|
||||
}
|
||||
noOfrouters--;
|
||||
}
|
||||
if(routers.size()==0 && masterRouters.size()==0){
|
||||
return null;
|
||||
}
|
||||
if(routers.size()==0 && masterRouters.size()!=0){
|
||||
routers=masterRouters;
|
||||
}
|
||||
routers=routers.subList(0,1);
|
||||
routers.get(0).setUpdateState(VirtualRouter.UpdateState.UPDATE_IN_PROGRESS);
|
||||
_routerDao.persist(routers.get(0));
|
||||
}
|
||||
return routers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shutdown(final Network network, final ReservationContext context, final boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
|
||||
final List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER);
|
||||
|
|
@ -1031,7 +1077,7 @@ NetworkMigrationResponder, AggregatedCommandExecutor {
|
|||
List<DomainRouterVO> routers;
|
||||
|
||||
if (publicNetwork) {
|
||||
routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER);
|
||||
routers = getRouters(network);
|
||||
} else {
|
||||
if (isPodBased && dest.getPod() != null) {
|
||||
final Long podId = dest.getPod().getId();
|
||||
|
|
@ -1228,7 +1274,27 @@ NetworkMigrationResponder, AggregatedCommandExecutor {
|
|||
throw new ResourceUnavailableException("Can't find at least one router!", DataCenter.class, network.getDataCenterId());
|
||||
}
|
||||
|
||||
return _routerMgr.completeAggregatedExecution(network, routers);
|
||||
NetworkDetailVO networkDetail=_networkDetailsDao.findDetail(network.getId(), Network.updatingInSequence);
|
||||
boolean updateInSequence= "true".equalsIgnoreCase((networkDetail!=null ? networkDetail.getValue() : null));
|
||||
if(updateInSequence){
|
||||
DomainRouterVO router=routers.get(0);
|
||||
router.setUpdateState(VirtualRouter.UpdateState.UPDATE_COMPLETE);
|
||||
_routerDao.persist(router);
|
||||
}
|
||||
boolean result=false;
|
||||
try{
|
||||
result=_routerMgr.completeAggregatedExecution(network, routers);
|
||||
} finally {
|
||||
if(!result && updateInSequence) {
|
||||
//fail the network update. even if one router fails we fail the network update.
|
||||
List<DomainRouterVO> routerList = _routerDao.listByNetworkAndRole(network.getId(), VirtualRouter.Role.VIRTUAL_ROUTER);
|
||||
for (DomainRouterVO router : routerList) {
|
||||
router.setUpdateState(VirtualRouter.UpdateState.UPDATE_FAILED);
|
||||
_routerDao.persist(router);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -1237,4 +1303,22 @@ NetworkMigrationResponder, AggregatedCommandExecutor {
|
|||
// lets not waste another command
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureResource(Network network) {
|
||||
NetworkDetailVO networkDetail=_networkDetailsDao.findDetail(network.getId(), Network.updatingInSequence);
|
||||
if(networkDetail==null || !"true".equalsIgnoreCase(networkDetail.getValue()))
|
||||
throw new CloudRuntimeException("failed to configure the resource, network update is not in progress.");
|
||||
List<DomainRouterVO>routers = _routerDao.listByNetworkAndRole(network.getId(), VirtualRouter.Role.VIRTUAL_ROUTER);
|
||||
for(DomainRouterVO router : routers){
|
||||
router.setUpdateState(VirtualRouter.UpdateState.UPDATE_NEEDED);
|
||||
_routerDao.persist(router);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getResourceCount(Network network) {
|
||||
return _routerDao.listByNetworkAndRole(network.getId(), VirtualRouter.Role.VIRTUAL_ROUTER).size();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2215,6 +2215,11 @@ Configurable, StateListener<VirtualMachine.State, VirtualMachine.Event, VirtualM
|
|||
|
||||
// verify parameters
|
||||
DomainRouterVO router = _routerDao.findById(routerId);
|
||||
//clean up the update_state feild
|
||||
if(router.getUpdateState()== VirtualRouter.UpdateState.UPDATE_FAILED){
|
||||
router.setUpdateState(null);
|
||||
_routerDao.update(router.getId(),router);
|
||||
}
|
||||
if (router == null) {
|
||||
throw new InvalidParameterValueException("Unable to find router by id " + routerId + ".");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -696,6 +696,16 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian
|
|||
return _routerDao.listByVpcId(vpcId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startRemoteAccessVpn(final RemoteAccessVpn vpn, final VirtualRouter router) throws ResourceUnavailableException {
|
||||
if (router.getState() != State.Running) {
|
||||
|
|
|
|||
|
|
@ -281,7 +281,7 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc
|
|||
@Override
|
||||
@DB
|
||||
@ActionEvent(eventType = EventTypes.EVENT_REMOTE_ACCESS_VPN_DESTROY, eventDescription = "removing remote access vpn", async = true)
|
||||
public boolean destroyRemoteAccessVpnForIp(long ipId, Account caller) throws ResourceUnavailableException {
|
||||
public boolean destroyRemoteAccessVpnForIp(long ipId, Account caller, final boolean forceCleanup) throws ResourceUnavailableException {
|
||||
final RemoteAccessVpnVO vpn = _remoteAccessVpnDao.findByPublicIpAddress(ipId);
|
||||
if (vpn == null) {
|
||||
s_logger.debug("there are no Remote access vpns for public ip address id=" + ipId);
|
||||
|
|
@ -309,7 +309,7 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc
|
|||
RemoteAccessVpn.State.Running);
|
||||
success = false;
|
||||
} finally {
|
||||
if (success) {
|
||||
if (success|| forceCleanup) {
|
||||
//Cleanup corresponding ports
|
||||
final List<? extends FirewallRule> vpnFwRules = _rulesDao.listByIpAndPurpose(ipId, Purpose.Vpn);
|
||||
|
||||
|
|
@ -339,7 +339,7 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc
|
|||
success = _firewallMgr.applyIngressFirewallRules(ipId, caller);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
if (success|| forceCleanup) {
|
||||
try {
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -786,7 +786,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||
|
||||
try {
|
||||
for (RemoteAccessVpnVO vpn : remoteAccessVpns) {
|
||||
_remoteAccessVpnMgr.destroyRemoteAccessVpnForIp(vpn.getServerAddressId(), caller);
|
||||
_remoteAccessVpnMgr.destroyRemoteAccessVpnForIp(vpn.getServerAddressId(), caller, false);
|
||||
}
|
||||
} catch (ResourceUnavailableException ex) {
|
||||
s_logger.warn("Failed to cleanup remote access vpn resources as a part of account id=" + accountId + " cleanup due to Exception: ", ex);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.network.dao.NetworkDetailVO;
|
||||
import com.cloud.network.dao.NetworkDetailsDao;
|
||||
import com.cloud.network.router.VirtualRouter;
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
|
@ -106,6 +109,7 @@ public class RouterDeploymentDefinition {
|
|||
protected Long tableLockId;
|
||||
protected boolean isPublicNetwork;
|
||||
protected PublicIp sourceNatIp;
|
||||
protected NetworkDetailsDao networkDetailsDao;
|
||||
|
||||
protected RouterDeploymentDefinition(final Network guestNetwork, final DeployDestination dest,
|
||||
final Account owner, final Map<Param, Object> params) {
|
||||
|
|
@ -410,7 +414,13 @@ public class RouterDeploymentDefinition {
|
|||
// Don't start the router as we are holding the network lock that
|
||||
// needs to be released at the end of router allocation
|
||||
final DomainRouterVO router = nwHelper.deployRouter(this, false);
|
||||
|
||||
//check if the network update is in progress.
|
||||
//if update is in progress add the update_pending flag to DomainRouterVO.
|
||||
NetworkDetailVO detail =networkDetailsDao.findDetail(guestNetwork.getId(),Network.updatingInSequence);
|
||||
if("true".equalsIgnoreCase(detail!=null ? detail.getValue() : null)) {
|
||||
router.setUpdateState(VirtualRouter.UpdateState.UPDATE_IN_PROGRESS);
|
||||
routerDao.persist(router);
|
||||
}
|
||||
if (router != null) {
|
||||
routerDao.addRouterToGuestNetwork(router, guestNetwork);
|
||||
//Fix according to changes by Sheng Yang in commit ID cb4513379996b262ae378daf00c6388c6b7313cf
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import java.util.Map;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.network.dao.NetworkDetailsDao;
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
|
|
@ -96,6 +97,8 @@ public class RouterDeploymentDefinitionBuilder {
|
|||
private VpcManager vpcMgr;
|
||||
@Inject
|
||||
private VlanDao vlanDao;
|
||||
@Inject
|
||||
private NetworkDetailsDao networkDetailsDao;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("networkHelper")
|
||||
|
|
@ -133,6 +136,7 @@ public class RouterDeploymentDefinitionBuilder {
|
|||
routerDeploymentDefinition.ipv6Dao = ipv6Dao;
|
||||
routerDeploymentDefinition.ipAddressDao = ipAddressDao;
|
||||
routerDeploymentDefinition.serviceOfferingId = offeringId;
|
||||
routerDeploymentDefinition.networkDetailsDao = networkDetailsDao;
|
||||
|
||||
routerDeploymentDefinition.nwHelper = nwHelper;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package com.cloud.network.element;
|
|||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
import static org.mockito.Matchers.anyList;
|
||||
import static org.mockito.Matchers.anyLong;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
|
@ -26,6 +27,11 @@ import static org.mockito.Mockito.when;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.exception.AgentUnavailableException;
|
||||
import com.cloud.network.dao.NetworkDetailVO;
|
||||
import com.cloud.network.dao.NetworkDetailsDao;
|
||||
import com.cloud.network.router.VirtualRouter;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.cloud.network.router.deployment.RouterDeploymentDefinitionBuilder;
|
||||
|
|
@ -35,6 +41,8 @@ import org.junit.runner.RunWith;
|
|||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Matchers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import com.cloud.cluster.dao.ManagementServerHostDao;
|
||||
|
|
@ -111,6 +119,7 @@ import com.cloud.vm.dao.NicIpAliasDao;
|
|||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.UserVmDetailsDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class VirtualRouterElementTest {
|
||||
|
|
@ -127,6 +136,7 @@ public class VirtualRouterElementTest {
|
|||
@Mock private ManagementServerHostDao _msHostDao;
|
||||
@Mock private NetworkDao _networkDao;
|
||||
@Mock private NetworkOfferingDao _networkOfferingDao;
|
||||
@Mock private NetworkDetailsDao _networkDetailsDao;
|
||||
@Mock private NicDao _nicDao;
|
||||
@Mock private NicIpAliasDao _nicIpAliasDao;
|
||||
@Mock private OpRouterMonitorServiceDao _opRouterMonitorServiceDao;
|
||||
|
|
@ -225,6 +235,62 @@ public class VirtualRouterElementTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRouters1(){
|
||||
Network networkUpdateInprogress=new NetworkVO(1l,null,null,null,1l,1l,1l,1l,"d","d","d",null,1l,1l,null,true,null,true);
|
||||
mockDAOs((NetworkVO)networkUpdateInprogress,testOffering);
|
||||
//getRoutes should always return the router that is updating.
|
||||
List<DomainRouterVO> routers=virtualRouterElement.getRouters(networkUpdateInprogress);
|
||||
assertTrue(routers.size()==1);
|
||||
assertTrue(routers.get(0).getUpdateState()== VirtualRouter.UpdateState.UPDATE_IN_PROGRESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRouters2(){
|
||||
Network networkUpdateInprogress=new NetworkVO(2l,null,null,null,1l,1l,1l,1l,"d","d","d",null,1l,1l,null,true,null,true);
|
||||
mockDAOs((NetworkVO)networkUpdateInprogress,testOffering);
|
||||
//alwyas return backup routers first when both master and backup need update.
|
||||
List<DomainRouterVO> routers=virtualRouterElement.getRouters(networkUpdateInprogress);
|
||||
assertTrue(routers.size()==1);
|
||||
assertTrue(routers.get(0).getRedundantState()==RedundantState.BACKUP && routers.get(0).getUpdateState()==VirtualRouter.UpdateState.UPDATE_IN_PROGRESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRouters3(){
|
||||
Network network=new NetworkVO(3l,null,null,null,1l,1l,1l,1l,"d","d","d",null,1l,1l,null,true,null,true);
|
||||
mockDAOs((NetworkVO)network,testOffering);
|
||||
//alwyas return backup routers first when both master and backup need update.
|
||||
List<DomainRouterVO> routers=virtualRouterElement.getRouters(network);
|
||||
assertTrue(routers.size()==4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResourceCountTest(){
|
||||
Network network=new NetworkVO(3l,null,null,null,1l,1l,1l,1l,"d","d","d",null,1l,1l,null,true,null,true);
|
||||
mockDAOs((NetworkVO)network,testOffering);
|
||||
int routers=virtualRouterElement.getResourceCount(network);
|
||||
assertTrue(routers==4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void completeAggregationCommandTest1() throws AgentUnavailableException,ResourceUnavailableException {
|
||||
virtualRouterElement._routerMgr = Mockito.mock(VpcVirtualNetworkApplianceManagerImpl.class);
|
||||
virtualRouterElement.routerDeploymentDefinitionBuilder = routerDeploymentDefinitionBuilder;
|
||||
Network network = new NetworkVO(6l, null, null, null, 1l, 1l, 1l, 1l, "d", "d", "d", null, 1l, 1l, null, true, null, true);
|
||||
when(virtualRouterElement._routerMgr.completeAggregatedExecution(any(Network.class), anyList())).thenReturn(true);
|
||||
mockDAOs((NetworkVO) network, testOffering);
|
||||
when(virtualRouterElement._routerDao.persist(any(DomainRouterVO.class))).thenAnswer(new Answer<Object>() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
|
||||
Object args[] = invocationOnMock.getArguments();
|
||||
DomainRouterVO router = (DomainRouterVO) args[0];
|
||||
if (router.getUpdateState() != VirtualRouter.UpdateState.UPDATE_COMPLETE) {
|
||||
throw new CloudRuntimeException("TestFailed: completeAggregationCommandTest1 failed");
|
||||
} else return null;
|
||||
}
|
||||
});
|
||||
virtualRouterElement.completeAggregatedExecution(network, testDestination);
|
||||
}
|
||||
/**
|
||||
* @param networks
|
||||
* @param offerings
|
||||
|
|
@ -293,11 +359,94 @@ public class VirtualRouterElementTest {
|
|||
/* haEnabled */ false,
|
||||
/* stopPending */ false,
|
||||
/* vpcId */ null);
|
||||
|
||||
final DomainRouterVO routerNeedUpdateBackup = new DomainRouterVO(/* id */ 2L,
|
||||
/* serviceOfferingId */ 1L,
|
||||
/* elementId */ 0L,
|
||||
"name",
|
||||
/* templateId */0L,
|
||||
HypervisorType.XenServer,
|
||||
/* guestOSId */ 0L,
|
||||
/* domainId */ 0L,
|
||||
/* accountId */ 1L,
|
||||
/* userId */ 1L,
|
||||
/* isRedundantRouter */ false,
|
||||
RedundantState.BACKUP,
|
||||
/* haEnabled */ false,
|
||||
/* stopPending */ false,
|
||||
/* vpcId */ null);
|
||||
routerNeedUpdateBackup.setUpdateState(VirtualRouter.UpdateState.UPDATE_NEEDED);
|
||||
final DomainRouterVO routerNeedUpdateMaster = new DomainRouterVO(/* id */ 3L,
|
||||
/* serviceOfferingId */ 1L,
|
||||
/* elementId */ 0L,
|
||||
"name",
|
||||
/* templateId */0L,
|
||||
HypervisorType.XenServer,
|
||||
/* guestOSId */ 0L,
|
||||
/* domainId */ 0L,
|
||||
/* accountId */ 1L,
|
||||
/* userId */ 1L,
|
||||
/* isRedundantRouter */ false,
|
||||
RedundantState.MASTER,
|
||||
/* haEnabled */ false,
|
||||
/* stopPending */ false,
|
||||
/* vpcId */ null);
|
||||
routerNeedUpdateMaster.setUpdateState(VirtualRouter.UpdateState.UPDATE_NEEDED);
|
||||
final DomainRouterVO routerUpdateComplete = new DomainRouterVO(/* id */ 4L,
|
||||
/* serviceOfferingId */ 1L,
|
||||
/* elementId */ 0L,
|
||||
"name",
|
||||
/* templateId */0L,
|
||||
HypervisorType.XenServer,
|
||||
/* guestOSId */ 0L,
|
||||
/* domainId */ 0L,
|
||||
/* accountId */ 1L,
|
||||
/* userId */ 1L,
|
||||
/* isRedundantRouter */ false,
|
||||
RedundantState.UNKNOWN,
|
||||
/* haEnabled */ false,
|
||||
/* stopPending */ false,
|
||||
/* vpcId */ null);
|
||||
routerUpdateComplete.setUpdateState(VirtualRouter.UpdateState.UPDATE_COMPLETE);
|
||||
final DomainRouterVO routerUpdateInProgress = new DomainRouterVO(/* id */ 5L,
|
||||
/* serviceOfferingId */ 1L,
|
||||
/* elementId */ 0L,
|
||||
"name",
|
||||
/* templateId */0L,
|
||||
HypervisorType.XenServer,
|
||||
/* guestOSId */ 0L,
|
||||
/* domainId */ 0L,
|
||||
/* accountId */ 1L,
|
||||
/* userId */ 1L,
|
||||
/* isRedundantRouter */ false,
|
||||
RedundantState.UNKNOWN,
|
||||
/* haEnabled */ false,
|
||||
/* stopPending */ false,
|
||||
/* vpcId */ null);
|
||||
routerUpdateInProgress.setUpdateState(VirtualRouter.UpdateState.UPDATE_IN_PROGRESS);
|
||||
List<DomainRouterVO> routerList1=new ArrayList<>();
|
||||
routerList1.add(routerUpdateComplete);
|
||||
routerList1.add(routerNeedUpdateBackup);
|
||||
routerList1.add(routerNeedUpdateMaster);
|
||||
routerList1.add(routerUpdateInProgress);
|
||||
List<DomainRouterVO> routerList2=new ArrayList<>();
|
||||
routerList2.add(routerUpdateComplete);
|
||||
routerList2.add(routerNeedUpdateBackup);
|
||||
routerList2.add(routerNeedUpdateMaster);
|
||||
List<DomainRouterVO> routerList3=new ArrayList<>();
|
||||
routerList3.add(routerUpdateComplete);
|
||||
routerList3.add(routerUpdateInProgress);
|
||||
when(_routerDao.getNextInSequence(Long.class, "id")).thenReturn(1L);
|
||||
when(_templateDao.findRoutingTemplate(HypervisorType.XenServer, "SystemVM Template (XenServer)")).thenReturn(new VMTemplateVO());
|
||||
when(_routerDao.persist(any(DomainRouterVO.class))).thenReturn(router);
|
||||
when(_routerDao.findById(router.getId())).thenReturn(router);
|
||||
when(_routerDao.listByNetworkAndRole(1l, VirtualRouter.Role.VIRTUAL_ROUTER)).thenReturn(routerList1);
|
||||
when(_routerDao.listByNetworkAndRole(2l, VirtualRouter.Role.VIRTUAL_ROUTER)).thenReturn(routerList2);
|
||||
when(_routerDao.listByNetworkAndRole(3l, VirtualRouter.Role.VIRTUAL_ROUTER)).thenReturn(routerList1);
|
||||
when(_routerDao.listByNetworkAndRole(6l, VirtualRouter.Role.VIRTUAL_ROUTER)).thenReturn(routerList3);
|
||||
when(_networkDetailsDao.findDetail(1l, Network.updatingInSequence)).thenReturn(new NetworkDetailVO(1l,Network.updatingInSequence,"true",true));
|
||||
when(_networkDetailsDao.findDetail(2l, Network.updatingInSequence)).thenReturn(new NetworkDetailVO(2l,Network.updatingInSequence,"true",true));
|
||||
when(_networkDetailsDao.findDetail(6l, Network.updatingInSequence)).thenReturn(new NetworkDetailVO(2l,Network.updatingInSequence,"true",true));
|
||||
when(_routerDao.persist(any(DomainRouterVO.class))).thenReturn(router);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -247,7 +247,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches
|
|||
*/
|
||||
@Override
|
||||
public Network updateGuestNetwork(long networkId, String name, String displayText, Account callerAccount, User callerUser, String domainSuffix,
|
||||
Long networkOfferingId, Boolean changeCidr, String guestVmCidr, Boolean displayNetwork, String newUUID) {
|
||||
Long networkOfferingId, Boolean changeCidr, String guestVmCidr, Boolean displayNetwork, String newUUID,boolean updateInSequence, boolean forced) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
|
@ -841,6 +841,31 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches
|
|||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUpdateInSequence(Network network) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getServicesNotSupportedInNewOffering(Network network, long newNetworkOfferingId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanupConfigForServicesInNetwork(List<String> services, Network network) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureUpdateInSequence(Network network) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getResourceCount(Network network) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareNicForMigration(VirtualMachineProfile vm, DeployDestination dest) {
|
||||
// TODO Auto-generated method stub
|
||||
|
|
|
|||
|
|
@ -714,7 +714,7 @@ public class RouterDeploymentDefinitionTest extends RouterDeploymentDefinitionTe
|
|||
final DomainRouterVO routerVO2 = mock(DomainRouterVO.class);
|
||||
when(mockNetworkHelper.deployRouter(deploymentUT, false))
|
||||
.thenReturn(routerVO1).thenReturn(routerVO2);
|
||||
|
||||
when(networkDetailsDao.findById(anyLong())).thenReturn(null);
|
||||
// Execute
|
||||
deploymentUT.deployAllVirtualRouters();
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.network.dao.NetworkDetailsDao;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
|
|
@ -79,6 +80,8 @@ public class RouterDeploymentDefinitionTestBase {
|
|||
@Mock
|
||||
protected NetworkHelper mockNetworkHelper;
|
||||
@Mock
|
||||
protected NetworkDetailsDao networkDetailsDao;
|
||||
@Mock
|
||||
protected VpcNetworkHelperImpl vpcNwHelper;
|
||||
@Mock
|
||||
protected VMInstanceDao mockVmDao;
|
||||
|
|
|
|||
|
|
@ -420,3 +420,5 @@ INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervis
|
|||
INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'KVM', 'default', 'CentOS 7', 246, utc_timestamp(), 0);
|
||||
|
||||
UPDATE `cloud`.`hypervisor_capabilities` SET `max_data_volumes_limit` = '32' WHERE `hypervisor_capabilities`.`hypervisor_type` = 'KVM';
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -18,3 +18,5 @@
|
|||
--;
|
||||
-- Schema upgrade from 4.9.1.0 to 4.10.0.0;
|
||||
--;
|
||||
|
||||
ALTER TABLE `cloud`.`domain_router` ADD COLUMN update_state varchar(64) DEFAULT NULL;
|
||||
|
|
@ -29,6 +29,7 @@ from marvin.lib.common import (get_domain,
|
|||
get_zone,
|
||||
get_process_status)
|
||||
import time
|
||||
import multiprocessing
|
||||
|
||||
# Import Local Modules
|
||||
from marvin.cloudstackTestCase import cloudstackTestCase
|
||||
|
|
@ -872,9 +873,16 @@ class TestRvRRedundancy(cloudstackTestCase):
|
|||
cls.testdata["nw_off_isolated_RVR"],
|
||||
conservemode=True
|
||||
)
|
||||
cls.network_offering_for_update=NetworkOffering.create(
|
||||
cls.api_client,
|
||||
cls.testdata["nw_off_isolated_RVR"],
|
||||
conservemode=True
|
||||
)
|
||||
cls._cleanup.append(cls.network_offering_for_update)
|
||||
cls._cleanup.append(cls.network_offering)
|
||||
# Enable Network offering
|
||||
cls.network_offering.update(cls.api_client, state='Enabled')
|
||||
cls.network_offering_for_update.update(cls.api_client, state='Enabled')
|
||||
return
|
||||
|
||||
@classmethod
|
||||
|
|
@ -1511,3 +1519,149 @@ class TestRvRRedundancy(cloudstackTestCase):
|
|||
"Redundant state of the router should be BACKUP but is %s" %
|
||||
routers[0].redundantstate)
|
||||
return
|
||||
|
||||
def updateNetwork(self, conn):
|
||||
try:
|
||||
self.network.update(
|
||||
self.api_client,
|
||||
networkofferingid=self.network_offering_for_update.id,
|
||||
updateinsequence=True,
|
||||
forced=True,
|
||||
changecidr=False
|
||||
)
|
||||
except Exception as e:
|
||||
conn.send("Failed to update network: %s due to %s"%(self.network.name, e))
|
||||
conn.send("update Network Complete")
|
||||
return
|
||||
|
||||
|
||||
|
||||
def get_master_and_backupRouter(self):
|
||||
retry = 4
|
||||
master_router = backup_router=None
|
||||
while retry > 0:
|
||||
routers = Router.list(
|
||||
self.apiclient,
|
||||
networkid=self.network.id,
|
||||
listall=True
|
||||
)
|
||||
retry = retry-1
|
||||
if not (routers[0].redundantstate == 'MASTER' or routers[1].redundantstate == 'MASTER'):
|
||||
continue;
|
||||
if routers[0].redundantstate == 'MASTER':
|
||||
master_router = routers[0]
|
||||
backup_router = routers[1]
|
||||
break
|
||||
else:
|
||||
master_router = routers[1]
|
||||
backup_router = routers[0]
|
||||
break
|
||||
return master_router, backup_router
|
||||
|
||||
|
||||
def chek_for_new_backupRouter(self,old_backup_router):
|
||||
master_router, backup_router = self.get_master_and_backupRouter()
|
||||
retry = 4
|
||||
self.info("Checking if new router is getting created.")
|
||||
self.info("old_backup_router:"+old_backup_router.name+" new_backup_router:"+backup_router.name)
|
||||
while old_backup_router.name == backup_router.name:
|
||||
self.debug("waiting for new router old router:"+backup_router.name)
|
||||
retry = retry-1
|
||||
if retry == 0:
|
||||
break;
|
||||
time.sleep(self.testdata["sleep"])
|
||||
master_router, backup_router = self.get_master_and_backupRouter()
|
||||
if retry == 0:
|
||||
self.fail("New router creation taking too long, timed out")
|
||||
|
||||
def wait_untill_router_stabilises(self):
|
||||
retry=4
|
||||
while retry > 0:
|
||||
routers = Router.list(
|
||||
self.apiclient,
|
||||
networkid=self.network.id,
|
||||
listall=True
|
||||
)
|
||||
retry = retry-1
|
||||
self.info("waiting untill state of the routers is stable")
|
||||
if routers[0].redundantstate != 'UNKNOWN' and routers[1].redundantstate != 'UNKNOWN':
|
||||
return
|
||||
elif retry==0:
|
||||
self.fail("timedout while waiting for routers to stabilise")
|
||||
return
|
||||
time.sleep(self.testdata["sleep"])
|
||||
|
||||
@attr(tags=["bharat"])
|
||||
def test_06_updateVRs_in_sequence(self):
|
||||
"""Test update network and check if VRs are updated in sequence
|
||||
"""
|
||||
|
||||
# Steps to validate
|
||||
# update network to a new offering
|
||||
# check if the master router is running while backup is starting.
|
||||
# check if the backup is running while master is starting.
|
||||
# check if both the routers are running after the update is complete.
|
||||
|
||||
#clean up the network to make sure it is in proper state.
|
||||
self.network.restart(self.apiclient,cleanup=True)
|
||||
time.sleep(self.testdata["sleep"])
|
||||
self.wait_untill_router_stabilises()
|
||||
old_master_router, old_backup_router = self.get_master_and_backupRouter()
|
||||
self.info("old_master_router:"+old_master_router.name+" old_backup_router"+old_backup_router.name)
|
||||
#chek if the network is in correct state
|
||||
self.assertEqual(old_master_router.state, "Running", "The master router is not running, network is not in a correct state to start the test")
|
||||
self.assertEqual(old_backup_router.state, "Running", "The backup router is not running, network is not in a correct state to start the test")
|
||||
|
||||
worker, monitor = multiprocessing.Pipe()
|
||||
worker_process = multiprocessing.Process(target=self.updateNetwork, args=(worker,))
|
||||
worker_process.start()
|
||||
if not worker_process.is_alive():
|
||||
message = monitor.recv()
|
||||
if "Complete" not in message:
|
||||
self.fail(message)
|
||||
|
||||
self.info("Network update Started, the old backup router will get destroyed and a new router will be created")
|
||||
|
||||
self.chek_for_new_backupRouter(old_backup_router)
|
||||
master_router, new_backup_router=self.get_master_and_backupRouter()
|
||||
#the state of the master router should be running. while backup is being updated
|
||||
self.assertEqual(master_router.state, "Running", "State of the master router is not running")
|
||||
self.assertEqual(master_router.redundantstate, 'MASTER', "Redundant state of the master router should be MASTER, but it is %s"%master_router.redundantstate)
|
||||
self.info("Old backup router:"+old_backup_router.name+" is destroyed and new router:"+new_backup_router.name+" got created")
|
||||
|
||||
#wait for the new backup to become master.
|
||||
retry = 4
|
||||
while new_backup_router.name != master_router.name:
|
||||
retry = retry-1
|
||||
if retry == 0:
|
||||
break
|
||||
time.sleep(self.testdata["sleep"])
|
||||
self.info("wating for backup router to become master router name:"+new_backup_router.name)
|
||||
master_router, backup_router = self.get_master_and_backupRouter()
|
||||
if retry == 0:
|
||||
self.fail("timed out while waiting for new backup router to change state to MASTER.")
|
||||
|
||||
#new backup router has become master.
|
||||
self.info("newly created router:"+new_backup_router.name+" has changed state to Master")
|
||||
self.info("old master router:"+old_master_router.name+"is destroyed")
|
||||
#old master will get destroyed and a new backup will be created.
|
||||
#wait until new backup changes state from unknown to backup
|
||||
master_router, backup_router = self.get_master_and_backupRouter()
|
||||
retry = 4
|
||||
while backup_router.redundantstate != 'BACKUP':
|
||||
retry = retry-1
|
||||
self.info("waiting for router:"+backup_router.name+" to change state to Backup")
|
||||
if retry == 0:
|
||||
break
|
||||
time.sleep(self.testdata["sleep"])
|
||||
master_router, backup_router = self.get_master_and_backupRouter()
|
||||
self.assertEqual(master_router.state, "Running", "State of the master router is not running")
|
||||
self.assertEqual(master_router.redundantstate, 'MASTER', "Redundant state of the master router should be MASTER, but it is %s"%master_router.redundantstate)
|
||||
if retry == 0:
|
||||
self.fail("timed out while waiting for new backup rotuer to change state to MASTER.")
|
||||
|
||||
#the network update is complete.finally both the router should be running.
|
||||
new_master_router, new_backup_router=self.get_master_and_backupRouter()
|
||||
self.assertEqual(new_master_router.state, "Running", "State of the master router:"+new_master_router.name+" is not running")
|
||||
self.assertEqual(new_backup_router.state, "Running", "State of the backup router:"+new_backup_router.name+" is not running")
|
||||
worker_process.join()
|
||||
|
|
|
|||
Loading…
Reference in New Issue