<configfile finalname="etc/opendaylight/karaf/hwgw-default-config.xml">mvn:org.opendaylight.netvirt/hwgw/{{VERSION}}/xml/config</configfile>
</feature>
- <feature name='odl-netvirt-neutron' version='${project.version}' description='OpenDaylight :: netvirt :: Neutron Renderer'>
+ <feature name='odl-netvirt-neutron' version='${project.version}' description='OpenDaylight :: netvirt :: Neutron Renderer'>
+ <feature version='${controller.mdsal.version}'>odl-mdsal-broker</feature>
<feature version="${neutron.version}">odl-neutron-service</feature>
<feature version="${project.version}">odl-netvirt-ui</feature>
+ <bundle>mvn:org.opendaylight.netvirt/utils.mdsal-utils/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.ovsdb/utils.mdsal-utils/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.netvirt/neutron/{{VERSION}}</bundle>
<configfile finalname="etc/opendaylight/karaf/netvirt-neutron-default-config.xml">mvn:org.opendaylight.netvirt/neutron/{{VERSION}}/xml/config</configfile>
</feature>
<version>1.3.0-SNAPSHOT</version>
<packaging>bundle</packaging>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ org.opendaylight.yang.gen.v1.*,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.*,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.common.rev151227,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.devices.rev151227,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l2.networks.rev151227,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.port,
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
</project>
list other-config {
description "This is used to store information needed by the renderer(s). In general,
it might be used as a cookie to relate external objects or configuration with
- the given NetVirt objed. For example, we may store neutron logical port
+ the given NetVirt object. For example, we may store neutron logical port
information here so that the OVS southbound renderer can match up the port
reported by OVSDB with the Neutron port configured by Neutron.";
key config-key;
description "Initial revision of netvirt ports definition";
}
- import ietf-inet-types { prefix inet; }
- import ietf-yang-types { prefix yang; }
+ import ietf-inet-types { prefix inet; revision-date 2010-09-24;}
+ import ietf-yang-types { prefix yang; revision-date "2013-07-15";}
import netvirt-common { prefix "common"; }
description "port type router";
}
+ identity port-type-router-interface-distributed {
+ base port-type-base;
+ description "port type router interface distributed";
+ }
+
+ identity port-type-router-gateway {
+ base port-type-base;
+ description "port type router gateway";
+ }
+
+ identity port-type-dhcp {
+ base port-type-base;
+ description "port type dhcp";
+ }
+
+ identity port-type-floating-ip {
+ base port-type-base;
+ description "port type floatingip";
+ }
+
+ identity port-type-compute-nova {
+ base port-type-base;
+ description "port type compute nova";
+ }
+
typedef port-type {
type identityref {
base port-type-base;
}
@Override
- public String getInstanceName() {
- return "netvirt-neutron-default";
- }
+ public String getInstanceName() { return "netvirt-neutron"; }
@Override
public MavenUrlReference getFeatureRepo() {
<artifactId>model</artifactId>
<version>${neutron.model.version}</version>
</dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>utils.mdsal-utils</artifactId>
- <version>${project.version}</version>
- </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>utils.mdsal-utils</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netvirt-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-inet-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-yang-types-20130715</artifactId>
+ </dependency>
<!-- Testing Dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
-
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>mdsal-it-base</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
<capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</capability>
</required-capabilities>
<configuration>
-
<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:netvirt:neutron">prefix:netvirt-neutron</type>
- <name>netvirt-neutron-default</name>
+ <name>netvirt-neutron</name>
<broker>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
<name>binding-osgi-broker</name>
--- /dev/null
+/*
+ * Copyright (c) 2016 Red Hat, 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.netvirt.netvirt.renderers.neutron;
+
+import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.ImmutableBiMap.Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.common.rev151227.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.PortTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.PortTypeComputeNova;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.PortTypeDhcp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.PortTypeFloatingIp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.PortTypeRouterGateway;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.PortTypeRouterInterfaceDistributed;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.PortTypeRouter;
+
+/**
+ * A collection of configuration constants
+ */
+public final class Constants {
+
+ /*
+ * Port owner descriptions used by Openstack Neutron
+ */
+ public static final String OWNER_ROUTER_INTERFACE = "network:router_interface";
+ public static final String OWNER_ROUTER_INTERFACE_DISTRIBUTED = "network:router_interface_distributed";
+ public static final String OWNER_ROUTER_GATEWAY = "network:router_gateway";
+ public static final String OWNER_NETWORK_DHCP = "network:dhcp";
+ public static final String OWNER_FLOATING_IP = "network:floatingip";
+ public static final String OWNER_COMPUTE_NOVA = "compute:nova";
+
+
+ public static final ImmutableBiMap<String, Class<? extends PortTypeBase>> NETVIRT_NEUTRON_PORT_TYPE_MAP
+ = new ImmutableBiMap.Builder<String, Class<? extends PortTypeBase>>()
+ .put(OWNER_ROUTER_INTERFACE, PortTypeRouter.class)
+ .put(OWNER_ROUTER_INTERFACE_DISTRIBUTED, PortTypeRouterInterfaceDistributed.class)
+ .put(OWNER_ROUTER_GATEWAY, PortTypeRouterGateway.class)
+ .put(OWNER_NETWORK_DHCP, PortTypeDhcp.class)
+ .put(OWNER_FLOATING_IP, PortTypeFloatingIp.class)
+ .put(OWNER_COMPUTE_NOVA, PortTypeComputeNova.class)
+ .build();
+
+ /*
+ * Network type descriptions used by Openstack Neutron
+ */
+ public static final String NETWORK_TYPE_FLAT = "NetworkTypeFlat";
+ public static final String NETWORK_TYPE_VLAN = "NetworkTypeVlan";
+ public static final String NETWORK_TYPE_VXLAN = "NetworkTypeVxlan";
+ public static final String NETWORK_TYPE_GRE = "NetworkTypeGre";
+
+ public static final ImmutableBiMap<String, Class<? extends NetworkTypeBase>> NETVIRT_NEUTRON_NETWORK_TYPE_MAP
+ = new ImmutableBiMap.Builder<String, Class<? extends NetworkTypeBase>>()
+ .put(NETWORK_TYPE_FLAT, NetworkTypeFlat.class)
+ .put(NETWORK_TYPE_VLAN, NetworkTypeVlan.class)
+ .put(NETWORK_TYPE_VXLAN, NetworkTypeVxlan.class)
+ .put(NETWORK_TYPE_GRE, NetworkTypeGre.class)
+ .build();
+
+ public static final String NETVIRT_NEUTRON_OWNER_ENTITY_TYPE = "ovsdb-netvirt-neutron-provider";
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013, 2016 Red Hat, 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.netvirt.netvirt.renderers.neutron;
+
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * netvirt data processor
+ * org.opendaylight.ovsdb.netvirt
+ */
+public interface DataProcessor<D extends DataObject> {
+
+ /**
+ * Method removes DataObject which is identified by InstanceIdentifier.
+ *
+ * @param identifier - the whole path to DataObject
+ * @param del - DataObject for removing
+ */
+ void remove(InstanceIdentifier<D> identifier, D del);
+
+ /**
+ * Method updates the original DataObject to the update DataObject.
+ * Both are identified by same InstanceIdentifier.
+ *
+ * @param identifier - the whole path to DataObject
+ * @param original - original DataObject (for update)
+ * @param update - changed DataObject (contain updates)
+ */
+ void update(InstanceIdentifier<D> identifier, D original, D update);
+
+ /**
+ * Method adds the DataObject which is identified by InstanceIdentifier
+ * to device.
+ *
+ * @param identifier - the whole path to new DataObject
+ * @param add - new DataObject
+ */
+ void add(InstanceIdentifier<D> identifier, D add);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013, 2016 Red Hat, 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.netvirt.netvirt.renderers.neutron;
+
+import com.google.common.base.Preconditions;
+import java.util.Collection;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.*;
+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;
+
+/**
+ * Data-tree listener which delegates data processing to a {@link DataProcessor}.
+ */
+public class DelegatingDataTreeListener<T extends DataObject> implements AutoCloseable, ClusteredDataTreeChangeListener<T> {
+ private static final Logger LOG = LoggerFactory.getLogger(DelegatingDataTreeListener.class);
+ protected NeutronProvider provider;
+ protected DataBroker db;
+ private final ExecutorService executorService = Executors.newFixedThreadPool(1);
+ private final DataProcessor<T> dataProcessor;
+ private ListenerRegistration<DelegatingDataTreeListener<T>> listenerRegistration;
+
+ public DelegatingDataTreeListener(NeutronProvider provider, DataProcessor<T> dataProcessor,
+ DataBroker db, DataTreeIdentifier<T> treeId) {
+ this.provider = Preconditions.checkNotNull(provider, "provider can not be null!");
+ this.dataProcessor = Preconditions.checkNotNull(dataProcessor, "Data processor can not be null!");
+ registerListener(Preconditions.checkNotNull(db, "Data broker can not be null!"),
+ Preconditions.checkNotNull(treeId, "Tree identifier can not be null!"));
+ }
+
+ private void registerListener(final DataBroker db, DataTreeIdentifier<T> treeId) {
+ try {
+ LOG.info("Registering Data Change Listener for {}", getClass().getSimpleName());
+ this.db = db;
+ listenerRegistration = db.registerDataTreeChangeListener(treeId, this);
+ } catch (final Exception e) {
+ LOG.warn("{} DataChange listener registration fail!", getClass().getSimpleName(), e);
+ throw new IllegalStateException("DataTreeListener startup fail! System needs restart.", e);
+ }
+ }
+
+ private void processChanges(Collection<DataTreeModification<T>> changes) {
+ for (DataTreeModification<T> change : changes) {
+ final InstanceIdentifier<T> key = change.getRootPath().getRootIdentifier();
+ final DataObjectModification<T> mod = change.getRootNode();
+ switch (mod.getModificationType()) {
+ case DELETE:
+ dataProcessor.remove(key, mod.getDataBefore());
+ break;
+ case SUBTREE_MODIFIED:
+ dataProcessor.update(key, mod.getDataBefore(), mod.getDataAfter());
+ break;
+ case WRITE:
+ if (mod.getDataBefore() == null) {
+ dataProcessor.add(key, mod.getDataAfter());
+ } else {
+ dataProcessor.update(key, mod.getDataBefore(), mod.getDataAfter());
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Unhandled modification type " + mod.getModificationType());
+ }
+ }
+ }
+
+ @Override
+ public void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<T>> changes) {
+ Preconditions.checkNotNull(changes, "Changes may not be null!");
+ executorService.submit(new Runnable() {
+ @Override
+ public void run() {
+ processChanges(changes);
+ }
+ });
+ }
+
+ @Override
+ public void close() {
+ if (listenerRegistration != null) {
+ listenerRegistration.close();
+ listenerRegistration = null;
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Red Hat Communications 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.netvirt.netvirt.renderers.neutron;
+
+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.netvirt.devices.rev151227.Devices;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.devices.rev151227.devices.Device;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.devices.rev151227.devices.DeviceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l2.networks.rev151227.L2Networks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l2.networks.rev151227.l2.networks.L2Network;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l2.networks.rev151227.l2.networks.L2NetworkKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.ports.PortKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MdsalHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(MdsalHelper.class);
+ public static InstanceIdentifier<Port> createPortInstanceIdentifier(Uuid portUuid) {
+ return InstanceIdentifier.create(Ports.class)
+ .child(Port.class, new PortKey(portUuid));
+ }
+
+ public static InstanceIdentifier<L2Network> createL2NetworkInstanceIdentifier(Uuid networkUuid) {
+ return InstanceIdentifier.create(L2Networks.class)
+ .child(L2Network.class, new L2NetworkKey(networkUuid));
+ }
+
+ public static InstanceIdentifier<Device> createDeviceInstanceIdentifier(Uuid deviceUuid) {
+ return InstanceIdentifier.create(Devices.class)
+ .child(Device.class, new DeviceKey(deviceUuid));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Red Hat, 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.netvirt.netvirt.renderers.neutron;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks;
+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.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Data tree listener for Neutron Network
+ */
+public class NeutronNetworkChangeListener extends DelegatingDataTreeListener<Network> {
+ /**
+ * {@link NeutronNetworkChangeListener} constructor.
+ * @param provider Neutron Provider
+ * @param db MdSal {@link DataBroker}
+ */
+ public NeutronNetworkChangeListener(final NeutronProvider provider, final DataBroker db) {
+ super(provider, new NeutronNetworkDataProcessor(provider, db), db,
+ new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(Neutron.class).child(Networks.class).child(Network.class)));
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2016 Red Hat, 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.netvirt.netvirt.renderers.neutron;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.netvirt.utils.mdsal.utils.MdsalUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.common.rev151227.NetworkTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l2.networks.rev151227.l2.networks.L2Network;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l2.networks.rev151227.l2.networks.L2NetworkBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l2.networks.rev151227.l2.networks.L2NetworkKey;
+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.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Data processor for Neutron Network
+ */
+public class NeutronNetworkDataProcessor implements DataProcessor<Network> {
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronNetworkDataProcessor.class);
+ private final MdsalUtils mdsalUtils;
+ private final NeutronProvider provider;
+
+ /**
+ *
+ * @param provider - Neutron provider
+ * @param db - mdsal
+ */
+ public NeutronNetworkDataProcessor(final NeutronProvider provider, DataBroker db) {
+ this.provider = Preconditions.checkNotNull(provider, "Provider can not be null!");
+ mdsalUtils = new MdsalUtils(db);
+ }
+
+ /**
+ * Remove a netvirt network from mdsal
+ *
+ * @param identifier - the whole path to DataObject
+ * @param change - port to be removed
+ */
+ @Override
+ public void remove(final InstanceIdentifier<Network> identifier,
+ final Network change) {
+ Preconditions.checkNotNull(change, "Removed object can not be null!");
+ LOG.debug("Delete Neutron Network model data changes for key: {} delete: {}", identifier, change);
+
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l2.networks.rev151227.l2.networks.L2Network> networkIid =
+ MdsalHelper.createL2NetworkInstanceIdentifier(change.getUuid());
+
+ LOG.debug("Remove netvirt network uuid {} from mdsal", change.getUuid());
+ try {
+ boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, networkIid);
+ if (result) {
+ LOG.debug("Remove netvirt network from mdsal success. Result: {}", result);
+ } else {
+ LOG.warn("Remove nevtirt network failed. Result: {}", result);
+ }
+ } catch (Exception e) {
+ LOG.warn("Remove netvirt network failed: exception {}", e);
+ }
+ }
+
+ /**
+ * Update a netvirt network in mdsal
+ *
+ * @param identifier - the whole path to DataObject
+ * @param original - original DataObject (for update)
+ * @param change - network to be updated
+ */
+
+ @Override
+ public void update(final InstanceIdentifier<Network> identifier,
+ final Network original, final Network change) {
+ Preconditions.checkNotNull(original, "Updated original object can not be null!");
+ Preconditions.checkNotNull(change, "Updated change object can not be null!");
+ LOG.debug("Update Neutron Network model data changes for key: {} delete: {}", identifier, change);
+ remove(identifier, original);
+ add(identifier, change);
+ }
+
+ private void addExtensions(L2NetworkBuilder l2NetworkBuilder, Network network)
+ {
+ NetworkProviderExtension providerExtension = network.getAugmentation(NetworkProviderExtension.class);
+ if (providerExtension != null) {
+ if (providerExtension.getSegmentationId() != null) {
+ l2NetworkBuilder.setSegmentationId(providerExtension.getSegmentationId());
+ }
+
+ if (Constants.NETVIRT_NEUTRON_NETWORK_TYPE_MAP.get(providerExtension.getNetworkType().getSimpleName()) != null) {
+ l2NetworkBuilder.setNetworkType(Constants.NETVIRT_NEUTRON_NETWORK_TYPE_MAP.get(providerExtension.getNetworkType().getSimpleName()));
+ } else {
+ LOG.warn("Neutron Network Type not supported.. using Flat for network {}", network);
+ l2NetworkBuilder.setNetworkType(NetworkTypeBase.class);
+ }
+ }
+ }
+
+ /**
+ * Add a netvirt Network to mdsal
+ *
+ * @param identifier - the whole path to new DataObject
+ * @param change - port to be added
+ */
+ @Override
+ public void add(final InstanceIdentifier<Network> identifier,
+ final Network change) {
+ Preconditions.checkNotNull(change, "Added object can not be null!");
+ LOG.debug("Create Neutron Network model data changes for identifier: {} change: {}", identifier, change);
+ L2NetworkBuilder l2NetworkBuilder = new L2NetworkBuilder();
+
+ InstanceIdentifier<L2Network> networkIid = MdsalHelper.createL2NetworkInstanceIdentifier(change.getUuid());
+ addExtensions(l2NetworkBuilder, change);
+
+ if (change.isAdminStateUp() != null) {
+ l2NetworkBuilder.setAdminStateUp(change.isAdminStateUp());
+ }
+ if (change.getName() != null) {
+ l2NetworkBuilder.setName(change.getName());
+ }
+ if (change.isShared() != null) {
+ l2NetworkBuilder.setShared(change.isShared());
+ }
+ if (change.getStatus() != null) {
+ l2NetworkBuilder.setStatus(change.getStatus());
+ }
+ if (change.getTenantId() != null) {
+ // TODO
+ //l2NetworkBuilder.setTenantId(change.getTenantId());
+ }
+ if (change.getUuid() != null) {
+ l2NetworkBuilder.setUuid(change.getUuid());
+ l2NetworkBuilder.setKey(new L2NetworkKey(change.getUuid()));
+ }
+
+ LOG.debug("Add Netvirt network {} to mdsal", l2NetworkBuilder.build().toString());
+ try {
+ boolean result = mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, networkIid, l2NetworkBuilder.build());
+ if (result) {
+ LOG.debug("createNetwork:addToMdSal success. Result: {}", result);
+ } else {
+ LOG.warn("createNetwork:addToMdSal failed. Result: {}", result);
+ }
+ } catch (Exception e) {
+ LOG.warn("create Netvirt Network : addToMdSal exception {}", e);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Red Hat, 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.netvirt.netvirt.renderers.neutron;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Data tree listener for Neutron Port
+ */
+public class NeutronPortChangeListener extends DelegatingDataTreeListener<Port> {
+ /**
+ * {@link NeutronPortChangeListener} constructor.
+ * @param provider Neutron Provider
+ * @param db MdSal {@link DataBroker}
+ */
+ public NeutronPortChangeListener(final NeutronProvider provider, final DataBroker db) {
+ super(provider, new NeutronPortDataProcessor(provider, db), db,
+ new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class)));
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2015, 2016 Red Hat, 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.netvirt.netvirt.renderers.neutron;
+
+import com.google.common.base.Preconditions;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.netvirt.utils.mdsal.utils.MdsalUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+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.netvirt.ports.rev151227.PortTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.port.EndPoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.port.EndPointsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.ports.PortBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.ports.PortKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Data processor for Neutron Port
+ */
+public class NeutronPortDataProcessor implements DataProcessor<Port> {
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronPortDataProcessor.class);
+ private MdsalUtils mdsalUtils;
+ private final NeutronProvider provider;
+
+ /**
+ *
+ * @param provider - Neutron provider
+ * @param db - mdsal
+ */
+ public NeutronPortDataProcessor(final NeutronProvider provider, DataBroker db) {
+ this.provider = Preconditions.checkNotNull(provider, "Provider can not be null!");
+ mdsalUtils = new MdsalUtils(db);
+ }
+
+ /**
+ * Remove a netvirt from mdsal
+ *
+ * @param identifier - the whole path to DataObject
+ * @param change - port to be removed
+ */
+ @Override
+ public void remove(final InstanceIdentifier<Port> identifier,
+ final Port change) {
+ Preconditions.checkNotNull(change, "Removed object can not be null!");
+ LOG.debug("Delete Neutron Port model data changes for key: {} delete: {}", identifier, change);
+
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.ports.Port> portIid =
+ MdsalHelper.createPortInstanceIdentifier(change.getUuid());
+
+ LOG.debug("Remove netvirt Port uuid {} from mdsal", change.getUuid());
+ try {
+ boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, portIid);
+ if (result) {
+ LOG.debug("Remove netvirt port from mdsal success. Result: {}", result);
+ } else {
+ LOG.warn("Remove nevtirt port failed. Result: {}", result);
+ }
+ } catch (Exception e) {
+ LOG.warn("Remove netvirt port failed: exception {}", e);
+ }
+ }
+
+ /**
+ * Update a netvirt port in mdsal
+ *
+ * @param identifier - the whole path to DataObject
+ * @param original - original DataObject (for update)
+ * @param change - port to be updated
+ */
+
+ @Override
+ public void update(final InstanceIdentifier<Port> identifier,
+ final Port original, final Port change) {
+ Preconditions.checkNotNull(original, "Updated original object can not be null!");
+ Preconditions.checkNotNull(original, "Updated update object can not be null!");
+ remove(identifier, original);
+ LOG.debug("Update Neutron Port model data changes for key: {} delete: {}", identifier, change);
+ remove(identifier, original);
+ add(identifier, change);
+ }
+
+ /**
+ * Add a netvirt port to mdsal
+ *
+ * @param identifier - the whole path to new DataObject
+ * @param change - port to be added
+ */
+ @Override
+ public void add(final InstanceIdentifier<Port> identifier,
+ final Port change) {
+ Preconditions.checkNotNull(change, "Added object can not be null!");
+ LOG.debug("Create Neutron Port model data changes for identifier: {} change: {}", identifier, change);
+ PortBuilder portBuilder = new PortBuilder();
+
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.ports.Port> portIid =
+ MdsalHelper.createPortInstanceIdentifier(change.getUuid());
+
+ portBuilder.setStatus(change.getStatus());
+ if (change.isAdminStateUp() != null) {
+ portBuilder.setAdminStateUp(change.isAdminStateUp());
+ }
+ portBuilder.setName(change.getName());
+
+ // TODO
+ // Some neutron fields to consider for netvirt model
+ // tenant-id
+ // network-id
+ // extra-dhcp-opts list
+ // fixed-ips list
+ // security groups
+ // vif-details list
+ // vif-type
+ // vnic-type
+ // profile
+ // port-security-enabled
+ // host-id
+
+ if (Constants.NETVIRT_NEUTRON_PORT_TYPE_MAP.get(change.getDeviceOwner()) != null) {
+ portBuilder.setPortType(Constants.NETVIRT_NEUTRON_PORT_TYPE_MAP.get(change.getDeviceOwner()));
+ } else {
+ LOG.warn("Unsupported device owner for neutron port identifier: {} port: {}", identifier, change);
+ portBuilder.setPortType(PortTypeBase.class);
+ }
+
+ // TODO - set parent when applicable
+ //portB.setParent(change.getParent());
+
+ portBuilder.setDeviceUuid(new Uuid(change.getDeviceId()));
+ portBuilder.setDeviceLocatorUuid(change.getNetworkId());
+ portBuilder.setKey(new PortKey(change.getUuid()));
+
+ if (change.getFixedIps() != null) {
+ List<IpAddress> ipAddressList = new ArrayList<>();
+ for (FixedIps ips : change.getFixedIps()) {
+ ipAddressList.add(new IpAddress(ips.getIpAddress().getValue()));
+ }
+ EndPoints endPoint = new EndPointsBuilder()
+ .setMacaddr(new MacAddress(change.getMacAddress()))
+ .setIpaddrs(ipAddressList)
+ .build();
+ portBuilder.setEndPoints(Collections.singletonList(endPoint));
+ }
+
+ LOG.debug("Add Netvirt Port {} to mdsal", portBuilder.build().toString());
+ try {
+ boolean result = mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, portIid, portBuilder.build());
+ if (result) {
+ LOG.debug("createPort:addToMdSal success. Result: {}", result);
+ } else {
+ LOG.warn("createPort:addToMdSal failed. Result: {}", result);
+ }
+ } catch (Exception e) {
+ LOG.warn("create Netvirt Port : addToMdSal exception {}", e);
+ }
+ }
+}
*/
package org.opendaylight.netvirt.netvirt.renderers.neutron;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
-import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import com.google.common.base.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipState;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.osgi.framework.BundleContext;
public class NeutronProvider implements BindingAwareProvider, AutoCloseable {
-
private static final Logger LOG = LoggerFactory.getLogger(NeutronProvider.class);
+ private BundleContext bundleContext = null;
+ private static DataBroker dataBroker = null;
+ private static EntityOwnershipService entityOwnershipService;
+ private static final Entity ownerInstanceEntity = new Entity(Constants.NETVIRT_NEUTRON_OWNER_ENTITY_TYPE,
+ Constants.NETVIRT_NEUTRON_OWNER_ENTITY_TYPE);
+ private NeutronPortChangeListener neutronPortChangeListener;
+ private NeutronNetworkChangeListener neutronNetworkChangeListener;
+
+ public NeutronProvider(BundleContext bundleContext, EntityOwnershipService eos) {
+ LOG.info("Netvirt NeutronProvider: bundleContext: {}", bundleContext);
+ this.bundleContext = bundleContext;
+ entityOwnershipService = eos;
+ }
+
+ public NeutronProvider() {
+ LOG.info("Netvirt NeutronProvider created");
+ }
+
+ public static boolean isMasterProviderInstance() {
+ if (entityOwnershipService != null) {
+ Optional<EntityOwnershipState> state = entityOwnershipService.getOwnershipState(ownerInstanceEntity);
+ return state.isPresent() && state.get().isOwner();
+ }
+ return false;
+ }
+
@Override
- public void onSessionInitiated(ProviderContext session) {
- LOG.info("NeutronProvider Session Initiated");
+ public void onSessionInitiated(ProviderContext providerContext) {
+ dataBroker = providerContext.getSALService(DataBroker.class);
+ LOG.info("Netvirt NeutronProvider: onSessionInitiated dataBroker: {}", dataBroker);
+
+ neutronPortChangeListener = new NeutronPortChangeListener(this, dataBroker);
+ neutronNetworkChangeListener = new NeutronNetworkChangeListener(this, dataBroker);
}
@Override
public void close() throws Exception {
- LOG.info("NeutronProvider Closed");
+ if (neutronPortChangeListener != null) {
+ neutronPortChangeListener.close();
+ }
+ if (neutronNetworkChangeListener != null) {
+ neutronNetworkChangeListener.close();
+ }
+ LOG.info("Netvirt NeutronProvider Closed");
}
}
import config { prefix config; revision-date 2013-04-05; }
import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
+ import opendaylight-entity-ownership-service {prefix eos; revision-date 2015-08-10;}
description
"Service definition for NetVirt Neutron renderer";
--- /dev/null
+package org.opendaylight.netvirt.netvirt.renderers.neutron;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+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.neutron.ports.rev150712.port.attributes.FixedIps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
+import com.google.common.base.Optional;
+
+/**
+ * Unit test for {@link NeutronPortDataProcessor}
+ */
+public class NeutronPortDataProcessorTest extends AbstractDataBrokerTest {
+ private static final Uuid portId = new Uuid("aaaaaaaa-bbbb-cccc-dddd-123456789012");
+ private static final Uuid portId2 = new Uuid("11111111-2222-3333-4444-555555555555");
+ private static final Uuid portId3 = new Uuid("33333333-3333-3333-3333-333333333333");
+ ProviderContext session;
+ NeutronPortDataProcessor neutronPortDataProcessor;
+ boolean initialized = false;
+
+ private org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.ports.Port readFromMdSal(Uuid uuid) throws Exception {
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.ports.Port> portIid =
+ MdsalHelper.createPortInstanceIdentifier(uuid);
+
+ org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.ports.Port netvirtPort = null;
+ Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.ports.Port> data =
+ getDataBroker()
+ .newReadOnlyTransaction()
+ .read(LogicalDatastoreType.CONFIGURATION, portIid)
+ .get();
+ return data.orNull();
+ }
+
+ private Port createNeutronPort(Uuid uuid, String name, boolean adminStateUp ) throws Exception {
+ String addr = "100.100.100.100";
+ List<FixedIps> ips = new ArrayList<>();
+ FixedIpsBuilder fixedIpsBuilder = new FixedIpsBuilder()
+ .setIpAddress(new IpAddress(addr.toCharArray()))
+ .setSubnetId(new Uuid("12345678-1234-1234-1234-222222222222"));
+ ips.add(fixedIpsBuilder.build());
+
+
+ return (new PortBuilder()
+ .setStatus("Up")
+ .setAdminStateUp(adminStateUp)
+ .setName(name)
+ .setDeviceOwner("compute:nova")
+ .setDeviceId("12345678-1234-1234-1234-123456789012")
+ .setUuid(uuid)
+ .setMacAddress("00:00:01:02:03:04")
+ .setFixedIps(ips)
+ .build());
+ }
+
+ private void initialize() {
+ if (!initialized) {
+ session = mock(ProviderContext.class);
+ when(session.getSALService(DataBroker.class)).thenReturn(getDataBroker());
+ neutronPortDataProcessor = new NeutronPortDataProcessor(new NeutronProvider(), session.getSALService(DataBroker.class));
+ initialized = true;
+ }
+ }
+
+ @Test
+ public void testRemove() throws Exception {
+ //Do some setup and initialization
+ initialize();
+
+ //Create Neutron port
+ Port neutronPort = createNeutronPort(portId2, "testRemovePort", true);
+ InstanceIdentifier<Port> instanceIdentifier = InstanceIdentifier.create(Ports.class).child(Port.class);
+
+ //Add the Neutron port.This should result in a Netvirt port being created, and added to mdsal.
+ neutronPortDataProcessor.add(instanceIdentifier, neutronPort);
+
+ //Verify the Netvirt port was added to mdsal
+ assertNotNull(readFromMdSal(neutronPort.getUuid()));
+
+ //Delete the Netvirt port that was just put into mdsal, and verify that it was removed from mdsal.
+ neutronPortDataProcessor.remove(instanceIdentifier, neutronPort);
+ assertNull(readFromMdSal(neutronPort.getUuid()));
+ }
+
+ @Test
+ public void testUpdate() throws Exception {
+ //Do some setup and initialization
+ initialize();
+
+ //Create Neutron port
+ Port neutronPort = createNeutronPort(portId3, "testUpdatePort", true);
+ InstanceIdentifier<Port> instanceIdentifier = InstanceIdentifier.create(Ports.class).child(Port.class);
+
+ //Add the Neutron port. This should result in a Netvirt port being created, and added to mdsal.
+ neutronPortDataProcessor.add(instanceIdentifier, neutronPort);
+
+ //Verify the Netvirt port was added to mdsal
+ assertNotNull(readFromMdSal(neutronPort.getUuid()));
+
+ //Create a second Neutron port, with different values for "name" and "AdminStateUp"
+ Port neutronPort1 = createNeutronPort(portId3, "portUpdatedTest", false);
+
+ //Update the Neutron port. This should result in the netvirt port in mdsal being updated, with a new name and
+ //admin state
+ neutronPortDataProcessor.update(instanceIdentifier, neutronPort, neutronPort1);
+
+ //Verify that the netvirt port was updated in mdsal
+ org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.ports.Port netvirtPort = readFromMdSal(neutronPort1.getUuid());
+ assertNotNull(netvirtPort);
+ assertEquals("Error, name not updated", netvirtPort.getName(), neutronPort1.getName());
+ assertEquals("Error, admin state not updated", netvirtPort.isAdminStateUp(), neutronPort1.isAdminStateUp());
+ }
+
+ @Test
+ public void testAdd() throws Exception {
+ //Do some setup and initialization
+ initialize();
+
+ //Create Neutron port.
+ Port neutronPort = createNeutronPort(portId, "testAddPort", true);
+ InstanceIdentifier<Port> instanceIdentifier = InstanceIdentifier.create(Ports.class).child(Port.class);
+
+ //Add the Neutron port.This should result in a Netvirt port being created, and added to mdsal.
+ neutronPortDataProcessor.add(instanceIdentifier, neutronPort);
+
+ //Verify that the Netvirt port was added to mdsal, and that the contents of the Netvirt port are correct.
+ org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ports.rev151227.ports.Port netvirtPort = readFromMdSal(neutronPort.getUuid());
+ assertNotNull(netvirtPort);
+ assertEquals("Error, status not correct", netvirtPort.getStatus(), neutronPort.getStatus());
+ assertEquals("Error, name not correct", netvirtPort.getName(), neutronPort.getName());
+ assertEquals("Error, admin state not correct", netvirtPort.isAdminStateUp(), neutronPort.isAdminStateUp());
+ assertEquals("Error, dev id is not correct", netvirtPort.getDeviceUuid().getValue(), neutronPort.getDeviceId());
+ assertEquals("Error, uuid is not correct", netvirtPort.getUuid().getValue(), neutronPort.getUuid().getValue());
+ }
+
+}
\ No newline at end of file
package org.opendaylight.netvirt.netvirt.renderers.neutron;
import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import static org.mockito.Mockito.mock;
public class NeutronProviderTest {
@Test
public void testOnSessionInitiated() {
+
NeutronProvider provider = new NeutronProvider();
// ensure no exceptions
// currently this method is empty
- provider.onSessionInitiated(mock(BindingAwareBroker.ProviderContext.class));
+
+ //TODO
+ //provider.onSessionInitiated(mock(BindingAwareBroker.ProviderContext.class));
}
@Test
<module>hwgw</module>
<module>neutron</module>
</modules>
+
<!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
<build>
<plugins>