From 04f73a9e43b63c4c3c1ae2214562741f8bc25c85 Mon Sep 17 00:00:00 2001 From: ANURADHA RAJU Date: Thu, 24 Mar 2016 12:42:13 +0530 Subject: [PATCH] itm and mdsal porting Change-Id: I9c2b3afa0d19608356e57704f0c85a3eaa3ed6d0 Signed-off-by: ANURADHA RAJU --- features/src/main/features/features.xml | 1 + .../vpnservice/itm/api/IITMProvider.java | 69 ++ .../vpnservice/itm/globals/ITMConstants.java | 11 +- itm/itm-api/src/main/yang/itm-config.yang | 114 +++ itm/itm-api/src/main/yang/itm-rpc.yang | 66 +- itm/itm-api/src/main/yang/itm-state.yang | 11 +- itm/itm-api/src/main/yang/itm.yang | 17 +- itm/itm-impl/pom.xml | 28 + .../vpnservice/itm/cli/ItmCliUtils.java | 45 + .../vpnservice/itm/cli/SubnetObject.java | 165 ++++ .../vpnservice/itm/cli/TepAdd.java | 63 ++ .../vpnservice/itm/cli/TepCommandHelper.java | 810 ++++++++++++++++++ .../vpnservice/itm/cli/TepCommit.java | 47 + .../itm/cli/TepConfigureTunnelType.java | 51 ++ .../vpnservice/itm/cli/TepDelete.java | 59 ++ .../itm/cli/TepDeleteDatastore.java | 83 ++ .../itm/cli/TepEnableTunnelMonitor.java | 41 + .../vpnservice/itm/cli/TepMonitor.java | 46 + .../vpnservice/itm/cli/TepShow.java | 50 ++ .../vpnservice/itm/cli/TepShowState.java | 50 ++ .../vpnservice/itm/cli/TepStateShow.java | 28 + .../vpnservice/itm/cli/VtepSchemaAdd.java | 138 +++ .../vpnservice/itm/cli/VtepSchemaDelete.java | 73 ++ .../vpnservice/itm/cli/VtepSchemaShow.java | 175 ++++ .../vpnservice/itm/cli/VtepSchemaUpdate.java | 93 ++ .../vpnservice/itm/confighelpers/HwVtep.java | 136 +++ .../ItmExternalTunnelAddWorker.java | 236 ++++- .../ItmExternalTunnelDeleteWorker.java | 207 ++++- .../ItmInternalTunnelAddWorker.java | 10 +- .../ItmInternalTunnelDeleteWorker.java | 24 +- .../itm/confighelpers/ItmTepAddWorker.java | 9 +- .../itm/confighelpers/ItmTepRemoveWorker.java | 8 +- .../vpnservice/itm/impl/ITMManager.java | 58 +- .../vpnservice/itm/impl/ItmProvider.java | 192 ++++- .../vpnservice/itm/impl/ItmUtils.java | 384 ++++++++- .../itm/listeners/TransportZoneListener.java | 135 ++- .../listeners/VtepConfigSchemaListener.java | 592 +++++++++++++ .../itm/rpc/ItmManagerRpcService.java | 402 +++++---- .../vpnservice/itm/snd/ITMStatusMonitor.java | 62 ++ .../itm/snd/ITMStatusMonitorMBean.java | 14 + mdsalutil/mdsalutil-api/pom.xml | 5 + .../vpnservice/mdsalutil/ActionType.java | 43 +- .../vpnservice/mdsalutil/MDSALUtil.java | 61 +- .../vpnservice/mdsalutil/MatchFieldType.java | 58 ++ .../vpnservice/mdsalutil/MetaDataUtil.java | 18 +- .../vpnservice/mdsalutil/NwConstants.java | 9 +- .../vpnservice/utils/cache/CacheUtil.java | 29 + .../utils/clustering/ClusteringUtils.java | 37 + .../hwvtep/HwvtepSouthboundConstants.java | 25 + .../utils/hwvtep/HwvtepSouthboundUtils.java | 367 ++++++++ .../vpnservice/utils/hwvtep/HwvtepUtils.java | 556 ++++++++++++ .../mdsalutil/internal/MDSALManager.java | 3 +- 52 files changed, 5732 insertions(+), 282 deletions(-) create mode 100644 itm/itm-api/src/main/yang/itm-config.yang create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/ItmCliUtils.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/SubnetObject.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepAdd.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepCommandHelper.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepCommit.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepConfigureTunnelType.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepDelete.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepDeleteDatastore.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepEnableTunnelMonitor.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepMonitor.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepShow.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepShowState.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepStateShow.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/VtepSchemaAdd.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/VtepSchemaDelete.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/VtepSchemaShow.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/VtepSchemaUpdate.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/HwVtep.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/listeners/VtepConfigSchemaListener.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/snd/ITMStatusMonitor.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/snd/ITMStatusMonitorMBean.java create mode 100644 mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/cache/CacheUtil.java create mode 100644 mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/clustering/ClusteringUtils.java create mode 100644 mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/hwvtep/HwvtepSouthboundConstants.java create mode 100644 mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/hwvtep/HwvtepSouthboundUtils.java create mode 100644 mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/hwvtep/HwvtepUtils.java diff --git a/features/src/main/features/features.xml b/features/src/main/features/features.xml index 513ae57e..dfd0ca06 100644 --- a/features/src/main/features/features.xml +++ b/features/src/main/features/features.xml @@ -26,6 +26,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html odl-openflowplugin-nsf-model odl-openflowplugin-nxm-extensions odl-ovsdb-southbound-impl-rest + odl-ovsdb-hwvtepsouthbound-api mvn:org.opendaylight.controller/liblldp/{{VERSION}} mvn:org.opendaylight.neutron/model/{{VERSION}} mvn:org.opendaylight.vpnservice/model-bgp/{{VERSION}} diff --git a/itm/itm-api/src/main/java/org/opendaylight/vpnservice/itm/api/IITMProvider.java b/itm/itm-api/src/main/java/org/opendaylight/vpnservice/itm/api/IITMProvider.java index 5610422d..c45b982d 100644 --- a/itm/itm-api/src/main/java/org/opendaylight/vpnservice/itm/api/IITMProvider.java +++ b/itm/itm-api/src/main/java/org/opendaylight/vpnservice/itm/api/IITMProvider.java @@ -6,7 +6,76 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.vpnservice.itm.api; +import java.math.BigInteger; +import java.util.List; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.vpnservice.interfacemgr.exceptions.InterfaceNotFoundException; +import org.opendaylight.vpnservice.mdsalutil.ActionInfo; +import org.opendaylight.vpnservice.mdsalutil.MatchInfo; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.TunnelsState; public interface IITMProvider { + // APIs used by i + public void createLocalCache(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask, String gatewayIp, String transportZone); + + public void commitTeps(); + + public DataBroker getDataBroker(); + + public void showTeps(); + + public void deleteVtep(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask, + String gatewayIp, String transportZone); + // public void showState(TunnelsState tunnelsState); + public void configureTunnelType(String transportZone, String tunnelType); + + + /** + * Adds the vtep config schema. + * + * @param vtepConfigSchema + * the vtep config schema + */ + public void addVtepConfigSchema(VtepConfigSchema vtepConfigSchema); + + /** + * Gets the vtep config schema. + * + * @param schemaName + * the schema name + * @return the vtep config schema + */ + public VtepConfigSchema getVtepConfigSchema(String schemaName); + + /** + * Gets the all vtep config schemas. + * + * @return the all vtep config schemas + */ + public List getAllVtepConfigSchemas(); + + /** + * Update VTEP schema. + * + * @param schemaName + * the schema name + * @param lstDpnsForAdd + * the lst dpns for add + * @param lstDpnsForDelete + * the lst dpns for delete + */ + public void updateVtepSchema(String schemaName, List lstDpnsForAdd, List lstDpnsForDelete); + + /** + * Delete all vtep schemas. + */ + public void deleteAllVtepSchemas(); + + public void configureTunnelMonitorEnabled(boolean monitorEnabled); + public void configureTunnelMonitorInterval(int interval); } diff --git a/itm/itm-api/src/main/java/org/opendaylight/vpnservice/itm/globals/ITMConstants.java b/itm/itm-api/src/main/java/org/opendaylight/vpnservice/itm/globals/ITMConstants.java index 1cb20a09..b6f6673b 100644 --- a/itm/itm-api/src/main/java/org/opendaylight/vpnservice/itm/globals/ITMConstants.java +++ b/itm/itm-api/src/main/java/org/opendaylight/vpnservice/itm/globals/ITMConstants.java @@ -9,12 +9,19 @@ package org.opendaylight.vpnservice.itm.globals; import java.math.BigInteger; - - public class ITMConstants{ public static final BigInteger COOKIE_ITM = new BigInteger("9000000", 16); + public static final BigInteger COOKIE_ITM_EXTERNAL = new BigInteger("9050000", 16); + public static final String ITM_IDPOOL_NAME = "Itmservices"; public static final long ITM_IDPOOL_START = 1L; public static final String ITM_IDPOOL_SIZE = "100000"; public static int LLDP_SERVICE_ID = 0; + //Tunnel Monitoring + public static final boolean DEFAULT_MONITOR_ENABLED = true; + public static final int DEFAULT_MONITOR_INTERVAL = 10; + public static final String DUMMY_IP_ADDRESS = "0.0.0.0"; + public static final String TUNNEL_TYPE_VXLAN = "VXLAN"; + public static final String TUNNEL_TYPE_GRE = "GRE"; } + diff --git a/itm/itm-api/src/main/yang/itm-config.yang b/itm/itm-api/src/main/yang/itm-config.yang new file mode 100644 index 00000000..858d0a1b --- /dev/null +++ b/itm/itm-api/src/main/yang/itm-config.yang @@ -0,0 +1,114 @@ +module itm-config { + + namespace "urn:opendaylight:vpnservice:itm:config"; + + prefix itm-config; + + import ietf-interfaces { + prefix if; + } + import ietf-yang-types { + prefix yang; + } + import ietf-inet-types { + prefix inet; + revision-date "2010-09-24"; + } + import odl-interface { + prefix odlif; + } + import config { prefix config; revision-date 2013-04-05; } + + description "This YANG module defines automatic tunnel configuration."; + revision "2015-11-02"; + + /* Tunnel Monitoring Knob */ + + container tunnel-monitor-enabled { + leaf enabled { + type boolean; + default true; + } + } + + container tunnel-monitor-interval { + leaf interval { + type uint16 { + range "5..30"; + } + default 10; + } + } + + /* Configuration data */ + + container vtep-config-schemas { + list vtep-config-schema { + key schema-name; + leaf schema-name { + type string; + mandatory true; + description "Schema name"; + } + leaf transport-zone-name { + type string; + mandatory true; + description "Transport zone"; + } + leaf tunnel-type { + type identityref { + base odlif:tunnel-type-base; + } + } + leaf port-name { + type string; + mandatory true; + description "Port name"; + } + leaf vlan-id { + type uint16 { + range "0..4094"; + } + mandatory true; + description "VLAN ID"; + } + leaf gateway-ip { + type inet:ip-address; + description "Gateway IP address"; + } + leaf subnet { + type inet:ip-prefix; + mandatory true; + description "Subnet Mask in CIDR-notation string, e.g. 10.0.0.0/24"; + } + leaf exclude-ip-filter { + type string; + description "IP Addresses which needs to be excluded from the specified subnet. IP address range or comma separated IP addresses can to be specified. e.g: 10.0.0.1-10.0.0.20,10.0.0.30,10.0.0.35"; + } + list dpn-ids { + key "DPN"; + leaf DPN { + type uint64; + description "DPN ID"; + } + } + } + } + + /* Ip Address book keeping */ + container vtep-ip-pools { + config true; + list vtep-ip-pool { + key subnet-cidr; + leaf subnet-cidr{ + type string; + } + leaf-list available-ipaddress { + type inet:ip-address; + } + leaf-list allocated-ipaddress { + type inet:ip-address; + } + } + } +} diff --git a/itm/itm-api/src/main/yang/itm-rpc.yang b/itm/itm-api/src/main/yang/itm-rpc.yang index 2347e6eb..866c6e63 100644 --- a/itm/itm-api/src/main/yang/itm-rpc.yang +++ b/itm/itm-api/src/main/yang/itm-rpc.yang @@ -23,7 +23,7 @@ module itm-rpc { import opendaylight-action-types {prefix action;revision-date "2013-11-12";} import opendaylight-flow-types {prefix offlow;revision-date "2013-10-26";} - + revision "2015-12-17" { description "ODL Specific Itm Manager Rpcs Module"; } @@ -65,13 +65,13 @@ module itm-rpc { } rpc get-external-tunnel-interface-name { - description "used to retrieve tunnel interface id between Dpns"; + description "used to retrieve external tunnel interface id between Dpns/TORs"; input { - leaf source-dpid { - type uint64; + leaf source-node { + type string; } - leaf destination-ip { - type inet:ip-address; + leaf destination-node { + type string; } } output { @@ -98,7 +98,7 @@ module itm-rpc { } } - rpc add-external-tunnel-endpoint { + rpc add-external-tunnel-endpoint { description "used for building tunnels between teps on all Dpns and external node"; input { leaf destination-ip { @@ -110,7 +110,7 @@ module itm-rpc { } } } - } + } rpc remove-external-tunnel-from-dpns { description "used for building tunnels between a Dpn and external node"; input { @@ -155,16 +155,46 @@ module itm-rpc { } } - rpc remove-terminating-service-actions { - description "used for removing the terminating service actions"; - input { - leaf dpn-id { + rpc remove-terminating-service-actions { + description "used for removing the terminating service actions"; + input { + leaf dpn-id { type uint64; - } - leaf service-id { - type uint16; - } - } - } + } + leaf service-id { + type uint16; + } + } + } + + rpc add-l2-gw-device { + description "used for building tunnels between teps on all Dpns and hwVtep"; + input { + leaf topology-id { + type string; + } + leaf node-id { + type string; + } + leaf ip-address { + type inet:ip-address; + } + } + } + + rpc delete-l2-gw-device { + description "used for deleting tunnels between teps on all Dpns and hwVtep"; + input { + leaf topology-id { + type string; + } + leaf node-id { + type string; + } + leaf ip-address { + type inet:ip-address; + } + } + } } \ No newline at end of file diff --git a/itm/itm-api/src/main/yang/itm-state.yang b/itm/itm-api/src/main/yang/itm-state.yang index ca39c03e..aa302691 100644 --- a/itm/itm-api/src/main/yang/itm-state.yang +++ b/itm/itm-api/src/main/yang/itm-state.yang @@ -102,14 +102,14 @@ module itm-state { container external-tunnel-list { list external-tunnel { - key "source-DPN destination-IP"; + key "source-device destination-device"; - leaf source-DPN { - type uint64; + leaf source-device { + type string; //dpnid or node-id } - leaf destination-IP { - type inet:ip-address; + leaf destination-device { + type string; //dpn-id or node-id or ip } /* logical-group interface id */ @@ -121,6 +121,7 @@ module itm-state { } } + notification itm-tunnel-build-complete{ } diff --git a/itm/itm-api/src/main/yang/itm.yang b/itm/itm-api/src/main/yang/itm.yang index 8785d0a6..3d3ccbe5 100644 --- a/itm/itm-api/src/main/yang/itm.yang +++ b/itm/itm-api/src/main/yang/itm.yang @@ -48,7 +48,9 @@ module itm { type inet:ip-address; } leaf vlan-id { - type uint16; + type uint16{ + range "0..4094"; + } } list vteps { key "dpn-id portname"; @@ -62,6 +64,19 @@ module itm { type inet:ip-address; } } + list device-vteps { + key "node-id ip-address"; + leaf topology-id { + type string; + } + leaf node-id { + type string; + } + leaf ip-address { + type inet:ip-address; + } + } + } } } diff --git a/itm/itm-impl/pom.xml b/itm/itm-impl/pom.xml index d555a771..cc057849 100644 --- a/itm/itm-impl/pom.xml +++ b/itm/itm-impl/pom.xml @@ -57,6 +57,16 @@ mockito-all test + + org.osgi + org.osgi.core + provided + + + org.apache.karaf.shell + org.apache.karaf.shell.console + ${karaf.shell.console.version} + com.google.guava guava @@ -77,4 +87,22 @@ 0.3.0-SNAPSHOT + + + + org.apache.felix + maven-bundle-plugin + + + + org.apache.felix.service.command, + org.apache.felix.gogo.commands, + org.apache.karaf.shell.console, + * + + + + + + diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/ItmCliUtils.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/ItmCliUtils.java new file mode 100644 index 00000000..798ee90c --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/ItmCliUtils.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016 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.itm.cli; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + +import com.google.common.base.Preconditions; + +/** + * The Utility class for ITM CLI. + */ +public final class ItmCliUtils { + + /** + * Construct dpn id list. + * + * @param dpnIds + * the dpn ids + * @return the list + */ + public static List constructDpnIdList(final String dpnIds) { + final List lstDpnIds = new ArrayList<>(); + if (StringUtils.isNotBlank(dpnIds)) { + final String[] arrDpnIds = StringUtils.split(dpnIds, ','); + for (String dpn : arrDpnIds) { + if (StringUtils.isNumeric(StringUtils.trim(dpn))) { + lstDpnIds.add(new BigInteger(StringUtils.trim(dpn))); + } else { + Preconditions.checkArgument(false, String.format("DPN ID [%s] is not a numeric value.", dpn)); + } + } + } + return lstDpnIds; + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/SubnetObject.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/SubnetObject.java new file mode 100644 index 00000000..f5baf254 --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/SubnetObject.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016 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.itm.cli; + +import java.util.Map; + +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.inet.types.rev100924.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.SubnetsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.SubnetsKey; +import org.opendaylight.yangtools.yang.binding.Augmentation; +import org.opendaylight.yangtools.yang.binding.DataObject; + +public class SubnetObject { + private IpAddress _gatewayIp; + private SubnetsKey _key; + private IpPrefix _prefix; + private java.lang.Integer _vlanId; + + public SubnetObject(IpAddress gWIP, SubnetsKey key, IpPrefix mask, Integer vlanId) { + _gatewayIp = gWIP; + _key = key; + _prefix = mask; + try { + if (vlanId != null) { + checkVlanIdRange(vlanId); + } + } catch (IllegalArgumentException e) { + System.out.println("Invalid VlanID. expected: 0 to 4095"); + } + _vlanId = vlanId; + } + + public IpAddress get_gatewayIp() { + return _gatewayIp; + } + + public SubnetsKey get_key() { + return _key; + } + + public IpPrefix get_prefix() { + return _prefix; + } + + public java.lang.Integer get_vlanId() { + return _vlanId; + } + + private int hash = 0; + private volatile boolean hashValid = false; + + @Override + public int hashCode() { + if (hashValid) { + return hash; + } + + final int prime = 31; + int result = 1; + result = prime * result + ((_gatewayIp == null) ? 0 : _gatewayIp.hashCode()); + result = prime * result + ((_key == null) ? 0 : _key.hashCode()); + result = prime * result + ((_prefix == null) ? 0 : _prefix.hashCode()); + result = prime * result + ((_vlanId == null) ? 0 : _vlanId.hashCode()); + hash = result; + hashValid = true; + return result; + } + + @Override + public boolean equals(java.lang.Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof SubnetObject)) { + return false; + } + SubnetObject other = (SubnetObject) obj; + if (_gatewayIp == null) { + if (other.get_gatewayIp() != null) { + return false; + } + } else if (!_gatewayIp.equals(other.get_gatewayIp())) { + return false; + } + if (_key == null) { + if (other.get_key() != null) { + return false; + } + } else if (!_key.equals(other.get_key())) { + return false; + } + if (_prefix == null) { + if (other.get_prefix() != null) { + return false; + } + } else if (!_prefix.equals(other.get_prefix())) { + return false; + } + if (_vlanId == null) { + if (other.get_vlanId() != null) { + return false; + } + } else if (!_vlanId.equals(other.get_vlanId())) { + return false; + } + return true; + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder builder = new java.lang.StringBuilder("Subnets ["); + boolean first = true; + + if (_gatewayIp != null) { + if (first) { + first = false; + } else { + builder.append(", "); + } + builder.append("_gatewayIp="); + builder.append(_gatewayIp); + } + if (_key != null) { + if (first) { + first = false; + } else { + builder.append(", "); + } + builder.append("_key="); + builder.append(_key); + } + if (_prefix != null) { + if (first) { + first = false; + } else { + builder.append(", "); + } + builder.append("_prefix="); + builder.append(_prefix); + } + if (_vlanId != null) { + if (first) { + first = false; + } else { + builder.append(", "); + } + builder.append("_vlanId="); + builder.append(_vlanId); + } + return builder.append(']').toString(); + } + + private static void checkVlanIdRange(final int value) { + if (value >= 0 && value <= 4095) { + return; + } + throw new IllegalArgumentException(String.format("Invalid range: %s, expected: [[0?4095]].", value)); + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepAdd.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepAdd.java new file mode 100644 index 00000000..d4e0c856 --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepAdd.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016 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.itm.cli; + +import java.math.BigInteger; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Command(scope = "tep", name = "add", description = "adding a tunnel end point") +public class TepAdd extends OsgiCommandSupport { + + @Argument(index = 0, name = "dpnId", description = "DPN-ID", required = false, multiValued = false) + private BigInteger dpnId; + @Argument(index = 1, name = "portNo", description = "port-name", required = false, multiValued = false) + private String portName; + @Argument(index = 2, name = "vlanId", description = "vlan-id", required = false, multiValued = false) + private Integer vlanId; + @Argument(index = 3, name = "ipAddress", description = "ip-address", required = false, multiValued = false) + private String ipAddress; + @Argument(index = 4, name = "subnetMask", description = "subnet-Mask", required = false, multiValued = false) + private String subnetMask; + @Argument(index = 5, name = "gatewayIp", description = "gateway-ip", required = false, multiValued = false) + private String gatewayIp; + @Argument(index = 6, name = "transportZone", description = "transport_zone", required = false, multiValued = false) + private String transportZone; + private static final Logger LOG = LoggerFactory.getLogger(TepAdd.class); + private IITMProvider itmProvider; + + public void setItmProvider(IITMProvider itmProvider) { + this.itmProvider = itmProvider; + } + + @Override + protected Object doExecute() { + try { + if (dpnId == null || portName == null || vlanId == null || ipAddress == null || subnetMask == null + || transportZone == null) { + System.out.println("Insufficient Arguments"); + System.out.println("Correct Usage : exec tep-add dpnId portName vlanId ipAddress subnetMask gatewayIp transportZone"); + return null; + } + LOG.debug("Executing create TEP command" + "\t" + dpnId + "\t" + portName + "\t" + vlanId + "\t" + + ipAddress + "\t" + subnetMask + "\t" + gatewayIp + "\t" + transportZone); + itmProvider.createLocalCache(dpnId, portName, vlanId, ipAddress, subnetMask, gatewayIp, transportZone); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } catch (Exception e) { + System.out.println(e.getMessage()); + LOG.error("Exception occurred during execution of command \"tep-add\": ", e); + } + return null; + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepCommandHelper.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepCommandHelper.java new file mode 100644 index 00000000..7f417d3b --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepCommandHelper.java @@ -0,0 +1,810 @@ +/* + * Copyright (c) 2016 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.itm.cli; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.net.util.SubnetUtils; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.interfacemgr.exceptions.InterfaceNotFoundException; +import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager; +//import org.opendaylight.vpnservice.interfacemgr.util.OperationalIfmUtil; +import org.opendaylight.vpnservice.itm.globals.ITMConstants; +import org.opendaylight.vpnservice.itm.impl.ItmUtils; +import org.opendaylight.vpnservice.mdsalutil.MDSALDataStoreUtils; +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.inet.types.rev100924.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorEnabled; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorEnabledBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorInterval; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorIntervalBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZonesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZoneBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZoneKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.Subnets; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.SubnetsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.SubnetsKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.Vteps; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.VtepsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.VtepsKey; +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.base.Preconditions; + + +public class TepCommandHelper { + + private static final Logger LOG = LoggerFactory.getLogger(TepCommandHelper.class); + private DataBroker dataBroker; + static int check = 0; + static short flag = 0; + /* + * boolean flag add_or_delete --- can be set to true if the last called tep + * command is Tep-add else set to false when Tep-delete is called + * tepCommandHelper object is created only once in session initiated + */ + final Map>> tZones = new HashMap>>(); + private List subnetList = new ArrayList(); + private List tZoneList = new ArrayList(); + private List vtepDelCommitList = new ArrayList(); + private IInterfaceManager interfaceManager; + + // private List> vtepPaths = new + // ArrayList<>(); + + + public TepCommandHelper(final DataBroker broker) { + this.dataBroker = broker; + } + + + public void setInterfaceManager(IInterfaceManager interfaceManager) { + this.interfaceManager = interfaceManager; + } + + public void createLocalCache(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, + String subnetMask, String gatewayIp, String transportZone) { + + check++; + IpAddress ipAddressObj = null; + IpAddress gatewayIpObj = null; + IpPrefix subnetMaskObj = null; + VtepsKey vtepkey = new VtepsKey(dpnId, portName); + try { + ipAddressObj = new IpAddress(ipAddress.toCharArray()); + gatewayIpObj = new IpAddress("0.0.0.0".toCharArray()); + if (gatewayIp != null) { + gatewayIpObj = new IpAddress(gatewayIp.toCharArray()); + } else { + LOG.debug("gateway is null"); + } + } catch (Exception e) { + System.out.println("Invalid IpAddress. Expected: 1.0.0.0 to 254.255.255.255"); + return; + } + try { + subnetMaskObj = new IpPrefix(subnetMask.toCharArray()); + } catch (Exception e) { + System.out.println("Invalid Subnet Mask. Expected: 0.0.0.0/0 to 255.255.255.255/32"); + return; + } + + if (!validateIPs(ipAddress, subnetMask, gatewayIp)) { + System.out.println("IpAddress and gateWayIp should belong to the subnet provided"); + return; + } + + if (checkTepPerTzPerDpn(transportZone, dpnId)) { + System.out.println("Only one end point per transport Zone per Dpn is allowed"); + return; + } + Vteps vtepCli = new VtepsBuilder().setDpnId(dpnId).setIpAddress(ipAddressObj).setKey(vtepkey) + .setPortname(portName).build(); + validateForDuplicates(vtepCli, transportZone); + + SubnetsKey subnetsKey = new SubnetsKey(subnetMaskObj); + SubnetObject subObCli = new SubnetObject(gatewayIpObj, subnetsKey, subnetMaskObj, vlanId); + if (tZones.containsKey(transportZone)) { + Map> subVtepMapTemp = (Map>) tZones.get(transportZone); + if (subVtepMapTemp.containsKey(subObCli)) { // if Subnet exists + List vtepListTemp = (List) subVtepMapTemp.get(subObCli); + if (vtepListTemp.contains(vtepCli)) { + // do nothing + } else { + vtepListTemp.add(vtepCli); + } + } else { // subnet doesnt exist + if (checkExistingSubnet(subVtepMapTemp, subObCli)) { + System.out.println("subnet with subnet mask " + subObCli.get_key() + "already exists"); + return; + } + List vtepListTemp = new ArrayList(); + vtepListTemp.add(vtepCli); + subVtepMapTemp.put(subObCli, vtepListTemp); + } + } else { + List vtepListTemp = new ArrayList(); + vtepListTemp.add(vtepCli); + Map> subVtepMapTemp = new HashMap>(); + subVtepMapTemp.put(subObCli, vtepListTemp); + tZones.put(transportZone, subVtepMapTemp); + } + } + + private boolean validateIPs(String ipAddress, String subnetMask, String gatewayIp) { + SubnetUtils utils = new SubnetUtils(subnetMask); + if ((utils.getInfo().isInRange(ipAddress)) && ((gatewayIp == null) || (utils.getInfo().isInRange(gatewayIp)))) { + return true; + } else { + LOG.trace("InValid IP"); + return false; + } + } + + /** + * Validate for duplicates. + * + * @param inputVtep + * the input vtep + * @param transportZone + * the transport zone + */ + public void validateForDuplicates(Vteps inputVtep, String transportZone) { + Map tZoneMap = getAllTransportZonesAsMap(); + + boolean isConfiguredTepGreType = isGreTunnelType(transportZone, tZoneMap); + // Checking for duplicates in local cache + for (String tZ : tZones.keySet()) { + boolean isGreType = isGreTunnelType(tZ, tZoneMap); + Map> subVtepMapTemp = (Map>) tZones.get(tZ); + for (SubnetObject subOb : subVtepMapTemp.keySet()) { + List vtepList = subVtepMapTemp.get(subOb); + validateForDuplicateAndSingleGreTep(inputVtep, isConfiguredTepGreType, isGreType, vtepList); + } + } + // Checking for duplicates in config DS + for (TransportZone tZ : tZoneMap.values()) { + boolean isGreType = false; + if (tZ.getTunnelType().equals(TunnelTypeGre.class)) { + isGreType = true; + } + for (Subnets sub : ItmUtils.emptyIfNull(tZ.getSubnets())) { + List vtepList = sub.getVteps(); + validateForDuplicateAndSingleGreTep(inputVtep, isConfiguredTepGreType, isGreType, vtepList); + } + } + } + + private void validateForDuplicateAndSingleGreTep(Vteps inputVtep, boolean isConfiguredTepGreType, boolean isGreType, + List vtepList) { + if (ItmUtils.isEmpty(vtepList)) { + return; + } + if (vtepList.contains(inputVtep)) { + Preconditions.checkArgument(false, "VTEP already exists"); + } + BigInteger dpnId = inputVtep.getDpnId(); + if (isConfiguredTepGreType && isGreType) { + for (Vteps vtep : vtepList) { + if (vtep.getDpnId().equals(dpnId)) { + String errMsg = new StringBuilder("DPN [").append(dpnId) + .append("] already configured with GRE TEP. Mutiple GRE TEP's on a single DPN are not allowed.") + .toString(); + Preconditions.checkArgument(false, errMsg); + } + } + } + } + + /** + * Gets all transport zones as map. + * + * @return all transport zones as map + */ + private Map getAllTransportZonesAsMap() { + TransportZones tZones = getAllTransportZones(); + Map tZoneMap = new HashMap<>(); + if( null != tZones) { + for (TransportZone tzone : ItmUtils.emptyIfNull(tZones.getTransportZone())) { + tZoneMap.put(tzone.getZoneName(), tzone); + } + } + return tZoneMap; + } + + /** + * Checks if is gre tunnel type. + * + * @param tZoneName + * the zone name + * @param tZoneMap + * the zone map + * @return true, if is gre tunnel type + */ + private boolean isGreTunnelType(String tZoneName, Map tZoneMap) { + TransportZone tzone = tZoneMap.get(tZoneName); + /* + if (tzone != null && StringUtils.equalsIgnoreCase(ITMConstants.TUNNEL_TYPE_GRE, tzone.getTunnelType())) { + return true; + } + */ + if( (tzone != null) && (tzone.getTunnelType()).equals(TunnelTypeGre.class) ) { + return true; + } + return false; + } + + /** + * Gets the transport zone. + * + * @param tzone + * the tzone + * @return the transport zone + */ + public TransportZone getTransportZone(String tzone) { + InstanceIdentifier tzonePath = InstanceIdentifier.builder(TransportZones.class) + .child(TransportZone.class, new TransportZoneKey(tzone)).build(); + Optional tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, + dataBroker); + if (tZoneOptional.isPresent()) { + return tZoneOptional.get(); + } + return null; + } + + /** + * Gets the transport zone from config ds. + * + * @param tzone + * the tzone + * @return the transport zone + */ + public TransportZone getTransportZoneFromConfigDS(String tzone) { + InstanceIdentifier tzonePath = InstanceIdentifier.builder(TransportZones.class) + .child(TransportZone.class, new TransportZoneKey(tzone)).build(); + Optional tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, + dataBroker); + if (tZoneOptional.isPresent()) { + return tZoneOptional.get(); + } + return null; + } + + /** + * Gets all transport zones. + * + * @return all transport zones + */ + public TransportZones getAllTransportZones() { + InstanceIdentifier path = InstanceIdentifier.builder(TransportZones.class).build(); + Optional tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker); + if (tZonesOptional.isPresent()) { + return tZonesOptional.get(); + } + return null; + } + + public boolean checkExistingSubnet(Map> subVtepMapTemp, SubnetObject subObCli) { + for (SubnetObject subOb : subVtepMapTemp.keySet()) { + if (subOb.get_key().equals(subObCli.get_key())) { + if (!(subOb.get_vlanId().equals(subObCli.get_vlanId()))) + return true; + if (!(subOb.get_gatewayIp().equals(subObCli.get_gatewayIp()))) + return true; + } + } + return false; + } + + public boolean checkTepPerTzPerDpn(String tzone, BigInteger dpnId) { + // check in local cache + if (tZones.containsKey(tzone)) { + Map> subVtepMapTemp = (Map>) tZones.get(tzone); + for (SubnetObject subOb : subVtepMapTemp.keySet()) { + List vtepList = subVtepMapTemp.get(subOb); + for (Vteps vtep : vtepList) + if (vtep.getDpnId().equals(dpnId)) + return true; + } + } + + // check in DS + InstanceIdentifier tzonePath = + InstanceIdentifier.builder(TransportZones.class) + .child(TransportZone.class, new TransportZoneKey(tzone)).build(); + Optional tZoneOptional = + ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker); + if (tZoneOptional.isPresent()) { + TransportZone tz = tZoneOptional.get(); + if (tz.getSubnets() == null || tz.getSubnets().isEmpty()) + return false; + for (Subnets sub : tz.getSubnets()) { + if (sub.getVteps() == null || sub.getVteps().isEmpty()) + continue; + for (Vteps vtep : sub.getVteps()) { + if (vtep.getDpnId().equals(dpnId)) { + return true; + } + } + } + } + return false; + } + + public void buildTeps() { + TransportZones tZonesBuilt = null; + TransportZone tZone = null; + try { + LOG.debug("no of teps added" + check); + if (tZones != null || !tZones.isEmpty()) { + tZoneList = new ArrayList(); + for (String tZ : tZones.keySet()) { + LOG.debug("tZones" + tZ); + subnetList = new ArrayList(); + Map> subVtepMapTemp = (Map>) tZones.get(tZ); + for (SubnetObject subOb : subVtepMapTemp.keySet()) { + LOG.debug("subnets" + subOb.get_prefix()); + List vtepList = subVtepMapTemp.get(subOb); + Subnets subnet = + new SubnetsBuilder().setGatewayIp(subOb.get_gatewayIp()) + .setKey(subOb.get_key()).setPrefix(subOb.get_prefix()) + .setVlanId(subOb.get_vlanId()).setVteps(vtepList).build(); + subnetList.add(subnet); + LOG.debug("vteps" + vtepList); + } + InstanceIdentifier tZonepath = + InstanceIdentifier.builder(TransportZones.class) + .child(TransportZone.class, new TransportZoneKey(tZ)).build(); + Optional tZoneOptional = + ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tZonepath, dataBroker); + LOG.debug("read container from DS"); + if (tZoneOptional.isPresent()) { + TransportZone tzoneFromDs = tZoneOptional.get(); + LOG.debug("read tzone container" + tzoneFromDs.toString()); + if (tzoneFromDs.getTunnelType() == null + || (tzoneFromDs.getTunnelType()).equals(TunnelTypeVxlan.class)) { + tZone = + new TransportZoneBuilder().setKey(new TransportZoneKey(tZ)) + .setTunnelType(TunnelTypeVxlan.class).setSubnets(subnetList) + .setZoneName(tZ).build(); + } else if ((tzoneFromDs.getTunnelType()).equals(TunnelTypeGre.class)) { + tZone = + new TransportZoneBuilder().setKey(new TransportZoneKey(tZ)) + .setTunnelType(TunnelTypeGre.class).setSubnets(subnetList) + .setZoneName(tZ).build(); + } + } else { + tZone = + new TransportZoneBuilder().setKey(new TransportZoneKey(tZ)) + .setTunnelType(TunnelTypeVxlan.class).setSubnets(subnetList).setZoneName(tZ) + .build(); + } + LOG.debug("tzone object" + tZone); + tZoneList.add(tZone); + } + tZonesBuilt = new TransportZonesBuilder().setTransportZone(tZoneList).build(); + InstanceIdentifier path = InstanceIdentifier.builder(TransportZones.class).build(); + LOG.debug("InstanceIdentifier" + path); + ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, path, tZonesBuilt, dataBroker, + ItmUtils.DEFAULT_CALLBACK); + LOG.debug("wrote to Config DS" + tZonesBuilt); + tZones.clear(); + tZoneList.clear(); + subnetList.clear(); + LOG.debug("Everything cleared"); + } else { + LOG.debug("NO vteps were configured"); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void showTeps(boolean monitorEnabled, int monitorInterval) { + boolean flag = false; + InstanceIdentifier path = InstanceIdentifier.builder(TransportZones.class).build(); + Optional tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker); + if (tZonesOptional.isPresent()) { + TransportZones tZones = tZonesOptional.get(); + if(tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) + { + System.out.println("No teps configured"); + return; + } + List result = new ArrayList(); + result.add(String.format("Tunnel Monitoring (for VXLAN tunnels): %s", (monitorEnabled ? "On" : "Off"))); + result.add(String.format("Tunnel Monitoring Interval (for VXLAN tunnels): %d", monitorInterval)); + result.add(System.lineSeparator()); + result.add(String.format("%-16s %-16s %-16s %-12s %-12s %-12s %-12s %-12s", "TransportZone", "TunnelType", "SubnetMask", + "GatewayIP", "VlanID", "DpnID", "IPAddress", "PortName")); + result.add("--------------------------------------------------------------------------------------------------------------"); + for (TransportZone tZ : tZones.getTransportZone()) { + if (tZ.getSubnets() == null || tZ.getSubnets().isEmpty()) { + LOG.error("Transport Zone " + tZ.getZoneName() + "has no subnets"); + continue; + } + for (Subnets sub : tZ.getSubnets()) { + if (sub.getVteps() == null || sub.getVteps().isEmpty()) { + LOG.error("Transport Zone " + tZ.getZoneName() + "subnet " + sub.getPrefix() + "has no vteps"); + continue; + } + for (Vteps vtep : sub.getVteps()) { + flag = true; + String strTunnelType ; + if( (tZ.getTunnelType()).equals(TunnelTypeGre.class) ) + strTunnelType = ITMConstants.TUNNEL_TYPE_GRE ; + else + strTunnelType = ITMConstants.TUNNEL_TYPE_VXLAN ; + result.add(String.format("%-16s %-16s %-16s %-12s %-12s %-12s %-12s %-12s", tZ.getZoneName(), strTunnelType, sub + .getPrefix().getIpv4Prefix().getValue(), sub.getGatewayIp().getIpv4Address() + .getValue(), sub.getVlanId().toString(), vtep.getDpnId().toString(), vtep + .getIpAddress().getIpv4Address().getValue(), vtep.getPortname().toString())); + } + } + } + if (flag == true) { + for (String p : result) { + System.out.println(p); + } + } else + System.out.println("No teps to display"); + } else + System.out.println("No teps configured"); + } + + + public void deleteVtep(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask, + String gatewayIp, String transportZone) { + + IpAddress ipAddressObj = null; + IpAddress gatewayIpObj = null; + IpPrefix subnetMaskObj = null; + VtepsKey vtepkey = new VtepsKey(dpnId, portName); + try { + ipAddressObj = new IpAddress(ipAddress.toCharArray()); + gatewayIpObj = new IpAddress("0.0.0.0".toCharArray()); + if (gatewayIp != null) { + gatewayIpObj = new IpAddress(gatewayIp.toCharArray()); + } else { + LOG.debug("gateway is null"); + } + } catch (Exception e) { + System.out.println("Invalid IpAddress. Expected: 1.0.0.0 to 254.255.255.255"); + return; + } + try { + subnetMaskObj = new IpPrefix(subnetMask.toCharArray()); + } catch (Exception e) { + System.out.println("Invalid Subnet Mask. Expected: 0.0.0.0/0 to 255.255.255.255/32"); + return; + } + + if (!validateIPs(ipAddress, subnetMask, gatewayIp)) { + System.out.println("IpAddress and gateWayIp should belong to the subnet provided"); + return; + } + SubnetsKey subnetsKey = new SubnetsKey(subnetMaskObj); + Vteps vtepCli = null; + Subnets subCli = null; + + InstanceIdentifier vpath = + InstanceIdentifier.builder(TransportZones.class) + .child(TransportZone.class, new TransportZoneKey(transportZone)) + .child(Subnets.class, subnetsKey).child(Vteps.class, vtepkey).build(); + + // check if present in tzones and delete from cache + boolean existsInCache = isInCache(dpnId, portName, vlanId, ipAddress, subnetMask, gatewayIp, transportZone); + if (!existsInCache) { + Optional vtepOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, vpath, dataBroker); + if (vtepOptional.isPresent()) { + vtepCli = vtepOptional.get(); + if(vtepCli.getIpAddress().equals(ipAddressObj)){ + InstanceIdentifier spath = + InstanceIdentifier + .builder(TransportZones.class) + .child(TransportZone.class, new TransportZoneKey(transportZone)) + .child(Subnets.class, subnetsKey).build(); + Optional subOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, spath, dataBroker); + if (subOptional.isPresent()) { + subCli = subOptional.get(); + if(subCli.getGatewayIp().equals(gatewayIpObj) && subCli.getVlanId().equals(vlanId)){ + vtepDelCommitList.add(vtepCli); + } + else + System.out.println(String.format("vtep with this vlan or gateway doesnt exist")); + } + } + else + System.out.println(String.format("Vtep with this ipaddress doesnt exist")); + } else { + System.out.println(String.format("Vtep Doesnt exist")); + } + } + } + + public void deleteOnCommit() { + List> vtepPaths = new ArrayList<>(); + List> subnetPaths = new ArrayList<>(); + List> tzPaths = new ArrayList<>(); + List subDelList = new ArrayList(); + List tzDelList = new ArrayList(); + List vtepDelList = new ArrayList(); + List> allPaths = new ArrayList<>(); + try { + if (vtepDelCommitList != null && !vtepDelCommitList.isEmpty()) { + InstanceIdentifier path = InstanceIdentifier.builder(TransportZones.class).build(); + Optional tZonesOptional = + ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker); + if (tZonesOptional.isPresent()) { + TransportZones tZones = tZonesOptional.get(); + for (TransportZone tZ : tZones.getTransportZone()) { + if (tZ.getSubnets() == null || tZ.getSubnets().isEmpty()) + continue; + for (Subnets sub : tZ.getSubnets()) { + vtepDelList.addAll(vtepDelCommitList); + for (Vteps vtep : vtepDelList) { + InstanceIdentifier vpath = + (InstanceIdentifier) InstanceIdentifier + .builder(TransportZones.class) + .child(TransportZone.class, tZ.getKey()) + .child(Subnets.class, sub.getKey()) + .child(Vteps.class, vtep.getKey()).build(); + if (sub.getVteps().remove(vtep)) { + vtepPaths.add(vpath); + if (sub.getVteps().size() == 0 || sub.getVteps() == null) { + subDelList.add(sub); + } + + } + } + } + } + + for (TransportZone tZ : tZones.getTransportZone()) { + if (tZ.getSubnets() == null || tZ.getSubnets().isEmpty()) + continue; + for (Subnets sub : subDelList) { + if (tZ.getSubnets().remove(sub)) { + InstanceIdentifier spath = + (InstanceIdentifier) InstanceIdentifier + .builder(TransportZones.class) + .child(TransportZone.class, tZ.getKey()) + .child(Subnets.class, sub.getKey()).build(); + subnetPaths.add(spath); + if (tZ.getSubnets() == null || tZ.getSubnets().size() == 0) { + tzDelList.add(tZ); + } + } + } + } + + for (TransportZone tZ : tzDelList) { + if (tZones.getTransportZone().remove(tZ)) { + InstanceIdentifier tpath = + (InstanceIdentifier) InstanceIdentifier.builder(TransportZones.class) + .child(TransportZone.class, tZ.getKey()).build(); + tzPaths.add(tpath); + if (tZones.getTransportZone() == null || tZones.getTransportZone().size() == 0) { + MDSALDataStoreUtils.asyncRemove(dataBroker, LogicalDatastoreType.CONFIGURATION, path, + ItmUtils.DEFAULT_CALLBACK); + return; + } + } + } + allPaths.addAll(vtepPaths); + allPaths.addAll(subnetPaths); + allPaths.addAll(tzPaths); + ItmUtils.asyncBulkRemove(dataBroker, LogicalDatastoreType.CONFIGURATION, allPaths, + ItmUtils.DEFAULT_CALLBACK); + } + vtepPaths.clear(); + subnetPaths.clear(); + tzPaths.clear(); + allPaths.clear(); + vtepDelCommitList.clear(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +/* + public void showState(TunnelsState tunnelsState, boolean tunnelMonitorEnabled) { + List tunnelLists = tunnelsState.getStateTunnelList(); + if (tunnelLists == null || tunnelLists.isEmpty()) { + System.out.println("No Logical Tunnels Exist"); + return; + } + if (!tunnelMonitorEnabled) { + System.out.println("Tunnel Monitoring is Off"); + } + System.out.println(String.format("%-16s %-16s %-16s %-10s %-16s %-8s %-10s %-10s", "Source-DPN", + "Destination-DPN", "SourcePortName", "Source-IP", "Destination-IP", "VLan-ID", "Trunk-State", + "Logical-Tunnel-State")); + System.out.println("----------------------------------------------------------------------------------------------------------------------"); + + for (StateTunnelList tunnel : tunnelLists) { + String logicaltunnelState = (tunnel.isLogicalTunnelState()) ? "UP" : "DOWN"; + try { + List trunks = + interfaceManager.getTunnelInterfacesOfLogicalGroup(tunnel.getLogicalTunnelGroupName()); + if (trunks != null && !trunks.isEmpty()) { + for (String trunk : trunks) { + List params = Arrays.asList(trunk.split(":")); + LOG.trace("trunk {} for LogicalIf {} ", trunk, tunnel.getLogicalTunnelGroupName()); + String trunkState = (OperationalIfmUtil.isInterfaceUp(dataBroker, trunk)) ? "UP" : "DOWN"; + System.out.println(String.format("%-16s %-16s %-16s %-10s %-16s %-8s %-10s %-10s", tunnel + .getSourceDPN().toString(), tunnel.getDestinationDPN().toString(), params + .get(1), params.get(3), params.get(4), params.get(2), trunkState, + logicaltunnelState)); + } + } else { + LOG.error("No trunks for " + tunnel.getLogicalTunnelGroupName()); + } + + } catch (InterfaceNotFoundException e) { + LOG.error("if not found " + tunnel.getLogicalTunnelGroupName()); + } + } + } +*/ + // deletes from ADD-cache if it exists. + public boolean isInCache(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask, + String gatewayIp, String transportZone) { + boolean exists = false; + VtepsKey vtepkey = new VtepsKey(dpnId, portName); + IpAddress ipAddressObj = new IpAddress(ipAddress.toCharArray()); + IpPrefix subnetMaskObj = new IpPrefix(subnetMask.toCharArray()); + IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray()); + if (gatewayIp != null) { + gatewayIpObj = new IpAddress(gatewayIp.toCharArray()); + } else { + LOG.debug("gateway is null"); + } + SubnetsKey subnetsKey = new SubnetsKey(subnetMaskObj); + Vteps vtepCli = + new VtepsBuilder().setDpnId(dpnId).setIpAddress(ipAddressObj).setKey(vtepkey) + .setPortname(portName).build(); + SubnetObject subObCli = new SubnetObject(gatewayIpObj, subnetsKey, subnetMaskObj, vlanId); + + if (tZones.containsKey(transportZone)) { + Map> subVtepMapTemp = (Map>) tZones.get(transportZone); + if (subVtepMapTemp.containsKey(subObCli)) { // if Subnet exists + List vtepListTemp = (List) subVtepMapTemp.get(subObCli); + if (vtepListTemp.contains(vtepCli)) { + exists = true; // return true if tzones has vtep + vtepListTemp.remove(vtepCli); + if (vtepListTemp.size() == 0) { + subVtepMapTemp.remove(subObCli); + if (subVtepMapTemp.size() == 0) { + tZones.remove(transportZone); + } + } + } else { + System.out.println("Vtep " + "has not been configured"); + } + } + } + return exists; + } + + public void configureTunnelType(String tZoneName, String tunnelType) { + LOG.debug("configureTunnelType {} for transportZone {}", tunnelType, tZoneName); + + TransportZone tZoneFromConfigDS = getTransportZoneFromConfigDS(tZoneName); + validateTunnelType(tZoneName, tunnelType,tZoneFromConfigDS); + + if (tZoneFromConfigDS != null) { + LOG.debug("Transport zone {} with tunnel type {} already exists. No action required.", tZoneName, + tunnelType); + return; + } + TransportZones transportZones = null; + List tZoneList = null; + InstanceIdentifier path = InstanceIdentifier.builder(TransportZones.class).build(); + Optional tZones = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker); + Class tunType = TunnelTypeVxlan.class; + if( tunnelType.equals(ITMConstants.TUNNEL_TYPE_VXLAN)) + tunType = TunnelTypeVxlan.class ; + else if( tunnelType.equals(ITMConstants.TUNNEL_TYPE_GRE) ) + tunType = TunnelTypeGre.class ; + + TransportZone tZone = new TransportZoneBuilder().setKey(new TransportZoneKey(tZoneName)) + .setTunnelType(tunType).build(); + if (tZones.isPresent()) { + tZoneList = tZones.get().getTransportZone(); + if(tZoneList == null || tZoneList.isEmpty()) { + tZoneList = new ArrayList(); + } + } else { + tZoneList = new ArrayList(); + } + tZoneList.add(tZone); + transportZones = new TransportZonesBuilder().setTransportZone(tZoneList).build(); + ItmUtils.syncWrite(LogicalDatastoreType.CONFIGURATION, path, transportZones, dataBroker); + + } + + /** + * Validate tunnel type. + * + * @param tZoneName + * the t zone name + * @param tunnelType + * the tunnel type + */ + private void validateTunnelType(String tZoneName, String tunnelType,TransportZone tZoneFromConfigDS) { + /* + String strTunnelType = ItmUtils.validateTunnelType(tunnelType); + + TransportZone tZone = getTransportZone(tZoneName); + if (tZone != null) { + if (!StringUtils.equalsIgnoreCase(strTunnelType, tZone.getTunnelType()) + && ItmUtils.isNotEmpty(tZone.getSubnets())) { + String errorMsg = new StringBuilder("Changing the tunnel type from ").append(tZone.getTunnelType()) + .append(" to ").append(strTunnelType) + .append(" is not allowed for already configured transport zone [").append(tZoneName) + .append("].").toString(); + Preconditions.checkArgument(false, errorMsg); + } + } + */ + String strTunnelType = ItmUtils.validateTunnelType(tunnelType); + Class tunType ; + if( strTunnelType.equals(ITMConstants.TUNNEL_TYPE_VXLAN)) + tunType = TunnelTypeVxlan.class ; + else + tunType = TunnelTypeGre.class ; + //TransportZone tZone = getTransportZone(tZoneName); + // if (tZone != null) { + if (tZoneFromConfigDS != null) { + if( (!tZoneFromConfigDS.getTunnelType().equals(tunType)) && ItmUtils.isNotEmpty(tZoneFromConfigDS.getSubnets())) { + String errorMsg = new StringBuilder("Changing the tunnel type from ").append(tZoneFromConfigDS.getTunnelType()) + .append(" to ").append(strTunnelType) + .append(" is not allowed for already configured transport zone [").append(tZoneName) + .append("].").toString(); + Preconditions.checkArgument(false, errorMsg); + } + } + } + + public void configureTunnelMonitorEnabled(boolean monitorEnabled) { + InstanceIdentifier path = InstanceIdentifier.builder(TunnelMonitorEnabled.class).build(); + Optional storedTunnelMonitor = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker); + if (!storedTunnelMonitor.isPresent() || storedTunnelMonitor.get().isEnabled() != monitorEnabled) { + TunnelMonitorEnabled tunnelMonitor = new TunnelMonitorEnabledBuilder().setEnabled(monitorEnabled).build(); + ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, path, tunnelMonitor, dataBroker, + ItmUtils.DEFAULT_CALLBACK); + } + } + + public void configureTunnelMonitorInterval(int interval) { + InstanceIdentifier path = InstanceIdentifier.builder(TunnelMonitorInterval.class).build(); + Optional storedTunnelMonitor = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker); + if (!storedTunnelMonitor.isPresent() || storedTunnelMonitor.get().getInterval() != interval) { + TunnelMonitorInterval tunnelMonitor = new TunnelMonitorIntervalBuilder().setInterval(interval).build(); + ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, path, tunnelMonitor, dataBroker, + ItmUtils.DEFAULT_CALLBACK); + } + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepCommit.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepCommit.java new file mode 100644 index 00000000..3d46c31c --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepCommit.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016 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.itm.cli; + +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.commands.Option; +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.vpnservice.itm.api.IITMProvider; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +@Command(scope = "tep", name = "commit", + description = "commits the configuration so that actual tunnel-building happens") +public class TepCommit extends OsgiCommandSupport { + private static final Logger logger = LoggerFactory.getLogger(TepCommit.class); + + private IITMProvider itmProvider; + + public void setItmProvider(IITMProvider itmProvider) { + this.itmProvider = itmProvider; + } + + @Override + protected Object doExecute() throws Exception { + + try { + itmProvider.commitTeps(); + logger.debug("Executing commit TEP command"); + } catch (NullPointerException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepConfigureTunnelType.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepConfigureTunnelType.java new file mode 100644 index 00000000..aabab224 --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepConfigureTunnelType.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016 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.itm.cli; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +@Command(scope = "tep", name = "configure-tunnelType", + description = "configuring the tunnel type for a transport zone") +public class TepConfigureTunnelType extends OsgiCommandSupport { + + @Argument(index = 0, name = "TransportZoneName", description = "TransportZoneName", required = true, multiValued = false) + private String tZoneName; + @Argument(index = 1, name = "TunnelType", description = "Tunnel-Type", required = true, multiValued = false) + private String tunnelType; + + + private static final Logger LOG = LoggerFactory.getLogger(TepConfigureTunnelType.class); + + private IITMProvider itmProvider; + + public void setItmProvider(IITMProvider itmProvider) { + this.itmProvider = itmProvider; + } + + @Override + protected Object doExecute() { + try { + LOG.debug("TepConfigureTunnelType: configureTunnelType {} for transportZone {}", tunnelType, tZoneName); + itmProvider.configureTunnelType(tZoneName, tunnelType); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } catch (Exception e) { + System.out.println(e.getMessage()); + LOG.error("Exception occurred during execution of command \"tep:configure-tunnelType\": ", e); + } + return null; + } + +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepDelete.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepDelete.java new file mode 100644 index 00000000..0ecba0b5 --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepDelete.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016 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.itm.cli; + +import java.math.BigInteger; + +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.commands.Option; +import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Command(scope = "tep", name = "delete", description = "deleting a tunnel end point") +public class TepDelete extends OsgiCommandSupport { + + @Argument(index = 0, name = "dpnId", description = "DPN-ID", required = false, multiValued = false) + private BigInteger dpnId; + @Argument(index = 1, name = "portName", description = "port-number", required = false, multiValued = false) + private String portName; + @Argument(index = 2, name = "vlanId", description = "vlan-id", required = false, multiValued = false) + private Integer vlanId; + @Argument(index = 3, name = "ipAddress", description = "ip-address", required = false, multiValued = false) + private String ipAddress; + @Argument(index = 4, name = "subnetMask", description = "subnet-Mask", required = false, multiValued = false) + private String subnetMask; + @Argument(index = 5, name = "gatewayIp", description = "gateway-ip", required = false, multiValued = false) + private String gatewayIp; + @Argument(index = 6, name = "transportZone", description = "transport_zone", required = false, multiValued = false) + private String transportZone; + + private static final Logger logger = LoggerFactory.getLogger(TepDelete.class); + private IITMProvider itmProvider; + + public void setItmProvider(IITMProvider itmProvider) { + this.itmProvider = itmProvider; + } + @Override + protected Object doExecute() throws Exception { + + if (dpnId == null || portName == null || vlanId == null || ipAddress == null || subnetMask == null + || transportZone == null) { + System.out.println("Insufficient Arguments"); + System.out.println("Correct Usage : exec tep-delete dpnId portName vlanId ipAddress subnetMask gatewayIp transportZone"); + return null; + } + itmProvider.deleteVtep(dpnId, portName, vlanId, ipAddress, subnetMask, gatewayIp, transportZone); + logger.trace("Executing delete TEP command"); + + return null; + + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepDeleteDatastore.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepDeleteDatastore.java new file mode 100644 index 00000000..1960a515 --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepDeleteDatastore.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016 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.itm.cli; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.commands.Option; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.util.concurrent.Futures; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.FutureCallback; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +//import org.opendaylight.vpnservice.interfacemgr.util.ConfigIfmUtil; +import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.opendaylight.vpnservice.itm.impl.ItmUtils; +import org.opendaylight.vpnservice.mdsalutil.MDSALDataStoreUtils; +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.InterfacesState; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.Tunnels; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.TunnelsState; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.tunnels_state.StateTunnelList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones; +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.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext; + +@Command(scope = "tep", name = "deleteDatastore", description = "view the configured tunnel endpoints") +public class TepDeleteDatastore extends OsgiCommandSupport { + private static final Logger logger = LoggerFactory.getLogger(TepDeleteDatastore.class); + private IITMProvider itmProvider; + + public void setItmProvider(IITMProvider itmProvider) { + this.itmProvider = itmProvider; + } + + @Override + protected Object doExecute() throws Exception { + DataBroker dataBroker = itmProvider.getDataBroker(); + InstanceIdentifier < TransportZones > itmConfigPath = InstanceIdentifier.builder(TransportZones.class).build(); + // InstanceIdentifier tunnelsConfigPath = InstanceIdentifier.builder(Tunnels.class).build(); + InstanceIdentifier InterfacesConfigPath = InstanceIdentifier.builder(Interfaces.class).build(); + // InstanceIdentifier tnStateOpPath = InstanceIdentifier.builder(TunnelsState.class).build(); + InstanceIdentifier ifStateOpPath = InstanceIdentifier.builder(InterfacesState.class).build(); + InstanceIdentifier frmConfigPath = InstanceIdentifier.builder(Nodes.class).build(); + List> allConfigPaths = + new ArrayList<>(); + allConfigPaths.add((InstanceIdentifier) itmConfigPath); + allConfigPaths.add((InstanceIdentifier) InterfacesConfigPath); + allConfigPaths.add((InstanceIdentifier) frmConfigPath); + //allConfigPaths.add((InstanceIdentifier) tunnelsConfigPath); + ItmUtils.asyncBulkRemove(dataBroker, LogicalDatastoreType.CONFIGURATION,allConfigPaths, + ItmUtils.DEFAULT_CALLBACK); + List> allOperationalPaths = + new ArrayList<>(); + // allOperationalPaths.add((InstanceIdentifier) tnStateOpPath); + allOperationalPaths.add((InstanceIdentifier) ifStateOpPath); + ItmUtils.asyncBulkRemove(dataBroker, LogicalDatastoreType.OPERATIONAL, allOperationalPaths, + ItmUtils.DEFAULT_CALLBACK); + + return null; + } + +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepEnableTunnelMonitor.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepEnableTunnelMonitor.java new file mode 100644 index 00000000..622d3d91 --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepEnableTunnelMonitor.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016 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.itm.cli; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Command(scope = "tep", name = "enable-tunnel-monitor", description = "switch ON/OFF supervision of VxLAN tunnels") +public class TepEnableTunnelMonitor extends OsgiCommandSupport { + + private static final Logger logger = LoggerFactory.getLogger(TepEnableTunnelMonitor.class); + + @Argument(index = 0, name = "true|false", description = "true|false to enable/disable Tunnel Monitoring", required = true, multiValued = false) + private Boolean enableTunnelMonitor; + + private IITMProvider itmProvider; + + public void setItmProvider(IITMProvider itmProvider) { + this.itmProvider = itmProvider; + } + + @Override + protected Object doExecute() { + try { + logger.debug("Executing Enable Tunnel Monitor command"); + itmProvider.configureTunnelMonitorEnabled(enableTunnelMonitor); + } catch (NullPointerException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepMonitor.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepMonitor.java new file mode 100644 index 00000000..a6939191 --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepMonitor.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016 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.itm.cli; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Command(scope = "tep", name = "monitor-interval", description = "configuring tunnel monitoring time interval") +public class TepMonitor extends OsgiCommandSupport { + + @Argument(index = 0, name = "interval", description = "monitoring interval", required = true, + multiValued = false) + private Integer interval; + + private static final Logger logger = LoggerFactory.getLogger(TepMonitor.class); + private IITMProvider itmProvider; + + public void setItmProvider(IITMProvider itmProvider) { + this.itmProvider = itmProvider; + } + + @Override + protected Object doExecute() { + try { + logger.debug("Executing TEP monitor command with interval: " + "\t" + interval); + if(!(interval >= 5 && interval <=30)){ + System.out.println("Monitoring Interval must be in the range 5 - 30"); + } + else { + itmProvider.configureTunnelMonitorInterval(interval); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepShow.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepShow.java new file mode 100644 index 00000000..cb44dedc --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepShow.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016 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.itm.cli; + +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.commands.Option; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.util.concurrent.Futures; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.FutureCallback; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones; +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.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext; + +@Command(scope = "tep", name = "show", description = "view the configured tunnel endpoints") +public class TepShow extends OsgiCommandSupport { + private static final Logger logger = LoggerFactory.getLogger(TepShow.class); + private IITMProvider itmProvider; + + public void setItmProvider(IITMProvider itmProvider) { + this.itmProvider = itmProvider; + } + + @Override + protected Object doExecute() throws Exception { + logger.debug("Executing show TEP command"); + itmProvider.showTeps(); + return null; + } + +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepShowState.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepShowState.java new file mode 100644 index 00000000..a2a254de --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepShowState.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016 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.itm.cli; + +import com.google.common.base.Optional; + +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.opendaylight.vpnservice.itm.impl.ItmUtils; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.TunnelsState; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import java.util.ArrayList; +import java.util.List; + +@Command(scope = "tep", name = "show-state", description="Monitors tunnel state") + + public class TepShowState extends OsgiCommandSupport { + + private IITMProvider itmProvider; + + public void setItmProvider(IITMProvider itmProvider) { + this.itmProvider = itmProvider; + } + + @Override + protected Object doExecute() throws Exception { + /* + DataBroker broker = itmProvider.getDataBroker(); + List result = new ArrayList(); + InstanceIdentifier path = InstanceIdentifier.builder(TunnelsState.class).build(); + Optional tunnels = ItmUtils.read(LogicalDatastoreType.OPERATIONAL, path, broker); + if (tunnels.isPresent()) { + itmProvider.showState(tunnels.get()); + } + else + System.out.println("No Logical Tunnels Exist"); + */ + System.out.println( "Logical Tunnels state is not currently supported"); + return null; + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepStateShow.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepStateShow.java new file mode 100644 index 00000000..6d7d8d3f --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/TepStateShow.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016 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.itm.cli; + +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.commands.Option; + +@Command(scope = "tep", name = "state-show", description="Monitors tunnel state") + + public class TepStateShow extends OsgiCommandSupport { + + @Override + + protected Object doExecute() throws Exception { + + System.out.println("Executing show TEP states command"); + + return null; + + } + } diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/VtepSchemaAdd.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/VtepSchemaAdd.java new file mode 100644 index 00000000..5e74bb16 --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/VtepSchemaAdd.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2016 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.itm.cli; + +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.commands.Option; +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.opendaylight.vpnservice.itm.globals.ITMConstants; +import org.opendaylight.vpnservice.itm.impl.ItmUtils; +import org.opendaylight.vpnservice.itm.cli.ItmCliUtils; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Class which implements karaf command "vtep:schema-add". + */ +@Command(scope = "vtep", name = "schema-add", description = "Adding a VTEP schema.") +public class VtepSchemaAdd extends OsgiCommandSupport { + + private static final String SCHEMA_NAME = "--schema-name"; + private static final String PORT_NAME = "--port-name"; + private static final String VLAN_ID = "--vlan-id"; + private static final String SUBNET_CIDR = "--subnet-cidr"; + private static final String TRANSPORT_ZONE = "--transport-zone"; + private static final String DPN_IDS = "--dpn-ids"; + private static final String GATEWAY_IP = "--gateway-ip"; + private static final String TUNNEL_TYPE = "--tunnel-type"; + private static final String EXCLUDE_IP_FILTER = "--exclude-ip-filter"; + + /** The schema name. */ + @Option(name = SCHEMA_NAME, aliases = { "-s" }, description = "Schema name", required = true, multiValued = false) + private String schemaName; + + /** The port name. */ + @Option(name = PORT_NAME, aliases = { "-p" }, description = "Port name", required = true, multiValued = false) + private String portName; + + /** The vlan id. */ + @Option(name = VLAN_ID, aliases = { "-v" }, description = "VLAN ID", required = true, multiValued = false) + private Integer vlanId; + + /** The subnet mask. */ + @Option(name = SUBNET_CIDR, aliases = { + "-sc" }, description = "Subnet Mask in CIDR-notation string, e.g. 10.0.0.0/24", required = true, multiValued = false) + private String subnetCIDR; + + /** The transport zone. */ + @Option(name = TRANSPORT_ZONE, aliases = { + "-tz" }, description = "Transport zone", required = true, multiValued = false) + private String transportZone; + + /** The dpn ids. */ + @Option(name = DPN_IDS, aliases = { + "-d" }, description = "DPN ID's in comma separated values. e.g: 2,3,10", required = false, multiValued = false) + private String dpnIds; + + /** The gateway ip. */ + @Option(name = GATEWAY_IP, aliases = { + "-g" }, description = "Gateway IP address", required = false, multiValued = false) + private String gatewayIp; + + /** The tunnel type. */ + @Option(name = TUNNEL_TYPE, aliases = { + "-t" }, description = "Tunnel type. Value: VXLAN | GRE. Default: VXLAN", required = false, multiValued = false) + private String tunnelType; + + /** The exclude ip filter. */ + @Option(name = EXCLUDE_IP_FILTER, aliases = { + "-ex" }, description = "IP Addresses which needs to be excluded from the specified subnet. IP address range or comma separated IP addresses can to be specified. e.g: 10.0.0.1-10.0.0.20,10.0.0.30,10.0.0.35", required = false, multiValued = false) + private String excludeIpFilter; + + /** The Constant logger. */ + private static final Logger LOG = LoggerFactory.getLogger(VtepSchemaAdd.class); + + /** The itm provider. */ + private IITMProvider itmProvider; + + /** + * Sets the itm provider. + * + * @param itmProvider + * the new itm provider + */ + public void setItmProvider(IITMProvider itmProvider) { + this.itmProvider = itmProvider; + } + + /** + * Command Usage. + */ + private void usage() { + System.out.println(String.format( + "usage: vtep:schema-add [%s schema-name] [%s port-name] [%s vlan-id] [%s subnet-cidr] [%s transport-zone] [%s dpn-ids] [%s gateway-ip] [%s tunnel-type] [%s exclude-ip-filter]", + SCHEMA_NAME, PORT_NAME, VLAN_ID, SUBNET_CIDR, TRANSPORT_ZONE, DPN_IDS, GATEWAY_IP, TUNNEL_TYPE, + EXCLUDE_IP_FILTER)); + } + + /* + * (non-Javadoc) + * + * @see org.apache.karaf.shell.console.AbstractAction#doExecute() + */ + @Override + protected Object doExecute() { + try { + if (this.schemaName == null || this.portName == null || this.vlanId == null || this.subnetCIDR == null + || this.transportZone == null) { + usage(); + return null; + } + LOG.debug("Executing vtep:schema-add command\t {} \t {} \t {} \t {} \t {} \t {} \t {} \t {} \t {}", schemaName, + portName, vlanId, subnetCIDR, gatewayIp, transportZone, tunnelType, dpnIds, excludeIpFilter); + + if( null == tunnelType) { + tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN ; + } + VtepConfigSchema schema = ItmUtils.constructVtepConfigSchema(schemaName, portName, vlanId, subnetCIDR, + gatewayIp, transportZone, tunnelType, ItmCliUtils.constructDpnIdList(dpnIds), excludeIpFilter); + this.itmProvider.addVtepConfigSchema(schema); + + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } catch (Exception e) { + LOG.error("Exception occurred during execution of command \"vtep:schema-add\": ", e); + } + return null; + } + +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/VtepSchemaDelete.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/VtepSchemaDelete.java new file mode 100644 index 00000000..5b7a22a9 --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/VtepSchemaDelete.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016 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.itm.cli; + +import org.apache.commons.lang3.StringUtils; +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Class which implements karaf command "vtep:schema-delete". + */ +@Command(scope = "vtep", name = "schema-delete", description = "Delete VTEP schema.") +public class VtepSchemaDelete extends OsgiCommandSupport { + + private static final String ALL = "all"; + + @Argument(index = 0, name = ALL, description = "Delete all VTEP schemas", required = true, multiValued = false) + String deleteAll = null; + + /** The Constant logger. */ + private static final Logger LOG = LoggerFactory.getLogger(VtepSchemaDelete.class); + + /** The itm provider. */ + private IITMProvider itmProvider; + + /** + * Sets the itm provider. + * + * @param itmProvider + * the new itm provider + */ + public void setItmProvider(IITMProvider itmProvider) { + this.itmProvider = itmProvider; + } + + private void usage() { + System.out.println("usage: vtep:schema-delete all"); + } + + /* + * (non-Javadoc) + * + * @see org.apache.karaf.shell.console.AbstractAction#doExecute() + */ + @Override + protected Object doExecute() { + try { + if (this.deleteAll == null || !StringUtils.equalsIgnoreCase(ALL, this.deleteAll)) { + usage(); + return null; + } + LOG.debug("Executing vtep:schema-delete command\t {} ", this.deleteAll); + this.itmProvider.deleteAllVtepSchemas(); + + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } catch (Exception e) { + LOG.error("Exception occurred during execution of command \"vtep:schema-delete all\": ", e); + } + return null; + } + +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/VtepSchemaShow.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/VtepSchemaShow.java new file mode 100644 index 00000000..139b82a0 --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/VtepSchemaShow.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2016 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.itm.cli; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.opendaylight.vpnservice.itm.globals.ITMConstants; +import org.opendaylight.vpnservice.itm.impl.ItmUtils; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Class which implements karaf command "vtep:schema-show". + */ +@Command(scope = "vtep", name = "schema-show", description = "Show all VTEP schemas.") +public class VtepSchemaShow extends OsgiCommandSupport { + + /** The schema name. */ + @Argument(index = 0, name = "schemaName", description = "Schema name", required = false, multiValued = false) + private String schemaName; + + private static String VTEP_CONFIG_SCHEMA_CLI_FORMAT = "%-14s %-12s %-8s %-16s %-13s %-14s %-11s %-20s %-32s"; + public static final String HEADER_UNDERLINE = "---------------------------------------------------------------------------------------------------------------------------------------"; + + /** The Constant logger. */ + private static final Logger LOG = LoggerFactory.getLogger(VtepSchemaShow.class); + + /** The itm provider. */ + private IITMProvider itmProvider; + + /** + * Sets the itm provider. + * + * @param itmProvider + * the new itm provider + */ + public void setItmProvider(IITMProvider itmProvider) { + this.itmProvider = itmProvider; + } + + /* + * (non-Javadoc) + * + * @see org.apache.karaf.shell.console.AbstractAction#doExecute() + */ + @Override + protected Object doExecute() { + LOG.debug("Executing command: schema-show {} ", this.schemaName); + try { + if (this.schemaName != null) { + VtepConfigSchema schema = this.itmProvider.getVtepConfigSchema(this.schemaName); + if (schema == null) { + System.out.println("No VTEP schema present with name: " + this.schemaName); + } else { + System.out.println(getHeaderOutput()); + printSchema(schema); + } + } else { + printAllVtepSchemas(); + } + } catch (Exception e) { + LOG.error("Exception occurred during execution of command \"vtep:schema-show\": ", e); + } + return null; + } + + /** + * Prints all vtep schemas. + */ + private void printAllVtepSchemas() { + List schemas = this.itmProvider.getAllVtepConfigSchemas(); + if (schemas == null || schemas.isEmpty()) { + System.out.println("No VTEP schemas present."); + return; + } + System.out.println(getHeaderOutput()); + for (VtepConfigSchema schema : schemas) { + printSchema(schema); + } + } + + /** + * Prints the schema. + * + * @param schema + * the schema + */ + private void printSchema(VtepConfigSchema schema) { + List lstDpnIds = (schema.getDpnIds() == null) ? Collections. emptyList() + : ItmUtils.getDpnIdList(schema.getDpnIds()); + List lstIpFilter = getExcludeIpFilterAsList(schema.getExcludeIpFilter()); + + Iterator dpnIterator = lstDpnIds.iterator(); + Iterator ipFilterIterator = lstIpFilter.iterator(); + + String portName = StringUtils.defaultString(schema.getPortName()); + String vlanId = String.valueOf(schema.getVlanId()); + String subnetCIDR = (schema.getSubnet() == null) ? StringUtils.EMPTY + : String.valueOf(schema.getSubnet().getValue()); + String gatewayIp = (schema.getGatewayIp() == null) ? StringUtils.EMPTY + : String.valueOf(schema.getGatewayIp().getValue()); + String transportZone = StringUtils.defaultString(schema.getTransportZoneName()); + String strTunnelType ; + + Class tunType = schema.getTunnelType(); + + if( tunType.equals(TunnelTypeGre.class) ) + strTunnelType = ITMConstants.TUNNEL_TYPE_GRE ; + else + strTunnelType = ITMConstants.TUNNEL_TYPE_VXLAN ; + String dpnId = (dpnIterator.hasNext() ? String.valueOf(dpnIterator.next()) : StringUtils.EMPTY); + String excludeIpFilter = (ipFilterIterator.hasNext() ? String.valueOf(ipFilterIterator.next()) + : StringUtils.EMPTY); + + // Print first row + System.out.println(String.format(VTEP_CONFIG_SCHEMA_CLI_FORMAT, schema.getSchemaName(), portName, vlanId, + subnetCIDR, gatewayIp, transportZone, strTunnelType, dpnId, excludeIpFilter)); + while (dpnIterator.hasNext() || ipFilterIterator.hasNext()) { + dpnId = (dpnIterator.hasNext() ? String.valueOf(dpnIterator.next()) : StringUtils.EMPTY); + excludeIpFilter = (ipFilterIterator.hasNext() ? String.valueOf(ipFilterIterator.next()) + : StringUtils.EMPTY); + System.out.println(String.format(VTEP_CONFIG_SCHEMA_CLI_FORMAT, StringUtils.EMPTY, StringUtils.EMPTY, + StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, + dpnId, excludeIpFilter)); + } + System.out.println(System.lineSeparator()); + } + + /** + * Gets the exclude ip filter as list. + * + * @param excludeIpFilter + * the exclude ip filter + * @return the exclude ip filter as list + */ + private List getExcludeIpFilterAsList(String excludeIpFilter) { + if (StringUtils.isBlank(excludeIpFilter)) { + return Collections.emptyList(); + } + final String[] arrIpsOrRange = StringUtils.split(excludeIpFilter, ','); + return Arrays.asList(arrIpsOrRange); + } + + /** + * Gets the vtep config schema header output. + * + * @return the vtep config schema header output + */ + private String getHeaderOutput() { + StringBuilder headerBuilder = new StringBuilder(); + headerBuilder.append(String.format(VTEP_CONFIG_SCHEMA_CLI_FORMAT, "SchemaName", "PortName", "VlanID", "Subnet", + "GatewayIP", "TransportZone", "TunnelType", "DPN-IDS", "ExcludeIpFilter")); + headerBuilder.append('\n'); + headerBuilder.append(HEADER_UNDERLINE); + return headerBuilder.toString(); + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/VtepSchemaUpdate.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/VtepSchemaUpdate.java new file mode 100644 index 00000000..008214b1 --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/cli/VtepSchemaUpdate.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016 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.itm.cli; + +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.commands.Option; +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Class which implements karaf command "vtep:schema-update". + */ +@Command(scope = "vtep", name = "schema-update", description = "Update VTEP schema.") +public class VtepSchemaUpdate extends OsgiCommandSupport { + + private static final String SCHEMA_NAME = "--schema-name"; + private static final String AD = "--add-dpn-ids"; + private static final String DD = "--del-dpn-ids"; + + /** The schema name. */ + @Option(name = SCHEMA_NAME, aliases = { "-s" }, description = "Schema name", required = true, multiValued = false) + private String schemaName; + + /** The dpn ids for add. */ + @Option(name = AD, aliases = { + "-ad" }, description = "DPN ID's to be added to schema in a comma separated value format. e.g: 2,3,10", required = false, multiValued = false) + private String dpnIdsForAdd; + + /** The dpn ids for delete. */ + @Option(name = DD, aliases = { + "-dd" }, description = "DPN ID's to be deleted from schema in a comma separated value format. e.g: 2,3,10", required = false, multiValued = false) + private String dpnIdsForDelete; + + /** The Constant logger. */ + private static final Logger LOG = LoggerFactory.getLogger(VtepSchemaUpdate.class); + + /** The itm provider. */ + private IITMProvider itmProvider; + + /** + * Sets the itm provider. + * + * @param itmProvider + * the new itm provider + */ + public void setItmProvider(IITMProvider itmProvider) { + this.itmProvider = itmProvider; + } + + /** + * Command Usage. + */ + private void usage() { + System.out.println( + String.format("usage: vtep:schema-update [%s schema-name] [%s dpn-ids-for-add] [%s dpn-ids-for-delete]", + SCHEMA_NAME, AD, DD)); + } + + /* + * (non-Javadoc) + * + * @see org.apache.karaf.shell.console.AbstractAction#doExecute() + */ + @Override + protected Object doExecute() { + try { + if (this.dpnIdsForAdd == null && this.dpnIdsForDelete == null) { + System.out.println(String.format("Atleast one of the parameters [%s or %s] is mandatory", AD, DD)); + usage(); + return null; + } + LOG.debug("Executing vtep:schema-update command\t {} \t {} \t {} ", this.schemaName, this.dpnIdsForAdd, + this.dpnIdsForDelete); + + this.itmProvider.updateVtepSchema(this.schemaName, ItmCliUtils.constructDpnIdList(this.dpnIdsForAdd), + ItmCliUtils.constructDpnIdList(this.dpnIdsForDelete)); + + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } catch (Exception e) { + LOG.error("Exception occurred during execution of command \"vtep:schema-update\": ", e); + } + return null; + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/HwVtep.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/HwVtep.java new file mode 100644 index 00000000..800ea62c --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/HwVtep.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2016 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.itm.confighelpers; + +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.inet.types.rev100924.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase; + +/** + * Created by eanraju on 02-Feb-16. + */ +public class HwVtep { + + private String transportZone; + private Class tunnel_type; + private IpPrefix ipPrefix; + private IpAddress gatewayIP; + private int vlanID; + private String topo_id; + private String node_id; + IpAddress hwIp; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + HwVtep HwVtep = (HwVtep) o; + + if (vlanID != HwVtep.vlanID) return false; + if (!transportZone.equals(HwVtep.transportZone)) return false; + if (tunnel_type != null ? !tunnel_type.equals(HwVtep.tunnel_type) : HwVtep.tunnel_type != null) return false; + if (!ipPrefix.equals(HwVtep.ipPrefix)) return false; + if (gatewayIP != null ? !gatewayIP.equals(HwVtep.gatewayIP) : HwVtep.gatewayIP != null) return false; + if (!topo_id.equals(HwVtep.topo_id)) return false; + if (!node_id.equals(HwVtep.node_id)) return false; + return hwIp.equals(HwVtep.hwIp); + + } + + @Override + public String toString() { + return "HwVtep{" + + "transportZone='" + transportZone + '\'' + + ", tunnel_type=" + tunnel_type + + ", ipPrefix=" + ipPrefix + + ", gatewayIP=" + gatewayIP + + ", vlanID=" + vlanID + + ", topo_id='" + topo_id + '\'' + + ", node_id='" + node_id + '\'' + + ", hwIp=" + hwIp + + '}'; + } + + @Override + public int hashCode() { + int result = transportZone.hashCode(); + result = 31 * result + (tunnel_type != null ? tunnel_type.hashCode() : 0); + result = 31 * result + ipPrefix.hashCode(); + result = 31 * result + (gatewayIP != null ? gatewayIP.hashCode() : 0); + result = 31 * result + vlanID; + result = 31 * result + topo_id.hashCode(); + result = 31 * result + node_id.hashCode(); + result = 31 * result + hwIp.hashCode(); + return result; + } + + public String getTransportZone() { + return transportZone; + } + + public void setTransportZone(String transportZone) { + this.transportZone = transportZone; + } + + public Class getTunnel_type() { + return tunnel_type; + } + + public void setTunnel_type(Class tunnel_type) { + this.tunnel_type = tunnel_type; + } + + public IpPrefix getIpPrefix() { + return ipPrefix; + } + + public void setIpPrefix(IpPrefix ipPrefix) { + this.ipPrefix = ipPrefix; + } + + public IpAddress getGatewayIP() { + return gatewayIP; + } + + public void setGatewayIP(IpAddress gatewayIP) { + this.gatewayIP = gatewayIP; + } + + public int getVlanID() { + return vlanID; + } + + public void setVlanID(int vlanID) { + this.vlanID = vlanID; + } + + public String getTopo_id() { + return topo_id; + } + + public void setTopo_id(String topo_id) { + this.topo_id = topo_id; + } + + public String getNode_id() { + return node_id; + } + + public void setNode_id(String node_id) { + this.node_id = node_id; + } + + public IpAddress getHwIp() { + return hwIp; + } + + public void setHwIp(IpAddress hwIp) { + this.hwIp = hwIp; + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmExternalTunnelAddWorker.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmExternalTunnelAddWorker.java index 54277d4a..6a0ed5be 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmExternalTunnelAddWorker.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmExternalTunnelAddWorker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015, 2016 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, @@ -11,23 +11,38 @@ import java.math.BigInteger; import java.util.ArrayList; import java.util.List; +import com.google.common.base.Optional; 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.vpnservice.itm.impl.ItmUtils; 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.inet.types.rev100924.IpPrefix; +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.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.ExternalTunnelList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPoints; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnelKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZoneKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.Subnets; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVteps; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.Vteps; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.*; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.commons.net.util.SubnetUtils; @@ -36,7 +51,7 @@ import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.ListenableFuture; public class ItmExternalTunnelAddWorker { - private static final Logger logger = LoggerFactory.getLogger(ItmExternalTunnelAddWorker.class ) ; + private static final Logger logger = LoggerFactory.getLogger(ItmExternalTunnelAddWorker.class); private static final FutureCallback DEFAULT_CALLBACK = new FutureCallback() { @@ -46,49 +61,200 @@ public class ItmExternalTunnelAddWorker { public void onFailure(Throwable error) { logger.error("Error in Datastore operation", error); - }; + } + + ; }; public static List> buildTunnelsToExternalEndPoint(DataBroker dataBroker, IdManagerService idManagerService, List cfgDpnList, IpAddress extIp, Class tunType) { List> futures = new ArrayList<>(); WriteTransaction t = dataBroker.newWriteOnlyTransaction(); - if( null != cfgDpnList) { - for( DPNTEPsInfo teps : cfgDpnList ) { - // CHECK -- Assumption -- Only one End Point / Dpn for GRE/Vxlan Tunnels - TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0) ; - String interfaceName = firstEndPt.getInterfaceName() ; - String trunkInterfaceName = ItmUtils.getTrunkInterfaceName(idManagerService, interfaceName, firstEndPt.getIpAddress().getIpv4Address().getValue(), extIp.getIpv4Address().getValue()) ; - char[] subnetMaskArray = firstEndPt.getSubnetMask().getValue() ; - String subnetMaskStr = String.valueOf(subnetMaskArray) ; - SubnetUtils utils = new SubnetUtils(subnetMaskStr); - String dcGwyIpStr = String.valueOf(extIp.getValue()); - IpAddress gwyIpAddress = (utils.getInfo().isInRange(dcGwyIpStr) ) ? null : firstEndPt.getGwIpAddress() ; - String ifDescription = tunType.getName(); - logger.debug( " Creating Trunk Interface with parameters trunk I/f Name - {}, parent I/f name - {}, source IP - {}, DC Gateway IP - {} gateway IP - {}",trunkInterfaceName, interfaceName, firstEndPt.getIpAddress(), extIp, gwyIpAddress ) ; - Interface iface = ItmUtils.buildTunnelInterface(teps.getDPNID(), trunkInterfaceName, String.format( "%s %s",ifDescription, "Trunk Interface"), true, tunType, firstEndPt.getIpAddress(), extIp, gwyIpAddress, false) ; - logger.debug( " Trunk Interface builder - {} ", iface ) ; - InstanceIdentifier trunkIdentifier = ItmUtils.buildId(trunkInterfaceName); - logger.debug( " Trunk Interface Identifier - {} ", trunkIdentifier ) ; - logger.trace( " Writing Trunk Interface to Config DS {}, {} ", trunkIdentifier, iface ) ; - t.merge(LogicalDatastoreType.CONFIGURATION, trunkIdentifier, iface, true); - // update external_tunnel_list ds - InstanceIdentifier path = InstanceIdentifier.create( - ExternalTunnelList.class) - .child(ExternalTunnel.class, new ExternalTunnelKey(extIp, teps.getDPNID())); - ExternalTunnel tnl = ItmUtils.buildExternalTunnel(teps.getDPNID(), extIp, trunkInterfaceName); - t.merge(LogicalDatastoreType.CONFIGURATION,path, tnl, true) ; - } - futures.add( t.submit()) ; - } - return futures ; + if (null != cfgDpnList) { + for (DPNTEPsInfo teps : cfgDpnList) { + // CHECK -- Assumption -- Only one End Point / Dpn for GRE/Vxlan Tunnels + TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0); + String interfaceName = firstEndPt.getInterfaceName(); + String trunkInterfaceName = ItmUtils.getTrunkInterfaceName(idManagerService, interfaceName, firstEndPt.getIpAddress().getIpv4Address().getValue(), extIp.getIpv4Address().getValue()); + char[] subnetMaskArray = firstEndPt.getSubnetMask().getValue(); + String subnetMaskStr = String.valueOf(subnetMaskArray); + SubnetUtils utils = new SubnetUtils(subnetMaskStr); + String dcGwyIpStr = String.valueOf(extIp.getValue()); + IpAddress gwyIpAddress = (utils.getInfo().isInRange(dcGwyIpStr)) ? null : firstEndPt.getGwIpAddress(); + String ifDescription = tunType.getName(); + logger.debug(" Creating Trunk Interface with parameters trunk I/f Name - {}, parent I/f name - {}, source IP - {}, DC Gateway IP - {} gateway IP - {}", trunkInterfaceName, interfaceName, firstEndPt.getIpAddress(), extIp, gwyIpAddress); + Interface iface = ItmUtils.buildTunnelInterface(teps.getDPNID(), trunkInterfaceName, String.format("%s %s", ifDescription, "Trunk Interface"), true, tunType, firstEndPt.getIpAddress(), extIp, gwyIpAddress, firstEndPt.getVLANID(), false,false,null); + logger.debug(" Trunk Interface builder - {} ", iface); + InstanceIdentifier trunkIdentifier = ItmUtils.buildId(trunkInterfaceName); + logger.debug(" Trunk Interface Identifier - {} ", trunkIdentifier); + logger.trace(" Writing Trunk Interface to Config DS {}, {} ", trunkIdentifier, iface); + t.merge(LogicalDatastoreType.CONFIGURATION, trunkIdentifier, iface, true); + // update external_tunnel_list ds + InstanceIdentifier path = InstanceIdentifier.create( + ExternalTunnelList.class) + .child(ExternalTunnel.class, new ExternalTunnelKey(extIp.toString(), teps.getDPNID().toString())); + ExternalTunnel tnl = ItmUtils.buildExternalTunnel(teps.getDPNID().toString(), extIp.toString(), trunkInterfaceName); + t.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true); + } + futures.add(t.submit()); + } + return futures; } public static List> buildTunnelsFromDpnToExternalEndPoint(DataBroker dataBroker, IdManagerService idManagerService, List dpnId, IpAddress extIp, Class tunType) { List> futures = new ArrayList<>(); - List cfgDpnList =( dpnId == null ) ? ItmUtils.getTunnelMeshInfo(dataBroker) :ItmUtils.getDPNTEPListFromDPNId(dataBroker, dpnId) ; - futures = buildTunnelsToExternalEndPoint( dataBroker, idManagerService, cfgDpnList, extIp, tunType) ; - return futures ; + List cfgDpnList = (dpnId == null) ? ItmUtils.getTunnelMeshInfo(dataBroker) : ItmUtils.getDPNTEPListFromDPNId(dataBroker, dpnId); + futures = buildTunnelsToExternalEndPoint(dataBroker, idManagerService, cfgDpnList, extIp, tunType); + return futures; + } + + public static List> buildHwVtepsTunnels(DataBroker dataBroker, IdManagerService idManagerService, List cfgdDpnList, List cfgdHwVteps) { + List> futures = new ArrayList<>(); + WriteTransaction t = dataBroker.newWriteOnlyTransaction(); + if (null != cfgdDpnList && !cfgdDpnList.isEmpty()) { + logger.trace("calling tunnels from css {}",cfgdDpnList); + tunnelsFromCSS(cfgdDpnList, idManagerService , futures, t , dataBroker); + + } + if (null != cfgdHwVteps && !cfgdHwVteps.isEmpty() ) { + logger.trace("calling tunnels from hwTep {}",cfgdHwVteps); + tunnelsFromhWVtep(cfgdHwVteps, idManagerService, futures, t, dataBroker); + } + + if ((cfgdDpnList != null && !cfgdDpnList.isEmpty()) || (cfgdHwVteps != null && !cfgdHwVteps.isEmpty())) + futures.add(t.submit()); + return futures; + } + + private static void tunnelsFromCSS(List cfgdDpnList, IdManagerService idManagerService, List> futures, WriteTransaction t, DataBroker dataBroker) { + for (DPNTEPsInfo dpn : cfgdDpnList) { + logger.trace("processing dpn {}" , dpn); + if (dpn.getTunnelEndPoints() != null && !dpn.getTunnelEndPoints().isEmpty()) + for (TunnelEndPoints tep : dpn.getTunnelEndPoints()) { + InstanceIdentifier tzonePath = InstanceIdentifier.builder(TransportZones.class).child(TransportZone.class, new TransportZoneKey((tep.getTransportZone()))).build(); + Optional tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker); + if (tZoneOptional.isPresent()) { + TransportZone tZone = tZoneOptional.get(); + //do we need to check tunnel type? + if (tZone.getSubnets() != null && !tZone.getSubnets().isEmpty()) { + for (Subnets sub : tZone.getSubnets()) { + if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) { + for (DeviceVteps hwVtepDS : sub.getDeviceVteps()) { + String cssID = dpn.getDPNID().toString(); + String nodeId = hwVtepDS.getNodeId(); + //CSS-TOR + logger.trace("wire up {} and {}",tep, hwVtepDS); + if (!wireUp(dpn.getDPNID(), tep.getPortname(), sub.getVlanId(), tep.getIpAddress(), nodeId, hwVtepDS.getIpAddress(), tep.getSubnetMask(), + sub.getGatewayIp(), sub.getPrefix(), tZone.getTunnelType(), idManagerService, dataBroker, futures, t)) + logger.error("Unable to build tunnel {} -- {}", tep.getIpAddress(), hwVtepDS.getIpAddress()); + //TOR-CSS + logger.trace("wire up {} and {}", hwVtepDS,tep); + if (!wireUp(hwVtepDS.getTopologyId(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(), cssID, tep.getIpAddress(), sub.getPrefix(), + sub.getGatewayIp(), tep.getSubnetMask(), tZone.getTunnelType(), idManagerService, dataBroker, futures, t)) + logger.error("Unable to build tunnel {} -- {}", hwVtepDS.getIpAddress(), tep.getIpAddress()); + + } + } + } + } + } + } + } + } + + private static void tunnelsFromhWVtep(List cfgdHwVteps, IdManagerService idManagerService, List> futures, WriteTransaction t, DataBroker dataBroker) { + for (HwVtep hwTep : cfgdHwVteps) { + InstanceIdentifier tzonePath = InstanceIdentifier.builder(TransportZones.class).child(TransportZone.class, new TransportZoneKey((hwTep.getTransportZone()))).build(); + Optional tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker); + if (tZoneOptional.isPresent()) { + TransportZone tZone = tZoneOptional.get(); + //do we need to check tunnel type? + if (tZone.getSubnets() != null && !tZone.getSubnets().isEmpty()) { + for (Subnets sub : tZone.getSubnets()) { + if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) { + for (DeviceVteps hwVtepDS : sub.getDeviceVteps()) { + if (hwVtepDS.getIpAddress().equals(hwTep.getHwIp())) + continue;//dont mesh with self + //TOR1-TOR2 + logger.trace("wire up {} and {}",hwTep, hwVtepDS); + if (!wireUp(hwTep.getTopo_id(), hwTep.getNode_id(), hwTep.getHwIp(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(), + hwTep.getIpPrefix(), hwTep.getGatewayIP(), sub.getPrefix(), tZone.getTunnelType(), idManagerService, dataBroker, futures, t)) + logger.error("Unable to build tunnel {} -- {}", hwTep.getHwIp(), hwVtepDS.getIpAddress()); + //TOR2-TOR1 + logger.trace("wire up {} and {}", hwVtepDS,hwTep); + if (!wireUp(hwTep.getTopo_id(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(), hwTep.getNode_id(), hwTep.getHwIp(), + sub.getPrefix(), sub.getGatewayIp(), hwTep.getIpPrefix(), tZone.getTunnelType(), idManagerService, dataBroker, futures, t)) + logger.error("Unable to build tunnel {} -- {}", hwVtepDS.getIpAddress(), hwTep.getHwIp()); + } + } + if (sub.getVteps() != null && !sub.getVteps().isEmpty()) { + for (Vteps vtep : sub.getVteps()) { + //TOR-CSS + String cssID = vtep.getDpnId().toString(); + logger.trace("wire up {} and {}",hwTep, vtep); + if(!wireUp(hwTep.getTopo_id(), hwTep.getNode_id(), hwTep.getHwIp(), cssID, vtep.getIpAddress(), hwTep.getIpPrefix(), + hwTep.getGatewayIP(), sub.getPrefix(), tZone.getTunnelType(),idManagerService, dataBroker, futures, t )) + logger.error("Unable to build tunnel {} -- {}", hwTep.getHwIp(), vtep.getIpAddress()); + //CSS-TOR + logger.trace("wire up {} and {}", vtep,hwTep); + if(!wireUp(vtep.getDpnId(), vtep.getPortname(), sub.getVlanId(), vtep.getIpAddress(), + hwTep.getNode_id(),hwTep.getHwIp(),sub.getPrefix(), sub.getGatewayIp(),hwTep.getIpPrefix(),tZone.getTunnelType(),idManagerService, dataBroker, futures, t )); + + } + + } + } + } + } + } + } + + //for tunnels from TOR device + private static boolean wireUp(String topo_id, String srcNodeid, IpAddress srcIp, String dstNodeId, IpAddress dstIp, IpPrefix srcSubnet, + IpAddress gWIp, IpPrefix dstSubnet, Class tunType, IdManagerService idManagerService, DataBroker dataBroker, List> futures, WriteTransaction t) { + IpAddress gwyIpAddress = (srcSubnet.equals(dstSubnet)) ? null : gWIp; + String parentIf = ItmUtils.getHwParentIf(topo_id, srcNodeid); + String tunnelIfName = ItmUtils.getTrunkInterfaceName(idManagerService, parentIf, srcIp.getIpv4Address().getValue(), dstIp.getIpv4Address().getValue()); + logger.debug(" Creating ExternalTrunk Interface with parameters Name - {}, parent I/f name - {}, source IP - {}, destination IP - {} gateway IP - {}", tunnelIfName, parentIf, srcIp, dstIp, gwyIpAddress); + Interface hwTunnelIf = ItmUtils.buildHwTunnelInterface(tunnelIfName, String.format("%s %s", tunType.getName(), "Trunk Interface"), + true, topo_id, srcNodeid, tunType, srcIp, dstIp, gwyIpAddress, true); + InstanceIdentifier ifIID = InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(tunnelIfName)).build(); + logger.trace(" Writing Trunk Interface to Config DS {}, {} ", ifIID, hwTunnelIf); + t.merge(LogicalDatastoreType.CONFIGURATION, ifIID, hwTunnelIf, true); + // also update itm-state ds? + InstanceIdentifier path = InstanceIdentifier.create( + ExternalTunnelList.class) + .child(ExternalTunnel.class, new ExternalTunnelKey(getExternalTunnelKey(dstNodeId), getExternalTunnelKey(srcNodeid))); + ExternalTunnel tnl = ItmUtils.buildExternalTunnel(getExternalTunnelKey(srcNodeid), getExternalTunnelKey(dstNodeId), tunnelIfName); + t.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true); + return true; + } + + //for tunnels from CSS + private static boolean wireUp(BigInteger dpnId,String portname, Integer vlanId, IpAddress srcIp, String dstNodeId, IpAddress dstIp, IpPrefix srcSubnet, + IpAddress gWIp, IpPrefix dstSubnet, Class tunType, IdManagerService idManagerService, DataBroker dataBroker, List> futures, WriteTransaction t) { + IpAddress gwyIpAddress = (srcSubnet.equals(dstSubnet)) ? null : gWIp; + String parentIf = ItmUtils.getInterfaceName(dpnId, portname, vlanId); + String tunnelIfName = ItmUtils.getTrunkInterfaceName(idManagerService, parentIf, srcIp.getIpv4Address().getValue(), dstIp.getIpv4Address().getValue()); + logger.debug(" Creating ExternalTrunk Interface with parameters Name - {}, parent I/f name - {}, source IP - {}, destination IP - {} gateway IP - {}", tunnelIfName, parentIf, srcIp, dstIp, gwyIpAddress); + Interface extTunnelIf = ItmUtils.buildTunnelInterface(dpnId, tunnelIfName, String.format("%s %s", tunType.getName(), "Trunk Interface"), true, tunType, srcIp, dstIp, gwyIpAddress, vlanId, false, true, 5L); + InstanceIdentifier ifIID = InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(tunnelIfName)).build(); + logger.trace(" Writing Trunk Interface to Config DS {}, {} ", ifIID, extTunnelIf); + t.merge(LogicalDatastoreType.CONFIGURATION, ifIID, extTunnelIf, true); + InstanceIdentifier path = InstanceIdentifier.create( + ExternalTunnelList.class) + .child(ExternalTunnel.class, new ExternalTunnelKey(getExternalTunnelKey(dstNodeId), dpnId.toString())); + ExternalTunnel tnl = ItmUtils.buildExternalTunnel(dpnId.toString(), getExternalTunnelKey(dstNodeId), tunnelIfName); + t.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true); + return true; + } + + static String getExternalTunnelKey(String nodeid) { + if (nodeid.indexOf("physicalswitch") > 0) { + nodeid = nodeid.substring(0, nodeid.indexOf("physicalswitch") - 1); + } + return nodeid; } } + diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmExternalTunnelDeleteWorker.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmExternalTunnelDeleteWorker.java index 5cef68f2..c1d8f863 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmExternalTunnelDeleteWorker.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmExternalTunnelDeleteWorker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015, 2016 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, @@ -7,9 +7,12 @@ */ package org.opendaylight.vpnservice.itm.confighelpers; +import java.math.BigInteger; import java.util.ArrayList; import java.util.List; +import com.google.common.base.Optional; + 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; @@ -23,6 +26,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZoneKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.Subnets; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVteps; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.Vteps; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,7 +60,7 @@ public class ItmExternalTunnelDeleteWorker { InstanceIdentifier path = InstanceIdentifier.create( ExternalTunnelList.class) - .child(ExternalTunnel.class, new ExternalTunnelKey(extIp, teps.getDPNID())); + .child(ExternalTunnel.class, getExternalTunnelKey(extIp.toString(), teps.getDPNID().toString())); t.delete(LogicalDatastoreType.CONFIGURATION, path); // Release the Ids for the trunk interface Name ItmUtils.releaseIdForTrunkInterfaceName(idManagerService,interfaceName,firstEndPt.getIpAddress().getIpv4Address().getValue(), extIp.getIpv4Address().getValue() ); @@ -61,4 +70,198 @@ public class ItmExternalTunnelDeleteWorker { return futures ; } + public static List> deleteHwVtepsTunnels(DataBroker dataBroker, IdManagerService idManagerService, List delDpnList ,List cfgdHwVteps) { + List> futures = new ArrayList<>(); + WriteTransaction t = dataBroker.newWriteOnlyTransaction(); + if (null != delDpnList) { + tunnelsFromCSS(delDpnList, idManagerService , futures, t , dataBroker); + } + if (null != cfgdHwVteps) { + tunnelsFromhWVtep(cfgdHwVteps, idManagerService, futures, t, dataBroker); + } + + if (delDpnList != null || cfgdHwVteps != null) + futures.add(t.submit()); + return futures; + } + + private static void tunnelsFromCSS(List cfgdDpnList, IdManagerService idManagerService, List> futures, WriteTransaction t, DataBroker dataBroker) { + for (DPNTEPsInfo dpn : cfgdDpnList) { + if (dpn.getTunnelEndPoints() != null && !dpn.getTunnelEndPoints().isEmpty()) + for (TunnelEndPoints srcTep : dpn.getTunnelEndPoints()) { + InstanceIdentifier tzonePath = InstanceIdentifier.builder(TransportZones.class).child(TransportZone.class, new TransportZoneKey((srcTep.getTransportZone()))).build(); + Optional tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker); + if (tZoneOptional.isPresent()) { + TransportZone tZone = tZoneOptional.get(); + //do we need to check tunnel type? + if (tZone.getSubnets() != null && !tZone.getSubnets().isEmpty()) { + for (Subnets sub : tZone.getSubnets()) { + if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) { + for (DeviceVteps hwVtepDS : sub.getDeviceVteps()) { + String cssID = dpn.getDPNID().toString(); + //CSS-TOR-CSS + deleteTrunksCSSTOR(dataBroker, idManagerService, dpn.getDPNID(), + srcTep.getInterfaceName(), srcTep.getIpAddress(), + hwVtepDS.getTopologyId(), hwVtepDS.getNodeId(), + hwVtepDS.getIpAddress(), t, futures); + + } + } + } + } + } + } + } + } + + + + + + private static void tunnelsFromhWVtep(List cfgdHwVteps, IdManagerService idManagerService, List> futures, WriteTransaction t, DataBroker dataBroker) { + for (HwVtep hwTep : cfgdHwVteps) { + logger.trace("processing hwTep from list {}",hwTep); + InstanceIdentifier tzonePath = InstanceIdentifier.builder(TransportZones.class).child(TransportZone.class, new TransportZoneKey((hwTep.getTransportZone()))).build(); + Optional tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker); + if (tZoneOptional.isPresent()) { + TransportZone tZone = tZoneOptional.get(); + //do we need to check tunnel type? + logger.trace("subnets under tz {} are {}",tZone.getZoneName(),tZone.getSubnets()); + if (tZone.getSubnets() != null && !tZone.getSubnets().isEmpty()) { + + for (Subnets sub : tZone.getSubnets()) { + if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) { + for (DeviceVteps hwVtepDS : sub.getDeviceVteps()) { + logger.trace("hwtepDS exists {}",hwVtepDS); + //do i need to check node-id? + //for mlag case and non-m-lag case, isnt it enough to just check ipaddress? + if (hwVtepDS.getIpAddress().equals(hwTep.getHwIp())) + continue;//dont delete tunnels with self + //TOR-TOR + logger.trace("deleting tor-tor {} and {}",hwTep,hwVtepDS); + deleteTrunksTORTOR(dataBroker, idManagerService, hwTep.getTopo_id(), hwTep.getNode_id(), + hwTep.getHwIp(), hwVtepDS.getTopologyId(), hwVtepDS.getNodeId(), + hwVtepDS.getIpAddress(), t, futures); + + } + } + if (sub.getVteps() != null && !sub.getVteps().isEmpty()) { + for (Vteps vtep : sub.getVteps()) { + //TOR-CSS + logger.trace("deleting tor-css-tor {} and {}",hwTep,vtep); + String parentIf = ItmUtils.getInterfaceName(vtep.getDpnId(),vtep.getPortname(),sub.getVlanId()); + deleteTrunksCSSTOR(dataBroker,idManagerService,vtep.getDpnId(),parentIf,vtep.getIpAddress(), + hwTep.getTopo_id(),hwTep.getNode_id(),hwTep.getHwIp(),t,futures ); + } + + } + } + } + } + } + } + + + private static void deleteTrunksCSSTOR(DataBroker dataBroker, IdManagerService idManagerService, BigInteger dpnid, + String interfaceName, IpAddress cssIpAddress, String topologyId, String nodeId, IpAddress hWIpAddress, + WriteTransaction t, List> futures) { + //CSS-TOR + if (trunkExists(dpnid.toString(), nodeId,dataBroker)) { + logger.trace("deleting tunnel from {} to {} ", dpnid.toString(), nodeId); + String parentIf = interfaceName; + String fwdTrunkIf = ItmUtils.getTrunkInterfaceName(idManagerService,parentIf,cssIpAddress.getIpv4Address().getValue(), + hWIpAddress.getIpv4Address().getValue()); + InstanceIdentifier trunkIdentifier = ItmUtils.buildId(fwdTrunkIf); + t.delete(LogicalDatastoreType.CONFIGURATION, trunkIdentifier); + + InstanceIdentifier path = InstanceIdentifier.create( + ExternalTunnelList.class) + .child(ExternalTunnel.class, getExternalTunnelKey(nodeId, dpnid.toString())); + t.delete(LogicalDatastoreType.CONFIGURATION, path); + } + else { + logger.trace(" trunk from {} to {} already deleted",dpnid.toString(), nodeId); + } + //TOR-CSS + if (trunkExists( nodeId, dpnid.toString(),dataBroker)) { + logger.trace("deleting tunnel from {} to {} ",nodeId, dpnid.toString()); + + String parentIf = ItmUtils.getHwParentIf(topologyId,nodeId); + String revTrunkIf = ItmUtils.getTrunkInterfaceName(idManagerService,parentIf, hWIpAddress.getIpv4Address().getValue(), + cssIpAddress.getIpv4Address().getValue()); + InstanceIdentifier trunkIdentifier = ItmUtils.buildId(revTrunkIf); + t.delete(LogicalDatastoreType.CONFIGURATION, trunkIdentifier); + + InstanceIdentifier path = InstanceIdentifier.create( + ExternalTunnelList.class) + .child(ExternalTunnel.class, getExternalTunnelKey( dpnid.toString(),nodeId)); + t.delete(LogicalDatastoreType.CONFIGURATION, path); + } + else { + logger.trace(" trunk from {} to {} already deleted", nodeId, dpnid.toString()); + } + } + + private static void deleteTrunksTORTOR(DataBroker dataBroker, IdManagerService idManagerService, + String topologyId1, String nodeId1, IpAddress hWIpAddress1, String topologyId2, String nodeId2, IpAddress hWIpAddress2, + WriteTransaction t, List> futures) { + //TOR1-TOR2 + if (trunkExists(nodeId1, nodeId2,dataBroker)) { + logger.trace("deleting tunnel from {} to {} ", nodeId1, nodeId2); + String parentIf = ItmUtils.getHwParentIf(topologyId1,nodeId1); + String fwdTrunkIf = ItmUtils.getTrunkInterfaceName(idManagerService, parentIf, + hWIpAddress1.getIpv4Address().getValue(), hWIpAddress2.getIpv4Address().getValue()); + InstanceIdentifier trunkIdentifier = ItmUtils.buildId(fwdTrunkIf); + t.delete(LogicalDatastoreType.CONFIGURATION, trunkIdentifier); + + InstanceIdentifier path = InstanceIdentifier.create( + ExternalTunnelList.class) + .child(ExternalTunnel.class, getExternalTunnelKey(nodeId2, nodeId1)); + t.delete(LogicalDatastoreType.CONFIGURATION, path); + } + else { + logger.trace(" trunk from {} to {} already deleted",nodeId1, nodeId2); + } + //TOR2-TOR1 + if (trunkExists( nodeId2, nodeId1,dataBroker)) { + logger.trace("deleting tunnel from {} to {} ",nodeId2, nodeId1); + + String parentIf = ItmUtils.getHwParentIf(topologyId2,nodeId2); + String revTrunkIf = ItmUtils.getTrunkInterfaceName(idManagerService,parentIf, hWIpAddress2.getIpv4Address().getValue(), + hWIpAddress1.getIpv4Address().getValue()); + InstanceIdentifier trunkIdentifier = ItmUtils.buildId(revTrunkIf); + t.delete(LogicalDatastoreType.CONFIGURATION, trunkIdentifier); + + InstanceIdentifier path = InstanceIdentifier.create( + ExternalTunnelList.class) + .child(ExternalTunnel.class, getExternalTunnelKey( nodeId1,nodeId2)); + t.delete(LogicalDatastoreType.CONFIGURATION, path); + } + else { + logger.trace(" trunk from {} to {} already deleted",nodeId2, nodeId1); + } + } + + private static boolean trunkExists( String srcDpnOrNode, String dstDpnOrNode, DataBroker dataBroker) { + boolean existsFlag = false ; + InstanceIdentifier path = InstanceIdentifier.create( + ExternalTunnelList.class) + .child(ExternalTunnel.class, getExternalTunnelKey(dstDpnOrNode, srcDpnOrNode)); + Optional exTunnels = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,path, dataBroker) ; + if( exTunnels.isPresent()) + existsFlag = true ; + return existsFlag ; + } + + static ExternalTunnelKey getExternalTunnelKey(String dst , String src) { + if (src.indexOf("physicalswitch") > 0) { + src = src.substring(0, src.indexOf("physicalswitch") - 1); + } + if (dst.indexOf("physicalswitch") > 0) { + dst = dst.substring(0, dst.indexOf("physicalswitch") - 1); + } + return new ExternalTunnelKey(dst, src); + } + + } diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmInternalTunnelAddWorker.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmInternalTunnelAddWorker.java index c7c5ae72..c1850200 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmInternalTunnelAddWorker.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmInternalTunnelAddWorker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015, 2016 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, @@ -64,7 +64,7 @@ public class ItmInternalTunnelAddWorker { WriteTransaction t = dataBroker.newWriteOnlyTransaction(); if( null == cfgdDpnList || cfgdDpnList.isEmpty()) { logger.error(" Build Tunnels was invoked with empty list"); - return null; + return futures; } for( DPNTEPsInfo dpn : cfgdDpnList) { @@ -152,7 +152,9 @@ public class ItmInternalTunnelAddWorker { String trunkInterfaceName = ItmUtils.getTrunkInterfaceName(idManagerService, interfaceName,srcte.getIpAddress().getIpv4Address().getValue(), dstte.getIpAddress().getIpv4Address().getValue()) ; IpAddress gwyIpAddress = ( srcte.getSubnetMask().equals(dstte.getSubnetMask()) ) ? null : srcte.getGwIpAddress() ; logger.debug( " Creating Trunk Interface with parameters trunk I/f Name - {}, parent I/f name - {}, source IP - {}, destination IP - {} gateway IP - {}",trunkInterfaceName, interfaceName, srcte.getIpAddress(), dstte.getIpAddress(), gwyIpAddress ) ; - Interface iface = ItmUtils.buildTunnelInterface(srcDpnId, trunkInterfaceName, String.format( "%s %s",ifDescription, "Trunk Interface"), true, tunType, srcte.getIpAddress(), dstte.getIpAddress(), gwyIpAddress, true) ; + Interface iface = ItmUtils.buildTunnelInterface(srcDpnId, trunkInterfaceName, + String.format("%s %s", ifDescription, "Trunk Interface"), true, tunType, srcte.getIpAddress(), + dstte.getIpAddress(), gwyIpAddress, srcte.getVLANID(), true, false, null); logger.debug( " Trunk Interface builder - {} ", iface ) ; InstanceIdentifier trunkIdentifier = ItmUtils.buildId(trunkInterfaceName); logger.debug( " Trunk Interface Identifier - {} ", trunkIdentifier ) ; @@ -161,7 +163,7 @@ public class ItmInternalTunnelAddWorker { // also update itm-state ds? InstanceIdentifier path = InstanceIdentifier.create( TunnelList.class) - .child(InternalTunnel.class, new InternalTunnelKey( srcDpnId, dstDpnId)); + .child(InternalTunnel.class, new InternalTunnelKey( dstDpnId,srcDpnId )); InternalTunnel tnl = ItmUtils.buildInternalTunnel(srcDpnId, dstDpnId, trunkInterfaceName); //ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, path, tnl, dataBroker, DEFAULT_CALLBACK); t.merge(LogicalDatastoreType.CONFIGURATION,path, tnl, true) ; diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmInternalTunnelDeleteWorker.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmInternalTunnelDeleteWorker.java index 9e113f25..ed065b6e 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmInternalTunnelDeleteWorker.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmInternalTunnelDeleteWorker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015, 2016 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, @@ -38,20 +38,22 @@ public class ItmInternalTunnelDeleteWorker { public static List> deleteTunnels(DataBroker dataBroker, IdManagerService idManagerService,IMdsalApiManager mdsalManager, List dpnTepsList, List meshedDpnList) { + logger.trace( "TEPs to be deleted {} " , dpnTepsList ); List> futures = new ArrayList<>(); WriteTransaction t = dataBroker.newWriteOnlyTransaction(); try { if (dpnTepsList == null || dpnTepsList.size() == 0) { logger.debug("no vtep to delete"); - return null ; + return futures ; } if (meshedDpnList == null || meshedDpnList.size() == 0) { logger.debug("No Meshed Vteps"); - return null ; + return futures ; } for (DPNTEPsInfo srcDpn : dpnTepsList) { logger.trace("Processing srcDpn " + srcDpn); + List meshedEndPtCache = new ArrayList(srcDpn.getTunnelEndPoints()) ; for (TunnelEndPoints srcTep : srcDpn.getTunnelEndPoints()) { logger.trace("Processing srcTep " + srcTep); String srcTZone = srcTep.getTransportZone(); @@ -79,18 +81,24 @@ public class ItmInternalTunnelDeleteWorker { logger.trace("Tep Removal from DPNTEPSINFO CONFIG DS " + srcTep); t.delete(LogicalDatastoreType.CONFIGURATION, tepPath); + // remove the tep from the cache + meshedEndPtCache.remove(srcTep) ; + InstanceIdentifier dpnPath = InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, srcDpn.getKey()) .build(); + /* Optional dpnOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, dpnPath, dataBroker); if (dpnOptional.isPresent()) { - DPNTEPsInfo dpnRead = dpnOptional.get(); + */ + if( meshedEndPtCache.isEmpty()) { + //DPNTEPsInfo dpnRead = dpnOptional.get(); // remove dpn if no vteps exist on dpn - if (dpnRead.getTunnelEndPoints() == null || dpnRead.getTunnelEndPoints().size() == 0) { + // if (dpnRead.getTunnelEndPoints() == null || dpnRead.getTunnelEndPoints().size() == 0) { logger.debug( "Removing Terminating Service Table Flow ") ; - ItmUtils.setUpOrRemoveTerminatingServiceTable(dpnRead.getDPNID(), mdsalManager,false); - logger.trace("DPN Removal from DPNTEPSINFO CONFIG DS " + dpnRead); + ItmUtils.setUpOrRemoveTerminatingServiceTable(srcDpn.getDPNID(), mdsalManager,false); + logger.trace("DPN Removal from DPNTEPSINFO CONFIG DS " + srcDpn.getDPNID()); t.delete(LogicalDatastoreType.CONFIGURATION, dpnPath); InstanceIdentifier tnlContainerPath = InstanceIdentifier.builder(DpnEndpoints.class).build(); @@ -105,7 +113,7 @@ public class ItmInternalTunnelDeleteWorker { t.delete(LogicalDatastoreType.CONFIGURATION, tnlContainerPath); } } - } + //} } } } diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmTepAddWorker.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmTepAddWorker.java index 40a5314e..ed6282d3 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmTepAddWorker.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmTepAddWorker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015, 2016 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, @@ -28,13 +28,16 @@ public class ItmTepAddWorker implements Callable>> { private List meshedDpnList; private List cfgdDpnList ; private IMdsalApiManager mdsalManager; + private List cfgdHwVteps; - public ItmTepAddWorker( List cfgdDpnList, DataBroker broker, IdManagerService idManagerService, IMdsalApiManager mdsalManager) { + public ItmTepAddWorker( List cfgdDpnList, List hwVtepList, DataBroker broker, IdManagerService idManagerService, IMdsalApiManager mdsalManager) { this.cfgdDpnList = cfgdDpnList ; this.dataBroker = broker ; this.idManagerService = idManagerService; this.mdsalManager = mdsalManager; + this.cfgdHwVteps = hwVtepList; logger.trace("ItmTepAddWorker initialized with DpnList {}",cfgdDpnList ); + logger.trace("ItmTepAddWorker initialized with hwvteplist {}",hwVtepList); } @Override @@ -45,6 +48,8 @@ public class ItmTepAddWorker implements Callable>> { futures.addAll( ItmInternalTunnelAddWorker.build_all_tunnels(dataBroker, idManagerService,mdsalManager, cfgdDpnList, meshedDpnList) ) ; // IF EXTERNAL TUNNELS NEEDS TO BE BUILT, DO IT HERE. IT COULD BE TO DC GATEWAY OR TOR SWITCH //futures.addAll(ItmExternalTunnelAddWorker.buildTunnelsToExternalEndPoint(dataBroker,meshedDpnList, extIp) ; + logger.debug("invoking build hwVtepTunnels with hwVteplist {}", cfgdHwVteps ); + futures.addAll(ItmExternalTunnelAddWorker.buildHwVtepsTunnels(dataBroker, idManagerService,cfgdDpnList,cfgdHwVteps)); return futures ; } diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmTepRemoveWorker.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmTepRemoveWorker.java index dfc6afdf..f320a11d 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmTepRemoveWorker.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmTepRemoveWorker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015, 2016 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, @@ -28,13 +28,16 @@ public class ItmTepRemoveWorker implements Callable> private List meshedDpnList ; private IdManagerService idManagerService; private IMdsalApiManager mdsalManager; + private List cfgdHwVteps; - public ItmTepRemoveWorker( List delDpnList, DataBroker broker, IdManagerService idManagerService, IMdsalApiManager mdsalManager) { + public ItmTepRemoveWorker( List delDpnList, List delHwList, DataBroker broker, IdManagerService idManagerService, IMdsalApiManager mdsalManager) { this.delDpnList = delDpnList ; this.dataBroker = broker ; this.idManagerService = idManagerService; this.mdsalManager = mdsalManager; + this.cfgdHwVteps = delHwList; logger.trace("ItmTepRemoveWorker initialized with DpnList {}",delDpnList ); + logger.trace("ItmTepRemoveWorker initialized with cfgdHwTeps {}",delHwList ); } @Override @@ -44,6 +47,7 @@ public class ItmTepRemoveWorker implements Callable> futures.addAll( ItmInternalTunnelDeleteWorker.deleteTunnels(dataBroker, idManagerService, mdsalManager, delDpnList, meshedDpnList)); logger.debug("Invoking Internal Tunnel delete method with DpnList to be deleted {} ; Meshed DpnList {} ",delDpnList, meshedDpnList ); // IF EXTERNAL TUNNELS NEEDS TO BE DELETED, DO IT HERE, IT COULD BE TO DC GATEWAY OR TOR SWITCH + futures.addAll(ItmExternalTunnelDeleteWorker.deleteHwVtepsTunnels(dataBroker, idManagerService,delDpnList,cfgdHwVteps)); return futures ; } diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ITMManager.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ITMManager.java index 87f8a8b1..0c784b08 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ITMManager.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ITMManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015, 2016 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, @@ -37,7 +37,10 @@ import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo; import com.google.common.base.Optional; - +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorEnabled; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorInterval; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorEnabledBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorIntervalBuilder; public class ITMManager implements AutoCloseable { private static final Logger LOG = LoggerFactory.getLogger(ITMManager.class); @@ -64,5 +67,56 @@ public class ITMManager implements AutoCloseable { public void setNotificationPublishService(NotificationPublishService notificationPublishService) { this.notificationPublishService = notificationPublishService; } + protected void initTunnelMonitorDataInConfigDS() { + new Thread() { + public void run() { + boolean readSucceeded = false; + InstanceIdentifier monitorPath = InstanceIdentifier.builder(TunnelMonitorEnabled.class).build(); + while (!readSucceeded) { + try { + Optional storedTunnelMonitor = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, monitorPath, broker); + // Store default values only when tunnel monitor data is not initialized + if (!storedTunnelMonitor.isPresent()) { + TunnelMonitorEnabled monitorEnabled = + new TunnelMonitorEnabledBuilder().setEnabled(ITMConstants.DEFAULT_MONITOR_ENABLED).build(); + ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, monitorPath, monitorEnabled, broker, ItmUtils.DEFAULT_CALLBACK); + + InstanceIdentifier intervalPath = InstanceIdentifier.builder(TunnelMonitorInterval.class).build(); + TunnelMonitorInterval monitorInteval = + new TunnelMonitorIntervalBuilder().setInterval(ITMConstants.DEFAULT_MONITOR_INTERVAL).build(); + ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, intervalPath, monitorInteval, broker, ItmUtils.DEFAULT_CALLBACK); + } + readSucceeded = true; + } catch (Exception e) { + LOG.warn("Unable to read monitor enabled info; retrying after some delay"); + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { + return; + } + } + } + } + }.start(); + } + protected boolean getTunnelMonitorEnabledFromConfigDS() { + boolean tunnelMonitorEnabled = true; + InstanceIdentifier path = InstanceIdentifier.builder(TunnelMonitorEnabled.class).build(); + Optional storedTunnelMonitor = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, broker); + if (storedTunnelMonitor.isPresent()) { + tunnelMonitorEnabled = storedTunnelMonitor.get().isEnabled(); + } + return tunnelMonitorEnabled; + } + + protected int getTunnelMonitorIntervalFromConfigDS() { + int tunnelMonitorInterval = ITMConstants.DEFAULT_MONITOR_INTERVAL; + InstanceIdentifier path = InstanceIdentifier.builder(TunnelMonitorInterval.class).build(); + Optional storedTunnelMonitor = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, broker); + if (storedTunnelMonitor.isPresent()) { + tunnelMonitorInterval = storedTunnelMonitor.get().getInterval(); + } + return tunnelMonitorInterval; + } } diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ItmProvider.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ItmProvider.java index 2c2126e9..57ed05ae 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ItmProvider.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ItmProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015, 2016 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, @@ -22,20 +22,33 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareProvider; import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager; import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.opendaylight.vpnservice.itm.cli.TepCommandHelper; import org.opendaylight.vpnservice.itm.globals.ITMConstants; +import org.opendaylight.vpnservice.itm.impl.ItmUtils; import org.opendaylight.vpnservice.itm.listeners.TransportZoneListener; +import org.opendaylight.vpnservice.itm.listeners.VtepConfigSchemaListener; import org.opendaylight.vpnservice.itm.rpc.ItmManagerRpcService; +import org.opendaylight.vpnservice.itm.snd.ITMStatusMonitor; +import org.opendaylight.vpnservice.mdsalutil.MDSALUtil; import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.VtepConfigSchemas; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchemaBuilder; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.VtepConfigSchemas; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.vtep.config.schemas.VtepConfigSchemaBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService; - import org.opendaylight.yangtools.yang.common.RpcResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; + public class ItmProvider implements BindingAwareProvider, AutoCloseable, IITMProvider /*,ItmStateService */{ private static final Logger LOG = LoggerFactory.getLogger(ItmProvider.class); @@ -47,8 +60,17 @@ public class ItmProvider implements BindingAwareProvider, AutoCloseable, IITMPro private ItmManagerRpcService itmRpcService ; private IdManagerService idManager; private NotificationService notificationService; + private TepCommandHelper tepCommandHelper; private TransportZoneListener tzChangeListener; + private VtepConfigSchemaListener vtepConfigSchemaListener; private RpcProviderRegistry rpcProviderRegistry; + private static final ITMStatusMonitor itmStatusMonitor = ITMStatusMonitor.getInstance(); + static short flag = 0; + + public ItmProvider() { + LOG.info("ItmProvider Before register MBean"); + itmStatusMonitor.registerMbean(); + } public void setRpcProviderRegistry(RpcProviderRegistry rpcProviderRegistry) { this.rpcProviderRegistry = rpcProviderRegistry; @@ -61,6 +83,7 @@ public class ItmProvider implements BindingAwareProvider, AutoCloseable, IITMPro @Override public void onSessionInitiated(ProviderContext session) { LOG.info("ItmProvider Session Initiated"); + itmStatusMonitor.reportStatus("STARTING"); try { dataBroker = session.getSALService(DataBroker.class); idManager = getRpcProviderRegistry().getRpcService(IdManagerService.class); @@ -68,6 +91,8 @@ public class ItmProvider implements BindingAwareProvider, AutoCloseable, IITMPro itmManager = new ITMManager(dataBroker); tzChangeListener = new TransportZoneListener(dataBroker, idManager) ; itmRpcService = new ItmManagerRpcService(dataBroker, idManager); + vtepConfigSchemaListener = new VtepConfigSchemaListener(dataBroker); + tepCommandHelper = new TepCommandHelper(dataBroker); final BindingAwareBroker.RpcRegistration rpcRegistration = getRpcProviderRegistry().addRpcImplementation(ItmRpcService.class, itmRpcService); itmRpcService.setMdsalManager(mdsalManager); itmManager.setMdsalManager(mdsalManager); @@ -76,9 +101,13 @@ public class ItmProvider implements BindingAwareProvider, AutoCloseable, IITMPro tzChangeListener.setMdsalManager(mdsalManager); tzChangeListener.setItmManager(itmManager); tzChangeListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker); + tepCommandHelper = new TepCommandHelper(dataBroker); + tepCommandHelper.setInterfaceManager(interfaceManager); createIdPool(); + itmStatusMonitor.reportStatus("OPERATIONAL"); } catch (Exception e) { LOG.error("Error initializing services", e); + itmStatusMonitor.reportStatus("ERROR"); } } @@ -124,4 +153,163 @@ public class ItmProvider implements BindingAwareProvider, AutoCloseable, IITMPro LOG.error("Failed to create idPool for ITM Service",e); } } + + @Override + public DataBroker getDataBroker() { + return dataBroker; + } + @Override + public void createLocalCache(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask, + String gatewayIp, String transportZone) { + if (tepCommandHelper != null) { + tepCommandHelper.createLocalCache(dpnId, portName, vlanId, ipAddress, subnetMask, gatewayIp, transportZone); + } else { + LOG.trace("tepCommandHelper doesnt exist"); + } + } + + @Override + public void commitTeps() { + try { + tepCommandHelper.deleteOnCommit(); + tepCommandHelper.buildTeps(); + } catch (Exception e) { + LOG.debug("unable to configure teps" + e.toString()); + } + } + + @Override + public void showTeps() { + tepCommandHelper.showTeps(itmManager.getTunnelMonitorEnabledFromConfigDS(), + itmManager.getTunnelMonitorIntervalFromConfigDS()); + } + + public void deleteVtep(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask, + String gatewayIp, String transportZone) { + try { + tepCommandHelper.deleteVtep(dpnId, portName, vlanId, ipAddress, subnetMask, gatewayIp, transportZone); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void configureTunnelType(String transportZone, String tunnelType) { + LOG .debug("ItmProvider: configureTunnelType {} for transportZone {}", tunnelType, transportZone); + tepCommandHelper.configureTunnelType(transportZone,tunnelType); + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.vpnservice.itm.api.IITMProvider#addVtepConfigSchema(org. + * opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config. + * rev151102.vtep.config.schemas.VtepConfigSchema) + */ + @Override + public void addVtepConfigSchema(VtepConfigSchema vtepConfigSchema) { + VtepConfigSchema validatedSchema = ItmUtils.validateForAddVtepConfigSchema(vtepConfigSchema, + getAllVtepConfigSchemas()); + + String schemaName = validatedSchema.getSchemaName(); + VtepConfigSchema existingSchema = getVtepConfigSchema(schemaName); + if (existingSchema != null) { + Preconditions.checkArgument(false, String.format("VtepConfigSchema [%s] already exists!", schemaName)); + } + MDSALUtil.syncWrite(this.dataBroker, LogicalDatastoreType.CONFIGURATION, + ItmUtils.getVtepConfigSchemaIdentifier(schemaName), validatedSchema); + LOG.debug("Vtep config schema {} added to config DS", schemaName); + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.vpnservice.itm.api.IITMProvider#getVtepConfigSchema(java + * .lang.String) + */ + @Override + public VtepConfigSchema getVtepConfigSchema(String schemaName) { + Optional schema = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, + ItmUtils.getVtepConfigSchemaIdentifier(schemaName), this.dataBroker); + if (schema.isPresent()) { + return schema.get(); + } + return null; + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.vpnservice.itm.api.IITMProvider#getAllVtepConfigSchemas( + * ) + */ + @Override + public List getAllVtepConfigSchemas() { + Optional schemas = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, + ItmUtils.getVtepConfigSchemasIdentifier(), this.dataBroker); + if (schemas.isPresent()) { + return schemas.get().getVtepConfigSchema(); + } + return null; + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.vpnservice.itm.api.IITMProvider#updateVtepSchema(java. + * lang.String, java.util.List, java.util.List) + */ + @Override + public void updateVtepSchema(String schemaName, List lstDpnsForAdd, List lstDpnsForDelete) { + LOG.trace("Updating VTEP schema {} by adding DPN's {} and deleting DPN's {}.", schemaName, lstDpnsForAdd, + lstDpnsForDelete); + + VtepConfigSchema schema = ItmUtils.validateForUpdateVtepSchema(schemaName, lstDpnsForAdd, lstDpnsForDelete, + this); + if (ItmUtils.getDpnIdList(schema.getDpnIds()) == null) { + VtepConfigSchemaBuilder builder = new VtepConfigSchemaBuilder(schema); + builder.setDpnIds(schema.getDpnIds()); + schema = builder.build(); + } else { + if (lstDpnsForAdd != null && !lstDpnsForAdd.isEmpty()) { + ItmUtils.getDpnIdList(schema.getDpnIds()).addAll(lstDpnsForAdd); + } + if (lstDpnsForDelete != null && !lstDpnsForDelete.isEmpty()) { + ItmUtils.getDpnIdList(schema.getDpnIds()).removeAll(lstDpnsForDelete); + } + } + MDSALUtil.syncWrite(this.dataBroker, LogicalDatastoreType.CONFIGURATION, + ItmUtils.getVtepConfigSchemaIdentifier(schemaName), schema); + LOG.debug("Vtep config schema {} updated to config DS with DPN's {}", schemaName, ItmUtils.getDpnIdList(schema.getDpnIds())); + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.vpnservice.itm.api.IITMProvider#deleteAllVtepSchemas() + */ + @Override + public void deleteAllVtepSchemas() { + List lstSchemas = getAllVtepConfigSchemas(); + if (lstSchemas != null && !lstSchemas.isEmpty()) { + for (VtepConfigSchema schema : lstSchemas) { + MDSALUtil.syncDelete(this.dataBroker, LogicalDatastoreType.CONFIGURATION, + ItmUtils.getVtepConfigSchemaIdentifier(schema.getSchemaName())); + } + } + LOG.debug("Deleted all Vtep schemas from config DS"); + } + + public void configureTunnelMonitorEnabled(boolean monitorEnabled) { + tepCommandHelper.configureTunnelMonitorEnabled(monitorEnabled); + } + + public void configureTunnelMonitorInterval(int interval) { + tepCommandHelper.configureTunnelMonitorInterval(interval); + } } diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ItmUtils.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ItmUtils.java index f597e9f3..7aa7fa99 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ItmUtils.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ItmUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015, 2016 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, @@ -11,10 +11,13 @@ import java.math.BigInteger; import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +import com.google.common.util.concurrent.CheckedFuture; import org.apache.commons.lang3.StringUtils; import org.apache.commons.net.util.SubnetUtils; import org.apache.commons.net.util.SubnetUtils.SubnetInfo; @@ -22,9 +25,19 @@ 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.TransactionCommitFailedException; +import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.opendaylight.vpnservice.itm.confighelpers.HwVtep; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.VtepConfigSchemas; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.VtepIpPools; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchemaBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchemaKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.ip.pools.VtepIpPool; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.ip.pools.VtepIpPoolKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput; @@ -32,6 +45,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.interfaces._interface.NodeIdentifier; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.interfaces._interface.NodeIdentifierBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.interfaces._interface.NodeIdentifierKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.DpnEndpoints; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.DpnEndpointsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo; @@ -46,6 +62,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnelBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnelKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre; import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; import org.opendaylight.vpnservice.itm.globals.ITMConstants; import org.opendaylight.vpnservice.mdsalutil.MDSALUtil; @@ -54,7 +71,13 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types. import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.vtep.config.schema.DpnIds ; //import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice._interface.service.rev150602._interface.service.info.ServiceInfo; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.vtep.config.schema.DpnIdsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.vtep.config.schema.DpnIdsKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.vtep.config.schema.DpnIds; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; @@ -62,7 +85,6 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces. import org.opendaylight.yangtools.yang.common.RpcResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.opendaylight.vpnservice.mdsalutil.ActionInfo; import org.opendaylight.vpnservice.mdsalutil.ActionType; import org.opendaylight.vpnservice.mdsalutil.FlowEntity; @@ -72,6 +94,7 @@ import org.opendaylight.vpnservice.mdsalutil.MatchFieldType; import org.opendaylight.vpnservice.mdsalutil.MatchInfo; import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil; import org.opendaylight.vpnservice.mdsalutil.NwConstants; + import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.net.InetAddresses; @@ -132,6 +155,16 @@ public class ItmUtils { tx.delete(datastoreType, path); Futures.addCallback(tx.submit(), callback); } + public static void asyncBulkRemove(final DataBroker broker,final LogicalDatastoreType datastoreType, + List> pathList, FutureCallback callback) { + if (!pathList.isEmpty()) { + WriteTransaction tx = broker.newWriteOnlyTransaction(); + for (InstanceIdentifier path : pathList) { + tx.delete(datastoreType, path); + } + Futures.addCallback(tx.submit(), callback); + } + } public static String getInterfaceName(final BigInteger datapathid, final String portName, final Integer vlanId) { return String.format("%s:%s:%s", datapathid, portName, vlanId); @@ -191,27 +224,56 @@ public class ItmUtils { } public static Interface buildTunnelInterface(BigInteger dpn, String ifName, String desc, boolean enabled, Class tunType, - IpAddress localIp, IpAddress remoteIp, IpAddress gatewayIp, boolean internal) { + IpAddress localIp, IpAddress remoteIp, IpAddress gatewayIp,Integer vlanId, boolean internal, boolean monitorEnabled, Long monitorInterval) { InterfaceBuilder builder = new InterfaceBuilder().setKey(new InterfaceKey(ifName)).setName(ifName) .setDescription(desc).setEnabled(enabled).setType(Tunnel.class); ParentRefs parentRefs = new ParentRefsBuilder().setDatapathNodeIdentifier(dpn).build(); builder.addAugmentation(ParentRefs.class, parentRefs); + if( vlanId > 0) { + IfL2vlan l2vlan = new IfL2vlanBuilder().setVlanId(new VlanId(vlanId)).build(); + builder.addAugmentation(IfL2vlan.class, l2vlan); + } + //use default monitoring value from Global Constants + Long monitoringInterval = 10000L; + if(monitorInterval!= null) + monitoringInterval = monitorInterval; IfTunnel tunnel = new IfTunnelBuilder().setTunnelDestination(remoteIp).setTunnelGateway(gatewayIp).setTunnelSource(localIp) - .setTunnelInterfaceType( tunType).setInternal(internal).build(); + .setTunnelInterfaceType(tunType).setInternal(internal).setMonitorEnabled(monitorEnabled).setMonitorInterval(monitoringInterval).build(); builder.addAugmentation(IfTunnel.class, tunnel); return builder.build(); } + public static Interface buildHwTunnelInterface(String tunnelIfName, String desc , boolean enabled, String topo_id, String node_id, + Class tunType, IpAddress srcIp , IpAddress destIp, IpAddress gWIp, + boolean monitor_enabled + ){ + InterfaceBuilder builder = new InterfaceBuilder().setKey(new InterfaceKey(tunnelIfName)).setName(tunnelIfName).setDescription(desc). + setEnabled(enabled).setType(Tunnel.class); + List nodeIds = new ArrayList(); + NodeIdentifier hWnode = new NodeIdentifierBuilder().setKey(new NodeIdentifierKey(topo_id)).setTopologyId( + topo_id). + setNodeId(node_id).build(); + nodeIds.add(hWnode); + ParentRefs parent = new ParentRefsBuilder().setNodeIdentifier(nodeIds).build(); + builder.addAugmentation(ParentRefs.class , parent); + IfTunnel tunnel = new IfTunnelBuilder().setTunnelDestination(destIp).setTunnelGateway(gWIp).setTunnelSource( + srcIp).setMonitorEnabled(monitor_enabled).setTunnelInterfaceType(tunType).setInternal(false).build(); + builder.addAugmentation(IfTunnel.class, tunnel); + LOG.trace("iftunnel {} built from hwvtep {} ",tunnel,node_id); + return builder.build(); + } + + public static InternalTunnel buildInternalTunnel( BigInteger srcDpnId, BigInteger dstDpnId, String trunkInterfaceName) { - InternalTunnel tnl = new InternalTunnelBuilder().setKey(new InternalTunnelKey(srcDpnId, dstDpnId)) - .setDestinationDPN(dstDpnId) - .setSourceDPN(srcDpnId) + InternalTunnel tnl = new InternalTunnelBuilder().setKey(new InternalTunnelKey(dstDpnId,srcDpnId)).setDestinationDPN(dstDpnId) + .setSourceDPN(srcDpnId) .setTunnelInterfaceName(trunkInterfaceName).build(); return tnl ; } - public static ExternalTunnel buildExternalTunnel( BigInteger srcDpnId, IpAddress dstIp, String trunkInterfaceName) { - ExternalTunnel extTnl = new ExternalTunnelBuilder().setKey(new ExternalTunnelKey(dstIp, srcDpnId)).setSourceDPN(srcDpnId).setDestinationIP(dstIp).setTunnelInterfaceName(trunkInterfaceName).build(); + public static ExternalTunnel buildExternalTunnel(String srcNode, String dstNode, String trunkInterfaceName) { + ExternalTunnel extTnl = new ExternalTunnelBuilder().setKey( + new ExternalTunnelKey(dstNode, srcNode)).setSourceDevice(srcNode).setDestinationDevice(dstNode).setTunnelInterfaceName(trunkInterfaceName).build(); return extTnl ; } @@ -220,12 +282,12 @@ public class ItmUtils { // Read the EndPoint Info from the operational database InstanceIdentifierBuilder depBuilder = InstanceIdentifier.builder( DpnEndpoints.class) ; - InstanceIdentifier deps = depBuilder.build() ; + InstanceIdentifier deps = depBuilder.build(); Optional dpnEps = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, deps, dataBroker); - if( dpnEps.isPresent()) { + if (dpnEps.isPresent()) { DpnEndpoints tn= dpnEps.get() ; - dpnTEPs = tn.getDPNTEPsInfo() ; - LOG.debug( "Read from CONFIGURATION datastore - No. of Dpns " , dpnTEPs.size() ); + dpnTEPs = tn.getDPNTEPsInfo(); + LOG.debug( "Read from CONFIGURATION datastore - No. of Dpns " , dpnTEPs.size() ); }else LOG.debug( "No Dpn information in CONFIGURATION datastore " ); return dpnTEPs ; @@ -251,7 +313,8 @@ public class ItmUtils { } public static void releaseId(IdManagerService idManager, String idKey) { - ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(ITMConstants.ITM_IDPOOL_NAME).setIdKey(idKey).build(); + ReleaseIdInput idInput = + new ReleaseIdInputBuilder().setPoolName(ITMConstants.ITM_IDPOOL_NAME).setIdKey(idKey).build(); try { Future> result = idManager.releaseId(idInput); RpcResult rpcResult = result.get(); @@ -316,4 +379,297 @@ public class ItmUtils { private static String getFlowRef(long termSvcTable, int svcId) { return new StringBuffer().append(termSvcTable).append(svcId).toString(); } + public static InstanceIdentifier getVtepConfigSchemaIdentifier(String schemaName) { + return InstanceIdentifier.builder(VtepConfigSchemas.class) + .child(VtepConfigSchema.class, new VtepConfigSchemaKey(schemaName)).build(); + } + + public static InstanceIdentifier getVtepConfigSchemaIdentifier() { + return InstanceIdentifier.builder(VtepConfigSchemas.class).child(VtepConfigSchema.class).build(); + } + public static InstanceIdentifier getVtepConfigSchemasIdentifier() { + return InstanceIdentifier.builder(VtepConfigSchemas.class).build(); + } + public static InstanceIdentifier getVtepIpPoolIdentifier(String subnetCidr) { + return InstanceIdentifier.builder(VtepIpPools.class).child(VtepIpPool.class, new VtepIpPoolKey(subnetCidr)) + .build(); + } + public static VtepConfigSchema validateForAddVtepConfigSchema(VtepConfigSchema schema, + List existingSchemas) { + VtepConfigSchema validSchema = validateVtepConfigSchema(schema); + for (VtepConfigSchema existingSchema : emptyIfNull(existingSchemas)) { + if (!StringUtils.equalsIgnoreCase(schema.getSchemaName(), existingSchema.getSchemaName()) + && schema.getSubnet().equals(existingSchema.getSubnet())) { + String subnetCidr = getSubnetCidrAsString(schema.getSubnet()); + Preconditions.checkArgument(false, new StringBuilder("VTEP schema with subnet [").append(subnetCidr) + .append("] already exists. Multiple VTEP schemas with same subnet is not allowed.").toString()); + } + } + if (isNotEmpty(getDpnIdList(validSchema.getDpnIds()))) { + String tzone = validSchema.getTransportZoneName(); + List lstDpns = getConflictingDpnsAlreadyConfiguredWithTz(validSchema.getSchemaName(), tzone, + getDpnIdList(validSchema.getDpnIds()), existingSchemas); + if (!lstDpns.isEmpty()) { + Preconditions.checkArgument(false, + new StringBuilder("DPN's ").append(lstDpns).append(" already configured for transport zone ") + .append(tzone).append(". Only one end point per transport Zone per Dpn is allowed.") + .toString()); + } + if (schema.getTunnelType().equals(TunnelTypeGre.class)){ + validateForSingleGreTep(validSchema.getSchemaName(), getDpnIdList(validSchema.getDpnIds()), existingSchemas); + } + } + return validSchema; + } + private static void validateForSingleGreTep(String schemaName, List lstDpnsForAdd, + List existingSchemas) { + for (VtepConfigSchema existingSchema : emptyIfNull(existingSchemas)) { + if ((TunnelTypeGre.class).equals(existingSchema.getTunnelType()) + && !StringUtils.equalsIgnoreCase(schemaName, existingSchema.getSchemaName())) { + List lstConflictingDpns = new ArrayList<>(getDpnIdList(existingSchema.getDpnIds())); + lstConflictingDpns.retainAll(emptyIfNull(lstDpnsForAdd)); + if (!lstConflictingDpns.isEmpty()) { + String errMsg = new StringBuilder("DPN's ").append(lstConflictingDpns) + .append(" already configured with GRE TEP. Mutiple GRE TEP's on a single DPN are not allowed.") + .toString(); + Preconditions.checkArgument(false, errMsg); + } + } + } + } + public static VtepConfigSchema validateVtepConfigSchema(VtepConfigSchema schema) { + Preconditions.checkNotNull(schema); + Preconditions.checkArgument(StringUtils.isNotBlank(schema.getSchemaName())); + Preconditions.checkArgument(StringUtils.isNotBlank(schema.getPortName())); + Preconditions.checkArgument((schema.getVlanId() >= 0 && schema.getVlanId() < 4095), + "Invalid VLAN ID, range (0-4094)"); + Preconditions.checkArgument(StringUtils.isNotBlank(schema.getTransportZoneName())); + Preconditions.checkNotNull(schema.getSubnet()); + String subnetCidr = getSubnetCidrAsString(schema.getSubnet()); + SubnetUtils subnetUtils = new SubnetUtils(subnetCidr); + IpAddress gatewayIp = schema.getGatewayIp(); + if (gatewayIp != null) { + String strGatewayIp = String.valueOf(gatewayIp.getValue()); + if (!strGatewayIp.equals(ITMConstants.DUMMY_IP_ADDRESS) && !subnetUtils.getInfo().isInRange(strGatewayIp)) { + Preconditions.checkArgument(false, new StringBuilder("Gateway IP address ").append(strGatewayIp) + .append(" is not in subnet range ").append(subnetCidr).toString()); + } + } + ItmUtils.getExcludeIpAddresses(schema.getExcludeIpFilter(), subnetUtils.getInfo()); + return new VtepConfigSchemaBuilder(schema).setTunnelType(schema.getTunnelType()).build(); + } + public static String validateTunnelType(String tunnelType) { + if (tunnelType == null) { + tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN; + } else { + tunnelType = StringUtils.upperCase(tunnelType); + String error = new StringBuilder("Invalid tunnel type. Valid values: ") + .append(ITMConstants.TUNNEL_TYPE_VXLAN).append(" | ").append(ITMConstants.TUNNEL_TYPE_GRE) + .toString(); + Preconditions.checkArgument(ITMConstants.TUNNEL_TYPE_VXLAN.equals(tunnelType) + || ITMConstants.TUNNEL_TYPE_GRE.equals(tunnelType), error); + } + return tunnelType; + } + private static List getConflictingDpnsAlreadyConfiguredWithTz(String schemaName, String tzone, + List lstDpns, List existingSchemas) { + List lstConflictingDpns = new ArrayList<>(); + for (VtepConfigSchema schema : emptyIfNull(existingSchemas)) { + if (!StringUtils.equalsIgnoreCase(schemaName, schema.getSchemaName()) + && StringUtils.equals(schema.getTransportZoneName(), tzone)) { + lstConflictingDpns = new ArrayList<>(getDpnIdList(schema.getDpnIds())); + lstConflictingDpns.retainAll(lstDpns); + if (!lstConflictingDpns.isEmpty()) { + break; + } + } + } + return lstConflictingDpns; + } + public static VtepConfigSchema constructVtepConfigSchema(String schemaName, String portName, Integer vlanId, + String subnetMask, String gatewayIp, String transportZone,String tunnelType, List dpnIds, + String excludeIpFilter) { + IpAddress gatewayIpObj = StringUtils.isBlank(gatewayIp) ? null : new IpAddress(gatewayIp.toCharArray()); + IpPrefix subnet = StringUtils.isBlank(subnetMask) ? null : new IpPrefix(subnetMask.toCharArray()); + Class tunType ; + if( tunnelType.equals(ITMConstants.TUNNEL_TYPE_VXLAN)) + tunType = TunnelTypeVxlan.class ; + else + tunType = TunnelTypeGre.class ; + VtepConfigSchemaBuilder schemaBuilder = new VtepConfigSchemaBuilder().setSchemaName(schemaName) + .setPortName(portName).setVlanId(vlanId).setSubnet(subnet).setGatewayIp(gatewayIpObj) + .setTransportZoneName(transportZone).setTunnelType(tunType).setDpnIds(getDpnIdsListFromBigInt(dpnIds)) + .setExcludeIpFilter(excludeIpFilter); + return schemaBuilder.build(); + } + public static List getExcludeIpAddresses(String excludeIpFilter, SubnetInfo subnetInfo) { + final List lstIpAddress = new ArrayList<>(); + if (StringUtils.isBlank(excludeIpFilter)) { + return lstIpAddress; + } + final String[] arrIps = StringUtils.split(excludeIpFilter, ','); + for (String ip : arrIps) { + if (StringUtils.countMatches(ip, "-") == 1) { + final String[] arrIpRange = StringUtils.split(ip, '-'); + String strStartIp = StringUtils.trim(arrIpRange[0]); + String strEndIp = StringUtils.trim(arrIpRange[1]); + Preconditions.checkArgument(InetAddresses.isInetAddress(strStartIp), + new StringBuilder("Invalid exclude IP filter: invalid IP address value ").append(strStartIp) + .toString()); + Preconditions.checkArgument(InetAddresses.isInetAddress(strEndIp), + new StringBuilder("Invalid exclude IP filter: invalid IP address value ").append(strEndIp) + .toString()); + Preconditions.checkArgument(subnetInfo.isInRange(strStartIp), + new StringBuilder("Invalid exclude IP filter: IP address [").append(strStartIp) + .append("] not in subnet range ").append(subnetInfo.getCidrSignature()).toString()); + Preconditions.checkArgument(subnetInfo.isInRange(strEndIp), + new StringBuilder("Invalid exclude IP filter: IP address [").append(strEndIp) + .append("] not in subnet range ").append(subnetInfo.getCidrSignature()).toString()); + int startIp = subnetInfo.asInteger(strStartIp); + int endIp = subnetInfo.asInteger(strEndIp); + + Preconditions.checkArgument(startIp < endIp, + new StringBuilder("Invalid exclude IP filter: Invalid range [").append(ip).append("] ") + .toString()); + for (int i = startIp; i <= endIp; i++) { + String ipAddress = ipFormat(toIpArray(i)); + validateAndAddIpAddressToList(subnetInfo, lstIpAddress, ipAddress); + } + } else { + validateAndAddIpAddressToList(subnetInfo, lstIpAddress, ip); + } + } + return lstIpAddress; + } + private static void validateAndAddIpAddressToList(SubnetInfo subnetInfo, final List lstIpAddress, + String ipAddress) { + String ip = StringUtils.trim(ipAddress); + Preconditions.checkArgument(InetAddresses.isInetAddress(ip), + new StringBuilder("Invalid exclude IP filter: invalid IP address value ").append(ip).toString()); + Preconditions.checkArgument(subnetInfo.isInRange(ip), + new StringBuilder("Invalid exclude IP filter: IP address [").append(ip).append("] not in subnet range ") + .append(subnetInfo.getCidrSignature()).toString()); + lstIpAddress.add(new IpAddress(ip.toCharArray())); + } + private static int[] toIpArray(int val) { + int[] ret = new int[4]; + for (int j = 3; j >= 0; --j) { + ret[j] |= ((val >>> 8 * (3 - j)) & (0xff)); + } + return ret; + } + private static String ipFormat(int[] octets) { + StringBuilder str = new StringBuilder(); + for (int i = 0; i < octets.length; ++i) { + str.append(octets[i]); + if (i != octets.length - 1) { + str.append("."); + } + } + return str.toString(); + } + public static VtepConfigSchema validateForUpdateVtepSchema(String schemaName, List lstDpnsForAdd, + List lstDpnsForDelete, IITMProvider itmProvider) { + Preconditions.checkArgument(StringUtils.isNotBlank(schemaName)); + if ((lstDpnsForAdd == null || lstDpnsForAdd.isEmpty()) + && (lstDpnsForDelete == null || lstDpnsForDelete.isEmpty())) { + Preconditions.checkArgument(false, + new StringBuilder("DPN ID list for add | delete is null or empty in schema ").append(schemaName) + .toString()); + } + VtepConfigSchema schema = itmProvider.getVtepConfigSchema(schemaName); + if (schema == null) { + Preconditions.checkArgument(false, new StringBuilder("Specified VTEP Schema [").append(schemaName) + .append("] doesn't exists!").toString()); + } + List existingDpnIds = getDpnIdList(schema.getDpnIds()); + if (isNotEmpty(lstDpnsForAdd)) { + if (isNotEmpty(existingDpnIds)) { + List lstAlreadyExistingDpns = new ArrayList<>(existingDpnIds); + lstAlreadyExistingDpns.retainAll(lstDpnsForAdd); + Preconditions.checkArgument(lstAlreadyExistingDpns.isEmpty(), + new StringBuilder("DPN ID's ").append(lstAlreadyExistingDpns) + .append(" already exists in VTEP schema [").append(schemaName).append("]").toString()); + } + if (schema.getTunnelType().equals(TunnelTypeGre.class)) { + validateForSingleGreTep(schema.getSchemaName(), lstDpnsForAdd, itmProvider.getAllVtepConfigSchemas()); + } + } + if (isNotEmpty(lstDpnsForDelete)) { + if (existingDpnIds == null || existingDpnIds.isEmpty()) { + StringBuilder builder = new StringBuilder("DPN ID's ").append(lstDpnsForDelete) + .append(" specified for delete from VTEP schema [").append(schemaName) + .append("] are not configured in the schema."); + Preconditions.checkArgument(false, builder.toString()); + } else if (!existingDpnIds.containsAll(lstDpnsForDelete)) { + List lstConflictingDpns = new ArrayList<>(lstDpnsForDelete); + lstConflictingDpns.removeAll(existingDpnIds); + StringBuilder builder = new StringBuilder("DPN ID's ").append(lstConflictingDpns) + .append(" specified for delete from VTEP schema [").append(schemaName) + .append("] are not configured in the schema."); + Preconditions.checkArgument(false, builder.toString()); + } + } + return schema; + } + public static String getSubnetCidrAsString(IpPrefix subnet) { + return (subnet == null) ? StringUtils.EMPTY : String.valueOf(subnet.getValue()); + } + public static List emptyIfNull(List list) { + return (list == null) ? Collections. emptyList() : list; + } + public static boolean isEmpty(Collection collection) { + return (collection == null || collection.isEmpty()) ? true : false; + } + public static boolean isNotEmpty(Collection collection) { + return !isEmpty(collection); + } + public static HwVtep createHwVtepObject(String topo_id, String node_id, IpAddress ipAddress, IpPrefix ipPrefix, IpAddress gatewayIP, int vlanID, Class tunnel_type, TransportZone transportZone) { + HwVtep hwVtep = new HwVtep(); + hwVtep.setGatewayIP(gatewayIP); + hwVtep.setHwIp(ipAddress); + hwVtep.setIpPrefix(ipPrefix); + hwVtep.setNode_id(node_id); + hwVtep.setTopo_id(topo_id); + hwVtep.setTransportZone(transportZone.getZoneName()); + hwVtep.setTunnel_type(tunnel_type); + hwVtep.setVlanID(vlanID); + return hwVtep; + } + + public static String getHwParentIf(String topo_id, String srcNodeid) { + return String.format("%s:%s", topo_id, srcNodeid); + } + + public static void syncWrite(LogicalDatastoreType datastoreType, + InstanceIdentifier path, T data, DataBroker broker) { + WriteTransaction tx = broker.newWriteOnlyTransaction(); + tx.put(datastoreType, path, data, true); + CheckedFuture futures = tx.submit(); + try { + futures.get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("ITMUtils:SyncWrite , Error writing to datastore (path, data) : ({}, {})", path, data); + throw new RuntimeException(e.getMessage()); + } + } + + public static List getDpnIdList( List dpnIds ) { + List dpnList = new ArrayList() ; + for( DpnIds dpn : dpnIds) { + dpnList.add(dpn.getDPN()) ; + } + return dpnList ; + } + + public static List getDpnIdsListFromBigInt( List dpnIds) { + List dpnIdList = new ArrayList() ; + DpnIdsBuilder builder = new DpnIdsBuilder() ; + for( BigInteger dpnId : dpnIds) { + dpnIdList.add(builder.setKey(new DpnIdsKey(dpnId)).setDPN(dpnId).build() ); + } + return dpnIdList; + } + } + diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/listeners/TransportZoneListener.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/listeners/TransportZoneListener.java index f15bd19b..fae12dc6 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/listeners/TransportZoneListener.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/listeners/TransportZoneListener.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015, 2016 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, @@ -9,10 +9,7 @@ package org.opendaylight.vpnservice.itm.listeners; import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import com.google.common.base.Optional; @@ -22,6 +19,7 @@ import com.google.common.util.concurrent.ListenableFuture; import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.vpnservice.itm.confighelpers.HwVtep; 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.inet.types.rev100924.IpPrefix; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService; @@ -32,6 +30,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.Tr import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZonesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.Subnets; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVteps; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.Vteps; import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase; import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator; @@ -107,34 +106,99 @@ public class TransportZoneListener extends AsyncDataTreeChangeListenerBase key, TransportZone tzOld) { LOG.debug("Received Transport Zone Remove Event: {}, {}", key, tzOld); List opDpnList = createDPNTepInfo(tzOld); + List hwVtepList = createhWVteps(tzOld); LOG.trace("Delete: Invoking deleteTunnels in ItmManager with DpnList {}", opDpnList); - if(opDpnList.size()>0) { + if(opDpnList.size()>0 || hwVtepList.size()>0) { LOG.trace("Delete: Invoking ItmManager"); - // itmManager.deleteTunnels(opDpnList); + LOG.trace("Add: Invoking ItmManager with hwVtep List {} " , hwVtepList); + // itmManager.deleteTunnels(opDpnList); DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance(); - ItmTepRemoveWorker removeWorker = new ItmTepRemoveWorker(opDpnList, dataBroker, idManagerService, mdsalManager); + ItmTepRemoveWorker removeWorker = new ItmTepRemoveWorker(opDpnList,hwVtepList, dataBroker, idManagerService, mdsalManager); coordinator.enqueueJob(tzOld.getZoneName(), removeWorker); } } @Override protected void update(InstanceIdentifier key, TransportZone tzOld, TransportZone tzNew) { - LOG.debug("Received Transport Zone Update Event: {}, {}, {}", key, tzOld, tzNew); - if( !(tzOld.equals(tzNew))) { - add(key, tzNew); + LOG.debug("Received Transport Zone Update Event: Key - {}, Old - {}, Updated - {}", key, tzOld, tzNew); + //if( !(tzOld.equals(tzNew))) { + //add(key, tzNew); + List oldDpnTepsList = new ArrayList(); + oldDpnTepsList = createDPNTepInfo(tzOld); + List newDpnTepsList = new ArrayList(); + newDpnTepsList = createDPNTepInfo(tzNew); + List oldDpnTepsListcopy = new ArrayList(); + oldDpnTepsListcopy.addAll(oldDpnTepsList); + LOG.trace("oldcopy0" + oldDpnTepsListcopy); + List newDpnTepsListcopy = new ArrayList(); + newDpnTepsListcopy.addAll(newDpnTepsList); + LOG.trace("newcopy0" + newDpnTepsListcopy); + DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance(); + + oldDpnTepsList.removeAll(newDpnTepsListcopy); + newDpnTepsList.removeAll(oldDpnTepsListcopy); + + LOG.trace("oldDpnTepsList" + oldDpnTepsList); + LOG.trace("newDpnTepsList" + newDpnTepsList); + LOG.trace("oldcopy"+oldDpnTepsListcopy); + LOG.trace("newcopy"+newDpnTepsListcopy); + LOG.trace("oldcopy Size "+oldDpnTepsList.size()); + LOG.trace("newcopy Size "+newDpnTepsList.size()); + if(newDpnTepsList.size() > 0) { + LOG.trace( "Adding TEPs " ); + ItmTepAddWorker addWorker = new ItmTepAddWorker(newDpnTepsList, Collections.emptyList(), dataBroker, idManagerService, mdsalManager); + coordinator.enqueueJob(tzNew.getZoneName(), addWorker); + } + if(oldDpnTepsList.size() > 0) { + LOG.trace( "Removing TEPs " ); + ItmTepRemoveWorker removeWorker = + new ItmTepRemoveWorker(oldDpnTepsList, Collections.emptyList(), dataBroker, idManagerService, mdsalManager); + coordinator.enqueueJob(tzNew.getZoneName(), removeWorker); + } + List oldHwList = new ArrayList(); + oldHwList = createhWVteps(tzOld); + List newHwList = new ArrayList(); + newHwList = createhWVteps(tzNew); + List oldHwListcopy = new ArrayList(); + oldHwListcopy.addAll(oldHwList); + LOG.trace("oldHwListcopy0" + oldHwListcopy); + List newHwListcopy = new ArrayList(); + newHwListcopy.addAll(newHwList); + LOG.trace("newHwListcopy0" + newHwListcopy); + + oldHwList.removeAll(newHwListcopy); + newHwList.removeAll(oldHwListcopy); + LOG.trace("oldHwList" + oldHwList); + LOG.trace("newHwList" + newHwList); + LOG.trace("oldHwListcopy" + oldHwListcopy); + LOG.trace("newHwListcopy" + newHwListcopy); + if(newHwList.size() > 0) { + LOG.trace( "Adding HW TEPs " ); + ItmTepAddWorker addWorker = new ItmTepAddWorker(Collections.emptyList(), newHwList, dataBroker, idManagerService, mdsalManager); + coordinator.enqueueJob(tzNew.getZoneName(), addWorker); } + if(oldHwList.size() > 0) { + LOG.trace( "Removing HW TEPs " ); + ItmTepRemoveWorker removeWorker = + new ItmTepRemoveWorker(Collections.emptyList(), oldHwList, dataBroker, + idManagerService, mdsalManager); + coordinator.enqueueJob(tzNew.getZoneName(), removeWorker); + } + } @Override protected void add(InstanceIdentifier key, TransportZone tzNew) { LOG.debug("Received Transport Zone Add Event: {}, {}", key, tzNew); List opDpnList = createDPNTepInfo(tzNew); + List hwVtepList = createhWVteps(tzNew); LOG.trace("Add: Operational dpnTepInfo - Before invoking ItmManager {}", opDpnList); - if(opDpnList.size()>0) { - LOG.trace("Add: Invoking ItmManager with DPN List {} " , opDpnList); + if(opDpnList.size()>0 || hwVtepList.size()>0) { + LOG.trace("Add: Invoking ItmManager with DPN List {} " , opDpnList); + LOG.trace("Add: Invoking ItmManager with hwVtep List {} " , hwVtepList); //itmManager.build_all_tunnels(opDpnList); DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance(); - ItmTepAddWorker addWorker = new ItmTepAddWorker(opDpnList,dataBroker, idManagerService, mdsalManager); + ItmTepAddWorker addWorker = new ItmTepAddWorker(opDpnList, hwVtepList, dataBroker, idManagerService, mdsalManager); coordinator.enqueueJob(tzNew.getZoneName(), addWorker); } } @@ -186,4 +250,45 @@ public class TransportZoneListener extends AsyncDataTreeChangeListenerBase createhWVteps(TransportZone transportZone) { + //creating hwVtepsList to pass + //Inventory model would deprecate Eventually, so not creating hWvtepslist under createDpnTepInfo(); + List hwVtepsList = new ArrayList(); + //currently the list has only one object always since we are adding L2Gws one by one and only to One TransportZone. + //Map> mapDPNToTunnelEndpt = new ConcurrentHashMap<>(); + + String zone_name = transportZone.getZoneName(); + Class tunnel_type = transportZone.getTunnelType(); + LOG.trace("Transport Zone_name: {}", zone_name); + List subnetsList = transportZone.getSubnets(); + if (subnetsList != null) { + for (Subnets subnet : subnetsList) { + IpPrefix ipPrefix = subnet.getPrefix(); + IpAddress gatewayIP = subnet.getGatewayIp(); + int vlanID = subnet.getVlanId(); + LOG.trace("IpPrefix: {}, gatewayIP: {}, vlanID: {} ", ipPrefix, gatewayIP, vlanID); + List deviceVtepsList = subnet.getDeviceVteps(); + if (deviceVtepsList != null) { + for (DeviceVteps vteps : deviceVtepsList) { + String topo_id = vteps.getTopologyId(); + String node_id = vteps.getNodeId(); + IpAddress ipAddress = vteps.getIpAddress(); + LOG.trace("topo-id: {}, node-id: {}, ipAddress: {}", topo_id, node_id, ipAddress); + //TunnelEndPoints tunnelEndPoints = ItmUtils.createTunnelEndPoints(dpnID, ipAddress, port, vlanID, ipPrefix, gatewayIP, zone_name, tunnel_type); + HwVtep hwVtep = ItmUtils.createHwVtepObject(topo_id, node_id, ipAddress, ipPrefix, gatewayIP, vlanID, tunnel_type, transportZone); + + if (hwVtepsList != null) { + LOG.trace("Existing hwVteps"); + hwVtepsList.add(hwVtep); + } else { + LOG.trace("Adding new HwVtep {} info ", hwVtep.getHwIp()); + hwVtepsList.add(hwVtep); + } + } + } + } + } + LOG.trace("returning hwvteplist {}", hwVtepsList); + return hwVtepsList; + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/listeners/VtepConfigSchemaListener.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/listeners/VtepConfigSchemaListener.java new file mode 100644 index 00000000..9b8b138c --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/listeners/VtepConfigSchemaListener.java @@ -0,0 +1,592 @@ +/* + * Copyright (c) 2016 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.itm.listeners; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.net.util.SubnetUtils; +import org.apache.commons.net.util.SubnetUtils.SubnetInfo; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.itm.cli.TepCommandHelper; +import org.opendaylight.vpnservice.itm.globals.ITMConstants; +import org.opendaylight.vpnservice.itm.impl.ItmUtils; +import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener; +import org.opendaylight.vpnservice.mdsalutil.MDSALUtil; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.VtepConfigSchemas; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchemaBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.ip.pools.VtepIpPool; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.ip.pools.VtepIpPoolBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.vtep.config.schema.DpnIds; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.vtep.config.schema.DpnIdsKey; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.VtepConfigSchemas; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.vtep.config.schemas.VtepConfigSchemaBuilder; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.vtep.ip.pools.VtepIpPool; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.vtep.ip.pools.VtepIpPoolBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZoneKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.Subnets; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.SubnetsKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.Vteps; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.VtepsKey; +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.Optional; + +/** + * The listener class interested in processing data change on + * {@code VtepConfigSchema} objects. + * + * @see VtepConfigSchema + */ +public class VtepConfigSchemaListener extends AbstractDataChangeListener implements AutoCloseable { + + /** The Constant LOG. */ + private static final Logger LOG = LoggerFactory.getLogger(VtepConfigSchemaListener.class); + + /** The listener registration. */ + private ListenerRegistration listenerRegistration; + + /** The data broker. */ + private final DataBroker dataBroker; + + /** + * Instantiates a new vtep config schema listener. + * + * @param db + * the db + */ + public VtepConfigSchemaListener(final DataBroker db) { + super(VtepConfigSchema.class); + this.dataBroker = db; + registerListener(db); + } + + /* + * (non-Javadoc) + * + * @see java.lang.AutoCloseable#close() + */ + @Override + public void close() throws Exception { + if (this.listenerRegistration != null) { + try { + this.listenerRegistration.close(); + } catch (final Exception e) { + LOG.error("Error when cleaning up DataChangeListener.", e); + } + this.listenerRegistration = null; + } + LOG.info("VtepConfigSchemaListener Closed"); + } + + /** + * Register listener. + * + * @param db + * the db + */ + private void registerListener(final DataBroker db) { + try { + this.listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, + getWildCardPath(), VtepConfigSchemaListener.this, AsyncDataBroker.DataChangeScope.SUBTREE); + } catch (final Exception e) { + LOG.error("VtepConfigSchemaListener DataChange listener registration fail!", e); + throw new IllegalStateException("VtepConfigSchemaListener registration Listener failed.", e); + } + } + + /** + * Gets the wild card path. + * + * @return the wild card path + */ + private InstanceIdentifier getWildCardPath() { + return ItmUtils.getVtepConfigSchemaIdentifier(); + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener#remove( + * org.opendaylight.yangtools.yang.binding.InstanceIdentifier, + * org.opendaylight.yangtools.yang.binding.DataObject) + */ + @Override + protected void remove(InstanceIdentifier identifier, VtepConfigSchema schema) { + LOG.trace("Received notification for VTEP config schema [{}] deleted.", schema.getSchemaName()); + try { + List lstDpnIds = ItmUtils.getDpnIdList(schema.getDpnIds()); + if (lstDpnIds != null && !lstDpnIds.isEmpty()) { + deleteVteps(schema, lstDpnIds); + } + + // Delete IP pool corresponding to schema + // TODO: Ensure no schema exists with same subnet before deleting + String subnetCidr = ItmUtils.getSubnetCidrAsString(schema.getSubnet()); + deleteVtepIpPool(subnetCidr); + } catch (Exception e) { + String error = new StringBuilder("Failed to handle DCN for delete VtepConfigSchema: ").append(schema) + .toString(); + LOG.error(error, e); + } + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener#update( + * org.opendaylight.yangtools.yang.binding.InstanceIdentifier, + * org.opendaylight.yangtools.yang.binding.DataObject, + * org.opendaylight.yangtools.yang.binding.DataObject) + */ + @Override + protected void update(InstanceIdentifier identifier, VtepConfigSchema original, + VtepConfigSchema updated) { + LOG.error("Receivedn DCN for updating VTEP Original schema: {}. Updated schema: {}", + original, updated); + //LOG.trace("Received notification for VTEP config schema [{}] updated.", original.getSchemaName()); + + try { + VtepConfigSchema orignalSchema = ItmUtils.validateVtepConfigSchema(original); + VtepConfigSchema updatedSchema = ItmUtils.validateVtepConfigSchema(updated); + + if (doesDeleteAndAddSchemaRequired(original, updated)) { + LOG.error("Failed to handle DCN for updating VTEP schema {}. Original schema: {}. Updated schema: {}", + original, updated); + // TODO: handle updates + return; + } + + handleUpdateOfDpnIds(orignalSchema, updatedSchema); + + } catch (Exception e) { + String error = new StringBuilder("Failed to handle DCN for update VtepConfigSchema original:") + .append(original).append(", updated: ").append(updated).toString(); + LOG.error(error, e); + } + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener#add(org. + * opendaylight.yangtools.yang.binding.InstanceIdentifier, + * org.opendaylight.yangtools.yang.binding.DataObject) + */ + @Override + protected void add(InstanceIdentifier identifier, VtepConfigSchema schema) { + // Construct the transport zones from the provided schemas and push it + // to config DS. + LOG.trace("Add VtepConfigSchema: key: {} , value: {}", identifier, schema); + + try { + VtepConfigSchema validatedSchema = ItmUtils.validateForAddVtepConfigSchema(schema, + getAllVtepConfigSchemas()); + + VtepIpPool vtepIpPool = processAvailableIps(validatedSchema); + addVteps(validatedSchema, vtepIpPool); + } catch (Exception e) { + LOG.error("Failed to handle DCN for add VtepConfigSchema: {}", e); + } + } + + /** + * Handle update of dpn ids. + * + * @param original + * the original + * @param updated + * the updated + */ + private void handleUpdateOfDpnIds(VtepConfigSchema original, VtepConfigSchema updated) { + // Handling add/delete DPNs from schema + List originalDpnIds = (original.getDpnIds() == null) ? new ArrayList() + : original.getDpnIds(); + List updatedDpnIds = (updated.getDpnIds() == null) ? new ArrayList() + : updated.getDpnIds(); + + handleDeletedDpnsFromSchema(original, originalDpnIds, updatedDpnIds); + handleNewlyAddedDpnsToSchema(original, originalDpnIds, updatedDpnIds); + } + + /** + * Does delete and add schema required. + * + * @param original + * the original + * @param updated + * the updated + * @return true, if successful + */ + private boolean doesDeleteAndAddSchemaRequired(VtepConfigSchema original, VtepConfigSchema updated) { + boolean delnAddRequired = false; + if (!StringUtils.equalsIgnoreCase(original.getPortName(), updated.getPortName())) { + delnAddRequired = true; + } else if (original.getVlanId() != updated.getVlanId()) { + delnAddRequired = true; + } else if (original.getSubnet() != null && !original.getSubnet().equals(updated.getSubnet())) { + delnAddRequired = true; + } else if (original.getGatewayIp() != null && !original.getGatewayIp().equals(updated.getGatewayIp())) { + delnAddRequired = true; + } else if (!StringUtils.equalsIgnoreCase(original.getTransportZoneName(), updated.getTransportZoneName())) { + delnAddRequired = true; + } else if (!(original.getTunnelType().equals(updated.getTunnelType()) )) { + delnAddRequired = true; + } + return delnAddRequired; + } + + /** + * Handle newly added dpns to schema. + * + * @param original + * the original + * @param originalDpnIds + * the original dpn ids + * @param updatedDpnIds + * the updated dpn ids + */ + private void handleNewlyAddedDpnsToSchema(VtepConfigSchema original, List originalDpnIds, + List updatedDpnIds) { + LOG.trace("Handle Addition of DPNs from VTEP Original Dpn: {}. Updated Dpn: {}", originalDpnIds, updatedDpnIds) ; + ArrayList newlyAddedDpns = new ArrayList<>(updatedDpnIds); + newlyAddedDpns.removeAll(originalDpnIds); + LOG.debug("Newly added DPNs {} to VTEP config schema [{}].", newlyAddedDpns, original.getSchemaName()); + if (!newlyAddedDpns.isEmpty()) { + VtepConfigSchema diffSchema = new VtepConfigSchemaBuilder(original).setDpnIds(newlyAddedDpns).build(); + String subnetCidr = ItmUtils.getSubnetCidrAsString(original.getSubnet()); + VtepIpPool vtepIpPool = getVtepIpPool(subnetCidr); + LOG.debug("Adding of DPNs in Diff Schema: {}", diffSchema) ; + addVteps(diffSchema, vtepIpPool); + } + } + + /** + * Handle deleted dpns from schema. + * + * @param original + * the original + * @param originalDpnIds + * the original dpn ids + * @param updatedDpnIds + * the updated dpn ids + */ + private void handleDeletedDpnsFromSchema(VtepConfigSchema original, List originalDpnIds, + List updatedDpnIds) { + ArrayList deletedDpns = new ArrayList<>(originalDpnIds); + deletedDpns.removeAll(updatedDpnIds); + LOG.debug("DPNs to be removed DPNs {} from VTEP config schema [{}].", deletedDpns, original.getSchemaName()); + if (!deletedDpns.isEmpty()) { + LOG.debug("Deleting of DPNs from VTEP Schema: {}. To be deleted Dpns: {}", original, deletedDpns) ; + deleteVteps(original, ItmUtils.getDpnIdList(deletedDpns)); + } + } + + /** + * Gets all vtep config schemas. + * + * @return the all vtep config schemas + */ + private List getAllVtepConfigSchemas() { + Optional schemas = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, + ItmUtils.getVtepConfigSchemasIdentifier(), this.dataBroker); + if (schemas.isPresent()) { + return schemas.get().getVtepConfigSchema(); + } + return null; + } + + /** + * Adds the vteps. + * + * @param schema + * the schema + * @param vtepIpPool + * the vtep ip pool + */ + private void addVteps(VtepConfigSchema schema, VtepIpPool vtepIpPool) { + if (schema.getDpnIds() == null || schema.getDpnIds().isEmpty()) { + LOG.debug("DPN list is empty, skipping addVteps for schema: {}", schema); + return; + } + + String subnetCidr = ItmUtils.getSubnetCidrAsString(schema.getSubnet()); + if (vtepIpPool == null) { + LOG.error("VTEP config pool not found for subnetCidr {}. Failed to add VTEPs for schema {}", subnetCidr, + schema); + return; + } + TepCommandHelper tepCommandHelper = new TepCommandHelper(this.dataBroker); + // Check this later + String tunType ; + Class tunnelType = schema.getTunnelType() ; + if( tunnelType.equals(TunnelTypeVxlan.class)) + tunType = ITMConstants.TUNNEL_TYPE_VXLAN ; + else + tunType = ITMConstants.TUNNEL_TYPE_GRE; + tepCommandHelper.configureTunnelType(schema.getTransportZoneName(), + StringUtils.upperCase(tunType)); + + List availableIps = vtepIpPool.getAvailableIpaddress(); + List newlyAllocatedIps = new ArrayList<>(); + List skippedDpnIds = new ArrayList<>(); + + String gatewayIp = handleGatewayIp(schema.getGatewayIp()); + for (BigInteger dpnId : ItmUtils.getDpnIdList(schema.getDpnIds())) { + IpAddress ipAddress = getAnAvailableIP(availableIps); + if (ipAddress == null) { + skippedDpnIds.add(dpnId); + continue; + } + tepCommandHelper.createLocalCache(dpnId, schema.getPortName(), schema.getVlanId(), + String.valueOf(ipAddress.getValue()), subnetCidr, gatewayIp, schema.getTransportZoneName()); + newlyAllocatedIps.add(ipAddress); + } + if (!skippedDpnIds.isEmpty()) { + LOG.error("No available IP addresses in the VTEP config pool {}, skipping VTEP configurations for DPN's {}", + subnetCidr, skippedDpnIds); + } + + if (!newlyAllocatedIps.isEmpty()) { + LOG.debug( "Delete OnCommit and buildTeps in NewlyAddedDpns"); + tepCommandHelper.deleteOnCommit(); + tepCommandHelper.buildTeps(); + allocateIpAddresses(newlyAllocatedIps, vtepIpPool, subnetCidr); + } + } + + /** + * Handle gateway ip. + * + * @param gatewayIp + * the gateway ip + * @return the string + */ + private String handleGatewayIp(IpAddress gatewayIp) { + String strGatewayIp = (gatewayIp == null) ? null : String.valueOf(gatewayIp.getValue()); + if (StringUtils.isBlank(strGatewayIp) || StringUtils.equals(ITMConstants.DUMMY_IP_ADDRESS, strGatewayIp)) { + // To avoid a validation exception in TepCommandHelper + strGatewayIp = null; + } + return strGatewayIp; + } + + /** + * Delete vteps. + * + * @param schema + * the schema + * @param lstDpnIdsToBeDeleted + * the dpn ids list to be deleted + */ + private void deleteVteps(VtepConfigSchema schema, List lstDpnIdsToBeDeleted) { + TepCommandHelper tepCommandHelper = new TepCommandHelper(this.dataBroker); + List freeIps = new ArrayList<>(); + + String subnetCidr = ItmUtils.getSubnetCidrAsString(schema.getSubnet()); + String gatewayIp = handleGatewayIp(schema.getGatewayIp()); + + for (BigInteger dpnId : lstDpnIdsToBeDeleted) { + VtepsKey vtepkey = new VtepsKey(dpnId, schema.getPortName()); + + InstanceIdentifier vpath = InstanceIdentifier.builder(TransportZones.class) + .child(TransportZone.class, new TransportZoneKey(schema.getTransportZoneName())) + .child(Subnets.class, new SubnetsKey(schema.getSubnet())).child(Vteps.class, vtepkey).build(); + + Vteps vtep = null; + Optional vtepOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, vpath, dataBroker); + if (vtepOptional.isPresent()) { + vtep = vtepOptional.get(); + } else { + LOG.warn("VTEP doesn't exist for DPN [{}] and port [{}].", dpnId, schema.getPortName()); + continue; + } + + IpAddress ipAddress = vtep.getIpAddress(); + tepCommandHelper.deleteVtep(dpnId, vtep.getPortname(), schema.getVlanId(), + String.valueOf(ipAddress.getValue()), subnetCidr, gatewayIp, schema.getTransportZoneName()); + + freeIps.add(ipAddress); + } + LOG.debug( "Delete OnCommit in NewlyAddedDpns"); + tepCommandHelper.deleteOnCommit(); + deAllocateIpAddresses(freeIps, subnetCidr); + } + + /** + * Calculate available IPs from the subnet mask specified in the schema. + * Pushes the available and allocated IP address to config DS. + * + * @param schema + * the schema + */ + private VtepIpPool processAvailableIps(final VtepConfigSchema schema) { + String subnetCidr = ItmUtils.getSubnetCidrAsString(schema.getSubnet()); + SubnetUtils subnetUtils = new SubnetUtils(subnetCidr); + + List availableIps = calculateAvailableIps(subnetUtils, schema.getExcludeIpFilter(), + schema.getGatewayIp()); + VtepIpPool vtepIpPool = new VtepIpPoolBuilder().setSubnetCidr(subnetCidr).setAvailableIpaddress(availableIps) + .setAllocatedIpaddress(new ArrayList()).build(); + + MDSALUtil.syncWrite(this.dataBroker, LogicalDatastoreType.CONFIGURATION, + ItmUtils.getVtepIpPoolIdentifier(subnetCidr), vtepIpPool); + LOG.info("Vtep IP Pool with key:{} added to config DS", subnetCidr); + return vtepIpPool; + } + + /** + * Gets the vtep ip pool. + * + * @param subnetCidr + * the subnet cidr + * @return the vtep ip pool + */ + private VtepIpPool getVtepIpPool(final String subnetCidr) { + Optional vtepIpPool = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, + ItmUtils.getVtepIpPoolIdentifier(subnetCidr), this.dataBroker); + if (vtepIpPool.isPresent()) { + return vtepIpPool.get(); + } + return null; + } + + /** + * Delete vtep ip pool. + * + * @param subnetCidr + * the subnet cidr + */ + private void deleteVtepIpPool(final String subnetCidr) { + if (StringUtils.isNotBlank(subnetCidr)) { + MDSALUtil.syncDelete(this.dataBroker, LogicalDatastoreType.CONFIGURATION, + ItmUtils.getVtepIpPoolIdentifier(subnetCidr)); + LOG.debug("Deleted Vtep IP Pool with key:{}", subnetCidr); + } + } + + /** + * Gets the an available ip. + * + * @param availableIps + * + * @return the an available ip + */ + private IpAddress getAnAvailableIP(List availableIps) { + // TODO: Sort IP Addresses, get the least value + IpAddress ipAddress = null; + if (availableIps != null && !availableIps.isEmpty()) { + ipAddress = availableIps.remove(0); + } + return ipAddress; + } + + /** + * Allocate ip addresses. + * + * @param allocatedIps + * the allocated ips + * @param vtepIpPool + * the vtep ip pool + * @param subnetCidr + * the subnet cidr + */ + private void allocateIpAddresses(List allocatedIps, VtepIpPool vtepIpPool, String subnetCidr) { + if (allocatedIps != null && !allocatedIps.isEmpty() && vtepIpPool != null) { + // Remove from the available IP address list and add to allocated IP + // address list. + VtepIpPoolBuilder builder = new VtepIpPoolBuilder(vtepIpPool); + if (builder.getAvailableIpaddress() != null) { + builder.getAvailableIpaddress().removeAll(allocatedIps); + } + if (builder.getAllocatedIpaddress() == null) { + builder.setAllocatedIpaddress(allocatedIps); + } else { + builder.getAllocatedIpaddress().addAll(allocatedIps); + } + + MDSALUtil.syncWrite(this.dataBroker, LogicalDatastoreType.CONFIGURATION, + ItmUtils.getVtepIpPoolIdentifier(subnetCidr), builder.build()); + } + } + + /** + * De-allocate ip addresses. + * + * @param freeIps + * the free ips + * @param subnetCidr + * the subnet cidr + */ + private void deAllocateIpAddresses(List freeIps, String subnetCidr) { + VtepIpPool vtepIpPool = getVtepIpPool(subnetCidr); + if (freeIps != null && !freeIps.isEmpty() && vtepIpPool != null) { + // Remove from the allocated IP address list and add to available IP + // address list. + VtepIpPoolBuilder builder = new VtepIpPoolBuilder(vtepIpPool); + if (builder.getAllocatedIpaddress() != null) { + builder.getAllocatedIpaddress().removeAll(freeIps); + } + if (builder.getAvailableIpaddress() == null) { + builder.setAvailableIpaddress(freeIps); + } else { + builder.getAvailableIpaddress().addAll(freeIps); + } + + MDSALUtil.syncWrite(this.dataBroker, LogicalDatastoreType.CONFIGURATION, + ItmUtils.getVtepIpPoolIdentifier(subnetCidr), builder.build()); + LOG.debug("Vtep IP Pool with key:{} updated to config DS", subnetCidr); + } + } + + /** + * Calculate available ips. + * + * @param subnetCidr + * the subnet cidr + * @param excludeIpFilter + * the exclude ip filter + * @param gatewayIp + * the gateway IP + * @return the list + */ + private List calculateAvailableIps(SubnetUtils subnetUtils, String excludeIpFilter, + IpAddress gatewayIp) { + List lstAvailableIps = new ArrayList<>(); + SubnetInfo subnetInfo = subnetUtils.getInfo(); + String[] arrIpAddresses = subnetInfo.getAllAddresses(); + + for (String ipAddress : arrIpAddresses) { + lstAvailableIps.add(new IpAddress(ipAddress.toCharArray())); + } + lstAvailableIps.remove(gatewayIp); + lstAvailableIps.removeAll(ItmUtils.getExcludeIpAddresses(excludeIpFilter, subnetInfo)); + + return lstAvailableIps; + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/rpc/ItmManagerRpcService.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/rpc/ItmManagerRpcService.java index 32b4f2a5..a373472b 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/rpc/ItmManagerRpcService.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/rpc/ItmManagerRpcService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015, 2016 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, @@ -12,20 +12,28 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.Future; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.vpnservice.mdsalutil.*; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZoneKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.Subnets; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.SubnetsKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVteps; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVtepsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVtepsKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; import org.opendaylight.vpnservice.itm.confighelpers.ItmExternalTunnelAddWorker; import org.opendaylight.vpnservice.itm.confighelpers.ItmExternalTunnelDeleteWorker; import org.opendaylight.vpnservice.itm.globals.ITMConstants; import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; import org.opendaylight.vpnservice.itm.impl.ItmUtils; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; -import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.ExternalTunnelList; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo; @@ -34,85 +42,68 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnelKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.AddExternalTunnelEndpointInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.BuildExternalTunnelFromDpnsInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.CreateTerminatingServiceActionsInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameOutput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameOutputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetInternalOrExternalInterfaceNameInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetInternalOrExternalInterfaceNameOutput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetInternalOrExternalInterfaceNameOutputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameOutput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameOutputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.RemoveExternalTunnelEndpointInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.RemoveExternalTunnelFromDpnsInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.RemoveTerminatingServiceActionsInput; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import com.google.common.util.concurrent.FutureCallback; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.SettableFuture; - import org.opendaylight.yangtools.yang.common.RpcError; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import com.google.common.base.Optional; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.SettableFuture; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; public class ItmManagerRpcService implements ItmRpcService { - private static final Logger LOG = LoggerFactory.getLogger(ItmManagerRpcService.class); - DataBroker dataBroker; - private IMdsalApiManager mdsalManager; + private static final Logger LOG = LoggerFactory.getLogger(ItmManagerRpcService.class); + DataBroker dataBroker; + private IMdsalApiManager mdsalManager; public void setMdsalManager(IMdsalApiManager mdsalManager) { - this.mdsalManager = mdsalManager; + this.mdsalManager = mdsalManager; + } + + IdManagerService idManagerService; + + public ItmManagerRpcService(DataBroker dataBroker, IdManagerService idManagerService) { + this.dataBroker = dataBroker; + this.idManagerService = idManagerService; } - IdManagerService idManagerService; + @Override + public Future> getTunnelInterfaceName(GetTunnelInterfaceNameInput input) { + RpcResultBuilder resultBld = null; + BigInteger sourceDpn = input.getSourceDpid() ; + BigInteger destinationDpn = input.getDestinationDpid() ; + InstanceIdentifier path = InstanceIdentifier.create( + TunnelList.class) + .child(InternalTunnel.class, new InternalTunnelKey( destinationDpn,sourceDpn)); + + Optional tnl = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker); - public ItmManagerRpcService(DataBroker dataBroker, IdManagerService idManagerService) { - this.dataBroker = dataBroker; - this.idManagerService = idManagerService; + if( tnl != null && tnl.isPresent()) + { + InternalTunnel tunnel = tnl.get(); + GetTunnelInterfaceNameOutputBuilder output = new GetTunnelInterfaceNameOutputBuilder() ; + output.setInterfaceName(tunnel.getTunnelInterfaceName()) ; + resultBld = RpcResultBuilder.success(); + resultBld.withResult(output.build()) ; + }else { + resultBld = RpcResultBuilder.failed(); } - @Override - public Future> getTunnelInterfaceName(GetTunnelInterfaceNameInput input) { - RpcResultBuilder resultBld = null; - BigInteger sourceDpn = input.getSourceDpid() ; - BigInteger destinationDpn = input.getDestinationDpid() ; - InstanceIdentifier path = InstanceIdentifier.create( - TunnelList.class) - .child(InternalTunnel.class, new InternalTunnelKey(sourceDpn,destinationDpn)); - - Optional tnl = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker); - - if( tnl != null && tnl.isPresent()) - { - InternalTunnel tunnel = tnl.get(); - GetTunnelInterfaceNameOutputBuilder output = new GetTunnelInterfaceNameOutputBuilder() ; - output.setInterfaceName(tunnel.getTunnelInterfaceName()) ; - resultBld = RpcResultBuilder.success(); - resultBld.withResult(output.build()) ; - }else { - resultBld = RpcResultBuilder.failed(); - } - - return Futures.immediateFuture(resultBld.build()); - } + return Futures.immediateFuture(resultBld.build()); + } @Override public Future> removeExternalTunnelEndpoint( RemoveExternalTunnelEndpointInput input) { - //Ignore the Futures for now + //Ignore the Futures for now final SettableFuture> result = SettableFuture.create(); List meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker) ; ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, idManagerService,meshedDpnList , input.getDestinationIp(), input.getTunnelType()); @@ -175,21 +166,21 @@ public class ItmManagerRpcService implements ItmRpcService { GetExternalTunnelInterfaceNameInput input) { final SettableFuture> result = SettableFuture.create() ; RpcResultBuilder resultBld; - BigInteger sourceDpn = input.getSourceDpid() ; - IpAddress destinationIp = input.getDestinationIp() ; + String sourceNode = input.getSourceNode(); + String dstNode = input.getDestinationNode(); InstanceIdentifier path = InstanceIdentifier.create( ExternalTunnelList.class) - .child(ExternalTunnel.class, new ExternalTunnelKey(destinationIp, sourceDpn)); + .child(ExternalTunnel.class, new ExternalTunnelKey(dstNode, sourceNode)); Optional ext = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker); if( ext != null && ext.isPresent()) { - ExternalTunnel exTunnel = ext.get(); - GetExternalTunnelInterfaceNameOutputBuilder output = new GetExternalTunnelInterfaceNameOutputBuilder() ; - output.setInterfaceName(exTunnel.getTunnelInterfaceName()) ; - resultBld = RpcResultBuilder.success(); - resultBld.withResult(output.build()) ; + ExternalTunnel exTunnel = ext.get(); + GetExternalTunnelInterfaceNameOutputBuilder output = new GetExternalTunnelInterfaceNameOutputBuilder() ; + output.setInterfaceName(exTunnel.getTunnelInterfaceName()) ; + resultBld = RpcResultBuilder.success(); + resultBld.withResult(output.build()) ; }else { resultBld = RpcResultBuilder.failed(); } @@ -199,46 +190,46 @@ public class ItmManagerRpcService implements ItmRpcService { @Override public Future> createTerminatingServiceActions(final CreateTerminatingServiceActionsInput input) { - LOG.info("create terminatingServiceAction on DpnId = {} for service id {} and instructions {}", input.getDpnId() , input.getServiceId(), input.getInstruction()); - final SettableFuture> result = SettableFuture.create(); - int serviceId = input.getServiceId() ; - List mkMatches = new ArrayList(); - byte[] vxLANHeader = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - // Flags Byte - byte Flags = (byte) 0x08; - vxLANHeader[0] = Flags; - - // Extract the serviceId details and imprint on the VxLAN Header - vxLANHeader[4] = (byte) (serviceId >> 16); - vxLANHeader[5] = (byte) (serviceId >> 8); - vxLANHeader[6] = (byte) (serviceId >> 0); - - // Matching metadata - mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] { - new BigInteger(1, vxLANHeader), - MetaDataUtil.METADA_MASK_VALID_TUNNEL_ID_BIT_AND_TUNNEL_ID })); - - Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE, - getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,serviceId), 5, String.format("%s:%d","ITM Flow Entry ",serviceId), - 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(serviceId)),mkMatches, input.getInstruction()); - - ListenableFuture installFlowResult = mdsalManager.installFlow(input.getDpnId(), terminatingServiceTableFlow); - Futures.addCallback(installFlowResult, new FutureCallback(){ - - @Override - public void onSuccess(Void aVoid) { - result.set(RpcResultBuilder.success().build()); - } - - @Override - public void onFailure(Throwable error) { - String msg = String.format("Unable to install terminating service flow for %s", input.getDpnId()); - LOG.error("create terminating service actions failed. {}. {}", msg, error); - result.set(RpcResultBuilder.failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build()); - } - }); - result.set(RpcResultBuilder.success().build()); - return result; + LOG.info("create terminatingServiceAction on DpnId = {} for service id {} and instructions {}", input.getDpnId() , input.getServiceId(), input.getInstruction()); + final SettableFuture> result = SettableFuture.create(); + int serviceId = input.getServiceId() ; + List mkMatches = new ArrayList(); + byte[] vxLANHeader = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + // Flags Byte + byte Flags = (byte) 0x08; + vxLANHeader[0] = Flags; + + // Extract the serviceId details and imprint on the VxLAN Header + vxLANHeader[4] = (byte) (serviceId >> 16); + vxLANHeader[5] = (byte) (serviceId >> 8); + vxLANHeader[6] = (byte) (serviceId >> 0); + + // Matching metadata + mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] { + new BigInteger(1, vxLANHeader), + MetaDataUtil.METADA_MASK_VALID_TUNNEL_ID_BIT_AND_TUNNEL_ID })); + + Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE, + getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,serviceId), 5, String.format("%s:%d","ITM Flow Entry ",serviceId), + 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(serviceId)),mkMatches, input.getInstruction()); + + ListenableFuture installFlowResult = mdsalManager.installFlow(input.getDpnId(), terminatingServiceTableFlow); + Futures.addCallback(installFlowResult, new FutureCallback(){ + + @Override + public void onSuccess(Void aVoid) { + result.set(RpcResultBuilder.success().build()); + } + + @Override + public void onFailure(Throwable error) { + String msg = String.format("Unable to install terminating service flow for %s", input.getDpnId()); + LOG.error("create terminating service actions failed. {}. {}", msg, error); + result.set(RpcResultBuilder.failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build()); + } + }); + // result.set(RpcResultBuilder.success().build()); + return result; } @Override @@ -264,11 +255,12 @@ public class ItmManagerRpcService implements ItmRpcService { result.set(RpcResultBuilder.failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build()); } }); - result.set(RpcResultBuilder.success().build()); + //result.set(RpcResultBuilder.success().build()); - return result ; + return result ; } + public List getTunnelMatchesForServiceId(int serviceId) { List mkMatches = new ArrayList(); byte[] vxLANHeader = new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; @@ -284,7 +276,7 @@ public class ItmManagerRpcService implements ItmRpcService { // Matching metadata mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[]{ - BigInteger.valueOf(serviceId)})); + BigInteger.valueOf(serviceId)})); return mkMatches; } @@ -295,49 +287,161 @@ public class ItmManagerRpcService implements ItmRpcService { @Override public Future> getInternalOrExternalInterfaceName( - GetInternalOrExternalInterfaceNameInput input) { - RpcResultBuilder resultBld = RpcResultBuilder.failed(); - BigInteger srcDpn = input.getSourceDpid() ; - IpAddress dstIp = input.getDestinationIp() ; - InstanceIdentifier path1 = InstanceIdentifier.create( - ExternalTunnelList.class) - .child(ExternalTunnel.class, new ExternalTunnelKey(dstIp, srcDpn)); - - Optional ext = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path1, dataBroker); - - if( ext != null && ext.isPresent()) - { - ExternalTunnel extTunnel = ext.get(); - GetInternalOrExternalInterfaceNameOutputBuilder output = new GetInternalOrExternalInterfaceNameOutputBuilder().setInterfaceName(extTunnel.getTunnelInterfaceName() ); - resultBld = RpcResultBuilder.success(); - resultBld.withResult(output.build()) ; - } else { - List meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker); - // Look for external tunnels if not look for internal tunnel - for (DPNTEPsInfo teps : meshedDpnList) { - TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0); - if (dstIp.equals(firstEndPt.getIpAddress())) { - InstanceIdentifier path = InstanceIdentifier.create( - TunnelList.class) - .child(InternalTunnel.class, new InternalTunnelKey(srcDpn, teps.getDPNID())); - - Optional - tnl = - ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker); - if (tnl != null && tnl.isPresent()) { - InternalTunnel tunnel = tnl.get(); - GetInternalOrExternalInterfaceNameOutputBuilder - output = - new GetInternalOrExternalInterfaceNameOutputBuilder() - .setInterfaceName(tunnel.getTunnelInterfaceName()); - resultBld = RpcResultBuilder.success(); - resultBld.withResult(output.build()); - break; + GetInternalOrExternalInterfaceNameInput input) { + RpcResultBuilder resultBld = RpcResultBuilder.failed(); + BigInteger srcDpn = input.getSourceDpid() ; + String srcNode = srcDpn.toString(); + IpAddress dstIp = input.getDestinationIp() ; + InstanceIdentifier path1 = InstanceIdentifier.create( + ExternalTunnelList.class) + .child(ExternalTunnel.class, new ExternalTunnelKey(String.valueOf(dstIp), srcDpn.toString())); + + Optional ext = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path1, dataBroker); + + if( ext != null && ext.isPresent()) + { + ExternalTunnel extTunnel = ext.get(); + GetInternalOrExternalInterfaceNameOutputBuilder output = new GetInternalOrExternalInterfaceNameOutputBuilder().setInterfaceName(extTunnel.getTunnelInterfaceName() ); + resultBld = RpcResultBuilder.success(); + resultBld.withResult(output.build()) ; + } else { + List meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker); + // Look for external tunnels if not look for internal tunnel + for (DPNTEPsInfo teps : meshedDpnList) { + TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0); + if (dstIp.equals(firstEndPt.getIpAddress())) { + InstanceIdentifier path = InstanceIdentifier.create( + TunnelList.class) + .child(InternalTunnel.class, new InternalTunnelKey(teps.getDPNID(),srcDpn)); + + Optional + tnl = + ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker); + if (tnl != null && tnl.isPresent()) { + InternalTunnel tunnel = tnl.get(); + GetInternalOrExternalInterfaceNameOutputBuilder + output = + new GetInternalOrExternalInterfaceNameOutputBuilder() + .setInterfaceName(tunnel.getTunnelInterfaceName()); + resultBld = RpcResultBuilder.success(); + resultBld.withResult(output.build()); + break; + } + } + } + } + return Futures.immediateFuture(resultBld.build()); + } + + @Override + public Future> deleteL2GwDevice(DeleteL2GwDeviceInput input) { + final SettableFuture> result = SettableFuture.create(); + try { + final IpAddress hwIp = input.getIpAddress(); + final String node_id = input.getNodeId(); + InstanceIdentifier containerPath = InstanceIdentifier.create(TransportZones.class); + Optional tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, containerPath, dataBroker); + if (tZonesOptional.isPresent()) { + TransportZones tZones = tZonesOptional.get(); + if (tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) { + LOG.error("No teps configured"); + result.set(RpcResultBuilder.failed().withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build()); + return result; + } + String transportZone = tZones.getTransportZone().get(0).getZoneName(); + if (tZones.getTransportZone().get(0).getSubnets() == null || tZones.getTransportZone().get(0).getSubnets().isEmpty()) { + result.set(RpcResultBuilder.failed().withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build()); + return result; + } + SubnetsKey subnetsKey = tZones.getTransportZone().get(0).getSubnets().get(0).getKey(); + DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, node_id); + InstanceIdentifier path = + InstanceIdentifier.builder(TransportZones.class) + .child(TransportZone.class, new TransportZoneKey(transportZone)) + .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey).build(); + WriteTransaction t = dataBroker.newWriteOnlyTransaction(); + //TO DO: add retry if it fails + t.delete(LogicalDatastoreType.CONFIGURATION, path); + + ListenableFuture futureCheck = t.submit(); + Futures.addCallback(futureCheck, new FutureCallback() { + + @Override + public void onSuccess(Void aVoid) { + result.set(RpcResultBuilder.success().build()); + } + + @Override + public void onFailure(Throwable error) { + String msg = String.format("Unable to write HwVtep {} to datastore", node_id); + LOG.error("Unable to write HwVtep {}, {} to datastore", node_id , hwIp); + result.set(RpcResultBuilder.failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build()); + } + }); + } + return result; + } catch (Exception e) { + RpcResultBuilder resultBuilder = RpcResultBuilder.failed(). + withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e); + return Futures.immediateFuture(resultBuilder.build()); + } + } + + @Override + public Future> addL2GwDevice(AddL2GwDeviceInput input) { + + final SettableFuture> result = SettableFuture.create(); + try { + final IpAddress hwIp = input.getIpAddress(); + final String node_id = input.getNodeId(); + InstanceIdentifier containerPath = InstanceIdentifier.create(TransportZones.class); + Optional tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, containerPath, dataBroker); + if (tZonesOptional.isPresent()) { + TransportZones tZones = tZonesOptional.get(); + if (tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) { + LOG.error("No teps configured"); + result.set(RpcResultBuilder.failed().withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build()); + return result; + } + String transportZone = tZones.getTransportZone().get(0).getZoneName(); + if (tZones.getTransportZone().get(0).getSubnets() == null || tZones.getTransportZone().get(0).getSubnets().isEmpty()) { + result.set(RpcResultBuilder.failed().withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build()); + return result; + } + SubnetsKey subnetsKey = tZones.getTransportZone().get(0).getSubnets().get(0).getKey(); + DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, node_id); + InstanceIdentifier path = + InstanceIdentifier.builder(TransportZones.class) + .child(TransportZone.class, new TransportZoneKey(transportZone)) + .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey).build(); + DeviceVteps deviceVtep = new DeviceVtepsBuilder().setKey(deviceVtepKey).setIpAddress(hwIp).setNodeId( + node_id).setTopologyId(input.getTopologyId()).build(); + WriteTransaction t = dataBroker.newWriteOnlyTransaction(); + //TO DO: add retry if it fails + t.put(LogicalDatastoreType.CONFIGURATION, path, deviceVtep, true); + + ListenableFuture futureCheck = t.submit(); + Futures.addCallback(futureCheck, new FutureCallback() { + + @Override + public void onSuccess(Void aVoid) { + result.set(RpcResultBuilder.success().build()); + } + + @Override + public void onFailure(Throwable error) { + String msg = String.format("Unable to write HwVtep {} to datastore", node_id); + LOG.error("Unable to write HwVtep {}, {} to datastore", node_id , hwIp); + result.set(RpcResultBuilder.failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build()); + } + }); } - } + return result; + } catch (Exception e) { + RpcResultBuilder resultBuilder = RpcResultBuilder.failed(). + withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e); + return Futures.immediateFuture(resultBuilder.build()); } - } - return Futures.immediateFuture(resultBld.build()); } } diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/snd/ITMStatusMonitor.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/snd/ITMStatusMonitor.java new file mode 100644 index 00000000..03a4b87e --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/snd/ITMStatusMonitor.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016 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.itm.snd; + +import java.lang.management.ManagementFactory; +import javax.management.InstanceAlreadyExistsException; +import javax.management.MBeanRegistrationException; +import javax.management.MBeanServer; +import javax.management.MalformedObjectNameException; +import javax.management.NotCompliantMBeanException; +import javax.management.ObjectName; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ITMStatusMonitor implements ITMStatusMonitorMBean { + + + private String serviceStatus; + private static ITMStatusMonitor itmStatusMonitor = new ITMStatusMonitor(); + private static final String JMX_ITM_OBJ_NAME = "com.ericsson.sdncp.services.status:type=SvcItmService"; + private static final Logger log = LoggerFactory.getLogger(ITMStatusMonitor.class); + + private ITMStatusMonitor () { + } + + public void registerMbean() { + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + try { + ObjectName objName = new ObjectName(JMX_ITM_OBJ_NAME); + mbs.registerMBean(itmStatusMonitor, objName); + log.info("itm MXBean registration SUCCESSFUL!!! {}", JMX_ITM_OBJ_NAME); + } catch (InstanceAlreadyExistsException iaeEx) { + log.error("itm MXBean registration FAILED with InstanceAlreadyExistsException", iaeEx); + } catch (MBeanRegistrationException mbrEx) { + log.error("itm MXBean registration FAILED with MBeanRegistrationException", mbrEx); + } catch (NotCompliantMBeanException ncmbEx) { + log.error("itm MXBean registration FAILED with NotCompliantMBeanException", ncmbEx); + } catch (MalformedObjectNameException monEx) { + log.error("itm MXBean registration failed with MalformedObjectNameException", monEx); + } + } + + public static ITMStatusMonitor getInstance() { + return itmStatusMonitor; + } + + @Override + public String acquireServiceStatus() { + return serviceStatus; + } + + public void reportStatus (String serviceStatus) { + this.serviceStatus = serviceStatus; + } + + +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/snd/ITMStatusMonitorMBean.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/snd/ITMStatusMonitorMBean.java new file mode 100644 index 00000000..e1557af1 --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/snd/ITMStatusMonitorMBean.java @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2016 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.itm.snd; + +public interface ITMStatusMonitorMBean { + + public String acquireServiceStatus(); + +} diff --git a/mdsalutil/mdsalutil-api/pom.xml b/mdsalutil/mdsalutil-api/pom.xml index d3f560fd..f42e3e9a 100644 --- a/mdsalutil/mdsalutil-api/pom.xml +++ b/mdsalutil/mdsalutil-api/pom.xml @@ -41,6 +41,11 @@ openflowjava-extension-nicira ${openflowplugin.version} + + org.opendaylight.ovsdb + hwvtepsouthbound-api + ${vpns.ovsdb.version} + diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/ActionType.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/ActionType.java index 8678917f..985806a1 100755 --- a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/ActionType.java +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/ActionType.java @@ -47,6 +47,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types. import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropAction; @@ -263,7 +264,7 @@ public enum ActionType { } }, - set_destination_port_field { + set_udp_destination_port { @Override public Action buildAction(ActionInfo actionInfo) { @@ -280,7 +281,7 @@ public enum ActionType { } }, - set_source_port_field { + set_udp_source_port { @Override public Action buildAction(ActionInfo actionInfo) { @@ -296,6 +297,40 @@ public enum ActionType { } + }, + set_tcp_destination_port { + + @Override + public Action buildAction(ActionInfo actionInfo) { + String[] actionValues = actionInfo.getActionValues(); + Integer portNumber = new Integer(actionValues[0]); + + return new ActionBuilder().setAction( + new SetFieldCaseBuilder().setSetField( + new SetFieldBuilder().setLayer4Match( + new TcpMatchBuilder().setTcpDestinationPort( + new PortNumber(portNumber)).build()) + .build()).build()).setKey(new ActionKey(actionInfo.getActionKey())).build(); + + } + + }, + set_tcp_source_port { + + @Override + public Action buildAction(ActionInfo actionInfo) { + String[] actionValues = actionInfo.getActionValues(); + Integer portNumber = new Integer(actionValues[0]); + + return new ActionBuilder().setAction( + new SetFieldCaseBuilder().setSetField( + new SetFieldBuilder().setLayer4Match( + new TcpMatchBuilder().setTcpSourcePort( + new PortNumber(portNumber)).build()) + .build()).build()).setKey(new ActionKey(actionInfo.getActionKey())).build(); + + } + }, set_source_ip { @@ -312,7 +347,7 @@ public enum ActionType { new SetFieldCaseBuilder().setSetField( new SetFieldBuilder().setLayer3Match( new Ipv4MatchBuilder().setIpv4Source( - new Ipv4Prefix(sourceIp.getHostAddress())).build()). + new Ipv4Prefix(sourceIp.getHostAddress() + "/" + actionValues[1])).build()). build()).build()).setKey(new ActionKey(actionInfo.getActionKey())).build(); } @@ -333,7 +368,7 @@ public enum ActionType { new SetFieldCaseBuilder().setSetField( new SetFieldBuilder().setLayer3Match( new Ipv4MatchBuilder().setIpv4Destination( - new Ipv4Prefix(sourceIp.getHostAddress())).build()). + new Ipv4Prefix(sourceIp.getHostAddress() + "/" + actionValues[1])).build()). build()).build()).setKey(new ActionKey(actionInfo.getActionKey())).build(); } diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java index f31a9675..a6e469d4 100644 --- a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java @@ -22,7 +22,9 @@ import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetFieldBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie; @@ -39,10 +41,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.M import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActions; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTableBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActions; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActionsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadataBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder; @@ -67,21 +73,19 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.No import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TunnelBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder; 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.yangtools.yang.binding.DataObject; -import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; -import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; -import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector; import org.opendaylight.controller.liblldp.HexEncode; + import com.google.common.base.Joiner; import com.google.common.base.Optional; import com.google.common.primitives.Bytes; @@ -90,6 +94,8 @@ import com.google.common.util.concurrent.CheckedFuture; public class MDSALUtil { + public enum MdsalOp { CREATION_OP, UPDATE_OP, REMOVAL_OP }; + public static final String NODE_PREFIX = "openflow"; public static final int GROUP_WEIGHT = 0; public static final long WATCH_PORT = 0xffffffffL; @@ -138,6 +144,10 @@ public class MDSALUtil { .setCookie(new FlowCookie(cookie)).build(); } + public static Flow buildFlow(short tableId, String flowId) { + return new FlowBuilder().setTableId(tableId).setId(new FlowId(flowId)).build(); + } + public static Flow buildFlowNew(short tableId, String flowId, int priority, String flowName, int idleTimeOut, int hardTimeOut, BigInteger cookie, List listMatchInfo, List listInstructionInfo) { return MDSALUtil.buildFlowNew(tableId, flowId, priority, flowName, idleTimeOut, hardTimeOut, cookie, @@ -195,6 +205,13 @@ public class MDSALUtil { .setIngress(ingress).setEgress(ingress).build(); } + public static Action retrieveSetTunnelIdAction(BigInteger tunnelId, int actionKey) { + return new ActionBuilder().setAction( + new SetFieldCaseBuilder().setSetField(new SetFieldBuilder().setTunnel(new TunnelBuilder() + .setTunnelId(tunnelId).build()).build()) + .build()).setKey(new ActionKey(actionKey)).build(); + } + public static List buildActions(List actions) { List actionsList = new ArrayList(); for (ActionInfo actionInfo : actions) { @@ -251,7 +268,7 @@ public class MDSALUtil { return EMPTY_Buckets; } - protected static Instructions buildInstructions(List listInstructionInfo) { + public static Instructions buildInstructions(List listInstructionInfo) { if (listInstructionInfo != null) { List instructions = new ArrayList(); int instructionKey = 0; @@ -345,7 +362,7 @@ public class MDSALUtil { public static long getDpnIdFromPortName(NodeConnectorId nodeConnectorId) { String ofPortName = nodeConnectorId.getValue(); - return Long.parseLong(ofPortName.substring(ofPortName.indexOf(":")+1, + return Long.parseLong(ofPortName.substring(ofPortName.indexOf(":")+1, ofPortName.lastIndexOf(":"))); } @@ -366,6 +383,14 @@ public class MDSALUtil { .setKey(new ActionKey(actionKey)).build(); List listAction = new ArrayList (); listAction.add(popVlanAction); + return buildApplyActionsInstruction(listAction, instructionKey); + } + + public static Instruction buildApplyActionsInstruction(List actions) { + return buildApplyActionsInstruction(actions, 0); + } + + public static Instruction buildApplyActionsInstruction(List listAction, int instructionKey) { ApplyActions applyActions = new ApplyActionsBuilder().setAction(listAction).build(); ApplyActionsCase applyActionsCase = new ApplyActionsCaseBuilder().setApplyActions(applyActions).build(); InstructionBuilder instructionBuilder = new InstructionBuilder(); @@ -375,6 +400,29 @@ public class MDSALUtil { return instructionBuilder.build(); } + public static List buildInstructionsDrop() { + return buildInstructionsDrop(0); + } + + public static List buildInstructionsDrop(int instructionKey) { + List mkInstructions = new ArrayList(); + List actionsInfos = new ArrayList (); + actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[]{}).buildAction()); + mkInstructions.add(getWriteActionsInstruction(actionsInfos, instructionKey)); + return mkInstructions; + } + + + public static Instruction getWriteActionsInstruction(List listAction, int instructionKey) { + WriteActions writeActions = new WriteActionsBuilder().setAction(listAction).build(); + WriteActionsCase writeActionsCase = new WriteActionsCaseBuilder().setWriteActions(writeActions).build(); + InstructionBuilder instructionBuilder = new InstructionBuilder(); + + instructionBuilder.setInstruction(writeActionsCase); + instructionBuilder.setKey(new InstructionKey(instructionKey)); + return instructionBuilder.build(); + } + public static Action buildAction(int actionKey, int instruction) { return new ActionBuilder().setAction( new PopVlanActionCaseBuilder().setPopVlanAction(new PopVlanActionBuilder().build()).build()) @@ -529,3 +577,4 @@ public class MDSALUtil { } } + diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MatchFieldType.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MatchFieldType.java index 7e4cfa29..24cdb3da 100755 --- a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MatchFieldType.java +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MatchFieldType.java @@ -251,6 +251,64 @@ public enum MatchFieldType { } } }, + + ipv4_destination { + @Override + protected Class getMatchType() { + return Ipv4Dst.class; + } + + @Override + public void createInnerMatchBuilder(MatchInfo matchInfo, Map, Object> mapMatchBuilder) { + Ipv4MatchBuilder ipv4MatchBuilder = (Ipv4MatchBuilder) mapMatchBuilder.get(Ipv4MatchBuilder.class); + + if (ipv4MatchBuilder == null) { + ipv4MatchBuilder = new Ipv4MatchBuilder(); + mapMatchBuilder.put(Ipv4MatchBuilder.class, ipv4MatchBuilder); + } + + String[] prefix = matchInfo.getStringMatchValues(); + ipv4MatchBuilder.setIpv4Destination(new Ipv4Prefix(prefix[0] + "/" + prefix[1])).build(); + } + + @Override + public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map, Object> mapMatchBuilder) { + Ipv4MatchBuilder ipv4MatchBuilder = (Ipv4MatchBuilder) mapMatchBuilder.remove(Ipv4MatchBuilder.class); + + if (ipv4MatchBuilder != null) { + matchBuilderInOut.setLayer3Match(ipv4MatchBuilder.build()); + } + } + }, + + ipv4_source { + @Override + protected Class getMatchType() { + return Ipv4Src.class; + } + + @Override + public void createInnerMatchBuilder(MatchInfo matchInfo, Map, Object> mapMatchBuilder) { + Ipv4MatchBuilder ipv4MatchBuilder = (Ipv4MatchBuilder) mapMatchBuilder.get(Ipv4MatchBuilder.class); + + if (ipv4MatchBuilder == null) { + ipv4MatchBuilder = new Ipv4MatchBuilder(); + mapMatchBuilder.put(Ipv4MatchBuilder.class, ipv4MatchBuilder); + } + + String[] prefix = matchInfo.getStringMatchValues(); + ipv4MatchBuilder.setIpv4Source(new Ipv4Prefix(prefix[0] + "/" + prefix[1])).build(); + } + + @Override + public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map, Object> mapMatchBuilder) { + Ipv4MatchBuilder ipv4MatchBuilder = (Ipv4MatchBuilder) mapMatchBuilder.remove(Ipv4MatchBuilder.class); + + if (ipv4MatchBuilder != null) { + matchBuilderInOut.setLayer3Match(ipv4MatchBuilder.build()); + } + } + }, arp_op { @Override diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MetaDataUtil.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MetaDataUtil.java index 568ad4f4..06f794bd 100644 --- a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MetaDataUtil.java +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MetaDataUtil.java @@ -10,14 +10,16 @@ package org.opendaylight.vpnservice.mdsalutil; import java.math.BigInteger; public class MetaDataUtil { - public static final BigInteger METADATA_MASK_VRFID = new BigInteger("00000000FFFFFFFF", 16); - public static final BigInteger METADATA_MASK_LPORT_TAG = new BigInteger("1FFFFF0000000000", 16); - public static final BigInteger METADATA_MASK_SERVICE = new BigInteger("000000FFFF000000", 16); + public static final BigInteger METADATA_MASK_VRFID = new BigInteger("00000000FFFFFFFF", 16); + public static final BigInteger METADATA_MASK_LPORT_TAG = new BigInteger("1FFFFF0000000000", 16); + public static final BigInteger METADATA_MASK_SERVICE = new BigInteger("000000FFFF000000", 16); public static final BigInteger METADATA_MASK_SERVICE_INDEX = new BigInteger("E000000000000000", 16); - public static final BigInteger METADATA_MASK_LPORT_WRITE = new BigInteger("00FFFF0000000000", 16); + public static final BigInteger METADATA_MASK_LPORT_WRITE = new BigInteger("00FFFF0000000000", 16); public static final BigInteger METADA_MASK_VALID_TUNNEL_ID_BIT_AND_TUNNEL_ID = new BigInteger("08000000FFFFFF00", 16); - public static final BigInteger METADATA_MASK_LABEL_ITM = new BigInteger("40FFFFFF000000FF", 16); - public static final BigInteger METADA_MASK_TUNNEL_ID = new BigInteger("00000000FFFFFF00", 16); + public static final BigInteger METADATA_MASK_LABEL_ITM = new BigInteger("40FFFFFF000000FF", 16); + public static final BigInteger METADA_MASK_TUNNEL_ID = new BigInteger("00000000FFFFFF00", 16); + public static final BigInteger METADATA_MASK_SERVICE_SH_FLAG = new BigInteger("000000FFFF000001", 16); + public static final BigInteger METADATA_MASK_LPORT_TAG_SH_FLAG = new BigInteger("1FFFFF0000000001", 16); public static BigInteger getMetaDataForLPortDispatcher(int lportTag, short serviceIndex) { return getServiceIndexMetaData(serviceIndex).or(getLportTagMetaData(lportTag)); @@ -66,4 +68,8 @@ public class MetaDataUtil { public static BigInteger getTunnelIdWithValidVniBitAndVniSet(int vni) { return BigInteger.valueOf(0X08).shiftLeft(56).or(BigInteger.valueOf(vni).shiftLeft(8)); } + + public static long getNatRouterIdFromMetadata(BigInteger metadata){ + return (metadata.and(METADATA_MASK_VRFID)).longValue(); + } } diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/NwConstants.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/NwConstants.java index 9133de48..55472e29 100644 --- a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/NwConstants.java +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/NwConstants.java @@ -16,7 +16,7 @@ public class NwConstants { public static final int ETHTYPE_MPLS_UC = 0X8847; public static final int ETHTYPE_PBB = 0X88E7; - + //Protocol Type public static final int IP_PROT_UDP = 17; public static final int IP_PROT_GRE = 47; @@ -28,7 +28,7 @@ public class NwConstants { //Default Port public static final int UDP_DEFAULT_PORT = 4789; - + // Flow Actions public static final int ADD_FLOW = 0; public static final int DEL_FLOW = 1; @@ -44,13 +44,14 @@ public class NwConstants { //Table IDs public static final short L3_FIB_TABLE = 21; public static final short L3_LFIB_TABLE = 20; + public static final short L3_SUBNET_ROUTE_TABLE=22; public static final short L3_PROTOCOL_TABLE = 36; public static final short L3_INTERFACE_TABLE = 80; public static final short LPORT_DISPATCHER_TABLE = 17; public static final short VLAN_INTERFACE_INGRESS_TABLE = 0; public static final short INTERNAL_TUNNEL_TABLE = 36; - public static final short EXTERNAL_TUNNEL_TABLE = 36; + public static final short EXTERNAL_TUNNEL_TABLE = 38; public static final short DHCP_TABLE = 16; - + public static final short DHCP_TABLE_EXTERNAL_TUNNEL = 18; } diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/cache/CacheUtil.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/cache/CacheUtil.java new file mode 100644 index 00000000..0f45a830 --- /dev/null +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/cache/CacheUtil.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016 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.utils.cache; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +public class CacheUtil { + private static final ConcurrentMap> m_mapCache = + new ConcurrentHashMap>(); + + public static ConcurrentMap getCache(String sCacheName) { + return m_mapCache.get(sCacheName); + } + + public static void createCache(String sCacheName) { + if (m_mapCache.get(sCacheName) == null) + m_mapCache.put(sCacheName, new ConcurrentHashMap()); + } + + public static void destroyCache(String sCacheName) { + m_mapCache.remove(sCacheName); + } +} diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/clustering/ClusteringUtils.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/clustering/ClusteringUtils.java new file mode 100644 index 00000000..ec90e2c5 --- /dev/null +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/clustering/ClusteringUtils.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 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.utils.clustering; + +import com.google.common.base.Optional; +import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService; +import org.opendaylight.controller.md.sal.common.api.clustering.Entity; +import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipState; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; + +public class ClusteringUtils { + + public static boolean isNodeEntityOwner(EntityOwnershipService entityOwnershipService, String entityType, + String nodeId) { + Entity entity = new Entity(entityType, nodeId); + Optional entityState = entityOwnershipService.getOwnershipState(entity); + if (entityState.isPresent()) { + return entityState.get().isOwner(); + } + return false; + } + + public static boolean isNodeEntityOwner(EntityOwnershipService entityOwnershipService, String entityType, + YangInstanceIdentifier nodeId) { + Entity entity = new Entity(entityType, nodeId); + Optional entityState = entityOwnershipService.getOwnershipState(entity); + if (entityState.isPresent()) { + return entityState.get().isOwner(); + } + return false; + } +} diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/hwvtep/HwvtepSouthboundConstants.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/hwvtep/HwvtepSouthboundConstants.java new file mode 100644 index 00000000..33eecd9a --- /dev/null +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/hwvtep/HwvtepSouthboundConstants.java @@ -0,0 +1,25 @@ +/* + * 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.utils.hwvtep; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeBase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeVxlanOverIpv4; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId; + +import com.google.common.collect.ImmutableBiMap; + +// TODO (eperefr) Remove this class once it's been added to hwvtep-southbound +public class HwvtepSouthboundConstants { + + public static final TopologyId HWVTEP_TOPOLOGY_ID = new TopologyId("hwvtep:1"); + public static final String HWVTEP_ENTITY_TYPE = "hwvtep"; + public static final Object PSWITCH_URI_PREFIX = "physicalswitch"; + public static final ImmutableBiMap, String> ENCAPS_TYPE_MAP = new ImmutableBiMap.Builder, String>() + .put(EncapsulationTypeVxlanOverIpv4.class, "vxlan_over_ipv4").build(); + +} diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/hwvtep/HwvtepSouthboundUtils.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/hwvtep/HwvtepSouthboundUtils.java new file mode 100644 index 00000000..72bb09d9 --- /dev/null +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/hwvtep/HwvtepSouthboundUtils.java @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2016 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.utils.hwvtep; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +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.opendaylight.l2.types.rev130827.VlanId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeBase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeVxlanOverIpv4; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentationBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalPortAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacsKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitchesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitchesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacsKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSetBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindings; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindingsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindingsKey; +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.NodeId; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableBiMap; + +/** + * TODO: Move these API's to ovsdb's utils.hwvtepsouthbound-utils module. + */ +public class HwvtepSouthboundUtils { + + /** + * Creates the hwvtep topology instance identifier. + * + * @return the instance identifier + */ + public static InstanceIdentifier createHwvtepTopologyInstanceIdentifier() { + return InstanceIdentifier.create(NetworkTopology.class).child(Topology.class, + new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID)); + } + + /** + * Creates the instance identifier. + * + * @param nodeId + * the node id + * @return the instance identifier + */ + public static InstanceIdentifier createInstanceIdentifier(NodeId nodeId) { + return InstanceIdentifier.create(NetworkTopology.class) + .child(Topology.class, new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID)) + .child(Node.class, new NodeKey(nodeId)); + } + + /** + * Creates the logical switches instance identifier. + * + * @param nodeId + * the node id + * @param hwvtepNodeName + * the hwvtep node name + * @return the instance identifier + */ + public static InstanceIdentifier createLogicalSwitchesInstanceIdentifier(NodeId nodeId, + HwvtepNodeName hwvtepNodeName) { + return createInstanceIdentifier(nodeId).augmentation(HwvtepGlobalAugmentation.class) + .child(LogicalSwitches.class, new LogicalSwitchesKey(hwvtepNodeName)); + } + + /** + * Creates the remote ucast macs instance identifier. + * + * @param nodeId + * the node id + * @param mac + * the mac + * @return the instance identifier + */ + public static InstanceIdentifier createRemoteUcastMacsInstanceIdentifier(NodeId nodeId, + String logicalSwitchName, + MacAddress mac) { + InstanceIdentifier logicalSwitch = createLogicalSwitchesInstanceIdentifier(nodeId, + new HwvtepNodeName(logicalSwitchName)); + return createInstanceIdentifier(nodeId).augmentation(HwvtepGlobalAugmentation.class) + .child(RemoteUcastMacs.class, new RemoteUcastMacsKey(new HwvtepLogicalSwitchRef(logicalSwitch), mac)); + } + + /** + * Creates the local ucast macs instance identifier. + * + * @param nodeId + * the node id + * @param mac + * the mac + * @return the instance identifier + */ + public static InstanceIdentifier createLocalUcastMacsInstanceIdentifier(NodeId nodeId, + String logicalSwitchName, + MacAddress mac) { + InstanceIdentifier logicalSwitch = createLogicalSwitchesInstanceIdentifier(nodeId, + new HwvtepNodeName(logicalSwitchName)); + return createInstanceIdentifier(nodeId).augmentation(HwvtepGlobalAugmentation.class).child(LocalUcastMacs.class, + new LocalUcastMacsKey(new HwvtepLogicalSwitchRef(logicalSwitch), mac)); + } + + public static InstanceIdentifier createRemoteMcastMacsInstanceIdentifier(NodeId nodeId, + String logicalSwitchName, + MacAddress mac) { + InstanceIdentifier logicalSwitch = createLogicalSwitchesInstanceIdentifier(nodeId, + new HwvtepNodeName(logicalSwitchName)); + return createInstanceIdentifier(nodeId).augmentation(HwvtepGlobalAugmentation.class).child(RemoteMcastMacs.class, + new RemoteMcastMacsKey(new HwvtepLogicalSwitchRef(logicalSwitch), mac)); + } + + /** + * Creates the remote mcast macs instance identifier. + * + * @param nodeId + * the node id + * @param remoteMcastMacsKey + * the remote mcast macs key + * @return the instance identifier + */ + public static InstanceIdentifier createRemoteMcastMacsInstanceIdentifier(NodeId nodeId, + RemoteMcastMacsKey remoteMcastMacsKey) { + return createInstanceIdentifier(nodeId).augmentation(HwvtepGlobalAugmentation.class) + .child(RemoteMcastMacs.class, remoteMcastMacsKey); + } + + /** + * Creates the physical locator instance identifier. + * + * @param nodeId + * the node id + * @param physicalLocatorAug + * the physical locator aug + * @return the instance identifier + */ + public static InstanceIdentifier createPhysicalLocatorInstanceIdentifier(NodeId nodeId, + HwvtepPhysicalLocatorAugmentation physicalLocatorAug) { + return createInstanceIdentifier(nodeId).child(TerminationPoint.class, + getTerminationPointKey(physicalLocatorAug)); + } + + /** + * Creates the physical port instance identifier. + * + * @param physicalSwitchNodeId + * the physical switch node id + * @param phyPortName + * the phy port name + * @return the instance identifier + */ + public static InstanceIdentifier createPhysicalPortInstanceIdentifier( + NodeId physicalSwitchNodeId, String phyPortName) { + return createInstanceIdentifier(physicalSwitchNodeId) + .child(TerminationPoint.class, new TerminationPointKey(new TpId(phyPortName))) + .augmentation(HwvtepPhysicalPortAugmentation.class); + } + + /** + * Creates the vlan binding instance identifier. + * + * @param physicalSwitchNodeId + * the physical switch node id + * @param phyPortName + * the phy port name + * @param vlanId + * the vlan id + * @return the instance identifier + */ + public static InstanceIdentifier createVlanBindingInstanceIdentifier(NodeId physicalSwitchNodeId, + String phyPortName, Integer vlanId) { + return createPhysicalPortInstanceIdentifier(physicalSwitchNodeId, phyPortName).child(VlanBindings.class, + new VlanBindingsKey(new VlanId(vlanId))); + } + + /** + * Gets the termination point key. + * + * @param phyLocator + * the phy locator + * @return the termination point key + */ + public static TerminationPointKey getTerminationPointKey(HwvtepPhysicalLocatorAugmentation phyLocator) { + TerminationPointKey tpKey = null; + if (phyLocator.getEncapsulationType() != null && phyLocator.getDstIp() != null) { + String encapType = HwvtepSouthboundConstants.ENCAPS_TYPE_MAP.get(phyLocator.getEncapsulationType()); + String tpKeyStr = encapType + ":" + String.valueOf(phyLocator.getDstIp().getValue()); + tpKey = new TerminationPointKey(new TpId(tpKeyStr)); + } + return tpKey; + } + + /** + * Creates the managed node id. + * + * @param nodeId + * the node id + * @param physicalSwitchName + * the physical switch name + * @return the node id + */ + public static NodeId createManagedNodeId(NodeId nodeId, String physicalSwitchName) { + String phySwitchNodeId = nodeId.getValue() + "/" + HwvtepSouthboundConstants.PSWITCH_URI_PREFIX + "/" + + physicalSwitchName; + return new NodeId(phySwitchNodeId); + } + + /** + * Create logical switch. + * + * @param name + * the name + * @param desc + * the desc + * @param tunnelKey + * the tunnel key + * @return the logical switches + */ + public static LogicalSwitches createLogicalSwitch(String name, String desc, String tunnelKey) { + HwvtepNodeName hwvtepName = new HwvtepNodeName(name); + LogicalSwitchesBuilder lsBuilder = new LogicalSwitchesBuilder().setHwvtepNodeDescription(desc) + .setHwvtepNodeName(hwvtepName).setKey(new LogicalSwitchesKey(hwvtepName)).setTunnelKey(tunnelKey); + return lsBuilder.build(); + } + + /** + * Create hwvtep physical locator augmentation. + * + * @param ipAddress + * the ip address + * @return the hwvtep physical locator augmentation + */ + public static HwvtepPhysicalLocatorAugmentation createHwvtepPhysicalLocatorAugmentation(String ipAddress) { + // FIXME: Get encapsulation type dynamically + Class encapTypeClass = createEncapsulationType(StringUtils.EMPTY); + HwvtepPhysicalLocatorAugmentationBuilder phyLocBuilder = new HwvtepPhysicalLocatorAugmentationBuilder() + .setEncapsulationType(encapTypeClass).setDstIp(new IpAddress(ipAddress.toCharArray())); + return phyLocBuilder.build(); + } + + public static Class createEncapsulationType(String type) { + Preconditions.checkNotNull(type); + if (type.isEmpty()) { + return EncapsulationTypeVxlanOverIpv4.class; + } else { + ImmutableBiMap> mapper = HwvtepSouthboundConstants.ENCAPS_TYPE_MAP + .inverse(); + return mapper.get(type); + } + } + + /** + * Create remote ucast mac. + * + * @param nodeId + * the node id + * @param mac + * the mac + * @param ipAddress + * the ip address + * @param logicalSwitchName + * the logical switch name + * @param physicalLocatorAug + * the physical locator aug + * @return the remote ucast macs + */ + public static RemoteUcastMacs createRemoteUcastMac(NodeId nodeId, String mac, IpAddress ipAddress, + String logicalSwitchName, HwvtepPhysicalLocatorAugmentation physicalLocatorAug) { + HwvtepLogicalSwitchRef lsRef = new HwvtepLogicalSwitchRef( + createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName))); + HwvtepPhysicalLocatorRef phyLocRef = new HwvtepPhysicalLocatorRef( + createPhysicalLocatorInstanceIdentifier(nodeId, physicalLocatorAug)); + + RemoteUcastMacs remoteUcastMacs = new RemoteUcastMacsBuilder().setMacEntryKey(new MacAddress(mac)) + .setIpaddr(ipAddress).setLogicalSwitchRef(lsRef).setLocatorRef(phyLocRef).build(); + return remoteUcastMacs; + } + + /** + * Creates the remote mcast mac. + * + * @param nodeId + * the node id + * @param mac + * the mac + * @param ipAddress + * the ip address + * @param logicalSwitchName + * the logical switch name + * @param lstPhysicalLocatorAug + * the lst physical locator aug + * @return the remote mcast macs + */ + public static RemoteMcastMacs createRemoteMcastMac(NodeId nodeId, String mac, IpAddress ipAddress, + String logicalSwitchName, List lstPhysicalLocatorAug) { + HwvtepLogicalSwitchRef lsRef = new HwvtepLogicalSwitchRef( + createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName))); + + List lstLocatorSet = new ArrayList<>(); + for (HwvtepPhysicalLocatorAugmentation phyLocatorAug : lstPhysicalLocatorAug) { + HwvtepPhysicalLocatorRef phyLocRef = new HwvtepPhysicalLocatorRef( + createPhysicalLocatorInstanceIdentifier(nodeId, phyLocatorAug)); + lstLocatorSet.add(new LocatorSetBuilder().setLocatorRef(phyLocRef).build()); + } + + RemoteMcastMacs remoteMcastMacs = new RemoteMcastMacsBuilder().setMacEntryKey(new MacAddress(mac)) + .setIpaddr(ipAddress).setLogicalSwitchRef(lsRef).setLocatorSet(lstLocatorSet).build(); + return remoteMcastMacs; + } + + /** + * Create vlan binding. + * + * @param nodeId + * the node id + * @param vlanId + * the vlan id + * @param logicalSwitchName + * the logical switch name + * @return the vlan bindings + */ + public static VlanBindings createVlanBinding(NodeId nodeId, int vlanId, String logicalSwitchName) { + VlanBindingsBuilder vbBuilder = new VlanBindingsBuilder(); + VlanBindingsKey vbKey = new VlanBindingsKey(new VlanId(vlanId)); + vbBuilder.setKey(vbKey); + vbBuilder.setVlanIdKey(vbKey.getVlanIdKey()); + + final InstanceIdentifier lSwitchIid = createLogicalSwitchesInstanceIdentifier(nodeId, + new HwvtepNodeName(logicalSwitchName)); + HwvtepLogicalSwitchRef lsRef = new HwvtepLogicalSwitchRef(lSwitchIid); + vbBuilder.setLogicalSwitchRef(lsRef); + return vbBuilder.build(); + } + +} diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/hwvtep/HwvtepUtils.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/hwvtep/HwvtepUtils.java new file mode 100644 index 00000000..f913f62c --- /dev/null +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/utils/hwvtep/HwvtepUtils.java @@ -0,0 +1,556 @@ +/* + * Copyright (c) 2016 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.utils.hwvtep; + +import java.util.List; + +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.vpnservice.mdsalutil.MDSALUtil; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalPortAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalPortAugmentationBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacsKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindings; +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.NodeId; +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.topology.Node; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Utility class to related to Hardware VTEP devices. + */ +public final class HwvtepUtils { + + // TODO: (eperefr) Move this to HwvtepSouthboundUtils when in place. + public static InstanceIdentifier getWildCardPathForLocalUcastMacs() { + return InstanceIdentifier.create(NetworkTopology.class).child(Topology.class).child(Node.class) + .augmentation(HwvtepGlobalAugmentation.class).child(LocalUcastMacs.class); + } + + /** + * Adds the logical switch into config DS. + * + * @param broker + * the broker + * @param nodeId + * the node id + * @param logicalSwitch + * the logical switch + * @return the listenable future + */ + public static ListenableFuture addLogicalSwitch(DataBroker broker, NodeId nodeId, + LogicalSwitches logicalSwitch) { + WriteTransaction transaction = broker.newWriteOnlyTransaction(); + putLogicalSwitch(transaction, nodeId, logicalSwitch); + return transaction.submit(); + } + + /** + * Put the logical switches in the transaction. + * + * @param transaction + * the transaction + * @param nodeId + * the node id + * @param lstSwitches + * the lst switches + */ + public static void putLogicalSwitches(final WriteTransaction transaction, final NodeId nodeId, + final List lstSwitches) { + if (lstSwitches != null) { + for (LogicalSwitches logicalSwitch : lstSwitches) { + putLogicalSwitch(transaction, nodeId, logicalSwitch); + } + } + } + + /** + * Put logical switch in the transaction. + * + * @param transaction + * the transaction + * @param nodeId + * the node id + * @param logicalSwitch + * the logical switch + */ + public static void putLogicalSwitch(final WriteTransaction transaction, final NodeId nodeId, + final LogicalSwitches logicalSwitch) { + InstanceIdentifier iid = HwvtepSouthboundUtils.createLogicalSwitchesInstanceIdentifier(nodeId, + logicalSwitch.getHwvtepNodeName()); + transaction.put(LogicalDatastoreType.CONFIGURATION, iid, logicalSwitch, true); + } + + /** + * Delete logical switch from config DS. + * + * @param broker + * the broker + * @param nodeId + * the node id + * @param logicalSwitchName + * the logical switch name + * @return the listenable future + */ + public static ListenableFuture deleteLogicalSwitch(DataBroker broker, NodeId nodeId, + String logicalSwitchName) { + WriteTransaction transaction = broker.newWriteOnlyTransaction(); + deleteLogicalSwitch(transaction, nodeId, logicalSwitchName); + return transaction.submit(); + } + + /** + * Delete logical switch from the transaction. + * + * @param transaction + * the transaction + * @param nodeId + * the node id + * @param logicalSwitchName + * the logical switch name + */ + public static void deleteLogicalSwitch(final WriteTransaction transaction, final NodeId nodeId, + final String logicalSwitchName) { + transaction.delete(LogicalDatastoreType.CONFIGURATION, HwvtepSouthboundUtils + .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName))); + } + + /** + * Gets the logical switch. + * + * @param nodeId + * the node id + * @param logicalSwitchName + * the logical switch name + * @return the logical switch + */ + public static LogicalSwitches getLogicalSwitch(DataBroker broker, LogicalDatastoreType datastoreType, NodeId nodeId, + String logicalSwitchName) { + final InstanceIdentifier iid = HwvtepSouthboundUtils + .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName)); + Optional optLogicalSwitch = MDSALUtil.read(broker, datastoreType, iid); + if (optLogicalSwitch.isPresent()) { + return optLogicalSwitch.get(); + } + return null; + } + + /** + * Get LogicalSwitches for a given hwVtepNodeId. + * + * @param broker + * the broker + * @param hwVtepNodeId + * Hardware VTEP Node Id + * @param vni + * virtual network id + * @return the logical switches + */ + public static LogicalSwitches getLogicalSwitches(DataBroker broker, String hwVtepNodeId, String vni) { + NodeId nodeId = new NodeId(hwVtepNodeId); + InstanceIdentifier logicalSwitchesIdentifier = HwvtepSouthboundUtils + .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(vni)); + + Optional logicalSwitches = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, + logicalSwitchesIdentifier); + if (!logicalSwitches.isPresent()) { + return null; + } + + return logicalSwitches.get(); + } + + /** + * Put physical locators in the transaction. + * + * @param transaction + * the transaction + * @param nodeId + * the node id + * @param lstPhysicalLocator + * the lst physical locator + */ + public static void putPhysicalLocators(WriteTransaction transaction, NodeId nodeId, + List lstPhysicalLocator) { + if (lstPhysicalLocator != null) { + for (HwvtepPhysicalLocatorAugmentation phyLocator : lstPhysicalLocator) { + putPhysicalLocator(transaction, nodeId, phyLocator); + } + } + } + + /** + * Put physical locator in the transaction. + * + * @param transaction + * the transaction + * @param nodeId + * the node id + * @param phyLocator + * the phy locator + */ + public static void putPhysicalLocator(final WriteTransaction transaction, final NodeId nodeId, + final HwvtepPhysicalLocatorAugmentation phyLocator) { + InstanceIdentifier iid = HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId, + phyLocator); + TerminationPoint terminationPoint = new TerminationPointBuilder() + .setKey(HwvtepSouthboundUtils.getTerminationPointKey(phyLocator)) + .addAugmentation(HwvtepPhysicalLocatorAugmentation.class, phyLocator).build(); + + transaction.put(LogicalDatastoreType.CONFIGURATION, iid, terminationPoint, true); + } + + /** + * Adds the remote ucast macs into config DS. + * + * @param broker + * the broker + * @param nodeId + * the node id + * @param lstRemoteUcastMacs + * the lst remote ucast macs + * @return the listenable future + */ + public static ListenableFuture addRemoteUcastMacs(DataBroker broker, NodeId nodeId, + List lstRemoteUcastMacs) { + WriteTransaction transaction = broker.newWriteOnlyTransaction(); + putRemoteUcastMacs(transaction, nodeId, lstRemoteUcastMacs); + return transaction.submit(); + } + + /** + * Put remote ucast macs in the transaction. + * + * @param transaction + * the transaction + * @param nodeId + * the node id + * @param lstRemoteUcastMacs + * the lst remote ucast macs + */ + public static void putRemoteUcastMacs(final WriteTransaction transaction, final NodeId nodeId, + final List lstRemoteUcastMacs) { + if (lstRemoteUcastMacs != null && !lstRemoteUcastMacs.isEmpty()) { + for (RemoteUcastMacs remoteUcastMac : lstRemoteUcastMacs) { + putRemoteUcastMac(transaction, nodeId, remoteUcastMac); + } + } + } + + /** + * Put remote ucast mac in the transaction. + * + * @param transaction + * the transaction + * @param nodeId + * the node id + * @param remoteUcastMac + * the remote ucast mac + */ + public static void putRemoteUcastMac(final WriteTransaction transaction, final NodeId nodeId, + RemoteUcastMacs remoteUcastMac) { + InstanceIdentifier iid = HwvtepSouthboundUtils.createInstanceIdentifier(nodeId).augmentation(HwvtepGlobalAugmentation.class) + .child(RemoteUcastMacs.class, new RemoteUcastMacsKey(remoteUcastMac.getLogicalSwitchRef(), remoteUcastMac.getMacEntryKey())); + transaction.put(LogicalDatastoreType.CONFIGURATION, iid, remoteUcastMac, true); + } + + /** + * Delete remote ucast mac from the config DS. + * + * @param broker + * the broker + * @param nodeId + * the node id + * @param mac + * the mac + * @return the listenable future + */ + public static ListenableFuture deleteRemoteUcastMac(DataBroker broker, NodeId nodeId, + String logicalSwitchName, MacAddress mac) { + WriteTransaction transaction = broker.newWriteOnlyTransaction(); + deleteRemoteUcastMac(transaction, nodeId, logicalSwitchName, mac); + return transaction.submit(); + } + + /** + * Delete remote ucast macs from the config DS. + * + * @param broker + * the broker + * @param nodeId + * the node id + * @param lstMac + * the lst mac + * @return the listenable future + */ + public static ListenableFuture deleteRemoteUcastMacs(DataBroker broker, NodeId nodeId, + String logicalSwitchName, List lstMac) { + WriteTransaction transaction = broker.newWriteOnlyTransaction(); + deleteRemoteUcastMacs(transaction, nodeId, logicalSwitchName, lstMac); + return transaction.submit(); + } + + /** + * Delete remote ucast macs from the transaction. + * + * @param transaction + * the transaction + * @param nodeId + * the node id + * @param lstMac + * the lst mac + */ + public static void deleteRemoteUcastMacs(final WriteTransaction transaction, final NodeId nodeId, + String logicalSwitchName, final List lstMac) { + if (lstMac != null && !lstMac.isEmpty()) { + for (MacAddress mac : lstMac) { + deleteRemoteUcastMac(transaction, nodeId, logicalSwitchName, mac); + } + } + } + + /** + * Delete remote ucast mac from the transaction. + * + * @param transaction + * the transaction + * @param nodeId + * the node id + * @param mac + * the mac + */ + public static void deleteRemoteUcastMac(final WriteTransaction transaction, final NodeId nodeId, + String logialSwitchName, + final MacAddress mac) { + transaction.delete(LogicalDatastoreType.CONFIGURATION, + HwvtepSouthboundUtils.createRemoteUcastMacsInstanceIdentifier(nodeId, logialSwitchName, mac)); + } + + /** + * Adds the remote mcast macs into config DS. + * + * @param broker + * the broker + * @param nodeId + * the node id + * @param lstRemoteMcastMacs + * the lst remote mcast macs + * @return the listenable future + */ + public static ListenableFuture addRemoteMcastMacs(DataBroker broker, NodeId nodeId, + List lstRemoteMcastMacs) { + WriteTransaction transaction = broker.newWriteOnlyTransaction(); + putRemoteMcastMacs(transaction, nodeId, lstRemoteMcastMacs); + return transaction.submit(); + } + + /** + * Put remote mcast macs in the transaction. + * + * @param transaction + * the transaction + * @param nodeId + * the node id + * @param lstRemoteMcastMacs + * the lst remote mcast macs + */ + public static void putRemoteMcastMacs(final WriteTransaction transaction, final NodeId nodeId, + final List lstRemoteMcastMacs) { + if (lstRemoteMcastMacs != null && !lstRemoteMcastMacs.isEmpty()) { + for (RemoteMcastMacs remoteMcastMac : lstRemoteMcastMacs) { + putRemoteMcastMac(transaction, nodeId, remoteMcastMac); + } + } + } + + /** + * Put remote mcast mac in the transaction. + * + * @param transaction + * the transaction + * @param nodeId + * the node id + * @param remoteMcastMac + * the remote mcast mac + */ + public static void putRemoteMcastMac(final WriteTransaction transaction, final NodeId nodeId, + RemoteMcastMacs remoteMcastMac) { + InstanceIdentifier iid = HwvtepSouthboundUtils.createRemoteMcastMacsInstanceIdentifier(nodeId, + remoteMcastMac.getKey()); + transaction.put(LogicalDatastoreType.CONFIGURATION, iid, remoteMcastMac, true); + } + + /** + * Delete remote mcast mac from config DS. + * + * @param broker + * the broker + * @param nodeId + * the node id + * @param remoteMcastMacsKey + * the remote mcast macs key + * @return the listenable future + */ + public static ListenableFuture deleteRemoteMcastMac(DataBroker broker, NodeId nodeId, + RemoteMcastMacsKey remoteMcastMacsKey) { + WriteTransaction transaction = broker.newWriteOnlyTransaction(); + deleteRemoteMcastMac(transaction, nodeId, remoteMcastMacsKey); + return transaction.submit(); + } + + /** + * Delete remote mcast macs from config DS. + * + * @param broker + * the broker + * @param nodeId + * the node id + * @param lstRemoteMcastMacsKey + * the lst remote mcast macs key + * @return the listenable future + */ + public static ListenableFuture deleteRemoteMcastMacs(DataBroker broker, NodeId nodeId, + List lstRemoteMcastMacsKey) { + WriteTransaction transaction = broker.newWriteOnlyTransaction(); + deleteRemoteMcastMacs(transaction, nodeId, lstRemoteMcastMacsKey); + return transaction.submit(); + } + + /** + * Delete remote mcast macs from the transaction. + * + * @param transaction + * the transaction + * @param nodeId + * the node id + * @param lstRemoteMcastMacsKey + * the lst remote mcast macs key + */ + public static void deleteRemoteMcastMacs(final WriteTransaction transaction, final NodeId nodeId, + final List lstRemoteMcastMacsKey) { + if (lstRemoteMcastMacsKey != null && !lstRemoteMcastMacsKey.isEmpty()) { + for (RemoteMcastMacsKey mac : lstRemoteMcastMacsKey) { + deleteRemoteMcastMac(transaction, nodeId, mac); + } + } + } + + /** + * Delete remote mcast mac from the transaction. + * + * @param transaction + * the transaction + * @param nodeId + * the node id + * @param remoteMcastMacsKey + * the remote mcast macs key + */ + public static void deleteRemoteMcastMac(final WriteTransaction transaction, final NodeId nodeId, + final RemoteMcastMacsKey remoteMcastMacsKey) { + transaction.delete(LogicalDatastoreType.CONFIGURATION, + HwvtepSouthboundUtils.createRemoteMcastMacsInstanceIdentifier(nodeId, remoteMcastMacsKey)); + } + + /** + * Merge vlan bindings in the transaction. + * + * @param transaction + * the transaction + * @param nodeId + * the node id + * @param phySwitchName + * the phy switch name + * @param phyPortName + * the phy port name + * @param vlanBindings + * the vlan bindings + */ + public static void mergeVlanBindings(final WriteTransaction transaction, final NodeId nodeId, + final String phySwitchName, final String phyPortName, final List vlanBindings) { + NodeId physicalSwitchNodeId = HwvtepSouthboundUtils.createManagedNodeId(nodeId, phySwitchName); + mergeVlanBindings(transaction, physicalSwitchNodeId, phyPortName, vlanBindings); + } + + /** + * Merge vlan bindings in the transaction. + * + * @param transaction + * the transaction + * @param physicalSwitchNodeId + * the physical switch node id + * @param phyPortName + * the phy port name + * @param vlanBindings + * the vlan bindings + */ + public static void mergeVlanBindings(final WriteTransaction transaction, final NodeId physicalSwitchNodeId, + final String phyPortName, final List vlanBindings) { + HwvtepPhysicalPortAugmentation phyPortAug = new HwvtepPhysicalPortAugmentationBuilder() + .setHwvtepNodeName(new HwvtepNodeName(phyPortName)).setVlanBindings(vlanBindings).build(); + + final InstanceIdentifier iid = HwvtepSouthboundUtils + .createPhysicalPortInstanceIdentifier(physicalSwitchNodeId, phyPortName); + transaction.merge(LogicalDatastoreType.CONFIGURATION, iid, phyPortAug, true); + } + + /** + * Delete vlan binding from transaction. + * + * @param transaction + * the transaction + * @param physicalSwitchNodeId + * the physical switch node id + * @param phyPortName + * the phy port name + * @param vlanId + * the vlan id + */ + public static void deleteVlanBinding(WriteTransaction transaction, NodeId physicalSwitchNodeId, String phyPortName, + Integer vlanId) { + InstanceIdentifier iid = HwvtepSouthboundUtils + .createVlanBindingInstanceIdentifier(physicalSwitchNodeId, phyPortName, vlanId); + transaction.delete(LogicalDatastoreType.CONFIGURATION, iid); + } + + /** + * Gets the hw vtep node. + * + * @param dataBroker + * the data broker + * @param datastoreType + * the datastore type + * @param nodeId + * the node id + * @return the hw vtep node + */ + public static Node getHwVtepNode(DataBroker dataBroker, LogicalDatastoreType datastoreType, NodeId nodeId) { + Optional optNode = MDSALUtil.read(dataBroker, datastoreType, + HwvtepSouthboundUtils.createInstanceIdentifier(nodeId)); + if (optNode.isPresent()) { + return optNode.get(); + } + return null; + } +} diff --git a/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALManager.java b/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALManager.java index 1192208f..08a1e657 100644 --- a/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALManager.java +++ b/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALManager.java @@ -264,7 +264,8 @@ public class MDSALManager implements AutoCloseable { public CheckedFuture removeFlowNew(BigInteger dpnId, Flow flowEntity) { s_logger.debug("Remove flow {}",flowEntity); Node nodeDpn = buildDpnNode(dpnId); - FlowKey flowKey = new FlowKey(new FlowId(flowEntity.getId())); + //FlowKey flowKey = new FlowKey(new FlowId(flowEntity.getId())); + FlowKey flowKey = new FlowKey(flowEntity.getId()); InstanceIdentifier flowInstanceId = InstanceIdentifier.builder(Nodes.class) .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class) .child(Table.class, new TableKey(flowEntity.getTableId())).child(Flow.class, flowKey).build(); -- 2.36.6