This is an automated email from the ASF dual-hosted git repository. rohit pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit bd9880003f8aa28287920f1d85c1bee4d4d1f675 Merge: e73fb76 ea771cf Author: Rohit Yadav <rohit.ya...@shapeblue.com> AuthorDate: Wed Oct 10 16:10:26 2018 +0530 Merge remote-tracking branch 'origin/4.11' Signed-off-by: Rohit Yadav <rohit.ya...@shapeblue.com> api/src/main/java/com/cloud/network/Network.java | 21 ++++++++++ .../java/com/cloud/network/NetworkProfile.java | 8 ++-- .../src/main/java/com/cloud/vm/dao/NicDao.java | 2 + .../src/main/java/com/cloud/vm/dao/NicDaoImpl.java | 7 ++++ .../cloud/network/element/NuageVspElementTest.java | 46 ++++++++++++++-------- .../VpcVirtualNetworkApplianceManagerImpl.java | 2 +- systemvm/debian/opt/cloud/bin/cs_ip.py | 17 ++++++++ .../java/com/cloud/utils/net/NetUtilsTest.java | 6 ++- 8 files changed, 87 insertions(+), 22 deletions(-) diff --cc plugins/network-elements/nuage-vsp/src/test/java/com/cloud/network/element/NuageVspElementTest.java index 8cd8ee4,0000000..da4312c mode 100644,000000..100644 --- a/plugins/network-elements/nuage-vsp/src/test/java/com/cloud/network/element/NuageVspElementTest.java +++ b/plugins/network-elements/nuage-vsp/src/test/java/com/cloud/network/element/NuageVspElementTest.java @@@ -1,368 -1,0 +1,382 @@@ +// +// 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 static org.hamcrest.Matchers.is; ++import static org.junit.Assert.assertFalse; ++import static org.junit.Assert.assertThat; ++import static org.junit.Assert.assertTrue; ++import static org.junit.Assert.fail; ++import static org.mockito.Matchers.any; ++import static org.mockito.Matchers.eq; ++import static org.mockito.Mockito.mock; ++import static org.mockito.Mockito.when; ++import static org.mockito.Mockito.withSettings; ++ +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Set; + - import com.cloud.network.dao.NetworkDao; - import com.cloud.network.dao.NetworkVO; - import com.cloud.tags.dao.ResourceTagDao; ++import org.apache.cloudstack.resourcedetail.dao.VpcDetailsDao; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; + - import com.google.common.collect.Lists; - import com.google.common.collect.Sets; - - import org.apache.cloudstack.resourcedetail.dao.VpcDetailsDao; - +import com.cloud.NuageTest; +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.deploy.DeployDestination; +import com.cloud.domain.DomainVO; +import com.cloud.domain.dao.DomainDao; +import com.cloud.exception.CloudException; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.ResourceUnavailableException; ++import com.cloud.exception.UnsupportedServiceException; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.network.Network; +import com.cloud.network.Network.GuestType; +import com.cloud.network.Network.Provider; +import com.cloud.network.Network.Service; +import com.cloud.network.Networks.BroadcastDomainType; +import com.cloud.network.Networks.TrafficType; +import com.cloud.network.NuageVspDeviceVO; +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.NetworkServiceMapDao; ++import com.cloud.network.dao.NetworkVO; +import com.cloud.network.dao.NuageVspDao; +import com.cloud.network.dao.PhysicalNetworkDao; +import com.cloud.network.dao.PhysicalNetworkVO; +import com.cloud.network.manager.NuageVspManager; +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.FirewallRuleVO; +import com.cloud.network.rules.StaticNat; +import com.cloud.network.vpc.NetworkACLItem; +import com.cloud.network.vpc.Vpc; +import com.cloud.offering.NetworkOffering; +import com.cloud.offerings.NetworkOfferingVO; +import com.cloud.offerings.dao.NetworkOfferingDao; +import com.cloud.offerings.dao.NetworkOfferingServiceMapDao; +import com.cloud.resource.ResourceManager; ++import com.cloud.tags.dao.ResourceTagDao; +import com.cloud.user.Account; +import com.cloud.util.NuageVspEntityBuilder; +import com.cloud.vm.DomainRouterVO; +import com.cloud.vm.ReservationContext; +import com.cloud.vm.dao.DomainRouterDao; - - import static org.junit.Assert.assertFalse; - import static org.junit.Assert.assertTrue; - import static org.mockito.Matchers.any; - import static org.mockito.Matchers.eq; - import static org.mockito.Mockito.mock; - import static org.mockito.Mockito.when; - import static org.mockito.Mockito.withSettings; ++import com.google.common.collect.Lists; ++import com.google.common.collect.Sets; + +public class NuageVspElementTest extends NuageTest { + + @InjectMocks + private NuageVspElement _nuageVspElement = new NuageVspElement(); + + @Mock private NetworkServiceMapDao _networkServiceMapDao; + @Mock private AgentManager _agentManager; + @Mock private HostDao _hostDao; + @Mock private NuageVspDao _nuageVspDao; + @Mock private DomainDao _domainDao; + @Mock private NetworkOfferingDao _networkOfferingDao; + @Mock private NetworkOfferingServiceMapDao _networkOfferingServiceMapDao; + @Mock private NuageVspManager _nuageVspManager; + @Mock private FirewallRulesDao _firewallRulesDao; + @Mock private IPAddressDao _ipAddressDao; + @Mock private PhysicalNetworkDao _physicalNetworkDao; + @Mock private NuageVspEntityBuilder _nuageVspEntityBuilder; + @Mock private VpcDetailsDao _vpcDetailsDao; + @Mock private DomainRouterDao _domainRouterDao; + @Mock private ResourceManager _resourceManager; + @Mock private ResourceTagDao _resourceTagDao; + @Mock private NetworkDao _networkDao; + + @Before + public void setUp() throws Exception { + super.setUp(); + _nuageVspElement._nuageVspEntityBuilder = _nuageVspEntityBuilder; + _nuageVspElement._vpcDetailsDao = _vpcDetailsDao; + _nuageVspElement._routerDao = _domainRouterDao; + _nuageVspElement._networkDao = _networkDao; + + when(_networkServiceMapDao.canProviderSupportServiceInNetwork(NETWORK_ID, Service.Connectivity, Provider.NuageVsp)).thenReturn(true); + when(_networkServiceMapDao.canProviderSupportServiceInNetwork(NETWORK_ID, Service.SourceNat, Provider.NuageVsp)).thenReturn(true); + + _nuageVspElement.configure("NuageVspTestElement", Collections.<String, Object>emptyMap()); + } + + @Test + public void testCanHandle() { + final Network net = mock(Network.class); + when(net.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Vsp); + when(net.getId()).thenReturn(NETWORK_ID); + when(net.getNetworkOfferingId()).thenReturn(NETWORK_ID); + + final NetworkOfferingVO ntwkoffer = mock(NetworkOfferingVO.class); + when(ntwkoffer.getId()).thenReturn(NETWORK_ID); + when(ntwkoffer.isPersistent()).thenReturn(true); + when(_networkOfferingDao.findById(NETWORK_ID)).thenReturn(ntwkoffer); + + // Golden path + assertTrue(_nuageVspElement.canHandle(net, Service.Connectivity)); + + when(net.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Vlan); + // Only broadcastdomaintype Vsp is supported + assertFalse(_nuageVspElement.canHandle(net, Service.Connectivity)); + + when(net.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Vsp); + when(_networkServiceMapDao.canProviderSupportServiceInNetwork(NETWORK_ID, Service.Connectivity, Provider.NuageVsp)).thenReturn(false); + // No NuageVsp provider in the network + assertFalse(_nuageVspElement.canHandle(net, Service.Connectivity)); + + when(_networkModel.isProviderForNetwork(Provider.NuageVsp, NETWORK_ID)).thenReturn(false); + when(_networkServiceMapDao.canProviderSupportServiceInNetwork(NETWORK_ID, Service.Connectivity, Provider.NuageVsp)).thenReturn(true); + // NusageVsp provider does not provide Connectivity for this network + assertFalse(_nuageVspElement.canHandle(net, Service.Connectivity)); + + when(_networkModel.isProviderForNetwork(Provider.NuageVsp, NETWORK_ID)).thenReturn(true); + // Only service Connectivity is supported + assertFalse(_nuageVspElement.canHandle(net, Service.Dhcp)); + + // Can't handle network offerings with specify vlan = true + when(ntwkoffer.isSpecifyVlan()).thenReturn(true); + assertFalse(_nuageVspElement.canHandle(net, Service.Connectivity)); + } + + @Test + public void testImplement() throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException, URISyntaxException { + final Network network = mock(NetworkVO.class, withSettings().extraInterfaces(Network.class)); + when(network.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Vsp); + when(network.getId()).thenReturn(NETWORK_ID); + when(network.getVpcId()).thenReturn(null); + when(network.getBroadcastUri()).thenReturn(new URI("")); + when(network.getPhysicalNetworkId()).thenReturn(NETWORK_ID); + when(network.getDomainId()).thenReturn(NETWORK_ID); + when(network.getDataCenterId()).thenReturn(NETWORK_ID); + when(_networkModel.isProviderForNetwork(Provider.NuageVsp, NETWORK_ID)).thenReturn(true); + + final NetworkVO networkVO = mock(NetworkVO.class); + when(network.getUuid()).thenReturn("aaaaaa"); + + when(_networkDao.findById(NETWORK_ID)).thenReturn(networkVO); + + final NetworkOffering offering = mock(NetworkOffering.class); + when(offering.getId()).thenReturn(NETWORK_ID); + when(offering.getTrafficType()).thenReturn(TrafficType.Guest); + when(offering.getGuestType()).thenReturn(GuestType.Isolated); + + DeployDestination deployDest = mock(DeployDestination.class); + + final DomainVO dom = mock(DomainVO.class); + when(dom.getName()).thenReturn("domain"); + when(_domainDao.findById(NETWORK_ID)).thenReturn(dom); + final Account acc = mock(Account.class); + when(acc.getAccountName()).thenReturn("accountname"); + final ReservationContext context = mock(ReservationContext.class); + when(context.getDomain()).thenReturn(dom); + when(context.getAccount()).thenReturn(acc); + + final HostVO host = mock(HostVO.class); + when(host.getId()).thenReturn(NETWORK_ID); + final NuageVspDeviceVO nuageVspDevice = mock(NuageVspDeviceVO.class); + when(nuageVspDevice.getHostId()).thenReturn(NETWORK_ID); + when(_nuageVspDao.listByPhysicalNetwork(NETWORK_ID)).thenReturn(Arrays.asList(new NuageVspDeviceVO[]{nuageVspDevice})); + when(_hostDao.findById(NETWORK_ID)).thenReturn(host); + when(_nuageVspManager.getNuageVspHost(NETWORK_ID)).thenReturn(host); + + when(_firewallRulesDao.listByNetworkPurposeTrafficType(NETWORK_ID, FirewallRule.Purpose.Firewall, FirewallRule.TrafficType.Ingress)).thenReturn(new ArrayList<FirewallRuleVO>()); + when(_firewallRulesDao.listByNetworkPurposeTrafficType(NETWORK_ID, FirewallRule.Purpose.Firewall, FirewallRule.TrafficType.Egress)).thenReturn(new ArrayList<FirewallRuleVO>()); + when(_ipAddressDao.listStaticNatPublicIps(NETWORK_ID)).thenReturn(new ArrayList<IPAddressVO>()); + when(_nuageVspManager.getDnsDetails(network.getDataCenterId())).thenReturn(new ArrayList<String>()); + when(_networkDao.findById(network.getId())).thenReturn((NetworkVO)network); + + assertTrue(_nuageVspElement.implement(network, offering, deployDest, context)); + } + + @Test + public void testVerifyServiceCombination() { + + Set<Service> services = Sets.newHashSet( + Service.Dhcp, + Service.StaticNat, + Service.SourceNat, + Service.Connectivity, + Service.Firewall); + assertTrue(_nuageVspElement.verifyServicesCombination(services)); + + services = Sets.newHashSet( + Service.Dhcp, + Service.StaticNat, + Service.Connectivity, + Service.Firewall); + assertTrue(_nuageVspElement.verifyServicesCombination(services)); ++ ++ ++ services = Sets.newHashSet( ++ Service.Dhcp, ++ Service.StaticNat, ++ Service.Firewall); ++ try { ++ _nuageVspElement.verifyServicesCombination(services); ++ fail("Expected Exception"); ++ } catch (UnsupportedServiceException e) { ++ assertThat(e.getMessage(), is("Provider Network.Provider[name=NuageVsp] requires services: [Network.Service[name=Connectivity]]")); ++ } + } + + @Test + public void testApplyStaticNats() throws CloudException { + final Network network = mock(Network.class); + when(network.getUuid()).thenReturn("aaaaaa"); + when(network.getVpcId()).thenReturn(null); + when(network.getNetworkOfferingId()).thenReturn(NETWORK_ID); + when(network.getPhysicalNetworkId()).thenReturn(NETWORK_ID); + when(network.getDomainId()).thenReturn(NETWORK_ID); + + final DomainVO domVo = mock(DomainVO.class); + when(_domainDao.findById(41l)).thenReturn(domVo); + + final NetworkOfferingVO ntwkoffer = mock(NetworkOfferingVO.class); + when(ntwkoffer.getId()).thenReturn(NETWORK_ID); + when(_networkOfferingDao.findById(NETWORK_ID)).thenReturn(ntwkoffer); + + final HostVO host = mock(HostVO.class); + when(host.getId()).thenReturn(NETWORK_ID); + final NuageVspDeviceVO nuageVspDevice = mock(NuageVspDeviceVO.class); + when(nuageVspDevice.getHostId()).thenReturn(NETWORK_ID); + when(_nuageVspDao.listByPhysicalNetwork(NETWORK_ID)).thenReturn(Arrays.asList(new NuageVspDeviceVO[]{nuageVspDevice})); + when(_hostDao.findById(NETWORK_ID)).thenReturn(host); + when(_nuageVspManager.getNuageVspHost(NETWORK_ID)).thenReturn(host); + + when(_domainDao.findById(NETWORK_ID)).thenReturn(mock(DomainVO.class)); + final Answer answer = mock(Answer.class); + when(answer.getResult()).thenReturn(true); + when(_agentManager.easySend(eq(NETWORK_ID), (Command)any())).thenReturn(answer); + assertTrue(_nuageVspElement.applyStaticNats(network, new ArrayList<StaticNat>())); + } + + @Test + public void testApplyFWRules() throws Exception { + final Network network = mock(Network.class); + when(network.getUuid()).thenReturn("aaaaaa"); + when(network.getVpcId()).thenReturn(null); + when(network.getNetworkOfferingId()).thenReturn(NETWORK_ID); + when(network.getPhysicalNetworkId()).thenReturn(NETWORK_ID); + when(network.getDomainId()).thenReturn(NETWORK_ID); + + final NetworkOfferingVO ntwkoffer = mock(NetworkOfferingVO.class); + when(ntwkoffer.getId()).thenReturn(NETWORK_ID); + when(ntwkoffer.isEgressDefaultPolicy()).thenReturn(true); + when(_networkOfferingDao.findById(NETWORK_ID)).thenReturn(ntwkoffer); + + final HostVO host = mock(HostVO.class); + when(host.getId()).thenReturn(NETWORK_ID); + final NuageVspDeviceVO nuageVspDevice = mock(NuageVspDeviceVO.class); + when(nuageVspDevice.getHostId()).thenReturn(NETWORK_ID); + when(_nuageVspDao.listByPhysicalNetwork(NETWORK_ID)).thenReturn(Arrays.asList(new NuageVspDeviceVO[]{nuageVspDevice})); + when(_hostDao.findById(NETWORK_ID)).thenReturn(host); + when(_nuageVspManager.getNuageVspHost(NETWORK_ID)).thenReturn(host); + + when(_domainDao.findById(NETWORK_ID)).thenReturn(mock(DomainVO.class)); + + final Answer answer = mock(Answer.class); + when(answer.getResult()).thenReturn(true); + when(_agentManager.easySend(eq(NETWORK_ID), (Command)any())).thenReturn(answer); + assertTrue(_nuageVspElement.applyFWRules(network, new ArrayList<FirewallRule>())); + } + + @Test + public void testApplyNetworkACL() throws Exception { + final Network network = mock(Network.class); + when(network.getUuid()).thenReturn("aaaaaa"); + when(network.getVpcId()).thenReturn(null); + when(network.getNetworkOfferingId()).thenReturn(NETWORK_ID); + when(network.getPhysicalNetworkId()).thenReturn(NETWORK_ID); + when(network.getDomainId()).thenReturn(NETWORK_ID); + + final NetworkOfferingVO ntwkoffer = mock(NetworkOfferingVO.class); + when(ntwkoffer.getId()).thenReturn(NETWORK_ID); + when(ntwkoffer.isEgressDefaultPolicy()).thenReturn(true); + when(_networkOfferingDao.findById(NETWORK_ID)).thenReturn(ntwkoffer); + + final HostVO host = mock(HostVO.class); + when(host.getId()).thenReturn(NETWORK_ID); + final NuageVspDeviceVO nuageVspDevice = mock(NuageVspDeviceVO.class); + when(nuageVspDevice.getHostId()).thenReturn(NETWORK_ID); + when(_nuageVspDao.listByPhysicalNetwork(NETWORK_ID)).thenReturn(Arrays.asList(new NuageVspDeviceVO[]{nuageVspDevice})); + when(_hostDao.findById(NETWORK_ID)).thenReturn(host); + when(_nuageVspManager.getNuageVspHost(NETWORK_ID)).thenReturn(host); + + when(_domainDao.findById(NETWORK_ID)).thenReturn(mock(DomainVO.class)); + final Answer answer = mock(Answer.class); + when(answer.getResult()).thenReturn(true); + when(_agentManager.easySend(eq(NETWORK_ID), (Command)any())).thenReturn(answer); + assertTrue(_nuageVspElement.applyNetworkACLs(network, new ArrayList<NetworkACLItem>())); + } + + @Test + public void testShutdownVpc() throws Exception { + final Vpc vpc = mock(Vpc.class); + when(vpc.getUuid()).thenReturn("aaaaaa"); + when(vpc.getState()).thenReturn(Vpc.State.Inactive); + when(vpc.getDomainId()).thenReturn(NETWORK_ID); + when(vpc.getZoneId()).thenReturn(NETWORK_ID); + when(vpc.getId()).thenReturn(NETWORK_ID); + + final DomainVO dom = mock(DomainVO.class); + when(dom.getName()).thenReturn("domain"); + when(_domainDao.findById(NETWORK_ID)).thenReturn(dom); + final Account acc = mock(Account.class); + when(acc.getAccountName()).thenReturn("accountname"); + final ReservationContext context = mock(ReservationContext.class); + when(context.getDomain()).thenReturn(dom); + when(context.getAccount()).thenReturn(acc); + + PhysicalNetworkVO physNet = mock(PhysicalNetworkVO.class); + when(physNet.getIsolationMethods()).thenReturn(Lists.newArrayList("VSP")); + when(physNet.getId()).thenReturn(NETWORK_ID); + when(_physicalNetworkDao.listByZone(NETWORK_ID)).thenReturn(Lists.newArrayList(physNet)); + + final HostVO host = mock(HostVO.class); + when(host.getId()).thenReturn(NETWORK_ID); + final NuageVspDeviceVO nuageVspDevice = mock(NuageVspDeviceVO.class); + when(nuageVspDevice.getHostId()).thenReturn(NETWORK_ID); + when(_nuageVspDao.listByPhysicalNetwork(NETWORK_ID)).thenReturn(Lists.newArrayList(nuageVspDevice)); + when(_hostDao.findById(NETWORK_ID)).thenReturn(host); + when(_nuageVspManager.getNuageVspHost(NETWORK_ID)).thenReturn(host); + + DomainRouterVO domainRouter = mock(DomainRouterVO.class); + when(domainRouter.getUuid()).thenReturn("aaaaaa"); + when(_domainRouterDao.listByVpcId(NETWORK_ID)).thenReturn(Lists.newArrayList(domainRouter)); + + final Answer answer = mock(Answer.class); + when(answer.getResult()).thenReturn(true); + when(_agentManager.easySend(eq(NETWORK_ID), (Command)any())).thenReturn(answer); + assertTrue(_nuageVspElement.shutdownVpc(vpc, context)); + } +} diff --cc server/src/main/java/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java index 1822b51,0000000..80b1797 mode 100644,000000..100644 --- a/server/src/main/java/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java +++ b/server/src/main/java/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java @@@ -1,786 -1,0 +1,786 @@@ +// 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.router; + +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.Command.OnError; +import com.cloud.agent.api.NetworkUsageCommand; +import com.cloud.agent.api.PlugNicCommand; +import com.cloud.agent.api.SetupGuestNetworkCommand; +import com.cloud.agent.api.routing.AggregationControlCommand; +import com.cloud.agent.api.routing.AggregationControlCommand.Action; +import com.cloud.agent.manager.Commands; +import com.cloud.dc.DataCenter; +import com.cloud.deploy.DeployDestination; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.IpAddress; +import com.cloud.network.Network; +import com.cloud.network.Network.Provider; +import com.cloud.network.Network.Service; +import com.cloud.network.Networks.BroadcastDomainType; +import com.cloud.network.Networks.TrafficType; +import com.cloud.network.PublicIpAddress; +import com.cloud.network.RemoteAccessVpn; +import com.cloud.network.Site2SiteVpnConnection; +import com.cloud.network.VirtualRouterProvider; +import com.cloud.network.addr.PublicIp; +import com.cloud.network.dao.IPAddressVO; +import com.cloud.network.dao.RemoteAccessVpnVO; +import com.cloud.network.vpc.NetworkACLItemDao; +import com.cloud.network.vpc.NetworkACLItemVO; +import com.cloud.network.vpc.NetworkACLManager; +import com.cloud.network.vpc.PrivateGateway; +import com.cloud.network.vpc.PrivateIpAddress; +import com.cloud.network.vpc.PrivateIpVO; +import com.cloud.network.vpc.StaticRoute; +import com.cloud.network.vpc.StaticRouteProfile; +import com.cloud.network.vpc.Vpc; +import com.cloud.network.vpc.VpcGateway; +import com.cloud.network.vpc.VpcGatewayVO; +import com.cloud.network.vpc.VpcManager; +import com.cloud.network.vpc.VpcVO; +import com.cloud.network.vpc.dao.PrivateIpDao; +import com.cloud.network.vpc.dao.StaticRouteDao; +import com.cloud.network.vpc.dao.VpcGatewayDao; +import com.cloud.network.vpn.Site2SiteVpnManager; +import com.cloud.user.UserStatisticsVO; +import com.cloud.utils.Pair; +import com.cloud.utils.db.EntityManager; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.fsm.StateMachine2; +import com.cloud.utils.net.NetUtils; +import com.cloud.vm.DomainRouterVO; +import com.cloud.vm.Nic; +import com.cloud.vm.NicProfile; +import com.cloud.vm.NicVO; +import com.cloud.vm.ReservationContext; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachine.State; +import com.cloud.vm.VirtualMachineProfile; +import com.cloud.vm.VirtualMachineProfile.Param; +import com.cloud.vm.dao.VMInstanceDao; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.hypervisor.Hypervisor; +import com.cloud.hypervisor.HypervisorGuru; +import com.cloud.hypervisor.HypervisorGuruManager; + +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +@Component +public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplianceManagerImpl implements VpcVirtualNetworkApplianceManager { + private static final Logger s_logger = Logger.getLogger(VpcVirtualNetworkApplianceManagerImpl.class); + + @Inject + private NetworkACLManager _networkACLMgr; + @Inject + private VMInstanceDao _vmDao; + @Inject + private StaticRouteDao _staticRouteDao; + @Inject + private VpcManager _vpcMgr; + @Inject + private PrivateIpDao _privateIpDao; + @Inject + private Site2SiteVpnManager _s2sVpnMgr; + @Inject + private VpcGatewayDao _vpcGatewayDao; + @Inject + private NetworkACLItemDao _networkACLItemDao; + @Inject + private EntityManager _entityMgr; + @Inject + protected HypervisorGuruManager _hvGuruMgr; + + @Override + public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException { + _itMgr.registerGuru(VirtualMachine.Type.DomainRouter, this); + return super.configure(name, params); + } + + @Override + public boolean addVpcRouterToGuestNetwork(final VirtualRouter router, final Network network, final Map<VirtualMachineProfile.Param, Object> params) + throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + if (network.getTrafficType() != TrafficType.Guest) { + s_logger.warn("Network " + network + " is not of type " + TrafficType.Guest); + return false; + } + + // Add router to the Guest network + boolean result = true; + try { + + // 1) add nic to the router + _routerDao.addRouterToGuestNetwork(router, network); + + final NicProfile guestNic = _itMgr.addVmToNetwork(router, network, null); + // 2) setup guest network + if (guestNic != null) { + result = setupVpcGuestNetwork(network, router, true, guestNic); + } else { + s_logger.warn("Failed to add router " + router + " to guest network " + network); + result = false; + } + // 3) apply networking rules + if (result && params.get(Param.ReProgramGuestNetworks) != null && (Boolean) params.get(Param.ReProgramGuestNetworks) == true) { + sendNetworkRulesToRouter(router.getId(), network.getId()); + } + } catch (final Exception ex) { + s_logger.warn("Failed to add router " + router + " to network " + network + " due to ", ex); + result = false; + } finally { + if (!result) { + s_logger.debug("Removing the router " + router + " from network " + network + " as a part of cleanup"); + if (removeVpcRouterFromGuestNetwork(router, network)) { + s_logger.debug("Removed the router " + router + " from network " + network + " as a part of cleanup"); + } else { + s_logger.warn("Failed to remove the router " + router + " from network " + network + " as a part of cleanup"); + } + } else { + s_logger.debug("Succesfully added router " + router + " to guest network " + network); + } + } + + return result; + } + + @Override + public boolean removeVpcRouterFromGuestNetwork(final VirtualRouter router, final Network network) throws ConcurrentOperationException, + ResourceUnavailableException { + if (network.getTrafficType() != TrafficType.Guest) { + s_logger.warn("Network " + network + " is not of type " + TrafficType.Guest); + return false; + } + + boolean result = true; + try { + // Check if router is a part of the Guest network + if (!_networkModel.isVmPartOfNetwork(router.getId(), network.getId())) { + s_logger.debug("Router " + router + " is not a part of the Guest network " + network); + return result; + } + + result = setupVpcGuestNetwork(network, router, false, _networkModel.getNicProfile(router, network.getId(), null)); + if (!result) { + s_logger.warn("Failed to destroy guest network config " + network + " on router " + router); + return false; + } + + result = result && _itMgr.removeVmFromNetwork(router, network, null); + } finally { + if (result) { + _routerDao.removeRouterFromGuestNetwork(router.getId(), network.getId()); + } + } + + return result; + } + + protected boolean setupVpcGuestNetwork(final Network network, final VirtualRouter router, final boolean add, final NicProfile guestNic) throws ConcurrentOperationException, + ResourceUnavailableException { + + boolean result = true; + if (router.getState() == State.Running) { + final SetupGuestNetworkCommand setupCmd = _commandSetupHelper.createSetupGuestNetworkCommand((DomainRouterVO) router, add, guestNic); + + final Commands cmds = new Commands(Command.OnError.Stop); + cmds.addCommand("setupguestnetwork", setupCmd); + _nwHelper.sendCommandsToRouter(router, cmds); + + final Answer setupAnswer = cmds.getAnswer("setupguestnetwork"); + final String setup = add ? "set" : "destroy"; + if (!(setupAnswer != null && setupAnswer.getResult())) { + s_logger.warn("Unable to " + setup + " guest network on router " + router); + result = false; + } + return result; + } else if (router.getState() == State.Stopped || router.getState() == State.Stopping) { + s_logger.debug("Router " + router.getInstanceName() + " is in " + router.getState() + ", so not sending setup guest network command to the backend"); + return true; + } else { + s_logger.warn("Unable to setup guest network on virtual router " + router + " is not in the right state " + router.getState()); + throw new ResourceUnavailableException("Unable to setup guest network on the backend," + " virtual router " + router + " is not in the right state", DataCenter.class, + router.getDataCenterId()); + } + } + + @Override + public boolean finalizeVirtualMachineProfile(final VirtualMachineProfile profile, final DeployDestination dest, final ReservationContext context) { + final DomainRouterVO domainRouterVO = _routerDao.findById(profile.getId()); + + final Long vpcId = domainRouterVO.getVpcId(); + + if (vpcId != null) { + if (domainRouterVO.getState() == State.Starting || domainRouterVO.getState() == State.Running) { + String defaultDns1 = null; + String defaultDns2 = null; + // remove public and guest nics as we will plug them later + final Iterator<NicProfile> it = profile.getNics().iterator(); + while (it.hasNext()) { + final NicProfile nic = it.next(); + if (nic.getTrafficType() == TrafficType.Public || nic.getTrafficType() == TrafficType.Guest) { + // save dns information + if (nic.getTrafficType() == TrafficType.Public) { + defaultDns1 = nic.getIPv4Dns1(); + defaultDns2 = nic.getIPv4Dns2(); + } + s_logger.debug("Removing nic " + nic + " of type " + nic.getTrafficType() + " from the nics passed on vm start. " + "The nic will be plugged later"); + it.remove(); + } + } + + // add vpc cidr/dns/networkdomain to the boot load args + final StringBuilder buf = profile.getBootArgsBuilder(); + final Vpc vpc = _entityMgr.findById(Vpc.class, vpcId); + buf.append(" vpccidr=" + vpc.getCidr() + " domain=" + vpc.getNetworkDomain()); + + buf.append(" dns1=").append(defaultDns1); + if (defaultDns2 != null) { + buf.append(" dns2=").append(defaultDns2); + } + + VpcGatewayVO privateGatewayForVpc = _vpcGatewayDao.getPrivateGatewayForVpc(domainRouterVO.getVpcId()); + if (privateGatewayForVpc != null) { + String ip4Address = privateGatewayForVpc.getIp4Address(); + buf.append(" privategateway=").append(ip4Address); + s_logger.debug("Set privategateway field in cmd_line.json to " + ip4Address); + } else { + buf.append(" privategateway=None"); + } + } + } + + return super.finalizeVirtualMachineProfile(profile, dest, context); + } + + @Override + public boolean finalizeCommandsOnStart(final Commands cmds, final VirtualMachineProfile profile) { + final DomainRouterVO domainRouterVO = _routerDao.findById(profile.getId()); + + Map<String, String> details = new HashMap<String, String>(); + + if(profile.getHypervisorType() == Hypervisor.HypervisorType.VMware){ + HypervisorGuru hvGuru = _hvGuruMgr.getGuru(profile.getHypervisorType()); + VirtualMachineTO vmTO = hvGuru.implement(profile); + if(vmTO.getDetails() != null){ + details = vmTO.getDetails(); + } + } + + final boolean isVpc = domainRouterVO.getVpcId() != null; + if (!isVpc) { + return super.finalizeCommandsOnStart(cmds, profile); + } + + if (domainRouterVO.getState() == State.Starting || domainRouterVO.getState() == State.Running) { + // 1) FORM SSH CHECK COMMAND + final NicProfile controlNic = getControlNic(profile); + if (controlNic == null) { + s_logger.error("Control network doesn't exist for the router " + domainRouterVO); + return false; + } + + finalizeSshAndVersionAndNetworkUsageOnStart(cmds, profile, domainRouterVO, controlNic); + + // 2) FORM PLUG NIC COMMANDS + final List<Pair<Nic, Network>> guestNics = new ArrayList<Pair<Nic, Network>>(); + final List<Pair<Nic, Network>> publicNics = new ArrayList<Pair<Nic, Network>>(); + final Map<String, String> vlanMacAddress = new HashMap<String, String>(); + - final List<? extends Nic> routerNics = _nicDao.listByVmId(profile.getId()); ++ final List<? extends Nic> routerNics = _nicDao.listByVmIdOrderByDeviceId(profile.getId()); + for (final Nic routerNic : routerNics) { + final Network network = _networkModel.getNetwork(routerNic.getNetworkId()); + if (network.getTrafficType() == TrafficType.Guest) { + final Pair<Nic, Network> guestNic = new Pair<Nic, Network>(routerNic, network); + guestNics.add(guestNic); + } else if (network.getTrafficType() == TrafficType.Public) { + final Pair<Nic, Network> publicNic = new Pair<Nic, Network>(routerNic, network); + publicNics.add(publicNic); + final String vlanTag = BroadcastDomainType.getValue(routerNic.getBroadcastUri()); + vlanMacAddress.put(vlanTag, routerNic.getMacAddress()); + } + } + + final List<Command> usageCmds = new ArrayList<Command>(); + + // 3) PREPARE PLUG NIC COMMANDS + try { + // add VPC router to public networks + final List<PublicIp> sourceNat = new ArrayList<PublicIp>(1); + for (final Pair<Nic, Network> nicNtwk : publicNics) { + final Nic publicNic = nicNtwk.first(); + final Network publicNtwk = nicNtwk.second(); + final IPAddressVO userIp = _ipAddressDao.findByIpAndSourceNetworkId(publicNtwk.getId(), publicNic.getIPv4Address()); + + if (userIp.isSourceNat()) { + final PublicIp publicIp = PublicIp.createFromAddrAndVlan(userIp, _vlanDao.findById(userIp.getVlanId())); + sourceNat.add(publicIp); + + if (domainRouterVO.getPublicIpAddress() == null) { + final DomainRouterVO routerVO = _routerDao.findById(domainRouterVO.getId()); + routerVO.setPublicIpAddress(publicNic.getIPv4Address()); + routerVO.setPublicNetmask(publicNic.getIPv4Netmask()); + routerVO.setPublicMacAddress(publicNic.getMacAddress()); + _routerDao.update(routerVO.getId(), routerVO); + } + } + final PlugNicCommand plugNicCmd = new PlugNicCommand(_nwHelper.getNicTO(domainRouterVO, publicNic.getNetworkId(), publicNic.getBroadcastUri().toString()), + domainRouterVO.getInstanceName(), domainRouterVO.getType(), details); + cmds.addCommand(plugNicCmd); + final VpcVO vpc = _vpcDao.findById(domainRouterVO.getVpcId()); + final NetworkUsageCommand netUsageCmd = new NetworkUsageCommand(domainRouterVO.getPrivateIpAddress(), domainRouterVO.getInstanceName(), true, publicNic.getIPv4Address(), vpc.getCidr()); + usageCmds.add(netUsageCmd); + UserStatisticsVO stats = _userStatsDao.findBy(domainRouterVO.getAccountId(), domainRouterVO.getDataCenterId(), publicNtwk.getId(), publicNic.getIPv4Address(), domainRouterVO.getId(), + domainRouterVO.getType().toString()); + if (stats == null) { + stats = new UserStatisticsVO(domainRouterVO.getAccountId(), domainRouterVO.getDataCenterId(), publicNic.getIPv4Address(), domainRouterVO.getId(), domainRouterVO.getType().toString(), + publicNtwk.getId()); + _userStatsDao.persist(stats); + } + } + + // create ip assoc for source nat + if (!sourceNat.isEmpty()) { + _commandSetupHelper.createVpcAssociatePublicIPCommands(domainRouterVO, sourceNat, cmds, vlanMacAddress); + } + + // add VPC router to guest networks + for (final Pair<Nic, Network> nicNtwk : guestNics) { + final Nic guestNic = nicNtwk.first(); + // plug guest nic + final PlugNicCommand plugNicCmd = new PlugNicCommand(_nwHelper.getNicTO(domainRouterVO, guestNic.getNetworkId(), null), domainRouterVO.getInstanceName(), domainRouterVO.getType(), details); + cmds.addCommand(plugNicCmd); + if (!_networkModel.isPrivateGateway(guestNic.getNetworkId())) { + // set guest network + final VirtualMachine vm = _vmDao.findById(domainRouterVO.getId()); + final NicProfile nicProfile = _networkModel.getNicProfile(vm, guestNic.getNetworkId(), null); + final SetupGuestNetworkCommand setupCmd = _commandSetupHelper.createSetupGuestNetworkCommand(domainRouterVO, true, nicProfile); + cmds.addCommand(setupCmd); + } else { + + // set private network + final PrivateIpVO ipVO = _privateIpDao.findByIpAndSourceNetworkId(guestNic.getNetworkId(), guestNic.getIPv4Address()); + final Network network = _networkDao.findById(guestNic.getNetworkId()); + BroadcastDomainType.getValue(network.getBroadcastUri()); + final String netmask = NetUtils.getCidrNetmask(network.getCidr()); + final PrivateIpAddress ip = new PrivateIpAddress(ipVO, network.getBroadcastUri().toString(), network.getGateway(), netmask, guestNic.getMacAddress()); + + final List<PrivateIpAddress> privateIps = new ArrayList<PrivateIpAddress>(1); + privateIps.add(ip); + _commandSetupHelper.createVpcAssociatePrivateIPCommands(domainRouterVO, privateIps, cmds, true); + + final Long privateGwAclId = _vpcGatewayDao.getNetworkAclIdForPrivateIp(ipVO.getVpcId(), ipVO.getNetworkId(), ipVO.getIpAddress()); + + if (privateGwAclId != null) { + // set network acl on private gateway + final List<NetworkACLItemVO> networkACLs = _networkACLItemDao.listByACL(privateGwAclId); + s_logger.debug("Found " + networkACLs.size() + " network ACLs to apply as a part of VPC VR " + domainRouterVO + " start for private gateway ip = " + + ipVO.getIpAddress()); + + _commandSetupHelper.createNetworkACLsCommands(networkACLs, domainRouterVO, cmds, ipVO.getNetworkId(), true); + } + } + } + } catch (final Exception ex) { + s_logger.warn("Failed to add router " + domainRouterVO + " to network due to exception ", ex); + return false; + } + + // 4) RE-APPLY ALL STATIC ROUTE RULES + final List<? extends StaticRoute> routes = _staticRouteDao.listByVpcId(domainRouterVO.getVpcId()); + final List<StaticRouteProfile> staticRouteProfiles = new ArrayList<StaticRouteProfile>(routes.size()); + final Map<Long, VpcGateway> gatewayMap = new HashMap<Long, VpcGateway>(); + for (final StaticRoute route : routes) { + VpcGateway gateway = gatewayMap.get(route.getVpcGatewayId()); + if (gateway == null) { + gateway = _entityMgr.findById(VpcGateway.class, route.getVpcGatewayId()); + gatewayMap.put(gateway.getId(), gateway); + } + staticRouteProfiles.add(new StaticRouteProfile(route, gateway)); + } + + s_logger.debug("Found " + staticRouteProfiles.size() + " static routes to apply as a part of vpc route " + domainRouterVO + " start"); + if (!staticRouteProfiles.isEmpty()) { + _commandSetupHelper.createStaticRouteCommands(staticRouteProfiles, domainRouterVO, cmds); + } + + // 5) RE-APPLY ALL REMOTE ACCESS VPNs + final RemoteAccessVpnVO vpn = _vpnDao.findByAccountAndVpc(domainRouterVO.getAccountId(), domainRouterVO.getVpcId()); + if (vpn != null) { + _commandSetupHelper.createApplyVpnCommands(true, vpn, domainRouterVO, cmds); + } + + // 6) REPROGRAM GUEST NETWORK + boolean reprogramGuestNtwks = true; + if (profile.getParameter(Param.ReProgramGuestNetworks) != null && (Boolean) profile.getParameter(Param.ReProgramGuestNetworks) == false) { + reprogramGuestNtwks = false; + } + + final VirtualRouterProvider vrProvider = _vrProviderDao.findById(domainRouterVO.getElementId()); + if (vrProvider == null) { + throw new CloudRuntimeException("Cannot find related virtual router provider of router: " + domainRouterVO.getHostName()); + } + final Provider provider = Network.Provider.getProvider(vrProvider.getType().toString()); + if (provider == null) { + throw new CloudRuntimeException("Cannot find related provider of virtual router provider: " + vrProvider.getType().toString()); + } + + for (final Pair<Nic, Network> nicNtwk : guestNics) { + final Nic guestNic = nicNtwk.first(); + final AggregationControlCommand startCmd = new AggregationControlCommand(Action.Start, domainRouterVO.getInstanceName(), controlNic.getIPv4Address(), _routerControlHelper.getRouterIpInNetwork( + guestNic.getNetworkId(), domainRouterVO.getId())); + cmds.addCommand(startCmd); + if (reprogramGuestNtwks) { + finalizeIpAssocForNetwork(cmds, domainRouterVO, provider, guestNic.getNetworkId(), vlanMacAddress); + finalizeNetworkRulesForNetwork(cmds, domainRouterVO, provider, guestNic.getNetworkId()); + } + + finalizeUserDataAndDhcpOnStart(cmds, domainRouterVO, provider, guestNic.getNetworkId()); + final AggregationControlCommand finishCmd = new AggregationControlCommand(Action.Finish, domainRouterVO.getInstanceName(), controlNic.getIPv4Address(), _routerControlHelper.getRouterIpInNetwork( + guestNic.getNetworkId(), domainRouterVO.getId())); + cmds.addCommand(finishCmd); + } + + // Add network usage commands + cmds.addCommands(usageCmds); + } + return true; + } + + @Override + protected void finalizeNetworkRulesForNetwork(final Commands cmds, final DomainRouterVO domainRouterVO, final Provider provider, final Long guestNetworkId) { + + super.finalizeNetworkRulesForNetwork(cmds, domainRouterVO, provider, guestNetworkId); + + if (domainRouterVO.getVpcId() != null) { + + if (domainRouterVO.getState() == State.Starting || domainRouterVO.getState() == State.Running) { + if (_networkModel.isProviderSupportServiceInNetwork(guestNetworkId, Service.NetworkACL, Provider.VPCVirtualRouter)) { + final List<NetworkACLItemVO> networkACLs = _networkACLMgr.listNetworkACLItems(guestNetworkId); + if (networkACLs != null && !networkACLs.isEmpty()) { + s_logger.debug("Found " + networkACLs.size() + " network ACLs to apply as a part of VPC VR " + domainRouterVO + " start for guest network id=" + guestNetworkId); + _commandSetupHelper.createNetworkACLsCommands(networkACLs, domainRouterVO, cmds, guestNetworkId, false); + } + } + } + } + } + + protected boolean sendNetworkRulesToRouter(final long routerId, final long networkId) throws ResourceUnavailableException { + final DomainRouterVO router = _routerDao.findById(routerId); + final Commands cmds = new Commands(OnError.Continue); + + final VirtualRouterProvider vrProvider = _vrProviderDao.findById(router.getElementId()); + if (vrProvider == null) { + throw new CloudRuntimeException("Cannot find related virtual router provider of router: " + router.getHostName()); + } + final Provider provider = Network.Provider.getProvider(vrProvider.getType().toString()); + if (provider == null) { + throw new CloudRuntimeException("Cannot find related provider of virtual router provider: " + vrProvider.getType().toString()); + } + + finalizeNetworkRulesForNetwork(cmds, router, provider, networkId); + return _nwHelper.sendCommandsToRouter(router, cmds); + } + + /** + * @param router + * @param add + * @param privateNic + * @return + * @throws ResourceUnavailableException + */ + protected boolean setupVpcPrivateNetwork(final VirtualRouter router, final boolean add, final NicProfile privateNic) throws ResourceUnavailableException { + + if (router.getState() == State.Running) { + final PrivateIpVO ipVO = _privateIpDao.findByIpAndSourceNetworkId(privateNic.getNetworkId(), privateNic.getIPv4Address()); + final Network network = _networkDao.findById(privateNic.getNetworkId()); + final String netmask = NetUtils.getCidrNetmask(network.getCidr()); + final PrivateIpAddress ip = new PrivateIpAddress(ipVO, network.getBroadcastUri().toString(), network.getGateway(), netmask, privateNic.getMacAddress()); + + final List<PrivateIpAddress> privateIps = new ArrayList<PrivateIpAddress>(1); + privateIps.add(ip); + final Commands cmds = new Commands(Command.OnError.Stop); + _commandSetupHelper.createVpcAssociatePrivateIPCommands(router, privateIps, cmds, add); + + try { + if (_nwHelper.sendCommandsToRouter(router, cmds)) { + s_logger.debug("Successfully applied ip association for ip " + ip + " in vpc network " + network); + return true; + } else { + s_logger.warn("Failed to associate ip address " + ip + " in vpc network " + network); + return false; + } + } catch (final Exception ex) { + s_logger.warn("Failed to send " + (add ? "add " : "delete ") + " private network " + network + " commands to rotuer "); + return false; + } + } else if (router.getState() == State.Stopped || router.getState() == State.Stopping) { + s_logger.debug("Router " + router.getInstanceName() + " is in " + router.getState() + ", so not sending setup private network command to the backend"); + } else { + s_logger.warn("Unable to setup private gateway, virtual router " + router + " is not in the right state " + router.getState()); + + throw new ResourceUnavailableException("Unable to setup Private gateway on the backend," + " virtual router " + router + " is not in the right state", + DataCenter.class, router.getDataCenterId()); + } + return true; + } + + @Override + public boolean destroyPrivateGateway(final PrivateGateway gateway, final VirtualRouter router) throws ConcurrentOperationException, ResourceUnavailableException { + boolean result = true; + + if (!_networkModel.isVmPartOfNetwork(router.getId(), gateway.getNetworkId())) { + s_logger.debug("Router doesn't have nic for gateway " + gateway + " so no need to removed it"); + return result; + } + + final Network privateNetwork = _networkModel.getNetwork(gateway.getNetworkId()); + final NicProfile nicProfile = _networkModel.getNicProfile(router, privateNetwork.getId(), null); + + s_logger.debug("Releasing private ip for gateway " + gateway + " from " + router); + result = setupVpcPrivateNetwork(router, false, nicProfile); + if (!result) { + s_logger.warn("Failed to release private ip for gateway " + gateway + " on router " + router); + return false; + } + + // revoke network acl on the private gateway. + if (!_networkACLMgr.revokeACLItemsForPrivateGw(gateway)) { + s_logger.debug("Failed to delete network acl items on " + gateway + " from router " + router); + return false; + } + + s_logger.debug("Removing router " + router + " from private network " + privateNetwork + " as a part of delete private gateway"); + result = result && _itMgr.removeVmFromNetwork(router, privateNetwork, null); + s_logger.debug("Private gateawy " + gateway + " is removed from router " + router); + return result; + } + + @Override + protected void finalizeIpAssocForNetwork(final Commands cmds, final VirtualRouter domainRouterVO, final Provider provider, final Long guestNetworkId, + final Map<String, String> vlanMacAddress) { + + if (domainRouterVO.getVpcId() == null) { + super.finalizeIpAssocForNetwork(cmds, domainRouterVO, provider, guestNetworkId, vlanMacAddress); + return; + } + + if (domainRouterVO.getState() == State.Starting || domainRouterVO.getState() == State.Running) { + final ArrayList<? extends PublicIpAddress> publicIps = getPublicIpsToApply(domainRouterVO, provider, guestNetworkId, IpAddress.State.Releasing); + + if (publicIps != null && !publicIps.isEmpty()) { + s_logger.debug("Found " + publicIps.size() + " ip(s) to apply as a part of domR " + domainRouterVO + " start."); + // Re-apply public ip addresses - should come before PF/LB/VPN + _commandSetupHelper.createVpcAssociatePublicIPCommands(domainRouterVO, publicIps, cmds, vlanMacAddress); + } + } + } + + @Override + public boolean startSite2SiteVpn(final Site2SiteVpnConnection conn, final VirtualRouter router) throws ResourceUnavailableException { + if (router.getState() != State.Running) { + s_logger.warn("Unable to apply site-to-site VPN configuration, virtual router is not in the right state " + router.getState()); + throw new ResourceUnavailableException("Unable to apply site 2 site VPN configuration," + " virtual router is not in the right state", DataCenter.class, + router.getDataCenterId()); + } + + return applySite2SiteVpn(true, router, conn); + } + + @Override + public boolean stopSite2SiteVpn(final Site2SiteVpnConnection conn, final VirtualRouter router) throws ResourceUnavailableException { + if (router.getState() != State.Running) { + s_logger.warn("Unable to apply site-to-site VPN configuration, virtual router is not in the right state " + router.getState()); + throw new ResourceUnavailableException("Unable to apply site 2 site VPN configuration," + " virtual router is not in the right state", DataCenter.class, + router.getDataCenterId()); + } + + return applySite2SiteVpn(false, router, conn); + } + + protected boolean applySite2SiteVpn(final boolean isCreate, final VirtualRouter router, final Site2SiteVpnConnection conn) throws ResourceUnavailableException { + final Commands cmds = new Commands(Command.OnError.Continue); + _commandSetupHelper.createSite2SiteVpnCfgCommands(conn, isCreate, router, cmds); + return _nwHelper.sendCommandsToRouter(router, cmds); + } + + protected Pair<Map<String, PublicIpAddress>, Map<String, PublicIpAddress>> getNicsToChangeOnRouter(final List<? extends PublicIpAddress> publicIps, final VirtualRouter router) { + // 1) check which nics need to be plugged/unplugged and plug/unplug them + + final Map<String, PublicIpAddress> nicsToPlug = new HashMap<String, PublicIpAddress>(); + final Map<String, PublicIpAddress> nicsToUnplug = new HashMap<String, PublicIpAddress>(); + + // find out nics to unplug + for (final PublicIpAddress ip : publicIps) { + final long publicNtwkId = ip.getNetworkId(); + + // if ip is not associated to any network, and there are no firewall + // rules, release it on the backend + if (!_vpcMgr.isIpAllocatedToVpc(ip)) { + ip.setState(IpAddress.State.Releasing); + } + + if (ip.getState() == IpAddress.State.Releasing) { + final Nic nic = _nicDao.findByIp4AddressAndNetworkIdAndInstanceId(publicNtwkId, router.getId(), ip.getAddress().addr()); + if (nic != null) { + nicsToUnplug.put(ip.getVlanTag(), ip); + s_logger.debug("Need to unplug the nic for ip=" + ip + "; vlan=" + ip.getVlanTag() + " in public network id =" + publicNtwkId); + } + } + } + + // find out nics to plug + for (final PublicIpAddress ip : publicIps) { + final URI broadcastUri = BroadcastDomainType.Vlan.toUri(ip.getVlanTag()); + final long publicNtwkId = ip.getNetworkId(); + + // if ip is not associated to any network, and there are no firewall + // rules, release it on the backend + if (!_vpcMgr.isIpAllocatedToVpc(ip)) { + ip.setState(IpAddress.State.Releasing); + } + + if (ip.getState() == IpAddress.State.Allocated || ip.getState() == IpAddress.State.Allocating) { + // nic has to be plugged only when there are no nics for this + // vlan tag exist on VR + final Nic nic = _nicDao.findByNetworkIdInstanceIdAndBroadcastUri(publicNtwkId, router.getId(), broadcastUri.toString()); + + if (nic == null && nicsToPlug.get(ip.getVlanTag()) == null) { + nicsToPlug.put(ip.getVlanTag(), ip); + s_logger.debug("Need to plug the nic for ip=" + ip + "; vlan=" + ip.getVlanTag() + " in public network id =" + publicNtwkId); + } else { + final PublicIpAddress nicToUnplug = nicsToUnplug.get(ip.getVlanTag()); + if (nicToUnplug != null) { + final NicVO nicVO = _nicDao.findByIp4AddressAndNetworkIdAndInstanceId(publicNtwkId, router.getId(), nicToUnplug.getAddress().addr()); + nicVO.setIPv4Address(ip.getAddress().addr()); + _nicDao.update(nicVO.getId(), nicVO); + s_logger.debug("Updated the nic " + nicVO + " with the new ip address " + ip.getAddress().addr()); + nicsToUnplug.remove(ip.getVlanTag()); + } + } + } + } + + final Pair<Map<String, PublicIpAddress>, Map<String, PublicIpAddress>> nicsToChange = new Pair<Map<String, PublicIpAddress>, Map<String, PublicIpAddress>>(nicsToPlug, + nicsToUnplug); + return nicsToChange; + } + + @Override + public void finalizeStop(final VirtualMachineProfile profile, final Answer answer) { + super.finalizeStop(profile, answer); + // Mark VPN connections as Disconnected + final DomainRouterVO router = _routerDao.findById(profile.getId()); + final Long vpcId = router.getVpcId(); + if (vpcId != null) { + _s2sVpnMgr.markDisconnectVpnConnByVpc(vpcId); + } + } + + @Override + public List<DomainRouterVO> getVpcRouters(final long vpcId) { + 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) { + s_logger.warn("Unable to apply remote access VPN configuration, virtual router is not in the right state " + router.getState()); + throw new ResourceUnavailableException("Unable to apply remote access VPN configuration," + " virtual router is not in the right state", DataCenter.class, + router.getDataCenterId()); + } + + final Commands cmds = new Commands(Command.OnError.Stop); + _commandSetupHelper.createApplyVpnCommands(true, vpn, router, cmds); + + try { + _agentMgr.send(router.getHostId(), cmds); + } catch (final OperationTimedoutException e) { + s_logger.debug("Failed to start remote access VPN: ", e); + throw new AgentUnavailableException("Unable to send commands to virtual router ", router.getHostId(), e); + } + Answer answer = cmds.getAnswer("users"); + if (answer == null || !answer.getResult()) { + String errorMessage = (answer == null) ? "null answer object" : answer.getDetails(); + s_logger.error("Unable to start vpn: unable add users to vpn in zone " + router.getDataCenterId() + " for account " + vpn.getAccountId() + " on domR: " + + router.getInstanceName() + " due to " + errorMessage); + throw new ResourceUnavailableException("Unable to start vpn: Unable to add users to vpn in zone " + router.getDataCenterId() + " for account " + vpn.getAccountId() + + " on domR: " + router.getInstanceName() + " due to " + errorMessage, DataCenter.class, router.getDataCenterId()); + } + answer = cmds.getAnswer("startVpn"); + if (answer == null || !answer.getResult()) { + String errorMessage = (answer == null) ? "null answer object" : answer.getDetails(); + s_logger.error("Unable to start vpn in zone " + router.getDataCenterId() + " for account " + vpn.getAccountId() + " on domR: " + router.getInstanceName() + " due to " + + errorMessage); + throw new ResourceUnavailableException("Unable to start vpn in zone " + router.getDataCenterId() + " for account " + vpn.getAccountId() + " on domR: " + + router.getInstanceName() + " due to " + errorMessage, DataCenter.class, router.getDataCenterId()); + } + + return true; + } + + @Override + public boolean stopRemoteAccessVpn(final RemoteAccessVpn vpn, final VirtualRouter router) throws ResourceUnavailableException { + boolean result = true; + + if (router.getState() == State.Running) { + final Commands cmds = new Commands(Command.OnError.Continue); + _commandSetupHelper.createApplyVpnCommands(false, vpn, router, cmds); + result = result && _nwHelper.sendCommandsToRouter(router, cmds); + } else if (router.getState() == State.Stopped) { + s_logger.debug("Router " + router + " is in Stopped state, not sending deleteRemoteAccessVpn command to it"); + } else { + s_logger.warn("Failed to stop remote access VPN: domR " + router + " is not in right state " + router.getState()); + throw new ResourceUnavailableException("Failed to stop remote access VPN: domR is not in right state " + router.getState(), DataCenter.class, + router.getDataCenterId()); + } + return true; + } + + @Override + public boolean postStateTransitionEvent(final StateMachine2.Transition<State, VirtualMachine.Event> transition, final VirtualMachine vo, final boolean status, final Object opaque) { + // Without this VirtualNetworkApplianceManagerImpl.postStateTransitionEvent() gets called twice as part of listeners - + // once from VpcVirtualNetworkApplianceManagerImpl and once from VirtualNetworkApplianceManagerImpl itself + return true; + } +} diff --cc utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java index fe2e329,262e928..bb8ba12 --- a/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java +++ b/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java @@@ -680,23 -680,10 +680,25 @@@ public class NetUtilsTest } @Test + public void testIsIpv4() { + assertTrue(NetUtils.isIpv4("192.168.1.1")); + assertFalse(NetUtils.isIpv4("2a01:4f8:130:2192::2")); + } + + @Test(expected = IllegalArgumentException.class) + public void testIsIpv4ExpectException() { + NetUtils.isIpv4("test"); + } + + @Test(expected = IllegalArgumentException.class) + public void testIsIpv4ExpectException2() { + NetUtils.isIpv4("2001:db8:300::/64"); + } + public void testAllIpsOfDefaultNic() { final String defaultHostIp = NetUtils.getDefaultHostIp(); - assertTrue(NetUtils.getAllDefaultNicIps().stream().anyMatch(defaultHostIp::contains)); + if (defaultHostIp != null) { + assertTrue(NetUtils.getAllDefaultNicIps().stream().anyMatch(defaultHostIp::contains)); + } } }