From da1a963c78ad216517b5f15a0802292d9ba05b75 Mon Sep 17 00:00:00 2001 From: Vishal Thapar Date: Wed, 8 Apr 2015 19:49:25 +0530 Subject: [PATCH] Initial code to handle changes to DS 1. Added InterfaceManager class to handle Data Change Notifications. 2. Added META-INF to .gitignore 3. Modified odl-interfaces.yang to use augment-identifiers 4. Added interfacemgr-api to features Change-Id: I787c49267476175b55b154e1bb526777e425f84a Signed-off-by: Vishal Thapar --- .gitignore | 1 + features/pom.xml | 5 + features/src/main/features/features.xml | 1 + interfacemgr/interfacemgr-api/pom.xml | 5 + .../src/main/yang/odl-interface.yang | 273 +++++++++--------- interfacemgr/interfacemgr-impl/pom.xml | 18 ++ .../interfacemgr/InterfaceManager.java | 194 +++++++++++++ .../interfacemgr/InterfacemgrProvider.java | 10 + 8 files changed, 378 insertions(+), 129 deletions(-) create mode 100644 interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfaceManager.java diff --git a/.gitignore b/.gitignore index 76a4e1efca..bbbe4f26f3 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ yang-gen-config yang-gen-sal classes maven-metadata-local.xml +META-INF diff --git a/features/pom.xml b/features/pom.xml index 93656e5f16..791a11a07f 100644 --- a/features/pom.xml +++ b/features/pom.xml @@ -93,6 +93,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL config xml + + ${project.groupId} + interfacemgr-api + ${interfacemgr.version} + ${project.groupId} vpnmanager-api diff --git a/features/src/main/features/features.xml b/features/src/main/features/features.xml index cf0d91c7cf..390fbaa6c0 100644 --- a/features/src/main/features/features.xml +++ b/features/src/main/features/features.xml @@ -19,6 +19,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html odl-flow-model mvn:org.opendaylight.vpnservice/model-bgp/2013.07.15.7-SNAPSHOT mvn:org.opendaylight.vpnservice/vpnmanager-api/${project.version} + mvn:org.opendaylight.vpnservice/interfacemgr-api/${interfacemgr.version} mvn:org.opendaylight.vpnservice/bgpmanager-api/${project.version} diff --git a/interfacemgr/interfacemgr-api/pom.xml b/interfacemgr/interfacemgr-api/pom.xml index 955f3c2e48..f1dce5500d 100644 --- a/interfacemgr/interfacemgr-api/pom.xml +++ b/interfacemgr/interfacemgr-api/pom.xml @@ -40,6 +40,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html yang-common ${yangtools.version} + + org.opendaylight.yangtools.model + yang-ext + ${yang.ext.version} + org.opendaylight.yangtools.model ietf-inet-types diff --git a/interfacemgr/interfacemgr-api/src/main/yang/odl-interface.yang b/interfacemgr/interfacemgr-api/src/main/yang/odl-interface.yang index 591f31fc18..f1483dba2f 100644 --- a/interfacemgr/interfacemgr-api/src/main/yang/odl-interface.yang +++ b/interfacemgr/interfacemgr-api/src/main/yang/odl-interface.yang @@ -1,144 +1,159 @@ module odl-interface { - namespace "urn:opendaylight:vpnservice:interfacemgr"; + namespace "urn:opendaylight:vpnservice:interfacemgr"; - prefix "odlif"; + prefix "odlif"; - import ietf-interfaces { - prefix if; - } - import iana-if-type { - prefix ianaift; - } + import ietf-interfaces { + prefix if; + } + + import yang-ext { + prefix ext; + } + + import iana-if-type { + prefix ianaift; + } + + import ietf-inet-types { + prefix inet; + } - import ietf-inet-types { - prefix inet; - } - revision "2015-03-31" { + import opendaylight-inventory { + prefix inv; revision-date "2013-08-19"; + } + + revision "2015-03-31" { description "ODL Interface Manager Module"; } - identity stacked-vlan { - base if:interface-type; - reference - "Q-in-Q interface"; - } - - identity l3tunnel { - base if:interface-type; - reference - "l3 tunnel interface"; - } - - identity mpls { - base if:interface-type; - reference - "MPLS interface"; - } - - /* l3Tunnel (GRE, VxLAN) logical port */ - identity tunnel-type-base { - description "Base identity for all tunnel-types"; - } - - identity tunnel-type-vxlan { - description "Tunnel type for vxlan tunnels"; - base tunnel-type-base; - } - - identity tunnel-type-gre { - description "Tunnel type for gre tunnels"; - base tunnel-type-base; - } - - /* base/common properties */ - augment "/if:interfaces/if:interface" { - leaf of-port-id { - type string; - description "can be a physical switch port or virtual switch port e.g. neutron port"; - } - leaf tenant-id { - type string; - description "Tenant that owns particular interface"; - } /* optional */ - leaf base-interface { - type if:interface-ref; - description "some interfaces need a reference to parent interface "; - } - } - - /* interface type specific properties */ - - /* VLAN logical port */ - augment "/if:interfaces/if:interface" { - when "if:type = 'ianaift:l2vlan'"; - leaf vlan-id { - type uint16 { - range "1..4094"; - } - must "../base-interface" { - description - "If a vlan-id is defined, a base-interface must - be specified."; - } - } - } - - /* Q-in-Q logical port */ - augment "/if:interfaces/if:interface" { - when "if:type = 'stacked_vlan'"; - leaf stacked_vlan-id { - type uint16 { - range "1..4094"; - } - must "../base-interface" { - description - "If a vlan-id is defined, a base-interface must - be specified."; - } - } - } - - augment "/if:interfaces/if:interface" { - when "if:type = 'ianaift:l3tunnel'"; - - leaf tunnel-type { + identity stacked-vlan { + base if:interface-type; + reference + "Q-in-Q interface"; + } + + identity l3tunnel { + base if:interface-type; + reference + "l3 tunnel interface"; + } + + identity mpls { + base if:interface-type; + reference + "MPLS interface"; + } + + /* l3Tunnel (GRE, VxLAN) logical port */ + identity tunnel-type-base { + description "Base identity for all tunnel-types"; + } + + identity tunnel-type-vxlan { + description "Tunnel type for vxlan tunnels"; + base tunnel-type-base; + } + + identity tunnel-type-gre { + description "Tunnel type for gre tunnels"; + base tunnel-type-base; + } + + /* base/common properties */ + augment "/if:interfaces/if:interface" { + ext:augment-identifier "base-ids"; + leaf of-port-id { + type inv:node-connector-id; + description "can be a physical switch port or virtual switch port e.g. neutron port"; + } + leaf tenant-id { + type string; + description "Tenant that owns particular interface"; + } /* optional */ + leaf base-interface { + type if:interface-ref; + description "some interfaces need a reference to parent interface "; + } + } + + /* interface type specific properties */ + + /* VLAN logical port */ + augment "/if:interfaces/if:interface" { + ext:augment-identifier "if-l2vlan"; + when "if:type = 'ianaift:l2vlan'"; + leaf vlan-id { + type uint16 { + range "1..4094"; + } + must "../base-interface" { + description + "If a vlan-id is defined, a base-interface must + be specified."; + } + } + } + + /* Q-in-Q logical port */ + augment "/if:interfaces/if:interface" { + ext:augment-identifier "if-stacked-vlan"; + when "if:type = 'stacked_vlan'"; + leaf stacked_vlan-id { + type uint16 { + range "1..4094"; + } + must "../base-interface" { + description + "If a vlan-id is defined, a base-interface must + be specified."; + } + } + } + + augment "/if:interfaces/if:interface" { + ext:augment-identifier "if-l3tunnel"; + when "if:type = 'ianaift:l3tunnel'"; + + leaf tunnel-type { type identityref { base tunnel-type-base; } } - leaf local-ip { - type inet:ip-address; - description "Local Endpoint IP address"; - } - - leaf remote-ip { - type inet:ip-address; - description "Remote Endpoint IP address"; - } - - leaf gateway-ip { - type inet:ip-address; - description "gateway IP address"; - } - - } - - - /* MPLS logical port */ - augment "/if:interfaces/if:interface" { - when "if:type = 'mpls'"; - leaf-list labelStack { - type uint32 { - range "15..1048575"; - } - } - leaf numLabels{ - type uint8 { - range "1..7"; - } - } - } + leaf local-ip { + type inet:ip-address; + description "Local Endpoint IP address"; + } + + leaf remote-ip { + type inet:ip-address; + description "Remote Endpoint IP address"; + } + + leaf gateway-ip { + type inet:ip-address; + description "gateway IP address"; + } + + } + + + /* MPLS logical port */ + augment "/if:interfaces/if:interface" { + ext:augment-identifier "if-mpls"; + when "if:type = 'mpls'"; + leaf-list labelStack { + type uint32 { + range "15..1048575"; + } + } + leaf numLabels{ + type uint8 { + range "1..7"; + } + } + } } diff --git a/interfacemgr/interfacemgr-impl/pom.xml b/interfacemgr/interfacemgr-impl/pom.xml index 52ad8bfb22..9c90c12700 100644 --- a/interfacemgr/interfacemgr-impl/pom.xml +++ b/interfacemgr/interfacemgr-impl/pom.xml @@ -21,6 +21,24 @@ and is available at http://www.eclipse.org/legal/epl-v10.html 0.0.1-SNAPSHOT bundle + + ${project.groupId} + interfacemgr-api + ${project.version} + + + org.opendaylight.controller.model + model-flow-service + + + org.opendaylight.yangtools.model + ietf-interfaces + + + org.opendaylight.vpnservice + vpnmanager-impl + 1.0-SNAPSHOT + junit diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfaceManager.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfaceManager.java new file mode 100644 index 0000000000..b8920bab7b --- /dev/null +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfaceManager.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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.vpnservice.interfacemgr; + +import com.google.common.util.concurrent.FutureCallback; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.BaseIds; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; +import org.opendaylight.vpnservice.AbstractDataChangeListener; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; +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.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.google.common.base.Optional; + +public class InterfaceManager extends AbstractDataChangeListener implements AutoCloseable{ + private static final Logger LOG = LoggerFactory.getLogger(InterfaceManager.class); + private ListenerRegistration listenerRegistration; + private final DataBroker broker; + + private static final FutureCallback DEFAULT_CALLBACK = + new FutureCallback() { + public void onSuccess(Void result) { + LOG.debug("Success in Datastore write operation"); + } + + public void onFailure(Throwable error) { + LOG.error("Error in Datastore write operation", error); + }; + }; + + public InterfaceManager(final DataBroker db) { + super(Interface.class); + broker = db; + registerListener(db); + } + + @Override + public void close() throws Exception { + if (listenerRegistration != null) { + try { + listenerRegistration.close(); + } catch (final Exception e) { + LOG.error("Error when cleaning up DataChangeListener.", e); + } + listenerRegistration = null; + } + LOG.info("Interface Manager Closed"); + } + + private void registerListener(final DataBroker db) { + try { + listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, + getWildCardPath(), InterfaceManager.this, DataChangeScope.SUBTREE); + } catch (final Exception e) { + LOG.error("InterfaceManager DataChange listener registration fail!", e); + throw new IllegalStateException("InterfaceManager registration Listener failed.", e); + } + } + + @Override + protected void add(final InstanceIdentifier identifier, + final Interface imgrInterface) { + LOG.trace("key: " + identifier + ", value=" + imgrInterface ); + addInterface(identifier, imgrInterface); + } + + private InstanceIdentifier buildId(final InstanceIdentifier identifier) { + //TODO Make this generic and move to AbstractDataChangeListener or Utils. + final InterfaceKey key = identifier.firstKeyOf(Interface.class, InterfaceKey.class); + String interfaceName = key.getName(); + InstanceIdentifierBuilder idBuilder = + InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName)); + InstanceIdentifier id = idBuilder.build(); + return id; + } + + private void addInterface(final InstanceIdentifier identifier, + final Interface imgrInterface) { + InstanceIdentifier id = buildId(identifier); + Optional port = read(LogicalDatastoreType.CONFIGURATION, id); + if(port.isPresent()) { + Interface interf = port.get(); + NodeConnector nodeConn = getNodeConnectorFromInterface(interf); + updateInterfaceState(identifier, imgrInterface, interf); + /* TODO: + * 1. Get interface-id from id manager + * 2. Update interface-state with following: + * admin-status = set to enable value + * oper-status = Down [?] + * if-index = interface-id + * + * FIXME: + * 1. Get operational data from node-connector-id? + * + */ + } + } + + private void updateInterfaceState(InstanceIdentifier identifier, Interface imgrInterface, + Interface interf) { + // TODO Update InterfaceState + + } + + private NodeConnector getNodeConnectorFromInterface(Interface interf) { + NodeConnectorId ncId = interf.getAugmentation(BaseIds.class).getOfPortId(); + NodeId nodeId = new NodeId(ncId.getValue().substring(0,ncId.getValue().lastIndexOf(":"))); + InstanceIdentifier ncIdentifier = InstanceIdentifier.builder(Nodes.class) + .child(Node.class, new NodeKey(nodeId)) + .child(NodeConnector.class, new NodeConnectorKey(ncId)).build(); + + Optional nc = read(LogicalDatastoreType.OPERATIONAL, ncIdentifier); + if(nc.isPresent()) { + NodeConnector nodeConn = nc.get(); + LOG.trace("nodeConnector: {}",nodeConn); + return nodeConn; + } + return null; + } + + private void delInterface(final InstanceIdentifier identifier, + final Interface del) { + InstanceIdentifier id = buildId(identifier); + Optional port = read(LogicalDatastoreType.CONFIGURATION, id); + if(port.isPresent()) { + Interface interf = port.get(); + // TODO: Update operational data + } + } + + private void updateInterface(final InstanceIdentifier identifier, + final Interface original, final Interface udpate) { + InstanceIdentifier id = buildId(identifier); + Optional port = read(LogicalDatastoreType.CONFIGURATION, id); + if(port.isPresent()) { + Interface interf = port.get(); + //TODO: Update operational data + } + } + + private Optional read(LogicalDatastoreType datastoreType, + InstanceIdentifier path) { + + ReadOnlyTransaction tx = broker.newReadOnlyTransaction(); + + Optional result = Optional.absent(); + try { + result = tx.read(datastoreType, path).get(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + return result; + } + + private InstanceIdentifier getWildCardPath() { + return InstanceIdentifier.create(Interfaces.class).child(Interface.class); + } + + @Override + protected void remove(InstanceIdentifier identifier, Interface del) { + LOG.trace("key: " + identifier + ", value=" + del ); + delInterface(identifier, del); + } + + @Override + protected void update(InstanceIdentifier identifier, Interface original, Interface update) { + LOG.trace("key: " + identifier + ", original=" + original + ", update=" + update ); + updateInterface(identifier, original, update); + + } + +} diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfacemgrProvider.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfacemgrProvider.java index a3d4e7324c..ad2a315de2 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfacemgrProvider.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfacemgrProvider.java @@ -7,6 +7,7 @@ */ package org.opendaylight.vpnservice.interfacemgr; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext; import org.opendaylight.controller.sal.binding.api.BindingAwareProvider; import org.slf4j.Logger; @@ -15,15 +16,24 @@ import org.slf4j.LoggerFactory; public class InterfacemgrProvider implements BindingAwareProvider, AutoCloseable { private static final Logger LOG = LoggerFactory.getLogger(InterfacemgrProvider.class); + + private InterfaceManager interfaceManager; @Override public void onSessionInitiated(ProviderContext session) { LOG.info("InterfacemgrProvider Session Initiated"); + try { + final DataBroker dataBroker = session.getSALService(DataBroker.class); + interfaceManager = new InterfaceManager(dataBroker); + } catch (Exception e) { + LOG.error("Error initializing services", e); + } } @Override public void close() throws Exception { LOG.info("InterfacemgrProvider Closed"); + interfaceManager.close(); } } -- 2.36.6