/* * Copyright (c) 2015 Hewlett-Packard Development Company 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.nic.neutron.integration.impl; import com.google.common.base.Optional; import com.google.gson.Gson; 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.nic.listeners.api.*; import org.opendaylight.nic.utils.FlowAction; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.Intents; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.ActionsBuilder; 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.ConditionsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.ConstraintsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.IntentsBuilder; 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.constraints.constraints.ClassificationConstraint; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.constraints.ClassificationConstraintBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.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.types.rev150122.Uuid; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.IntentKey; import org.opendaylight.nic.neutron.NeutronSecurityRule; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionEgress; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionIngress; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; public class SecRuleNotificationSubscriberImpl implements IEventListener<NicNotification> { private NeutronSecurityRule securityRule; private static final int FIRST_SUBJECT = 1; private static final int SECOND_SUBJECT = 2; public static final InstanceIdentifier<Intents> INTENTS_IID = InstanceIdentifier.builder(Intents.class).build(); private static final Logger LOG = LoggerFactory.getLogger(SecRuleNotificationSubscriberImpl.class); private DataBroker dataBroker; private Map<String, org.opendaylight.yang.gen.v1.urn.opendaylight.intent.types.rev150122.Uuid> ruleToIntentMap; public SecRuleNotificationSubscriberImpl(DataBroker db) { this.dataBroker = db; this.ruleToIntentMap = new HashMap<>(); } @Override public void handleEvent(NicNotification event) { if (SecurityRuleAdded.class.isInstance(event)) { //Translate Security rules into intents SecurityRuleAdded securityRuleAdded = (SecurityRuleAdded) event; securityRule = securityRuleAdded.getSecurityRule(); Intent intent = createIntent(); ruleToIntentMap.put(securityRule.getSecurityRuleID(), intent.getId()); addIntentToMDSAL(intent, FlowAction.ADD_FLOW); } else if (SecurityRuleDeleted.class.isInstance(event)) { SecurityRuleDeleted securityRuleDeleted = (SecurityRuleDeleted) event; securityRule = (NeutronSecurityRule) securityRuleDeleted.getSecurityRule(); Uuid uuid = ruleToIntentMap.get(securityRule.getSecurityRuleID()); removeIntent(uuid); } else if(SecurityRuleUpdated.class.isInstance(event)) { //TODO: } } private void addIntentToMDSAL(Intent intent, FlowAction flowAction) { Intents intents; List<Intent> listOfIntents = listIntents(true); try { listOfIntents.add(intent); intents = new IntentsBuilder().setIntent(listOfIntents).build(); // Place default config data in data store tree WriteTransaction tx = dataBroker.newWriteOnlyTransaction(); tx.put(LogicalDatastoreType.CONFIGURATION, INTENTS_IID, intents); // Perform the tx.submit synchronously tx.submit(); } catch (Exception e) { LOG.error("addIntent: failed: {}", e); } } //TODO: Move to utils folder as code repetition in NicProvider public void removeIntent(Uuid id) { try { InstanceIdentifier<Intent> iid = InstanceIdentifier.create(Intents.class) .child(Intent.class, new IntentKey(id)); // Removes default config data in data store tree WriteTransaction tx = dataBroker.newWriteOnlyTransaction(); tx.delete(LogicalDatastoreType.CONFIGURATION, iid); // Perform the tx.submit synchronously tx.submit(); } catch (Exception e) { LOG.info("RemoveIntent: failed: {}", e); } } //TODO: Move to utils folder as code repetition in NicProvider public List<Intent> listIntents(boolean isConfigurationDatastore) { List<Intent> listOfIntents = null; try { ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction(); Optional<Intents> intents = tx.read((isConfigurationDatastore) ? LogicalDatastoreType.CONFIGURATION : LogicalDatastoreType.OPERATIONAL, INTENTS_IID).checkedGet(); if(intents.isPresent()) { listOfIntents = intents.get().getIntent(); } else { LOG.info("Intent tree was empty!"); } } catch (Exception e) { LOG.error("ListIntents: failed: {}", e.getMessage(), e); } if (listOfIntents == null) { listOfIntents = new ArrayList<Intent>(); } return listOfIntents; } /** * Converts the security rule to intent with the ports, protocols and EtherType as * a constraint */ private Intent createIntent() { String fromString = "any"; String toString = "any"; IntentBuilder intentBuilder = new IntentBuilder(); UUID uuid = UUID.randomUUID(); intentBuilder. setId(new Uuid(uuid.toString())); if (securityRule.getSecurityRuleDirection().compareTo("DirectionEgress") == 0) { if (securityRule.getSecurityRuleRemoteIpPrefix() != null) { toString = securityRule.getSecurityRuleRemoteIpPrefix(); if(toString.contains("0.0.0.0")) { toString = "any"; } } } else if (securityRule.getSecurityRuleDirection().compareTo("DirectionIngress") == 0) { if (securityRule.getSecurityRuleRemoteIpPrefix() != null) { fromString = securityRule.getSecurityRuleRemoteIpPrefix(); if(fromString.contains("0.0.0.0")) { fromString = "any"; } } } intentBuilder.setActions(Arrays.asList( new ActionsBuilder().setOrder((short) 1).setAction( new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action .AllowBuilder().setAllow(new AllowBuilder().build()).build()).build())); Subjects to = subject((short) SECOND_SUBJECT, toString); Subjects from = subject((short) FIRST_SUBJECT, fromString); intentBuilder.setSubjects(Arrays.asList(from, to)); ClassificationConstraint constraint = classificationConstraint(); intentBuilder.setConstraints(Arrays.asList(new ConstraintsBuilder().setOrder((short) 1).setConstraints(constraint).build())); intentBuilder. setId(new Uuid(uuid.toString())); return intentBuilder.build(); } private Subjects subject(short order, String name) { return new SubjectsBuilder() .setSubject( new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroupBuilder() .setEndPointGroup( new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.end.point.group.EndPointGroupBuilder() .setName(name).build()).build()).setOrder(order).build(); } private ClassificationConstraint classificationConstraint() { //use gson to convert Neutron Security object to json, then add to constraint Gson gson = new Gson(); String portObject = gson.toJson(securityRule); return new ClassificationConstraintBuilder() .setClassificationConstraint(new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.constraints.classification.constraint.ClassificationConstraintBuilder() .setClassifier(portObject).build()).build(); } }