blob: 287f871bb0905bf1a0b8e2436d069f5b4cad45b0 [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;
Aaron Kruglikov309068e2017-03-17 15:25:54 -070037import org.onosproject.yang.model.ResourceId;
38import org.onosproject.yang.runtime.DefaultResourceData;
39import org.slf4j.Logger;
40import org.slf4j.LoggerFactory;
41
42import java.io.IOException;
Thomas Vachuska59d24eb2017-03-22 10:57:34 -070043import java.net.URI;
44import java.net.URISyntaxException;
Aaron Kruglikov309068e2017-03-17 15:25:54 -070045
Sithara Punnassery425837f2017-03-21 12:58:00 -070046
Aaron Kruglikov309068e2017-03-17 15:25:54 -070047@Beta
48@Component(immediate = true)
Sithara Punnassery425837f2017-03-21 12:58:00 -070049public class NetconfActiveComponent implements DynamicConfigListener {
Aaron Kruglikov309068e2017-03-17 15:25:54 -070050
Sithara Punnassery425837f2017-03-21 12:58:00 -070051 private static final Logger log = LoggerFactory.getLogger(NetconfActiveComponent.class);
Aaron Kruglikov309068e2017-03-17 15:25:54 -070052 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Sithara Punnassery425837f2017-03-21 12:58:00 -070053 protected DynamicConfigService cfgService;
Aaron Kruglikov309068e2017-03-17 15:25:54 -070054 public static final String DEVNMSPACE = "namespace1";
55
56 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
57 protected NetconfTranslator netconfTranslator;
58
59 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
60 protected MastershipService mastershipService;
61
Sithara Punnassery425837f2017-03-21 12:58:00 -070062 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63 protected NetconfController controller;
64
Aaron Kruglikov309068e2017-03-17 15:25:54 -070065 private ResourceId resId = new ResourceId.Builder()
Thomas Vachuska59d24eb2017-03-22 10:57:34 -070066 .addBranchPointSchema("device", DEVNMSPACE)
Aaron Kruglikov309068e2017-03-17 15:25:54 -070067 .build();
Thomas Vachuska59d24eb2017-03-22 10:57:34 -070068
Aaron Kruglikov309068e2017-03-17 15:25:54 -070069 @Activate
70 protected void activate() {
Sithara Punnassery425837f2017-03-21 12:58:00 -070071 cfgService.addListener(this);
Aaron Kruglikov309068e2017-03-17 15:25:54 -070072 log.info("Started");
73 }
74
75 @Deactivate
76 protected void deactivate() {
Sithara Punnassery425837f2017-03-21 12:58:00 -070077 cfgService.removeListener(this);
Aaron Kruglikov309068e2017-03-17 15:25:54 -070078 log.info("Stopped");
79 }
80
81 @Override
82 public boolean isRelevant(DynamicConfigEvent event) {
Thomas Vachuska59d24eb2017-03-22 10:57:34 -070083 return event.subject().equals(resId);
Aaron Kruglikov309068e2017-03-17 15:25:54 -070084 }
Sithara Punnassery425837f2017-03-21 12:58:00 -070085
86 public boolean isMaster(DeviceId deviceId) {
Thomas Vachuska59d24eb2017-03-22 10:57:34 -070087 return mastershipService.isLocalMaster(deviceId);
Sithara Punnassery425837f2017-03-21 12:58:00 -070088 }
89
Aaron Kruglikov309068e2017-03-17 15:25:54 -070090 @Override
91 public void event(DynamicConfigEvent event) {
92 Filter filt = new Filter();
Sithara Punnassery425837f2017-03-21 12:58:00 -070093 DataNode node = cfgService.readNode(event.subject(), filt);
94 DeviceId deviceId = getDeviceId(node);
95 if (!isMaster(deviceId)) {
96 log.info("NetConfListener: not master, ignoring config for {}", event.type());
97 return;
98 }
99 initiateConnection(deviceId);
Aaron Kruglikov309068e2017-03-17 15:25:54 -0700100 switch (event.type()) {
101 case NODE_ADDED:
102 case NODE_UPDATED:
103 case NODE_REPLACED:
104 configUpdate(node, deviceId, event.subject());
105 break;
106 case NODE_DELETED:
107 configDelete(node, deviceId, event.subject());
108 break;
109 case UNKNOWN_OPRN:
110 default:
111 log.warn("NetConfListener: unknown event: {}", event.type());
112 break;
113 }
114 }
115
116 /**
117 * Performs the delete operation corresponding to the passed event.
Thomas Vachuska59d24eb2017-03-22 10:57:34 -0700118 *
119 * @param node a relevant dataNode
120 * @param deviceId the deviceId of the device to be updated
Aaron Kruglikov309068e2017-03-17 15:25:54 -0700121 * @param resourceId the resourceId of the root of the subtree to be edited
122 * @return true if the update succeeds false otherwise
123 */
124 private boolean configDelete(DataNode node, DeviceId deviceId, ResourceId resourceId) {
125 return parseAndEdit(node, deviceId, resourceId, OperationType.DELETE);
126 }
127
128 /**
129 * Performs the update operation corresponding to the passed event.
Thomas Vachuska59d24eb2017-03-22 10:57:34 -0700130 *
131 * @param node a relevant dataNode
132 * @param deviceId the deviceId of the device to be updated
Aaron Kruglikov309068e2017-03-17 15:25:54 -0700133 * @param resourceId the resourceId of the root of the subtree to be edited
134 * @return true if the update succeeds false otherwise
135 */
136 private boolean configUpdate(DataNode node, DeviceId deviceId, ResourceId resourceId) {
137 return parseAndEdit(node, deviceId, resourceId, OperationType.REPLACE);
138 }
139
140 /**
141 * Parses the incoming event and pushes configuration to the effected
142 * device.
Thomas Vachuska59d24eb2017-03-22 10:57:34 -0700143 *
144 * @param node the dataNode effecting a particular device of which this node
145 * is master
146 * @param deviceId the deviceId of the device to be modified
147 * @param resourceId the resourceId of the root of the subtree to be edited
Aaron Kruglikov309068e2017-03-17 15:25:54 -0700148 * @param operationType the type of editing to be performed
149 * @return true if the operation succeeds, false otherwise
150 */
151 private boolean parseAndEdit(DataNode node, DeviceId deviceId,
152 ResourceId resourceId,
153 NetconfTranslator.OperationType operationType) {
154 try {
155 return netconfTranslator.editDeviceConfig(
156 deviceId,
157 DefaultResourceData.builder()
158 .addDataNode(node)
159 .resourceId(resourceId)
160 .build(),
161 operationType);
162 } catch (IOException e) {
163 e.printStackTrace();
164 return false;
165 }
166 }
167
168 /**
Sithara Punnassery425837f2017-03-21 12:58:00 -0700169 * Retrieves device id from Data node.
170 *
171 * @param node the node associated with the event
Aaron Kruglikov309068e2017-03-17 15:25:54 -0700172 * @return the deviceId of the effected device
173 */
Sithara Punnassery425837f2017-03-21 12:58:00 -0700174 public DeviceId getDeviceId(DataNode node) {
175 String[] temp;
176 String ip, port;
177 if (node.type() == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
178 temp = ((LeafNode) node).asString().split("\\:");
179 if (temp.length != 3) {
180 throw new RuntimeException(new NetconfException("Invalid device id form, cannot apply"));
181 }
182 ip = temp[1];
183 port = temp[2];
184 } else {
185 throw new RuntimeException(new NetconfException("Invalid device id type, cannot apply"));
186 }
187 try {
188 return DeviceId.deviceId(new URI("netconf", ip + ":" + port, (String) null));
189 } catch (URISyntaxException var4) {
190 throw new IllegalArgumentException("Unable to build deviceID for device " + ip + ":" + port, var4);
191 }
192 }
193
194 /**
195 * Inititates a Netconf connection to the device.
196 *
197 * @param deviceId of the added device
198 */
199 private void initiateConnection(DeviceId deviceId) {
200 if (controller.getNetconfDevice(deviceId) == null) {
201 try {
202 //if (this.isReachable(deviceId)) {
Thomas Vachuska59d24eb2017-03-22 10:57:34 -0700203 this.controller.connectDevice(deviceId);
Sithara Punnassery425837f2017-03-21 12:58:00 -0700204 //}
205 } catch (Exception ex) {
Thomas Vachuska59d24eb2017-03-22 10:57:34 -0700206 throw new RuntimeException(new NetconfException("Unable to connect to NETCONF device on " +
207 deviceId, ex));
Sithara Punnassery425837f2017-03-21 12:58:00 -0700208 }
209 }
Aaron Kruglikov309068e2017-03-17 15:25:54 -0700210 }
211}