/* * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping; import static com.google.common.base.Preconditions.checkNotNull; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.UUID; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory; import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkClient; import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkService; import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.group.NeutronSecurityGroupAware; import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils; import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NeutronMapperIidFactory; import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NeutronUtils; import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils; import org.opendaylight.groupbasedpolicy.util.DataStoreHelper; import org.opendaylight.groupbasedpolicy.util.IidFactory; import org.opendaylight.neutron.spi.NeutronNetwork; import org.opendaylight.neutron.spi.NeutronNetwork_Segment; import org.opendaylight.neutron.spi.NeutronSecurityGroup; import org.opendaylight.neutron.spi.NeutronSecurityRule; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.provider.physical.networks.as.l2.flood.domains.ProviderPhysicalNetworkAsL2FloodDomain; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.provider.physical.networks.as.l2.flood.domains.ProviderPhysicalNetworkAsL2FloodDomainBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.network.mappings.NetworkMapping; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.network.mappings.NetworkMappingBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomainBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomain; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomainBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3ContextBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.ExternalImplicitGroup; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.ExternalImplicitGroupBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.ext.rev150712.NetworkL3Extension; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeBase; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeFlat; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeGre; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeVlan; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeVxlan; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.neutron.networks.network.Segments; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Optional; import com.google.common.base.Strings; import com.google.common.collect.ImmutableBiMap; import com.google.common.collect.ImmutableList; public class NeutronNetworkAware implements MappingProcessor { private static final Logger LOG = LoggerFactory.getLogger(NeutronNetworkAware.class); private final DataBroker dataProvider; private final Set tenantsWithRouterAndNetworkSeviceEntities = new HashSet<>(); private final NeutronSecurityGroupAware secGrpAware; private final NeutronNetworkDao networkDao; public NeutronNetworkAware(DataBroker dataProvider, NeutronSecurityGroupAware secGrpAware, NeutronNetworkDao networkDao) { this.dataProvider = checkNotNull(dataProvider); this.secGrpAware = checkNotNull(secGrpAware); this.networkDao = checkNotNull(networkDao); } private static final ImmutableBiMap,String> NETWORK_MAP = new ImmutableBiMap.Builder,String>() .put(NetworkTypeFlat.class,"flat") .put(NetworkTypeGre.class,"gre") .put(NetworkTypeVlan.class,"vlan") .put(NetworkTypeVxlan.class,"vxlan") .build(); @Override public NeutronNetwork convertToNeutron(Network network) { NeutronNetwork result = new NeutronNetwork(); result.initDefaults(); result.setAdminStateUp(network.isAdminStateUp()); result.setNetworkName(network.getName()); result.setShared(network.isShared()); result.setStatus(network.getStatus()); result.setTenantID(network.getTenantId()); result.setID(network.getUuid().getValue()); NetworkL3Extension l3Extension = network.getAugmentation(NetworkL3Extension.class); result.setRouterExternal(l3Extension.isExternal()); NetworkProviderExtension providerExtension = network.getAugmentation(NetworkProviderExtension.class); result.setProviderPhysicalNetwork(providerExtension.getPhysicalNetwork()); result.setProviderSegmentationID(providerExtension.getSegmentationId()); result.setProviderNetworkType(NETWORK_MAP.get(providerExtension.getNetworkType())); List segments = new ArrayList(); if (providerExtension.getSegments() != null) { for (Segments segment: providerExtension.getSegments()) { NeutronNetwork_Segment neutronSegment = new NeutronNetwork_Segment(); neutronSegment.setProviderPhysicalNetwork(segment.getPhysicalNetwork()); neutronSegment.setProviderSegmentationID(segment.getSegmentationId()); neutronSegment.setProviderNetworkType(NETWORK_MAP.get(segment.getNetworkType())); segments.add(neutronSegment); } } result.setSegments(segments); return result; } @Override public int canCreate(NeutronNetwork network) { LOG.trace("canCreate network - {}", network); // nothing to consider return StatusCode.OK; } @Override public void created(NeutronNetwork network) { LOG.trace("created network - {}", network); ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction(); L2FloodDomainId l2FdId = new L2FloodDomainId(network.getID()); TenantId tenantId = new TenantId(Utils.normalizeUuid(network.getTenantID())); Name name = null; if (network.getNetworkName() != null) { try { name = new Name(network.getNetworkName()); } catch (Exception e) { name = null; LOG.info("Name of Neutron Network '{}' is ignored.", network.getNetworkName()); LOG.debug("Name exception", e); } } L3ContextId l3ContextId = new L3ContextId(UUID.randomUUID().toString()); L3Context l3Context = new L3ContextBuilder().setId(l3ContextId).setName(name).build(); rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l3ContextIid(tenantId, l3ContextId), l3Context, true); L2BridgeDomainId l2BdId = new L2BridgeDomainId(UUID.randomUUID().toString()); L2BridgeDomain l2Bd = new L2BridgeDomainBuilder().setId(l2BdId).setParent(l3ContextId).setName(name).build(); rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd, true); L2FloodDomain l2Fd = new L2FloodDomainBuilder().setId(l2FdId).setParent(l2BdId).setName(name).build(); rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2FloodDomainIid(tenantId, l2FdId), l2Fd, true); NetworkMapping networkMapping = new NetworkMappingBuilder().setNetworkId(l2FdId) .setL2BridgeDomainId(l2BdId) .setL3ContextId(l3ContextId) .build(); rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronMapperIidFactory.networkMappingIid(l2FdId), networkMapping, true); if (!tenantsWithRouterAndNetworkSeviceEntities.contains(tenantId)) { tenantsWithRouterAndNetworkSeviceEntities.add(tenantId); NetworkService.writeNetworkServiceEntitiesToTenant(tenantId, rwTx); NetworkService.writeDhcpClauseWithConsProvEic(tenantId, null, rwTx); NetworkService.writeDnsClauseWithConsProvEic(tenantId, null, rwTx); NetworkService.writeMgmtClauseWithConsProvEic(tenantId, null, rwTx); NetworkClient.writeNetworkClientEntitiesToTenant(tenantId, rwTx); NetworkClient.writeConsumerNamedSelector(tenantId, NetworkService.DHCP_CONTRACT_CONSUMER_SELECTOR, rwTx); NetworkClient.writeConsumerNamedSelector(tenantId, NetworkService.DNS_CONTRACT_CONSUMER_SELECTOR, rwTx); NetworkClient.writeConsumerNamedSelector(tenantId, NetworkService.MGMT_CONTRACT_CONSUMER_SELECTOR, rwTx); } networkDao.addNetwork(network); if (network.getRouterExternal() != null && network.getRouterExternal() == true) { addEigEpgExternalWithContracts(tenantId, rwTx); } if (!Strings.isNullOrEmpty(network.getProviderPhysicalNetwork())) { String segmentationId = network.getProviderSegmentationID(); addProviderPhysicalNetworkMapping(tenantId, l2FdId, segmentationId, rwTx); } DataStoreHelper.submitToDs(rwTx); } private void addEigEpgExternalWithContracts(TenantId tenantId, ReadWriteTransaction rwTx) { Uuid tenantUuid = new Uuid(tenantId.getValue()); NeutronSecurityRule inIpv4 = new NeutronSecurityRule(); inIpv4.setID("19b85ad2-bdfc-11e5-9912-ba0be0483c18"); inIpv4.setSecurityRuleDirection(NeutronUtils.INGRESS); inIpv4.setSecurityRuleEthertype(NeutronUtils.IPv4); inIpv4.setSecurityRuleGroupID(MappingUtils.EPG_EXTERNAL_ID.getValue()); inIpv4.setTenantID(tenantUuid); NeutronSecurityRule outIpv4 = new NeutronSecurityRule(); outIpv4.setID("19b85eba-bdfc-11e5-9912-ba0be0483c18"); outIpv4.setSecurityRuleDirection(NeutronUtils.EGRESS); outIpv4.setSecurityRuleEthertype(NeutronUtils.IPv4); outIpv4.setSecurityRuleGroupID(MappingUtils.EPG_EXTERNAL_ID.getValue()); outIpv4.setTenantID(tenantUuid); NeutronSecurityRule inIpv6 = new NeutronSecurityRule(); inIpv6.setID("19b86180-bdfc-11e5-9912-ba0be0483c18"); inIpv6.setSecurityRuleDirection(NeutronUtils.INGRESS); inIpv6.setSecurityRuleEthertype(NeutronUtils.IPv6); inIpv6.setSecurityRuleGroupID(MappingUtils.EPG_EXTERNAL_ID.getValue()); inIpv6.setTenantID(tenantUuid); NeutronSecurityRule outIpv6 = new NeutronSecurityRule(); outIpv6.setID("19b86270-bdfc-11e5-9912-ba0be0483c18"); outIpv6.setSecurityRuleDirection(NeutronUtils.EGRESS); outIpv6.setSecurityRuleEthertype(NeutronUtils.IPv6); outIpv6.setSecurityRuleGroupID(MappingUtils.EPG_EXTERNAL_ID.getValue()); outIpv6.setTenantID(tenantUuid); NeutronSecurityGroup externalSecGrp = new NeutronSecurityGroup(); externalSecGrp.setID(MappingUtils.EPG_EXTERNAL_ID.getValue()); externalSecGrp.setSecurityGroupName("EXTERNAL_group"); externalSecGrp.setTenantID(tenantUuid); externalSecGrp.setSecurityRules(ImmutableList.of(inIpv4, outIpv4, inIpv6, outIpv6)); boolean isAddedNeutronSecurityGroup = secGrpAware.addNeutronSecurityGroup(externalSecGrp, rwTx); if (!isAddedNeutronSecurityGroup) { LOG.error("Problem with adding External Neutron Security Group representing External Implicit Group. {}", externalSecGrp); return; } ExternalImplicitGroup eig = new ExternalImplicitGroupBuilder().setId(MappingUtils.EPG_EXTERNAL_ID).build(); rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.externalImplicitGroupIid(tenantId, eig.getId()), eig, true); } private void addProviderPhysicalNetworkMapping(TenantId tenantId, L2FloodDomainId l2FdId, String segmentationId, WriteTransaction wTx) { ProviderPhysicalNetworkAsL2FloodDomain provNetAsL2Fd = new ProviderPhysicalNetworkAsL2FloodDomainBuilder() .setTenantId(tenantId).setL2FloodDomainId(l2FdId).setSegmentationId(segmentationId).build(); wTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.providerPhysicalNetworkAsL2FloodDomainIid(tenantId, l2FdId), provNetAsL2Fd); } @Override public int canUpdate(NeutronNetwork delta, NeutronNetwork original) { LOG.trace("canUpdate network - delta: {} original: {}", delta, original); // nothing to consider return StatusCode.OK; } @Override public void updated(NeutronNetwork network) { LOG.trace("updated network - {}", network); // TODO we could update just name } @Override public int canDelete(NeutronNetwork network) { LOG.trace("canDelete network - {}", network); // nothing to consider return StatusCode.OK; } @Override public void deleted(NeutronNetwork network) { LOG.trace("deleted network - {}", network); ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction(); TenantId tenantId = new TenantId(Utils.normalizeUuid(network.getTenantID())); L2FloodDomainId l2FdId = new L2FloodDomainId(network.getID()); InstanceIdentifier networkMappingIid = NeutronMapperIidFactory.networkMappingIid(l2FdId); Optional potentionalNetworkMapping = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, networkMappingIid, rwTx); if (!potentionalNetworkMapping.isPresent()) { LOG.warn("Illegal state - network-mapping {} does not exist.", l2FdId.getValue()); rwTx.cancel(); return; } NetworkMapping networkMapping = potentionalNetworkMapping.get(); L2BridgeDomainId l2BdId = networkMapping.getL2BridgeDomainId(); L3ContextId l3ContextId = networkMapping.getL3ContextId(); if (l2BdId == null || l3ContextId == null) { LOG.warn("Illegal state - network-mapping {} is not valid.", networkMapping); rwTx.cancel(); return; } Optional potentialL2Fd = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, IidFactory.l2FloodDomainIid(tenantId, l2FdId), rwTx); if (!potentialL2Fd.isPresent()) { LOG.warn("Illegal state - l2-flood-domain {} does not exist.", l2FdId.getValue()); rwTx.cancel(); return; } Optional potentialL2Bd = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), rwTx); if (!potentialL2Bd.isPresent()) { LOG.warn("Illegal state - l2-bridge-domain {} does not exist.", l2BdId.getValue()); rwTx.cancel(); return; } Optional potentialL3Context = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, IidFactory.l3ContextIid(tenantId, l3ContextId), rwTx); if (!potentialL3Context.isPresent()) { LOG.warn("Illegal state - l3-context {} does not exist.", l3ContextId.getValue()); rwTx.cancel(); return; } rwTx.delete(LogicalDatastoreType.OPERATIONAL, networkMappingIid); DataStoreHelper.submitToDs(rwTx); } }