/* * Copyright (c) 2015 Huawei Technologies 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.renderer.faas; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledExecutorService; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; 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.AsyncDataChangeEvent; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.faas.uln.datastore.api.UlnDatastoreApi; import org.opendaylight.groupbasedpolicy.util.DataStoreHelper; import org.opendaylight.groupbasedpolicy.util.IetfModelCodec; import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Text; import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Uuid; import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.subnets.rev151013.subnets.container.subnets.SubnetBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.subnets.rev151013.subnets.container.subnets.subnet.ExternalGateways; import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.subnets.rev151013.subnets.container.subnets.subnet.ExternalGatewaysBuilder; 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.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedSubnet; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedSubnetBuilder; 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.subnet.Gateways; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.subnet.gateways.Prefixes; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; public class FaasSubnetManagerListener implements DataChangeListener { private static final Logger LOG = LoggerFactory.getLogger(FaasSubnetManagerListener.class); private ConcurrentHashMap<SubnetId, Uuid> mappedSubnets = new ConcurrentHashMap<>(); private final ScheduledExecutorService executor; private final DataBroker dataProvider; private final TenantId gbpTenantId; private final Uuid faasTenantId; public FaasSubnetManagerListener(DataBroker dataProvider, TenantId gbpTenantId, Uuid faasTenantId, ScheduledExecutorService executor) { this.executor = executor; this.faasTenantId = faasTenantId; this.gbpTenantId = gbpTenantId; this.dataProvider = dataProvider; } @Override public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) { executor.execute(new Runnable() { public void run() { executeEvent(change); } }); } @VisibleForTesting void executeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) { // Create for (DataObject dao : change.getCreatedData().values()) { if (dao instanceof Subnet) { Subnet subnet = (Subnet) dao; LOG.debug("Subnet {} is Created.", subnet.getId().getValue()); UlnDatastoreApi.submitSubnetToDs(initSubnetBuilder(subnet).build()); } } // Update Map<InstanceIdentifier<?>, DataObject> dao = change.getUpdatedData(); for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : dao.entrySet()) { if (entry.getValue() instanceof Subnet) { Subnet subnet = (Subnet) entry.getValue(); LOG.debug("Subnet {} is Updated.", subnet.getId().getValue()); UlnDatastoreApi.submitSubnetToDs(initSubnetBuilder(subnet).build()); } } // Remove for (InstanceIdentifier<?> iid : change.getRemovedPaths()) { DataObject old = change.getOriginalData().get(iid); if (old == null) { continue; } if (old instanceof Subnet) { Subnet subnet = (Subnet) old; ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction(); Optional<MappedSubnet> op = DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, FaasIidFactory.mappedSubnetIid(gbpTenantId, subnet.getId()), rwTx); if (op.isPresent()) { DataStoreHelper.submitToDs(rwTx); } Uuid faasSubnetId = mappedSubnets.remove(subnet.getId()); if (faasSubnetId != null) { UlnDatastoreApi.removeSubnetFromDsIfExists(faasTenantId, faasSubnetId); } } } } public void loadAll(List<Subnet> subnets, List<MappedSubnet> mpSubnets) { if (mpSubnets != null) { for (MappedSubnet mpSubnet : mpSubnets) { mappedSubnets.putIfAbsent(mpSubnet.getGbpSubnetId(), mpSubnet.getFaasSubnetId()); } } if (subnets != null) { for (Subnet subnet : subnets) { LOG.debug("Loading Subnet {}", subnet.getId().getValue()); UlnDatastoreApi.submitSubnetToDs(initSubnetBuilder(subnet).build()); } } } protected SubnetBuilder initSubnetBuilder(Subnet gbpSubnet) { SubnetBuilder builder = new SubnetBuilder(); if (gbpSubnet.getGateways() != null) { List<ExternalGateways> gateways = new ArrayList<>(); for (Gateways gw : gbpSubnet.getGateways()) { ExternalGatewaysBuilder eb = new ExternalGatewaysBuilder(); eb.setExternalGateway(IetfModelCodec.ipAddress2013(gw.getGateway())); if (gw.getPrefixes() != null) { List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix> ipPrefixes = new ArrayList<>(); for (Prefixes px : gw.getPrefixes()) { ipPrefixes.add(IetfModelCodec.ipPrefix2013(px.getPrefix())); } eb.setPrefixes(ipPrefixes); } gateways.add(eb.build()); } builder.setExternalGateways(gateways); } builder.setIpPrefix(IetfModelCodec.ipPrefix2013(gbpSubnet.getIpPrefix())); builder.setUuid(getFaasSubnetId(gbpSubnet.getId())); builder.setName(new Text(gbpSubnet.getId().getValue())); if (gbpSubnet.getDescription() != null) builder.setDescription(new Text("gbp-subnet: " + gbpSubnet.getDescription().getValue())); else builder.setDescription(new Text("gbp-subnet")); builder.setTenantId(faasTenantId); builder.setVirtualRouterIp(IetfModelCodec.ipAddress2013(gbpSubnet.getVirtualRouterIp())); // TODO DNS servers builder.setDnsNameservers(null); // TODO DHCP server builder.setEnableDhcp(false); return builder; } private Uuid getFaasSubnetId(SubnetId subnetId) { Uuid val = mappedSubnets.get(subnetId); if (val != null) { return val; } Uuid faasSubnetId = null; if (FaasPolicyManager.isUUid(subnetId.getValue())) { faasSubnetId = new Uuid(subnetId.getValue()); } else { faasSubnetId = new Uuid(UUID.randomUUID().toString()); } mappedSubnets.putIfAbsent(subnetId, faasSubnetId); val = mappedSubnets.get(subnetId); MappedSubnetBuilder builder = new MappedSubnetBuilder(); builder.setFaasSubnetId(val); builder.setGbpSubnetId(subnetId); WriteTransaction wTx = dataProvider.newWriteOnlyTransaction(); MappedSubnet result = builder.build(); wTx.put(LogicalDatastoreType.OPERATIONAL, FaasIidFactory.mappedSubnetIid(gbpTenantId, subnetId), result); if (DataStoreHelper.submitToDs(wTx)) { LOG.debug("Cached in Datastore Mapped Subnet {}", result); } else { LOG.error("Couldn't Cache in Datastore Mapped Subnet {}", result); } return val; } }