<mdsal.model.version>0.9.0-SNAPSHOT</mdsal.model.version>
<netconf.version>1.1.0-SNAPSHOT</netconf.version>
<genius.version>0.1.0-SNAPSHOT</genius.version>
+ <tenantutil.version>0.1.0-SNAPSHOT</tenantutil.version>
<configfile.directory>etc/opendaylight/karaf</configfile.directory>
</properties>
<dependencyManagement>
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
-import org.opendaylight.genius.mdsalutil.MDSALUtil;
import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
-import org.opendaylight.unimgr.command.EvcAddCommand;
-import org.opendaylight.unimgr.command.EvcRemoveCommand;
-import org.opendaylight.unimgr.command.EvcUpdateCommand;
-import org.opendaylight.unimgr.impl.UnimgrConstants;
import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.MefServices;
import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.MefService;
import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.Evc;
import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.evc.unis.Uni;
import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.evc.unis.uni.EvcUniCeVlans;
import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.evc.unis.uni.evc.uni.ce.vlans.EvcUniCeVlan;
-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.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.Link;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
--- /dev/null
+/*
+ * Copyright (c) 2016 Hewlett Packard Enterprise, Co. 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.unimgr.mef.netvirt;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
+import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.PhysicalLayers;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.Links;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.Link;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.MefServices;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.MefService;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.Evc;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.evc.Unis;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.evc.unis.Uni;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.evc.unis.uni.EvcUniCeVlans;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.evc.unis.uni.evc.uni.ce.vlans.EvcUniCeVlan;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.VlanIdType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.CheckedFuture;
+
+public class EvcUniListener extends UnimgrDataTreeChangeListener<Uni> {
+ private static final Logger logger = LoggerFactory.getLogger(EvcUniListener.class);
+
+ private ListenerRegistration<EvcUniListener> uniListenerRegistration;
+
+ public EvcUniListener(final DataBroker dataBroker) {
+ super(dataBroker);
+
+ registerListener();
+ }
+
+ @Override
+ public void add(DataTreeModification<Uni> newDataObject) {
+ if (newDataObject.getRootPath() != null && newDataObject.getRootNode() != null) {
+ logger.info("uni {} created", newDataObject.getRootNode().getIdentifier());
+ addUni(newDataObject);
+ }
+ }
+
+ @Override
+ public void remove(DataTreeModification<Uni> removedDataObject) {
+ if (removedDataObject.getRootPath() != null && removedDataObject.getRootNode() != null) {
+ logger.info("uni {} deleted", removedDataObject.getRootNode().getIdentifier());
+ removeUni(removedDataObject);
+ }
+ }
+
+ @Override
+ public void update(DataTreeModification<Uni> modifiedDataObject) {
+ if (modifiedDataObject.getRootPath() != null && modifiedDataObject.getRootNode() != null) {
+ logger.info("uni {} updated", modifiedDataObject.getRootNode().getIdentifier());
+ updateUni(modifiedDataObject);
+ }
+ }
+
+ protected void removeUni(DataTreeModification<Uni> removedDataObject) {
+ try {
+ Uni data = removedDataObject.getRootNode().getDataBefore();
+
+ String uniId = data.getUniId().getValue();
+ WriteTransaction tx = createTransaction();
+ logger.info("Removing trunk {}", uniId);
+ delete(uniId, tx);
+
+ Optional<List<EvcUniCeVlan>> ceVlansOptional = getCeVlans(data);
+ if (!ceVlansOptional.isPresent()) {
+ return;
+ }
+
+ removeTrunkMemberInterfaces(uniId, ceVlansOptional.get(), tx);
+ commitTransaction(tx);
+ } catch (final Exception e) {
+ logger.error("Remove uni failed !", e);
+ }
+ }
+
+ protected void updateUni(DataTreeModification<Uni> modifiedDataObject) {
+ try {
+ Uni original = modifiedDataObject.getRootNode().getDataBefore();
+ Uni update = modifiedDataObject.getRootNode().getDataAfter();
+
+ String uniId = update.getUniId().getValue();
+ WriteTransaction tx = createTransaction();
+ String origTrunkParentName = getTrunkParentName(original);
+ String updatedTrunkParentName = getTrunkParentName(update);
+
+ if (!Objects.equal(origTrunkParentName, updatedTrunkParentName)) {
+ addTrunkInterface(uniId, updatedTrunkParentName, tx);
+ }
+
+ Set<EvcUniCeVlan> origCeVlans = Sets.newHashSet(getCeVlans(original).or(Collections.emptyList()));
+ Set<EvcUniCeVlan> updatedCeVlans = Sets.newHashSet(getCeVlans(update).or(Collections.emptyList()));
+ Iterable<EvcUniCeVlan> removedCeVlans = Sets.difference(origCeVlans, updatedCeVlans);
+ Iterable<EvcUniCeVlan> addedCeVlans = Sets.difference(updatedCeVlans, origCeVlans);
+ removeTrunkMemberInterfaces(uniId, removedCeVlans, tx);
+ addTrunkMemberInterfaces(uniId, addedCeVlans, tx);
+ commitTransaction(tx);
+ } catch (final Exception e) {
+ logger.error("Update uni failed !", e);
+ }
+
+ }
+
+ protected void addUni(DataTreeModification<Uni> newDataObject) {
+ try {
+ Uni data = newDataObject.getRootNode().getDataAfter();
+
+ String uniId = data.getUniId().getValue();
+ WriteTransaction tx = createTransaction();
+ addTrunkInterface(uniId, getTrunkParentName(data), tx);
+
+ Optional<List<EvcUniCeVlan>> ceVlansOptional = getCeVlans(data);
+ if (ceVlansOptional.isPresent()) {
+ addTrunkMemberInterfaces(uniId, ceVlansOptional.get(), tx);
+ }
+
+ commitTransaction(tx);
+ } catch (final Exception e) {
+ logger.error("Add uni failed !", e);
+ }
+
+ }
+
+ private void addTrunkInterface(String interfaceName, String parentInterfaceName, WriteTransaction tx) {
+ logger.info("Adding VLAN trunk {} ParentRef {}", interfaceName, parentInterfaceName);
+ Interface trunkInterface = NetvirtUtils.createTrunkInterface(interfaceName, parentInterfaceName);
+ write(trunkInterface, tx);
+ }
+
+ private void addTrunkMemberInterfaces(String parentInterfaceName, Iterable<EvcUniCeVlan> ceVlans,
+ WriteTransaction tx) {
+ for (EvcUniCeVlan ceVlan : ceVlans) {
+ Long vlanId = ((VlanIdType) ceVlan.getVid()).getValue();
+ String interfaceName = NetvirtUtils.getInterfaceNameForVlan(parentInterfaceName, vlanId.toString());
+ logger.info("Adding VLAN trunk-member {} ParentRef {}", interfaceName, parentInterfaceName);
+ Interface trunkMemberInterface = NetvirtUtils.createTrunkMemberInterface(interfaceName, parentInterfaceName,
+ vlanId.intValue());
+ write(trunkMemberInterface, tx);
+ }
+ }
+
+ private void removeTrunkMemberInterfaces(String parentInterfaceName, Iterable<EvcUniCeVlan> ceVlans,
+ WriteTransaction tx) {
+ for (EvcUniCeVlan ceVlan : ceVlans) {
+ Long vlanId = ((VlanIdType) ceVlan.getVid()).getValue();
+ String interfaceName = NetvirtUtils.getInterfaceNameForVlan(parentInterfaceName, vlanId.toString());
+ logger.info("Removing VLAN trunk-member {}", interfaceName);
+ delete(interfaceName, tx);
+ }
+ }
+
+ private InstanceIdentifier<Interface> createInterfaceIdentifier(String interfaceName) {
+ return InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName))
+ .build();
+ }
+
+ private WriteTransaction createTransaction() {
+ WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+ return tx;
+ }
+
+ private void commitTransaction(WriteTransaction tx) {
+ try {
+ CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+ futures.get();
+ } catch (Exception e) {
+ logger.error("failed to commit transaction due to exception ", e);
+ }
+ }
+
+ private void write(Interface iface, WriteTransaction tx) {
+ String interfaceName = iface.getName();
+ InstanceIdentifier<Interface> interfaceIdentifier = createInterfaceIdentifier(interfaceName);
+ tx.put(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier, iface, true);
+ }
+
+ private void delete(String interfaceName, WriteTransaction tx) {
+ InstanceIdentifier<Interface> interfaceIdentifier = createInterfaceIdentifier(interfaceName);
+ tx.delete(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier);
+ }
+
+ private String getTrunkParentName(Uni evcUni) {
+
+ Optional<org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni> optional = MdsalUtils
+ .read(dataBroker, LogicalDatastoreType.CONFIGURATION,
+ MefUtils.getUniInstanceIdentifier(evcUni.getUniId().getValue()));
+
+ if (!optional.isPresent()) {
+ logger.error("A matching Uni doesn't exist for EvcUni {}", evcUni.getUniId());
+ return null;
+ }
+
+ org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni uni = optional
+ .get();
+
+ PhysicalLayers physicalLayers = uni.getPhysicalLayers();
+ if (physicalLayers == null) {
+ logger.warn("Uni {} is missing PhysicalLayers", evcUni.getUniId());
+ return null;
+ }
+
+ Links links = physicalLayers.getLinks();
+ if (links == null || links.getLink() == null) {
+ logger.warn("Uni {} is has no links", evcUni.getUniId());
+ return null;
+ }
+
+ Link link = links.getLink().get(0);
+ String deviceName = link.getDevice().getValue();
+ String interfaceName = link.getInterface().toString();
+ return getDeviceInterfaceName(deviceName, interfaceName);
+ }
+
+ private String getDeviceInterfaceName(String deviceName, String interfaceName) {
+ return deviceName + IfmConstants.OF_URI_SEPARATOR + interfaceName;
+ }
+
+ private Optional<List<EvcUniCeVlan>> getCeVlans(Uni uni) {
+ EvcUniCeVlans ceVlans = uni.getEvcUniCeVlans();
+ if (ceVlans == null) {
+ return Optional.absent();
+ }
+
+ return Optional.fromNullable(ceVlans.getEvcUniCeVlan());
+ }
+
+ private void registerListener() {
+ try {
+ final DataTreeIdentifier<Uni> dataTreeIid = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
+ getUniTopologyPath());
+ uniListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
+ logger.info("UniDataTreeChangeListener created and registered");
+ } catch (final Exception e) {
+ logger.error("Uni DataChange listener registration failed !", e);
+ throw new IllegalStateException("Uni registration Listener failed.", e);
+ }
+ }
+
+ private InstanceIdentifier<Uni> getUniTopologyPath() {
+ return InstanceIdentifier.create(MefServices.class).child(MefService.class).child(Evc.class).child(Unis.class)
+ .child(Uni.class);
+ }
+
+ @Override
+ public void close() throws Exception {
+ // TODO Auto-generated method stub
+
+ }
+}
\ No newline at end of file
import java.util.concurrent.ExecutionException;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
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.base.Optional;
import com.google.common.util.concurrent.CheckedFuture;
public class MdsalUtils {
return futures;
}
+ public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path) {
+ ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
+ Optional<T> result = Optional.absent();
+ try {
+ CheckedFuture<Optional<T>, ReadFailedException> checkedFuture = tx.read(datastoreType, path);
+ result = checkedFuture.get();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ return result;
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Hewlett Packard Enterprise, Co. 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.unimgr.mef.netvirt;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.MefInterfaces;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.Unis;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.UniBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.UniKey;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.PhysicalLayers;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.PhysicalLayersBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.Links;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.LinksBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.Link;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.LinkBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.LinkKey;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.MefServices;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.MefService;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.Evc;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.MefTopology;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.Devices;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.Device;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.DeviceBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.DeviceKey;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.device.Interfaces;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.device.InterfacesBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.device.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.device.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.device.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.DeviceRole;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.Identifier45;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+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.util.concurrent.CheckedFuture;
+
+public final class MefUtils {
+ private static final Logger logger = LoggerFactory.getLogger(MefUtils.class);
+
+ public static InstanceIdentifier getDeviceInterfaceInstanceIdentifier(String deviceId, String interfaceId) {
+ return InstanceIdentifier.builder(MefTopology.class).child(Devices.class)
+ .child(Device.class, new DeviceKey(new Identifier45(deviceId))).child(Interfaces.class)
+ .child(Interface.class, new InterfaceKey(new Identifier45(interfaceId))).build();
+ }
+
+ public static InstanceIdentifier<Uni> getUniInstanceIdentifier(String uniId) {
+ return InstanceIdentifier.builder(MefInterfaces.class).child(Unis.class)
+ .child(Uni.class, new UniKey(new Identifier45(uniId))).build();
+ }
+
+ public static InstanceIdentifier<org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.evc.unis.Uni> getEvcUniInstanceIdentifier(
+ String uniId) {
+ return InstanceIdentifier.builder(MefServices.class).child(MefService.class).child(Evc.class)
+ .child(org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.evc.Unis.class)
+ .child(org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.evc.unis.Uni.class,
+ new org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.evc.unis.UniKey(
+ new Identifier45(uniId))).build();
+
+ }
+
+ public static InstanceIdentifier getUniLinkInstanceIdentifier(String uniId, String deviceId, String interfaceId) {
+ return InstanceIdentifier.builder(MefInterfaces.class).child(Unis.class)
+ .child(Uni.class, new UniKey(new Identifier45(uniId))).child(PhysicalLayers.class).child(Links.class)
+ .child(Link.class, new LinkKey(new Identifier45(deviceId), interfaceId)).build();
+ }
+}
MdsalUtils.delete(dataBroker, LogicalDatastoreType.CONFIGURATION,
getElanInterfaceInstanceIdentifier(interfaceName));
}
+
+ public static Interface createTrunkInterface(String interfaceName, String parentIfaceName) {
+ IfL2vlanBuilder ifL2vlanBuilder = new IfL2vlanBuilder();
+ ifL2vlanBuilder.setL2vlanMode(IfL2vlan.L2vlanMode.Trunk);
+ return createInterface(interfaceName, parentIfaceName, ifL2vlanBuilder.build());
+ }
+
+ public static Interface createTrunkMemberInterface(String interfaceName, String parentIfaceName, int vlanId) {
+ IfL2vlanBuilder ifL2vlanBuilder = new IfL2vlanBuilder();
+ ifL2vlanBuilder.setL2vlanMode(IfL2vlan.L2vlanMode.TrunkMember).setVlanId(new VlanId(vlanId));
+ return createInterface(interfaceName, parentIfaceName, ifL2vlanBuilder.build());
+ }
+
+ private static Interface createInterface(String interfaceName, String parentIfaceName, IfL2vlan ifL2vlan) {
+ InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
+ ParentRefsBuilder parentRefsBuilder = new ParentRefsBuilder().setParentInterface(parentIfaceName);
+ interfaceBuilder.setEnabled(true).setName(interfaceName).setType(L2vlan.class).addAugmentation(IfL2vlan
+ .class, ifL2vlan).addAugmentation(ParentRefs.class, parentRefsBuilder.build());
+ return interfaceBuilder.build();
+ }
public static String getInterfaceNameForVlan(String uniId, String vlanId) {
- return uniId + "#" + vlanId;
+ return uniId + "." + vlanId;
}
private static ElanInstanceBuilder createElanInstance(String instanceName) {
private static InstanceIdentifier getUniInterfaceInstanceIdentifier(String interfaceName) {
return InstanceIdentifier.builder(MefInterfaces.class).child(Unis.class)
.child(Uni.class, new UniKey(new Identifier45(interfaceName))).build();
- }
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Hewlett Packard Enterprise, Co. 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.unimgr.mef.netvirt;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.UniBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.PhysicalLayersBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.LinksBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.Link;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.LinkBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.Device;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.DeviceBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.device.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.Identifier45;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.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 com.google.common.util.concurrent.CheckedFuture;
+
+public class NodeConnectorListener extends UnimgrDataTreeChangeListener<FlowCapableNodeConnector> {
+
+ private static final String OF_URI_SEPARATOR = ":";
+ private static final Logger log = LoggerFactory.getLogger(NodeConnectorListener.class);
+ private static final Logger logger = LoggerFactory.getLogger(NodeConnectorListener.class);
+ private static boolean handleRemovedNodeConnectors = false;
+ private ListenerRegistration<NodeConnectorListener> evcListenerRegistration;
+
+ public NodeConnectorListener(final DataBroker dataBroker) {
+ super(dataBroker);
+
+ registerListener();
+ }
+
+ public void registerListener() {
+ try {
+ final DataTreeIdentifier<FlowCapableNodeConnector> dataTreeIid = new DataTreeIdentifier<>(
+ LogicalDatastoreType.OPERATIONAL, getInstanceIdentifier());
+ evcListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
+ log.info("NodeConnectorListener created and registered");
+ } catch (final Exception e) {
+ log.error("Node connector listener registration failed !", e);
+ throw new IllegalStateException("Node connector listener registration failed.", e);
+ }
+ }
+
+ private InstanceIdentifier<FlowCapableNodeConnector> getInstanceIdentifier() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class).child(NodeConnector.class)
+ .augmentation(FlowCapableNodeConnector.class);
+ }
+
+ @Override
+ public void close() throws Exception {
+ evcListenerRegistration.close();
+ }
+
+ @Override
+ public void add(DataTreeModification<FlowCapableNodeConnector> newDataObject) {
+ if (newDataObject.getRootPath() != null && newDataObject.getRootNode() != null) {
+ log.info("node connector {} created", newDataObject.getRootNode().getIdentifier());
+ addFlowCapableNodeConnector(newDataObject);
+ }
+ }
+
+ @Override
+ public void remove(DataTreeModification<FlowCapableNodeConnector> removedDataObject) {
+ if (removedDataObject.getRootPath() != null && removedDataObject.getRootNode() != null) {
+ log.info("node connector {} deleted", removedDataObject.getRootNode().getIdentifier());
+ removeFlowCapableNodeConnector(removedDataObject);
+ }
+ }
+
+ @Override
+ public void update(DataTreeModification<FlowCapableNodeConnector> modifiedDataObject) {
+ if (modifiedDataObject.getRootPath() != null && modifiedDataObject.getRootNode() != null) {
+ log.info("node connector {} updated", modifiedDataObject.getRootNode().getIdentifier());
+ updateFlowCapableNodeConnector(modifiedDataObject);
+ }
+ }
+
+ private void addFlowCapableNodeConnector(DataTreeModification<FlowCapableNodeConnector> newDataObject) {
+ try {
+ FlowCapableNodeConnector data = newDataObject.getRootNode().getDataAfter();
+
+ String dpnFromNodeConnectorId = getDpnIdFromNodeConnector(newDataObject);
+
+ handleNodeConnectorAdded(dataBroker, dpnFromNodeConnectorId, data);
+ } catch (final Exception e) {
+ log.error("Add node connector failed !", e);
+ }
+ }
+
+ private void removeFlowCapableNodeConnector(DataTreeModification<FlowCapableNodeConnector> removedDataObject) {
+ try {
+ FlowCapableNodeConnector data = removedDataObject.getRootNode().getDataBefore();
+
+ String dpnFromNodeConnectorId = getDpnIdFromNodeConnector(removedDataObject);
+
+ handleNodeConnectorRemoved(dataBroker, dpnFromNodeConnectorId, data);
+ } catch (final Exception e) {
+ log.error("Remove node connector failed !", e);
+ }
+ }
+
+ private void updateFlowCapableNodeConnector(DataTreeModification<FlowCapableNodeConnector> modifiedDataObject) {
+ try {
+ FlowCapableNodeConnector original = modifiedDataObject.getRootNode().getDataBefore();
+ FlowCapableNodeConnector update = modifiedDataObject.getRootNode().getDataAfter();
+
+ String dpnFromNodeConnectorId = getDpnIdFromNodeConnector(modifiedDataObject);
+
+ handleNodeConnectorUpdated(dataBroker, dpnFromNodeConnectorId, original,update);
+ } catch (final Exception e) {
+ log.error("Update node connector failed !", e);
+ }
+ }
+
+ private String getDpnIdFromNodeConnector(DataTreeModification<FlowCapableNodeConnector> newDataObject) {
+ InstanceIdentifier<FlowCapableNodeConnector> key = newDataObject.getRootPath().getRootIdentifier();
+ NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
+
+ String dpnFromNodeConnectorId = getDpnFromNodeConnectorId(nodeConnectorId);
+ return dpnFromNodeConnectorId;
+ }
+
+ private static String getDpnFromNodeConnectorId(NodeConnectorId portId) {
+ /*
+ * NodeConnectorId is of form 'openflow:dpnid:portnum'
+ */
+ String[] split = portId.getValue().split(OF_URI_SEPARATOR);
+ return split[1];
+ }
+
+ private void handleNodeConnectorAdded(DataBroker dataBroker, String dpnId,
+ FlowCapableNodeConnector nodeConnector) {
+
+ WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+
+ InstanceIdentifier interfacePath = MefUtils.getDeviceInterfaceInstanceIdentifier(dpnId, nodeConnector.getName());
+ InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
+ interfaceBuilder.setPhy(new Identifier45(nodeConnector.getName()));
+ DataObject deviceInterface = interfaceBuilder.build();
+
+ tx.merge(LogicalDatastoreType.CONFIGURATION, interfacePath, deviceInterface, true);
+
+ InstanceIdentifier uniPath = MefUtils.getUniInstanceIdentifier(nodeConnector.getName());
+ UniBuilder uniBuilder = new UniBuilder();
+ uniBuilder.setUniId(new Identifier45(nodeConnector.getName()));
+
+ PhysicalLayersBuilder physicalLayersBuilder = new PhysicalLayersBuilder();
+ LinksBuilder linksBuilder = new LinksBuilder();
+ List<Link> links = new ArrayList();
+ LinkBuilder linkBuilder = new LinkBuilder();
+ linkBuilder.setDevice(new Identifier45(dpnId));
+ linkBuilder.setInterface(nodeConnector.getName());
+ links.add(linkBuilder.build());
+ linksBuilder.setLink(links);
+ physicalLayersBuilder.setLinks(linksBuilder.build());
+ uniBuilder.setPhysicalLayers(physicalLayersBuilder.build());
+ DataObject uni = uniBuilder.build();
+
+ tx.merge(LogicalDatastoreType.CONFIGURATION, uniPath, uni, true);
+ CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+
+ try {
+ futures.get();
+ } catch (InterruptedException | ExecutionException e) {
+ logger.error("Error writing to datastore (path, data) : ({}, {}), ({}, {})", interfacePath, deviceInterface,
+ uniPath, uni);
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+
+ private void handleNodeConnectorRemoved(DataBroker dataBroker, String dpnId,
+ FlowCapableNodeConnector nodeConnector) {
+
+ if (!handleRemovedNodeConnectors) {
+ return;
+ }
+
+ MdsalUtils.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
+ MefUtils.getDeviceInterfaceInstanceIdentifier(dpnId, nodeConnector.getName()));
+
+ MdsalUtils.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
+ MefUtils.getUniLinkInstanceIdentifier(nodeConnector.getName(), dpnId, nodeConnector.getName()));
+ }
+
+ private void handleNodeConnectorUpdated(DataBroker dataBroker, String dpnFromNodeConnectorId,
+ FlowCapableNodeConnector original, FlowCapableNodeConnector update) {
+
+ }
+}
<argument index="0" ref="dataBroker" />
</bean>
+ <bean class="org.opendaylight.unimgr.mef.netvirt.EvcUniListener">
+ <argument index="0" ref="dataBroker" />
+ </bean>
+
+ <bean class="org.opendaylight.unimgr.mef.netvirt.NodeConnectorListener">
+ <argument index="0" ref="dataBroker" />
+ </bean>
+
</blueprint>
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2016 Hewlett Packard Enterprise, Co. 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.unimgr.mef.netvirt;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.internal.stubbing.answers.Returns;
+import org.mockito.internal.stubbing.answers.ReturnsArgumentAt;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.OngoingStubbing;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.CeVlans;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.PhysicalLayers;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.PhysicalLayersBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.Links;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.LinksBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.Link;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.LinkBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.evc.unis.Uni;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.evc.unis.UniBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.evc.unis.uni.EvcUniCeVlans;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.evc.unis.uni.EvcUniCeVlansBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.evc.unis.uni.evc.uni.ce.vlans.EvcUniCeVlan;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.evc.unis.uni.evc.uni.ce.vlans.EvcUniCeVlanBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.Identifier45;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.VlanIdType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+
+import scala.collection.TraversableOnce.OnceCanBuildFrom;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({ LogicalDatastoreType.class, EvcUniListener.class })
+public class EvcUniListenerTest {
+
+ @Mock
+ private DataBroker dataBroker;
+ @Mock
+ private WriteTransaction transaction;
+ private EvcUniListener uniListener;
+
+ @Before
+ public void setUp() {
+ dataBroker = mock(DataBroker.class);
+ uniListener = new EvcUniListener(dataBroker);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testUniAdded() throws Exception {
+ String uniId = "MMPOP1-ce0-Slot0-Port1";
+ String deviceName = "ce0";
+ String interfaceName = "GigabitEthernet-0-1";
+ Uni uni = evcUni(uniId, deviceName, interfaceName);
+
+ prepareWriteTransaction();
+
+ Collection<DataTreeModification<Uni>> collection = new ArrayList();
+ collection.add(TestHelper.getUni(null, uni, ModificationType.WRITE));
+
+ prepareReadTransaction(uniId, deviceName, interfaceName);
+
+ uniListener.onDataTreeChanged(collection);
+
+ Interface trunkInterface = NetvirtUtils.createTrunkInterface(uniId, getParentIfaceName(deviceName, interfaceName));
+
+ verifyWriteInterface(trunkInterface);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testUniWithVlansAdded() throws Exception {
+ String uniId = "MMPOP1-ce0-Slot1-Port1";
+ String deviceName = "ce0";
+ String interfaceName = "GigabitEthernet-1-1";
+ Uni uni = evcUni(uniId, deviceName, interfaceName, 3, 4);
+ prepareWriteTransaction();
+ prepareReadTransaction(uniId, deviceName, interfaceName);
+
+ Collection<DataTreeModification<Uni>> collection = new ArrayList();
+ collection.add(TestHelper.getUni(null, uni, ModificationType.WRITE));
+ uniListener.onDataTreeChanged(collection);
+
+ Interface trunkInterface = NetvirtUtils.createTrunkInterface(uniId, getParentIfaceName(deviceName, interfaceName));
+ verifyWriteInterface(trunkInterface);
+ Interface vlan3Interface = NetvirtUtils.createTrunkMemberInterface(uniId + ".3", uniId, 3);
+ verifyWriteInterface(vlan3Interface);
+ Interface vlan4Interface = NetvirtUtils.createTrunkMemberInterface(uniId + ".4", uniId, 4);
+ verifyWriteInterface(vlan4Interface);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testUniRemoved() throws Exception {
+ String uniId = "MMPOP1-ce0-Slot0-Port1";
+ String deviceName = "ce0";
+ String interfaceName = "GigabitEthernet-0-1";
+ Uni uni = evcUni(uniId, deviceName, interfaceName);
+
+ prepareWriteTransaction();
+ prepareReadTransaction(uniId, deviceName, interfaceName);
+
+ Collection<DataTreeModification<Uni>> collection = new ArrayList();
+ collection.add(TestHelper.getUni(uni, null, ModificationType.DELETE));
+
+ uniListener.onDataTreeChanged(collection);
+
+ verifyDeleteInterface(uniId);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testUniWithVlansRemoved() throws Exception {
+ String uniId = "MMPOP1-ce0-Slot1-Port1";
+ String deviceName = "ce0";
+ String interfaceName = "GigabitEthernet-1-1";
+ Uni uni = evcUni(uniId, deviceName, interfaceName, 3, 4);
+ prepareWriteTransaction();
+ prepareReadTransaction(uniId, deviceName, interfaceName);
+
+ Collection<DataTreeModification<Uni>> collection = new ArrayList();
+ collection.add(TestHelper.getUni(uni, null, ModificationType.DELETE));
+
+ uniListener.onDataTreeChanged(collection);
+
+ verifyDeleteInterface(uniId);
+ verifyDeleteInterface(uniId + ".3");
+ verifyDeleteInterface(uniId + ".4");
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testUniInterfaceUpdated() throws Exception {
+ String uniId = "MMPOP1-ce0-Slot0-Port1";
+ String deviceName = "ce0";
+ String origInterfaceName = "GigabitEthernet-0-1";
+ String updatedInterfaceName = "GigabitEthernet-1-1";
+ Uni origUni = evcUni(uniId, deviceName, origInterfaceName);
+ Uni updatedUni = evcUni(uniId, deviceName, updatedInterfaceName);
+ prepareWriteTransaction();
+ prepareReadTransaction(uniId, deviceName, origInterfaceName, updatedInterfaceName);
+
+ Collection<DataTreeModification<Uni>> collection = new ArrayList();
+ collection.add(TestHelper.getUni(origUni, updatedUni, ModificationType.SUBTREE_MODIFIED));
+
+ uniListener.onDataTreeChanged(collection);
+
+ Interface trunkInterface = NetvirtUtils.createTrunkInterface(uniId, getParentIfaceName(deviceName, updatedInterfaceName));
+ verifyWriteInterface(trunkInterface);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testUniWithVlanInterfaceUpdated() throws Exception {
+ String uniId = "MMPOP1-ce0-Slot0-Port1";
+ String deviceName = "ce0";
+ String origInterfaceName = "GigabitEthernet-0-1";
+ String updatedInterfaceName = "GigabitEthernet-1-1";
+ Uni origUni = evcUni(uniId, deviceName, origInterfaceName, 3, 4);
+ Uni updatedUni = evcUni(uniId, deviceName, updatedInterfaceName, 3, 4);
+ prepareWriteTransaction();
+ prepareReadTransaction(uniId, deviceName, origInterfaceName, updatedInterfaceName);
+
+ Collection<DataTreeModification<Uni>> collection = new ArrayList();
+ collection.add(TestHelper.getUni(origUni, updatedUni, ModificationType.SUBTREE_MODIFIED));
+
+ uniListener.onDataTreeChanged(collection);
+
+ Interface trunkInterface = NetvirtUtils.createTrunkInterface(uniId, getParentIfaceName(deviceName, updatedInterfaceName));
+ verifyWriteInterface(trunkInterface);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testUniVlanUpdated() throws Exception {
+ String uniId = "MMPOP1-ce0-Slot0-Port1";
+ String deviceName = "ce0";
+ String interfaceName = "GigabitEthernet-1-1";
+ Uni origUni = evcUni(uniId, deviceName, interfaceName, 1, 2, 3);
+ Uni updatedUni = evcUni(uniId, deviceName, interfaceName, 2, 3, 4, 5);
+ prepareWriteTransaction();
+ prepareReadTransaction(uniId, deviceName, interfaceName);
+
+ Collection<DataTreeModification<Uni>> collection = new ArrayList();
+ collection.add(TestHelper.getUni(origUni, updatedUni, ModificationType.SUBTREE_MODIFIED));
+
+ uniListener.onDataTreeChanged(collection);
+
+ Interface vlan4Interface = NetvirtUtils.createTrunkMemberInterface(uniId + ".4", uniId, 4);
+ verifyWriteInterface(vlan4Interface);
+ Interface vlan5Interface = NetvirtUtils.createTrunkMemberInterface(uniId + ".5", uniId, 5);
+ verifyWriteInterface(vlan5Interface);
+ verifyDeleteInterface(uniId + ".1");
+
+ }
+
+ private void verifyWriteInterface(Interface iface) {
+ verify(transaction).put(LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier(iface.getName()), iface,
+ true);
+ verify(transaction).submit();
+ }
+
+ private void verifyDeleteInterface(String interfaceName) {
+ verify(transaction).delete(LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier(interfaceName));
+ verify(transaction).submit();
+ }
+
+ @SuppressWarnings("unchecked")
+ private void prepareWriteTransaction() {
+ transaction = mock(WriteTransaction.class);
+ when(dataBroker.newWriteOnlyTransaction()).thenReturn(transaction);
+ CheckedFuture<Void, TransactionCommitFailedException> future = mock(CheckedFuture.class);
+ when(transaction.submit()).thenReturn(future);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void prepareReadTransaction(String uniId, String deviceName, String... interfaceNames)
+ throws InterruptedException, ExecutionException {
+
+ ReadOnlyTransaction readTransaction = mock(ReadOnlyTransaction.class);
+ when(dataBroker.newReadOnlyTransaction()).thenReturn(readTransaction);
+
+ CheckedFuture<Optional<org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni>, ReadFailedException> future = mock(
+ CheckedFuture.class);
+
+ OngoingStubbing<Optional<org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni>> ongoingStubbing = when(future.get());
+
+ for (String interfaceName : interfaceNames)
+ {
+ ongoingStubbing = ongoingStubbing.thenReturn(Optional.of(uni(uniId, deviceName, interfaceName)));
+ }
+
+ when(readTransaction.read(LogicalDatastoreType.CONFIGURATION, MefUtils.getUniInstanceIdentifier(uniId)))
+ .thenReturn(future);
+ }
+
+ private InstanceIdentifier<Interface> interfaceInstanceIdentifier(String interfaceName) {
+ return InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName))
+ .build();
+ }
+
+ private org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni uni(
+ String uniId, String deviceName, String interfaceName) {
+ Link link = new LinkBuilder().setDevice(new Identifier45(deviceName)).setInterface(interfaceName).build();
+ Links links = new LinksBuilder().setLink(Arrays.asList(link)).build();
+ PhysicalLayers physicalLayers = new PhysicalLayersBuilder().setLinks(links).build();
+ org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.UniBuilder uniBuilder = new org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.UniBuilder()
+ .setUniId(new Identifier45(uniId)).setPhysicalLayers(physicalLayers);
+
+ return uniBuilder.build();
+ }
+
+ private Uni evcUni(String uniId, String deviceName, String interfaceName, long... vlans) {
+ UniBuilder uniBuilder = new UniBuilder().setUniId(new Identifier45(uniId));
+
+ if (vlans != null) {
+ List<EvcUniCeVlan> vlanList = new ArrayList<>();
+ for (long vlan : vlans) {
+ vlanList.add(ceVlan(vlan));
+ }
+ EvcUniCeVlans ceVlans = new EvcUniCeVlansBuilder().setEvcUniCeVlan(vlanList).build();
+ uniBuilder.setEvcUniCeVlans(ceVlans);
+ }
+
+ return uniBuilder.build();
+ }
+
+ private EvcUniCeVlan ceVlan(long vlanId) {
+ return new EvcUniCeVlanBuilder().setVid(new VlanIdType(vlanId)).build();
+ }
+
+ private String getParentIfaceName(String deviceName, String interfaceName) {
+ return deviceName + ":" + interfaceName;
+ }
+}
--- /dev/null
+package org.opendaylight.unimgr.mef.netvirt;
+
+import java.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.evc.unis.Uni;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+
+public class TestHelper {
+ public static final DataTreeModification<Uni> getUni(final Uni before, final Uni after, ModificationType modificationType) {
+ final DataTreeIdentifier<Uni> uniDataTreeIid = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, MefUtils.getEvcUniInstanceIdentifier("testUni"));
+ final DataObjectModification<Uni> uniDataTreeObj = new DataObjectModification<Uni>() {
+ @Override
+ public Collection<DataObjectModification<? extends DataObject>> getModifiedChildren() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public <C extends Identifiable<K> & ChildOf<? super Uni>, K extends Identifier<C>> DataObjectModification<C> getModifiedChildListItem(
+ Class<C> arg0, K arg1) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public <C extends ChildOf<? super Uni>> DataObjectModification<C> getModifiedChildContainer(Class<C> arg0) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public DataObjectModification<? extends DataObject> getModifiedChild(PathArgument arg0) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public <C extends Augmentation<Uni> & DataObject> DataObjectModification<C> getModifiedAugmentation(
+ Class<C> arg0) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public ModificationType getModificationType() {
+ return modificationType;
+ }
+ @Override
+ public PathArgument getIdentifier() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public Class<Uni> getDataType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public Uni getDataBefore() {
+ return before;
+ }
+ @Override
+ public Uni getDataAfter() {
+ return after;
+ }
+ };
+ DataTreeModification<Uni> uniUni = new DataTreeModification<Uni>() {
+ @Override
+ public DataTreeIdentifier<Uni> getRootPath() {
+ return uniDataTreeIid;
+ }
+ @Override
+ public DataObjectModification<Uni> getRootNode() {
+ return uniDataTreeObj;
+ }
+ };
+ return uniUni;
+ }
+}