/* * Copyright (c) 2015 Yale University 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.alto.core.resourcepool; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.UUID; import java.util.concurrent.ExecutionException; import com.google.common.base.Optional; import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; import org.opendaylight.controller.md.sal.binding.api.ReadTransaction; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yang.gen.v1.urn.alto.resourcepool.rev150921.ResourceType; import org.opendaylight.yang.gen.v1.urn.alto.resourcepool.rev150921.ServiceContext; import org.opendaylight.yang.gen.v1.urn.alto.resourcepool.rev150921.Context; import org.opendaylight.yang.gen.v1.urn.alto.resourcepool.rev150921.ContextBuilder; import org.opendaylight.yang.gen.v1.urn.alto.resourcepool.rev150921.ContextKey; import org.opendaylight.yang.gen.v1.urn.alto.resourcepool.rev150921.context.Resource; import org.opendaylight.yang.gen.v1.urn.alto.resourcepool.rev150921.context.ResourceBuilder; import org.opendaylight.yang.gen.v1.urn.alto.resourcepool.rev150921.context.ResourceKey; import org.opendaylight.yang.gen.v1.urn.alto.resourcepool.rev150921.context.resource.Capabilities; import org.opendaylight.yang.gen.v1.urn.alto.resourcepool.rev150921.context.resource.CapabilitiesBuilder; import org.opendaylight.yang.gen.v1.urn.alto.resourcepool.rev150921.context.resource.ContextTag; import org.opendaylight.yang.gen.v1.urn.alto.resourcepool.rev150921.context.resource.ContextTagBuilder; import org.opendaylight.yang.gen.v1.urn.alto.resourcepool.rev150921.context.resource.ContextTagKey; import org.opendaylight.yang.gen.v1.urn.alto.types.rev150921.ResourceId; import org.opendaylight.yang.gen.v1.urn.alto.types.rev150921.Tag; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.RpcService; public class ResourcepoolUtils { public static final String DEFAULT_CONTEXT = "00000000-0000-0000-0000-000000000000"; public static InstanceIdentifier<Context> getDefaultContextIID() { return getContextIID(DEFAULT_CONTEXT); } public static InstanceIdentifier<Context> getContextIID(String cid) { Uuid _cid = new Uuid(cid); return getContextIID(_cid); } public static InstanceIdentifier<Context> getContextIID(Uuid cid) { ContextKey key = new ContextKey(cid); return getContextIID(key); } public static InstanceIdentifier<Context> getContextIID(ContextKey key) { return InstanceIdentifier.builder(Context.class, key).build(); } public static InstanceIdentifier<Resource> getResourceIID(String cid, String rid) { Uuid _cid = new Uuid(cid); ResourceId _rid = new ResourceId(rid); return getResourceIID(_cid, _rid); } public static InstanceIdentifier<Resource> getResourceIID(String cid, ResourceId rid) { Uuid _cid = new Uuid(cid); return getResourceIID(_cid, rid); } public static InstanceIdentifier<Resource> getResourceIID(Uuid cid, String rid) { ResourceId _rid = new ResourceId(rid); return getResourceIID(cid, _rid); } public static InstanceIdentifier<Resource> getResourceIID(Uuid cid, ResourceId rid) { ContextKey contextKey = new ContextKey(cid); ResourceKey resourceKey = new ResourceKey(rid); return InstanceIdentifier.builder(Context.class, contextKey) .child(Resource.class, resourceKey).build(); } public static InstanceIdentifier<ContextTag> getContextTagIID(String cid, String rid, String tag) { Uuid _cid = new Uuid(cid); ResourceId _rid = new ResourceId(rid); Tag _tag = new Tag(tag); return getContextTagIID(_cid, _rid, _tag); } public static InstanceIdentifier<ContextTag> getContextTagIID(Uuid cid, ResourceId rid, Tag tag) { ContextKey contextKey = new ContextKey(cid); ResourceKey resourceKey = new ResourceKey(rid); ContextTagKey contextTagKey = new ContextTagKey(tag); return InstanceIdentifier.builder(Context.class, contextKey) .child(Resource.class, resourceKey) .child(ContextTag.class, contextTagKey).build(); } public static boolean contextExists(String cid, ReadTransaction rx) throws InterruptedException, ExecutionException { return contextExists(new Uuid(cid), rx); } public static boolean contextExists(Uuid cid, ReadTransaction rx) throws InterruptedException, ExecutionException { return contextExists(new ContextKey(cid), rx); } public static boolean contextExists(ContextKey key, ReadTransaction rx) throws InterruptedException, ExecutionException { Optional<Context> context; context = rx.read(LogicalDatastoreType.OPERATIONAL, getContextIID(key)).get(); return (context.isPresent()); } public static Uuid createRandomContext(final WriteTransaction wx) { String cid = UUID.randomUUID().toString(); return createContext(cid, wx); } public static Uuid createContext(String cid, final WriteTransaction wx) { return createContext(new Uuid(cid), wx); } public static Uuid createContext(Uuid cid, final WriteTransaction wx) { ContextBuilder builder = new ContextBuilder(); builder.setContextId(cid); builder.setResource(new LinkedList<Resource>()); /* DO NOT submit because this might be just one step in a sequence of write operations */ wx.put(LogicalDatastoreType.OPERATIONAL, getContextIID(cid), builder.build()); return cid; } public static void deleteContext(String cid, final WriteTransaction wx) { deleteContext(new Uuid(cid), wx); } public static void deleteContext(Uuid cid, final WriteTransaction wx) { /* DO NOT submit because this might be just one step in a sequence of write operations */ wx.delete(LogicalDatastoreType.OPERATIONAL, getContextIID(cid)); } public static boolean resourceExists(String cid, String rid, ReadTransaction rx) throws InterruptedException, ExecutionException { return resourceExists(new Uuid(cid), new ResourceId(rid), rx); } public static boolean resourceExists(Uuid cid, ResourceId rid, ReadTransaction rx) throws InterruptedException, ExecutionException { InstanceIdentifier<Resource> iid = getResourceIID(cid, rid); Optional<Resource> resource; resource = rx.read(LogicalDatastoreType.OPERATIONAL, iid).get(); return (resource.isPresent()); } public static ResourceId createResource(String cid, String rid, Class<? extends ResourceType> type, final WriteTransaction wx) { Uuid _cid = new Uuid(cid); ResourceId _rid = new ResourceId(rid); return createResource(_cid, _rid, type, wx); } public static ResourceId createResource(Uuid cid, ResourceId rid, Class<? extends ResourceType> type, final WriteTransaction wx) { return createResourceWithCapabilities(cid, rid, type, null, wx); } public static ResourceId createResourceWithCapabilities(String cid, String rid, Class<? extends ResourceType> type, Capabilities capabilities, final WriteTransaction wx) { Uuid contextId = new Uuid(cid); ResourceId resourceId = new ResourceId(rid); return createResourceWithCapabilities(contextId, resourceId, type, capabilities, wx); } public static ResourceId createResourceWithCapabilities(Uuid cid, ResourceId rid, Class<? extends ResourceType> type, Capabilities capabilities, final WriteTransaction wx) { ResourceBuilder builder = new ResourceBuilder(); builder.setResourceId(rid); builder.setType(type); builder.setContextTag(new LinkedList<ContextTag>()); if (capabilities == null) { capabilities = new CapabilitiesBuilder().build(); } builder.setCapabilities(capabilities); InstanceIdentifier<Resource> iid = getResourceIID(cid, rid); /* DO NOT submit because this might be just one step in a sequence of write operations */ wx.put(LogicalDatastoreType.OPERATIONAL, iid, builder.build()); return rid; } public static void deleteResource(String cid, String rid, final WriteTransaction wx) { Uuid contextId = new Uuid(cid); ResourceId resourceId = new ResourceId(rid); deleteResource(contextId, resourceId, wx); } public static void deleteResource(Uuid cid, ResourceId rid, final WriteTransaction wx) { InstanceIdentifier<Resource> iid = getResourceIID(cid, rid); /* DO NOT submit because this might be just one step in a sequence of write operations */ wx.delete(LogicalDatastoreType.OPERATIONAL, iid); } public static Tag updateResource(String cid, String rid, List<InstanceIdentifier<?>> dependencies, final WriteTransaction wx) { return updateResource(new Uuid(cid), new ResourceId(rid), dependencies, wx); } public static Tag updateResource(Uuid cid, ResourceId rid, List<InstanceIdentifier<?>> dependencies, final WriteTransaction wx) { String stripped = getUUID().replace("-", ""); return updateResource(cid, rid, new Tag(stripped), dependencies, wx); } public static Tag updateResource(Uuid cid, ResourceId rid, Tag tag, List<InstanceIdentifier<?>> dependencies, final WriteTransaction wx) { ContextTagBuilder ctBuilder = new ContextTagBuilder(); ctBuilder.setTag(tag); /* * Unfortunately the resources must handle the dependency resolving themselves * */ if (dependencies == null) { dependencies = new LinkedList<InstanceIdentifier<?>>(); } ctBuilder.setDependency(dependencies); ResourceBuilder rscBuilder = new ResourceBuilder(); rscBuilder.setResourceId(rid); rscBuilder.setDefaultTag(tag); rscBuilder.setContextTag(Arrays.asList(ctBuilder.build())); InstanceIdentifier<Resource> iid = getResourceIID(cid, rid); /* DO NOT submit because this might be just one step in a sequence of write operations */ wx.merge(LogicalDatastoreType.OPERATIONAL, iid, rscBuilder.build()); return tag; } /* * For those who don't have dependencies * */ public static Tag lazyUpdateResource(String cid, String rid, final WriteTransaction wx) { Uuid contextId = new Uuid(cid); ResourceId resourceId = new ResourceId(rid); return lazyUpdateResource(contextId, resourceId, wx); } public static Tag lazyUpdateResource(Uuid cid, ResourceId rid, final WriteTransaction wx) { String stripped = getUUID().replace("-", ""); return updateResource(cid, rid, new Tag(stripped), null, wx); } public static String getUUID() { return UUID.randomUUID().toString(); } public static String getUUID(String name) { return UUID.nameUUIDFromBytes(name.getBytes()).toString(); } public static final class ContextTagListener implements DataChangeListener { private RoutedRpcRegistration<? extends RpcService> m_registration = null; private InstanceIdentifier<Resource> m_iid = null; public ContextTagListener(InstanceIdentifier<Resource> resourceIID, RoutedRpcRegistration<? extends RpcService> registration) { m_iid = resourceIID; m_registration = registration; } @Override public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) { for (InstanceIdentifier<?> path: change.getRemovedPaths()) { if (path.getTargetType().equals(ContextTag.class)) { if (m_iid.contains(path)) { // Only manage resource's own context tag m_registration.unregisterPath(ServiceContext.class, path); } } } for (InstanceIdentifier<?> path: change.getCreatedData().keySet()) { if (path.getTargetType().equals(ContextTag.class)) { if (m_iid.contains(path)) { // Only manage resource's own context tag m_registration.registerPath(ServiceContext.class, path); } } } } } }