blob: 8d824f7c33e8453005f144d3c3ed3729e0518835 [file] [log] [blame]
Aaron Kruglikov309068e2017-03-17 15:25:54 -07001/*
2 * Copyright 2017-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.netconf.storeadapter;
18
19import com.google.common.annotations.Beta;
20import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
26import org.onosproject.config.DynamicConfigEvent;
27import org.onosproject.config.DynamicConfigListener;
28import org.onosproject.config.DynamicConfigService;
29import org.onosproject.config.Filter;
30import org.onosproject.mastership.MastershipService;
31import org.onosproject.net.DeviceId;
32import org.onosproject.net.resource.Resource;
33import org.onosproject.netconf.client.NetconfTranslator;
34import org.onosproject.netconf.client.NetconfTranslator.OperationType;
Sithara Punnassery425837f2017-03-21 12:58:00 -070035import org.onosproject.netconf.NetconfException;
36import org.onosproject.netconf.NetconfController;
37import java.net.URI;
38import java.net.URISyntaxException;
Aaron Kruglikov309068e2017-03-17 15:25:54 -070039import org.onosproject.yang.model.DataNode;
Sithara Punnassery425837f2017-03-21 12:58:00 -070040import org.onosproject.yang.model.LeafNode;
Aaron Kruglikov309068e2017-03-17 15:25:54 -070041import org.onosproject.yang.model.ResourceId;
42import org.onosproject.yang.runtime.DefaultResourceData;
43import org.slf4j.Logger;
44import org.slf4j.LoggerFactory;
45
46import java.io.IOException;
47
Sithara Punnassery425837f2017-03-21 12:58:00 -070048
Aaron Kruglikov309068e2017-03-17 15:25:54 -070049@Beta
50@Component(immediate = true)
Sithara Punnassery425837f2017-03-21 12:58:00 -070051public class NetconfActiveComponent implements DynamicConfigListener {
Aaron Kruglikov309068e2017-03-17 15:25:54 -070052
Sithara Punnassery425837f2017-03-21 12:58:00 -070053 private static final Logger log = LoggerFactory.getLogger(NetconfActiveComponent.class);
Aaron Kruglikov309068e2017-03-17 15:25:54 -070054 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Sithara Punnassery425837f2017-03-21 12:58:00 -070055 protected DynamicConfigService cfgService;
Aaron Kruglikov309068e2017-03-17 15:25:54 -070056 public static final String DEVNMSPACE = "namespace1";
57
58 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
59 protected NetconfTranslator netconfTranslator;
60
61 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
62 protected MastershipService mastershipService;
63
Sithara Punnassery425837f2017-03-21 12:58:00 -070064 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
65 protected NetconfController controller;
66
Aaron Kruglikov309068e2017-03-17 15:25:54 -070067 private ResourceId resId = new ResourceId.Builder()
68 .addBranchPointSchema("device", DEVNMSPACE )
69 .build();
70 @Activate
71 protected void activate() {
Sithara Punnassery425837f2017-03-21 12:58:00 -070072 cfgService.addListener(this);
Aaron Kruglikov309068e2017-03-17 15:25:54 -070073 log.info("Started");
74 }
75
76 @Deactivate
77 protected void deactivate() {
Sithara Punnassery425837f2017-03-21 12:58:00 -070078 cfgService.removeListener(this);
Aaron Kruglikov309068e2017-03-17 15:25:54 -070079 log.info("Stopped");
80 }
81
82 @Override
83 public boolean isRelevant(DynamicConfigEvent event) {
Sithara Punnassery425837f2017-03-21 12:58:00 -070084 if (event.subject().equals(resId)) {
85 return true;
86 } else {
Aaron Kruglikov309068e2017-03-17 15:25:54 -070087 return false;
88 }
89 }
Sithara Punnassery425837f2017-03-21 12:58:00 -070090
91 public boolean isMaster(DeviceId deviceId) {
92 if (mastershipService.isLocalMaster(deviceId)) {
93 return true;
94 } else {
95 return false;
96 }
97 }
98
Aaron Kruglikov309068e2017-03-17 15:25:54 -070099 @Override
100 public void event(DynamicConfigEvent event) {
101 Filter filt = new Filter();
Sithara Punnassery425837f2017-03-21 12:58:00 -0700102 DataNode node = cfgService.readNode(event.subject(), filt);
103 DeviceId deviceId = getDeviceId(node);
104 if (!isMaster(deviceId)) {
105 log.info("NetConfListener: not master, ignoring config for {}", event.type());
106 return;
107 }
108 initiateConnection(deviceId);
Aaron Kruglikov309068e2017-03-17 15:25:54 -0700109 switch (event.type()) {
110 case NODE_ADDED:
111 case NODE_UPDATED:
112 case NODE_REPLACED:
113 configUpdate(node, deviceId, event.subject());
114 break;
115 case NODE_DELETED:
116 configDelete(node, deviceId, event.subject());
117 break;
118 case UNKNOWN_OPRN:
119 default:
120 log.warn("NetConfListener: unknown event: {}", event.type());
121 break;
122 }
123 }
124
125 /**
126 * Performs the delete operation corresponding to the passed event.
127 * @param node a relevant dataNode
128 * @param deviceId the deviceId of the device to be updated
129 * @param resourceId the resourceId of the root of the subtree to be edited
130 * @return true if the update succeeds false otherwise
131 */
132 private boolean configDelete(DataNode node, DeviceId deviceId, ResourceId resourceId) {
133 return parseAndEdit(node, deviceId, resourceId, OperationType.DELETE);
134 }
135
136 /**
137 * Performs the update operation corresponding to the passed event.
138 * @param node a relevant dataNode
139 * @param deviceId the deviceId of the device to be updated
140 * @param resourceId the resourceId of the root of the subtree to be edited
141 * @return true if the update succeeds false otherwise
142 */
143 private boolean configUpdate(DataNode node, DeviceId deviceId, ResourceId resourceId) {
144 return parseAndEdit(node, deviceId, resourceId, OperationType.REPLACE);
145 }
146
147 /**
148 * Parses the incoming event and pushes configuration to the effected
149 * device.
150 * @param node the dataNode effecting a particular device of which this node
151 * is master
152 * @param deviceId the deviceId of the device to be modified
153 * @param resourceId the resourceId of the root of the subtree to be edited
154 * @param operationType the type of editing to be performed
155 * @return true if the operation succeeds, false otherwise
156 */
157 private boolean parseAndEdit(DataNode node, DeviceId deviceId,
158 ResourceId resourceId,
159 NetconfTranslator.OperationType operationType) {
160 try {
161 return netconfTranslator.editDeviceConfig(
162 deviceId,
163 DefaultResourceData.builder()
164 .addDataNode(node)
165 .resourceId(resourceId)
166 .build(),
167 operationType);
168 } catch (IOException e) {
169 e.printStackTrace();
170 return false;
171 }
172 }
173
174 /**
Sithara Punnassery425837f2017-03-21 12:58:00 -0700175 * Retrieves device id from Data node.
176 *
177 * @param node the node associated with the event
Aaron Kruglikov309068e2017-03-17 15:25:54 -0700178 * @return the deviceId of the effected device
179 */
Sithara Punnassery425837f2017-03-21 12:58:00 -0700180 public DeviceId getDeviceId(DataNode node) {
181 String[] temp;
182 String ip, port;
183 if (node.type() == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
184 temp = ((LeafNode) node).asString().split("\\:");
185 if (temp.length != 3) {
186 throw new RuntimeException(new NetconfException("Invalid device id form, cannot apply"));
187 }
188 ip = temp[1];
189 port = temp[2];
190 } else {
191 throw new RuntimeException(new NetconfException("Invalid device id type, cannot apply"));
192 }
193 try {
194 return DeviceId.deviceId(new URI("netconf", ip + ":" + port, (String) null));
195 } catch (URISyntaxException var4) {
196 throw new IllegalArgumentException("Unable to build deviceID for device " + ip + ":" + port, var4);
197 }
198 }
199
200 /**
201 * Inititates a Netconf connection to the device.
202 *
203 * @param deviceId of the added device
204 */
205 private void initiateConnection(DeviceId deviceId) {
206 if (controller.getNetconfDevice(deviceId) == null) {
207 try {
208 //if (this.isReachable(deviceId)) {
209 this.controller.connectDevice(deviceId);
210 //}
211 } catch (Exception ex) {
212 throw new RuntimeException(new NetconfException("Can\'t " +
213 "connect to NETCONF device on " + deviceId + ":" + deviceId, ex));
214 }
215 }
Aaron Kruglikov309068e2017-03-17 15:25:54 -0700216 }
217}