You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ra...@apache.org on 2018/11/07 12:00:03 UTC
[cloudstack] 01/01: Forward merge Fix DirectNetworkGuru canHandle
for lowercase isolation methods
This is an automated email from the ASF dual-hosted git repository.
rafael pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit 077e692dbb4abef95ab62f77c0e62e5aa19b32e5
Merge: e175e93 af0c1e4
Author: Rafael Weingärtner <ra...@gmail.com>
AuthorDate: Wed Nov 7 09:56:05 2018 -0200
Forward merge Fix DirectNetworkGuru canHandle for lowercase isolation methods
forward merge of #3010 -- Fix DirectNetworkGuru canHandle checks for lowercase isolation methods
.../com/cloud/network/guru/DirectNetworkGuru.java | 13 +++++-
.../cloud/network/guru/DirectNetworkGuruTest.java | 53 ++++++++++++++++++++++
2 files changed, 64 insertions(+), 2 deletions(-)
diff --cc server/src/main/java/com/cloud/network/guru/DirectNetworkGuru.java
index 6c473c5,0000000..ee880e6
mode 100644,000000..100644
--- a/server/src/main/java/com/cloud/network/guru/DirectNetworkGuru.java
+++ b/server/src/main/java/com/cloud/network/guru/DirectNetworkGuru.java
@@@ -1,413 -1,0 +1,422 @@@
+// 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.guru;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
+import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
++import org.apache.commons.collections.CollectionUtils;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.DataCenter;
+import com.cloud.dc.DataCenter.NetworkType;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.dc.dao.VlanDao;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.deploy.DeploymentPlan;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientAddressCapacityException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InsufficientVirtualNetworkCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.network.dao.PhysicalNetworkDao;
+import com.cloud.network.dao.PhysicalNetworkVO;
+import com.cloud.network.IpAddressManager;
+import com.cloud.network.Ipv6AddressManager;
+import com.cloud.network.Network;
+import com.cloud.network.Network.GuestType;
+import com.cloud.network.Network.Service;
+import com.cloud.network.Network.State;
+import com.cloud.network.NetworkModel;
+import com.cloud.network.NetworkProfile;
+import com.cloud.network.NetworkService;
+import com.cloud.network.Networks.BroadcastDomainType;
+import com.cloud.network.Networks.Mode;
+import com.cloud.network.Networks.TrafficType;
+import com.cloud.network.PhysicalNetwork;
+import com.cloud.network.PhysicalNetwork.IsolationMethod;
+import com.cloud.network.dao.IPAddressDao;
+import com.cloud.network.dao.IPAddressVO;
+import com.cloud.network.dao.NetworkVO;
+import com.cloud.network.dao.UserIpv6AddressDao;
+import com.cloud.offering.NetworkOffering;
+import com.cloud.offerings.dao.NetworkOfferingDao;
+import com.cloud.user.Account;
+import com.cloud.utils.component.AdapterBase;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.TransactionCallbackNoReturn;
+import com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn;
+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.Nic;
+import com.cloud.vm.Nic.ReservationStrategy;
+import com.cloud.vm.NicProfile;
+import com.cloud.vm.NicVO;
+import com.cloud.vm.ReservationContext;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachineProfile;
+import com.cloud.vm.dao.NicDao;
+import com.cloud.vm.dao.NicSecondaryIpDao;
+import com.cloud.vm.dao.NicSecondaryIpVO;
+
+
+public class DirectNetworkGuru extends AdapterBase implements NetworkGuru {
+ private static final Logger s_logger = Logger.getLogger(DirectNetworkGuru.class);
+
+ @Inject
+ DataCenterDao _dcDao;
+ @Inject
+ VlanDao _vlanDao;
+ @Inject
+ NetworkModel _networkModel;
+ @Inject
+ NetworkOrchestrationService _networkMgr;
+ @Inject
+ IPAddressDao _ipAddressDao;
+ @Inject
+ NetworkOfferingDao _networkOfferingDao;
+ @Inject
+ UserIpv6AddressDao _ipv6Dao;
+ @Inject
+ Ipv6AddressManager _ipv6Mgr;
+ @Inject
+ NicSecondaryIpDao _nicSecondaryIpDao;
+ @Inject
+ NicDao _nicDao;
+ @Inject
+ IpAddressManager _ipAddrMgr;
+ @Inject
+ NetworkOfferingServiceMapDao _ntwkOfferingSrvcDao;
+ @Inject
+ PhysicalNetworkDao _physicalNetworkDao;
+ @Inject
+ private NetworkService networkService;
+ @Inject
+ private NicSecondaryIpDao nicSecondaryIpDao;
+
+ private static final TrafficType[] TrafficTypes = {TrafficType.Guest};
+ protected IsolationMethod[] _isolationMethods;
+
+ @Override
+ public boolean isMyTrafficType(TrafficType type) {
+ for (TrafficType t : TrafficTypes) {
+ if (t == type) {
+ return true;
+ }
+ }
+ return false;
+ }
+
++ /**
++ * Return true if the physical network isolation method contains the expected isolation method for this guru
++ */
+ protected boolean isMyIsolationMethod(PhysicalNetwork physicalNetwork) {
+ for (IsolationMethod m : _isolationMethods) {
- if (physicalNetwork.getIsolationMethods().contains(m.toString())) {
- return true;
++ List<String> isolationMethods = physicalNetwork.getIsolationMethods();
++ if (CollectionUtils.isNotEmpty(isolationMethods)) {
++ for (String method : isolationMethods) {
++ if (method.equalsIgnoreCase(m.toString())) {
++ return true;
++ }
++ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public TrafficType[] getSupportedTrafficType() {
+ return TrafficTypes;
+ }
+
+ /**
+ * True for Advanced zones, with VXLAN isolation method and Security Groups enabled
+ */
+ private boolean isMyIsolationMethodVxlanWithSecurityGroups(NetworkOffering offering, DataCenter dc, PhysicalNetwork physnet) {
+ return dc.getNetworkType().equals(NetworkType.Advanced) &&
+ _networkModel.areServicesSupportedByNetworkOffering(offering.getId(), Service.SecurityGroup) &&
+ physnet.getIsolationMethods().contains("VXLAN");
+ }
+
+ protected boolean canHandle(NetworkOffering offering, DataCenter dc, PhysicalNetwork physnet) {
+ // this guru handles only Guest networks in Advance zone with source nat service disabled
+ boolean vxlanWithSecurityGroups = isMyIsolationMethodVxlanWithSecurityGroups(offering, dc, physnet);
+ if (dc.getNetworkType() == NetworkType.Advanced && isMyTrafficType(offering.getTrafficType()) &&
+ (isMyIsolationMethod(physnet) || vxlanWithSecurityGroups) && offering.getGuestType() == GuestType.Shared
+ && !_ntwkOfferingSrvcDao.isProviderForNetworkOffering(offering.getId(), Network.Provider.NuageVsp)
+ && !_ntwkOfferingSrvcDao.isProviderForNetworkOffering(offering.getId(), Network.Provider.NiciraNvp)) {
+ return true;
+ } else {
+ s_logger.trace("We only take care of Guest networks of type " + GuestType.Shared);
+ return false;
+ }
+ }
+
+ @Override
+ public Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner) {
+ DataCenter dc = _dcDao.findById(plan.getDataCenterId());
+ PhysicalNetworkVO physnet = _physicalNetworkDao.findById(plan.getPhysicalNetworkId());
+
+ if (!canHandle(offering, dc, physnet)) {
+ return null;
+ }
+
+ State state = State.Allocated;
+ if (dc.getNetworkType() == NetworkType.Basic) {
+ state = State.Setup;
+ }
+
+ NetworkVO config =
+ new NetworkVO(offering.getTrafficType(), Mode.Dhcp, BroadcastDomainType.Vlan, offering.getId(), state, plan.getDataCenterId(),
+ plan.getPhysicalNetworkId(), offering.isRedundantRouter());
+
+ if (userSpecified != null) {
+ if ((userSpecified.getCidr() == null && userSpecified.getGateway() != null) || (userSpecified.getCidr() != null && userSpecified.getGateway() == null)) {
+ throw new InvalidParameterValueException("cidr and gateway must be specified together.");
+ }
+
+ if ((userSpecified.getIp6Cidr() == null && userSpecified.getIp6Gateway() != null) ||
+ (userSpecified.getIp6Cidr() != null && userSpecified.getIp6Gateway() == null)) {
+ throw new InvalidParameterValueException("cidrv6 and gatewayv6 must be specified together.");
+ }
+
+ if (userSpecified.getCidr() != null) {
+ config.setCidr(userSpecified.getCidr());
+ config.setGateway(userSpecified.getGateway());
+ }
+
+ if (userSpecified.getIp6Cidr() != null) {
+ config.setIp6Cidr(userSpecified.getIp6Cidr());
+ config.setIp6Gateway(userSpecified.getIp6Gateway());
+ }
+
+ if (userSpecified.getBroadcastUri() != null) {
+ config.setBroadcastUri(userSpecified.getBroadcastUri());
+ config.setState(State.Setup);
+ }
+
+ if (userSpecified.getBroadcastDomainType() != null) {
+ config.setBroadcastDomainType(userSpecified.getBroadcastDomainType());
+ }
+ }
+
+ boolean isSecurityGroupEnabled = _networkModel.areServicesSupportedByNetworkOffering(offering.getId(), Service.SecurityGroup);
+ if (isSecurityGroupEnabled) {
+ if (userSpecified.getIp6Cidr() != null) {
+ throw new InvalidParameterValueException("Didn't support security group with IPv6");
+ }
+ config.setName("SecurityGroupEnabledNetwork");
+ config.setDisplayText("SecurityGroupEnabledNetwork");
+ }
+
+ return config;
+ }
+
+ protected DirectNetworkGuru() {
+ super();
+ _isolationMethods = new IsolationMethod[] { new IsolationMethod("VLAN") };
+ }
+
+ @Override
+ public void updateNicProfile(NicProfile profile, Network network) {
+ DataCenter dc = _dcDao.findById(network.getDataCenterId());
+ if (profile != null) {
+ profile.setIPv4Dns1(dc.getDns1());
+ profile.setIPv4Dns2(dc.getDns2());
+ profile.setIPv6Dns1(dc.getIp6Dns1());
+ profile.setIPv6Dns2(dc.getIp6Dns2());
+ }
+ }
+
+ @Override
+ public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapacityException,
+ InsufficientAddressCapacityException, ConcurrentOperationException {
+
+ DataCenter dc = _dcDao.findById(network.getDataCenterId());
+
+ if (nic == null) {
+ nic = new NicProfile(ReservationStrategy.Create, null, null, null, null);
+ } else if (nic.getIPv4Address() == null && nic.getIPv6Address() == null) {
+ nic.setReservationStrategy(ReservationStrategy.Start);
+ } else {
+ nic.setReservationStrategy(ReservationStrategy.Create);
+ }
+
+ allocateDirectIp(nic, network, vm, dc, nic.getRequestedIPv4(), nic.getRequestedIPv6());
+ nic.setReservationStrategy(ReservationStrategy.Create);
+
+ if (nic.getMacAddress() == null) {
+ nic.setMacAddress(_networkModel.getNextAvailableMacAddressInNetwork(network.getId()));
+ if (nic.getMacAddress() == null) {
+ throw new InsufficientAddressCapacityException("Unable to allocate more mac addresses", Network.class, network.getId());
+ }
+ }
+
+ return nic;
+ }
+
+ @Override
+ public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context)
+ throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException, ConcurrentOperationException {
+ if (nic.getIPv4Address() == null && nic.getIPv6Address() == null) {
+ allocateDirectIp(nic, network, vm, dest.getDataCenter(), null, null);
+ nic.setReservationStrategy(ReservationStrategy.Create);
+ }
+ }
+
+ @DB
+ protected void allocateDirectIp(final NicProfile nic, final Network network, final VirtualMachineProfile vm, final DataCenter dc, final String requestedIp4Addr,
+ final String requestedIp6Addr) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException {
+
+ try {
+ Transaction.execute(new TransactionCallbackWithExceptionNoReturn<InsufficientCapacityException>() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) throws InsufficientVirtualNetworkCapacityException,
+ InsufficientAddressCapacityException {
+ if (_networkModel.isSharedNetworkWithoutServices(network.getId())) {
+ _ipAddrMgr.allocateNicValues(nic, dc, vm, network, requestedIp4Addr, requestedIp6Addr);
+ } else {
+ _ipAddrMgr.allocateDirectIp(nic, dc, vm, network, requestedIp4Addr, requestedIp6Addr);
+ //save the placeholder nic if the vm is the Virtual router
+ if (vm.getType() == VirtualMachine.Type.DomainRouter) {
+ Nic placeholderNic = _networkModel.getPlaceholderNicForRouter(network, null);
+ if (placeholderNic == null) {
+ s_logger.debug("Saving placeholder nic with ip4 address " + nic.getIPv4Address() + " and ipv6 address " + nic.getIPv6Address() +
+ " for the network " + network);
+ _networkMgr.savePlaceholderNic(network, nic.getIPv4Address(), nic.getIPv6Address(), VirtualMachine.Type.DomainRouter);
+ }
+ }
+ }
+ }
+ });
+ } catch (InsufficientCapacityException e) {
+ ExceptionUtil.rethrow(e, InsufficientVirtualNetworkCapacityException.class);
+ ExceptionUtil.rethrow(e, InsufficientAddressCapacityException.class);
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) {
+ return true;
+ }
+
+ @Override
+ public Network implement(Network network, NetworkOffering offering, DeployDestination destination, ReservationContext context)
+ throws InsufficientVirtualNetworkCapacityException {
+ return network;
+ }
+
+ @Override
+ @DB
+ public void deallocate(final Network network, final NicProfile nic, VirtualMachineProfile vm) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Deallocate network: networkId: " + nic.getNetworkId() + ", ip: " + nic.getIPv4Address());
+ }
+
+ if (nic.getIPv4Address() != null) {
+ final IPAddressVO ip = _ipAddressDao.findByIpAndSourceNetworkId(nic.getNetworkId(), nic.getIPv4Address());
+ if (ip != null) {
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // if the ip address a part of placeholder, don't release it
+ Nic placeholderNic = _networkModel.getPlaceholderNicForRouter(network, null);
+ if (placeholderNic != null && placeholderNic.getIPv4Address().equalsIgnoreCase(ip.getAddress().addr())) {
+ s_logger.debug("Not releasing direct ip " + ip.getId() + " yet as its ip is saved in the placeholder");
+ } else {
+ _ipAddrMgr.markIpAsUnavailable(ip.getId());
+ _ipAddressDao.unassignIpAddress(ip.getId());
+ }
+
+ //unassign nic secondary ip address
+ s_logger.debug("remove nic " + nic.getId() + " secondary ip ");
+ List<String> nicSecIps = null;
+ nicSecIps = _nicSecondaryIpDao.getSecondaryIpAddressesForNic(nic.getId());
+ for (String secIp : nicSecIps) {
+ if (NetUtils.isValidIp4(secIp)) {
+ IPAddressVO pubIp = _ipAddressDao.findByIpAndSourceNetworkId(nic.getNetworkId(), secIp);
+ _ipAddrMgr.markIpAsUnavailable(pubIp.getId());
+ _ipAddressDao.unassignIpAddress(pubIp.getId());
+ } else {
+ NicSecondaryIpVO nicSecIp = nicSecondaryIpDao.findByIp6AddressAndNetworkId(secIp, nic.getNetworkId());
+ if (nicSecIp != null) {
+ networkService.releaseSecondaryIpFromNic(nicSecIp.getId());
+ }
+ }
+ }
+ }
+ });
+ }
+ }
+
+ if (nic.getIPv6Address() != null) {
+ _ipv6Mgr.revokeDirectIpv6Address(nic.getNetworkId(), nic.getIPv6Address());
+ }
+ nic.deallocate();
+ }
+
+ @Override
+ public void shutdown(NetworkProfile network, NetworkOffering offering) {
+ }
+
+ @Override
+ @DB
+ public boolean trash(Network network, NetworkOffering offering) {
+ //Have to remove all placeholder nics
+ try {
+ long id = network.getId();
+ final List<NicVO> nics = _nicDao.listPlaceholderNicsByNetworkId(id);
+ if (nics != null) {
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ for (Nic nic : nics) {
+ if (nic.getIPv4Address() != null) {
+ s_logger.debug("Releasing ip " + nic.getIPv4Address() + " of placeholder nic " + nic);
+ IPAddressVO ip = _ipAddressDao.findByIpAndSourceNetworkId(nic.getNetworkId(), nic.getIPv4Address());
+ if (ip != null) {
+ _ipAddrMgr.markIpAsUnavailable(ip.getId());
+ _ipAddressDao.unassignIpAddress(ip.getId());
+ s_logger.debug("Removing placeholder nic " + nic);
+ _nicDao.remove(nic.getId());
+ }
+ }
+ }
+ }
+ });
+ }
+ return true;
+ }catch (Exception e) {
+ s_logger.error("trash. Exception:" + e.getMessage());
+ throw new CloudRuntimeException("trash. Exception:" + e.getMessage(),e);
+ }
+ }
+
+ @Override
+ public void updateNetworkProfile(NetworkProfile networkProfile) {
+ DataCenter dc = _dcDao.findById(networkProfile.getDataCenterId());
+ networkProfile.setDns1(dc.getDns1());
+ networkProfile.setDns2(dc.getDns2());
+ }
+}