From: Rashmi Pujar Date: Fri, 22 Jan 2016 17:18:30 +0000 (-0500) Subject: Provide IntentServiceManager and MplsLabelManagerService classes X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=4640d73e6e16aa7ddc6ed7293e3cc0bffd9993e4;hp=5883189b599acad3c3cea665315774e9a447d2d6;p=vpnservice.git Provide IntentServiceManager and MplsLabelManagerService classes - YANG model to support failover constraints - slow & fast-reroute YANG model to support MPLS labels - Utility class to ad/remove intents from vpnservice with constraints set to intent object - Utility class to allocate unique MPLS label for each endpoint and label management. Labels are stored to operational data tree Change-Id: I905ad2c08c3cade745539b0cf489a71a98f24f78 Signed-off-by: Rashmi Pujar --- diff --git a/vpnintent/api/src/main/yang/vpnintent.yang b/vpnintent/api/src/main/yang/vpnintent.yang index bb2528f2..e9a971db 100644 --- a/vpnintent/api/src/main/yang/vpnintent.yang +++ b/vpnintent/api/src/main/yang/vpnintent.yang @@ -24,12 +24,29 @@ module vpnintent { } } + typedef failover-type { + type enumeration { + enum fast-reroute { + value 1; + } + enum slow-reroute { + value 2; + } + } + } + grouping vpn-intent { leaf vpn-name { type string; description "VPN name"; mandatory true; } + leaf path-protection { + type boolean; + } + leaf failover-type { + type failover-type; + } list endpoint { key "site-name"; uses endpoint-fields; @@ -58,12 +75,18 @@ module vpnintent { list label { key "label-id"; leaf "label-id"{ - type uint64; - description "MPLS or other label ID."; + type uint32 { + range "0 .. 524288"; + } + description "20 bit MPLS label ID"; mandatory true; } uses endpoint-fields; description "Keep track of MPLS/other label endpoint relation."; } } + + container mpls-labels { + uses labels; + } } diff --git a/vpnintent/impl/pom.xml b/vpnintent/impl/pom.xml index 546b1e13..ab00412e 100644 --- a/vpnintent/impl/pom.xml +++ b/vpnintent/impl/pom.xml @@ -21,6 +21,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL 1.2.0-SNAPSHOT + 1.5.2 @@ -34,6 +35,19 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL vpnintent-api ${project.version} + + + + org.opendaylight.nic + intent-api + ${nic.version} + + + org.opendaylight.nic + utils + ${nic.version} + + junit @@ -46,6 +60,18 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL mockito-all test + + org.powermock + powermock-api-mockito + ${powermock.version} + test + + + org.powermock + powermock-module-junit4 + ${powermock.version} + test + org.opendaylight.nic diff --git a/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/IntentServiceManager.java b/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/IntentServiceManager.java new file mode 100644 index 00000000..99d0edc9 --- /dev/null +++ b/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/IntentServiceManager.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2016 Inocybe Technologies and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vpnservice.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.nic.utils.MdsalUtils; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.constraints.rev150122.FailoverType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.Intents; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.IntentsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.Actions; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.ActionsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.Constraints; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.ConstraintsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.Subjects; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.SubjectsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action.allow.AllowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action.block.BlockBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.constraints.failover.constraint.FailoverConstraintBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.constraints.protection.constraint.ProtectionConstraintBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.end.point.group.EndPointGroup; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.end.point.group.EndPointGroupBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.Intent; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.IntentBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.IntentKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.types.rev150122.Uuid; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Preconditions; + + +public class IntentServiceManager { + + /** + * This class is used to build Intents object and + * write it to Network Intent Composition md-sal tree + * in order to create/delete intents between two endpoint groups. + */ + + private static final Logger LOG = LoggerFactory.getLogger(IntentServiceManager.class); + private static final short FIRST_SUBJECT = 1; + private static final short SECOND_SUBJECT = 2; + public static final String ACTION_ALLOW = "ALLOW"; + public static final String ACTION_BLOCK = "BLOCK"; + public static final String FAST_REROUTE = "fast-reroute"; + public static final String SLOW_REROUTE = "slow-reroute"; + private final DataBroker dataBroker; + private static final InstanceIdentifier INTENTS_IID = InstanceIdentifier.builder(Intents.class).build(); + private MdsalUtils mdsal; + + public IntentServiceManager(DataBroker dataBroker) { + this.dataBroker = dataBroker; + this.mdsal = new MdsalUtils(dataBroker); + } + + /** + * Create Intents object and write to to config tree to trigger intents + * @param src :Source Site Name + * @param dst :Destination Site Name + * @param intentAction :Intent verb: ALLOW or BLOCK + * @param failOverType + */ + public void addIntent(String src, String dst, String intentAction, String failOverType) { + Preconditions.checkNotNull(src); + Preconditions.checkNotNull(dst); + Preconditions.checkNotNull(intentAction); + + List intentList = null; + List subjects = createSubjects(dst, src); + List intentActions = createActions(intentAction); + List intentConstraints = createConstraints(failOverType); + + Intent intent = new IntentBuilder().setId(new Uuid(UUID.randomUUID().toString())) + .setSubjects(subjects).setActions(intentActions) + .setConstraints(intentConstraints) + .build(); + + Intents currentIntents = mdsal.read(LogicalDatastoreType.CONFIGURATION, INTENTS_IID); + if (currentIntents == null) { + intentList = new ArrayList<>(); + } else { + intentList = currentIntents.getIntent(); + } + intentList.add(intent); + Intents intents = new IntentsBuilder().setIntent(intentList).build(); + mdsal.put(LogicalDatastoreType.CONFIGURATION, INTENTS_IID, intents); + LOG.info("AddIntent: config populated: {}", intents); + } + + /** + * Delete an Intent + * @param id :Uuid of the Intent to be deleted + */ + public void removeIntent(Uuid id) { + Preconditions.checkNotNull(id); + InstanceIdentifier iid = InstanceIdentifier.create(Intents.class).child(Intent.class, new IntentKey(id)); + mdsal.delete(LogicalDatastoreType.CONFIGURATION, iid); + LOG.info("RemoveIntent succeeded"); + } + + /** + * Remove all associated intents by endpointGroupName + * @param endpointGroupName + */ + public void removeIntentsByEndpoint(String endpointGroupName) { + Preconditions.checkNotNull(endpointGroupName); + + Intents intents = mdsal.read(LogicalDatastoreType.CONFIGURATION, INTENTS_IID); + + if (intents != null && intents.getIntent() != null) { + for (Intent intent : intents.getIntent()) { + if (intent.getSubjects() != null && intent.getSubjects().size() > 0) { + String endpointValue = ""; + for (Subjects subject : intent.getSubjects()) { + if (subject + .getSubject() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup) { + org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup epg = (org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup) subject + .getSubject(); + endpointValue = epg.getEndPointGroup().getName(); + } else if (subject + .getSubject() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointSelector) { + org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointSelector epg = (org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointSelector) subject + .getSubject(); + endpointValue = epg.getEndPointSelector().getEndPointSelector(); + } else if (subject + .getSubject() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroupSelector) { + org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroupSelector epg = (org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroupSelector) subject + .getSubject(); + endpointValue = epg.getEndPointGroupSelector().getEndPointGroupSelector(); + } + if (endpointValue.equalsIgnoreCase(endpointGroupName)) { + removeIntent(intent.getId()); + LOG.info("Deleted Intent ID : {} for endpoint: {}", intent.getId(), endpointGroupName); + } + } + } + } + } + } + + /** + * Create a list of Intent actions + * @param intentAction + * @return :a list of Actions + */ + private List createActions(String intentAction) { + List actionsList = new ArrayList(); + short order = 1; + org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.Action action = null; + if (intentAction.equalsIgnoreCase(ACTION_ALLOW)) { + action = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action + .AllowBuilder().setAllow(new AllowBuilder().build()).build(); + } else if (intentAction.equalsIgnoreCase(ACTION_BLOCK)) { + action = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action + .BlockBuilder().setBlock(new BlockBuilder().build()).build(); + } + + Actions intentActions = new ActionsBuilder().setOrder(order).setAction(action).build(); + actionsList.add(intentActions); + return actionsList; + } + + /** + * Create a list of Intent subjects + * @param src :Source Site Name + * @param dst :Destination Site Name + * @return :a list of Subjects + */ + private List createSubjects(String src, String dst) { + List subjectList = new ArrayList(); + + EndPointGroup endpointGroupFrom = new EndPointGroupBuilder().setName(src).build(); + org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup fromEPG = + new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject + .EndPointGroupBuilder().setEndPointGroup(endpointGroupFrom).build(); + Subjects subjects1 = new SubjectsBuilder().setOrder(FIRST_SUBJECT).setSubject(fromEPG).build(); + + EndPointGroup endpointGroupTo = new EndPointGroupBuilder().setName(dst).build(); + org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup toEPG = + new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject + .EndPointGroupBuilder().setEndPointGroup(endpointGroupTo).build(); + Subjects subjects2 = new SubjectsBuilder().setOrder(SECOND_SUBJECT).setSubject(toEPG).build(); + + subjectList.add(subjects1); + subjectList.add(subjects2); + return subjectList; + } + + /** + * Create a list of Intent constraints + * @param failOverType :Type of failover, fast-reroute or slow-reroute + * @return + */ + private List createConstraints(String failOverType) { + List intentConstraints = new ArrayList(); + if (failOverType==null) { + return intentConstraints; + } + short order = 1; + org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.Constraints + protectionConstraint = null; + org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.Constraints + failoverConstraint = null; + if (failOverType.equals(FAST_REROUTE)) { + protectionConstraint = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent + .constraints.constraints.ProtectionConstraintBuilder() + .setProtectionConstraint(new ProtectionConstraintBuilder().setIsProtected(true).build()).build(); + failoverConstraint = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints + .constraints.FailoverConstraintBuilder() + .setFailoverConstraint(new FailoverConstraintBuilder().setFailoverSelector(FailoverType.FastReroute).build()) + .build(); + } else if (failOverType.equals(SLOW_REROUTE)) { + protectionConstraint = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent + .constraints.constraints.ProtectionConstraintBuilder() + .setProtectionConstraint(new ProtectionConstraintBuilder().setIsProtected(true).build()).build(); + failoverConstraint = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints + .constraints.FailoverConstraintBuilder() + .setFailoverConstraint(new FailoverConstraintBuilder().setFailoverSelector(FailoverType.SlowReroute).build()) + .build(); + } + Constraints constraint1 = new ConstraintsBuilder().setOrder(order).setConstraints(protectionConstraint).build(); + Constraints constraint2 = new ConstraintsBuilder().setOrder(++order).setConstraints(failoverConstraint).build(); + intentConstraints.add(constraint1); + intentConstraints.add(constraint2); + return intentConstraints; + } +} diff --git a/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/MplsLabelManagerService.java b/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/MplsLabelManagerService.java new file mode 100644 index 00000000..48b4986a --- /dev/null +++ b/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/MplsLabelManagerService.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2016 Inocybe Technologies and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vpnservice.impl; + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.nic.utils.MdsalUtils; +import org.opendaylight.vpnservice.utils.IidFactory; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.MplsLabels; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.Label; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.LabelBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.LabelKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.Endpoint; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MplsLabelManagerService { + + private static final Logger LOG = LoggerFactory.getLogger(MplsLabelManagerService.class); + private static final Integer MAX_MPLS_LABEL = 524288; + private static InstanceIdentifier