blob: f5694be052853abe4876f038a3950096b6d3857a [file] [log] [blame]
Thomas Vachuska9252bc32014-10-23 02:33:25 -07001/*
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07002 * Copyright 2014 Open Networking Laboratory
Thomas Vachuska9252bc32014-10-23 02:33:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska9252bc32014-10-23 02:33:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska9252bc32014-10-23 02:33:25 -070015 */
16package org.onlab.onos.rest;
17
18import com.fasterxml.jackson.databind.JsonNode;
19import org.onlab.onos.net.ConnectPoint;
20import org.onlab.onos.net.DefaultAnnotations;
21import org.onlab.onos.net.Device;
Thomas Vachuskad16ce182014-10-29 17:25:29 -070022import org.onlab.onos.net.DeviceId;
Thomas Vachuska9252bc32014-10-23 02:33:25 -070023import org.onlab.onos.net.Host;
24import org.onlab.onos.net.HostId;
25import org.onlab.onos.net.HostLocation;
26import org.onlab.onos.net.Link;
27import org.onlab.onos.net.MastershipRole;
Thomas Vachuskad16ce182014-10-29 17:25:29 -070028import org.onlab.onos.net.Port;
Thomas Vachuska9252bc32014-10-23 02:33:25 -070029import org.onlab.onos.net.SparseAnnotations;
30import org.onlab.onos.net.device.DefaultDeviceDescription;
Thomas Vachuskad16ce182014-10-29 17:25:29 -070031import org.onlab.onos.net.device.DefaultPortDescription;
Thomas Vachuska9252bc32014-10-23 02:33:25 -070032import org.onlab.onos.net.device.DeviceDescription;
33import org.onlab.onos.net.device.DeviceProvider;
34import org.onlab.onos.net.device.DeviceProviderRegistry;
35import org.onlab.onos.net.device.DeviceProviderService;
Thomas Vachuskad16ce182014-10-29 17:25:29 -070036import org.onlab.onos.net.device.PortDescription;
Thomas Vachuska9252bc32014-10-23 02:33:25 -070037import org.onlab.onos.net.host.DefaultHostDescription;
38import org.onlab.onos.net.host.HostProvider;
39import org.onlab.onos.net.host.HostProviderRegistry;
40import org.onlab.onos.net.host.HostProviderService;
41import org.onlab.onos.net.link.DefaultLinkDescription;
42import org.onlab.onos.net.link.LinkProvider;
43import org.onlab.onos.net.link.LinkProviderRegistry;
44import org.onlab.onos.net.link.LinkProviderService;
45import org.onlab.onos.net.provider.ProviderId;
46import org.onlab.packet.ChassisId;
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -070047import org.onlab.packet.IpAddress;
Thomas Vachuska9252bc32014-10-23 02:33:25 -070048import org.onlab.packet.MacAddress;
49import org.onlab.packet.VlanId;
50
51import java.net.URI;
Thomas Vachuskad16ce182014-10-29 17:25:29 -070052import java.util.ArrayList;
Thomas Vachuskaece59ee2014-11-19 19:06:11 -080053import java.util.HashSet;
Thomas Vachuska9252bc32014-10-23 02:33:25 -070054import java.util.Iterator;
Thomas Vachuskad16ce182014-10-29 17:25:29 -070055import java.util.List;
Thomas Vachuskaece59ee2014-11-19 19:06:11 -080056import java.util.Set;
Thomas Vachuska9252bc32014-10-23 02:33:25 -070057
58import static com.google.common.base.Preconditions.checkNotNull;
59import static org.onlab.onos.net.DeviceId.deviceId;
60import static org.onlab.onos.net.PortNumber.portNumber;
61
62/**
63 * Provider of devices and links parsed from a JSON configuration structure.
64 */
65class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider {
66
67 private static final ProviderId PID =
68 new ProviderId("cfg", "org.onlab.onos.rest", true);
69
70 private final JsonNode cfg;
71 private final DeviceProviderRegistry deviceProviderRegistry;
72 private final LinkProviderRegistry linkProviderRegistry;
73 private final HostProviderRegistry hostProviderRegistry;
74
75 /**
76 * Creates a new configuration provider.
77 *
78 * @param cfg JSON configuration
79 * @param deviceProviderRegistry device provider registry
80 * @param linkProviderRegistry link provider registry
81 * @param hostProviderRegistry host provider registry
82 */
83 ConfigProvider(JsonNode cfg,
84 DeviceProviderRegistry deviceProviderRegistry,
85 LinkProviderRegistry linkProviderRegistry,
86 HostProviderRegistry hostProviderRegistry) {
87 this.cfg = checkNotNull(cfg, "Configuration cannot be null");
88 this.deviceProviderRegistry = checkNotNull(deviceProviderRegistry, "Device provider registry cannot be null");
89 this.linkProviderRegistry = checkNotNull(linkProviderRegistry, "Link provider registry cannot be null");
90 this.hostProviderRegistry = checkNotNull(hostProviderRegistry, "Host provider registry cannot be null");
91 }
92
93 /**
94 * Parses the given JSON and provides links as configured.
95 */
96 void parse() {
97 parseDevices();
98 parseLinks();
99 parseHosts();
100 }
101
102 // Parses the given JSON and provides devices.
103 private void parseDevices() {
104 try {
105 DeviceProviderService dps = deviceProviderRegistry.register(this);
106 JsonNode nodes = cfg.get("devices");
107 if (nodes != null) {
108 for (JsonNode node : nodes) {
109 parseDevice(dps, node);
110 }
111 }
112 } finally {
113 deviceProviderRegistry.unregister(this);
114 }
115 }
116
117 // Parses the given node with device data and supplies the device.
118 private void parseDevice(DeviceProviderService dps, JsonNode node) {
119 URI uri = URI.create(get(node, "uri"));
120 Device.Type type = Device.Type.valueOf(get(node, "type"));
121 String mfr = get(node, "mfr");
122 String hw = get(node, "hw");
123 String sw = get(node, "sw");
124 String serial = get(node, "serial");
125 ChassisId cid = new ChassisId(get(node, "mac"));
126 SparseAnnotations annotations = annotations(node.get("annotations"));
127
128 DeviceDescription desc =
129 new DefaultDeviceDescription(uri, type, mfr, hw, sw, serial,
130 cid, annotations);
Thomas Vachuskad16ce182014-10-29 17:25:29 -0700131 DeviceId deviceId = deviceId(uri);
132 dps.deviceConnected(deviceId, desc);
133
134 JsonNode ports = node.get("ports");
135 if (ports != null) {
136 parsePorts(dps, deviceId, ports);
137 }
138 }
139
140 // Parses the given node with list of device ports.
141 private void parsePorts(DeviceProviderService dps, DeviceId deviceId, JsonNode nodes) {
142 List<PortDescription> ports = new ArrayList<>();
143 for (JsonNode node : nodes) {
144 ports.add(parsePort(node));
145 }
146 dps.updatePorts(deviceId, ports);
147 }
148
149 // Parses the given node with port information.
150 private PortDescription parsePort(JsonNode node) {
151 Port.Type type = Port.Type.valueOf(node.path("type").asText("COPPER"));
152 return new DefaultPortDescription(portNumber(node.path("port").asLong(0)),
153 node.path("enabled").asBoolean(true),
154 type, node.path("speed").asLong(1_000));
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700155 }
156
157 // Parses the given JSON and provides links as configured.
158 private void parseLinks() {
159 try {
160 LinkProviderService lps = linkProviderRegistry.register(this);
161 JsonNode nodes = cfg.get("links");
162 if (nodes != null) {
163 for (JsonNode node : nodes) {
164 parseLink(lps, node, false);
165 if (!node.has("halfplex")) {
166 parseLink(lps, node, true);
167 }
168 }
169 }
170 } finally {
171 linkProviderRegistry.unregister(this);
172 }
173 }
174
175 // Parses the given node with link data and supplies the link.
176 private void parseLink(LinkProviderService lps, JsonNode node, boolean reverse) {
177 ConnectPoint src = connectPoint(get(node, "src"));
178 ConnectPoint dst = connectPoint(get(node, "dst"));
179 Link.Type type = Link.Type.valueOf(get(node, "type"));
180 SparseAnnotations annotations = annotations(node.get("annotations"));
181
182 DefaultLinkDescription desc = reverse ?
183 new DefaultLinkDescription(dst, src, type, annotations) :
184 new DefaultLinkDescription(src, dst, type, annotations);
185 lps.linkDetected(desc);
186 }
187
188 // Parses the given JSON and provides hosts as configured.
189 private void parseHosts() {
190 try {
191 HostProviderService hps = hostProviderRegistry.register(this);
192 JsonNode nodes = cfg.get("hosts");
193 if (nodes != null) {
194 for (JsonNode node : nodes) {
195 parseHost(hps, node);
196 }
197 }
198 } finally {
199 hostProviderRegistry.unregister(this);
200 }
201 }
202
203 // Parses the given node with host data and supplies the host.
204 private void parseHost(HostProviderService hps, JsonNode node) {
205 MacAddress mac = MacAddress.valueOf(get(node, "mac"));
206 VlanId vlanId = VlanId.vlanId(node.get("vlan").shortValue());
207 HostId hostId = HostId.hostId(mac, vlanId);
208 SparseAnnotations annotations = annotations(node.get("annotations"));
209 HostLocation location = new HostLocation(connectPoint(get(node, "location")), 0);
Thomas Vachuskaece59ee2014-11-19 19:06:11 -0800210
211 String[] ipStrings = get(node, "ip").split(",");
212 Set<IpAddress> ips = new HashSet<>();
213 for (String ip : ipStrings) {
214 ips.add(IpAddress.valueOf(ip.trim()));
215 }
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700216
217 DefaultHostDescription desc =
Thomas Vachuskaece59ee2014-11-19 19:06:11 -0800218 new DefaultHostDescription(mac, vlanId, location, ips, annotations);
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700219 hps.hostDetected(hostId, desc);
220 }
221
222 // Produces set of annotations from the given JSON node.
223 private SparseAnnotations annotations(JsonNode node) {
224 if (node == null) {
225 return null;
226 }
227
228 DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
229 Iterator<String> it = node.fieldNames();
230 while (it.hasNext()) {
231 String k = it.next();
232 builder.set(k, node.get(k).asText());
233 }
234 return builder.build();
235 }
236
237 // Produces a connection point from the specified uri/port text.
238 private ConnectPoint connectPoint(String text) {
239 int i = text.lastIndexOf("/");
240 return new ConnectPoint(deviceId(text.substring(0, i)),
241 portNumber(text.substring(i + 1)));
242 }
243
244 // Returns string form of the named property in the given JSON object.
245 private String get(JsonNode node, String name) {
246 return node.path(name).asText();
247 }
248
249 @Override
Ayaka Koshibe78bcbc12014-11-19 14:28:58 -0800250 public void triggerProbe(DeviceId deviceId) {
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700251 }
252
253 @Override
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700254 public void roleChanged(DeviceId device, MastershipRole newRole) {
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700255 }
256
257 @Override
258 public void triggerProbe(Host host) {
259 }
260
261 @Override
262 public ProviderId id() {
263 return PID;
264 }
Ayaka Koshibee60d4522014-10-28 15:07:00 -0700265
266 @Override
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700267 public boolean isReachable(DeviceId device) {
Ayaka Koshibee60d4522014-10-28 15:07:00 -0700268 return false;
269 }
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700270}