import static com.google.common.base.Preconditions.checkNotNull;
-import java.util.ArrayList;
-import java.util.List;
-
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.domain_extension.l2_l3.util.L2L3IidFactory;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.EndpointRegistrator;
import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils.ForwardingCtx;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NetworkUtils;
import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
import org.opendaylight.groupbasedpolicy.util.IidFactory;
-import org.opendaylight.neutron.spi.NeutronSubnet;
-import org.opendaylight.neutron.spi.NeutronSubnetIPAllocationPool;
-import org.opendaylight.neutron.spi.NeutronSubnet_HostRoute;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
-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.NetworkDomainId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L2FloodDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentForwarding;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentForwardingBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.SubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomainBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.SubnetBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.Dhcpv6Base;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.Dhcpv6Off;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.Dhcpv6Slaac;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.Dhcpv6Stateful;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.Dhcpv6Stateless;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.IpVersionBase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.IpVersionV4;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.IpVersionV6;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnet.attributes.AllocationPools;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnet.attributes.HostRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
+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;
-public class NeutronSubnetAware implements MappingProcessor<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet, NeutronSubnet> {
+public class NeutronSubnetAware implements
+ NeutronAware<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet> {
private final static Logger LOG = LoggerFactory.getLogger(NeutronSubnetAware.class);
+ public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet> SUBNET_WILDCARD_IID =
+ InstanceIdentifier.builder(Neutron.class)
+ .child(Subnets.class)
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet.class)
+ .build();
private final DataBroker dataProvider;
- private final NeutronNetworkDao networkDao;
+ private final EndpointRegistrator epRegistrator;
- public NeutronSubnetAware(DataBroker dataProvider, NeutronNetworkDao networkDao) {
+ public NeutronSubnetAware(DataBroker dataProvider, EndpointRegistrator epRegistrator) {
this.dataProvider = checkNotNull(dataProvider);
- this.networkDao = checkNotNull(networkDao);
+ this.epRegistrator = checkNotNull(epRegistrator);
}
- // copied from Neutron's NeutronSubnetInterface
- static final ImmutableBiMap<Class<? extends IpVersionBase>,Integer> IPV_MAP
- = new ImmutableBiMap.Builder<Class<? extends IpVersionBase>,Integer>()
- .put(IpVersionV4.class, 4)
- .put(IpVersionV6.class, 6)
- .build();
-
- // copied from Neutron's NeutronSubnetInterface
- private static final ImmutableBiMap<Class<? extends Dhcpv6Base>,String> DHCPV6_MAP
- = new ImmutableBiMap.Builder<Class<? extends Dhcpv6Base>,String>()
- .put(Dhcpv6Off.class,"off")
- .put(Dhcpv6Stateful.class,"dhcpv6-stateful")
- .put(Dhcpv6Slaac.class,"slaac")
- .put(Dhcpv6Stateless.class,"dhcpv6-stateless")
- .build();
-
@Override
- public NeutronSubnet convertToNeutron(
- org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet subnet) {
- return toNeutron(subnet);
- }
+ public void onCreated(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet neutronSubnet,
+ Neutron neutron) {
+ LOG.trace("created subnet - {}", neutronSubnet);
+ ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+ TenantId tenantId = new TenantId(neutronSubnet.getTenantId().getValue());
- @SuppressWarnings("deprecation")
- static NeutronSubnet toNeutron(
- org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet subnet) {
- NeutronSubnet result = new NeutronSubnet();
- result.setName(subnet.getName());
- result.setTenantID(subnet.getTenantId());
- result.setNetworkUUID(subnet.getNetworkId().getValue());
- result.setIpVersion(IPV_MAP.get(subnet.getIpVersion()));
- result.setCidr(subnet.getCidr());
- if (subnet.getGatewayIp() != null) {
- result.setGatewayIP(String.valueOf(subnet.getGatewayIp().getValue()));
- }
- if (subnet.getIpv6RaMode() != null) {
- result.setIpV6RaMode(DHCPV6_MAP.get(subnet.getIpv6RaMode()));
- }
- if (subnet.getIpv6AddressMode() != null) {
- result.setIpV6AddressMode(DHCPV6_MAP.get(subnet.getIpv6AddressMode()));
- }
- result.setEnableDHCP(subnet.isEnableDhcp());
- if (subnet.getAllocationPools() != null) {
- List<NeutronSubnetIPAllocationPool> allocationPools = new ArrayList<NeutronSubnetIPAllocationPool>();
- for (AllocationPools allocationPool : subnet.getAllocationPools()) {
- NeutronSubnetIPAllocationPool pool = new NeutronSubnetIPAllocationPool();
- pool.setPoolStart(allocationPool.getStart());
- pool.setPoolEnd(allocationPool.getEnd());
- allocationPools.add(pool);
- }
- result.setAllocationPools(allocationPools);
- }
- if (subnet.getDnsNameservers() != null) {
- List<String> dnsNameServers = new ArrayList<String>();
- for (IpAddress dnsNameServer : subnet.getDnsNameservers()) {
- dnsNameServers.add(String.valueOf(dnsNameServer.getValue()));
- }
- result.setDnsNameservers(dnsNameServers);
+ Optional<Network> potentialNetwork =
+ NetworkUtils.findNetwork(neutronSubnet.getNetworkId(), neutron.getNetworks());
+ if (!potentialNetwork.isPresent()) {
+ LOG.warn("Illegal state - network {} does not exist for subnet {}.",
+ neutronSubnet.getNetworkId().getValue(), neutronSubnet);
+ rwTx.cancel();
+ return;
}
- if (subnet.getHostRoutes() != null) {
- List<NeutronSubnet_HostRoute> hostRoutes = new ArrayList<NeutronSubnet_HostRoute>();
- for (HostRoutes hostRoute : subnet.getHostRoutes()) {
- NeutronSubnet_HostRoute nsHostRoute = new NeutronSubnet_HostRoute();
- nsHostRoute.setDestination(String.valueOf(hostRoute.getDestination().getValue()));
- nsHostRoute.setNextHop(String.valueOf(hostRoute.getNexthop().getValue()));
- hostRoutes.add(nsHostRoute);
+
+ Network networkOfSubnet = potentialNetwork.get();
+
+ NetworkDomain subnetDomain = null;
+ if (NetworkUtils.isProviderPhysicalNetwork(networkOfSubnet)) {
+ // add virtual router IP only in case it is provider physical network
+ subnetDomain = createSubnet(neutronSubnet, neutronSubnet.getGatewayIp());
+ IpAddress gatewayIp = neutronSubnet.getGatewayIp();
+ boolean registeredDefaultRoute = epRegistrator.registerExternalL3PrefixEndpoint(MappingUtils.DEFAULT_ROUTE,
+ new L3ContextId(neutronSubnet.getNetworkId().getValue()), gatewayIp, tenantId);
+ if (!registeredDefaultRoute) {
+ LOG.warn("Could not add EndpointL3Prefix as default route. Subnet within provider physical network {}",
+ neutronSubnet);
+ rwTx.cancel();
+ return;
}
- result.setHostRoutes(hostRoutes);
+ } else {
+ // virtual router IP is not set and it will be set when router gateway port is set
+ // or when a router port is attached to a network
+ subnetDomain = createSubnet(neutronSubnet, null);
}
- result.setID(subnet.getUuid().getValue());
- return result;
+ processTenantSubnet(neutronSubnet, networkOfSubnet, tenantId, rwTx);
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain, true);
+ DataStoreHelper.submitToDs(rwTx);
}
- @Override
- public int canCreate(NeutronSubnet subnet) {
- LOG.trace("canCreate subnet - {}", subnet);
- // nothing to consider
- return StatusCode.OK;
+ public static NetworkDomain createSubnet(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet subnet,
+ IpAddress virtualRouterIp) {
+ SubnetBuilder sb = new SubnetBuilder();
+ sb.setIpPrefix(subnet.getCidr());
+ sb.setVirtualRouterIp(virtualRouterIp);
+ NetworkDomainBuilder ndb = new NetworkDomainBuilder();
+ if (!Strings.isNullOrEmpty(subnet.getName())) {
+ try {
+ ndb.setName(new Name(subnet.getName()));
+ } catch (Exception e) {
+ LOG.info("Name '{}' of Neutron Subnet '{}' is ignored.", subnet.getName(), subnet.getUuid().getValue());
+ LOG.debug("Name exception", e);
+ }
+ }
+ ndb.setNetworkDomainId(new NetworkDomainId(subnet.getUuid().getValue()));
+ ndb.setNetworkDomainType(MappingUtils.SUBNET);
+ ndb.setParent(MappingUtils.createParent(new NetworkDomainId(subnet.getNetworkId().getValue()), L2FloodDomain.class));
+ ndb.addAugmentation(SubnetAugmentForwarding.class, new SubnetAugmentForwardingBuilder().setSubnet(sb.build())
+ .build());
+ return ndb.build();
}
- @Override
- public void created(NeutronSubnet neutronSubnet) {
- LOG.trace("created subnet - {}", neutronSubnet);
- ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
- SubnetId subnetId = new SubnetId(Utils.normalizeUuid(neutronSubnet.getID()));
- TenantId tenantId = new TenantId(Utils.normalizeUuid(neutronSubnet.getTenantID()));
- Subnet subnet = createSubnet(neutronSubnet);
- rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnetId), subnet, true);
- DataStoreHelper.submitToDs(rwTx);
-
- rwTx = dataProvider.newReadWriteTransaction();
- if (networkDao.isExternalNetwork(neutronSubnet.getNetworkUUID())) {
- LOG.trace("created - adding L3 Endpoint");
- L2FloodDomainId l2FdId = new L2FloodDomainId(subnet.getParent().getValue());
- ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rwTx);
- IpAddress defaultGateway = Utils.createIpAddress(neutronSubnet.getGatewayIP());
- //Create L3Endpoint for defaultGateway
- NetworkDomainId containment = new NetworkDomainId(neutronSubnet.getID());
- NeutronPortAware.addL3EndpointForExternalGateway(tenantId, fwCtx.getL3Context().getId(), defaultGateway, containment ,rwTx);
- DataStoreHelper.submitToDs(rwTx);
+ @Deprecated
+ private void processTenantSubnet(org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet neutronSubnet, Network networkOfSubnet, TenantId tenantId, ReadWriteTransaction rwTx) {
+ Subnet subnet;
+ if (NetworkUtils.isProviderPhysicalNetwork(networkOfSubnet)) {
+ // add virtual router IP only in case it is provider physical network
+ subnet = createTenantSubnet(neutronSubnet, neutronSubnet.getGatewayIp());
+ IpAddress gatewayIp = neutronSubnet.getGatewayIp();
+ boolean registeredDefaultRoute = epRegistrator.registerExternalL3PrefixEndpoint(MappingUtils.DEFAULT_ROUTE,
+ new L3ContextId(neutronSubnet.getNetworkId().getValue()), gatewayIp, tenantId);
+ if (!registeredDefaultRoute) {
+ LOG.warn("Could not add EndpointL3Prefix as default route. Subnet within provider physical network {}",
+ neutronSubnet);
+ rwTx.cancel();
+ return;
+ }
+ } else {
+ // virtual router IP is not set and it will be set when router gateway port is set
+ // or when a router port is attached to a network
+ subnet = createTenantSubnet(neutronSubnet, null);
}
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnet.getId()), subnet, true);
}
- private Subnet createSubnet(NeutronSubnet neutronSubnet) {
- SubnetBuilder subnetBuilder = new SubnetBuilder();
- subnetBuilder.setId(new SubnetId(neutronSubnet.getID()));
- subnetBuilder.setParent(new ContextId(neutronSubnet.getNetworkUUID()));
- if (!Strings.isNullOrEmpty(neutronSubnet.getName())) {
- subnetBuilder.setName(new Name(neutronSubnet.getName()));
+ @Deprecated
+ public static Subnet createTenantSubnet(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet subnet,
+ IpAddress virtualRouterIp) {
+ org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.SubnetBuilder subnetBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.SubnetBuilder();
+ subnetBuilder.setId(new SubnetId(subnet.getUuid().getValue()));
+ subnetBuilder.setParent(new ContextId(subnet.getNetworkId().getValue()));
+ if (!Strings.isNullOrEmpty(subnet.getName())) {
+ try {
+ subnetBuilder.setName(new Name(subnet.getName()));
+ } catch (Exception e) {
+ LOG.info("Name '{}' of Neutron Subnet '{}' is ignored.", subnet.getName(),
+ subnet.getUuid().getValue());
+ LOG.debug("Name exception", e);
+ }
}
- subnetBuilder.setIpPrefix(Utils.createIpPrefix(neutronSubnet.getCidr()));
+ subnetBuilder.setIpPrefix(subnet.getCidr());
+ subnetBuilder.setVirtualRouterIp(virtualRouterIp);
return subnetBuilder.build();
}
@Override
- public int canUpdate(NeutronSubnet delta, NeutronSubnet original) {
- LOG.trace("canUpdate subnet - delta: {} original: {}", delta, original);
- // nothing to consider
- return StatusCode.OK;
+ public void onUpdated(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet oldItem,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet newItem,
+ Neutron oldNeutron, Neutron newNeutron) {
+ LOG.trace("updated subnet - {}", newItem);
+ onCreated(newItem, newNeutron);
}
@Override
- public void updated(NeutronSubnet subnet) {
- LOG.trace("updated subnet - {}", subnet);
- created(subnet);
- }
+ public void onDeleted(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet neutronSubnet,
+ Neutron oldNeutron, Neutron newNeutron) {
+ LOG.trace("deleted subnet - {}", neutronSubnet);
+ ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+ NetworkDomainId subnetId = new NetworkDomainId(neutronSubnet.getUuid().getValue());
+ TenantId tenantId = new TenantId(neutronSubnet.getTenantId().getValue());
+ Optional<NetworkDomain> potentialSubnetDomain = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
+ L2L3IidFactory.subnetIid(tenantId, subnetId), rwTx);
+ if (!potentialSubnetDomain.isPresent()) {
+ LOG.warn("Illegal state - subnet network domain {} does not exist.", subnetId.getValue());
+ rwTx.cancel();
+ return;
+ }
+ removeTenantSubnet(tenantId, new SubnetId(subnetId), rwTx);
- @Override
- public int canDelete(NeutronSubnet subnet) {
- LOG.trace("canDelete subnet - {}", subnet);
- // nothing to consider
- return StatusCode.OK;
+ // TODO remove default gateway EP in case when subnet is in provider physical network
+
+ DataStoreHelper.submitToDs(rwTx);
}
- @Override
- public void deleted(NeutronSubnet neutronSubnet) {
- LOG.trace("deleted subnet - {}", neutronSubnet);
- ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
- SubnetId subnetId = new SubnetId(Utils.normalizeUuid(neutronSubnet.getID()));
- TenantId tenantId = new TenantId(Utils.normalizeUuid(neutronSubnet.getTenantID()));
+ @Deprecated
+ private void removeTenantSubnet(TenantId tenantId, SubnetId subnetId, ReadWriteTransaction rwTx) {
Optional<Subnet> potentialSubnet = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
IidFactory.subnetIid(tenantId, subnetId), rwTx);
if (!potentialSubnet.isPresent()) {
rwTx.cancel();
return;
}
- DataStoreHelper.submitToDs(rwTx);
}
}