// // 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.util; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import javax.inject.Inject; import net.nuage.vsp.acs.client.api.model.NetworkRelatedVsdIds; import net.nuage.vsp.acs.client.api.model.VspAclRule; import net.nuage.vsp.acs.client.api.model.VspAddressRange; import net.nuage.vsp.acs.client.api.model.VspDhcpDomainOption; import net.nuage.vsp.acs.client.api.model.VspDhcpVMOption; import net.nuage.vsp.acs.client.api.model.VspDomain; import net.nuage.vsp.acs.client.api.model.VspDomainCleanUp; import net.nuage.vsp.acs.client.api.model.VspNetwork; import net.nuage.vsp.acs.client.api.model.VspNic; import net.nuage.vsp.acs.client.api.model.VspStaticNat; import net.nuage.vsp.acs.client.api.model.VspVm; import net.nuage.vsp.acs.client.common.model.Pair; import org.apache.commons.collections.MapUtils; import org.apache.log4j.Logger; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.apache.cloudstack.resourcedetail.dao.VpcDetailsDao; import com.cloud.dc.Vlan; import com.cloud.dc.VlanVO; import com.cloud.dc.dao.VlanDao; import com.cloud.dc.dao.VlanDetailsDao; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.network.Network; import com.cloud.network.NetworkModel; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkDetailsDao; import com.cloud.network.dao.NetworkVO; import com.cloud.network.manager.NuageVspManager; import com.cloud.network.rules.FirewallRule; import com.cloud.network.vpc.NetworkACLItem; import com.cloud.network.vpc.VpcVO; import com.cloud.network.vpc.dao.VpcDao; 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.user.AccountVO; import com.cloud.user.dao.AccountDao; import com.cloud.utils.net.NetUtils; import com.cloud.vm.NicProfile; import com.cloud.vm.NicVO; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.NicSecondaryIpDao; import com.cloud.vm.dao.NicSecondaryIpVO; import com.cloud.vm.dao.VMInstanceDao; public class NuageVspEntityBuilder { private static final Logger s_logger = Logger.getLogger(NuageVspEntityBuilder.class); @Inject NetworkDao _networkDao; @Inject VpcDao _vpcDao; @Inject DomainDao _domainDao; @Inject AccountDao _accountDao; @Inject NetworkOfferingDao _networkOfferingDao; @Inject NetworkOfferingServiceMapDao _networkOfferingServiceMapDao; @Inject NetworkModel _networkModel; @Inject VlanDao _vlanDao; @Inject VlanDetailsDao _vlanDetailsDao; @Inject IPAddressDao _ipAddressDao; @Inject NetworkDetailsDao _networkDetailsDao; @Inject VpcDetailsDao _vpcDetailsDao; @Inject VMInstanceDao _vmInstanceDao; @Inject NuageVspManager _nuageVspManager; @Inject NicDao _nicDao; @Inject NicSecondaryIpDao _nicSecondaryIpDao; @Inject NetworkOfferingServiceMapDao _ntwkOfferingSrvcDao; public VspDomain buildVspDomain(Domain domain) { return new VspDomain.Builder() .uuid(domain.getUuid()) .name(domain.getName()) .path(domain.getPath()) .build(); } public VspDomainCleanUp buildVspDomainCleanUp(Domain domain) { VspDomainCleanUp.Builder vspDomainCleanUpBuilder = new VspDomainCleanUp.Builder().uuid(domain.getUuid()); Map> sharedNetworkUuids = Maps.newHashMap(); List allSharedNetworks = _networkDao.listByGuestType(Network.GuestType.Shared); for (NetworkVO sharedNetwork : allSharedNetworks) { if (_networkModel.isNetworkAvailableInDomain(sharedNetwork.getId(), domain.getId())) { String preConfiguredDomainTemplateName = _nuageVspManager.getPreConfiguredDomainTemplateName(sharedNetwork); if (!sharedNetworkUuids.containsKey(preConfiguredDomainTemplateName)) { sharedNetworkUuids.put(preConfiguredDomainTemplateName, Lists.newArrayList()); } sharedNetworkUuids.get(preConfiguredDomainTemplateName).add(sharedNetwork.getUuid()); } } vspDomainCleanUpBuilder.sharedNetworkUuids(sharedNetworkUuids); return vspDomainCleanUpBuilder.build(); } public VspNetwork buildVspNetwork(Network network) { return buildVspNetwork(network.getDomainId(), network, null); } public VspNetwork buildVspNetwork(Network network, String vsdSubnetId) { return buildVspNetwork(network.getDomainId(), network, vsdSubnetId); } public VspNetwork buildVspNetwork(long domainId, Network network) { return buildVspNetwork(domainId, network, null); } public VspNetwork buildVspNetwork(long domainId, Network network, String vsdSubnetId) { VspNetwork.Builder vspNetworkBuilder = new VspNetwork.Builder() .id(network.getId()) .uuid(network.getUuid()) .name(network.getName()) .cidr(network.getCidr()) .gateway(network.getGateway()); DomainVO domain = _domainDao.findById(domainId); VspDomain vspDomain = buildVspDomain(domain); vspNetworkBuilder.domain(vspDomain); AccountVO account = _accountDao.findById(network.getAccountId()); if (account != null) { vspNetworkBuilder.accountUuid(account.getUuid()).accountName(account.getAccountName()); } NetworkOfferingVO networkOffering = _networkOfferingDao.findById(network.getNetworkOfferingId()); vspNetworkBuilder.egressDefaultPolicy(networkOffering.getEgressDefaultPolicy()) .publicAccess(networkOffering.getSupportsPublicAccess()); Map networkDetails = _networkDetailsDao.listDetailsKeyPairs(network.getId(), false); final NetworkRelatedVsdIds.Builder relatedVsdIdsBuilder = new NetworkRelatedVsdIds.Builder(); if (MapUtils.isNotEmpty(networkDetails)) { relatedVsdIdsBuilder.vsdSubnetId(networkDetails.get(NuageVspManager.NETWORK_METADATA_VSD_SUBNET_ID)) .withVsdManaged("true".equals(networkDetails.get(NuageVspManager.NETWORK_METADATA_VSD_MANAGED))); } else if (vsdSubnetId != null) { relatedVsdIdsBuilder.vsdSubnetId(vsdSubnetId) .withVsdManaged("true".equals(networkDetails.get(NuageVspManager.NETWORK_METADATA_VSD_MANAGED))); } if (network.getVpcId() != null) { long vpcId = network.getVpcId(); VpcVO vpc = _vpcDao.findById(vpcId); vspNetworkBuilder.vpcUuid(vpc.getUuid()) .vpcName(vpc.getName()) .networkType(VspNetwork.NetworkType.Vpc); Map vpcDetails = _vpcDetailsDao.listDetailsKeyPairs(vpcId, false); applyDomainAndZoneId(relatedVsdIdsBuilder, vpcDetails); } else { applyDomainAndZoneId(relatedVsdIdsBuilder, networkDetails); if (networkOffering.getGuestType() == Network.GuestType.Shared) { List vlans = _vlanDao.listVlansByNetworkIdIncludingRemoved(network.getId()); List vspAddressRanges = vlans.stream() .map(vlan -> new VspAddressRange.Builder().gateway(vlan.getVlanGateway()).netmask(vlan.getVlanNetmask()).build()) .collect(Collectors.toList()); vspNetworkBuilder.networkType(VspNetwork.NetworkType.Shared) .addressRanges(vspAddressRanges); } else if (_networkOfferingServiceMapDao.areServicesSupportedByNetworkOffering(network.getNetworkOfferingId(), Network.Service.SourceNat) || _networkOfferingServiceMapDao.areServicesSupportedByNetworkOffering(network.getNetworkOfferingId(), Network.Service.StaticNat)) { vspNetworkBuilder.networkType(VspNetwork.NetworkType.L3); } else { vspNetworkBuilder.networkType(VspNetwork.NetworkType.L2); } } NetworkRelatedVsdIds networkRelatedVsdIds = relatedVsdIdsBuilder.build(); vspNetworkBuilder.networkRelatedVsdIds(networkRelatedVsdIds); boolean firewallServiceSupported = _networkModel.areServicesSupportedByNetworkOffering(network.getNetworkOfferingId(), Network.Service.Firewall); vspNetworkBuilder.firewallServiceSupported(firewallServiceSupported); String preConfiguredDomainTemplateName = _nuageVspManager.getPreConfiguredDomainTemplateName(network); vspNetworkBuilder.domainTemplateName(preConfiguredDomainTemplateName); if (usesVirtualRouter(networkOffering.getId())) { String virtualRouterIp = getVirtualRouterIP(network); vspNetworkBuilder.virtualRouterIp(virtualRouterIp); } return vspNetworkBuilder.build(); } private void applyDomainAndZoneId(NetworkRelatedVsdIds.Builder relatedVsdIdsBuilder, Map details) { if (MapUtils.isNotEmpty(details)) { relatedVsdIdsBuilder .vsdDomainId(details.get(NuageVspManager.NETWORK_METADATA_VSD_DOMAIN_ID)) .vsdZoneId(details.get(NuageVspManager.NETWORK_METADATA_VSD_ZONE_ID)); } } public boolean usesVirtualRouter(long networkOfferingId) { return _networkOfferingServiceMapDao.isProviderForNetworkOffering(networkOfferingId, Network.Provider.VirtualRouter) || _networkOfferingServiceMapDao.isProviderForNetworkOffering(networkOfferingId, Network.Provider.VPCVirtualRouter); } public VspNetwork updateVspNetworkByPublicIp(VspNetwork vspNetwork, Network network, String publicIp) { List vlans = _vlanDao.listVlansByNetworkId(network.getId()); final long ip = NetUtils.ip2Long(publicIp); VlanVO matchingVlan = vlans.stream() .filter(vlan -> isVlanContainingIp(vlan, ip)) .findFirst() .get(); boolean underlayEnabled = NuageVspUtil.isUnderlayEnabledForVlan(_vlanDetailsDao, matchingVlan); return new VspNetwork.Builder().fromObject(vspNetwork) .gateway(matchingVlan.getVlanGateway()) .cidr(NetUtils.getCidrFromGatewayAndNetmask(matchingVlan.getVlanGateway(), matchingVlan.getVlanNetmask())) .vlanUnderlay(underlayEnabled) .build(); } private boolean isVlanContainingIp(Vlan vlan, long ip) { Pair ipAddressRange = NuageVspUtil.getIpAddressRange(vlan); long startIp = NetUtils.ip2Long(ipAddressRange.getLeft()); long endIp = NetUtils.ip2Long(ipAddressRange.getRight()); return startIp <= ip && ip <= endIp; } private String getVirtualRouterIP(Network network) { return network.getBroadcastUri() != null ? network.getBroadcastUri().getPath().substring(1) : null; } public VspVm buildVspVm(VirtualMachine vm, Network network) { VspVm.Builder vspVmBuilder = new VspVm.Builder() .uuid(vm.getUuid()) .name(vm.getInstanceName()) .state(getEnumValue(vm.getState(), VspVm.State.Unknown)); boolean isDomainRouter = vm.getType().equals(VirtualMachine.Type.DomainRouter); vspVmBuilder.domainRouter(isDomainRouter); if (network.getBroadcastUri() != null) { String domainRouterIp = network.getBroadcastUri().getPath().substring(1); vspVmBuilder.domainRouterIp(domainRouterIp); } return vspVmBuilder.build(); } public VspNic buildVspNic(String nicUuid, NicProfile nicProfile) { return buildVspNic(nicUuid, nicProfile.getMacAddress(), nicProfile.getIPv4Address(), nicProfile.getNetworkId(), null); } public VspNic buildVspNic(NicVO nic) { return buildVspNic(nic.getUuid(), nic.getMacAddress(), nic.getIPv4Address(), nic.getNetworkId(), null); } public VspNic buildVspNic(NicVO nic, NicSecondaryIpVO nicSecondaryIp) { return buildVspNic(nic.getUuid(), nic.getMacAddress(), nic.getIPv4Address(), nic.getNetworkId(), nicSecondaryIp); } private VspNic buildVspNic(String uuid, String macAddress, String ip, long networkId, NicSecondaryIpVO nicSecondaryIp) { VspNic.Builder vspNicBuilder = new VspNic.Builder() .uuid(uuid) .macAddress(macAddress) .useStaticIp(true) .ip(ip); if (nicSecondaryIp != null) { vspNicBuilder.secondaryIpUuid(nicSecondaryIp.getUuid()).secondaryIpAddress(nicSecondaryIp.getIp4Address()); } Network network = _networkDao.findById(networkId); NetworkOffering networkOffering = _networkOfferingDao.findById(network.getNetworkOfferingId()); return vspNicBuilder.build(); } public VspStaticNat buildVspStaticNat(Boolean forRevoke, IPAddressVO staticNatIp, VlanVO staticNatVlan, VspNic vspNic) { VspStaticNat.Builder vspStaticNatBuilder = new VspStaticNat.Builder() .ipUuid(staticNatIp.getUuid()) .ipAddress(staticNatIp.getAddress().addr()) .revoke(forRevoke) .oneToOneNat(staticNatIp.isOneToOneNat()) .state(getEnumValue(staticNatIp.getState(), VspStaticNat.State.class)) .vlanUuid(staticNatVlan.getUuid()) .vlanGateway(staticNatVlan.getVlanGateway()) .vlanNetmask(staticNatVlan.getVlanNetmask()) .vlanUnderlay(NuageVspUtil.isUnderlayEnabledForVlan(_vlanDetailsDao, staticNatVlan)); if (staticNatIp.getVmIp() != null) { vspStaticNatBuilder.destinationIp(staticNatIp.getVmIp() + "/32"); } if (vspNic != null) { vspStaticNatBuilder.nic(vspNic); } return vspStaticNatBuilder.build(); } public VspStaticNat buildVspStaticNat(Boolean forRevoke, IPAddressVO staticNatIp, VlanVO staticNatVlan, NicVO nic) { NicSecondaryIpVO nicSecondaryIp = null; if (nic == null && staticNatIp.getAssociatedWithVmId() != null && staticNatIp.getVmIp() != null) { nicSecondaryIp = _nicSecondaryIpDao.findByIp4AddressAndInstanceId(staticNatIp.getAssociatedWithVmId(), staticNatIp.getVmIp()); if (nicSecondaryIp != null) { nic = _nicDao.findById(nicSecondaryIp.getNicId()); } } VspNic vspNic = (nic != null) ? buildVspNic(nic, nicSecondaryIp) : null; return buildVspStaticNat(forRevoke, staticNatIp, staticNatVlan, vspNic); } public VspAclRule buildVspAclRule(FirewallRule firewallRule, Network network) { return buildVspAclRule(firewallRule, network, null); } public VspAclRule buildVspAclRule(FirewallRule firewallRule, Network network, IPAddressVO staticNat) { VspAclRule.Builder vspAclRuleBuilder = new VspAclRule.Builder() .uuid(firewallRule.getUuid()) .protocol(firewallRule.getProtocol()) .startPort(firewallRule.getSourcePortStart()) .endPort(firewallRule.getSourcePortEnd()) .sourceCidrList(firewallRule.getSourceCidrList()) .priority(-1) .type(VspAclRule.ACLType.Firewall) .state(getEnumValue(firewallRule.getState(), VspAclRule.ACLState.class)) .trafficType(getEnumValue(firewallRule.getTrafficType(), VspAclRule.ACLTrafficType.class)); NetworkOfferingVO networkOffering = _networkOfferingDao.findById(network.getNetworkOfferingId()); if (firewallRule.getTrafficType() == FirewallRule.TrafficType.Egress && networkOffering.getEgressDefaultPolicy()) { vspAclRuleBuilder.deny(); } else { vspAclRuleBuilder.allow(); } if (staticNat == null && firewallRule.getSourceIpAddressId() != null) { IPAddressVO staticNatIp = _ipAddressDao.findById(firewallRule.getSourceIpAddressId()); if (staticNatIp != null) { VlanVO staticNatVlan = _vlanDao.findById(staticNatIp.getVlanId()); NicVO nic = _nicDao.findByIp4AddressAndNetworkId(staticNatIp.getVmIp(), staticNatIp.getAssociatedWithNetworkId()); vspAclRuleBuilder.staticNat(buildVspStaticNat(null, staticNatIp, staticNatVlan, nic)); } } return vspAclRuleBuilder.build(); } public VspAclRule buildVspAclRule(NetworkACLItem networkAcl) { return new VspAclRule.Builder() .uuid(networkAcl.getUuid()) .protocol(networkAcl.getProtocol()) .startPort(networkAcl.getSourcePortStart()) .endPort(networkAcl.getSourcePortEnd()) .sourceIpAddress(null) .sourceCidrList(networkAcl.getSourceCidrList()) .priority(networkAcl.getNumber()) .type(VspAclRule.ACLType.NetworkACL) .state(getEnumValue(networkAcl.getState(), VspAclRule.ACLState.class)) .trafficType(getEnumValue(networkAcl.getTrafficType(), VspAclRule.ACLTrafficType.class)) .action(getEnumValue(networkAcl.getAction(), VspAclRule.ACLAction.class)) .build(); } /** Build VspDhcpVMOption to put on the VM interface */ public VspDhcpVMOption buildVmDhcpOption (NicVO userNic, boolean defaultHasDns, boolean networkHasDns) { VMInstanceVO userVm = _vmInstanceDao.findById(userNic.getInstanceId()); VspDhcpVMOption.Builder vspDhcpVMOptionBuilder = new VspDhcpVMOption.Builder() .nicUuid(userNic.getUuid()) .defaultHasDns(defaultHasDns) .hostname(userVm.getHostName()) .networkHasDns(networkHasDns) .isDefaultInterface(userNic.isDefaultNic()) .domainRouter(VirtualMachine.Type.DomainRouter.equals(userNic.getVmType())); return vspDhcpVMOptionBuilder.build(); } /** Build VspDhcpVMOption to put on the subnet */ public VspDhcpDomainOption buildNetworkDhcpOption(Network network, NetworkOffering offering) { List dnsProvider = _ntwkOfferingSrvcDao.listProvidersForServiceForNetworkOffering(offering.getId(), Network.Service.Dns); boolean isVrDnsProvider = dnsProvider.contains("VirtualRouter") || dnsProvider.contains("VpcVirtualRouter"); VspDhcpDomainOption.Builder vspDhcpDomainBuilder = new VspDhcpDomainOption.Builder() .dnsServers(_nuageVspManager.getDnsDetails(network.getDataCenterId())) .vrIsDnsProvider(isVrDnsProvider); if (isVrDnsProvider) { vspDhcpDomainBuilder.networkDomain(network.getVpcId() != null ? _vpcDao.findById(network.getVpcId()).getNetworkDomain() : network.getNetworkDomain()); } return vspDhcpDomainBuilder.build(); } private > E getEnumValue(Enum cloudstackValue, Class target) { try { return Enum.valueOf(target, cloudstackValue.name()); } catch (IllegalArgumentException e) { return null; } } private > E getEnumValue(Enum cloudstackValue, E defaultValue) { try { return Enum.valueOf(defaultValue.getDeclaringClass(), cloudstackValue.name()); } catch (IllegalArgumentException e) { return defaultValue; } } }