blob: 3120511faffb8e1fb5002c3a35cd5d3380415f0a [file] [log] [blame]
Thomas Vachuska9252bc32014-10-23 02:33:25 -07001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19package org.onlab.onos.rest;
20
21import com.fasterxml.jackson.databind.JsonNode;
22import org.onlab.onos.net.ConnectPoint;
23import org.onlab.onos.net.DefaultAnnotations;
24import org.onlab.onos.net.Device;
25import org.onlab.onos.net.Host;
26import org.onlab.onos.net.HostId;
27import org.onlab.onos.net.HostLocation;
28import org.onlab.onos.net.Link;
29import org.onlab.onos.net.MastershipRole;
30import org.onlab.onos.net.SparseAnnotations;
31import org.onlab.onos.net.device.DefaultDeviceDescription;
32import 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;
36import org.onlab.onos.net.host.DefaultHostDescription;
37import org.onlab.onos.net.host.HostProvider;
38import org.onlab.onos.net.host.HostProviderRegistry;
39import org.onlab.onos.net.host.HostProviderService;
40import org.onlab.onos.net.link.DefaultLinkDescription;
41import org.onlab.onos.net.link.LinkProvider;
42import org.onlab.onos.net.link.LinkProviderRegistry;
43import org.onlab.onos.net.link.LinkProviderService;
44import org.onlab.onos.net.provider.ProviderId;
45import org.onlab.packet.ChassisId;
46import org.onlab.packet.IpPrefix;
47import org.onlab.packet.MacAddress;
48import org.onlab.packet.VlanId;
49
50import java.net.URI;
51import java.util.Iterator;
52
53import static com.google.common.base.Preconditions.checkNotNull;
54import static org.onlab.onos.net.DeviceId.deviceId;
55import static org.onlab.onos.net.PortNumber.portNumber;
56
57/**
58 * Provider of devices and links parsed from a JSON configuration structure.
59 */
60class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider {
61
62 private static final ProviderId PID =
63 new ProviderId("cfg", "org.onlab.onos.rest", true);
64
65 private final JsonNode cfg;
66 private final DeviceProviderRegistry deviceProviderRegistry;
67 private final LinkProviderRegistry linkProviderRegistry;
68 private final HostProviderRegistry hostProviderRegistry;
69
70 /**
71 * Creates a new configuration provider.
72 *
73 * @param cfg JSON configuration
74 * @param deviceProviderRegistry device provider registry
75 * @param linkProviderRegistry link provider registry
76 * @param hostProviderRegistry host provider registry
77 */
78 ConfigProvider(JsonNode cfg,
79 DeviceProviderRegistry deviceProviderRegistry,
80 LinkProviderRegistry linkProviderRegistry,
81 HostProviderRegistry hostProviderRegistry) {
82 this.cfg = checkNotNull(cfg, "Configuration cannot be null");
83 this.deviceProviderRegistry = checkNotNull(deviceProviderRegistry, "Device provider registry cannot be null");
84 this.linkProviderRegistry = checkNotNull(linkProviderRegistry, "Link provider registry cannot be null");
85 this.hostProviderRegistry = checkNotNull(hostProviderRegistry, "Host provider registry cannot be null");
86 }
87
88 /**
89 * Parses the given JSON and provides links as configured.
90 */
91 void parse() {
92 parseDevices();
93 parseLinks();
94 parseHosts();
95 }
96
97 // Parses the given JSON and provides devices.
98 private void parseDevices() {
99 try {
100 DeviceProviderService dps = deviceProviderRegistry.register(this);
101 JsonNode nodes = cfg.get("devices");
102 if (nodes != null) {
103 for (JsonNode node : nodes) {
104 parseDevice(dps, node);
105 }
106 }
107 } finally {
108 deviceProviderRegistry.unregister(this);
109 }
110 }
111
112 // Parses the given node with device data and supplies the device.
113 private void parseDevice(DeviceProviderService dps, JsonNode node) {
114 URI uri = URI.create(get(node, "uri"));
115 Device.Type type = Device.Type.valueOf(get(node, "type"));
116 String mfr = get(node, "mfr");
117 String hw = get(node, "hw");
118 String sw = get(node, "sw");
119 String serial = get(node, "serial");
120 ChassisId cid = new ChassisId(get(node, "mac"));
121 SparseAnnotations annotations = annotations(node.get("annotations"));
122
123 DeviceDescription desc =
124 new DefaultDeviceDescription(uri, type, mfr, hw, sw, serial,
125 cid, annotations);
126 dps.deviceConnected(deviceId(uri), desc);
127 }
128
129 // Parses the given JSON and provides links as configured.
130 private void parseLinks() {
131 try {
132 LinkProviderService lps = linkProviderRegistry.register(this);
133 JsonNode nodes = cfg.get("links");
134 if (nodes != null) {
135 for (JsonNode node : nodes) {
136 parseLink(lps, node, false);
137 if (!node.has("halfplex")) {
138 parseLink(lps, node, true);
139 }
140 }
141 }
142 } finally {
143 linkProviderRegistry.unregister(this);
144 }
145 }
146
147 // Parses the given node with link data and supplies the link.
148 private void parseLink(LinkProviderService lps, JsonNode node, boolean reverse) {
149 ConnectPoint src = connectPoint(get(node, "src"));
150 ConnectPoint dst = connectPoint(get(node, "dst"));
151 Link.Type type = Link.Type.valueOf(get(node, "type"));
152 SparseAnnotations annotations = annotations(node.get("annotations"));
153
154 DefaultLinkDescription desc = reverse ?
155 new DefaultLinkDescription(dst, src, type, annotations) :
156 new DefaultLinkDescription(src, dst, type, annotations);
157 lps.linkDetected(desc);
158 }
159
160 // Parses the given JSON and provides hosts as configured.
161 private void parseHosts() {
162 try {
163 HostProviderService hps = hostProviderRegistry.register(this);
164 JsonNode nodes = cfg.get("hosts");
165 if (nodes != null) {
166 for (JsonNode node : nodes) {
167 parseHost(hps, node);
168 }
169 }
170 } finally {
171 hostProviderRegistry.unregister(this);
172 }
173 }
174
175 // Parses the given node with host data and supplies the host.
176 private void parseHost(HostProviderService hps, JsonNode node) {
177 MacAddress mac = MacAddress.valueOf(get(node, "mac"));
178 VlanId vlanId = VlanId.vlanId(node.get("vlan").shortValue());
179 HostId hostId = HostId.hostId(mac, vlanId);
180 SparseAnnotations annotations = annotations(node.get("annotations"));
181 HostLocation location = new HostLocation(connectPoint(get(node, "location")), 0);
182 IpPrefix ip = IpPrefix.valueOf(get(node, "ip"));
183
184 DefaultHostDescription desc =
185 new DefaultHostDescription(mac, vlanId, location, ip, annotations);
186 hps.hostDetected(hostId, desc);
187 }
188
189 // Produces set of annotations from the given JSON node.
190 private SparseAnnotations annotations(JsonNode node) {
191 if (node == null) {
192 return null;
193 }
194
195 DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
196 Iterator<String> it = node.fieldNames();
197 while (it.hasNext()) {
198 String k = it.next();
199 builder.set(k, node.get(k).asText());
200 }
201 return builder.build();
202 }
203
204 // Produces a connection point from the specified uri/port text.
205 private ConnectPoint connectPoint(String text) {
206 int i = text.lastIndexOf("/");
207 return new ConnectPoint(deviceId(text.substring(0, i)),
208 portNumber(text.substring(i + 1)));
209 }
210
211 // Returns string form of the named property in the given JSON object.
212 private String get(JsonNode node, String name) {
213 return node.path(name).asText();
214 }
215
216 @Override
217 public void triggerProbe(Device device) {
218 }
219
220 @Override
221 public void roleChanged(Device device, MastershipRole newRole) {
222 }
223
224 @Override
225 public void triggerProbe(Host host) {
226 }
227
228 @Override
229 public ProviderId id() {
230 return PID;
231 }
232}