2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.genius.resourcemanager;
11 import com.google.common.base.Optional;
12 import com.google.common.util.concurrent.Futures;
13 import java.util.ArrayList;
14 import java.util.List;
15 import java.util.Objects;
16 import java.util.concurrent.ConcurrentHashMap;
17 import java.util.concurrent.ConcurrentMap;
18 import java.util.concurrent.ExecutionException;
19 import java.util.concurrent.Future;
20 import javax.annotation.PreDestroy;
21 import javax.inject.Inject;
22 import javax.inject.Singleton;
23 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.genius.mdsalutil.MDSALUtil;
26 import org.opendaylight.infrautils.utils.concurrent.JdkFutures;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdRangeInputBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdRangeOutput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.IdPool;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.id.pool.AvailableIdsHolder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.id.pool.ReleasedIdsHolder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.released.ids.DelayedIdEntries;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.AllocateResourceInput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.AllocateResourceOutput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.AllocateResourceOutputBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.GetAvailableResourcesInput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.GetAvailableResourcesOutput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.GetAvailableResourcesOutputBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.GetResourcePoolInput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.GetResourcePoolOutput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.GetResourcePoolOutputBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.ReleaseResourceInput;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.ResourceManagerService;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.ResourceTypeBase;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.ResourceTypeGroupIds;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.ResourceTypeMeterIds;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.ResourceTypeTableIds;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.getresourcepool.output.AvailableIds;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.getresourcepool.output.AvailableIdsBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.released.resource.ids.DelayedResourceEntries;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.resourcemanager.rev160622.released.resource.ids.DelayedResourceEntriesBuilder;
55 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
56 import org.opendaylight.yangtools.yang.common.RpcError;
57 import org.opendaylight.yangtools.yang.common.RpcResult;
58 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
63 public class ResourceManager implements ResourceManagerService, AutoCloseable {
65 private static final String RESOURCE_TABLES_NAME_PROPERTY = "resource.tables.name";
66 private static final String RESOURCE_GROUPS_NAME_PROPERTY = "resource.groups.name";
67 private static final String RESOURCE_METERS_NAME_PROPERTY = "resource.meters.name";
69 private static final String RESOURCE_TABLES_START_ID_PROPERTY = "resource.tables.startId";
70 private static final String RESOURCE_TABLES_END_ID_PROPERTY = "resource.tables.endId";
71 private static final String RESOURCE_GROUPS_START_ID_PROPERTY = "resource.groups.startId";
72 private static final String RESOURCE_GROUPS_END_ID_PROPERTY = "resource.groups.endId";
73 private static final String RESOURCE_METERS_START_ID_PROPERTY = "resource.meters.startId";
74 private static final String RESOURCE_METERS_END_ID_PROPERTY = "resource.meters.endId";
76 // Cache default values
77 private static final String RESOURCE_TABLES_DEFAULT_NAME = "tables";
78 private static final String RESOURCE_GROUPS_DEFAULT_NAME = "groups";
79 private static final String RESOURCE_METERS_DEFAULT_NAME = "meters";
81 // Default ranges of IDs
82 private static final String DEFAULT_LOW_RANGE = "0";
83 private static final String DEFAULT_HIGH_RANGE = "254";
86 private static final String RESOURCE_TYPE_CANNOT_BE_NULL = "Resource type cannot be null";
87 private static final String RESOURCE_TYPE_NOT_FOUND = "Resource type not found";
88 private static final String RESOURCE_ID_CANNOT_BE_NULL = "Id key cannot be null";
89 private static final String RESOURCE_SIZE_CANNOT_BE_NULL = "Resource size cannot be null";
92 private final DataBroker dataBroker;
93 private final IdManagerService idManager;
96 private final ConcurrentMap<Class<? extends ResourceTypeBase>, String> resourcesCache;
98 private static final Logger LOG = LoggerFactory.getLogger(ResourceManager.class);
101 public ResourceManager(final DataBroker dataBroker, final IdManagerService idManager) {
102 this.dataBroker = dataBroker;
103 this.idManager = idManager;
104 this.resourcesCache = loadCache();
108 private ConcurrentMap<Class<? extends ResourceTypeBase>, String> loadCache() {
109 ConcurrentMap<Class<? extends ResourceTypeBase>, String> cache = new ConcurrentHashMap<>();
110 cache.put(ResourceTypeTableIds.class,
111 System.getProperty(RESOURCE_TABLES_NAME_PROPERTY, RESOURCE_TABLES_DEFAULT_NAME));
112 cache.put(ResourceTypeGroupIds.class,
113 System.getProperty(RESOURCE_GROUPS_NAME_PROPERTY, RESOURCE_GROUPS_DEFAULT_NAME));
114 cache.put(ResourceTypeMeterIds.class,
115 System.getProperty(RESOURCE_METERS_NAME_PROPERTY, RESOURCE_METERS_DEFAULT_NAME));
120 public Future<RpcResult<AllocateResourceOutput>> allocateResource(AllocateResourceInput input) {
121 Objects.requireNonNull(input.getResourceType(), RESOURCE_TYPE_CANNOT_BE_NULL);
122 Objects.requireNonNull(input.getIdKey(), RESOURCE_ID_CANNOT_BE_NULL);
123 Objects.requireNonNull(input.getSize(), RESOURCE_SIZE_CANNOT_BE_NULL);
125 Objects.requireNonNull(resourcesCache.get(input.getResourceType()), RESOURCE_TYPE_NOT_FOUND);
127 AllocateIdRangeInputBuilder allocateIdRangeBuilder = new AllocateIdRangeInputBuilder();
128 allocateIdRangeBuilder.setIdKey(input.getIdKey()).setPoolName(resourcesCache.get(input.getResourceType()))
129 .setSize(input.getSize());
130 Future<RpcResult<AllocateIdRangeOutput>> output = idManager.allocateIdRange(allocateIdRangeBuilder.build());
131 AllocateResourceOutputBuilder allocateResourceOutputBuilder = new AllocateResourceOutputBuilder();
132 RpcResultBuilder<AllocateResourceOutput> allocateResourceOutputRpcBuilder = null;
134 if (output.get().isSuccessful()) {
135 AllocateIdRangeOutput allocateIdRangeOutput = output.get().getResult();
136 List<Long> idValues = allocateIdRangeOutput.getIdValues();
137 allocateResourceOutputBuilder.setIdValues(idValues);
138 allocateResourceOutputRpcBuilder = RpcResultBuilder.success();
139 allocateResourceOutputRpcBuilder.withResult(allocateResourceOutputBuilder.build());
141 } catch (InterruptedException | ExecutionException e) {
142 LOG.error("Allocate Resource failed for resource {} due to ", input.getResourceType(), e);
143 allocateResourceOutputRpcBuilder = RpcResultBuilder.failed();
144 allocateResourceOutputRpcBuilder.withError(RpcError.ErrorType.APPLICATION, e.getMessage());
147 if (allocateResourceOutputRpcBuilder == null) {
148 allocateResourceOutputRpcBuilder = RpcResultBuilder.failed();
149 allocateResourceOutputRpcBuilder.withError(RpcError.ErrorType.APPLICATION, "Resource cannot be allocated");
151 return Futures.immediateFuture(allocateResourceOutputRpcBuilder.build());
155 public Future<RpcResult<GetResourcePoolOutput>> getResourcePool(GetResourcePoolInput input) {
156 Objects.requireNonNull(input.getResourceType(), RESOURCE_TYPE_CANNOT_BE_NULL);
157 Objects.requireNonNull(resourcesCache.get(input.getResourceType()), RESOURCE_TYPE_CANNOT_BE_NULL);
159 long currentTimeSec = System.currentTimeMillis() / 1000;
160 List<AvailableIds> availableIdsList = new ArrayList<>();
161 List<DelayedResourceEntries> delayedIdEntriesList = new ArrayList<>();
162 InstanceIdentifier<IdPool> parentId = ResourceManagerUtils
163 .getIdPoolInstance(resourcesCache.get(input.getResourceType()));
164 Optional<IdPool> optionalParentIdPool = MDSALUtil.read(LogicalDatastoreType.CONFIGURATION, parentId,
166 if (optionalParentIdPool != null && optionalParentIdPool.isPresent()) {
167 IdPool parentIdPool = optionalParentIdPool.get();
168 AvailableIdsHolder availableParentIdsHolder = parentIdPool.getAvailableIdsHolder();
169 if (availableParentIdsHolder.getStart() < availableParentIdsHolder.getEnd()) {
170 availableIdsList.add(new AvailableIdsBuilder().setStart(availableParentIdsHolder.getStart())
171 .setEnd(availableParentIdsHolder.getEnd()).build());
173 ReleasedIdsHolder releasedParentIdsHolder = parentIdPool.getReleasedIdsHolder();
174 if (releasedParentIdsHolder != null) {
175 List<DelayedIdEntries> delayedIdParentList = releasedParentIdsHolder.getDelayedIdEntries();
176 if (delayedIdParentList != null && !delayedIdParentList.isEmpty()) {
177 for (DelayedIdEntries delayedParentEntry : delayedIdParentList) {
178 delayedIdEntriesList.add(new DelayedResourceEntriesBuilder().setId(delayedParentEntry.getId())
179 .setReadyTimeSec(delayedParentEntry.getReadyTimeSec()).build());
185 String localPool = ResourceManagerUtils.getLocalPoolName(resourcesCache.get(input.getResourceType()));
186 InstanceIdentifier<IdPool> localId = ResourceManagerUtils.getIdPoolInstance(localPool);
187 Optional<IdPool> optionalLocalId = MDSALUtil.read(LogicalDatastoreType.CONFIGURATION, localId, dataBroker);
188 if (optionalLocalId != null && optionalLocalId.isPresent()) {
189 IdPool localIdPool = optionalLocalId.get();
190 AvailableIdsHolder availableLocalIdsHolder = localIdPool.getAvailableIdsHolder();
191 if (availableLocalIdsHolder != null
192 && availableLocalIdsHolder.getStart() < availableLocalIdsHolder.getEnd()) {
193 availableIdsList.add(new AvailableIdsBuilder().setStart(availableLocalIdsHolder.getStart())
194 .setEnd(availableLocalIdsHolder.getEnd()).build());
196 ReleasedIdsHolder releasedLocalIdsHolder = localIdPool.getReleasedIdsHolder();
197 if (releasedLocalIdsHolder != null) {
198 List<DelayedIdEntries> delayedIdLocalList = releasedLocalIdsHolder.getDelayedIdEntries();
199 if (delayedIdLocalList != null && !delayedIdLocalList.isEmpty()) {
200 for (DelayedIdEntries delayedLocalEntry : delayedIdLocalList) {
201 if (delayedLocalEntry.getReadyTimeSec() > currentTimeSec) {
204 delayedIdEntriesList.add(new DelayedResourceEntriesBuilder().setId(delayedLocalEntry.getId())
205 .setReadyTimeSec(delayedLocalEntry.getReadyTimeSec()).build());
210 GetResourcePoolOutput output = new GetResourcePoolOutputBuilder().setAvailableIds(availableIdsList)
211 .setDelayedResourceEntries(delayedIdEntriesList).build();
212 return RpcResultBuilder.success(output).buildFuture();
216 public Future<RpcResult<GetAvailableResourcesOutput>> getAvailableResources(GetAvailableResourcesInput input) {
217 Objects.requireNonNull(input.getResourceType(), RESOURCE_TYPE_CANNOT_BE_NULL);
218 Objects.requireNonNull(resourcesCache.get(input.getResourceType()), RESOURCE_TYPE_NOT_FOUND);
220 long totalIdsAvailableForAllocation = 0;
221 long currentTimeSec = System.currentTimeMillis() / 1000;
222 InstanceIdentifier<IdPool> parentId = ResourceManagerUtils
223 .getIdPoolInstance(resourcesCache.get(input.getResourceType()));
224 Optional<IdPool> optionalParentIdPool = MDSALUtil.read(LogicalDatastoreType.CONFIGURATION, parentId,
226 if (optionalParentIdPool != null && optionalParentIdPool.isPresent()) {
227 IdPool parentIdPool = optionalParentIdPool.get();
228 AvailableIdsHolder availableParentIdsHolder = parentIdPool.getAvailableIdsHolder();
229 totalIdsAvailableForAllocation = availableParentIdsHolder.getEnd() - availableParentIdsHolder.getCursor();
230 ReleasedIdsHolder releasedParentIdsHolder = parentIdPool.getReleasedIdsHolder();
231 if (releasedParentIdsHolder != null) {
232 List<DelayedIdEntries> delayedIdParentList = releasedParentIdsHolder.getDelayedIdEntries();
233 if (delayedIdParentList != null && !delayedIdParentList.isEmpty()) {
234 totalIdsAvailableForAllocation += delayedIdParentList.size();
239 String localPool = ResourceManagerUtils.getLocalPoolName(resourcesCache.get(input.getResourceType()));
240 InstanceIdentifier<IdPool> localId = ResourceManagerUtils.getIdPoolInstance(localPool);
241 Optional<IdPool> optionalLocalId = MDSALUtil.read(LogicalDatastoreType.CONFIGURATION, localId, dataBroker);
242 if (optionalLocalId != null && optionalLocalId.isPresent()) {
243 IdPool localIdPool = optionalLocalId.get();
244 AvailableIdsHolder availableLocalIdsHolder = localIdPool.getAvailableIdsHolder();
245 if (availableLocalIdsHolder != null) {
246 totalIdsAvailableForAllocation += availableLocalIdsHolder.getEnd()
247 - availableLocalIdsHolder.getCursor();
249 ReleasedIdsHolder releasedLocalIdsHolder = localIdPool.getReleasedIdsHolder();
250 if (releasedLocalIdsHolder != null) {
252 List<DelayedIdEntries> delayedIdLocalList = releasedLocalIdsHolder.getDelayedIdEntries();
253 if (delayedIdLocalList != null && !delayedIdLocalList.isEmpty()) {
254 for (DelayedIdEntries delayedLocalEntry : delayedIdLocalList) {
255 if (delayedLocalEntry.getReadyTimeSec() > currentTimeSec) {
261 totalIdsAvailableForAllocation += count;
265 GetAvailableResourcesOutputBuilder outputBuilder = new GetAvailableResourcesOutputBuilder()
266 .setTotalAvailableIdCount(totalIdsAvailableForAllocation);
267 RpcResultBuilder<GetAvailableResourcesOutput> rpcOutputBuilder = null;
268 rpcOutputBuilder = RpcResultBuilder.success();
269 rpcOutputBuilder.withResult(outputBuilder.build());
271 return Futures.immediateFuture(rpcOutputBuilder.build());
275 public Future<RpcResult<Void>> releaseResource(ReleaseResourceInput input) {
276 Objects.requireNonNull(input.getIdKey(), RESOURCE_ID_CANNOT_BE_NULL);
277 Objects.requireNonNull(input.getResourceType(), RESOURCE_TYPE_CANNOT_BE_NULL);
279 Objects.requireNonNull(resourcesCache.get(input.getResourceType()), RESOURCE_TYPE_NOT_FOUND);
281 ReleaseIdInputBuilder releaseIdInputBuilder = new ReleaseIdInputBuilder();
282 releaseIdInputBuilder.setIdKey(input.getIdKey()).setPoolName(resourcesCache.get(input.getResourceType()));
284 return idManager.releaseId(releaseIdInputBuilder.build());
287 private void createIdPool(String poolNameProperty, String lowIdProperty, String highIdProperty,
288 String poolDefaultName) {
289 JdkFutures.addErrorLogging(idManager.createIdPool(
290 new CreateIdPoolInputBuilder().setPoolName(System.getProperty(poolNameProperty, poolDefaultName))
291 .setLow(Long.valueOf(System.getProperty(lowIdProperty, DEFAULT_LOW_RANGE)))
292 .setHigh(Long.valueOf(System.getProperty(highIdProperty, DEFAULT_HIGH_RANGE))).build()),
293 LOG, "createIdPool");
296 private void createIdpools() {
297 // Create Tables Id Pool
298 createIdPool(RESOURCE_TABLES_NAME_PROPERTY, RESOURCE_TABLES_START_ID_PROPERTY, RESOURCE_TABLES_END_ID_PROPERTY,
299 RESOURCE_TABLES_DEFAULT_NAME);
301 // Create Groups Id Pool
302 createIdPool(RESOURCE_GROUPS_NAME_PROPERTY, RESOURCE_GROUPS_START_ID_PROPERTY, RESOURCE_GROUPS_END_ID_PROPERTY,
303 RESOURCE_GROUPS_DEFAULT_NAME);
305 // Create Meters Id Pool
306 createIdPool(RESOURCE_METERS_NAME_PROPERTY, RESOURCE_METERS_START_ID_PROPERTY, RESOURCE_METERS_END_ID_PROPERTY,
307 RESOURCE_METERS_DEFAULT_NAME);
312 public void close() {
313 LOG.debug("{} close", getClass().getSimpleName());