From 462c6a1f859067a517111cb7a1441571659c984b Mon Sep 17 00:00:00 2001 From: Manohar SL Date: Thu, 3 Dec 2015 15:23:03 +0530 Subject: [PATCH 1/1] Adding IdManager/LockManager and related Changes Change-Id: I5910c4537a5825667c04a6ca71312c83775e2a99 Signed-off-by: Gaurav Bhagwani --- features/pom.xml | 18 + features/src/main/features/features.xml | 3 + .../src/main/yang/id-manager.yang | 142 ++++- idmanager/idmanager-impl/pom.xml | 10 + .../org/opendaylight/idmanager/IdManager.java | 533 ++++++++++++++---- .../idmanager/IdManagerServiceProvider.java | 15 +- .../org/opendaylight/idmanager/IdUtils.java | 307 ++++++++++ .../idmanager/test/IdManagerTest.java | 442 ++++++++++++--- .../vpnservice/interfacemgr/IfmConstants.java | 3 +- .../vpnservice/interfacemgr/IfmUtil.java | 13 +- .../interfacemgr/InterfacemgrProvider.java | 4 +- .../commons/InterfaceManagerCommonUtils.java | 23 - .../OvsVlanMemberConfigAddHelper.java | 21 +- .../test/InterfaceManagerTestUtil.java | 6 +- lockmanager/lockmanager-api/pom.xml | 72 +++ .../src/main/yang/lock-manager.yang | 71 +++ lockmanager/lockmanager-impl/pom.xml | 84 +++ .../src/main/config/default-config.xml | 34 ++ .../opendaylight/lockmanager/LockManager.java | 188 ++++++ .../LockManagerServiceProvider.java | 56 ++ .../lockmanager/LockManagerUtils.java | 62 ++ .../impl/rev150819/LockManagerImplModule.java | 26 + .../LockManagerImplModuleFactory.java | 13 + .../src/main/yang/lockmanager-impl.yang | 44 ++ lockmanager/pom.xml | 49 ++ .../vpnservice/mdsalutil/MDSALUtil.java | 82 +++ .../vpnservice/nexthopmgr/NexthopManager.java | 42 +- .../nexthopmgr/test/NexthopManagerTest.java | 2 +- pom.xml | 3 +- .../vpnservice/VpnInterfaceManager.java | 39 +- .../opendaylight/vpnservice/VpnManager.java | 44 +- .../org/opendaylight/vpnservice/VpnUtil.java | 53 +- .../vpnservice/VpnserviceProvider.java | 4 +- 33 files changed, 2167 insertions(+), 341 deletions(-) create mode 100644 idmanager/idmanager-impl/src/main/java/org/opendaylight/idmanager/IdUtils.java create mode 100644 lockmanager/lockmanager-api/pom.xml create mode 100644 lockmanager/lockmanager-api/src/main/yang/lock-manager.yang create mode 100644 lockmanager/lockmanager-impl/pom.xml create mode 100644 lockmanager/lockmanager-impl/src/main/config/default-config.xml create mode 100644 lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManager.java create mode 100644 lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManagerServiceProvider.java create mode 100644 lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManagerUtils.java create mode 100644 lockmanager/lockmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/lockmanager/impl/rev150819/LockManagerImplModule.java create mode 100644 lockmanager/lockmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/lockmanager/impl/rev150819/LockManagerImplModuleFactory.java create mode 100644 lockmanager/lockmanager-impl/src/main/yang/lockmanager-impl.yang create mode 100644 lockmanager/pom.xml diff --git a/features/pom.xml b/features/pom.xml index 298fc804..8433fba5 100644 --- a/features/pom.xml +++ b/features/pom.xml @@ -33,6 +33,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL ${vpnservices.version} ${vpnservices.version} ${vpnservices.version} + ${vpnservices.version} ${vpnservices.version} @@ -209,6 +210,23 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL fibmanager-api ${fibmanager.version} + + ${project.groupId} + lockmanager-impl + ${lockmanager.version} + + + ${project.groupId} + lockmanager-impl + ${lockmanager.version} + config + xml + + + ${project.groupId} + lockmanager-api + ${lockmanager.version} + ${project.groupId} idmanager-impl diff --git a/features/src/main/features/features.xml b/features/src/main/features/features.xml index e03ef333..b4a6735a 100644 --- a/features/src/main/features/features.xml +++ b/features/src/main/features/features.xml @@ -21,6 +21,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html odl-mdsal-models odl-openflowplugin-nsf-model mvn:org.opendaylight.vpnservice/model-bgp/{{VERSION}} + mvn:org.opendaylight.vpnservice/lockmanager-api/${lockmanager.version} mvn:org.opendaylight.vpnservice/idmanager-api/${idmanager.version} mvn:org.opendaylight.vpnservice/vpnmanager-api/${vpnmanager.version} mvn:org.opendaylight.vpnservice/nexthopmgr-api/${nexthopmgr.version} @@ -33,6 +34,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html odl-vpnservice-api odl-openflowplugin-southbound odl-openflowplugin-flow-services + mvn:org.opendaylight.vpnservice/lockmanager-impl/${lockmanager.version} mvn:org.opendaylight.vpnservice/idmanager-impl/${idmanager.version} mvn:org.opendaylight.vpnservice/bgpmanager-api/${vpnservices.version} mvn:org.opendaylight.vpnservice/bgpmanager-impl/${vpnservices.version} @@ -47,6 +49,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html wrap:mvn:org.apache.thrift/libthrift/0.9.1$overwrite=merge&Bundle-Version=0.9.1&Export-Package=*;-noimport:=true;version="0.9.1" + mvn:org.opendaylight.vpnservice/lockmanager-impl/${lockmanager.version}/xml/config mvn:org.opendaylight.vpnservice/idmanager-impl/${idmanager.version}/xml/config mvn:org.opendaylight.vpnservice/bgpmanager-impl/${vpnservices.version}/xml/config mvn:org.opendaylight.vpnservice/mdsalutil-impl/${interfacemgr.version}/xml/config diff --git a/idmanager/idmanager-api/src/main/yang/id-manager.yang b/idmanager/idmanager-api/src/main/yang/id-manager.yang index 79bd2ffa..7e4a41f5 100644 --- a/idmanager/idmanager-api/src/main/yang/id-manager.yang +++ b/idmanager/idmanager-api/src/main/yang/id-manager.yang @@ -3,41 +3,133 @@ module id-manager { prefix idmgr; revision "2015-04-03" { - description "ID generator and manager Service module"; + description "YANG model describes methods for allocating or releasing Ids as well as to create/delete Id Pools. The child pools + are created inside the IdManager. This helps to improve ID Pool scalability/performance"; } - container pools { - description - "id pool instances"; - config false; + container id-pools { + description "Parent Id Pool is responsible allocating block (or) set of Ids to child Id Pools. The number of child pools are determined using some algorthimic approach inside IdManager. For example, spawning child pools based on Id allocation request rate for the given Pool, one child pool per blade in the cluster etc"; + config true; list id-pool { key "pool-name"; - leaf id-start { type uint32;} - leaf pool-size { type uint64;} - leaf pool-name { type string;} - list generated-ids { - key "id-key"; - leaf id-key { type string;} - leaf id-value { type uint32;} + leaf pool-name { + type string; + mandatory true; + } + leaf block-size { + type uint16; + mandatory true; + } + leaf parent-pool-name { + type string; + } + list child-pools { + key "child-pool-name"; + leaf child-pool-name { + type string; + mandatory true; + } + leaf last-access-time { + type uint32; + } + } + list id-entries { + description "Id entry for the given Id Pool, where id-key is used to identify the id entry"; + key "id-key"; + leaf id-key { type string;} + leaf id-value { type uint32;} + } + container available-ids-holder { + uses available-ids; + } + container released-ids-holder { + uses released-ids; } } } + grouping available-ids { + leaf start { + type uint32; + } + leaf end { + type uint32; + } + leaf cursor { + type int64; + } + } + + grouping released-ids { + leaf available-id-count { + type uint32; + } + leaf delayed-time-sec { + type uint32; + mandatory true; + } + list delayed-id-entries { + uses delayed-id-entry; + } + } + + grouping delayed-id-entry { + leaf id { + type uint32; + mandatory true; + } + leaf ready-time-sec { + type uint32; + mandatory true; + } + } + rpc createIdPool { - input { - leaf pool-name { type string; } - leaf id-start { type uint32; } - leaf pool-size { type uint64; } - } + input { + leaf pool-name { + type string; + } + leaf low { + type uint32; + } + leaf high { + type uint32; + } + } } - rpc getUniqueId { - input { - leaf pool-name { type string; } - leaf id-key {type string; } - } - output { - leaf id-value { type uint32; } - } + rpc deleteIdPool { + input { + leaf pool-name { + type string; + } + } + } + + rpc allocateId { + input { + leaf pool-name { + type string; + } + leaf id-key { + type string; + } + } + output { + leaf id-value { + type uint32; + } + } + } + + rpc releaseId { + input { + leaf pool-name { + type string; + } + leaf id-key { + type string; + } + } } } diff --git a/idmanager/idmanager-impl/pom.xml b/idmanager/idmanager-impl/pom.xml index 4e135b9f..e1ea21c2 100644 --- a/idmanager/idmanager-impl/pom.xml +++ b/idmanager/idmanager-impl/pom.xml @@ -26,6 +26,16 @@ and is available at http://www.eclipse.org/legal/epl-v10.html idmanager-api ${vpnservices.version} + + org.opendaylight.vpnservice + lockmanager-api + ${vpnservices.version} + + + org.opendaylight.vpnservice + mdsalutil-api + ${vpnservices.version} + diff --git a/idmanager/idmanager-impl/src/main/java/org/opendaylight/idmanager/IdManager.java b/idmanager/idmanager-impl/src/main/java/org/opendaylight/idmanager/IdManager.java index a57086a4..07f0e3c6 100644 --- a/idmanager/idmanager-impl/src/main/java/org/opendaylight/idmanager/IdManager.java +++ b/idmanager/idmanager-impl/src/main/java/org/opendaylight/idmanager/IdManager.java @@ -8,37 +8,61 @@ package org.opendaylight.idmanager; -import com.google.common.base.Optional; -import com.google.common.util.concurrent.FutureCallback; -import com.google.common.util.concurrent.Futures; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; import org.opendaylight.controller.md.sal.binding.api.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.mdsalutil.MDSALUtil; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.DeleteIdPoolInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolderBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPools; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntries; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolderBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntries; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntriesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService; import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcError.ErrorType; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.*; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.*; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.id.pool.*; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Future; +import com.google.common.base.Optional; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; public class IdManager implements IdManagerService, AutoCloseable{ private static final Logger LOG = LoggerFactory.getLogger(IdManager.class); - private ListenerRegistration listenerRegistration; - private final DataBroker broker; + private static final long DEFAULT_IDLE_TIME = 24 * 60 * 60; + private ListenerRegistration listenerRegistration; + private final DataBroker broker; + private LockManagerService lockManager; @Override public void close() throws Exception { @@ -57,146 +81,423 @@ public class IdManager implements IdManagerService, AutoCloseable{ broker = db; } - private Optional read(LogicalDatastoreType datastoreType, - InstanceIdentifier path) { - - ReadOnlyTransaction tx = broker.newReadOnlyTransaction(); + public void setLockManager(LockManagerService lockManager) { + this.lockManager = lockManager; + } - Optional result = Optional.absent(); + @Override + public Future> createIdPool(CreateIdPoolInput input) { + LOG.debug("createIdPool called with input {}", input); + String poolName = input.getPoolName(); + long low = input.getLow(); + long high = input.getHigh(); + long blockSize = IdUtils.computeBlockSize(low, high); + RpcResultBuilder createIdPoolRpcBuilder; + IdUtils.lockPool(lockManager, poolName); try { - result = tx.read(datastoreType, path).get(); - } catch (Exception e) { - throw new RuntimeException(e); + InstanceIdentifier idPoolInstanceIdentifier = IdUtils.getIdPoolInstance(poolName); + poolName = poolName.intern(); + IdPool idPool; + idPool = createGlobalPool(poolName, low, high, blockSize, idPoolInstanceIdentifier); + String localPoolName = IdUtils.getLocalPoolName(poolName); + if (createLocalPool(localPoolName, idPool)) { + LOG.debug("Updating global id pool {} with childPool {}", poolName, localPoolName); + updateChildPool(poolName, localPoolName); + } + createIdPoolRpcBuilder = RpcResultBuilder.success(); + } catch (Exception ex) { + LOG.error("Creation of Id Pool {} failed due to {}", poolName, ex); + createIdPoolRpcBuilder = RpcResultBuilder.failed(); + createIdPoolRpcBuilder.withError(ErrorType.APPLICATION, ex.getMessage()); + } finally { + IdUtils.unlockPool(lockManager, poolName); } - - return result; - } - - protected void asyncWrite(LogicalDatastoreType datastoreType, - InstanceIdentifier path, T data, FutureCallback callback) { - WriteTransaction tx = broker.newWriteOnlyTransaction(); - tx.put(datastoreType, path, data, true); - Futures.addCallback(tx.submit(), callback); + return Futures.immediateFuture(createIdPoolRpcBuilder.build()); } - protected void asyncUpdate(LogicalDatastoreType datastoreType, - InstanceIdentifier path, T data, FutureCallback callback) { - WriteTransaction tx = broker.newWriteOnlyTransaction(); - tx.merge(datastoreType, path, data, true); - Futures.addCallback(tx.submit(), callback); + @Override + public Future> allocateId(AllocateIdInput input) { + LOG.debug("AllocateId called with input {}", input); + String idKey = input.getIdKey(); + String poolName = input.getPoolName(); + String localPoolName = IdUtils.getLocalPoolName(poolName); + RpcResultBuilder allocateIdRpcBuilder; + long newIdValue = -1; + AllocateIdOutputBuilder output = new AllocateIdOutputBuilder(); + try { + newIdValue = allocateIdFromLocalPool(localPoolName, idKey); + output.setIdValue(newIdValue); + allocateIdRpcBuilder = RpcResultBuilder.success(); + allocateIdRpcBuilder.withResult(output.build()); + } catch (Exception ex) { + LOG.error("Allocate id in pool {} failed due to {}", poolName, ex); + allocateIdRpcBuilder = RpcResultBuilder.failed(); + allocateIdRpcBuilder.withError(ErrorType.APPLICATION, ex.getMessage()); + } + return Futures.immediateFuture(allocateIdRpcBuilder.build()); } @Override - public Future> createIdPool(CreateIdPoolInput input) - { - + public Future> deleteIdPool(DeleteIdPoolInput input) { + LOG.debug("DeleteIdPool called with input {}", input); String poolName = input.getPoolName(); - long startIndx = input.getIdStart(); - long poolSize = input.getPoolSize().longValue(); - RpcResultBuilder rpcResultBuilder; - - LOG.debug("poolName: {}, startIndx: {} , poolSize: {} ", poolName, startIndx, poolSize); - + RpcResultBuilder deleteIdPoolRpcBuilder; try { - InstanceIdentifier.InstanceIdentifierBuilder idBuilder = - InstanceIdentifier.builder(Pools.class).child(IdPool.class, new IdPoolKey(poolName)); - InstanceIdentifier id = idBuilder.build(); - Optional pool = read(LogicalDatastoreType.OPERATIONAL, id); - if (!pool.isPresent()) { - LOG.debug("Creating a new global pool: {} ", poolName); - IdPool newPool = getPoolInterface(poolName, startIndx, poolSize); - LOG.debug("NewPool: {}", newPool); - asyncWrite(LogicalDatastoreType.OPERATIONAL, id, newPool, DEFAULT_CALLBACK); - + InstanceIdentifier idPoolToBeDeleted = IdUtils.getIdPoolInstance(poolName); + poolName = poolName.intern(); + synchronized(poolName) { + IdPool idPool = getIdPool(idPoolToBeDeleted); + List childPoolList = idPool.getChildPools(); + if (childPoolList != null) { + for (ChildPools childPoolName : childPoolList) { + deletePool(childPoolName.getChildPoolName()); + } + } + MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, idPoolToBeDeleted); + LOG.debug("Deleted id pool {}", poolName); } - - rpcResultBuilder = RpcResultBuilder.success(); + deleteIdPoolRpcBuilder = RpcResultBuilder.success(); } - catch(Exception e){ - LOG.error("Creation of global pool {} failed due to {}" ,poolName, e); - rpcResultBuilder = RpcResultBuilder.failed(); + catch (Exception ex) { + LOG.error("Delete id in pool {} failed due to {}", poolName, ex); + deleteIdPoolRpcBuilder = RpcResultBuilder.failed(); + deleteIdPoolRpcBuilder.withError(ErrorType.APPLICATION, ex.getMessage()); } - - return Futures.immediateFuture(rpcResultBuilder.build()); + return Futures.immediateFuture(deleteIdPoolRpcBuilder.build()); } - @Override - public Future> getUniqueId(GetUniqueIdInput input){ - + public Future> releaseId(ReleaseIdInput input) { String poolName = input.getPoolName(); String idKey = input.getIdKey(); + RpcResultBuilder releaseIdRpcBuilder; + try { + releaseIdFromLocalPool(IdUtils.getLocalPoolName(poolName), idKey); + releaseIdRpcBuilder = RpcResultBuilder.success(); + } catch (Exception ex) { + LOG.error("Release id {} from pool {} failed due to {}", idKey, poolName, ex); + releaseIdRpcBuilder = RpcResultBuilder.failed(); + releaseIdRpcBuilder.withError(ErrorType.APPLICATION, ex.getMessage()); + } + return Futures.immediateFuture(releaseIdRpcBuilder.build()); + } - LOG.debug("poolName: {} ,idKey: {}", poolName, idKey); - RpcResultBuilder rpcResultBuilder; + private long allocateIdFromLocalPool(String localPoolName, String idKey) { + long newIdValue = -1; + InstanceIdentifier idPoolInstanceIdentifier = IdUtils.getIdPoolInstance(localPoolName); + localPoolName = localPoolName.intern(); + synchronized (localPoolName) { + IdEntries newIdEntry; + IdPool pool = getIdPool(idPoolInstanceIdentifier); + List idEntries = pool.getIdEntries(); + + AvailableIdsHolderBuilder availableIds = IdUtils.getAvailableIdsHolderBuilder(pool); + ReleasedIdsHolderBuilder releasedIds = IdUtils.getReleaseIdsHolderBuilder(pool); + //Calling cleanupExcessIds since there could be excessive ids. + cleanupExcessIds(availableIds, releasedIds, pool.getParentPoolName(), pool.getBlockSize()); + if (idEntries == null) { + idEntries = new LinkedList(); + } else { + InstanceIdentifier existingId = IdUtils.getIdEntry(idPoolInstanceIdentifier, idKey); + Optional existingIdEntry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, existingId); + if (existingIdEntry.isPresent()) { + newIdValue = existingIdEntry.get().getIdValue(); + LOG.debug("Existing id {} for the key {} ", idKey, newIdValue); + InstanceIdentifier releasedIdsHolderInstanceIdentifier = InstanceIdentifier + .builder(IdPools.class).child(IdPool.class, new IdPoolKey(localPoolName)).child(ReleasedIdsHolder.class).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, releasedIdsHolderInstanceIdentifier, releasedIds.build()); + return newIdValue; + } + } + newIdValue = getIdFromPool(pool, availableIds, releasedIds); + newIdEntry = IdUtils.createIdEntries(idKey, newIdValue); + idEntries.add(newIdEntry); + pool = new IdPoolBuilder(pool).setIdEntries(idEntries) + .setAvailableIdsHolder(availableIds.build()).setReleasedIdsHolder(releasedIds.build()).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier, pool); + updateChildPool(pool.getParentPoolName(), localPoolName); + } + return newIdValue; + } + private long getIdFromPool(IdPool pool, AvailableIdsHolderBuilder availableIds, ReleasedIdsHolderBuilder releasedIds) { + long newIdValue = -1; + while (true) { + newIdValue = IdUtils.getIdFromReleaseIdsIfAvailable(releasedIds); + if (newIdValue != -1) { + LOG.debug("Retrieved id value {} from released id holder", newIdValue); + return newIdValue; + } + newIdValue = IdUtils.getIdFromAvailableIds(availableIds); + if (newIdValue != -1) { + LOG.debug("Creating a new id {} for the pool: {} ", newIdValue, pool.getPoolName()); + return newIdValue; + } + long idCount = allocateIdBlockFromParentPool(pool.getParentPoolName(), availableIds, releasedIds); + if (idCount <= 0) { + LOG.debug("Unable to allocate Id block from global pool"); + throw new RuntimeException(String.format("Ids exhausted for pool : %s", pool.getPoolName())); + } + } + } + + /** + * Changes made to releaseIds and AvailableIds are not persisted. + * @param availableIds + * @param releasedIds + * @param parentPoolName + * @param blockSize + */ + private void cleanupExcessIds(AvailableIdsHolderBuilder availableIds, ReleasedIdsHolderBuilder releasedIds, String parentPoolName, int blockSize) { + IdUtils.processDelayList(releasedIds); + long totalAvailableIdCount = releasedIds.getAvailableIdCount() + IdUtils.getAvailableIdsCount(availableIds); + if (totalAvailableIdCount > blockSize * 2) { + parentPoolName = parentPoolName.intern(); + InstanceIdentifier releasedIdInstanceIdentifier = IdUtils.getReleasedIdsHolderInstance(parentPoolName); + IdUtils.lockPool(lockManager, parentPoolName); + try { + Optional releasedIdsHolder = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, releasedIdInstanceIdentifier); + ReleasedIdsHolderBuilder releasedIdsParent; + if (!releasedIdsHolder.isPresent()) { + LOG.error("ReleasedIds not present in parent pool. Unable to cleanup excess ids"); + return; + } + releasedIdsParent = new ReleasedIdsHolderBuilder(releasedIdsHolder.get()); + LOG.debug("Releasing excesss Ids from local pool"); + IdUtils.freeExcessAvailableIds(releasedIds, releasedIdsParent, blockSize); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, releasedIdInstanceIdentifier, releasedIdsParent.build()); + } finally { + IdUtils.unlockPool(lockManager, parentPoolName); + } + } + } + + /** + * Changes made to availableIds and releasedIds will not be persisted to the datastore + * @param parentPoolName + * @param availableIdsBuilder + * @param releasedIdsBuilder + * @return + */ + private long allocateIdBlockFromParentPool(String parentPoolName, + AvailableIdsHolderBuilder availableIdsBuilder, ReleasedIdsHolderBuilder releasedIdsBuilder) { + LOG.debug("Allocating block of id from parent pool {}", parentPoolName); + InstanceIdentifier idPoolInstanceIdentifier = IdUtils.getIdPoolInstance(parentPoolName); + parentPoolName = parentPoolName.intern(); + long idCount = -1; + IdUtils.lockPool(lockManager, parentPoolName); try { - InstanceIdentifier.InstanceIdentifierBuilder idBuilder = - InstanceIdentifier.builder(Pools.class).child(IdPool.class, new IdPoolKey(poolName)); - InstanceIdentifier id = idBuilder.build(); - Optional globalPool = read(LogicalDatastoreType.OPERATIONAL, id); - GetUniqueIdOutputBuilder output = new GetUniqueIdOutputBuilder(); - Long newIdValue = null; - GeneratedIds newGenId = null; - if (globalPool.isPresent()) { - IdPool pool = globalPool.get(); - List generatedIds = pool.getGeneratedIds(); - - if (generatedIds == null) { - generatedIds = new ArrayList(); + IdPool parentIdPool = getIdPool(idPoolInstanceIdentifier); + ReleasedIdsHolderBuilder releasedIdsBuilderParent = IdUtils.getReleaseIdsHolderBuilder(parentIdPool); + while (true) { + idCount = allocateIdBlockFromReleasedIdsHolder(releasedIdsBuilder, releasedIdsBuilderParent, parentIdPool); + if (idCount > 0) { + return idCount; + } + idCount = allocateIdBlockFromAvailableIdsHolder(availableIdsBuilder, parentIdPool); + if (idCount > 0) { + return idCount; } - if (!generatedIds.isEmpty()) { - for (GeneratedIds genId : generatedIds) { - if (genId.getIdKey().equals(idKey)) { - newIdValue = genId.getIdValue(); - LOG.debug("Existing id {} for the key {} ", idKey, newIdValue); - } + idCount = getIdsFromOtherChildPools(releasedIdsBuilderParent, parentIdPool); + if (idCount <= 0) { + LOG.debug("Unable to allocate Id block from global pool"); + throw new RuntimeException(String.format("Ids exhausted for pool : %s", parentPoolName)); + } + } + } + finally { + IdUtils.unlockPool(lockManager, parentPoolName); + } + } - } + private long getIdsFromOtherChildPools(ReleasedIdsHolderBuilder releasedIdsBuilderParent, IdPool parentIdPool) { + List childPoolsList = parentIdPool.getChildPools(); + // Sorting the child pools on last accessed time so that the pool that was not accessed for a long time comes first. + Collections.sort(childPoolsList, new Comparator() { + @Override + public int compare(ChildPools childPool1, ChildPools childPool2) { + return childPool1.getLastAccessTime().compareTo(childPool2.getLastAccessTime()); + } + }); + long currentTime = System.currentTimeMillis() / 1000; + for (ChildPools childPools : childPoolsList) { + if (childPools.getLastAccessTime() + DEFAULT_IDLE_TIME < currentTime) { + break; + } + if (!childPools.getChildPoolName().equals(IdUtils.getLocalPoolName(parentIdPool.getPoolName()))) { + InstanceIdentifier idPoolInstanceIdentifier = IdUtils.getIdPoolInstance(childPools.getChildPoolName()); + IdPool otherChildPool = getIdPool(idPoolInstanceIdentifier); + ReleasedIdsHolderBuilder releasedIds = IdUtils.getReleaseIdsHolderBuilder(otherChildPool); + AvailableIdsHolderBuilder availableIds = IdUtils.getAvailableIdsHolderBuilder(otherChildPool); + long totalAvailableIdCount = releasedIds.getDelayedIdEntries().size() + IdUtils.getAvailableIdsCount(availableIds); + List delayedIdEntriesChild = releasedIds.getDelayedIdEntries(); + List delayedIdEntriesParent = releasedIdsBuilderParent.getDelayedIdEntries(); + if (delayedIdEntriesParent == null) { + delayedIdEntriesParent = new LinkedList<>(); } - synchronized (this) { - if (newIdValue == null) { - newIdValue = (long) generatedIds.size() + 1; - LOG.debug("Creating a new id {} for the pool: {} ", newIdValue, poolName); - newGenId = getIdsInterface(idKey, newIdValue); - generatedIds.add(newGenId); - pool = new IdPoolBuilder(pool).setGeneratedIds(generatedIds).build(); - asyncUpdate(LogicalDatastoreType.OPERATIONAL, id, pool, DEFAULT_CALLBACK); - } + delayedIdEntriesParent.addAll(delayedIdEntriesChild); + delayedIdEntriesChild.removeAll(delayedIdEntriesChild); + while (IdUtils.isIdAvailable(availableIds)) { + long cursor = availableIds.getCursor() + 1; + delayedIdEntriesParent.add(new DelayedIdEntriesBuilder().setId(cursor).setReadyTimeSec(System.currentTimeMillis()).build()); + availableIds.setCursor(cursor); } - output.setIdValue(newIdValue); + long count = releasedIdsBuilderParent.getAvailableIdCount() + totalAvailableIdCount; + releasedIdsBuilderParent.setDelayedIdEntries(delayedIdEntriesParent).setAvailableIdCount(count); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier, + new IdPoolBuilder(otherChildPool).setAvailableIdsHolder(availableIds.build()).setReleasedIdsHolder(releasedIds.build()).build()); + return totalAvailableIdCount; } + } + return 0; + } - rpcResultBuilder = RpcResultBuilder.success(); - rpcResultBuilder.withResult(output.build()); + private long allocateIdBlockFromReleasedIdsHolder(ReleasedIdsHolderBuilder releasedIdsBuilderChild, ReleasedIdsHolderBuilder releasedIdsBuilderParent, IdPool parentIdPool) { + if (releasedIdsBuilderParent.getAvailableIdCount() == 0) { + LOG.debug("Ids unavailable in releasedIds of parent pool {}", parentIdPool); + return 0; } - catch(Exception e){ - LOG.error("Creation of id for the key {} , global pool {} failed due to {}" ,idKey, poolName, e); - rpcResultBuilder = RpcResultBuilder.failed(); + List delayedIdEntriesParent = releasedIdsBuilderParent.getDelayedIdEntries(); + List delayedIdEntriesChild = releasedIdsBuilderChild.getDelayedIdEntries(); + if (delayedIdEntriesChild == null) { + delayedIdEntriesChild = new LinkedList(); } - return Futures.immediateFuture(rpcResultBuilder.build()); + int idCount = Math.min(delayedIdEntriesParent.size(), parentIdPool.getBlockSize()); + List idEntriesToBeRemoved = delayedIdEntriesParent.subList(0, idCount); + delayedIdEntriesChild.addAll(0, idEntriesToBeRemoved); + delayedIdEntriesParent.removeAll(idEntriesToBeRemoved); + releasedIdsBuilderParent.setDelayedIdEntries(delayedIdEntriesParent); + releasedIdsBuilderChild.setDelayedIdEntries(delayedIdEntriesChild); + releasedIdsBuilderChild.setAvailableIdCount(releasedIdsBuilderChild.getAvailableIdCount() + idCount); + InstanceIdentifier releasedIdsHolderInstanceIdentifier = InstanceIdentifier + .builder(IdPools.class).child(IdPool.class, + new IdPoolKey(parentIdPool.getPoolName())).child(ReleasedIdsHolder.class).build(); + releasedIdsBuilderParent.setAvailableIdCount(releasedIdsBuilderParent.getAvailableIdCount() - idCount); + LOG.debug("Allocated {} ids from releasedIds of parent pool {}", idCount, parentIdPool); + MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, releasedIdsHolderInstanceIdentifier, releasedIdsBuilderParent.build()); + return idCount; } + private long allocateIdBlockFromAvailableIdsHolder(AvailableIdsHolderBuilder availableIdsBuilder, IdPool parentIdPool) { + long idCount = 0; + AvailableIdsHolderBuilder availableIdsBuilderParent = IdUtils.getAvailableIdsHolderBuilder(parentIdPool); + long end = availableIdsBuilderParent.getEnd(); + long cur = availableIdsBuilderParent.getCursor(); + if (!IdUtils.isIdAvailable(availableIdsBuilderParent)) { + LOG.debug("Ids exhausted in parent pool {}", parentIdPool); + return idCount; + } + // Update availableIdsHolder of Local Pool + availableIdsBuilder.setStart(cur + 1); + idCount = Math.min(end - cur, parentIdPool.getBlockSize()); + availableIdsBuilder.setEnd(cur + idCount); + availableIdsBuilder.setCursor(cur); + // Update availableIdsHolder of Global Pool + InstanceIdentifier availableIdsHolderInstanceIdentifier = InstanceIdentifier + .builder(IdPools.class).child(IdPool.class, + new IdPoolKey(parentIdPool.getPoolName())).child(AvailableIdsHolder.class).build(); + availableIdsBuilderParent.setCursor(cur + idCount); + LOG.debug("Allocated {} ids from availableIds of global pool {}", idCount, parentIdPool); + MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, availableIdsHolderInstanceIdentifier, availableIdsBuilderParent.build()); + return idCount; + } - private IdPool getPoolInterface(String poolName, long startIndx, long poolSize) { - BigInteger size = BigInteger.valueOf(poolSize); - return new IdPoolBuilder().setKey(new IdPoolKey(poolName)).setPoolName(poolName).setIdStart(startIndx) - .setPoolSize(size).build(); + private void releaseIdFromLocalPool(String poolName, String idKey) { + InstanceIdentifier idPoolInstanceIdentifier = IdUtils.getIdPoolInstance(poolName); + poolName = poolName.intern(); + synchronized (poolName) { + IdPool pool = getIdPool(idPoolInstanceIdentifier); + List idEntries = pool.getIdEntries(); + List newIdEntries = idEntries; + if (idEntries == null) { + throw new RuntimeException("Id Entries does not exist"); + } + InstanceIdentifier existingId = IdUtils.getIdEntry(idPoolInstanceIdentifier, idKey); + Optional existingIdEntryObject = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, existingId); + if (!existingIdEntryObject.isPresent()) { + throw new RuntimeException(String.format("Specified Id key %s does not exist in id pool %s", idKey, poolName)); + } + IdEntries existingIdEntry = existingIdEntryObject.get(); + long idValue = existingIdEntry.getIdValue(); + newIdEntries.remove(existingIdEntry); + ReleasedIdsHolderBuilder releasedIds = IdUtils.getReleaseIdsHolderBuilder(pool); + AvailableIdsHolderBuilder availableIds = IdUtils.getAvailableIdsHolderBuilder(pool); + long delayTime = System.currentTimeMillis() / 1000 + releasedIds.getDelayedTimeSec(); + DelayedIdEntries delayedIdEntry = IdUtils.createDelayedIdEntry(idValue, delayTime); + List delayedIdEntries = releasedIds.getDelayedIdEntries(); + if (delayedIdEntries == null) { + delayedIdEntries = new LinkedList(); + } + delayedIdEntries.add(delayedIdEntry); + long availableIdCount = releasedIds + .getAvailableIdCount() == null ? 0 + : releasedIds.getAvailableIdCount(); + releasedIds.setDelayedIdEntries(delayedIdEntries); + releasedIds.setAvailableIdCount(availableIdCount); + //Calling cleanupExcessIds since there could be excessive ids. + cleanupExcessIds(availableIds, releasedIds, pool.getParentPoolName(), pool.getBlockSize()); + pool = new IdPoolBuilder(pool).setIdEntries(newIdEntries) + .setAvailableIdsHolder(availableIds.build()) + .setReleasedIdsHolder(releasedIds.build()).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier, pool); + LOG.debug("Released id ({}, {}) from pool {}", idKey, idValue, poolName); + } } - private GeneratedIds getIdsInterface(String idKey, long newIdVal) { - return new GeneratedIdsBuilder().setKey(new GeneratedIdsKey(idKey)).setIdKey(idKey) - .setIdValue(newIdVal).build(); + private IdPool createGlobalPool(String poolName, long low, long high, + long blockSize, InstanceIdentifier idPoolInstanceIdentifier) { + IdPool idPool; + Optional existingIdPool = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier); + if (!existingIdPool.isPresent()) { + LOG.debug("Creating new global pool {}", poolName); + idPool = IdUtils.createGlobalPool(poolName, low, high, blockSize); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier, idPool); + } + else { + idPool = existingIdPool.get(); + LOG.debug("GlobalPool exists {}", idPool); + } + return idPool; } - private static final FutureCallback DEFAULT_CALLBACK = - new FutureCallback() { - public void onSuccess(Void result) { - LOG.debug("Success in Datastore write operation"); + private boolean createLocalPool(String localPoolName, IdPool idPool) { + localPoolName = localPoolName.intern(); + synchronized (localPoolName) { + InstanceIdentifier localIdPoolInstanceIdentifier = IdUtils.getIdPoolInstance(localPoolName); + Optional localIdPool = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, localIdPoolInstanceIdentifier); + if (!localIdPool.isPresent()) { + LOG.debug("Creating new local pool"); + IdPool newLocalIdPool = IdUtils.createLocalIdPool(localPoolName, idPool); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, localIdPoolInstanceIdentifier, newLocalIdPool); + LOG.debug("Local pool created {}", newLocalIdPool); + return true; } + } + return false; + } - public void onFailure(Throwable error) { - LOG.error("Error in Datastore write operation", error); + private void deletePool(String poolName) { + InstanceIdentifier idPoolToBeDeleted = IdUtils.getIdPoolInstance(poolName); + synchronized (poolName) { + Optional idPool = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, idPoolToBeDeleted); + if (idPool.isPresent()) { + MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, idPoolToBeDeleted); + LOG.debug("Deleted local pool {}", poolName); } - }; + } + } + + private IdPool getIdPool(InstanceIdentifier idPoolInstanceIdentifier) { + Optional idPool = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier); + if (!idPool.isPresent()) { + throw new RuntimeException(String.format("Specified pool %s does not exist" , idPool)); + } + return idPool.get(); + } + + private void updateChildPool(String poolName, String localPoolName) { + ChildPools childPool = IdUtils.createChildPool(localPoolName); + InstanceIdentifier childPoolInstanceIdentifier = IdUtils.getChildPoolsInstanceIdentifier(poolName, localPoolName); + MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, childPoolInstanceIdentifier, childPool); + } } diff --git a/idmanager/idmanager-impl/src/main/java/org/opendaylight/idmanager/IdManagerServiceProvider.java b/idmanager/idmanager-impl/src/main/java/org/opendaylight/idmanager/IdManagerServiceProvider.java index ab016b1e..b027da1c 100644 --- a/idmanager/idmanager-impl/src/main/java/org/opendaylight/idmanager/IdManagerServiceProvider.java +++ b/idmanager/idmanager-impl/src/main/java/org/opendaylight/idmanager/IdManagerServiceProvider.java @@ -15,6 +15,7 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareProvider; import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,9 +23,10 @@ import org.slf4j.LoggerFactory; public class IdManagerServiceProvider implements BindingAwareProvider, AutoCloseable { - private static final Logger LOG = LoggerFactory.getLogger(IdManagerServiceProvider.class); - private IdManager idManager; - private RpcProviderRegistry rpcProviderRegistry; + private static final Logger LOG = LoggerFactory.getLogger(IdManagerServiceProvider.class); + private IdManager idManager; + private RpcProviderRegistry rpcProviderRegistry; + private LockManagerService lockManager; public RpcProviderRegistry getRpcProviderRegistry() { return rpcProviderRegistry; @@ -34,12 +36,17 @@ public class IdManagerServiceProvider implements BindingAwareProvider, this.rpcProviderRegistry = rpcProviderRegistry; } - @Override + public void setLockManager(LockManagerService lockManager) { + this.lockManager = lockManager; + } + + @Override public void onSessionInitiated(ProviderContext session){ LOG.info("IDManagerserviceProvider Session Initiated"); try { final DataBroker dataBroker = session.getSALService(DataBroker.class); idManager = new IdManager(dataBroker); + idManager.setLockManager(lockManager); final BindingAwareBroker.RpcRegistration rpcRegistration = getRpcProviderRegistry().addRpcImplementation(IdManagerService.class, idManager); } catch (Exception e) { LOG.error("Error initializing services", e); diff --git a/idmanager/idmanager-impl/src/main/java/org/opendaylight/idmanager/IdUtils.java b/idmanager/idmanager-impl/src/main/java/org/opendaylight/idmanager/IdUtils.java new file mode 100644 index 00000000..507dad2b --- /dev/null +++ b/idmanager/idmanager-impl/src/main/java/org/opendaylight/idmanager/IdUtils.java @@ -0,0 +1,307 @@ +/* + * 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.idmanager; + +import java.net.InetAddress; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.DelayedIdEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolderBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPools; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPoolsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPoolsKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntries; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntriesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntriesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolderBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntries; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntriesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.UnlockInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.UnlockInputBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.net.InetAddresses; + +class IdUtils { + + private static final Logger LOGGER = LoggerFactory.getLogger(IdUtils.class); + private static final long DEFAULT_DELAY_TIME = 30; + private static final long DEFAULT_AVAILABLE_ID_COUNT = 0; + private static final int DEFAULT_BLOCK_SIZE_DIFF = 50; + + private static int BLADE_ID; + static { + String hostName; + try { + hostName = InetAddress.getLocalHost().getHostName(); + BLADE_ID = InetAddresses.coerceToInteger(InetAddress.getLocalHost()); + if (hostName.indexOf("-") > 0) { + BLADE_ID = new Integer(hostName.split("-")[1].toString()).intValue(); + } else { + LOGGER.error("Host name {} is not matching with the condition!! PL-X is expected", hostName); + } + } catch (Exception e) { + LOGGER.error("IdManager - Exception - {}", e.getMessage()); + } + } + + protected static InstanceIdentifier getIdEntry(InstanceIdentifier poolName, String idKey) { + InstanceIdentifier.InstanceIdentifierBuilder idEntriesBuilder = poolName + .builder().child(IdEntries.class, new IdEntriesKey(idKey)); + InstanceIdentifier idEntry = idEntriesBuilder.build(); + return idEntry; + } + + protected static IdEntries createIdEntries(String idKey, long newIdVal) { + return new IdEntriesBuilder().setKey(new IdEntriesKey(idKey)) + .setIdKey(idKey).setIdValue(newIdVal).build(); + } + + protected static DelayedIdEntries createDelayedIdEntry(long idValue, long delayTime) { + return new DelayedIdEntriesBuilder() + .setId(idValue) + .setReadyTimeSec(delayTime).build(); + } + + protected static IdPool createGlobalPool(String poolName, long low, long high, long blockSize) { + AvailableIdsHolder availableIdsHolder = createAvailableIdsHolder(low, high, low - 1); + ReleasedIdsHolder releasedIdsHolder = createReleasedIdsHolder(DEFAULT_AVAILABLE_ID_COUNT, 0); + int size = (int) blockSize; + return new IdPoolBuilder().setKey(new IdPoolKey(poolName)) + .setBlockSize(size).setPoolName(poolName) + .setAvailableIdsHolder(availableIdsHolder) + .setReleasedIdsHolder(releasedIdsHolder).build(); + } + + protected static AvailableIdsHolder createAvailableIdsHolder(long low, long high, long cursor) { + AvailableIdsHolder availableIdsHolder = new AvailableIdsHolderBuilder() + .setStart(low).setEnd(high).setCursor(cursor).build(); + return availableIdsHolder; + } + + protected static ReleasedIdsHolder createReleasedIdsHolder(long availableIdCount, long delayTime) { + ReleasedIdsHolder releasedIdsHolder = new ReleasedIdsHolderBuilder() + .setAvailableIdCount(availableIdCount) + .setDelayedTimeSec(delayTime).build(); + return releasedIdsHolder; + } + + protected static InstanceIdentifier getIdPoolInstance(String poolName) { + InstanceIdentifier.InstanceIdentifierBuilder idPoolBuilder = InstanceIdentifier + .builder(IdPools.class).child(IdPool.class, + new IdPoolKey(poolName)); + InstanceIdentifier id = idPoolBuilder.build(); + return id; + } + + protected static InstanceIdentifier getReleasedIdsHolderInstance(String poolName) { + InstanceIdentifier.InstanceIdentifierBuilder releasedIdsHolder = InstanceIdentifier + .builder(IdPools.class).child(IdPool.class, + new IdPoolKey(poolName)).child(ReleasedIdsHolder.class); + InstanceIdentifier releasedIds = releasedIdsHolder.build(); + return releasedIds; + } + + /** + * Changes made to releasedIds are not persisted in the datastore. + * @param releasedIds + * @return + */ + protected static long getIdFromReleaseIdsIfAvailable(ReleasedIdsHolderBuilder releasedIds) { + List delayedIdEntries = releasedIds.getDelayedIdEntries(); + long newIdValue = -1; + if (delayedIdEntries != null && !delayedIdEntries.isEmpty()) { + processDelayList(releasedIds); + if (releasedIds.getAvailableIdCount() > 0) { + DelayedIdEntries delayedIdEntry= delayedIdEntries.get(0); + newIdValue = delayedIdEntry.getId(); + delayedIdEntries.remove(delayedIdEntry); + releasedIds.setDelayedIdEntries(delayedIdEntries); + releasedIds.setAvailableIdCount(releasedIds.getAvailableIdCount() - 1); + } + } + return newIdValue; + } + + /** + * Changes made to availableIds are not persisted to datastore. + * @param availableIds + * @return + */ + protected static long getIdFromAvailableIds(AvailableIdsHolderBuilder availableIds) { + long newIdValue = -1; + if (availableIds != null && isIdAvailable(availableIds)) { + newIdValue = availableIds.getCursor() + 1; + availableIds.setCursor(newIdValue); + } + return newIdValue; + } + + protected static boolean isIdAvailable(AvailableIdsHolderBuilder availableIds) { + if (availableIds.getCursor() != null && availableIds.getEnd() != null) + return availableIds.getCursor() < availableIds.getEnd(); + return false; + } + + protected static String getLocalPoolName(String poolName) { + return (poolName + "." + BLADE_ID); + } + + protected static IdPool createLocalIdPool(String localPoolName, IdPool parentIdPool) { + ReleasedIdsHolder releasedIdsHolder = createReleasedIdsHolder(DEFAULT_AVAILABLE_ID_COUNT, DEFAULT_DELAY_TIME); + return new IdPoolBuilder().setKey(new IdPoolKey(localPoolName)) + .setPoolName(localPoolName) + .setParentPoolName(parentIdPool.getPoolName()) + .setBlockSize(parentIdPool.getBlockSize()) + .setReleasedIdsHolder(releasedIdsHolder).build(); + } + + protected static ChildPools createChildPool(String childPoolName) { + return new ChildPoolsBuilder().setKey(new ChildPoolsKey(childPoolName)).setChildPoolName(childPoolName).setLastAccessTime(System.currentTimeMillis() / 1000).build(); + } + + protected static AvailableIdsHolderBuilder getAvailableIdsHolderBuilder(IdPool pool) { + AvailableIdsHolder availableIds = pool.getAvailableIdsHolder(); + if (availableIds != null ) + return new AvailableIdsHolderBuilder(availableIds); + return new AvailableIdsHolderBuilder(); + } + + protected static ReleasedIdsHolderBuilder getReleaseIdsHolderBuilder(IdPool pool) { + ReleasedIdsHolder releasedIds = pool.getReleasedIdsHolder(); + if (releasedIds != null) + return new ReleasedIdsHolderBuilder(releasedIds); + return new ReleasedIdsHolderBuilder(); + } + + /** + * Changes made to releaseIds are not persisted to the Datastore. Method invoking should ensure that releaseIds gets persisted. + * @param releasedIds + */ + protected static void processDelayList(ReleasedIdsHolderBuilder releasedIds) { + List delayedIdEntries = releasedIds.getDelayedIdEntries(); + if (delayedIdEntries == null) + return; + long availableIdCount = releasedIds.getAvailableIdCount() == null ? 0 : releasedIds.getAvailableIdCount(); + int index = (int) availableIdCount; + long currentTimeSec = System.currentTimeMillis() / 1000; + DelayedIdEntry delayedIdEntry; + while (index < delayedIdEntries.size()) { + delayedIdEntry = delayedIdEntries.get(index); + if (delayedIdEntry.getReadyTimeSec() > currentTimeSec) { + break; + } + availableIdCount++; + index++; + } + releasedIds.setAvailableIdCount(availableIdCount); + } + + /** + * Changes made to the parameters passed are not persisted to the Datastore. Method invoking should ensure that these gets persisted. + * @param releasedIdsChild + * @param releasedIdsParent + * @param idCountToBeFreed + */ + protected static void freeExcessAvailableIds(ReleasedIdsHolderBuilder releasedIdsChild, ReleasedIdsHolderBuilder releasedIdsParent, int idCountToBeFreed) { + List existingDelayedIdEntriesInParent = releasedIdsParent.getDelayedIdEntries(); + List delayedIdEntriesChild = releasedIdsChild.getDelayedIdEntries(); + long availableIdCountParent = releasedIdsParent.getAvailableIdCount(); + long availableIdCountChild = releasedIdsChild.getAvailableIdCount(); + if (existingDelayedIdEntriesInParent == null) { + existingDelayedIdEntriesInParent = new LinkedList<>(); + } + idCountToBeFreed = Math.min(idCountToBeFreed, delayedIdEntriesChild.size()); + for (int index = 0; index < idCountToBeFreed; index++) { + existingDelayedIdEntriesInParent.add(delayedIdEntriesChild.get(0)); + delayedIdEntriesChild.remove(0); + } + releasedIdsChild.setDelayedIdEntries(delayedIdEntriesChild).setAvailableIdCount(availableIdCountChild - idCountToBeFreed); + releasedIdsParent.setDelayedIdEntries(existingDelayedIdEntriesInParent).setAvailableIdCount(availableIdCountParent + idCountToBeFreed); + } + + protected static InstanceIdentifier getIdEntriesInstanceIdentifier(String poolName, String idKey) { + InstanceIdentifier idEntries = InstanceIdentifier + .builder(IdPools.class).child(IdPool.class, + new IdPoolKey(poolName)).child(IdEntries.class, new IdEntriesKey(idKey)).build(); + return idEntries; + } + + protected static InstanceIdentifier getChildPoolsInstanceIdentifier(String poolName, String localPoolName) { + InstanceIdentifier childPools = InstanceIdentifier + .builder(IdPools.class) + .child(IdPool.class, new IdPoolKey(poolName)) + .child(ChildPools.class, new ChildPoolsKey(localPoolName)).build(); + return childPools; + } + + protected static long computeBlockSize(long low, long high) { + long blockSize; + + long diff = high - low; + if (diff > DEFAULT_BLOCK_SIZE_DIFF) { + blockSize = diff / DEFAULT_BLOCK_SIZE_DIFF; + } else { + blockSize = 1; + } + return blockSize; + } + + public static long getAvailableIdsCount(AvailableIdsHolderBuilder availableIds) { + if(availableIds != null && isIdAvailable(availableIds)) { + return availableIds.getEnd() - availableIds.getCursor(); + } + return 0; + } + + public static void lockPool(LockManagerService lockManager, String poolName) { + LockInput input = new LockInputBuilder().setLockName(poolName).build(); + Future> result = lockManager.lock(input); + try { + if ((result != null) && (result.get().isSuccessful())) { + LOGGER.debug("Acquired lock {}", poolName); + } else { + throw new RuntimeException(String.format("Unable to getLock for pool %s", poolName)); + } + } catch (InterruptedException | ExecutionException e) { + LOGGER.error("Unable to getLock for pool {}", poolName); + throw new RuntimeException(String.format("Unable to getLock for pool %s", poolName), e.getCause()); + } + } + + public static void unlockPool(LockManagerService lockManager, String poolName) { + UnlockInput input = new UnlockInputBuilder().setLockName(poolName).build(); + Future> result = lockManager.unlock(input); + try { + if ((result != null) && (result.get().isSuccessful())) { + LOGGER.debug("Unlocked {}", poolName); + } else { + LOGGER.debug("Unable to unlock pool {}", poolName); + } + } catch (InterruptedException | ExecutionException e) { + LOGGER.error("Unable to unlock for pool {}", poolName); + throw new RuntimeException(String.format("Unable to unlock pool %s", poolName), e.getCause()); + } + } +} \ No newline at end of file diff --git a/idmanager/idmanager-impl/src/test/java/org/opendaylight/idmanager/test/IdManagerTest.java b/idmanager/idmanager-impl/src/test/java/org/opendaylight/idmanager/test/IdManagerTest.java index 7002c7b0..181cc499 100644 --- a/idmanager/idmanager-impl/src/test/java/org/opendaylight/idmanager/test/IdManagerTest.java +++ b/idmanager/idmanager-impl/src/test/java/org/opendaylight/idmanager/test/IdManagerTest.java @@ -1,146 +1,434 @@ package org.opendaylight.idmanager.test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.when; + +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Future; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import com.google.common.base.Optional; -import com.google.common.util.concurrent.FutureCallback; -import com.google.common.util.concurrent.Futures; 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.idmanager.IdManager; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.*; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPool; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPoolBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPoolKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.id.pool.GeneratedIds; +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; +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.DeleteIdPoolInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.DeleteIdPoolInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools; +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.idmanager.rev150403.id.pools.IdPool; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolderBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPools; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPoolsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPoolsKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntries; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntriesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntriesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolderBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntries; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntriesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.UnlockInput; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.math.BigInteger; -import java.util.*; -import java.util.concurrent.Future; + +import com.google.common.base.Optional; +import com.google.common.net.InetAddresses; +import com.google.common.util.concurrent.Futures; @RunWith(MockitoJUnitRunner.class) public class IdManagerTest { private static final Logger LOG = LoggerFactory.getLogger(IdManagerTest.class); - Map,DataObject> written = new HashMap<>(); - Map,DataObject> updated = new HashMap<>(); + private static int BLADE_ID; + static { + String hostName; + try { + hostName = InetAddress.getLocalHost().getHostName(); + BLADE_ID = InetAddresses.coerceToInteger(InetAddress.getLocalHost()); + if (hostName.indexOf("-") > 0) { + BLADE_ID = new Integer(hostName.split("-")[1].toString()).intValue(); + } else { + LOG.error("Host name {} is not matching with the condition!! PL-X is expected", hostName); + } + } catch (Exception e) { + LOG.error("IdManager - Exception - {}", e.getMessage()); + } + } + + Map,DataObject> configDataStore = new HashMap<>(); @Mock DataBroker dataBroker; @Mock ReadOnlyTransaction mockReadTx; @Mock WriteTransaction mockWriteTx; - CreateIdPoolInput createPoolTest; - GetUniqueIdInput getIdInputTest; + @Mock LockManagerService lockManager; + Future> rpcResult; IdManager idManager; - IdPool idPoolTest; + IdPool globalIdPool; InstanceIdentifier identifier; + InstanceIdentifier childIdentifier; + InstanceIdentifier childPoolIdentifier; + String globalPoolName = "test-pool"; + String localPoolName = new StringBuilder(globalPoolName).append(".").append(BLADE_ID).toString(); + String idKey = "test-key1"; + int idStart = 100; + int idEnd = 200; + int blockSize = 2; + String idKey2 = "test-key2"; + int idValue = 25; @Before public void setUp() throws Exception { - idManager = new IdManager(dataBroker) { - protected void asyncWrite(LogicalDatastoreType datastoreType, - InstanceIdentifier path, T data, FutureCallback callback) { - written.put(path, data); - } - protected void asyncUpdate(LogicalDatastoreType datastoreType, - InstanceIdentifier path, T data, FutureCallback callback) { - updated.put(path, data); - } - - }; + idManager = new IdManager(dataBroker); + idManager.setLockManager(lockManager); setupMocks(); } private void setupMocks() { - createPoolTest = buildCreateIdPool("vpn", 100, 100); - getIdInputTest = buildUniqueId("vpn", "vpn1"); - idPoolTest = buildIdPool("vpn", 100, 100); - identifier = buildInstanceIdentifier("vpn"); + globalIdPool = buildGlobalIdPool(globalPoolName, idStart, idEnd, blockSize, buildChildPool(localPoolName)).build(); + identifier = buildInstanceIdentifier(globalPoolName); + childIdentifier = buildInstanceIdentifier(localPoolName); + childPoolIdentifier = buildChildPoolInstanceIdentifier(globalPoolName, localPoolName); when(dataBroker.newReadOnlyTransaction()).thenReturn(mockReadTx); when(dataBroker.newWriteOnlyTransaction()).thenReturn(mockWriteTx); + when(lockManager.lock(any(LockInput.class))).thenReturn(Futures.immediateFuture(RpcResultBuilder.success().build())); + when(lockManager.unlock(any(UnlockInput.class))).thenReturn(Futures.immediateFuture(RpcResultBuilder.success().build())); + doReturn(Futures.immediateCheckedFuture(null)).when(mockWriteTx).submit(); + doReturn(Futures.immediateCheckedFuture(null)).when(mockReadTx).read(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class)); } @Test - public void testCreateIdPool() + public void testCreateIdPool() throws Exception { + CreateIdPoolInput createPoolTest = buildCreateIdPool(globalPoolName, idStart, idEnd); doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read( - LogicalDatastoreType.OPERATIONAL, identifier); - + LogicalDatastoreType.CONFIGURATION, identifier); + doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read( + LogicalDatastoreType.CONFIGURATION, childIdentifier); Future> result = idManager.createIdPool(createPoolTest); - Collection idPoolVal = new ArrayList< >(); - idPoolVal = written.values(); - assertEquals(1,written.size()); - for (DataObject poolData: idPoolVal) { - IdPool pool = null; - if (poolData instanceof IdPool) { - pool = (IdPool) poolData; - assertEquals(createPoolTest.getPoolName(), pool.getPoolName()); - assertEquals(createPoolTest.getIdStart(), pool.getIdStart()); - assertEquals(createPoolTest.getPoolSize(), pool.getPoolSize()); - } - } + DataObject dataObject; + IdPool pool; + assertTrue(result.get().isSuccessful()); + assertEquals(0,configDataStore.size()); + dataObject = configDataStore.get(childIdentifier); + if (dataObject instanceof IdPool) { + pool = (IdPool) dataObject; + assertEquals(localPoolName, pool.getPoolName()); + assertEquals(createPoolTest.getPoolName(), pool.getParentPoolName()); + assertEquals(null, pool.getAvailableIdsHolder()); + assertEquals(30, pool.getReleasedIdsHolder().getDelayedTimeSec().longValue()); + assertEquals(0, pool.getReleasedIdsHolder().getAvailableIdCount().longValue()); + assertEquals(blockSize, pool.getBlockSize().longValue()); + } + dataObject = configDataStore.get(identifier); + if (dataObject instanceof IdPool) { + pool = (IdPool) dataObject; + assertEquals(createPoolTest.getPoolName(), pool.getPoolName()); + assertEquals(0, pool.getReleasedIdsHolder().getDelayedTimeSec().longValue()); + assertEquals(0, pool.getReleasedIdsHolder().getAvailableIdCount().longValue()); + assertEquals(createPoolTest.getLow(), pool.getAvailableIdsHolder().getStart()); + assertEquals(createPoolTest.getHigh(), pool.getAvailableIdsHolder().getEnd()); + assertEquals(createPoolTest.getLow() - 1, pool.getAvailableIdsHolder().getCursor().intValue()); + assertEquals(blockSize, pool.getBlockSize().longValue()); + } + dataObject = configDataStore.get(childPoolIdentifier); + if (dataObject instanceof ChildPools) { + ChildPools childPool = (ChildPools) dataObject; + assertEquals(localPoolName, childPool.getChildPoolName()); + } } @Test - public void testUniqueId() + public void testAllocateId() throws Exception { - Optional expected = Optional.of(idPoolTest); + AllocateIdInput allocateIdInput = buildAllocateId(globalPoolName, idKey); + Optional expected = Optional.of(globalIdPool); + List idEntries = new ArrayList(); + idEntries.add(buildIdEntry(idKey2, idValue)); + Optional expectedLocalPool = Optional.of(buildLocalIdPool(blockSize, localPoolName, globalPoolName).setIdEntries(idEntries).build()); doReturn(Futures.immediateCheckedFuture(expected)).when(mockReadTx).read( - LogicalDatastoreType.OPERATIONAL, identifier); - - idManager.getUniqueId(getIdInputTest); - Collection idPoolVal = new ArrayList< >(); - idPoolVal = updated.values(); - assertEquals(1,updated.size()); - for (DataObject poolData: idPoolVal) { - IdPool pool = null; - if (poolData instanceof IdPool) { - pool = (IdPool) poolData; - assertEquals(getIdInputTest.getPoolName(), pool.getPoolName()); - List genIds = pool.getGeneratedIds(); - assertEquals(1,genIds.size()); - } - } + LogicalDatastoreType.CONFIGURATION, identifier); + doReturn(Futures.immediateCheckedFuture(expectedLocalPool)).when(mockReadTx).read( + LogicalDatastoreType.CONFIGURATION, childIdentifier); + InstanceIdentifier idEntriesIdentifier = buildIdEntriesIdentifier(idKey); + doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read( + LogicalDatastoreType.CONFIGURATION, idEntriesIdentifier); + InstanceIdentifier availableIdsIdentifier = buildAvailbaleIdsIdentifier(globalPoolName); + + Future> result = idManager.allocateId(allocateIdInput); + assertTrue(result.get().isSuccessful()); + assertEquals(0,configDataStore.size()); + DataObject dataObject = configDataStore.get(childIdentifier); + if (dataObject instanceof IdPool) { + IdPool pool = (IdPool) dataObject; + assertEquals(localPoolName, pool.getPoolName()); + assertEquals(idStart, pool.getAvailableIdsHolder().getStart().intValue()); + assertEquals(idStart + blockSize - 1 , pool.getAvailableIdsHolder().getEnd().intValue()); + assertEquals(idStart, pool.getAvailableIdsHolder().getCursor().intValue()); + assertEquals(2, pool.getIdEntries().size()); + } + dataObject = configDataStore.get(availableIdsIdentifier); + if (dataObject instanceof AvailableIdsHolder) { + AvailableIdsHolder availableIds = (AvailableIdsHolder) dataObject; + assertEquals(idEnd, availableIds.getEnd().intValue()); + assertEquals(idStart, availableIds.getStart().intValue()); + assertEquals(idStart + blockSize - 1, availableIds.getCursor().intValue()); + } + } + + @Test + public void testReleaseId() throws Exception { + ReleaseIdInput releaseIdInput = createReleaseIdInput(globalPoolName, idKey); + List idEntries = new ArrayList(); + idEntries.add(buildIdEntry(idKey, idValue)); + Optional expectedLocalPool = Optional.of(buildLocalIdPool(blockSize, localPoolName, globalPoolName).setIdEntries(idEntries).build()); + doReturn(Futures.immediateCheckedFuture(expectedLocalPool)).when(mockReadTx).read( + LogicalDatastoreType.CONFIGURATION, childIdentifier); + InstanceIdentifier idEntriesIdentifier = buildIdEntriesIdentifier(idKey); + Optional expectedIdEntry = Optional.of(buildIdEntry(idKey, idValue)); + doReturn(Futures.immediateCheckedFuture(expectedIdEntry)).when(mockReadTx).read( + LogicalDatastoreType.CONFIGURATION, idEntriesIdentifier); + Future> result = idManager.releaseId(releaseIdInput); + assertTrue(result.get().isSuccessful()); + assertEquals(0, configDataStore.size()); + DataObject idPoolVal = configDataStore.get(childIdentifier); + if (idPoolVal instanceof IdPool) { + IdPool pool = (IdPool) idPoolVal; + assertEquals(0, pool.getIdEntries().size()); + assertEquals(0, pool.getReleasedIdsHolder().getAvailableIdCount().intValue()); + assertEquals(idValue, pool.getReleasedIdsHolder().getDelayedIdEntries().get(0).getId().intValue()); + } + } + + @Test + public void testCleanupReleasedIds() throws Exception { + AllocateIdInput allocateIdInput = buildAllocateId(globalPoolName, idKey2); + Optional expected = Optional.of(createReleasedIdsHolder(0, null, 0)); + long[] excessIds = new long[] { 1, 2, 3, 4, 5 }; + List idEntries = new ArrayList(); + idEntries.add(buildIdEntry(idKey2, idValue)); + ReleasedIdsHolder excessReleasedIds = createReleasedIdsHolder(0, buildDelayedIdEntries(excessIds), (long) 30); + Optional expectedLocalPool = Optional.of(buildLocalIdPool(blockSize, localPoolName, globalPoolName) + .setIdEntries(idEntries).setReleasedIdsHolder(excessReleasedIds) + .build()); + InstanceIdentifier releaseIdsIdentifier = buildReleaseIdsIdentifier(globalPoolName); + doReturn(Futures.immediateCheckedFuture(expected)).when(mockReadTx) + .read(LogicalDatastoreType.CONFIGURATION, releaseIdsIdentifier); + doReturn(Futures.immediateCheckedFuture(expectedLocalPool)).when( + mockReadTx).read(LogicalDatastoreType.CONFIGURATION, + childIdentifier); + InstanceIdentifier idEntriesIdentifier = buildIdEntriesIdentifier(idKey2); + doReturn(Futures.immediateCheckedFuture(Optional.absent())).when( + mockReadTx).read(LogicalDatastoreType.CONFIGURATION, + idEntriesIdentifier); + + Future> result = idManager.allocateId(allocateIdInput); + assertTrue(result.get().isSuccessful()); + assertEquals(0, configDataStore.size()); + DataObject dataObject = configDataStore.get(childIdentifier); + if (dataObject instanceof IdPool) { + IdPool pool = (IdPool) dataObject; + assertEquals(localPoolName, pool.getPoolName()); + assertEquals(excessIds.length - 3, pool.getReleasedIdsHolder().getAvailableIdCount().intValue()); + assertEquals(2, pool.getIdEntries().size()); + } + dataObject = configDataStore.get(releaseIdsIdentifier); + if (dataObject instanceof ReleasedIdsHolder) { + ReleasedIdsHolder releasedIds = (ReleasedIdsHolder) dataObject; + assertEquals(2, releasedIds.getAvailableIdCount().intValue()); + assertEquals(2, releasedIds.getDelayedIdEntries().size()); + } + } + + @Test + public void testAllocateIdBlockFromReleasedIds() throws Exception { + AllocateIdInput allocateIdInput = buildAllocateId(globalPoolName, globalPoolName); + List delayedIdEntries = buildDelayedIdEntries(new long[] {1, 2, 3}); + ReleasedIdsHolder expectedReleasedIds = createReleasedIdsHolder(3, delayedIdEntries , 0); + IdPool globalIdPool = buildGlobalIdPool(globalPoolName, idStart, idEnd, blockSize, buildChildPool(localPoolName)).setReleasedIdsHolder(expectedReleasedIds).build(); + Optional expected = Optional.of(globalIdPool); + Optional expectedLocalPool = Optional.of(buildLocalIdPool(blockSize, localPoolName, globalPoolName).build()); + doReturn(Futures.immediateCheckedFuture(expected)).when(mockReadTx).read( + LogicalDatastoreType.CONFIGURATION, identifier); + doReturn(Futures.immediateCheckedFuture(expectedLocalPool)).when(mockReadTx).read( + LogicalDatastoreType.CONFIGURATION, childIdentifier); + InstanceIdentifier idEntriesIdentifier = buildIdEntriesIdentifier(globalPoolName); + doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read( + LogicalDatastoreType.CONFIGURATION, idEntriesIdentifier); + InstanceIdentifier releaseIdsIdentifier = buildReleaseIdsIdentifier(globalPoolName); + + Future> result = idManager.allocateId(allocateIdInput); + assertTrue(result.get().isSuccessful()); + assertEquals(0,configDataStore.size()); + DataObject dataObject = configDataStore.get(childIdentifier); + if (dataObject instanceof IdPool) { + IdPool pool = (IdPool) dataObject; + assertEquals(localPoolName, pool.getPoolName()); + assertEquals(1, pool.getReleasedIdsHolder().getDelayedIdEntries().size()); + assertEquals(1, pool.getIdEntries().size()); + assertEquals(1, pool.getReleasedIdsHolder().getAvailableIdCount().intValue()); + } + dataObject = configDataStore.get(releaseIdsIdentifier); + if (dataObject instanceof ReleasedIdsHolder) { + ReleasedIdsHolder releasedIds = (ReleasedIdsHolder) dataObject; + assertEquals(1, releasedIds.getAvailableIdCount().intValue()); + assertEquals(1, releasedIds.getDelayedIdEntries().size()); + } + } + + @Test + public void testDeletePool() throws Exception { + IdPool globalIdPool = buildGlobalIdPool(globalPoolName, idStart, idEnd, blockSize, buildChildPool(localPoolName)).build(); + Optional expected = Optional.of(globalIdPool); + Optional expectedLocalPool = Optional.of(buildLocalIdPool(blockSize, localPoolName, globalPoolName).build()); + doReturn(Futures.immediateCheckedFuture(expected)).when(mockReadTx).read( + LogicalDatastoreType.CONFIGURATION, identifier); + doReturn(Futures.immediateCheckedFuture(expectedLocalPool)).when(mockReadTx).read( + LogicalDatastoreType.CONFIGURATION, childIdentifier); + DeleteIdPoolInput deleteIdPoolInput = createDeleteIdPoolInput(globalPoolName); + configDataStore.put(childIdentifier, null); + configDataStore.put(identifier, null); + Future> result = idManager.deleteIdPool(deleteIdPoolInput); + assertTrue(result.get().isSuccessful()); + assertEquals(2, configDataStore.size()); + } + + private InstanceIdentifier buildReleaseIdsIdentifier( + String poolName) { + InstanceIdentifier releasedIds = InstanceIdentifier + .builder(IdPools.class).child(IdPool.class, + new IdPoolKey(poolName)).child(ReleasedIdsHolder.class).build(); + return releasedIds; + } + + private InstanceIdentifier buildAvailbaleIdsIdentifier( + String poolName) { + InstanceIdentifier availableIds = InstanceIdentifier + .builder(IdPools.class).child(IdPool.class, + new IdPoolKey(poolName)).child(AvailableIdsHolder.class).build(); + return availableIds; + } + + private InstanceIdentifier buildChildPoolInstanceIdentifier(String poolName, String childPoolName) { + InstanceIdentifier childPool = InstanceIdentifier + .builder(IdPools.class).child(IdPool.class, + new IdPoolKey(poolName)).child(ChildPools.class, new ChildPoolsKey(childPoolName)).build(); + return childPool; + } + + private ReleaseIdInput createReleaseIdInput(String poolName, String idKey) { + return new ReleaseIdInputBuilder().setIdKey(idKey).setPoolName(poolName).build(); } - private CreateIdPoolInput buildCreateIdPool(String poolName, long idStart, long poolSize) { + private IdEntries buildIdEntry(String idKey, long idValue) { + return new IdEntriesBuilder().setIdKey(idKey).setIdValue(idValue).build(); + } + + private InstanceIdentifier buildIdEntriesIdentifier(String idKey) { + InstanceIdentifier.InstanceIdentifierBuilder idEntriesBuilder = childIdentifier + .builder().child(IdEntries.class, new IdEntriesKey(idKey)); + InstanceIdentifier idEntry = idEntriesBuilder.build(); + return idEntry; + } + + private CreateIdPoolInput buildCreateIdPool(String poolName, long low, long high) { CreateIdPoolInput createPool = new CreateIdPoolInputBuilder().setPoolName(poolName) - .setIdStart(idStart) - .setPoolSize(BigInteger.valueOf(poolSize)) + .setLow(low) + .setHigh(high) .build(); return createPool; } - private IdPool buildIdPool(String poolName, long idStart, long poolSize) { - IdPool idPool = new IdPoolBuilder().setPoolName(poolName) - .setIdStart(idStart) - .setPoolSize(BigInteger.valueOf(poolSize)) - .build(); - return idPool; + private IdPoolBuilder buildGlobalIdPool(String poolName, long idStart, long poolSize, int blockSize, List childPools) { + AvailableIdsHolder availableIdsHolder = createAvailableIdsHolder(idStart, poolSize, idStart - 1); + ReleasedIdsHolder releasedIdsHolder = createReleasedIdsHolder(0, null, 0); + return new IdPoolBuilder().setKey(new IdPoolKey(poolName)) + .setPoolName(poolName) + .setBlockSize(blockSize) + .setChildPools(childPools) + .setAvailableIdsHolder(availableIdsHolder) + .setReleasedIdsHolder(releasedIdsHolder); } - private GetUniqueIdInput buildUniqueId(String poolName, String idKey) { - GetUniqueIdInput getIdInput = new GetUniqueIdInputBuilder().setPoolName(poolName) + private IdPoolBuilder buildLocalIdPool(int blockSize, String localPoolName, String parentPoolName) { + ReleasedIdsHolder releasedIdsHolder = createReleasedIdsHolder(0, null, (long) 30); + return new IdPoolBuilder().setBlockSize(blockSize) + .setKey(new IdPoolKey(localPoolName)) + .setParentPoolName(parentPoolName) + .setReleasedIdsHolder(releasedIdsHolder); + } + + private AllocateIdInput buildAllocateId(String poolName, String idKey) { + AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName) .setIdKey(idKey).build(); return getIdInput; } - private InstanceIdentifier buildInstanceIdentifier(String poolName){ + private InstanceIdentifier buildInstanceIdentifier(String poolName) { InstanceIdentifier.InstanceIdentifierBuilder idBuilder = - InstanceIdentifier.builder(Pools.class).child(IdPool.class, new IdPoolKey(poolName)); + InstanceIdentifier.builder(IdPools.class).child(IdPool.class, new IdPoolKey(poolName)); InstanceIdentifier id = idBuilder.build(); return id; } -} + private AvailableIdsHolder createAvailableIdsHolder(long low, long high, long cursor) { + AvailableIdsHolder availableIdsHolder = new AvailableIdsHolderBuilder() + .setStart(low).setEnd(high).setCursor(cursor).build(); + return availableIdsHolder; + } + + private ReleasedIdsHolder createReleasedIdsHolder(long availableIdCount, List delayedIdEntries, long delayTime) { + ReleasedIdsHolder releasedIdsHolder = new ReleasedIdsHolderBuilder() + .setAvailableIdCount(availableIdCount) + .setDelayedIdEntries(delayedIdEntries) + .setDelayedTimeSec(delayTime).build(); + return releasedIdsHolder; + } + + private DeleteIdPoolInput createDeleteIdPoolInput(String poolName) { + return new DeleteIdPoolInputBuilder().setPoolName(poolName).build(); + } + + private List buildDelayedIdEntries(long[] idValues) { + List delayedIdEntriesList = new ArrayList(); + for (long idValue : idValues) { + DelayedIdEntries delayedIdEntries = new DelayedIdEntriesBuilder().setId(idValue).setReadyTimeSec(0L).build(); + delayedIdEntriesList.add(delayedIdEntries); + } + return delayedIdEntriesList; + } + + private List buildChildPool(String childPoolName) { + ChildPools childPools = new ChildPoolsBuilder().setChildPoolName(childPoolName).build(); + List childPoolsList = new ArrayList(); + childPoolsList.add(childPools); + return childPoolsList; + } +} \ No newline at end of file diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmConstants.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmConstants.java index bcaf8ef2..351a37a5 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmConstants.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmConstants.java @@ -10,7 +10,8 @@ package org.opendaylight.vpnservice.interfacemgr; public class IfmConstants { public static final String IFM_IDPOOL_NAME = "interfaces"; - public static final long IFM_IDPOOL_START = 1L; + public static final long IFM_ID_POOL_START = 1L; + public static final long IFM_ID_POOL_END = 65535; public static final String IFM_IDPOOL_SIZE = "65535"; public static final String OF_URI_PREFIX = "openflow:"; public static final String OF_URI_SEPARATOR = ":"; diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmUtil.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmUtil.java index 400ebd24..ebfed475 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmUtil.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmUtil.java @@ -26,10 +26,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +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; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.Pools; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPool; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPoolKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools; +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.idmanager.rev150403.id.pools.IdPool; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; @@ -80,7 +85,7 @@ public class IfmUtil { public static InstanceIdentifier getPoolId(String poolName){ InstanceIdentifier.InstanceIdentifierBuilder idBuilder = - InstanceIdentifier.builder(Pools.class).child(IdPool.class, new IdPoolKey(poolName)); + InstanceIdentifier.builder(IdPools.class).child(IdPool.class, new IdPoolKey(poolName)); InstanceIdentifier id = idBuilder.build(); return id; } diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfacemgrProvider.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfacemgrProvider.java index b2003ff7..e886115f 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfacemgrProvider.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfacemgrProvider.java @@ -98,8 +98,8 @@ public class InterfacemgrProvider implements BindingAwareProvider, AutoCloseable private void createIdPool() { CreateIdPoolInput createPool = new CreateIdPoolInputBuilder() .setPoolName(IfmConstants.IFM_IDPOOL_NAME) - .setIdStart(IfmConstants.IFM_IDPOOL_START) - .setPoolSize(new BigInteger(IfmConstants.IFM_IDPOOL_SIZE)) + .setLow(IfmConstants.IFM_ID_POOL_START) + .setHigh(IfmConstants.IFM_ID_POOL_END) .build(); //TODO: Error handling Future> result = idManager.createIdPool(createPool); diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/commons/InterfaceManagerCommonUtils.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/commons/InterfaceManagerCommonUtils.java index 6b10cb0c..3456bf3e 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/commons/InterfaceManagerCommonUtils.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/commons/InterfaceManagerCommonUtils.java @@ -24,9 +24,6 @@ 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.vpnservice.idmanager.rev150403.GetUniqueIdInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdOutput; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; import org.slf4j.Logger; @@ -119,26 +116,6 @@ public class InterfaceManagerCommonUtils { return ifStateOptional.get(); } - public static Integer getUniqueId(IdManager idManager, String idKey) { - GetUniqueIdInput getIdInput = new GetUniqueIdInputBuilder() - .setPoolName(IfmConstants.IFM_LPORT_TAG_IDPOOL_NAME) - .setIdKey(idKey).build(); - - try { - Future> result = idManager. - getUniqueId(getIdInput); - RpcResult rpcResult = result.get(); - if(rpcResult.isSuccessful()) { - return rpcResult.getResult().getIdValue().intValue(); - } else { - LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors()); - } - } catch (NullPointerException | InterruptedException | ExecutionException e) { - LOG.warn("Exception when getting Unique Id",e); - } - return 0; - } - public static String getJobKey(String dpId, String portName) { String jobKey = ""; if (dpId != null && !"".equals(dpId)) { diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsVlanMemberConfigAddHelper.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsVlanMemberConfigAddHelper.java index e90a8f95..78f87f34 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsVlanMemberConfigAddHelper.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsVlanMemberConfigAddHelper.java @@ -12,6 +12,8 @@ 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.idmanager.IdManager; +import org.opendaylight.vpnservice.VpnUtil; +import org.opendaylight.vpnservice.interfacemgr.IfmConstants; import org.opendaylight.vpnservice.interfacemgr.IfmUtil; import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils; import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils; @@ -137,13 +139,16 @@ public class OvsVlanMemberConfigAddHelper { private static long createInterfaceChildEntry(DataBroker dataBroker, IdManager idManager, WriteTransaction t, InterfaceParentEntryKey interfaceParentEntryKey, String childInterface){ - long lportTag = InterfaceManagerCommonUtils.getUniqueId(idManager, childInterface); - InterfaceChildEntryKey interfaceChildEntryKey = new InterfaceChildEntryKey(childInterface); - InstanceIdentifier intfId = - InterfaceMetaUtils.getInterfaceChildEntryIdentifier(interfaceParentEntryKey, interfaceChildEntryKey); - InterfaceChildEntryBuilder entryBuilder = new InterfaceChildEntryBuilder().setKey(interfaceChildEntryKey) - .setChildInterface(childInterface); - t.put(LogicalDatastoreType.CONFIGURATION, intfId, entryBuilder.build(),true); - return lportTag; + + //TODO FIXME +// long lportTag = InterfaceManagerCommonUtils.getUniqueId(idManager, childInterface); +// InterfaceChildEntryKey interfaceChildEntryKey = new InterfaceChildEntryKey(childInterface); +// InstanceIdentifier intfId = +// InterfaceMetaUtils.getInterfaceChildEntryIdentifier(interfaceParentEntryKey, interfaceChildEntryKey); +// InterfaceChildEntryBuilder entryBuilder = new InterfaceChildEntryBuilder().setKey(interfaceChildEntryKey) +// .setChildInterface(childInterface); +// t.put(LogicalDatastoreType.CONFIGURATION, intfId, entryBuilder.build(),true); +// return lportTag; + return 0L; } } diff --git a/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/InterfaceManagerTestUtil.java b/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/InterfaceManagerTestUtil.java index 1bcba00d..e8e7e6f4 100644 --- a/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/InterfaceManagerTestUtil.java +++ b/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/InterfaceManagerTestUtil.java @@ -44,9 +44,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.Pools; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPool; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPoolKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntryBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntryKey; diff --git a/lockmanager/lockmanager-api/pom.xml b/lockmanager/lockmanager-api/pom.xml new file mode 100644 index 00000000..4b9fe8c7 --- /dev/null +++ b/lockmanager/lockmanager-api/pom.xml @@ -0,0 +1,72 @@ + + + + + org.opendaylight.vpnservice + binding-parent + 0.2.0-SNAPSHOT + ../../commons/binding-parent + + + 4.0.0 + org.opendaylight.vpnservice + lockmanager-api + ${vpnservices.version} + bundle + + + + org.opendaylight.yangtools + yang-binding + ${yangtools.version} + + + org.opendaylight.yangtools + yang-common + ${yangtools.version} + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + + org.opendaylight.yangtools + + + yang-maven-plugin + + + [0.7.1-SNAPSHOT,) + + + generate-sources + + + + + + + + + + + + + + diff --git a/lockmanager/lockmanager-api/src/main/yang/lock-manager.yang b/lockmanager/lockmanager-api/src/main/yang/lock-manager.yang new file mode 100644 index 00000000..4ac3049e --- /dev/null +++ b/lockmanager/lockmanager-api/src/main/yang/lock-manager.yang @@ -0,0 +1,71 @@ +module lock-manager { + namespace "urn:opendaylight:vpnservice:lockmanager"; + prefix lockmgr; + + revision "2015-08-19" { + description "YANG model describes methods that ensure locking while accessing the datastore"; + } + + typedef time-units { + type enumeration { + enum days; + enum hours; + enum microseconds; + enum milliseconds; + enum minutes; + enum nanoseconds; + enum seconds; + } + } + + container locks { + description "Holds the list of lock name and lock owner"; + list lock { + key "lock-name"; + leaf lock-name { + type string; + mandatory true; + } + leaf lock-owner { + type string; + mandatory true; + } + } + } + + rpc lock { + description "Method that checks if its locked already. If not adds the lock to the list of locks. Else tries until it acquires the lock"; + input { + leaf lock-name { + type string; + mandatory true; + } + } + } + + rpc try-lock { + description "Method that checks if its locked already. If not adds the lock to the list of locks. Else tries for the specified time"; + input { + leaf lock-name { + type string; + mandatory true; + } + leaf time { + type uint32; + } + leaf time-unit { + type time-units; + } + } + } + + rpc unlock { + description "Method that removes the lock from the list of locks"; + input { + leaf lock-name { + type string; + mandatory true; + } + } + } +} \ No newline at end of file diff --git a/lockmanager/lockmanager-impl/pom.xml b/lockmanager/lockmanager-impl/pom.xml new file mode 100644 index 00000000..915f6917 --- /dev/null +++ b/lockmanager/lockmanager-impl/pom.xml @@ -0,0 +1,84 @@ + + + + + + org.opendaylight.vpnservice + config-parent + 0.2.0-SNAPSHOT + ../../commons/config-parent + + + 4.0.0 + org.opendaylight.vpnservice + lockmanager-impl + ${vpnservices.version} + bundle + + + org.opendaylight.vpnservice + lockmanager-api + ${vpnservices.version} + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + + org.opendaylight.yangtools + + + yang-maven-plugin + + + [0.7.1-SNAPSHOT,) + + + generate-sources + + + + + + + + + org.jacoco + + jacoco-maven-plugin + + + [0.7.2.201409121644,) + + + prepare-agent + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lockmanager/lockmanager-impl/src/main/config/default-config.xml b/lockmanager/lockmanager-impl/src/main/config/default-config.xml new file mode 100644 index 00000000..fbf1b5b3 --- /dev/null +++ b/lockmanager/lockmanager-impl/src/main/config/default-config.xml @@ -0,0 +1,34 @@ + + + + + + urn:opendaylight:params:xml:ns:yang:lockmanager:impl?module=lockmanager-impl&revision=2015-08-19 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28 + + + + + + + prefix:lockmanager-impl + lockmanager-default + + binding:binding-broker-osgi-registry + binding-osgi-broker + + + binding:binding-rpc-registry + binding-rpc-broker + + + + + + diff --git a/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManager.java b/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManager.java new file mode 100644 index 00000000..28e548fd --- /dev/null +++ b/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManager.java @@ -0,0 +1,188 @@ +/* + * 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.lockmanager; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.TryLockInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.UnlockInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.locks.Lock; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; + +public class LockManager implements LockManagerService { + private static final Logger LOG = LoggerFactory.getLogger(LockManager.class); + + private static final int DEFAULT_RETRY_COUNT = 3; + private static final int DEFAULT_WAIT_TIME_IN_MILLIS = 1000; + + private final DataBroker broker; + + public LockManager(final DataBroker db) { + broker = db; + } + + @Override + public Future> lock(LockInput input) { + String lockName = input.getLockName(); + LOG.info("Locking {}" , lockName); + InstanceIdentifier lockInstanceIdentifier = LockManagerUtils.getLockInstanceIdentifier(lockName); + Lock lockData = LockManagerUtils.buildLockData(lockName); + try { + getLock(lockInstanceIdentifier, lockData); + RpcResultBuilder lockRpcBuilder = RpcResultBuilder.success(); + LOG.info("Acquired lock {}" , lockName); + return Futures.immediateFuture(lockRpcBuilder.build()); + } catch (InterruptedException e) { + RpcResultBuilder lockRpcBuilder = RpcResultBuilder.failed(); + LOG.info("Failed to get lock {}" , lockName); + return Futures.immediateFuture(lockRpcBuilder.build()); + } + } + + @Override + public Future> tryLock(TryLockInput input) { + String lockName = input.getLockName(); + LOG.info("Locking {}" , lockName); + long waitTime = input.getTime() == null ? DEFAULT_WAIT_TIME_IN_MILLIS * DEFAULT_RETRY_COUNT : input.getTime(); + TimeUnit timeUnit = (TimeUnit) (input.getTimeUnit() == null ? TimeUnit.MILLISECONDS: LockManagerUtils.convertToTimeUnit(input.getTimeUnit())); + waitTime = LockManagerUtils.convertToMillis(waitTime, timeUnit); + long retryCount = waitTime / DEFAULT_WAIT_TIME_IN_MILLIS; + InstanceIdentifier lockInstanceIdentifier = LockManagerUtils.getLockInstanceIdentifier(lockName); + Lock lockData = LockManagerUtils.buildLockData(lockName); + try { + if (getLock(lockInstanceIdentifier, lockData, retryCount)) { + RpcResultBuilder lockRpcBuilder = RpcResultBuilder.success(); + LOG.info("Acquired lock {}" , lockName); + return Futures.immediateFuture(lockRpcBuilder.build()); + } + RpcResultBuilder lockRpcBuilder = RpcResultBuilder.failed(); + LOG.info("Failed to get lock {}" , lockName); + return Futures.immediateFuture(lockRpcBuilder.build()); + } catch (Exception e) { + RpcResultBuilder lockRpcBuilder = RpcResultBuilder.failed(); + LOG.info("Failed to get lock {}" , lockName); + return Futures.immediateFuture(lockRpcBuilder.build()); + } + } + + @Override + public Future> unlock(UnlockInput input) { + String lockName = input.getLockName(); + LOG.info("Unlocking {}" , lockName); + InstanceIdentifier lockInstanceIdentifier = LockManagerUtils.getLockInstanceIdentifier(lockName); + unlock(lockName, lockInstanceIdentifier); + RpcResultBuilder lockRpcBuilder = RpcResultBuilder.success(); + return Futures.immediateFuture(lockRpcBuilder.build()); + } + + /** + * Try to acquire lock indefinitely until it is successful. + * @param lockInstanceIdentifier + * @param lockData + */ + private void getLock(final InstanceIdentifier lockInstanceIdentifier, final Lock lockData) throws InterruptedException { + try { + if (!readWriteLock(lockInstanceIdentifier, lockData)) { + LOG.debug("Already locked trying after {}", DEFAULT_WAIT_TIME_IN_MILLIS); + LockManagerUtils.sleep(DEFAULT_WAIT_TIME_IN_MILLIS); + getLock(lockInstanceIdentifier, lockData); + } + } catch (ExecutionException e) { + LOG.error("In getLock unable to get lock due to {}, trying again", e.getMessage()); + LockManagerUtils.sleep(DEFAULT_WAIT_TIME_IN_MILLIS); + getLock(lockInstanceIdentifier, lockData); + } + } + + /** + * Try to acquire lock for mentioned retryCount. Returns true if successfully acquired lock. + * @param lockInstanceIdentifier + * @param lockData + * @param retryCount + * @return + * @throws InterruptedException + */ + private boolean getLock(InstanceIdentifier lockInstanceIdentifier, + Lock lockData, long retryCount) throws InterruptedException { + if (retryCount < 0) { + return false; + } + try { + if (!readWriteLock(lockInstanceIdentifier, lockData)) { + LOG.debug("Already locked trying after {}, retry value {}", DEFAULT_WAIT_TIME_IN_MILLIS, retryCount); + LockManagerUtils.sleep(DEFAULT_WAIT_TIME_IN_MILLIS); + return getLock(lockInstanceIdentifier, lockData, retryCount - 1); + } + } catch (ExecutionException e) { + LOG.error("In getLock unable to get lock due to {}, trying again, retry value {}", e.getMessage(), retryCount); + LockManagerUtils.sleep(DEFAULT_WAIT_TIME_IN_MILLIS); + return getLock(lockInstanceIdentifier, lockData, retryCount - 1); + } + return true; + } + + /** + * Read and write the lock immediately if available. Returns true if successfully locked. + * @param lockInstanceIdentifier + * @param lockData + * @return + * @throws InterruptedException + * @throws ExecutionException + */ + private boolean readWriteLock (final InstanceIdentifier lockInstanceIdentifier, final Lock lockData) throws InterruptedException, ExecutionException { + ReadWriteTransaction tx = broker.newReadWriteTransaction(); + Optional result = Optional.absent(); + result = tx.read(LogicalDatastoreType.OPERATIONAL, lockInstanceIdentifier).get(); + if (!result.isPresent()) { + tx.put(LogicalDatastoreType.OPERATIONAL, lockInstanceIdentifier, lockData, true); + CheckedFuture futures = tx.submit(); + futures.get(); + return true; + } + if (result.get().getLockOwner() == Thread.currentThread().getName()) { + return true; + } + return false; + } + + private void unlock(final String lockName, final InstanceIdentifier lockInstanceIdentifier) { + ReadWriteTransaction tx = broker.newReadWriteTransaction(); + Optional result = Optional.absent(); + try { + result = tx.read(LogicalDatastoreType.OPERATIONAL, lockInstanceIdentifier).get(); + if (!result.isPresent()) { + LOG.info("{} is already unlocked", lockName); + return; + } + tx.delete(LogicalDatastoreType.OPERATIONAL, lockInstanceIdentifier); + CheckedFuture futures = tx.submit(); + futures.get(); + } catch (Exception e) { + LOG.error("In unlock unable to unlock due to {}", e.getMessage()); + } + } + + +} diff --git a/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManagerServiceProvider.java b/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManagerServiceProvider.java new file mode 100644 index 00000000..c90ba23e --- /dev/null +++ b/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManagerServiceProvider.java @@ -0,0 +1,56 @@ +/* + * 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.lockmanager; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext; +import org.opendaylight.controller.sal.binding.api.BindingAwareProvider; + +import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class LockManagerServiceProvider implements BindingAwareProvider, + AutoCloseable { + + private static final Logger LOG = LoggerFactory.getLogger(LockManagerServiceProvider.class); + private LockManager lockManager; + private RpcProviderRegistry rpcProviderRegistry; + + public RpcProviderRegistry getRpcProviderRegistry() { + return rpcProviderRegistry; + } + + public void setRpcProviderRegistry(RpcProviderRegistry rpcProviderRegistry) { + this.rpcProviderRegistry = rpcProviderRegistry; + } + + @Override + public void onSessionInitiated(ProviderContext session){ + LOG.info("LockManagerServiceProvider Session Initiated"); + try { + final DataBroker dataBroker = session.getSALService(DataBroker.class); + lockManager = new LockManager(dataBroker); + final BindingAwareBroker.RpcRegistration rpcRegistration = getRpcProviderRegistry().addRpcImplementation(LockManagerService.class, lockManager); + } catch (Exception e) { + LOG.error("Error initializing services", e); + } + } + + public LockManagerServiceProvider(RpcProviderRegistry rpcRegistry) { + this.rpcProviderRegistry = rpcRegistry; + } + + @Override + public void close() throws Exception { + } + } \ No newline at end of file diff --git a/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManagerUtils.java b/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManagerUtils.java new file mode 100644 index 00000000..e4b8a96f --- /dev/null +++ b/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManagerUtils.java @@ -0,0 +1,62 @@ +/* + * 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.lockmanager; + +import java.util.concurrent.TimeUnit; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.Locks; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.TimeUnits; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.locks.Lock; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.locks.LockBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.locks.LockKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class LockManagerUtils { + + public static long convertToMillis(long waitTime, TimeUnit timeUnit) { + return timeUnit.toMillis(waitTime); + } + + public static void sleep(long waitTime) { + try { + Thread.sleep(waitTime); + } catch (InterruptedException exception) { + } + } + + public static TimeUnit convertToTimeUnit(TimeUnits timeUnit) { + switch (timeUnit) { + case Days: + return TimeUnit.DAYS; + case Microseconds: + return TimeUnit.MICROSECONDS; + case Hours: + return TimeUnit.HOURS; + case Minutes: + return TimeUnit.MINUTES; + case Nanoseconds: + return TimeUnit.NANOSECONDS; + case Seconds: + return TimeUnit.SECONDS; + case Milliseconds: + default: + return TimeUnit.MILLISECONDS; + } + } + + public static InstanceIdentifier getLockInstanceIdentifier(String lockName) { + return InstanceIdentifier + .builder(Locks.class).child(Lock.class, + new LockKey(lockName)).build(); + } + + public static Lock buildLockData(String lockName) { + return new LockBuilder().setKey(new LockKey(lockName)).setLockName(lockName).setLockOwner(Thread.currentThread().getName()).build(); + } +} \ No newline at end of file diff --git a/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/lockmanager/impl/rev150819/LockManagerImplModule.java b/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/lockmanager/impl/rev150819/LockManagerImplModule.java new file mode 100644 index 00000000..8df2fca4 --- /dev/null +++ b/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/lockmanager/impl/rev150819/LockManagerImplModule.java @@ -0,0 +1,26 @@ +package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lockmanager.impl.rev150819; + +import org.opendaylight.lockmanager.LockManagerServiceProvider; + +public class LockManagerImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lockmanager.impl.rev150819.AbstractLockManagerImplModule { + public LockManagerImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public LockManagerImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lockmanager.impl.rev150819.LockManagerImplModule oldModule, java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void customValidation() { + // add custom validation form module attributes here. + } + + @Override + public java.lang.AutoCloseable createInstance() { + LockManagerServiceProvider provider = new LockManagerServiceProvider(getRpcRegistryDependency()); + getBrokerDependency().registerProvider(provider); + return provider; + } + +} diff --git a/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/lockmanager/impl/rev150819/LockManagerImplModuleFactory.java b/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/lockmanager/impl/rev150819/LockManagerImplModuleFactory.java new file mode 100644 index 00000000..12b3b60c --- /dev/null +++ b/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/lockmanager/impl/rev150819/LockManagerImplModuleFactory.java @@ -0,0 +1,13 @@ +/* +* Generated file +* +* Generated from: yang module name: lockmanager-impl yang module local name: lockmanager-impl +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Thu Aug 27 12:50:22 IST 2015 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lockmanager.impl.rev150819; +public class LockManagerImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lockmanager.impl.rev150819.AbstractLockManagerImplModuleFactory { + +} diff --git a/lockmanager/lockmanager-impl/src/main/yang/lockmanager-impl.yang b/lockmanager/lockmanager-impl/src/main/yang/lockmanager-impl.yang new file mode 100644 index 00000000..3178ba87 --- /dev/null +++ b/lockmanager/lockmanager-impl/src/main/yang/lockmanager-impl.yang @@ -0,0 +1,44 @@ +module lockmanager-impl { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:lockmanager:impl"; + prefix "lockmanager-impl"; + + import config { prefix config; revision-date 2013-04-05; } + import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;} + + description + "Service definition for lockmanager project"; + + revision "2015-08-19" { + description + "Initial revision"; + } + + identity lockmanager-impl { + base config:module-type; + config:java-name-prefix LockManagerImpl; + } + + augment "/config:modules/config:module/config:configuration" { + case lockmanager-impl { + when "/config:modules/config:module/config:type = 'lockmanager-impl'"; + container broker { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity md-sal-binding:binding-broker-osgi-registry; + } + } + } + container rpc-registry { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity md-sal-binding:binding-rpc-registry; + } + } + } + + } + } +} diff --git a/lockmanager/pom.xml b/lockmanager/pom.xml new file mode 100644 index 00000000..9bc8422c --- /dev/null +++ b/lockmanager/pom.xml @@ -0,0 +1,49 @@ + + + + + + org.opendaylight.odlparent + odlparent + 1.6.0-SNAPSHOT + + + + org.opendaylight.vpnservice + lockmanager-aggregator + 0.2.0-SNAPSHOT + lockmanager + pom + 4.0.0 + + 3.1.1 + + + lockmanager-api + lockmanager-impl + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.apache.maven.plugins + maven-install-plugin + + true + + + + + \ No newline at end of file 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 23b7b619..5ccaa576 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 @@ -14,6 +14,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; import java.util.concurrent.LinkedBlockingQueue; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCaseBuilder; @@ -63,10 +64,20 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.Tr import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder; 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 com.google.common.base.Joiner; +import com.google.common.base.Optional; import com.google.common.primitives.Bytes; import com.google.common.primitives.Ints; +import com.google.common.util.concurrent.CheckedFuture; public class MDSALUtil { @@ -76,6 +87,7 @@ public class MDSALUtil { private static final Instructions EMPTY_Instructions = new InstructionsBuilder().setInstruction( new ArrayList()).build(); private static final Match EMPTY_Matches = new MatchBuilder().build(); + private static final Logger logger = LoggerFactory.getLogger(MDSALUtil.class); public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, String flowId, int priority, String flowName, int idleTimeOut, int hardTimeOut, BigInteger cookie, List listMatchInfo, @@ -336,4 +348,74 @@ public class MDSALUtil { new WriteMetadataBuilder().setMetadata(metadata).setMetadataMask(mask).build()) .build()).setKey(new InstructionKey(instructionKey)).build(); } + + public static Optional read(LogicalDatastoreType datastoreType, + InstanceIdentifier path, DataBroker broker) { + + ReadOnlyTransaction tx = broker.newReadOnlyTransaction(); + + Optional result = Optional.absent(); + try { + result = tx.read(datastoreType, path).get(); + } catch (Exception e) { + logger.error("An error occured while reading data from the path {} with the exception {}", path, e); + } + return result; + } + + public static Optional read(DataBroker broker, + LogicalDatastoreType datastoreType, InstanceIdentifier path) { + + ReadOnlyTransaction tx = broker.newReadOnlyTransaction(); + + Optional result = Optional.absent(); + try { + result = tx.read(datastoreType, path).get(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + return result; + } + + public static void syncWrite(DataBroker broker, + LogicalDatastoreType datastoreType, InstanceIdentifier path, + T data) { + WriteTransaction tx = broker.newWriteOnlyTransaction(); + tx.put(datastoreType, path, data, true); + CheckedFuture futures = tx.submit(); + try { + futures.get(); + } catch (InterruptedException | ExecutionException e) { + logger.error("Error writing to datastore (path, data) : ({}, {})", path, data); + throw new RuntimeException(e.getMessage()); + } + } + + public static void syncUpdate(DataBroker broker, + LogicalDatastoreType datastoreType, InstanceIdentifier path, + T data) { + WriteTransaction tx = broker.newWriteOnlyTransaction(); + tx.merge(datastoreType, path, data, true); + CheckedFuture futures = tx.submit(); + try { + futures.get(); + } catch (InterruptedException | ExecutionException e) { + logger.error("Error writing to datastore (path, data) : ({}, {})", path, data); + throw new RuntimeException(e.getMessage()); + } + } + + public static void syncDelete(DataBroker broker, + LogicalDatastoreType datastoreType, InstanceIdentifier obj) { + WriteTransaction tx = broker.newWriteOnlyTransaction(); + tx.delete(datastoreType, obj); + CheckedFuture futures = tx.submit(); + try { + futures.get(); + } catch (InterruptedException | ExecutionException e) { + logger.error("Error deleting from datastore (path) : ({})", obj); + throw new RuntimeException(e.getMessage()); + } + } } diff --git a/nexthopmgr/nexthopmgr-impl/src/main/java/org/opendaylight/vpnservice/nexthopmgr/NexthopManager.java b/nexthopmgr/nexthopmgr-impl/src/main/java/org/opendaylight/vpnservice/nexthopmgr/NexthopManager.java index c0a99838..f44e8419 100644 --- a/nexthopmgr/nexthopmgr-impl/src/main/java/org/opendaylight/vpnservice/nexthopmgr/NexthopManager.java +++ b/nexthopmgr/nexthopmgr-impl/src/main/java/org/opendaylight/vpnservice/nexthopmgr/NexthopManager.java @@ -35,11 +35,14 @@ import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev14081 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstance1; +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; 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.GetUniqueIdOutput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService; +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.l3nexthop.rev150409.*; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.*; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.tunnelnexthops.*; @@ -106,20 +109,13 @@ public class NexthopManager implements L3nexthopService, AutoCloseable { protected void createNexthopPointerPool() { CreateIdPoolInput createPool = new CreateIdPoolInputBuilder() - .setPoolName("nextHopPointerPool") - .setIdStart(1L) - .setPoolSize(new BigInteger("65535")) - .build(); + .setPoolName("nextHopPointerPool") + .setLow(150000L) + .setHigh(175000L) + .build(); //TODO: Error handling Future> result = idManager.createIdPool(createPool); LOG.trace("NextHopPointerPool result : {}", result); -// try { -// LOG.info("Result2: {}",result.get()); -// } catch (InterruptedException | ExecutionException e) { -// // TODO Auto-generated catch block -// LOG.error("Error in result.get"); -// } - } @@ -146,15 +142,15 @@ public class NexthopManager implements L3nexthopService, AutoCloseable { return dpn; } - protected int createNextHopPointer(String nexthopKey) { - GetUniqueIdInput getIdInput = new GetUniqueIdInputBuilder() - .setPoolName("nextHopPointerPool").setIdKey(nexthopKey) - .build(); + protected long createNextHopPointer(String nexthopKey) { + AllocateIdInput getIdInput = new AllocateIdInputBuilder() + .setPoolName("nextHopPointerPool").setIdKey(nexthopKey) + .build(); //TODO: Proper error handling once IdManager code is complete try { - Future> result = idManager.getUniqueId(getIdInput); - RpcResult rpcResult = result.get(); - return rpcResult.getResult().getIdValue().intValue(); + Future> result = idManager.allocateId(getIdInput); + RpcResult rpcResult = result.get(); + return rpcResult.getResult().getIdValue(); } catch (NullPointerException | InterruptedException | ExecutionException e) { LOG.trace("",e); } @@ -163,7 +159,7 @@ public class NexthopManager implements L3nexthopService, AutoCloseable { public void createLocalNextHop(String ifName, String vpnName, String ipAddress, String macAddress) { String nhKey = new String("nexthop." + vpnName + ipAddress); - int groupId = createNextHopPointer(nhKey); + long groupId = createNextHopPointer(nhKey); long vpnId = getVpnId(vpnName); BigInteger dpnId = interfaceManager.getDpnForInterface(ifName); @@ -197,7 +193,7 @@ public class NexthopManager implements L3nexthopService, AutoCloseable { public void createRemoteNextHop(String ifName, String ipAddress) { String nhKey = new String("nexthop." + ifName + ipAddress); - int groupId = createNextHopPointer(nhKey); + long groupId = createNextHopPointer(nhKey); BigInteger dpnId = interfaceManager.getDpnForInterface(ifName); TunnelNexthop nexthop = getTunnelNexthop(dpnId, ipAddress); diff --git a/nexthopmgr/nexthopmgr-impl/src/test/java/org/opendaylight/vpnservice/nexthopmgr/test/NexthopManagerTest.java b/nexthopmgr/nexthopmgr-impl/src/test/java/org/opendaylight/vpnservice/nexthopmgr/test/NexthopManagerTest.java index fdcb511f..bef3a277 100644 --- a/nexthopmgr/nexthopmgr-impl/src/test/java/org/opendaylight/vpnservice/nexthopmgr/test/NexthopManagerTest.java +++ b/nexthopmgr/nexthopmgr-impl/src/test/java/org/opendaylight/vpnservice/nexthopmgr/test/NexthopManagerTest.java @@ -158,7 +158,7 @@ public class NexthopManagerTest { dataChangeEvent = new MockDataChangedEvent(); vpnNexthop = new VpnNexthopBuilder().setEgressPointer(10L).setIpAddress(ipAddress).build(); nhmgr = new NexthopManager(dataBroker) { - protected int createNextHopPointer(String nexthopKey) { + protected long createNextHopPointer(String nexthopKey) { return groupId; } diff --git a/pom.xml b/pom.xml index b7fbb630..f090c569 100644 --- a/pom.xml +++ b/pom.xml @@ -20,10 +20,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL commons/config-parent model-bgp mdsalutil + lockmanager + idmanager vpnmanager interfacemgr nexthopmgr - idmanager fibmanager bgpmanager distribution/karaf diff --git a/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnInterfaceManager.java b/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnInterfaceManager.java index b56c1d06..0fc976e7 100644 --- a/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnInterfaceManager.java +++ b/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnInterfaceManager.java @@ -55,10 +55,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacencyLi import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstance1; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput; +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.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies; import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig; @@ -202,7 +202,11 @@ public class VpnInterfaceManager extends AbstractDataChangeListener> result = idManager.getUniqueId(getIdInput); - RpcResult rpcResult = result.get(); - if(rpcResult.isSuccessful()) { - return rpcResult.getResult().getIdValue().intValue(); - } else { - LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors()); - } - } catch (NullPointerException | InterruptedException | ExecutionException e) { - LOG.warn("Exception when getting Unique Id",e); - } - return 0; - } - private long getVpnId(String vpnName) { //TODO: This should be a Util function InstanceIdentifier id = InstanceIdentifier.builder(VpnInstances.class) @@ -495,7 +484,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener implemen VpnInstance value) { LOG.trace("key: {}, value: {}", identifier, value); - long vpnId = getUniqueId(value.getVpnInstanceName()); + long vpnId = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, value.getVpnInstanceName()); VpnInstance opValue = new VpnInstanceBuilder(value). addAugmentation(VpnInstance1.class, new VpnInstance1Builder().setVpnId(vpnId).build()).build(); @@ -228,24 +228,24 @@ public class VpnManager extends AbstractDataChangeListener implemen return null; } - private Integer getUniqueId(String idKey) { - GetUniqueIdInput getIdInput = new GetUniqueIdInputBuilder() - .setPoolName(VpnConstants.VPN_IDPOOL_NAME) - .setIdKey(idKey).build(); - - try { - Future> result = idManager.getUniqueId(getIdInput); - RpcResult rpcResult = result.get(); - if(rpcResult.isSuccessful()) { - return rpcResult.getResult().getIdValue().intValue(); - } else { - LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors()); - } - } catch (InterruptedException | ExecutionException e) { - LOG.warn("Exception when getting Unique Id",e); - } - return 0; - } +// private Integer getUniqueId(IdManagerService idManager, String poolName,String idKey) { +// AllocateIdInput getIdInput = new AllocateIdInputBuilder() +// .setPoolName(poolName) +// .setIdKey(idKey).build(); +// +// try { +// Future> result = idManager.allocateId(getIdInput); +// RpcResult rpcResult = result.get(); +// if(rpcResult.isSuccessful()) { +// return rpcResult.getResult().getIdValue().intValue(); +// } else { +// LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors()); +// } +// } catch (InterruptedException | ExecutionException e) { +// LOG.warn("Exception when getting Unique Id",e); +// } +// return 0; +// } private void delete(LogicalDatastoreType datastoreType, InstanceIdentifier path) { WriteTransaction tx = broker.newWriteOnlyTransaction(); diff --git a/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnUtil.java b/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnUtil.java index 3d4be78c..75b55e29 100644 --- a/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnUtil.java +++ b/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnUtil.java @@ -25,13 +25,26 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces. import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacenciesBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.Pools; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPool; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPoolKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey; +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; +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.idmanager.rev150403.IdManagerService; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class VpnUtil { + + private static final Logger LOG = LoggerFactory.getLogger(VpnUtil.class); + private static final int DEFAULT_PREFIX_LENGTH = 32; + private static final String PREFIX_SEPARATOR = "/"; + static InstanceIdentifier getVpnInterfaceIdentifier(String vpnInterfaceName) { return InstanceIdentifier.builder(VpnInterfaces.class) .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).build(); @@ -53,7 +66,7 @@ public class VpnUtil { public static InstanceIdentifier getPoolId(String poolName){ InstanceIdentifier.InstanceIdentifierBuilder idBuilder = - InstanceIdentifier.builder(Pools.class).child(IdPool.class, new IdPoolKey(poolName)); + InstanceIdentifier.builder(IdPools.class).child(IdPool.class, new IdPoolKey(poolName)); InstanceIdentifier id = idBuilder.build(); return id; } @@ -66,4 +79,36 @@ public class VpnUtil { return InstanceIdentifier.builder(Interfaces.class) .child(Interface.class, new InterfaceKey(interfaceName)).build(); } + + public static String getNextHopLabelKey(String rd, String prefix){ + String key = rd + VpnConstants.SEPARATOR + prefix; + return key; + } + + static String getIpPrefix(String prefix) { + String prefixValues[] = prefix.split("/"); + if (prefixValues.length == 1) { + prefix = prefix + PREFIX_SEPARATOR + DEFAULT_PREFIX_LENGTH ; + } + return prefix; + } + + public static int getUniqueId(IdManagerService idManager, String poolName,String idKey) { + AllocateIdInput getIdInput = new AllocateIdInputBuilder() + .setPoolName(poolName) + .setIdKey(idKey).build(); + + try { + Future> result = idManager.allocateId(getIdInput); + RpcResult rpcResult = result.get(); + if(rpcResult.isSuccessful()) { + return rpcResult.getResult().getIdValue().intValue(); + } else { + LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors()); + } + } catch (InterruptedException | ExecutionException e) { + LOG.warn("Exception when getting Unique Id",e); + } + return 0; + } } diff --git a/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnserviceProvider.java b/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnserviceProvider.java index 0548c362..eb8b3d12 100644 --- a/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnserviceProvider.java +++ b/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnserviceProvider.java @@ -85,8 +85,8 @@ public class VpnserviceProvider implements BindingAwareProvider, IVpnManager, private void createIdPool() { CreateIdPoolInput createPool = new CreateIdPoolInputBuilder() .setPoolName(VpnConstants.VPN_IDPOOL_NAME) - .setIdStart(VpnConstants.VPN_IDPOOL_START) - .setPoolSize(new BigInteger(VpnConstants.VPN_IDPOOL_SIZE)) + .setLow(VpnConstants.VPN_IDPOOL_START) + .setHigh(new BigInteger(VpnConstants.VPN_IDPOOL_SIZE).longValue()) .build(); try { Future> result = idManager.createIdPool(createPool); -- 2.36.6