/*
* Copyright (c) 2016 Cisco Systems, Inc. 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.groupbasedpolicy.renderer.ios_xe_provider.impl.writer;
import javax.annotation.Nonnull;
import java.util.List;
import com.google.common.base.Optional;
import com.google.common.util.concurrent.CheckedFuture;
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.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308.ClassNameType;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308.Native;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.ServicePolicy;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChain.Direction;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapKey;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.Interface;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMap;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapKey;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._interface.GigabitEthernet;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._interface.GigabitEthernetKey;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassKey;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePath;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePathKey;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfName;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfNameKey;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Purpose: Util class for every policy writer
*/
public class PolicyWriterUtil {
private static final Logger LOG = LoggerFactory.getLogger(PolicyWriterUtil.class);
private PolicyWriterUtil() {
throw new IllegalAccessError("instance of util class not supported");
}
public static boolean writeClassMap(@Nonnull final ClassMap classMap,
final PolicyManagerImpl.PolicyMapLocation policyMapLocation) {
boolean result = true;
final DataBroker mountpoint = policyMapLocation.getMountpoint();
final NodeId nodeId = policyMapLocation.getNodeId();
final InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(classMap);
netconfWrite(mountpoint, classMapIid, classMap);
// Check
final java.util.Optional<ClassMap> checkCreated = java.util.Optional.ofNullable(netconfRead(mountpoint, classMapIid));
if (checkCreated.isPresent()) {
LOG.trace("Created class-map {} on node {}", classMap.getName(), nodeId.getValue());
} else {
LOG.warn("Failed to create class-map {} on node {}", classMap.getName(), nodeId.getValue());
result = false;
}
return result;
}
public static boolean removeClassMap(final ClassMap classMap, final PolicyManagerImpl.PolicyMapLocation location) {
final DataBroker mountpoint = location.getMountpoint();
final NodeId nodeId = location.getNodeId();
boolean result = true;
if (classMap == null) {
return true;
}
final InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(classMap);
netconfDeleteIfPresent(mountpoint, classMapIid);
// Check
final java.util.Optional<ClassMap> checkCreated = java.util.Optional.ofNullable(netconfRead(mountpoint, classMapIid));
if (checkCreated.isPresent()) {
LOG.warn("Failed to remove class-map {} on node {}", classMap.getName(), nodeId.getValue());
result = false;
} else {
LOG.trace("Class-map {} removed from node {}", classMap.getName(), nodeId.getValue());
}
return result;
}
public static boolean writePolicyMap(final PolicyMap policyMap, final PolicyManagerImpl.PolicyMapLocation location) {
final DataBroker mountpoint = location.getMountpoint();
final NodeId nodeId = location.getNodeId();
final InstanceIdentifier<PolicyMap> policyMapIid = policyMapInstanceIdentifier(policyMap.getName());
netconfWrite(mountpoint, policyMapIid, policyMap);
// Check
if (netconfRead(mountpoint, policyMapIid) == null) {
LOG.warn("Failed to create policy-map {} on node {}", policyMap.getName(), nodeId.getValue());
return false;
}
LOG.trace("Created policy-map {} on node {}", policyMap.getName(), nodeId.getValue());
return true;
}
public static boolean removePolicyMap(final PolicyManagerImpl.PolicyMapLocation location) {
final String policyMapName = location.getPolicyMapName();
final DataBroker mountpoint = location.getMountpoint();
final NodeId nodeId = location.getNodeId();
final InstanceIdentifier<PolicyMap> policyMapIid = policyMapInstanceIdentifier(policyMapName);
netconfDeleteIfPresent(mountpoint, policyMapIid);
// Check
if (netconfRead(mountpoint, policyMapIid) != null) {
LOG.warn("Failed to remove policy-map {} from node {}", policyMapName, nodeId.getValue());
return false;
}
LOG.trace("Policy-map {} removed from node {}", policyMapName, nodeId.getValue());
return true;
}
public static boolean writePolicyMapEntry(final Class policyMapEntry,
final PolicyManagerImpl.PolicyMapLocation location) {
final String policyMapName = location.getPolicyMapName();
final NodeId nodeId = location.getNodeId();
final DataBroker mountpoint = location.getMountpoint();
final ClassNameType entryName = policyMapEntry.getName();
final InstanceIdentifier<Class> policyMapEntryIid = policyMapEntryInstanceIdentifier(policyMapName, entryName);
netconfWrite(mountpoint, policyMapEntryIid, policyMapEntry);
// Check
if (netconfRead(mountpoint, policyMapEntryIid) == null) {
LOG.warn("Failed to create entry in policy-map {} on node {}. Entry: {}", policyMapName, nodeId.getValue(),
policyMapEntry);
return false;
}
LOG.trace("Created entry in policy-map {} on node {}. Entry: {}", policyMapName, nodeId.getValue(), policyMapEntry);
return true;
}
public static boolean removePolicyMapEntry(final Class policyMapEntry, final PolicyManagerImpl.PolicyMapLocation location) {
final String policyMapName = location.getPolicyMapName();
final DataBroker mountpoint = location.getMountpoint();
final NodeId nodeId = location.getNodeId();
if (policyMapEntry == null) {
return true;
}
boolean result = true;
final InstanceIdentifier policyMapEntryIid = policyMapEntryInstanceIdentifier(policyMapName, policyMapEntry.getName());
if (netconfDeleteIfPresent(mountpoint, policyMapEntryIid)) {
LOG.trace("Policy-map entry {} removed from node {}", policyMapEntry.getName(), nodeId.getValue());
} else {
LOG.warn("Failed to remove policy-map entry {} from node {}", policyMapEntry.getName(), nodeId.getValue());
result = false;
}
return result;
}
public static boolean writeInterface(final PolicyManagerImpl.PolicyMapLocation location) {
final String policyMapName = location.getPolicyMapName();
final String interfaceName = location.getInterfaceName();
final NodeId nodeId = location.getNodeId();
final DataBroker mountpoint = location.getMountpoint();
final ServicePolicy servicePolicy = PolicyManagerUtil.createServicePolicy(policyMapName, Direction.Input);
final InstanceIdentifier<ServicePolicy> servicePolicyIid = interfaceInstanceIdentifier(interfaceName);
if (netconfWrite(mountpoint, servicePolicyIid, servicePolicy)) {
LOG.trace("Service-policy interface {}, bound to policy-map {} created on node {}",
interfaceName, policyMapName, nodeId.getValue());
return true;
} else {
LOG.warn("Failed to write service-policy interface {} to policy-map {} on node {}",
interfaceName, policyMapName, nodeId.getValue());
return false;
}
}
public static boolean removeInterface(final PolicyManagerImpl.PolicyMapLocation location) {
final String policyMapName = location.getPolicyMapName();
final String interfaceName = location.getInterfaceName();
final DataBroker mountpoint = location.getMountpoint();
final NodeId nodeId = location.getNodeId();
final InstanceIdentifier<ServicePolicy> servicePolicyIid = interfaceInstanceIdentifier(interfaceName);
if (netconfDeleteIfPresent(mountpoint, servicePolicyIid)) {
LOG.trace("Service-policy interface {}, removed from node {}",
interfaceName, policyMapName, nodeId.getValue());
return true;
} else {
LOG.warn("Failed to remove service-policy interface {} from node {}",
interfaceName, policyMapName, nodeId.getValue());
return false;
}
}
public static boolean writeRemote(final ServiceFfName remoteForwarder,
final PolicyManagerImpl.PolicyMapLocation location) {
// TODO writeNE
final DataBroker mountpoint = location.getMountpoint();
final NodeId nodeId = location.getNodeId();
if (remoteForwarder == null) {
return true;
}
boolean result = true;
final InstanceIdentifier<ServiceFfName> forwarderIid = remoteSffInstanceIdentifier(remoteForwarder);
if (netconfWrite(mountpoint, forwarderIid, remoteForwarder)) {
LOG.trace("Remote forwarder {} created on node {}", remoteForwarder.getName(), nodeId.getValue());
} else {
LOG.warn("Failed to create remote forwarder {} on node {}", remoteForwarder.getName(), nodeId.getValue());
result = false;
}
return result;
}
public static boolean removeRemote(final ServiceFfName remoteForwarder, final PolicyManagerImpl.PolicyMapLocation location) {
final DataBroker mountpoint = location.getMountpoint();
final NodeId nodeId = location.getNodeId();
if (remoteForwarder == null) {
return true;
}
boolean result = true;
final InstanceIdentifier<ServiceFfName> forwarderIid = remoteSffInstanceIdentifier(remoteForwarder);
if (netconfDeleteIfPresent(mountpoint, forwarderIid)) {
LOG.trace("Remote forwarder {} removed from node {}", remoteForwarder.getName(), nodeId.getValue());
} else {
LOG.warn("Failed to remove forwarder {} from node {}", remoteForwarder.getName(), nodeId.getValue());
result = false;
}
return result;
}
public static boolean writeServicePath(final ServiceChain serviceChain,
final PolicyManagerImpl.PolicyMapLocation location) {
final DataBroker mountpoint = location.getMountpoint();
final NodeId nodeId = location.getNodeId();
boolean result = true;
for (ServicePath entry : serviceChain.getServicePath()) {
final InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(entry.getKey());
if (netconfWrite(mountpoint, servicePathIid, entry)) {
LOG.trace("Service-path with ID: {} created on node {}", entry.getServicePathId(), nodeId.getValue());
} else {
LOG.warn("Failed to create service-path with ID: {} on node {}", entry.getServicePathId(), nodeId.getValue());
result = false;
}
}
return result;
}
public static boolean removeServicePath(final ServiceChain serviceChain, final PolicyManagerImpl.PolicyMapLocation location) {
final DataBroker mountpoint = location.getMountpoint();
final NodeId nodeId = location.getNodeId();
if (serviceChain == null) {
return true;
}
boolean result = true;
List<ServicePath> servicePaths = serviceChain.getServicePath();
if (servicePaths == null || servicePaths.isEmpty()) {
return true;
}
for (ServicePath servicePath : servicePaths) {
final InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(servicePath.getKey());
if (netconfDeleteIfPresent(mountpoint, servicePathIid)) {
LOG.trace("Service-path with ID: {} removed from node {}", servicePath.getServicePathId(),
nodeId.getValue());
} else {
LOG.warn("Failed to remove service-path with ID: {} from node {}", servicePath.getServicePathId(),
nodeId.getValue());
result = false;
}
}
return result;
}
private static InstanceIdentifier<ClassMap> classMapInstanceIdentifier(final ClassMap classMap) {
return InstanceIdentifier.builder(Native.class)
.child(ClassMap.class, new ClassMapKey(classMap.getName())).build();
}
public static InstanceIdentifier<PolicyMap> policyMapInstanceIdentifier(final String policyMapName) {
return InstanceIdentifier.builder(Native.class)
.child(PolicyMap.class, new PolicyMapKey(policyMapName)).build();
}
private static InstanceIdentifier<Class> policyMapEntryInstanceIdentifier(final String policyMapName,
final ClassNameType classNameType) {
return InstanceIdentifier.builder(Native.class)
.child(PolicyMap.class, new PolicyMapKey(policyMapName))
.child(Class.class, new ClassKey(classNameType)).build();
}
public static InstanceIdentifier<ServicePolicy> interfaceInstanceIdentifier(final String ethernetName) {
return InstanceIdentifier.builder(Native.class)
.child(Interface.class)
.child(GigabitEthernet.class, new GigabitEthernetKey(ethernetName))
.child(ServicePolicy.class)
.build();
}
private static InstanceIdentifier<ServiceFfName> remoteSffInstanceIdentifier(final ServiceFfName sffName) {
return InstanceIdentifier.builder(Native.class)
.child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain.class)
.child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServiceFunctionForwarder.class)
.child(ServiceFfName.class, new ServiceFfNameKey(sffName.getName())).build();
}
private static InstanceIdentifier<ServicePath> servicePathInstanceIdentifier(final ServicePathKey key) {
return InstanceIdentifier.builder(Native.class)
.child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain.class)
.child(ServicePath.class, key).build();
}
private static <U extends DataObject> boolean netconfWrite(final DataBroker mountpoint,
final InstanceIdentifier<U> addIID,
final U data) {
// TODO consider to move netconfWrite, netconfDeleteIfPresent and netconfRead methods (+ methods in NetconfTransactionCreator) to gbp base
final java.util.Optional<WriteTransaction> optionalWriteTransaction =
NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
if (!optionalWriteTransaction.isPresent()) {
LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
return false;
}
final WriteTransaction transaction = optionalWriteTransaction.get();
try {
transaction.merge(LogicalDatastoreType.CONFIGURATION, addIID, data);
final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = transaction.submit();
submitFuture.checkedGet();
return true;
} catch (TransactionCommitFailedException e) {
LOG.error("Write transaction failed to {}", e.getMessage());
} catch (Exception e) {
LOG.error("Failed to .. {}", e.getMessage());
}
return false;
}
private static <U extends DataObject> boolean netconfDeleteIfPresent(final DataBroker mountpoint,
final InstanceIdentifier<U> deleteIID) {
if (netconfRead(mountpoint, deleteIID) == null) {
LOG.trace("Remove action called on non-existing element, skipping. Iid was: {}, data provider: {} ",
deleteIID, mountpoint);
return true;
}
final java.util.Optional<WriteTransaction> optionalWriteTransaction =
NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
if (!optionalWriteTransaction.isPresent()) {
LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
return false;
}
final WriteTransaction transaction = optionalWriteTransaction.get();
try {
transaction.delete(LogicalDatastoreType.CONFIGURATION, deleteIID);
final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = transaction.submit();
submitFuture.checkedGet();
return true;
} catch (TransactionCommitFailedException e) {
LOG.error("Write transaction failed to {}", e.getMessage());
} catch (Exception e) {
LOG.error("Failed to .. {}", e.getMessage());
}
return false;
}
public static <U extends DataObject> U netconfRead(final DataBroker mountpoint,
final InstanceIdentifier<U> readIID) {
final java.util.Optional<ReadOnlyTransaction> optionalReadTransaction =
NetconfTransactionCreator.netconfReadOnlyTransaction(mountpoint);
if (!optionalReadTransaction.isPresent()) {
LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
return null;
}
final ReadOnlyTransaction transaction = optionalReadTransaction.get();
try {
final CheckedFuture<Optional<U>, ReadFailedException> submitFuture =
transaction.read(LogicalDatastoreType.CONFIGURATION, readIID);
final Optional<U> optional = submitFuture.checkedGet();
if (optional != null && optional.isPresent()) {
transaction.close(); // Release lock
return optional.get();
}
} catch (ReadFailedException e) {
LOG.warn("Read transaction failed to {} ", e);
} catch (Exception e) {
LOG.error("Failed to .. {}", e.getMessage());
}
return null;
}
}