blob: ac7735e1e483c50e871561f7ed0839e7566b4e91 [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
Thomas Vachuska59d24eb2017-03-22 10:57:34 -070017package org.onosproject.netconf.client.impl;
Aaron Kruglikov309068e2017-03-17 15:25:54 -070018
19import com.google.common.annotations.Beta;
20import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
Aaron Kruglikov309068e2017-03-17 15:25:54 -070022import org.apache.felix.scr.annotations.Deactivate;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.onosproject.config.DynamicConfigEvent;
26import org.onosproject.config.DynamicConfigListener;
27import org.onosproject.config.DynamicConfigService;
28import org.onosproject.config.Filter;
29import org.onosproject.mastership.MastershipService;
30import org.onosproject.net.DeviceId;
Thomas Vachuska59d24eb2017-03-22 10:57:34 -070031import org.onosproject.netconf.NetconfController;
32import org.onosproject.netconf.NetconfException;
Aaron Kruglikov309068e2017-03-17 15:25:54 -070033import org.onosproject.netconf.client.NetconfTranslator;
34import org.onosproject.netconf.client.NetconfTranslator.OperationType;
35import org.onosproject.yang.model.DataNode;
Sithara Punnassery425837f2017-03-21 12:58:00 -070036import org.onosproject.yang.model.LeafNode;
Sithara Punnasserybda82502017-03-22 19:08:19 -070037import org.onosproject.yang.model.ListKey;
Aaron Kruglikov309068e2017-03-17 15:25:54 -070038import org.onosproject.yang.model.ResourceId;
39import org.onosproject.yang.runtime.DefaultResourceData;
40import org.slf4j.Logger;
41import org.slf4j.LoggerFactory;
42
43import java.io.IOException;
Thomas Vachuska59d24eb2017-03-22 10:57:34 -070044import java.net.URI;
45import java.net.URISyntaxException;
Aaron Kruglikov309068e2017-03-17 15:25:54 -070046
Sithara Punnassery425837f2017-03-21 12:58:00 -070047
Aaron Kruglikov309068e2017-03-17 15:25:54 -070048@Beta
49@Component(immediate = true)
Sithara Punnassery425837f2017-03-21 12:58:00 -070050public class NetconfActiveComponent implements DynamicConfigListener {
Aaron Kruglikov309068e2017-03-17 15:25:54 -070051
Sithara Punnassery425837f2017-03-21 12:58:00 -070052 private static final Logger log = LoggerFactory.getLogger(NetconfActiveComponent.class);
Aaron Kruglikov309068e2017-03-17 15:25:54 -070053 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Sithara Punnassery425837f2017-03-21 12:58:00 -070054 protected DynamicConfigService cfgService;
Sithara Punnasserybda82502017-03-22 19:08:19 -070055 public static final String DEVNMSPACE = "ne-l3vpn-api";
Aaron Kruglikov309068e2017-03-17 15:25:54 -070056
57 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
58 protected NetconfTranslator netconfTranslator;
59
60 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
61 protected MastershipService mastershipService;
62
Sithara Punnassery425837f2017-03-21 12:58:00 -070063 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
64 protected NetconfController controller;
65
Aaron Kruglikov309068e2017-03-17 15:25:54 -070066 private ResourceId resId = new ResourceId.Builder()
Thomas Vachuska59d24eb2017-03-22 10:57:34 -070067 .addBranchPointSchema("device", DEVNMSPACE)
Sithara Punnasserybda82502017-03-22 19:08:19 -070068 .addBranchPointSchema("device", DEVNMSPACE)
69 .addKeyLeaf("deviceid", DEVNMSPACE, "netconf:172.16.5.11:22")
Aaron Kruglikov309068e2017-03-17 15:25:54 -070070 .build();
Thomas Vachuska59d24eb2017-03-22 10:57:34 -070071
Aaron Kruglikov309068e2017-03-17 15:25:54 -070072 @Activate
73 protected void activate() {
Sithara Punnassery425837f2017-03-21 12:58:00 -070074 cfgService.addListener(this);
Aaron Kruglikov309068e2017-03-17 15:25:54 -070075 log.info("Started");
76 }
77
78 @Deactivate
79 protected void deactivate() {
Sithara Punnassery425837f2017-03-21 12:58:00 -070080 cfgService.removeListener(this);
Aaron Kruglikov309068e2017-03-17 15:25:54 -070081 log.info("Stopped");
82 }
83
84 @Override
85 public boolean isRelevant(DynamicConfigEvent event) {
Thomas Vachuska59d24eb2017-03-22 10:57:34 -070086 return event.subject().equals(resId);
Aaron Kruglikov309068e2017-03-17 15:25:54 -070087 }
Sithara Punnassery425837f2017-03-21 12:58:00 -070088
89 public boolean isMaster(DeviceId deviceId) {
Thomas Vachuska59d24eb2017-03-22 10:57:34 -070090 return mastershipService.isLocalMaster(deviceId);
Sithara Punnassery425837f2017-03-21 12:58:00 -070091 }
92
Aaron Kruglikov309068e2017-03-17 15:25:54 -070093 @Override
94 public void event(DynamicConfigEvent event) {
95 Filter filt = new Filter();
Sithara Punnassery425837f2017-03-21 12:58:00 -070096 DataNode node = cfgService.readNode(event.subject(), filt);
97 DeviceId deviceId = getDeviceId(node);
98 if (!isMaster(deviceId)) {
99 log.info("NetConfListener: not master, ignoring config for {}", event.type());
100 return;
101 }
102 initiateConnection(deviceId);
Aaron Kruglikov309068e2017-03-17 15:25:54 -0700103 switch (event.type()) {
104 case NODE_ADDED:
105 case NODE_UPDATED:
106 case NODE_REPLACED:
107 configUpdate(node, deviceId, event.subject());
108 break;
109 case NODE_DELETED:
110 configDelete(node, deviceId, event.subject());
111 break;
112 case UNKNOWN_OPRN:
113 default:
114 log.warn("NetConfListener: unknown event: {}", event.type());
115 break;
116 }
117 }
118
119 /**
120 * Performs the delete operation corresponding to the passed event.
Thomas Vachuska59d24eb2017-03-22 10:57:34 -0700121 *
122 * @param node a relevant dataNode
123 * @param deviceId the deviceId of the device to be updated
Aaron Kruglikov309068e2017-03-17 15:25:54 -0700124 * @param resourceId the resourceId of the root of the subtree to be edited
125 * @return true if the update succeeds false otherwise
126 */
127 private boolean configDelete(DataNode node, DeviceId deviceId, ResourceId resourceId) {
128 return parseAndEdit(node, deviceId, resourceId, OperationType.DELETE);
129 }
130
131 /**
132 * Performs the update operation corresponding to the passed event.
Thomas Vachuska59d24eb2017-03-22 10:57:34 -0700133 *
134 * @param node a relevant dataNode
135 * @param deviceId the deviceId of the device to be updated
Aaron Kruglikov309068e2017-03-17 15:25:54 -0700136 * @param resourceId the resourceId of the root of the subtree to be edited
137 * @return true if the update succeeds false otherwise
138 */
139 private boolean configUpdate(DataNode node, DeviceId deviceId, ResourceId resourceId) {
140 return parseAndEdit(node, deviceId, resourceId, OperationType.REPLACE);
141 }
142
143 /**
144 * Parses the incoming event and pushes configuration to the effected
145 * device.
Thomas Vachuska59d24eb2017-03-22 10:57:34 -0700146 *
147 * @param node the dataNode effecting a particular device of which this node
148 * is master
149 * @param deviceId the deviceId of the device to be modified
150 * @param resourceId the resourceId of the root of the subtree to be edited
Aaron Kruglikov309068e2017-03-17 15:25:54 -0700151 * @param operationType the type of editing to be performed
152 * @return true if the operation succeeds, false otherwise
153 */
154 private boolean parseAndEdit(DataNode node, DeviceId deviceId,
155 ResourceId resourceId,
156 NetconfTranslator.OperationType operationType) {
157 try {
158 return netconfTranslator.editDeviceConfig(
159 deviceId,
160 DefaultResourceData.builder()
161 .addDataNode(node)
162 .resourceId(resourceId)
163 .build(),
164 operationType);
165 } catch (IOException e) {
166 e.printStackTrace();
167 return false;
168 }
169 }
170
171 /**
Sithara Punnassery425837f2017-03-21 12:58:00 -0700172 * Retrieves device id from Data node.
173 *
174 * @param node the node associated with the event
Aaron Kruglikov309068e2017-03-17 15:25:54 -0700175 * @return the deviceId of the effected device
176 */
Sithara Punnasserybda82502017-03-22 19:08:19 -0700177 @Beta
Sithara Punnassery425837f2017-03-21 12:58:00 -0700178 public DeviceId getDeviceId(DataNode node) {
179 String[] temp;
180 String ip, port;
181 if (node.type() == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
182 temp = ((LeafNode) node).asString().split("\\:");
183 if (temp.length != 3) {
184 throw new RuntimeException(new NetconfException("Invalid device id form, cannot apply"));
185 }
186 ip = temp[1];
187 port = temp[2];
Sithara Punnasserybda82502017-03-22 19:08:19 -0700188 } else if (node.type() == DataNode.Type.MULTI_INSTANCE_NODE) {
189 ListKey key = (ListKey) node.key();
190 temp = key.keyLeafs().get(0).leafValAsString().split("\\:");
191 if (temp.length != 3) {
192 throw new RuntimeException(new NetconfException("Invalid device id form, cannot apply"));
193 }
194 ip = temp[1];
195 port = temp[2];
Sithara Punnassery425837f2017-03-21 12:58:00 -0700196 } else {
197 throw new RuntimeException(new NetconfException("Invalid device id type, cannot apply"));
198 }
199 try {
200 return DeviceId.deviceId(new URI("netconf", ip + ":" + port, (String) null));
201 } catch (URISyntaxException var4) {
202 throw new IllegalArgumentException("Unable to build deviceID for device " + ip + ":" + port, var4);
203 }
204 }
205
206 /**
207 * Inititates a Netconf connection to the device.
208 *
209 * @param deviceId of the added device
210 */
211 private void initiateConnection(DeviceId deviceId) {
212 if (controller.getNetconfDevice(deviceId) == null) {
213 try {
214 //if (this.isReachable(deviceId)) {
Thomas Vachuska59d24eb2017-03-22 10:57:34 -0700215 this.controller.connectDevice(deviceId);
Sithara Punnassery425837f2017-03-21 12:58:00 -0700216 //}
217 } catch (Exception ex) {
Thomas Vachuska59d24eb2017-03-22 10:57:34 -0700218 throw new RuntimeException(new NetconfException("Unable to connect to NETCONF device on " +
219 deviceId, ex));
Sithara Punnassery425837f2017-03-21 12:58:00 -0700220 }
221 }
Aaron Kruglikov309068e2017-03-17 15:25:54 -0700222 }
223}