From 3285cd1a1de458050eb43dee5508658d3525272e Mon Sep 17 00:00:00 2001 From: Prasanna Huddar Date: Thu, 7 Nov 2013 19:10:57 +0530 Subject: [PATCH] Added trasaction capabilities. Signed-off-by: Prasanna Huddar Change-Id: I3d176d25ec1478d5c6f1ed546bfab511f204dda9 --- .../openflow/pom.xml | 16 +- .../consumer/impl/FRMConsumerImpl.java | 104 +++- .../consumer/impl/FRMUtil.java | 33 ++ .../consumer/impl/FlowConsumerImpl.java | 35 +- .../consumer/impl/GroupConsumerImpl.java | 475 +++++++++++++++++- .../src/main/yang/group-types.yang | 4 + .../src/main/yang/meter-types.yang | 11 + .../src/main/yang/port-types.yang | 16 +- .../src/main/yang/meter-config.yang | 2 - .../main/yang/flow-capable-transaction.yang | 46 ++ .../src/main/yang/group-service.yang | 16 +- .../src/main/yang/meter-service.yang | 13 + .../src/main/yang/port-service.yang | 46 ++ .../src/main/yang/table-service.yang | 12 +- 14 files changed, 789 insertions(+), 40 deletions(-) create mode 100644 opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMUtil.java create mode 100644 opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-capable-transaction.yang create mode 100644 opendaylight/md-sal/model/model-flow-service/src/main/yang/port-service.yang diff --git a/opendaylight/forwardingrulesmanager_mdsal/openflow/pom.xml b/opendaylight/forwardingrulesmanager_mdsal/openflow/pom.xml index 9b96f86c92..29de77270b 100644 --- a/opendaylight/forwardingrulesmanager_mdsal/openflow/pom.xml +++ b/opendaylight/forwardingrulesmanager_mdsal/openflow/pom.xml @@ -31,9 +31,21 @@ org.opendaylight.controller.sal.binding.api, org.opendaylight.controller.sal.binding.api.data, - org.opendaylight.controller.md.sal.common.api.data, - org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.flow, + org.opendaylight.controller.md.sal.common.api.data, + org.opendaylight.controller.sal.utils, + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow, + org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups, + org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918, + org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018, + org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group, + org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets, + org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.bucket, org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819, + org.opendaylight.controller.clustering.services, org.opendaylight.controller.sal.core, + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction, + org.opendaylight.controller.switchmanager, + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list, + org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024, org.opendaylight.yangtools.concepts, org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819, org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819, diff --git a/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMConsumerImpl.java b/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMConsumerImpl.java index ae488b689f..e48e03867c 100644 --- a/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMConsumerImpl.java +++ b/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMConsumerImpl.java @@ -10,16 +10,23 @@ package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl; +import org.eclipse.osgi.framework.console.CommandProvider; +import org.opendaylight.controller.clustering.services.IClusterContainerServices; import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext; import org.opendaylight.controller.sal.binding.api.NotificationService; import org.opendaylight.controller.sal.binding.api.data.DataBrokerService; import org.opendaylight.controller.sal.binding.api.data.DataProviderService; +import org.opendaylight.controller.sal.core.IContainer; +import org.opendaylight.controller.sal.utils.ServiceHelper; +import org.opendaylight.controller.switchmanager.ISwitchManager; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class FRMConsumerImpl extends AbstractBindingAwareProvider { +public class FRMConsumerImpl extends AbstractBindingAwareProvider implements CommandProvider{ protected static final Logger logger = LoggerFactory.getLogger(FRMConsumerImpl.class); private static ProviderContext p_session; private static DataBrokerService dataBrokerService; @@ -28,11 +35,21 @@ public class FRMConsumerImpl extends AbstractBindingAwareProvider { private GroupConsumerImpl groupImplRef; private static DataProviderService dataProviderService; + private static IClusterContainerServices clusterContainerService = null; + private static ISwitchManager switchManager; + private static IContainer container; + @Override public void onSessionInitiated(ProviderContext session) { FRMConsumerImpl.p_session = session; + if (!getDependentModule()) { + logger.error("Unable to fetch handlers for dependent modules"); + System.out.println("Unable to fetch handlers for dependent modules"); + return; + } + if (null != session) { notificationService = session.getSALService(NotificationService.class); @@ -44,7 +61,8 @@ public class FRMConsumerImpl extends AbstractBindingAwareProvider { if (null != dataProviderService) { flowImplRef = new FlowConsumerImpl(); - groupImplRef = new GroupConsumerImpl(); + // groupImplRef = new GroupConsumerImpl(); + registerWithOSGIConsole(); } else { logger.error("Data Provider Service is down or NULL. " + @@ -68,18 +86,85 @@ public class FRMConsumerImpl extends AbstractBindingAwareProvider { System.out.println("Consumer session is NULL. Please check if provider is registered"); } + } + + public static IClusterContainerServices getClusterContainerService() { + return clusterContainerService; + } + + public static void setClusterContainerService( + IClusterContainerServices clusterContainerService) { + FRMConsumerImpl.clusterContainerService = clusterContainerService; + } + + public static ISwitchManager getSwitchManager() { + return switchManager; + } + + public static void setSwitchManager(ISwitchManager switchManager) { + FRMConsumerImpl.switchManager = switchManager; + } + + public static IContainer getContainer() { + return container; } - public static DataProviderService getDataProviderService() { + public static void setContainer(IContainer container) { + FRMConsumerImpl.container = container; + } + + private void registerWithOSGIConsole() { + BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext(); + bundleContext.registerService(CommandProvider.class.getName(), this, null); + } + + private boolean getDependentModule() { + do { + clusterContainerService = (IClusterContainerServices) ServiceHelper.getGlobalInstance(IClusterContainerServices.class, this); + try { + Thread.sleep(4); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } while(clusterContainerService == null); + + do { + + + container = (IContainer) ServiceHelper.getGlobalInstance(IContainer.class, this); + try { + Thread.sleep(5); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } while (container == null); + + do { + switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, container.getName(), this); + try { + Thread.sleep(5); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } while(null == switchManager); + return true; + } + + + + public static DataProviderService getDataProviderService() { return dataProviderService; } public FlowConsumerImpl getFlowImplRef() { - return flowImplRef; + return flowImplRef; } public GroupConsumerImpl getGroupImplRef() { - return groupImplRef; + return groupImplRef; } public static ProviderContext getProviderSession() { @@ -93,6 +178,15 @@ public class FRMConsumerImpl extends AbstractBindingAwareProvider { public static DataBrokerService getDataBrokerService() { return dataBrokerService; } + + /* + * OSGI COMMANDS + */ + @Override + public String getHelp() { + StringBuffer help = new StringBuffer(); + return help.toString(); + } } diff --git a/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMUtil.java b/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMUtil.java new file mode 100644 index 0000000000..df34d19b23 --- /dev/null +++ b/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMUtil.java @@ -0,0 +1,33 @@ +package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.bucket.Actions; + +public class FRMUtil { + private static final String NAMEREGEX = "^[a-zA-Z0-9]+$"; + public enum operation {ADD, DELETE, UPDATE, GET}; + + + public static boolean isNameValid(String name) { + + // Name validation + if (name == null || name.trim().isEmpty() || !name.matches(NAMEREGEX)) { + return false; + } + return true; + + } + + public static boolean areActionsValid(Actions actions) { + // List actionList; + // Action actionRef; + // if (null != actions && null != actions.getAction()) { + // actionList = actions.getAction(); + + + + + // } + + return true; + } +} diff --git a/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FlowConsumerImpl.java b/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FlowConsumerImpl.java index a6a3c71325..59c7e043de 100644 --- a/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FlowConsumerImpl.java +++ b/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FlowConsumerImpl.java @@ -20,6 +20,7 @@ import org.opendaylight.controller.sal.common.util.Rpcs; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput; + import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved; @@ -27,6 +28,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.Flow import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; @@ -61,6 +63,7 @@ public class FlowConsumerImpl { } listener = new FlowDataListener(); + if (null == FRMConsumerImpl.getDataBrokerService().registerDataChangeListener(path, listener)) { logger.error("Failed to listen on flow data modifcation events"); System.out.println("Consumer SAL Service is down or NULL."); @@ -75,7 +78,7 @@ public class FlowConsumerImpl { System.out.println("Consumer SAL Service is down or NULL."); return; } - addFlowTest(); + //addFlowTest(); System.out.println("-------------------------------------------------------------------"); allocateCaches(); commitHandler = new FlowDataCommitHandler(); @@ -120,11 +123,19 @@ public class FlowConsumerImpl { private void addFlow(InstanceIdentifier path, Flow dataObject) { AddFlowInputBuilder input = new AddFlowInputBuilder(); + List inst = (dataObject).getInstructions().getInstruction(); input.setNode((dataObject).getNode()); input.setPriority((dataObject).getPriority()); input.setMatch((dataObject).getMatch()); input.setCookie((dataObject).getCookie()); - input.setAction((dataObject).getAction()); + input.setInstructions((dataObject).getInstructions()); + dataObject.getMatch().getLayer3Match() + for (int i=0;i, Flow> entry :transaction.additions.entrySet()) { + System.out.println("Coming add cc in FlowDatacommitHandler"); addFlow(entry.getKey(),entry.getValue()); } - for(@SuppressWarnings("unused") Entry, Flow> entry :transaction.additions.entrySet()) { + for(@SuppressWarnings("unused") Entry, Flow> entry :transaction.updates.entrySet()) { + System.out.println("Coming update cc in FlowDatacommitHandler"); // updateFlow(entry.getKey(),entry.getValue()); } @@ -196,9 +209,11 @@ public class FlowConsumerImpl { Flow original = originalSwView.get(key); if (original != null) { // It is update for us + System.out.println("Coming update in FlowDatacommitHandler"); updates.put(key, flow); } else { // It is addition for us + System.out.println("Coming add in FlowDatacommitHandler"); additions.put(key, flow); } } @@ -273,7 +288,7 @@ public class FlowConsumerImpl { for (DataObject dataObject : additions) { if (dataObject instanceof NodeFlow) { NodeRef nodeOne = createNodeRef("foo:node:1"); - // validating the dataObject here + // validating the dataObject here AddFlowInputBuilder input = new AddFlowInputBuilder(); input.setNode(((NodeFlow) dataObject).getNode()); input.setNode(nodeOne); @@ -300,18 +315,6 @@ public class FlowConsumerImpl { return new NodeRef(path); } - /* private void loadFlowData() { - DataModification modification = (DataModification) dataservice.beginTransaction(); - String id = "abc"; - FlowKey key = new FlowKey(id, new NodeRef()); - InstanceIdentifier path1; - FlowBuilder flow = new FlowBuilder(); - flow.setKey(key); - path1 = InstanceIdentifier.builder().node(Flows.class).node(Flow.class, key).toInstance(); - DataObject cls = (DataObject) modification.readConfigurationData(path); - modification.putConfigurationData(path, flow.build()); - modification.commit(); - }*/ } diff --git a/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/GroupConsumerImpl.java b/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/GroupConsumerImpl.java index cc42e21f2a..acc0dc69cd 100644 --- a/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/GroupConsumerImpl.java +++ b/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/GroupConsumerImpl.java @@ -1,7 +1,478 @@ package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import org.opendaylight.controller.clustering.services.CacheConfigException; +import org.opendaylight.controller.clustering.services.CacheExistException; +import org.opendaylight.controller.clustering.services.IClusterContainerServices; +import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler; +import org.opendaylight.controller.md.sal.common.api.data.DataModification; +import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction; +import org.opendaylight.controller.sal.common.util.Rpcs; +import org.opendaylight.controller.sal.core.IContainer; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.utils.GlobalConstants; +import org.opendaylight.controller.sal.utils.Status; +import org.opendaylight.controller.sal.utils.StatusCode; +import org.opendaylight.controller.switchmanager.ISwitchManager; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.Groups; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups.Group; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups.GroupKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupAdded; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupRemoved; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupUpdated; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes.GroupType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket; +import org.opendaylight.yangtools.concepts.Registration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.NotificationListener; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@SuppressWarnings("unused") public class GroupConsumerImpl { - public GroupConsumerImpl() { - + + protected static final Logger logger = LoggerFactory.getLogger(GroupConsumerImpl.class); + private GroupEventListener groupEventListener = new GroupEventListener(); + private Registration groupListener; + private SalGroupService groupService; + private GroupDataCommitHandler commitHandler; + + private ConcurrentMap originalSwGroupView; + private ConcurrentMap installedSwGroupView; + + private ConcurrentMap> nodeGroups; + private ConcurrentMap inactiveGroups; + + private IClusterContainerServices clusterGroupContainerService = null; + private ISwitchManager switchGroupManager; + private IContainer container; + + public GroupConsumerImpl() { + InstanceIdentifier path = InstanceIdentifier.builder().node(Groups.class).toInstance(); + groupService = FRMConsumerImpl.getProviderSession().getRpcService(SalGroupService.class); + + clusterGroupContainerService = FRMConsumerImpl.getClusterContainerService(); + switchGroupManager = FRMConsumerImpl.getSwitchManager(); + container = FRMConsumerImpl.getContainer(); + + if (!(cacheStartup())) { + logger.error("Unanle to allocate/retrieve group cache"); + System.out.println("Unable to allocate/retrieve group cache"); + } + + if (null == groupService) { + logger.error("Consumer SAL Group Service is down or NULL. FRM may not function as intended"); + System.out.println("Consumer SAL Group Service is down or NULL."); + return; + } + + // For switch events + groupListener = FRMConsumerImpl.getNotificationService().registerNotificationListener(groupEventListener); + + if (null == groupListener) { + logger.error("Listener to listen on group data modifcation events"); + System.out.println("Listener to listen on group data modifcation events."); + return; + } + + commitHandler = new GroupDataCommitHandler(); + FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, commitHandler); } + + private boolean allocateGroupCaches() { + if (this.clusterGroupContainerService == null) { + logger.warn("Group: Un-initialized clusterGroupContainerService, can't create cache"); + return false; + } + + try { + clusterGroupContainerService.createCache("frm.originalSwGroupView", + EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL)); + + clusterGroupContainerService.createCache("frm.installedSwGroupView", + EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL)); + + clusterGroupContainerService.createCache("frm.inactiveGroups", + EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL)); + + clusterGroupContainerService.createCache("frm.nodeGroups", + EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL)); + +//TODO for cluster mode + /* clusterGroupContainerService.createCache(WORK_STATUS_CACHE, + EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC)); + + clusterGroupContainerService.createCache(WORK_ORDER_CACHE, + EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));*/ + + } catch (CacheConfigException cce) { + logger.error("Group CacheConfigException"); + return false; + + } catch (CacheExistException cce) { + logger.error(" Group CacheExistException"); + } + + return true; + } + + private void nonClusterGroupObjectCreate() { + originalSwGroupView = new ConcurrentHashMap(); + installedSwGroupView = new ConcurrentHashMap(); + nodeGroups = new ConcurrentHashMap>(); + inactiveGroups = new ConcurrentHashMap(); + } + + @SuppressWarnings({ "unchecked" }) + private boolean retrieveGroupCaches() { + ConcurrentMap map; + + if (this.clusterGroupContainerService == null) { + logger.warn("Group: un-initialized clusterGroupContainerService, can't retrieve cache"); + nonClusterGroupObjectCreate(); + return false; + } + + map = clusterGroupContainerService.getCache("frm.originalSwGroupView"); + if (map != null) { + originalSwGroupView = (ConcurrentMap) map; + } else { + logger.error("Retrieval of cache(originalSwGroupView) failed"); + return false; + } + + map = clusterGroupContainerService.getCache("frm.installedSwGroupView"); + if (map != null) { + installedSwGroupView = (ConcurrentMap) map; + } else { + logger.error("Retrieval of cache(installedSwGroupView) failed"); + return false; + } + + map = clusterGroupContainerService.getCache("frm.inactiveGroups"); + if (map != null) { + inactiveGroups = (ConcurrentMap) map; + } else { + logger.error("Retrieval of cache(inactiveGroups) failed"); + return false; + } + + map = clusterGroupContainerService.getCache("frm.nodeGroups"); + if (map != null) { + nodeGroups = (ConcurrentMap>) map; + } else { + logger.error("Retrieval of cache(nodeGroup) failed"); + return false; + } + + return true; + } + + private boolean cacheStartup() { + if (allocateGroupCaches()) { + if (retrieveGroupCaches()) { + return true; + } + } + + return false; + } + + public Status validateGroup(Group group, FRMUtil.operation operation) { + String containerName; + String groupName; + Iterator bucketIterator; + boolean returnResult; + Buckets groupBuckets; + + if (null != group) { + containerName = group.getContainerName(); + + if (null == containerName) { + containerName = GlobalConstants.DEFAULT.toString(); + } + else if (!FRMUtil.isNameValid(containerName)) { + logger.error("Container Name is invalid %s" + containerName); + return new Status(StatusCode.BADREQUEST, "Container Name is invalid"); + } + + groupName = group.getGroupName(); + if (!FRMUtil.isNameValid(groupName)) { + logger.error("Group Name is invalid %s" + groupName); + return new Status(StatusCode.BADREQUEST, "Group Name is invalid"); + } + + returnResult = doesGroupEntryExists(group.getKey(), groupName, containerName); + + if (FRMUtil.operation.ADD == operation && returnResult) { + logger.error("Record with same Group Name exists"); + return new Status(StatusCode.BADREQUEST, "Group record exists"); + } + else if (!returnResult) { + logger.error("Group record does not exist"); + return new Status(StatusCode.BADREQUEST, "Group record does not exist"); + } + + if (!(group.getGroupType().getIntValue() >= GroupType.GroupAll.getIntValue() && + group.getGroupType().getIntValue() <= GroupType.GroupFf.getIntValue())) { + logger.error("Invalid Group type %d" + group.getGroupType().getIntValue()); + return new Status(StatusCode.BADREQUEST, "Invalid Group type"); + } + + groupBuckets = group.getBuckets(); + + if (null != groupBuckets && null != groupBuckets.getBucket()) { + bucketIterator = groupBuckets.getBucket().iterator(); + + while (bucketIterator.hasNext()) { + if(!(FRMUtil.areActionsValid(bucketIterator.next().getActions()))) { + logger.error("Error in action bucket"); + return new Status(StatusCode.BADREQUEST, "Invalid Group bucket contents"); + } + } + } + } + + return new Status(StatusCode.SUCCESS); + + } + + private boolean doesGroupEntryExists(GroupKey key, String groupName, String containerName) { + if (! originalSwGroupView.containsKey(key)) { + return false; + } + + for (ConcurrentMap.Entry entry : originalSwGroupView.entrySet()) { + if (entry.getValue().getGroupName().equals(groupName)) { + if (entry.getValue().getContainerName().equals(containerName)) { + return true; + } + } + } + return false; + } + + + /** + * Update Group entries to the southbound plugin/inventory and our internal database + * + * @param path + * @param dataObject + */ + private Status updateGroup(InstanceIdentifier path, Group groupUpdateDataObject) { + GroupKey groupKey = groupUpdateDataObject.getKey(); + Status groupOperationStatus = validateGroup(groupUpdateDataObject, FRMUtil.operation.UPDATE); + + if (!groupOperationStatus.isSuccess()) { + logger.error("Group data object validation failed %s" + groupUpdateDataObject.getGroupName()); + return groupOperationStatus; + } + + originalSwGroupView.remove(groupKey); + originalSwGroupView.put(groupKey, groupUpdateDataObject); + + if (groupUpdateDataObject.isInstall()) { + UpdateGroupInputBuilder groupData = new UpdateGroupInputBuilder(); + //TODO how to get original group and modified group. + + if (installedSwGroupView.containsKey(groupKey)) { + installedSwGroupView.remove(groupKey); + } + + installedSwGroupView.put(groupKey, groupUpdateDataObject); + groupService.updateGroup(groupData.build()); + } + + return groupOperationStatus; + } + + /** + * Adds Group to the southbound plugin and our internal database + * + * @param path + * @param dataObject + */ + private Status addGroup(InstanceIdentifier path, Group groupAddDataObject) { + GroupKey groupKey = groupAddDataObject.getKey(); + Status groupOperationStatus = validateGroup(groupAddDataObject, FRMUtil.operation.ADD); + + if (!groupOperationStatus.isSuccess()) { + logger.error("Group data object validation failed %s" + groupAddDataObject.getGroupName()); + return groupOperationStatus; + } + validateGroup(groupAddDataObject, FRMUtil.operation.ADD); + originalSwGroupView.put(groupKey, groupAddDataObject); + + if (groupAddDataObject.isInstall()) { + AddGroupInputBuilder groupData = new AddGroupInputBuilder(); + groupData.setBuckets(groupAddDataObject.getBuckets()); + groupData.setContainerName(groupAddDataObject.getContainerName()); + groupData.setGroupId(groupAddDataObject.getGroupId()); + groupData.setGroupType(groupAddDataObject.getGroupType()); + groupData.setNode(groupAddDataObject.getNode()); + installedSwGroupView.put(groupKey, groupAddDataObject); + groupService.addGroup(groupData.build()); + } + + return groupOperationStatus; + } + + private RpcResult commitToPlugin(internalTransaction transaction) { + for(Entry, Group> entry :transaction.additions.entrySet()) { + + if (!addGroup(entry.getKey(),entry.getValue()).isSuccess()) { + return Rpcs.getRpcResult(false, null, null); + } + } + for(@SuppressWarnings("unused") Entry, Group> entry :transaction.additions.entrySet()) { + + if (!updateGroup(entry.getKey(),entry.getValue()).isSuccess()) { + return Rpcs.getRpcResult(false, null, null); + } + } + + for(InstanceIdentifier removal : transaction.removals) { + // removeFlow(removal); + } + + return Rpcs.getRpcResult(true, null, null); + } + + private final class GroupDataCommitHandler implements DataCommitHandler, DataObject> { + + @SuppressWarnings("unchecked") + @Override + public DataCommitTransaction requestCommit(DataModification, DataObject> modification) { + // We should verify transaction + System.out.println("Coming in FlowDatacommitHandler"); + internalTransaction transaction = new internalTransaction(modification); + transaction.prepareUpdate(); + return transaction; + } + } + + private final class internalTransaction implements DataCommitTransaction, DataObject> { + + private final DataModification, DataObject> modification; + + @Override + public DataModification, DataObject> getModification() { + return modification; + } + + public internalTransaction(DataModification, DataObject> modification) { + this.modification = modification; + } + + Map, Group> additions = new HashMap<>(); + Map, Group> updates = new HashMap<>(); + Set> removals = new HashSet<>(); + + /** + * We create a plan which flows will be added, which will be updated and + * which will be removed based on our internal state. + * + */ + void prepareUpdate() { + + Set, DataObject>> puts = modification.getUpdatedConfigurationData().entrySet(); + for (Entry, DataObject> entry : puts) { + if (entry.getValue() instanceof Group) { + Group group = (Group) entry.getValue(); + preparePutEntry(entry.getKey(), group); + } + + } + + removals = modification.getRemovedConfigurationData(); + } + + private void preparePutEntry(InstanceIdentifier key, Group group) { + + Group original = originalSwGroupView.get(key); + if (original != null) { + // It is update for us + + updates.put(key, group); + } else { + // It is addition for us + + additions.put(key, group); + } + } + + /** + * We are OK to go with execution of plan + * + */ + @Override + public RpcResult finish() throws IllegalStateException { + + RpcResult rpcStatus = commitToPlugin(this); + // We return true if internal transaction is successful. + // return Rpcs.getRpcResult(true, null, Collections.emptySet()); + return rpcStatus; + } + + /** + * + * We should rollback our preparation + * + */ + @Override + public RpcResult rollback() throws IllegalStateException { + // NOOP - we did not modified any internal state during + // requestCommit phase + // return Rpcs.getRpcResult(true, null, Collections.emptySet()); + return Rpcs.getRpcResult(true, null, null); + + } + + } + + + final class GroupEventListener implements SalGroupListener { + + List addedGroups = new ArrayList<>(); + List removedGroups = new ArrayList<>(); + List updatedGroups = new ArrayList<>(); + + + @Override + public void onGroupAdded(GroupAdded notification) { + System.out.println("added Group.........................."); + addedGroups.add(notification); + } + + @Override + public void onGroupRemoved(GroupRemoved notification) { + // TODO Auto-generated method stub + + } + + @Override + public void onGroupUpdated(GroupUpdated notification) { + // TODO Auto-generated method stub + + } + } } diff --git a/opendaylight/md-sal/model/model-flow-base/src/main/yang/group-types.yang b/opendaylight/md-sal/model/model-flow-base/src/main/yang/group-types.yang index 8e77d26ea4..03e36924e7 100644 --- a/opendaylight/md-sal/model/model-flow-base/src/main/yang/group-types.yang +++ b/opendaylight/md-sal/model/model-flow-base/src/main/yang/group-types.yang @@ -41,6 +41,10 @@ module opendaylight-group-types { type string; } + leaf barrier { + type boolean; + } + container buckets { list bucket { key "order"; diff --git a/opendaylight/md-sal/model/model-flow-base/src/main/yang/meter-types.yang b/opendaylight/md-sal/model/model-flow-base/src/main/yang/meter-types.yang index 99d4588cbc..20353af785 100644 --- a/opendaylight/md-sal/model/model-flow-base/src/main/yang/meter-types.yang +++ b/opendaylight/md-sal/model/model-flow-base/src/main/yang/meter-types.yang @@ -85,6 +85,17 @@ module opendaylight-meter-types { type meter-id; } + leaf install { + type boolean; + } + leaf meter-name { + type string; + } + + leaf container-name { + type string; + } + container meter-band-headers { list meter-band-header { key "order"; diff --git a/opendaylight/md-sal/model/model-flow-base/src/main/yang/port-types.yang b/opendaylight/md-sal/model/model-flow-base/src/main/yang/port-types.yang index 6a83f75959..8338d185cc 100644 --- a/opendaylight/md-sal/model/model-flow-base/src/main/yang/port-types.yang +++ b/opendaylight/md-sal/model/model-flow-base/src/main/yang/port-types.yang @@ -20,10 +20,10 @@ module opendaylight-port-types { } typedef port-state { - type enumeration { - enum link-down; - enum blocked; - enum live; + type enumeration { + enum link-down; + enum blocked; + enum live; } } @@ -125,7 +125,7 @@ module opendaylight-port-types { uses common-port; leaf mask { - type uint32; + type port-config; description "Bitmap of OFPPC-* flags to be changed"; } @@ -135,7 +135,11 @@ module opendaylight-port-types { leaf port-name { type string; - } + } + + leaf barrier { + type boolean; + } } } } diff --git a/opendaylight/md-sal/model/model-flow-management/src/main/yang/meter-config.yang b/opendaylight/md-sal/model/model-flow-management/src/main/yang/meter-config.yang index 579ce70c62..111d3d60fa 100644 --- a/opendaylight/md-sal/model/model-flow-management/src/main/yang/meter-config.yang +++ b/opendaylight/md-sal/model/model-flow-management/src/main/yang/meter-config.yang @@ -11,11 +11,9 @@ module meter-management { } grouping meter-entry { - leaf node { type inv:node-ref; } - uses meter:meter; } diff --git a/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-capable-transaction.yang b/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-capable-transaction.yang new file mode 100644 index 0000000000..483c0c9e12 --- /dev/null +++ b/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-capable-transaction.yang @@ -0,0 +1,46 @@ +module flow-capable-transaction { + namespace "urn:opendaylight:flow:transaction"; + prefix type; + + import opendaylight-inventory {prefix inv; revision-date "2013-08-19";} + import yang-ext {prefix ext; revision-date "2013-07-09";} + + revision "2013-11-03" { + description "Initial revision"; + } + + typedef transaction-id { + type uint64; + } + + grouping transaction-aware { + leaf transaction-id { + type transaction-id; + } + } + + rpc get-next-transaction-id { + input { + leaf node { + ext:context-reference "inv:node-context"; + type inv:node-ref; + } + } + output { + uses transaction-aware; + } + } + + // Barier request? + rpc finish-transaction { + input { + leaf node { + ext:context-reference "inv:node-context"; + type inv:node-ref; + } + leaf transaction-id { + type transaction-id; + } + } + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/model/model-flow-service/src/main/yang/group-service.yang b/opendaylight/md-sal/model/model-flow-service/src/main/yang/group-service.yang index fba1c0829c..bb01035328 100644 --- a/opendaylight/md-sal/model/model-flow-service/src/main/yang/group-service.yang +++ b/opendaylight/md-sal/model/model-flow-service/src/main/yang/group-service.yang @@ -6,14 +6,14 @@ module sal-group { import opendaylight-inventory {prefix inv;revision-date "2013-08-19";} import ietf-inet-types {prefix inet;revision-date 2010-09-24;} import opendaylight-group-types {prefix group-type;revision-date 2013-10-18;} + import flow-capable-transaction {prefix tr;} revision "2013-09-18" { description "Initial revision of group service"; } grouping node-group { - uses "inv:node-context-ref"; - + uses "inv:node-context-ref"; uses group-type:group; } @@ -32,18 +32,30 @@ module sal-group { rpc add-group { input { uses node-group; + uses tr:transaction-aware; + } + output { + uses tr:transaction-aware; } } rpc remove-group { input { uses group-update; + uses tr:transaction-aware; + } + output { + uses tr:transaction-aware; } } rpc update-group { input { uses group-update; + uses tr:transaction-aware; + } + output { + uses tr:transaction-aware; } } diff --git a/opendaylight/md-sal/model/model-flow-service/src/main/yang/meter-service.yang b/opendaylight/md-sal/model/model-flow-service/src/main/yang/meter-service.yang index d3777ff332..c187181e5e 100644 --- a/opendaylight/md-sal/model/model-flow-service/src/main/yang/meter-service.yang +++ b/opendaylight/md-sal/model/model-flow-service/src/main/yang/meter-service.yang @@ -5,6 +5,7 @@ module sal-meter { import yang-ext {prefix ext; revision-date "2013-07-09";} import opendaylight-inventory {prefix inv;revision-date "2013-08-19";} import opendaylight-meter-types {prefix meter-type;revision-date "2013-09-18";} + import flow-capable-transaction {prefix tr;} revision "2013-09-18" { description "Initial revision of meter service"; @@ -31,18 +32,30 @@ module sal-meter { rpc add-meter { input { uses node-meter; + uses tr:transaction-aware; + } + output { + uses tr:transaction-aware; } } rpc remove-meter { input { uses node-meter; + uses tr:transaction-aware; + } + output { + uses tr:transaction-aware; } } rpc update-meter { input { uses meter-update; + uses tr:transaction-aware; + } + output { + uses tr:transaction-aware; } } diff --git a/opendaylight/md-sal/model/model-flow-service/src/main/yang/port-service.yang b/opendaylight/md-sal/model/model-flow-service/src/main/yang/port-service.yang new file mode 100644 index 0000000000..df527ef267 --- /dev/null +++ b/opendaylight/md-sal/model/model-flow-service/src/main/yang/port-service.yang @@ -0,0 +1,46 @@ +module sal-port { + namespace "urn:opendaylight:port:service"; + prefix port; + + import yang-ext {prefix ext; revision-date "2013-07-09";} + import opendaylight-inventory {prefix inv;revision-date "2013-08-19";} + import opendaylight-port-types {prefix port-type;revision-date "2013-09-25";} + + revision "2013-11-07" { + description "Initial revision of port service"; + } + + grouping node-port { + uses "inv:node-context-ref"; + + uses port-type:ofp-port-mod; + } + + /** Base configuration structure **/ + grouping port-update { + uses "inv:node-context-ref"; + + container original-port { + uses port-type:ofp-port-mod; + } + container updated-port { + uses port-type:ofp-port-mod; + } + } + + rpc update-port { + input { + uses port-update; + } + } + + rpc get-port { + output { + uses port-type:flow-capable-port; + } + } + + notification port-removed { + uses node-port; + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/model/model-flow-service/src/main/yang/table-service.yang b/opendaylight/md-sal/model/model-flow-service/src/main/yang/table-service.yang index e740f961d5..3a6f20f77d 100644 --- a/opendaylight/md-sal/model/model-flow-service/src/main/yang/table-service.yang +++ b/opendaylight/md-sal/model/model-flow-service/src/main/yang/table-service.yang @@ -5,13 +5,15 @@ module sal-table { import yang-ext {prefix ext; revision-date "2013-07-09";} import opendaylight-inventory {prefix inv;revision-date "2013-08-19";} import opendaylight-table-types {prefix table-type;revision-date "2013-10-26";} + import flow-capable-transaction {prefix tr;} revision "2013-10-26" { description "Initial revision of table service"; - } + } /** Base configuration structure **/ grouping table-update { + uses "inv:node-context-ref"; container original-table { uses table-type:table-features; } @@ -22,11 +24,11 @@ module sal-table { rpc update-table { input { - leaf node { - ext:context-reference "inv:node-context"; - type inv:node-ref; - } uses table-update; + uses tr:transaction-aware; + } + output { + uses tr:transaction-aware; } } } \ No newline at end of file -- 2.36.6