/*
* Copyright © 2016 SNLAB 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.alto.basic.impl;
import org.opendaylight.alto.basic.manual.maps.ManualMapsUtils;
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.AsyncDataBroker;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
import org.opendaylight.yang.gen.v1.urn.opendaylight.address.tracker.rev140617.address.node.connector.Addresses;
import org.opendaylight.yang.gen.v1.urn.alto.manual.maps.networkmap.rev151021.EndpointAddressType;
import org.opendaylight.yang.gen.v1.urn.alto.manual.maps.networkmap.rev151021.endpoint.address.group.EndpointAddressGroup;
import org.opendaylight.yang.gen.v1.urn.alto.manual.maps.networkmap.rev151021.endpoint.address.group.EndpointAddressGroupBuilder;
import org.opendaylight.yang.gen.v1.urn.alto.types.rev150921.PidName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.host.tracker.rev140624.HostNode;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class AltoAutoMapsUpdateListener implements DataChangeListener, AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(AltoAutoMapsUpdateListener.class);
private final DataBroker dataBroker;
private ListenerRegistration<DataChangeListener> registration;
private static final String TOPOLOGY_NAME = "flow:1";
private static final String DEFAULT_AUTO_NETWORKMAP = "default-auto-networkmap";
private static final String DEFAULT_AUTO_COSTMAP = "default-auto-costmap";
private static final String DEFAULT_PID = "PID0";
public AltoAutoMapsUpdateListener(final DataBroker dataBroker) {
this.dataBroker = dataBroker;
InstanceIdentifier<Topology> iid = InstanceIdentifier
.builder(NetworkTopology.class)
.child(Topology.class,
new TopologyKey(new TopologyId(TOPOLOGY_NAME)))
.build();
this.registration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
iid, this, AsyncDataBroker.DataChangeScope.BASE);
}
@Override
public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event) {
if (event == null) {
return;
}
final ReadWriteTransaction rwx = dataBroker.newReadWriteTransaction();
Map<InstanceIdentifier<?>, DataObject> original = event.getOriginalData();
for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : event.getCreatedData().entrySet()) {
InstanceIdentifier<?> iid = entry.getKey();
DataObject created = entry.getValue();
if (created instanceof Topology) {
createDefaultAutoNetworkMap((Topology) created, rwx);
LOG.info("Create default auto networkmap");
}
}
for (InstanceIdentifier<?> iid : event.getRemovedPaths()) {
DataObject removed = original.get(iid);
if (removed instanceof Topology) {
emptyDefaultAutoNetworkMap(rwx);
LOG.info("Empty default auto networkmap");
}
}
for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : event.getUpdatedData().entrySet()) {
InstanceIdentifier<?> iid = entry.getKey();
DataObject updated = entry.getValue();
if (updated instanceof Topology) {
updateDefaultAutoNetworkMap((Topology) updated, rwx);
LOG.info("Update default auto networkmap");
}
}
rwx.submit();
}
private void createDefaultAutoNetworkMap(Topology topology, final WriteTransaction wx) {
for (Node node : topology.getNode()) {
HostNode hostNode = node.getAugmentation(HostNode.class);
if (hostNode != null) {
List<Addresses> addressesList = hostNode.getAddresses();
mergeAddressesListToDefaultNetworkMap(addressesList, wx);
}
}
}
private void emptyDefaultAutoNetworkMap(final WriteTransaction wx) {
mergeAddressesListToDefaultNetworkMap(new LinkedList<Addresses>(), wx);
}
private void updateDefaultAutoNetworkMap(Topology topology, final WriteTransaction wx) {
// TODO: can be more efficient
emptyDefaultAutoNetworkMap(wx);
createDefaultAutoNetworkMap(topology, wx);
}
private void mergeAddressesListToDefaultNetworkMap(List<Addresses> addressesList, final WriteTransaction wx) {
List<org.opendaylight.yang.gen.v1.urn.alto
.manual.maps.networkmap.rev151021.network.map.Map> networkMap = new LinkedList<>();
org.opendaylight.yang.gen.v1.urn.alto
.manual.maps.networkmap.rev151021.network.map.MapBuilder builder =
new org.opendaylight.yang.gen.v1.urn.alto
.manual.maps.networkmap.rev151021.network.map.MapBuilder();
List<IpPrefix> prefixList = aggregateAddressesList(addressesList);
List<EndpointAddressGroup> emptyEndpointAddressGroup = new LinkedList<>();
emptyEndpointAddressGroup.add(new EndpointAddressGroupBuilder()
.setAddressType(new EndpointAddressType(EndpointAddressType.Enumeration.Ipv4))
.setEndpointPrefix(prefixList)
.build());
builder.setPid(new PidName("PID0"))
.setEndpointAddressGroup(emptyEndpointAddressGroup);
networkMap.add(builder.build());
ManualMapsUtils.createResourceNetworkMap(DEFAULT_AUTO_NETWORKMAP, networkMap, wx);
}
private List<IpPrefix> aggregateAddressesList(List<Addresses> addressesList) {
List<IpPrefix> prefixList = new LinkedList<>();
for (Addresses addresses : addressesList) {
if (addresses.getIp() == null)
continue;
String ipAddress = addresses.getIp().getIpv4Address().getValue();
IpPrefix prefix = new IpPrefix(new Ipv4Prefix(ipAddress + "/32"));
prefixList.add(prefix);
}
return prefixList;
}
@Override
public void close() throws Exception {
registration.close();
LOG.info("AltoAutoMapsUpdateListener Closed");
}
}