c993e7f29d9aa45f70d49f2d1a0c7089bf70db52
[netvirt.git] / aclservice / impl / src / main / java / org / opendaylight / netvirt / aclservice / listeners / AclNodeListener.java
1 /*
2  * Copyright (c) 2016, 2018 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netvirt.aclservice.listeners;
10
11 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
12
13 import java.math.BigInteger;
14 import java.util.Collections;
15 import javax.annotation.PostConstruct;
16 import javax.inject.Inject;
17 import javax.inject.Singleton;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
21 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
22 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
23 import org.opendaylight.genius.mdsalutil.MDSALUtil;
24 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
25 import org.opendaylight.genius.srm.RecoverableListener;
26 import org.opendaylight.genius.srm.ServiceRecoveryRegistry;
27 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
28 import org.opendaylight.netvirt.aclservice.utils.AclConstants;
29 import org.opendaylight.netvirt.aclservice.utils.AclNodeDefaultFlowsTxBuilder;
30 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig.SecurityGroupMode;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 /**
42  * Listener to handle flow capable node updates. Configures default ACL flows
43  * during when node is discovered.
44  */
45 @Singleton
46 public class AclNodeListener extends AsyncDataTreeChangeListenerBase<FlowCapableNode, AclNodeListener>
47         implements RecoverableListener {
48
49     private static final Logger LOG = LoggerFactory.getLogger(AclNodeListener.class);
50
51     private final IMdsalApiManager mdsalManager;
52     private final AclserviceConfig config;
53     private final DataBroker dataBroker;
54     private final ManagedNewTransactionRunner txRunner;
55     private final AclServiceUtils aclServiceUtils;
56     private final JobCoordinator jobCoordinator;
57
58     private SecurityGroupMode securityGroupMode = null;
59
60     @Inject
61     public AclNodeListener(final IMdsalApiManager mdsalManager, DataBroker dataBroker, AclserviceConfig config,
62             AclServiceUtils aclServiceUtils, JobCoordinator jobCoordinator,
63             ServiceRecoveryRegistry serviceRecoveryRegistry) {
64         super(FlowCapableNode.class, AclNodeListener.class);
65
66         this.mdsalManager = mdsalManager;
67         this.dataBroker = dataBroker;
68         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
69         this.config = config;
70         this.aclServiceUtils = aclServiceUtils;
71         this.jobCoordinator = jobCoordinator;
72         serviceRecoveryRegistry.addRecoverableListener(AclServiceUtils.getRecoverServiceRegistryKey(), this);
73     }
74
75     @Override
76     @PostConstruct
77     public void init() {
78         LOG.info("{} start", getClass().getSimpleName());
79         if (config != null) {
80             this.securityGroupMode = config.getSecurityGroupMode();
81         }
82         registerListener();
83         LOG.info("AclserviceConfig: {}", this.config);
84     }
85
86     @Override
87     public void registerListener() {
88         this.aclServiceUtils.createRemoteAclIdPool();
89         registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
90     }
91
92     @Override
93     public  void deregisterListener() {
94         super.deregisterListener();
95         this.aclServiceUtils.deleteRemoteAclIdPool();
96     }
97
98     @Override
99     public void close() {
100         super.close();
101         this.aclServiceUtils.deleteRemoteAclIdPool();
102     }
103
104     @Override
105     protected InstanceIdentifier<FlowCapableNode> getWildCardPath() {
106         return InstanceIdentifier.create(Nodes.class).child(Node.class).augmentation(FlowCapableNode.class);
107     }
108
109     @Override
110     protected void remove(InstanceIdentifier<FlowCapableNode> key, FlowCapableNode dataObjectModification) {
111         // do nothing
112     }
113
114     @Override
115     protected void update(InstanceIdentifier<FlowCapableNode> key, FlowCapableNode dataObjectModificationBefore,
116             FlowCapableNode dataObjectModificationAfter) {
117         // do nothing
118     }
119
120     @Override
121     protected void add(InstanceIdentifier<FlowCapableNode> key, FlowCapableNode dataObjectModification) {
122         NodeKey nodeKey = key.firstKeyOf(Node.class);
123         BigInteger dpId = MDSALUtil.getDpnIdFromNodeName(nodeKey.getId());
124         LOG.info("Received ACL node [{}] add event", dpId);
125
126         if (securityGroupMode != null && securityGroupMode != SecurityGroupMode.Stateful) {
127             LOG.error("Invalid security group mode ({}) obtained from AclserviceConfig. dpId={}", securityGroupMode,
128                     dpId);
129             return;
130         }
131         jobCoordinator.enqueueJob(String.valueOf(dpId),
132             () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
133                 new AclNodeDefaultFlowsTxBuilder(dpId, mdsalManager, config, tx).build();
134
135                 LOG.info("Adding default ACL flows for dpId={}", dpId);
136             })), AclConstants.JOB_MAX_RETRIES);
137
138         LOG.trace("FlowCapableNode (dpid: {}) add event is processed.", dpId);
139     }
140
141     @Override
142     protected AclNodeListener getDataTreeChangeListener() {
143         return AclNodeListener.this;
144     }
145 }