<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.genius</groupId>
+ <artifactId>networkutils</artifactId>
+ <version>${genius.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.infrautils</groupId>
<artifactId>jobcoordinator-api</artifactId>
<version>${infrautils.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-access-control-list</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>yang-ext</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>aclservice-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>coe-api</artifactId>
<artifactId>utils.southbound-utils</artifactId>
<version>${ovsdb.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.serviceutils</groupId>
+ <artifactId>listener-api</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.serviceutils</groupId>
<artifactId>tools-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.aries.blueprint</groupId>
+ <artifactId>blueprint-maven-plugin-annotation</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.awaitility</groupId>
+ <artifactId>awaitility</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <version>${controller.mdsal.version}</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.opendaylight.genius</groupId>
- <artifactId>mdsalutil-api</artifactId>
+ <artifactId>testutils</artifactId>
<version>${genius.version}</version>
+ <scope>test</scope>
</dependency>
<dependency>
<groupId>org.opendaylight.genius</groupId>
- <artifactId>networkutils</artifactId>
- <version>0.6.0-SNAPSHOT</version>
+ <artifactId>mdsalutil-testutils</artifactId>
+ <version>${genius.version}</version>
+ <scope>test</scope>
</dependency>
<dependency>
- <groupId>org.apache.aries.blueprint</groupId>
- <artifactId>blueprint-maven-plugin-annotation</artifactId>
+ <groupId>org.opendaylight.serviceutils</groupId>
+ <artifactId>tools-testutils</artifactId>
+ <version>${serviceutils.version}</version>
+ <scope>test</scope>
</dependency>
</dependencies>
--- /dev/null
+/*
+ * Copyright (c) 2018 Red Hat, 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.netvirt.coe.listeners;
+
+import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
+import static org.opendaylight.netvirt.coe.utils.AceNetworkPolicyUtils.buildAcl;
+import static org.opendaylight.netvirt.coe.utils.AceNetworkPolicyUtils.getAclNameFromPolicy;
+import static org.opendaylight.netvirt.coe.utils.AclUtils.getAclIid;
+
+import javax.annotation.Nonnull;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.apache.aries.blueprint.annotation.service.Reference;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.infra.RetryingManagedNewTransactionRunner;
+import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
+import org.opendaylight.serviceutils.tools.mdsal.listener.AbstractSyncDataTreeChangeListener;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.NetworkPolicies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.network.policies.NetworkPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.rev181205.K8s;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class NetworkPolicyListener extends AbstractSyncDataTreeChangeListener<NetworkPolicy> {
+ private static final Logger LOG = LoggerFactory.getLogger(NetworkPolicyListener.class);
+ private final RetryingManagedNewTransactionRunner txRunner;
+
+ @Inject
+ public NetworkPolicyListener(@Reference DataBroker dataBroker) {
+ super(dataBroker, LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(K8s.class).child(NetworkPolicies.class).child(NetworkPolicy.class));
+ this.txRunner = new RetryingManagedNewTransactionRunner(dataBroker);
+ }
+
+ @Override
+ public void add(@Nonnull InstanceIdentifier<NetworkPolicy> instanceIdentifier, @Nonnull NetworkPolicy policy) {
+ LOG.info("add: id: {}\npolicy: {}", instanceIdentifier, policy);
+ updateAcl(policy, false);
+ }
+
+ @Override
+ public void remove(@Nonnull InstanceIdentifier<NetworkPolicy> instanceIdentifier, @Nonnull NetworkPolicy policy) {
+ LOG.info("remove: id: {}\npolicy: {}", instanceIdentifier, policy);
+ updateAcl(policy, true);
+ }
+
+ @Override
+ public void update(@Nonnull InstanceIdentifier<NetworkPolicy> instanceIdentifier,
+ @Nonnull NetworkPolicy oldPolicy, @Nonnull NetworkPolicy policy) {
+ LOG.info("update: id: {}\nold policy: {}\nnew policy: {}", instanceIdentifier, oldPolicy, policy);
+ updateAcl(policy, false);
+ }
+
+ private void updateAcl(@Nonnull NetworkPolicy policy, boolean isDeleted) {
+ LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
+ String aclName = getAclNameFromPolicy(policy);
+ Acl acl = buildAcl(policy, isDeleted);
+ InstanceIdentifier<Acl> aclIid = getAclIid(aclName);
+ // write the ace, and the api will create the acl parent if needed
+ tx.put(aclIid, acl, true);
+ }), LOG, "Failed to add acl from policy: {}", policy);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2018 Red Hat, 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.netvirt.coe.utils;
+
+import static org.opendaylight.netvirt.coe.utils.AclUtils.DIRECTION_MAP;
+import static org.opendaylight.netvirt.coe.utils.AclUtils.buildName;
+import static org.opendaylight.netvirt.coe.utils.NetworkPolicyUtils.PROTOCOL_MAP;
+
+import java.util.ArrayList;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.ActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.MatchesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.actions.packet.handling.PermitBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIpBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160218.acl.transport.header.fields.DestinationPortRangeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.egress.rule.NetworkPolicyEgressRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.egress.rule.network.policy.egress.rule.EgressPorts;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.egress.rule.network.policy.egress.rule.To;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.ingress.rule.NetworkPolicyIngressRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.ingress.rule.network.policy.ingress.rule.From;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.ingress.rule.network.policy.ingress.rule.IngressPorts;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.network.policies.NetworkPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.peer.NetworkPolicyPeer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.port.NetworkPolicyPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.spec.NetworkPolicySpec;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.spec.network.policy.spec.Egress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.spec.network.policy.spec.Ingress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionEgress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionIngress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttrBuilder;
+
+public final class AceNetworkPolicyUtils {
+ private AceNetworkPolicyUtils() {}
+
+ @Nonnull
+ public static String getAclNameFromPolicy(@Nonnull NetworkPolicy policy) {
+ String aclName = "";
+ if (policy.getUuid() != null) {
+ aclName = policy.getUuid().getValue();
+ }
+ return aclName;
+ }
+
+ // TODO map empty rules:
+ // ingress:empty - no incoming allowed
+ // egress:empty - no outgoing allowed
+ @Nonnull
+ public static Acl buildAcl(@Nonnull NetworkPolicy policy, boolean isDeleted) {
+ String aclName = getAclNameFromPolicy(policy);
+ ArrayList<Ace> aceList = new ArrayList<>();
+
+ if (policy.getNetworkPolicySpec() != null) {
+ NetworkPolicySpec spec = policy.getNetworkPolicySpec();
+ if (spec.getIngress() != null) {
+ for (Ingress ingress : spec.getIngress()) {
+ NetworkPolicyIngressRule rule = ingress.getNetworkPolicyIngressRule();
+ if (rule.getIngressPorts() != null) {
+ for (IngressPorts port : rule.getIngressPorts()) {
+ if (port.getNetworkPolicyPort() != null) {
+ Ace ace = buildPortAce(isDeleted, aclName,
+ DirectionIngress.class, port.getNetworkPolicyPort());
+ aceList.add(ace);
+ }
+ }
+ }
+ if (rule.getFrom() != null) {
+ for (From from: rule.getFrom()) {
+ if (from.getNetworkPolicyPeer() != null) {
+ Ace ace = buildPolicyAce(isDeleted, aclName,
+ DirectionIngress.class, from.getNetworkPolicyPeer());
+ aceList.add(ace);
+ }
+ }
+ }
+ }
+ }
+
+ if (spec.getEgress() != null) {
+ for (Egress egress : spec.getEgress()) {
+ NetworkPolicyEgressRule rule = egress.getNetworkPolicyEgressRule();
+ if (rule.getEgressPorts() != null) {
+ for (EgressPorts port : rule.getEgressPorts()) {
+ if (port.getNetworkPolicyPort() != null) {
+ Ace ace = buildPortAce(isDeleted, aclName,
+ DirectionEgress.class, port.getNetworkPolicyPort());
+ aceList.add(ace);
+ }
+ }
+ }
+ if (rule.getTo() != null) {
+ for (To to: rule.getTo()) {
+ if (to.getNetworkPolicyPeer() != null) {
+ Ace ace = buildPolicyAce(isDeleted, aclName,
+ DirectionEgress.class, to.getNetworkPolicyPeer());
+ aceList.add(ace);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ AccessListEntriesBuilder accessListEntriesBuilder = new AccessListEntriesBuilder();
+ accessListEntriesBuilder.setAce(aceList);
+
+ AclBuilder aclBuilder = new AclBuilder();
+ aclBuilder.setAclName(aclName);
+ aclBuilder.setAclType(Ipv4Acl.class);
+ aclBuilder.setAccessListEntries(accessListEntriesBuilder.build());
+ aclBuilder.withKey(new AclKey(aclBuilder.getAclName(), aclBuilder.getAclType()));
+ return aclBuilder.build();
+ }
+
+ @Nonnull
+ public static AceBuilder getAceBuilder(boolean isDeleted, String ruleName,
+ @Nonnull Class<? extends DirectionBase> direction,
+ @Nonnull AceIpBuilder aceIpBuilder) {
+ MatchesBuilder matchesBuilder = new MatchesBuilder();
+ matchesBuilder.setAceType(aceIpBuilder.build());
+ ActionsBuilder actionsBuilder = new ActionsBuilder();
+ actionsBuilder.setPacketHandling(new PermitBuilder().setPermit(true).build());
+
+ AceBuilder aceBuilder = new AceBuilder();
+ aceBuilder.setRuleName(ruleName);
+ aceBuilder.withKey(new AceKey(aceBuilder.getRuleName()));
+ aceBuilder.setMatches(matchesBuilder.build());
+ aceBuilder.setActions(actionsBuilder.build());
+
+ SecurityRuleAttrBuilder securityRuleAttrBuilder = new SecurityRuleAttrBuilder();
+ securityRuleAttrBuilder.setDeleted(isDeleted);
+ securityRuleAttrBuilder.setDirection(direction);
+ aceBuilder.addAugmentation(SecurityRuleAttr.class, securityRuleAttrBuilder.build());
+ return aceBuilder;
+ }
+
+ @Nonnull
+ public static Ace buildPortAce(boolean isDeleted, @Nonnull String aclName,
+ @Nonnull Class<? extends DirectionBase> direction,
+ @Nonnull NetworkPolicyPort port) {
+ AceIpBuilder aceIpBuilder = new AceIpBuilder();
+ String ruleName = AclUtils.buildName(aclName, DIRECTION_MAP.get(direction), "port");
+ if (port.getProtocol() != null) {
+ aceIpBuilder.setProtocol(PROTOCOL_MAP.get(port.getProtocol()));
+ ruleName = buildName(ruleName, port.getProtocol().toString());
+ }
+
+ // TODO: map a named port
+ if (port.getPort() != null) {
+ DestinationPortRangeBuilder portRangeBuilder = new DestinationPortRangeBuilder();
+ PortNumber portNumber = new PortNumber(Integer.parseInt(port.getPort()));
+ portRangeBuilder.setLowerPort(portNumber);
+ portRangeBuilder.setUpperPort(portNumber);
+ aceIpBuilder.setDestinationPortRange(portRangeBuilder.build());
+ ruleName = buildName(ruleName, portNumber.getValue().toString());
+ }
+
+ AceBuilder aceBuilder = getAceBuilder(isDeleted, ruleName, direction, aceIpBuilder);
+
+ return aceBuilder.build();
+ }
+
+ @Nonnull
+ public static Ace buildPolicyAce(boolean isDeleted, @Nonnull String aclName,
+ @Nonnull Class<? extends DirectionBase> direction,
+ @Nonnull NetworkPolicyPeer peer) {
+ AceIpBuilder aceIpBuilder = new AceIpBuilder();
+ String ruleName = AclUtils.buildName(aclName, DIRECTION_MAP.get(direction), "peer");
+
+ if (peer.getIpBlock() != null) {
+ // TODO handle except
+ String cidr = peer.getIpBlock().getCidr();
+ ruleName = AclUtils.buildName(ruleName, "cidr", cidr);
+ AceIpv4Builder aceIpv4Builder = new AceIpv4Builder();
+ if (direction == DirectionIngress.class) {
+ aceIpv4Builder.setSourceIpv4Network(new Ipv4Prefix(cidr));
+ } else {
+ aceIpv4Builder.setDestinationIpv4Network(new Ipv4Prefix(cidr));
+ }
+ aceIpBuilder.setAceIpVersion(aceIpv4Builder.build());
+ }
+ // TODO handle pod-selector and namespace-selector
+
+ AceBuilder aceBuilder = getAceBuilder(isDeleted, ruleName, direction, aceIpBuilder);
+
+ return aceBuilder.build();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2018 Red Hat, 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.netvirt.coe.utils;
+
+import com.google.common.collect.ImmutableBiMap;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntries;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionEgress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionIngress;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public final class AclUtils {
+ public static final String INGRESS = "ingress";
+ public static final String EGRESS = "egress";
+ public static final ImmutableBiMap<Class<? extends DirectionBase>, String> DIRECTION_MAP = ImmutableBiMap.of(
+ DirectionIngress.class, INGRESS,
+ DirectionEgress.class, EGRESS
+ );
+
+ private AclUtils() {}
+
+ @Nonnull
+ public static InstanceIdentifier<Acl> getAclIid(@Nonnull String aclName) {
+ return InstanceIdentifier
+ .builder(AccessLists.class)
+ .child(Acl.class, new AclKey(aclName, Ipv4Acl.class))
+ .build();
+ }
+
+ @Nonnull
+ public static InstanceIdentifier<Ace> getAceIid(@Nonnull String aclName, @Nonnull String ruleName) {
+ return getAclIid(aclName).builder()
+ .child(AccessListEntries.class)
+ .child(Ace.class, new AceKey(ruleName))
+ .build();
+ }
+
+ @Nonnull
+ public static String buildName(String... args) {
+ return String.join("_", args);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2018 Red Hat, 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.netvirt.coe.utils;
+
+import com.google.common.collect.ImmutableBiMap;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.core.rev181205.Protocol;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.meta.v1.rev181205.label.selector.MatchLabels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.meta.v1.rev181205.label.selector.MatchLabelsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.PolicyType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.ip.block.IpBlock;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.ip.block.IpBlockBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.NetworkPolicies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.egress.rule.NetworkPolicyEgressRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.egress.rule.NetworkPolicyEgressRuleBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.egress.rule.network.policy.egress.rule.EgressPorts;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.egress.rule.network.policy.egress.rule.EgressPortsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.egress.rule.network.policy.egress.rule.To;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.egress.rule.network.policy.egress.rule.ToBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.ingress.rule.NetworkPolicyIngressRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.ingress.rule.NetworkPolicyIngressRuleBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.ingress.rule.network.policy.ingress.rule.From;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.ingress.rule.network.policy.ingress.rule.FromBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.ingress.rule.network.policy.ingress.rule.IngressPorts;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.ingress.rule.network.policy.ingress.rule.IngressPortsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.network.policies.NetworkPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.network.policies.NetworkPolicyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.network.policies.NetworkPolicyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.peer.NetworkPolicyPeer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.peer.NetworkPolicyPeerBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.port.NetworkPolicyPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.port.NetworkPolicyPortBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.spec.NetworkPolicySpec;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.spec.NetworkPolicySpecBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.spec.network.policy.spec.Egress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.spec.network.policy.spec.EgressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.spec.network.policy.spec.Ingress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.spec.network.policy.spec.IngressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.spec.network.policy.spec.PodSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.spec.network.policy.spec.PodSelectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.rev181205.K8s;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public final class NetworkPolicyUtils {
+ public static final ImmutableBiMap<Protocol, Short> PROTOCOL_MAP = ImmutableBiMap.of(
+ Protocol.TCP, (short)6,
+ Protocol.UDP, (short)17,
+ Protocol.SCTP, (short)132
+ );
+
+ private NetworkPolicyUtils() {}
+
+ @Nonnull
+ public static MatchLabels buildMatchLabels(@Nonnull String key, @Nonnull String value) {
+ return new MatchLabelsBuilder().setKey(key).setValue(value).build();
+ }
+
+ @Nonnull
+ public static PodSelector buildPodSelector(@Nonnull List<MatchLabels> matchLabels) {
+ return new PodSelectorBuilder().setMatchLabels(matchLabels).build();
+ }
+
+ @Nonnull
+ public static InstanceIdentifier<NetworkPolicy> getNetworkPolicyIid(@Nonnull String uuid) {
+ return InstanceIdentifier.create(K8s.class).child(NetworkPolicies.class)
+ .child(NetworkPolicy.class, new NetworkPolicyKey(new Uuid(uuid)));
+ }
+
+ @Nonnull
+ public static IpBlock buildIpBlock(@Nonnull String cidr, @Nullable List<String> except) {
+ IpBlockBuilder ipBlockBuilder = new IpBlockBuilder().setCidr(cidr);
+
+ if (except != null && !except.isEmpty()) {
+ ipBlockBuilder.setExcept(except);
+ }
+
+ return new IpBlockBuilder().setCidr(cidr).setExcept(except).build();
+ }
+
+ // TODO add pod and namespace selector handling
+ @Nonnull
+ public static NetworkPolicyPeer buildNetworkPolicyPeer(@Nonnull IpBlock ipBlock) {
+ return new NetworkPolicyPeerBuilder().setIpBlock(ipBlock).build();
+ }
+
+ @Nonnull
+ public static NetworkPolicyPort buildNetworkPolicyPort(@Nonnull String port, @Nonnull Protocol protocol) {
+ return new NetworkPolicyPortBuilder().setPort(port).setProtocol(protocol).build();
+ }
+
+ @Nonnull
+ public static IngressPorts buildIngressPorts(@Nonnull NetworkPolicyPort port) {
+ return new IngressPortsBuilder().setNetworkPolicyPort(port).build();
+ }
+
+ @Nonnull
+ public static From buildFrom(@Nonnull NetworkPolicyPeer peer) {
+ return new FromBuilder().setNetworkPolicyPeer(peer).build();
+ }
+
+ @Nonnull
+ public static EgressPorts buildEgressPorts(@Nonnull NetworkPolicyPort port) {
+ return new EgressPortsBuilder().setNetworkPolicyPort(port).build();
+ }
+
+ @Nonnull
+ public static To buildTo(@Nonnull NetworkPolicyPeer peer) {
+ return new ToBuilder().setNetworkPolicyPeer(peer).build();
+ }
+
+ @Nonnull
+ public static NetworkPolicyIngressRule buildNetworkPolicyIngressRule(@Nullable List<IngressPorts> ports,
+ @Nullable List<From> fromList) {
+
+ NetworkPolicyIngressRuleBuilder networkPolicyIngressRuleBuilder = new NetworkPolicyIngressRuleBuilder();
+
+ if (ports != null && !ports.isEmpty()) {
+ networkPolicyIngressRuleBuilder.setIngressPorts(ports);
+ }
+ if (fromList != null && !fromList.isEmpty()) {
+ networkPolicyIngressRuleBuilder.setFrom(fromList);
+ }
+
+ return networkPolicyIngressRuleBuilder.build();
+ }
+
+ @Nonnull
+ public static NetworkPolicyEgressRule buildNetworkPolicyEgressRule(@Nullable List<EgressPorts> ports,
+ @Nullable List<To> toList) {
+
+ NetworkPolicyEgressRuleBuilder networkPolicyEgressRuleBuilder = new NetworkPolicyEgressRuleBuilder();
+
+ if (ports != null && !ports.isEmpty()) {
+ networkPolicyEgressRuleBuilder.setEgressPorts(ports);
+ }
+ if (toList != null && !toList.isEmpty()) {
+ networkPolicyEgressRuleBuilder.setTo(toList);
+ }
+
+ return networkPolicyEgressRuleBuilder.build();
+ }
+
+ @Nonnull
+ public static Ingress buildIngress(@Nonnull NetworkPolicyIngressRule rule) {
+ return new IngressBuilder().setNetworkPolicyIngressRule(rule).build();
+ }
+
+ @Nonnull
+ public static Egress buildEgress(@Nonnull NetworkPolicyEgressRule rule) {
+ return new EgressBuilder().setNetworkPolicyEgressRule(rule).build();
+ }
+
+ @Nonnull
+ public static NetworkPolicySpec buildNetworkPolicySpec(@Nonnull PodSelector podSelector,
+ @Nullable List<Ingress> ingress,
+ @Nullable List<Egress> egress,
+ @Nullable List<PolicyType> policyTypes) {
+ NetworkPolicySpecBuilder networkPolicySpecBuilder = new NetworkPolicySpecBuilder().setPodSelector(podSelector);
+
+ if (ingress != null && !ingress.isEmpty()) {
+ networkPolicySpecBuilder.setIngress(ingress);
+ }
+ if (egress != null && !egress.isEmpty()) {
+ networkPolicySpecBuilder.setEgress(egress);
+ }
+ if (policyTypes != null && !policyTypes.isEmpty()) {
+ networkPolicySpecBuilder.setPolicyTypes(policyTypes);
+ }
+
+ return networkPolicySpecBuilder.build();
+ }
+
+ @Nonnull
+ public static NetworkPolicy buildNetworkPolicy(@Nonnull String uuid, @Nullable String name,
+ @Nullable NetworkPolicySpec spec) {
+ NetworkPolicyBuilder networkPolicyBuilder = new NetworkPolicyBuilder().setUuid(new Uuid(uuid));
+ if (name != null) {
+ networkPolicyBuilder.setName(name);
+ }
+ if (spec != null) {
+ networkPolicyBuilder.setNetworkPolicySpec(spec);
+ }
+
+ return networkPolicyBuilder.build();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2018 Red Hat, 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.netvirt.coe.listeners;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
+import static org.opendaylight.netvirt.coe.utils.AclUtils.getAceIid;
+import static org.opendaylight.netvirt.coe.utils.AclUtils.getAclIid;
+import static org.opendaylight.netvirt.coe.utils.NetworkPolicyUtils.buildEgress;
+import static org.opendaylight.netvirt.coe.utils.NetworkPolicyUtils.buildEgressPorts;
+import static org.opendaylight.netvirt.coe.utils.NetworkPolicyUtils.buildFrom;
+import static org.opendaylight.netvirt.coe.utils.NetworkPolicyUtils.buildIngress;
+import static org.opendaylight.netvirt.coe.utils.NetworkPolicyUtils.buildIngressPorts;
+import static org.opendaylight.netvirt.coe.utils.NetworkPolicyUtils.buildIpBlock;
+import static org.opendaylight.netvirt.coe.utils.NetworkPolicyUtils.buildMatchLabels;
+import static org.opendaylight.netvirt.coe.utils.NetworkPolicyUtils.buildNetworkPolicy;
+import static org.opendaylight.netvirt.coe.utils.NetworkPolicyUtils.buildNetworkPolicyEgressRule;
+import static org.opendaylight.netvirt.coe.utils.NetworkPolicyUtils.buildNetworkPolicyIngressRule;
+import static org.opendaylight.netvirt.coe.utils.NetworkPolicyUtils.buildNetworkPolicyPeer;
+import static org.opendaylight.netvirt.coe.utils.NetworkPolicyUtils.buildNetworkPolicyPort;
+import static org.opendaylight.netvirt.coe.utils.NetworkPolicyUtils.buildNetworkPolicySpec;
+import static org.opendaylight.netvirt.coe.utils.NetworkPolicyUtils.buildPodSelector;
+import static org.opendaylight.netvirt.coe.utils.NetworkPolicyUtils.buildTo;
+import static org.opendaylight.netvirt.coe.utils.NetworkPolicyUtils.getNetworkPolicyIid;
+
+import com.google.common.base.Optional;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.test.AbstractConcurrentDataBrokerTest;
+import org.opendaylight.genius.infra.RetryingManagedNewTransactionRunner;
+import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.core.rev181205.Protocol;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.meta.v1.rev181205.label.selector.MatchLabels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.PolicyType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.egress.rule.NetworkPolicyEgressRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.egress.rule.network.policy.egress.rule.EgressPorts;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.egress.rule.network.policy.egress.rule.To;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.ingress.rule.NetworkPolicyIngressRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.ingress.rule.network.policy.ingress.rule.From;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.ingress.rule.network.policy.ingress.rule.IngressPorts;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.network.policies.NetworkPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.peer.NetworkPolicyPeer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.spec.NetworkPolicySpec;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.spec.network.policy.spec.Egress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.spec.network.policy.spec.Ingress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.k8s.network.policy.rev181205.network.policy.spec.network.policy.spec.PodSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetworkPolicyListenerTest extends AbstractConcurrentDataBrokerTest {
+ private static final Logger LOG = LoggerFactory.getLogger(NetworkPolicyListenerTest.class);
+ private RetryingManagedNewTransactionRunner txRunner;
+ private Verifications verifications;
+
+ @Before
+ public void setUp() {
+ DataBroker dataBroker = getDataBroker();
+ NetworkPolicyListener networkPolicyListener = new NetworkPolicyListener(dataBroker);
+ networkPolicyListener.register();
+ verifications = new Verifications(dataBroker);
+ txRunner = new RetryingManagedNewTransactionRunner(dataBroker, 3);
+ }
+
+ @Test
+ public void testNetworkPolicy() throws ExecutionException, InterruptedException {
+ String policyUuid = "11111111-1111-1111-1111-111111111111";
+ String policyName = "network-policy-1";
+
+ NetworkPolicy networkPolicy1 = buildNetworkPolicy1(policyUuid, policyName);
+ InstanceIdentifier<NetworkPolicy> networkPolicyIid = getNetworkPolicyIid(policyUuid);
+
+ // write and verify NetworkPolicy to ds
+ LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
+ tx.put(networkPolicyIid, networkPolicy1, true);
+ }), LOG, "writing network policy").get();
+
+ LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
+ Optional<NetworkPolicy> networkPolicyOptional = tx.read(networkPolicyIid).get();
+ assertTrue(networkPolicyOptional.isPresent());
+ assertEquals(networkPolicyOptional.get().getName(), policyName);
+ }), LOG, "reading network policy {}", networkPolicyIid);
+
+ // wait and verify for the NetworkPolicyListener to write an acl from the policy just written
+ InstanceIdentifier<Acl> aclIid = getAclIid(policyUuid);
+ verifications.awaitForData(CONFIGURATION, aclIid);
+ verifyAcl(policyUuid);
+
+ // verify children Ace's have been written
+ verifyAce(policyUuid, "11111111-1111-1111-1111-111111111111_ingress_port_TCP_53", false);
+ verifyAce(policyUuid, "11111111-1111-1111-1111-111111111111_ingress_port_UDP_53", false);
+ verifyAce(policyUuid, "11111111-1111-1111-1111-111111111111_ingress_peer_cidr_10.1.1.1/16", false);
+ verifyAce(policyUuid, "11111111-1111-1111-1111-111111111111_egress_port_TCP_53", false);
+ verifyAce(policyUuid, "11111111-1111-1111-1111-111111111111_egress_port_UDP_53", false);
+ verifyAce(policyUuid, "11111111-1111-1111-1111-111111111111_egress_peer_cidr_10.1.1.1/16", false);
+
+ // Update the policy and verify the acl is updated
+
+ NetworkPolicy networkPolicy2 = buildNetworkPolicy2(policyUuid, policyName + "updated");
+ LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
+ tx.put(networkPolicyIid, networkPolicy2, true);
+ }), LOG, "writing network policy").get();
+
+ LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
+ Optional<NetworkPolicy> networkPolicyOptional = tx.read(networkPolicyIid).get();
+ assertTrue(networkPolicyOptional.isPresent());
+ assertEquals(networkPolicyOptional.get().getName(), policyName + "updated");
+ }), LOG, "reading network policy {}", networkPolicyIid);
+
+ // wait and verify for the NetworkPolicyListener to write an acl from the policy just written
+ verifications.awaitForData(CONFIGURATION, aclIid);
+ verifyAcl(policyUuid);
+ // verify children Ace's have been written
+ verifyAce(policyUuid, "11111111-1111-1111-1111-111111111111_ingress_port_TCP_69", false);
+ verifyAce(policyUuid, "11111111-1111-1111-1111-111111111111_ingress_port_UDP_69", false);
+ verifyAce(policyUuid, "11111111-1111-1111-1111-111111111111_ingress_peer_cidr_10.2.1.1/16", false);
+
+ // wait and verify a deleted policy will updates acls to deleted
+ LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
+ tx.delete(networkPolicyIid);
+ }), LOG, "deleting network policy").get();
+ verifications.awaitForData(CONFIGURATION, aclIid);
+ verifyAce(policyUuid, "11111111-1111-1111-1111-111111111111_ingress_port_TCP_69", true);
+ }
+
+ private void verifyAcl(String policyUuid) {
+ InstanceIdentifier<Acl> aclIid = getAclIid(policyUuid);
+ LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
+ Optional<Acl> aclOptional = tx.read(aclIid).get();
+ assertTrue(aclOptional.isPresent());
+ LOG.info("acl: {}", aclOptional.get());
+ }), LOG, "reading acl {}", aclIid);
+ }
+
+ private void verifyAce(String policyUuid, String ruleName, boolean isDeleted) {
+ InstanceIdentifier<Ace> aceIid = getAceIid(policyUuid, ruleName);
+ LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
+ Optional<Ace> aceOptional = tx.read(aceIid).get();
+ assertTrue(aceOptional.isPresent());
+ assertEquals(aceOptional.get().augmentation(SecurityRuleAttr.class).isDeleted(), isDeleted);
+ LOG.info("ace: {}", aceOptional.get());
+ }), LOG, "reading ace {}", aceIid);
+ }
+
+ private NetworkPolicy buildNetworkPolicy1(String policyUuid, String policyName) {
+ List<IngressPorts> ingressPorts = Arrays.asList(
+ buildIngressPorts(buildNetworkPolicyPort("53", Protocol.TCP)),
+ buildIngressPorts(buildNetworkPolicyPort("53", Protocol.UDP)));
+ List<String> except = Arrays.asList("10.1.2.1/24", "10.1.3.1/24");
+ NetworkPolicyPeer ingressNetworkPolicyPeer = buildNetworkPolicyPeer(buildIpBlock("10.1.1.1/16", except));
+ List<From> fromList = Collections.singletonList(buildFrom(ingressNetworkPolicyPeer));
+ NetworkPolicyIngressRule networkPolicyIngressRule = buildNetworkPolicyIngressRule(ingressPorts, fromList);
+ List<Ingress> ingressList = Collections.singletonList(buildIngress(networkPolicyIngressRule));
+
+ List<EgressPorts> egressPorts = Arrays.asList(
+ buildEgressPorts(buildNetworkPolicyPort("53", Protocol.TCP)),
+ buildEgressPorts(buildNetworkPolicyPort("53", Protocol.UDP)));
+ List<String> exceptEgress = Arrays.asList("10.1.2.1/24", "10.1.3.1/24");
+ NetworkPolicyPeer egressNetworkPolicyPeer = buildNetworkPolicyPeer(buildIpBlock("10.1.1.1/16", exceptEgress));
+ List<To> toList = Collections.singletonList(buildTo(egressNetworkPolicyPeer));
+ NetworkPolicyEgressRule networkPolicyEgressRule = buildNetworkPolicyEgressRule(egressPorts, toList);
+ List<Egress> egressList = Collections.singletonList(buildEgress(networkPolicyEgressRule));
+
+ List<PolicyType> policyTypes = Collections.singletonList(PolicyType.Egress);
+ MatchLabels matchLabels = buildMatchLabels("app", "db");
+ PodSelector podSelector = buildPodSelector(Collections.singletonList(matchLabels));
+ NetworkPolicySpec networkPolicySpec = buildNetworkPolicySpec(podSelector, ingressList, egressList, policyTypes);
+ return buildNetworkPolicy(policyUuid, policyName, networkPolicySpec);
+ }
+
+ private NetworkPolicy buildNetworkPolicy2(String policyUuid, String policyName) {
+ List<IngressPorts> ingressPorts = Arrays.asList(
+ buildIngressPorts(buildNetworkPolicyPort("69", Protocol.TCP)),
+ buildIngressPorts(buildNetworkPolicyPort("69", Protocol.UDP)));
+ List<String> except = Arrays.asList("10.2.2.1/24", "10.2.3.1/24");
+ NetworkPolicyPeer ingressNetworkPolicyPeer = buildNetworkPolicyPeer(buildIpBlock("10.2.1.1/16", except));
+ List<From> fromList = Collections.singletonList(buildFrom(ingressNetworkPolicyPeer));
+ NetworkPolicyIngressRule networkPolicyIngressRule = buildNetworkPolicyIngressRule(ingressPorts, fromList);
+ List<Ingress> ingressList = Collections.singletonList(buildIngress(networkPolicyIngressRule));
+
+ List<EgressPorts> egressPorts = Arrays.asList(
+ buildEgressPorts(buildNetworkPolicyPort("53", Protocol.TCP)),
+ buildEgressPorts(buildNetworkPolicyPort("53", Protocol.UDP)));
+ List<String> exceptEgress = Arrays.asList("10.1.2.1/24", "10.1.3.1/24");
+ NetworkPolicyPeer egressNetworkPolicyPeer = buildNetworkPolicyPeer(buildIpBlock("10.1.1.1/16", exceptEgress));
+ List<To> toList = Collections.singletonList(buildTo(egressNetworkPolicyPeer));
+ NetworkPolicyEgressRule networkPolicyEgressRule = buildNetworkPolicyEgressRule(egressPorts, toList);
+ List<Egress> egressList = Collections.singletonList(buildEgress(networkPolicyEgressRule));
+
+ List<PolicyType> policyTypes = Collections.singletonList(PolicyType.Egress);
+ MatchLabels matchLabels = buildMatchLabels("app", "db");
+ PodSelector podSelector = buildPodSelector(Collections.singletonList(matchLabels));
+ NetworkPolicySpec networkPolicySpec = buildNetworkPolicySpec(podSelector, ingressList, egressList, policyTypes);
+ return buildNetworkPolicy(policyUuid, policyName, networkPolicySpec);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2018 Red Hat, 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.netvirt.coe.listeners;
+
+import java.util.concurrent.TimeUnit;
+import org.awaitility.Awaitility;
+import org.awaitility.core.ConditionFactory;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.genius.infra.Datastore;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class Verifications {
+ private static final Logger LOG = LoggerFactory.getLogger(Verifications.class);
+ private static final int AWAIT_TIMEOUT = 10;
+ private static final int AWAIT_INTERVAL = 1000;
+ private final ConditionFactory awaiter;
+ private final ManagedNewTransactionRunner txRunner;
+
+ Verifications(final DataBroker dataBroker) {
+ this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
+ this.awaiter = getAwaiter();
+ }
+
+ private ConditionFactory getAwaiter() {
+ return Awaitility.await("TestableListener")
+ .atMost(AWAIT_TIMEOUT, TimeUnit.SECONDS)//TODO constant
+ .pollInterval(AWAIT_INTERVAL, TimeUnit.MILLISECONDS);
+ }
+
+ <D extends Datastore> void awaitForData(Class<D> datastoreType, InstanceIdentifier<? extends DataObject> iid) {
+ awaiter.with()
+ .conditionEvaluationListener(condition -> LOG.info("{} ({} ms of {} s)",
+ condition.getDescription(), condition.getElapsedTimeInMS(), AWAIT_TIMEOUT))
+ .until(() ->
+ txRunner.applyWithNewReadOnlyTransactionAndClose(datastoreType, tx -> tx.read(iid)).get().isPresent());
+ }
+
+ <D extends Datastore> void awaitForDataDelete(Class<D> datastoreType,
+ InstanceIdentifier<? extends DataObject> iid) {
+ awaiter.with()
+ .conditionEvaluationListener(condition -> LOG.info("{} ({} ms of {} s)",
+ condition.getDescription(), condition.getElapsedTimeInMS(), AWAIT_TIMEOUT))
+ .until(() ->
+ !txRunner.applyWithNewReadOnlyTransactionAndClose(datastoreType, tx -> tx.read(iid)).get().isPresent());
+ }
+}