Thomas Vachuska

Implementing net config subsystem and revising its interfaces.

Added a few basic configs for device, host and links.

Added initial REST API.

Added CLI.

Tests remain to be added.

Change-Id: Ic7bba4b5ad7d553c51d69f6459b3bff146970323
Showing 28 changed files with 1700 additions and 64 deletions
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.cli.cfg;
17 +
18 +import com.fasterxml.jackson.databind.ObjectMapper;
19 +import com.fasterxml.jackson.databind.node.ObjectNode;
20 +import org.apache.karaf.shell.commands.Argument;
21 +import org.apache.karaf.shell.commands.Command;
22 +import org.onosproject.cli.AbstractShellCommand;
23 +import org.onosproject.incubator.net.config.Config;
24 +import org.onosproject.incubator.net.config.NetworkConfigService;
25 +import org.onosproject.incubator.net.config.SubjectFactory;
26 +
27 +import static com.google.common.base.Strings.isNullOrEmpty;
28 +
29 +/**
30 + * Manages network configuration.
31 + */
32 +@Command(scope = "onos", name = "netcfg",
33 + description = "Manages network configuration")
34 +public class NetworkConfigCommand extends AbstractShellCommand {
35 +
36 + @Argument(index = 0, name = "subjectKey", description = "Subject key",
37 + required = false, multiValued = false)
38 + String subjectKey = null;
39 +
40 + @Argument(index = 1, name = "subject", description = "Subject",
41 + required = false, multiValued = false)
42 + String subject = null;
43 +
44 + @Argument(index = 2, name = "configKey", description = "Config key",
45 + required = false, multiValued = false)
46 + String configKey = null;
47 +
48 + private final ObjectMapper mapper = new ObjectMapper();
49 + private NetworkConfigService service;
50 +
51 + @Override
52 + protected void execute() {
53 + service = get(NetworkConfigService.class);
54 + ObjectNode root = new ObjectMapper().createObjectNode();
55 + if (isNullOrEmpty(subjectKey)) {
56 + addAll(root);
57 + } else {
58 + SubjectFactory subjectFactory = service.getSubjectFactory(subjectKey);
59 + if (isNullOrEmpty(subject)) {
60 + addSubjectClass(root, subjectFactory);
61 + } else {
62 + Object s = subjectFactory.createSubject(subject);
63 + if (isNullOrEmpty(configKey)) {
64 + addSubject(root, s);
65 + } else {
66 + addSubjectConfig(root, getConfig(s, configKey));
67 + }
68 + }
69 + }
70 + print("%s", root.toString());
71 + }
72 +
73 + @SuppressWarnings("unchecked")
74 + private void addAll(ObjectNode root) {
75 + service.getSubjectClasses()
76 + .forEach(sc -> {
77 + SubjectFactory sf = service.getSubjectFactory((Class) sc);
78 + addSubjectClass(newObject(root, sf.subjectKey()), sf);
79 + });
80 + }
81 +
82 + @SuppressWarnings("unchecked")
83 + private void addSubjectClass(ObjectNode root, SubjectFactory sf) {
84 + service.getSubjects(sf.subjectClass())
85 + .forEach(s -> addSubject(newObject(root, s.toString()), s));
86 + }
87 +
88 + private void addSubject(ObjectNode root, Object s) {
89 + service.getConfigs(s)
90 + .forEach(c -> addSubjectConfig(newObject(root, c.key()), getConfig(s, c.key())));
91 + }
92 +
93 + private void addSubjectConfig(ObjectNode root, Config config) {
94 + if (config != null) {
95 + root.set(config.key(), config.node());
96 + }
97 + }
98 +
99 + private Config getConfig(Object s, String ck) {
100 + Class<? extends Config> configClass = service.getConfigClass(ck);
101 + return configClass != null ? service.getConfig(s, configClass) : null;
102 + }
103 +
104 + private ObjectNode newObject(ObjectNode parent, String key) {
105 + ObjectNode node = mapper.createObjectNode();
106 + parent.set(key, node);
107 + return node;
108 + }
109 +}
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.cli.cfg;
17 +
18 +import org.apache.karaf.shell.commands.Command;
19 +import org.apache.karaf.shell.commands.Option;
20 +import org.onosproject.cli.AbstractShellCommand;
21 +import org.onosproject.incubator.net.config.ConfigFactory;
22 +import org.onosproject.incubator.net.config.NetworkConfigRegistry;
23 +
24 +/**
25 + * Displays network configuration registry contents.
26 + */
27 +@Command(scope = "onos", name = "netcfg-registry",
28 + description = "Displays network configuration registry contents")
29 +public class NetworkConfigRegistryCommand extends AbstractShellCommand {
30 +
31 + private static final String FMT = "subjectKey=%s, configKey=%s, subjectClass=%s, configClass=%s";
32 + private static final String SHORT_FMT = "%-12s %-12s %-40s %s";
33 +
34 + @Option(name = "-s", aliases = "--short", description = "Show short output only",
35 + required = false, multiValued = false)
36 + private boolean shortOnly = false;
37 +
38 + @Override
39 + protected void execute() {
40 + get(NetworkConfigRegistry.class).getConfigFactories().forEach(this::print);
41 + }
42 +
43 + private void print(ConfigFactory configFactory) {
44 + print(shortOnly ? SHORT_FMT : FMT,
45 + configFactory.subjectFactory().subjectKey(),
46 + configFactory.configKey(),
47 + configFactory.subjectFactory().subjectClass().getName(),
48 + configFactory.configClass().getName());
49 + }
50 +
51 +}
...@@ -15,6 +15,6 @@ ...@@ -15,6 +15,6 @@
15 */ 15 */
16 16
17 /** 17 /**
18 - * CLI commands for managing centralized component configuration. 18 + * CLI commands for managing centralized component and network configurations.
19 */ 19 */
20 package org.onosproject.cli.cfg; 20 package org.onosproject.cli.cfg;
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -51,6 +51,14 @@ ...@@ -51,6 +51,14 @@
51 </command> 51 </command>
52 52
53 <command> 53 <command>
54 + <action class="org.onosproject.cli.cfg.NetworkConfigRegistryCommand"/>
55 + </command>
56 +
57 + <command>
58 + <action class="org.onosproject.cli.cfg.NetworkConfigCommand"/>
59 + </command>
60 +
61 + <command>
54 <action class="org.onosproject.cli.MetricsListCommand"/> 62 <action class="org.onosproject.cli.MetricsListCommand"/>
55 </command> 63 </command>
56 64
......
...@@ -17,7 +17,11 @@ package org.onosproject.net; ...@@ -17,7 +17,11 @@ package org.onosproject.net;
17 17
18 /** 18 /**
19 * Collection of keys for annotation. 19 * Collection of keys for annotation.
20 - * Definitions of annotation keys needs to be here to avoid scattering. 20 + * <p>
21 + * Number of the annotation keys have been deprecated as the use of annotations
22 + * is being phased out and instead network configuration subsystem is being
23 + * phased-in for majority of model meta-data.
24 + * </p>
21 */ 25 */
22 public final class AnnotationKeys { 26 public final class AnnotationKeys {
23 27
...@@ -26,22 +30,34 @@ public final class AnnotationKeys { ...@@ -26,22 +30,34 @@ public final class AnnotationKeys {
26 30
27 /** 31 /**
28 * Annotation key for instance name. 32 * Annotation key for instance name.
33 + *
34 + * @deprecated since Cardinal
29 */ 35 */
36 + @Deprecated
30 public static final String NAME = "name"; 37 public static final String NAME = "name";
31 38
32 /** 39 /**
33 * Annotation key for instance type (e.g. host type). 40 * Annotation key for instance type (e.g. host type).
41 + *
42 + * @deprecated since Cardinal
34 */ 43 */
44 + @Deprecated
35 public static final String TYPE = "type"; 45 public static final String TYPE = "type";
36 46
37 /** 47 /**
38 * Annotation key for latitude (e.g. latitude of device). 48 * Annotation key for latitude (e.g. latitude of device).
49 + *
50 + * @deprecated since Cardinal
39 */ 51 */
52 + @Deprecated
40 public static final String LATITUDE = "latitude"; 53 public static final String LATITUDE = "latitude";
41 54
42 /** 55 /**
43 * Annotation key for longitute (e.g. longitude of device). 56 * Annotation key for longitute (e.g. longitude of device).
57 + *
58 + * @deprecated since Cardinal
44 */ 59 */
60 + @Deprecated
45 public static final String LONGITUDE = "longitude"; 61 public static final String LONGITUDE = "longitude";
46 62
47 /** 63 /**
...@@ -51,7 +67,10 @@ public final class AnnotationKeys { ...@@ -51,7 +67,10 @@ public final class AnnotationKeys {
51 67
52 /** 68 /**
53 * Annotation key for the device driver name. 69 * Annotation key for the device driver name.
70 + *
71 + * @deprecated since Cardinal
54 */ 72 */
73 + @Deprecated
55 public static final String DRIVER = "driver"; 74 public static final String DRIVER = "driver";
56 75
57 /** 76 /**
...@@ -61,13 +80,19 @@ public final class AnnotationKeys { ...@@ -61,13 +80,19 @@ public final class AnnotationKeys {
61 80
62 /** 81 /**
63 * Annotation key for latency. 82 * Annotation key for latency.
83 + *
84 + * @deprecated since Cardinal
64 */ 85 */
86 + @Deprecated
65 public static final String LATENCY = "latency"; 87 public static final String LATENCY = "latency";
66 88
67 /** 89 /**
68 * Annotation key for bandwidth. 90 * Annotation key for bandwidth.
69 * The value for this key is interpreted as Mbps. 91 * The value for this key is interpreted as Mbps.
92 + *
93 + * @deprecated since Cardinal
70 */ 94 */
95 + @Deprecated
71 public static final String BANDWIDTH = "bandwidth"; 96 public static final String BANDWIDTH = "bandwidth";
72 97
73 /** 98 /**
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 package org.onosproject.rest; 16 package org.onosproject.rest;
17 17
18 import com.fasterxml.jackson.databind.ObjectMapper; 18 import com.fasterxml.jackson.databind.ObjectMapper;
19 +import com.fasterxml.jackson.databind.node.ArrayNode;
19 import com.fasterxml.jackson.databind.node.ObjectNode; 20 import com.fasterxml.jackson.databind.node.ObjectNode;
20 import org.onlab.rest.BaseResource; 21 import org.onlab.rest.BaseResource;
21 import org.onosproject.codec.CodecContext; 22 import org.onosproject.codec.CodecContext;
...@@ -27,9 +28,11 @@ import org.onosproject.codec.JsonCodec; ...@@ -27,9 +28,11 @@ import org.onosproject.codec.JsonCodec;
27 */ 28 */
28 public class AbstractWebResource extends BaseResource implements CodecContext { 29 public class AbstractWebResource extends BaseResource implements CodecContext {
29 30
31 + private final ObjectMapper mapper = new ObjectMapper();
32 +
30 @Override 33 @Override
31 public ObjectMapper mapper() { 34 public ObjectMapper mapper() {
32 - return new ObjectMapper(); 35 + return mapper;
33 } 36 }
34 37
35 /** 38 /**
...@@ -65,4 +68,31 @@ public class AbstractWebResource extends BaseResource implements CodecContext { ...@@ -65,4 +68,31 @@ public class AbstractWebResource extends BaseResource implements CodecContext {
65 return get(serviceClass); 68 return get(serviceClass);
66 } 69 }
67 70
71 + /**
72 + * Creates and returns a new child object within the specified parent and
73 + * bound to the given key.
74 + *
75 + * @param parent parent object
76 + * @param key key for the new child object
77 + * @return child object
78 + */
79 + public ObjectNode newObject(ObjectNode parent, String key) {
80 + ObjectNode node = mapper.createObjectNode();
81 + parent.set(key, node);
82 + return node;
83 + }
84 +
85 + /**
86 + * Creates and returns a new child array within the specified parent and
87 + * bound to the given key.
88 + *
89 + * @param parent parent object
90 + * @param key key for the new child array
91 + * @return child array
92 + */
93 + public ArrayNode newArray(ObjectNode parent, String key) {
94 + ArrayNode node = mapper.createArrayNode();
95 + parent.set(key, node);
96 + return node;
97 + }
68 } 98 }
......
...@@ -23,48 +23,212 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -23,48 +23,212 @@ import static com.google.common.base.Preconditions.checkNotNull;
23 23
24 /** 24 /**
25 * Base abstraction of a configuration facade for a specific subject. Derived 25 * Base abstraction of a configuration facade for a specific subject. Derived
26 - * classes should keep all state in the specified JSON tree. 26 + * classes should keep all state in the specified JSON tree as that is the
27 + * only state that will be distributed or persisted; this class is merely
28 + * a facade for interacting with a particular facet of configuration on a
29 + * given subject.
27 * 30 *
28 * @param <S> type of subject 31 * @param <S> type of subject
29 */ 32 */
30 @Beta 33 @Beta
31 public abstract class Config<S> { 34 public abstract class Config<S> {
32 35
33 - protected ObjectMapper mapper; 36 + protected S subject;
37 + protected String key;
34 protected ObjectNode node; 38 protected ObjectNode node;
35 - private S subject; 39 + protected ObjectMapper mapper;
36 - private ConfigApplyDelegate<S> delegate; 40 + protected ConfigApplyDelegate delegate;
37 -
38 - /**
39 - * Returns the specific subject to which this configuration pertains.
40 - *
41 - * @return configuration subject
42 - */
43 - S subject() {
44 - return subject;
45 - }
46 41
47 /** 42 /**
48 * Initializes the configuration behaviour with necessary context. 43 * Initializes the configuration behaviour with necessary context.
49 * 44 *
50 * @param subject configuration subject 45 * @param subject configuration subject
46 + * @param key configuration key
51 * @param node JSON object node where configuration data is stored 47 * @param node JSON object node where configuration data is stored
52 * @param mapper JSON object mapper 48 * @param mapper JSON object mapper
53 * @param delegate delegate context 49 * @param delegate delegate context
54 */ 50 */
55 - public void init(S subject, ObjectNode node, ObjectMapper mapper, 51 + public void init(S subject, String key, ObjectNode node, ObjectMapper mapper,
56 - ConfigApplyDelegate<S> delegate) { 52 + ConfigApplyDelegate delegate) {
57 this.subject = checkNotNull(subject); 53 this.subject = checkNotNull(subject);
54 + this.key = key;
58 this.node = checkNotNull(node); 55 this.node = checkNotNull(node);
59 this.mapper = checkNotNull(mapper); 56 this.mapper = checkNotNull(mapper);
60 this.delegate = checkNotNull(delegate); 57 this.delegate = checkNotNull(delegate);
61 } 58 }
62 59
63 /** 60 /**
61 + * Returns the specific subject to which this configuration pertains.
62 + *
63 + * @return configuration subject
64 + */
65 + public S subject() {
66 + return subject;
67 + }
68 +
69 + /**
70 + * Returns the configuration key. This is primarily aimed for use in
71 + * composite JSON trees in external representations and has no bearing on
72 + * the internal behaviours.
73 + *
74 + * @return configuration key
75 + */
76 + public String key() {
77 + return key;
78 + }
79 +
80 + /**
81 + * Returns the JSON node that contains the configuration data.
82 + *
83 + * @return JSON node backing the configuration
84 + */
85 + public ObjectNode node() {
86 + return node;
87 + }
88 +
89 + /**
64 * Applies any configuration changes made via this configuration. 90 * Applies any configuration changes made via this configuration.
65 */ 91 */
66 public void apply() { 92 public void apply() {
67 delegate.onApply(this); 93 delegate.onApply(this);
68 } 94 }
69 95
96 +
97 + // Miscellaneous helpers for interacting with JSON
98 +
99 + /**
100 + * Gets the specified property as a string.
101 + *
102 + * @param name property name
103 + * @param defaultValue default value if property not set
104 + * @return property value or default value
105 + */
106 + protected String get(String name, String defaultValue) {
107 + return node.path(name).asText(defaultValue);
108 + }
109 +
110 + /**
111 + * Sets the specified property as a string or clears it if null value given.
112 + *
113 + * @param name property name
114 + * @param value new value or null to clear the property
115 + * @return self
116 + */
117 + protected Config<S> setOrClear(String name, String value) {
118 + if (value != null) {
119 + node.put(name, value);
120 + } else {
121 + node.remove(name);
122 + }
123 + return this;
124 + }
125 +
126 + /**
127 + * Gets the specified property as a boolean.
128 + *
129 + * @param name property name
130 + * @param defaultValue default value if property not set
131 + * @return property value or default value
132 + */
133 + protected boolean get(String name, boolean defaultValue) {
134 + return node.path(name).asBoolean(defaultValue);
135 + }
136 +
137 + /**
138 + * Sets the specified property as a boolean or clears it if null value given.
139 + *
140 + * @param name property name
141 + * @param value new value or null to clear the property
142 + * @return self
143 + */
144 + protected Config<S> setOrClear(String name, Boolean value) {
145 + if (value != null) {
146 + node.put(name, value.booleanValue());
147 + } else {
148 + node.remove(name);
149 + }
150 + return this;
151 + }
152 +
153 + /**
154 + * Gets the specified property as a long.
155 + *
156 + * @param name property name
157 + * @param defaultValue default value if property not set
158 + * @return property value or default value
159 + */
160 + protected long get(String name, long defaultValue) {
161 + return node.path(name).asLong(defaultValue);
162 + }
163 +
164 + /**
165 + * Sets the specified property as a long or clears it if null value given.
166 + *
167 + * @param name property name
168 + * @param value new value or null to clear the property
169 + * @return self
170 + */
171 + protected Config<S> setOrClear(String name, Long value) {
172 + if (value != null) {
173 + node.put(name, value.longValue());
174 + } else {
175 + node.remove(name);
176 + }
177 + return this;
178 + }
179 +
180 + /**
181 + * Gets the specified property as a double.
182 + *
183 + * @param name property name
184 + * @param defaultValue default value if property not set
185 + * @return property value or default value
186 + */
187 + protected double get(String name, double defaultValue) {
188 + return node.path(name).asDouble(defaultValue);
189 + }
190 +
191 + /**
192 + * Sets the specified property as a double or clears it if null value given.
193 + *
194 + * @param name property name
195 + * @param value new value or null to clear the property
196 + * @return self
197 + */
198 + protected Config<S> setOrClear(String name, Double value) {
199 + if (value != null) {
200 + node.put(name, value.doubleValue());
201 + } else {
202 + node.remove(name);
203 + }
204 + return this;
205 + }
206 +
207 + /**
208 + * Gets the specified property as an enum.
209 + *
210 + * @param name property name
211 + * @param defaultValue default value if property not set
212 + * @param enumClass the enum class
213 + * @return property value or default value
214 + */
215 + protected <E extends Enum<E>> E get(String name, E defaultValue, Class<E> enumClass) {
216 + return Enum.valueOf(enumClass, node.path(name).asText(defaultValue.toString()));
217 + }
218 +
219 + /**
220 + * Sets the specified property as a double or clears it if null value given.
221 + *
222 + * @param name property name
223 + * @param value new value or null to clear the property
224 + * @return self
225 + */
226 + protected <E extends Enum> Config<S> setOrClear(String name, E value) {
227 + if (value != null) {
228 + node.put(name, value.toString());
229 + } else {
230 + node.remove(name);
231 + }
232 + return this;
233 + }
70 } 234 }
......
...@@ -21,13 +21,13 @@ import com.google.common.annotations.Beta; ...@@ -21,13 +21,13 @@ import com.google.common.annotations.Beta;
21 * Delegate for notification when configuration changes have been applied. 21 * Delegate for notification when configuration changes have been applied.
22 */ 22 */
23 @Beta 23 @Beta
24 -public interface ConfigApplyDelegate<S> { 24 +public interface ConfigApplyDelegate {
25 25
26 /** 26 /**
27 * Processes changes applied to the specified configuration. 27 * Processes changes applied to the specified configuration.
28 * 28 *
29 * @param config changed configuration 29 * @param config changed configuration
30 */ 30 */
31 - void onApply(Config<S> config); 31 + void onApply(Config config);
32 32
33 } 33 }
......
...@@ -21,24 +21,31 @@ import com.google.common.annotations.Beta; ...@@ -21,24 +21,31 @@ import com.google.common.annotations.Beta;
21 /** 21 /**
22 * Base abstract factory for creating configurations for the specified subject type. 22 * Base abstract factory for creating configurations for the specified subject type.
23 * 23 *
24 - * @param <S> subject class 24 + * @param <S> type of subject
25 + * @param <C> type of configuration
25 */ 26 */
26 @Beta 27 @Beta
27 -public abstract class ConfigFactory<S> { 28 +public abstract class ConfigFactory<S, C extends Config<S>> {
28 29
29 - private final Class<S> subjectClass; 30 + private final SubjectFactory<S> subjectFactory;
30 - private final String key; 31 + private final Class<C> configClass;
32 + private final String configKey;
31 33
32 /** 34 /**
33 * Creates a new configuration factory for the specified class of subjects 35 * Creates a new configuration factory for the specified class of subjects
34 - * and bound to the given subject configuration key. 36 + * capable of generating the configurations of the specified class. The
37 + * subject and configuration class keys are used merely as keys for use in
38 + * composite JSON trees.
35 * 39 *
36 - * @param subjectClass subject class 40 + * @param subjectFactory subject factory
37 - * @param key subject configuration key 41 + * @param configClass configuration class
42 + * @param configKey configuration class key
38 */ 43 */
39 - protected ConfigFactory(Class<S> subjectClass, String key) { 44 + protected ConfigFactory(SubjectFactory<S> subjectFactory,
40 - this.subjectClass = subjectClass; 45 + Class<C> configClass, String configKey) {
41 - this.key = key; 46 + this.subjectFactory = subjectFactory;
47 + this.configClass = configClass;
48 + this.configKey = configKey;
42 } 49 }
43 50
44 /** 51 /**
...@@ -46,17 +53,28 @@ public abstract class ConfigFactory<S> { ...@@ -46,17 +53,28 @@ public abstract class ConfigFactory<S> {
46 * 53 *
47 * @return subject type 54 * @return subject type
48 */ 55 */
49 - public Class<S> subjectClass() { 56 + public SubjectFactory<S> subjectFactory() {
50 - return subjectClass; 57 + return subjectFactory;
51 } 58 }
52 59
53 /** 60 /**
54 - * Returns the key to which produced configurations should be bound. 61 + * Returns the class of the configuration which this factory generates.
55 * 62 *
56 - * @return subject configuration key 63 + * @return configuration type
57 */ 64 */
58 - public String key() { 65 + public Class<C> configClass() {
59 - return key; 66 + return configClass;
67 + }
68 +
69 + /**
70 + * Returns the unique key (within subject class) of this configuration.
71 + * This is primarily aimed for use in composite JSON trees in external
72 + * representations and has no bearing on the internal behaviours.
73 + *
74 + * @return configuration key
75 + */
76 + public String configKey() {
77 + return configKey;
60 } 78 }
61 79
62 /** 80 /**
...@@ -65,6 +83,6 @@ public abstract class ConfigFactory<S> { ...@@ -65,6 +83,6 @@ public abstract class ConfigFactory<S> {
65 * 83 *
66 * @return new uninitialized configuration 84 * @return new uninitialized configuration
67 */ 85 */
68 - public abstract Config<S> createConfig(); 86 + public abstract C createConfig();
69 87
70 } 88 }
......
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.incubator.net.config;
17 +
18 +import org.onosproject.event.AbstractEvent;
19 +
20 +/**
21 + * Describes network configuration event.
22 + */
23 +public class NetworkConfigEvent extends AbstractEvent<NetworkConfigEvent.Type, Object> {
24 +
25 + private final Class configClass;
26 +
27 + /**
28 + * Type of network configuration events.
29 + */
30 + public enum Type {
31 + /**
32 + * Signifies that network configuration was added.
33 + */
34 +
35 + CONFIG_ADDED,
36 + /**
37 + * Signifies that network configuration was updated.
38 + */
39 + CONFIG_UPDATED,
40 +
41 + /**
42 + * Signifies that network configuration was removed.
43 + */
44 + CONFIG_REMOVED
45 + }
46 +
47 + /**
48 + * Creates an event of a given type and for the specified subject and the
49 + * current time.
50 + *
51 + * @param type event type
52 + * @param subject event subject
53 + * @param configClass configuration class
54 + */
55 + public NetworkConfigEvent(Type type, Object subject, Class configClass) {
56 + super(type, subject);
57 + this.configClass = configClass;
58 + }
59 +
60 + /**
61 + * Creates an event of a given type and for the specified subject and time.
62 + *
63 + * @param type device event type
64 + * @param subject event subject
65 + * @param configClass configuration class
66 + * @param time occurrence time
67 + */
68 + public NetworkConfigEvent(Type type, Object subject, Class configClass, long time) {
69 + super(type, subject, time);
70 + this.configClass = configClass;
71 + }
72 +
73 + /**
74 + * Returns the class of configuration that has been changed.
75 + *
76 + * @return configuration class
77 + */
78 + public Class configClass() {
79 + return configClass;
80 + }
81 +
82 +}
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.incubator.net.config;
17 +
18 +import org.onosproject.event.EventListener;
19 +
20 +/**
21 + * Entity capable of receiving network configuration related events.
22 + */
23 +public interface NetworkConfigListener extends EventListener<NetworkConfigEvent> {
24 +}
...@@ -20,7 +20,11 @@ import com.google.common.annotations.Beta; ...@@ -20,7 +20,11 @@ import com.google.common.annotations.Beta;
20 import java.util.Set; 20 import java.util.Set;
21 21
22 /** 22 /**
23 - * Service for tracking network configuration factories. 23 + * Service for tracking network configuration factories. It is the basis for
24 + * extensibility to allow various core subsystems or apps to register their
25 + * own configuration factories that permit use to inject additional meta
26 + * information about how various parts of the network should be viewed and
27 + * treated.
24 */ 28 */
25 @Beta 29 @Beta
26 public interface NetworkConfigRegistry { 30 public interface NetworkConfigRegistry {
...@@ -40,34 +44,32 @@ public interface NetworkConfigRegistry { ...@@ -40,34 +44,32 @@ public interface NetworkConfigRegistry {
40 void unregisterConfigFactory(ConfigFactory configFactory); 44 void unregisterConfigFactory(ConfigFactory configFactory);
41 45
42 /** 46 /**
43 - * Returns set of configuration factories available for the specified 47 + * Returns set of all registered configuration factories.
44 - * class of subject.
45 * 48 *
46 - * @param subjectClass subject class
47 - * @param <T> type of subject
48 * @return set of config factories 49 * @return set of config factories
49 */ 50 */
50 - <T> Set<ConfigFactory<T>> getConfigFactories(Class<T> subjectClass); 51 + Set<ConfigFactory> getConfigFactories();
51 52
52 /** 53 /**
53 - * Returns the configuration type registered for the specified 54 + * Returns set of all configuration factories registered for the specified
54 - * subject type and key. 55 + * class of subject.
55 * 56 *
56 * @param subjectClass subject class 57 * @param subjectClass subject class
57 - * @param configKey configuration key 58 + * @param <S> type of subject
58 - * @param <T> type of subject 59 + * @param <C> type of configuration
59 - * @return config factory 60 + * @return set of config factories
60 */ 61 */
61 - <T> ConfigFactory<T> getConfigFactory(Class<T> subjectClass, String configKey); 62 + <S, C extends Config<S>> Set<ConfigFactory<S, C>> getConfigFactories(Class<S> subjectClass);
62 63
63 /** 64 /**
64 - * Returns the configuration type registered for the specified 65 + * Returns the configuration factory that produces the specified class of
65 - * configuration class. 66 + * configurations.
66 * 67 *
67 * @param configClass configuration class 68 * @param configClass configuration class
68 - * @param <T> type of subject 69 + * @param <S> type of subject
70 + * @param <C> type of configuration
69 * @return config factory 71 * @return config factory
70 */ 72 */
71 - <T> ConfigFactory<T> getConfigFactory(Class<Config<T>> configClass); 73 + <S, C extends Config<S>> ConfigFactory<S, C> getConfigFactory(Class<C> configClass);
72 74
73 } 75 }
......
...@@ -15,26 +15,59 @@ ...@@ -15,26 +15,59 @@
15 */ 15 */
16 package org.onosproject.incubator.net.config; 16 package org.onosproject.incubator.net.config;
17 17
18 +import com.fasterxml.jackson.databind.node.ObjectNode;
18 import com.google.common.annotations.Beta; 19 import com.google.common.annotations.Beta;
19 20
20 import java.util.Set; 21 import java.util.Set;
21 22
22 /** 23 /**
23 * Service for tracking network configurations which specify how the discovered 24 * Service for tracking network configurations which specify how the discovered
24 - * network information should be interpreted and how the network should be 25 + * network information should be interpreted and how the core or applications
25 - * configured. 26 + * should act on or configure the network.
26 */ 27 */
27 @Beta 28 @Beta
28 public interface NetworkConfigService { 29 public interface NetworkConfigService {
29 30
30 /** 31 /**
32 + * Returns the set of subject classes for which configuration may be
33 + * available.
34 + *
35 + * @return set of subject classes
36 + */
37 + Set<Class> getSubjectClasses();
38 +
39 + /**
40 + * Returns the subject factory with the specified key.
41 + *
42 + * @param subjectKey subject class key
43 + * @return subject class
44 + */
45 + SubjectFactory getSubjectFactory(String subjectKey);
46 +
47 + /**
48 + * Returns the subject factory for the specified class.
49 + *
50 + * @param subjectClass subject class
51 + * @return subject class key
52 + */
53 + SubjectFactory getSubjectFactory(Class subjectClass);
54 +
55 + /**
56 + * Returns the configuration class with the specified key.
57 + *
58 + * @param configKey subject class name
59 + * @return subject class
60 + */
61 + Class<? extends Config> getConfigClass(String configKey);
62 +
63 + /**
31 * Returns the set of subjects for which some configuration is available. 64 * Returns the set of subjects for which some configuration is available.
32 * 65 *
33 * @param subjectClass subject class 66 * @param subjectClass subject class
34 - * @param <T> type of subject 67 + * @param <S> type of subject
35 * @return set of configured subjects 68 * @return set of configured subjects
36 */ 69 */
37 - <T> Set<T> getSubjects(Class<T> subjectClass); 70 + <S> Set<S> getSubjects(Class<S> subjectClass);
38 71
39 /** 72 /**
40 * Returns the set of subjects for which the specified configuration is 73 * Returns the set of subjects for which the specified configuration is
...@@ -42,20 +75,20 @@ public interface NetworkConfigService { ...@@ -42,20 +75,20 @@ public interface NetworkConfigService {
42 * 75 *
43 * @param subjectClass subject class 76 * @param subjectClass subject class
44 * @param configClass configuration class 77 * @param configClass configuration class
45 - * @param <T> type of subject 78 + * @param <S> type of subject
79 + * @param <C> type of configuration
46 * @return set of configured subjects 80 * @return set of configured subjects
47 */ 81 */
48 - <T> Set<T> getSubjects(Class<T> subjectClass, Class<Config<T>> configClass); 82 + <S, C extends Config<S>> Set<S> getSubjects(Class<S> subjectClass, Class<C> configClass);
49 -
50 83
51 /** 84 /**
52 * Returns all configurations for the specified subject. 85 * Returns all configurations for the specified subject.
53 * 86 *
54 * @param subject configuration subject 87 * @param subject configuration subject
55 - * @param <T> type of subject 88 + * @param <S> type of subject
56 * @return set of configurations 89 * @return set of configurations
57 */ 90 */
58 - <T> Set<Config<T>> getConfigs(T subject); 91 + <S> Set<? extends Config<S>> getConfigs(S subject);
59 92
60 /** 93 /**
61 * Returns the configuration for the specified subject and configuration 94 * Returns the configuration for the specified subject and configuration
...@@ -63,9 +96,61 @@ public interface NetworkConfigService { ...@@ -63,9 +96,61 @@ public interface NetworkConfigService {
63 * 96 *
64 * @param subject configuration subject 97 * @param subject configuration subject
65 * @param configClass configuration class 98 * @param configClass configuration class
66 - * @param <T> type of subject 99 + * @param <S> type of subject
100 + * @param <C> type of configuration
101 + * @return configuration or null if one is not available
102 + */
103 + <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass);
104 +
105 + /**
106 + * Creates a new configuration for the specified subject and configuration
107 + * class. If one already exists, it is simply returned.
108 + *
109 + * @param subject configuration subject
110 + * @param configClass configuration class
111 + * @param <S> type of subject
112 + * @param <C> type of configuration
113 + * @return configuration or null if one is not available
114 + */
115 + <S, C extends Config<S>> C addConfig(S subject, Class<C> configClass);
116 +
117 + /**
118 + * Applies configuration for the specified subject and configuration
119 + * class using the raw JSON object. If configuration already exists, it
120 + * will be updated.
121 + *
122 + * @param subject configuration subject
123 + * @param configClass configuration class
124 + * @param json raw JSON node containing the configuration data
125 + * @param <S> type of subject
126 + * @param <C> type of configuration
67 * @return configuration or null if one is not available 127 * @return configuration or null if one is not available
68 */ 128 */
69 - <T> Config<T> getConfig(T subject, Class<Config<T>> configClass); 129 + <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass,
130 + ObjectNode json);
70 131
132 + /**
133 + * Clears any configuration for the specified subject and configuration
134 + * class. If one does not exist, this call has no effect.
135 + *
136 + * @param subject configuration subject
137 + * @param configClass configuration class
138 + * @param <S> type of subject
139 + * @param <C> type of configuration
140 + */
141 + <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass);
142 +
143 + /**
144 + * Adds the specified network config listener.
145 + *
146 + * @param listener network config listener
147 + */
148 + void addListener(NetworkConfigListener listener);
149 +
150 + /**
151 + * Removes the specified network config listener.
152 + *
153 + * @param listener network config listener
154 + */
155 + void removeListener(NetworkConfigListener listener);
71 } 156 }
......
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.incubator.net.config;
17 +
18 +import com.fasterxml.jackson.databind.node.ObjectNode;
19 +import org.onosproject.store.Store;
20 +
21 +import java.util.Set;
22 +
23 +/**
24 + * Mechanism for distributing and storing network configuration information.
25 + */
26 +public interface NetworkConfigStore extends Store<NetworkConfigEvent, NetworkConfigStoreDelegate> {
27 +
28 + /**
29 + * Adds a new configuration factory.
30 + *
31 + * @param configFactory configuration factory to add
32 + */
33 + void addConfigFactory(ConfigFactory configFactory);
34 +
35 + /**
36 + * Removes a configuration factory.
37 + *
38 + * @param configFactory configuration factory to remove
39 + */
40 + void removeConfigFactory(ConfigFactory configFactory);
41 +
42 + /**
43 + * Returns the configuration factory for the specified configuration class.
44 + *
45 + * @param configClass configuration class
46 + * @param <S> type of subject
47 + * @param <C> type of configuration
48 + * @return configuration factory or null
49 + */
50 + <S, C extends Config<S>> ConfigFactory<S, C> getConfigFactory(Class<C> configClass);
51 +
52 + /**
53 + * Returns set of subjects of the specified class, which have some
54 + * network configuration associated with them.
55 + *
56 + * @param subjectClass subject class
57 + * @param <S> type of subject
58 + * @return set of subject
59 + */
60 + <S> Set<S> getSubjects(Class<S> subjectClass);
61 +
62 + /**
63 + * Returns set of subjects of the specified class, which have the
64 + * specified class of network configuration associated with them.
65 + *
66 + * @param subjectClass subject class
67 + * @param configClass configuration class
68 + * @param <S> type of subject
69 + * @param <C> type of configuration
70 + * @return set of subject
71 + */
72 + <S, C extends Config<S>> Set<S> getSubjects(Class<S> subjectClass, Class<C> configClass);
73 +
74 + /**
75 + * Returns set of configuration classes available for the specified subject.
76 + *
77 + * @param subject configuration subject
78 + * @param <S> type of subject
79 + * @return set of configuration classes
80 + */
81 + <S> Set<Class<? extends Config<S>>> getConfigClasses(S subject);
82 +
83 + /**
84 + * Get the configuration of the given class and for the specified subject.
85 + *
86 + * @param subject configuration subject
87 + * @param configClass configuration class
88 + * @param <S> type of subject
89 + * @param <C> type of configuration
90 + * @return configuration object
91 + */
92 + <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass);
93 +
94 + /**
95 + * Creates a new configuration of the given class for the specified subject.
96 + *
97 + * @param subject configuration subject
98 + * @param configClass configuration class
99 + * @param <S> type of subject
100 + * @param <C> type of configuration
101 + * @return configuration object
102 + */
103 + <S, C extends Config<S>> C createConfig(S subject, Class<C> configClass);
104 +
105 + /**
106 + * Applies configuration for the specified subject and configuration
107 + * class using the raw JSON object. If configuration already exists, it
108 + * will be updated.
109 + *
110 + * @param subject configuration subject
111 + * @param configClass configuration class
112 + * @param json raw JSON node containing the configuration data
113 + * @param <S> type of subject
114 + * @param <C> type of configuration
115 + */
116 + <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass,
117 + ObjectNode json);
118 +
119 + /**
120 + * Clears the configuration of the given class for the specified subject.
121 + *
122 + * @param subject configuration subject
123 + * @param configClass configuration class
124 + * @param <S> type of subject
125 + * @param <C> type of configuration
126 + */
127 + <S, C extends Config<S>> void clearConfig(S subject, Class<C> configClass);
128 +
129 +}
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.incubator.net.config;
17 +
18 +import org.onosproject.store.StoreDelegate;
19 +
20 +/**
21 + * Network configuration store delegate abstraction.
22 + */
23 +public interface NetworkConfigStoreDelegate extends StoreDelegate<NetworkConfigEvent> {
24 +}
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.incubator.net.config;
17 +
18 +
19 +import com.google.common.annotations.Beta;
20 +
21 +/**
22 + * Base abstract factory for creating configuration subjects from their
23 + * string key image.
24 + *
25 + * @param <S> subject class
26 + */
27 +@Beta
28 +public abstract class SubjectFactory<S> {
29 +
30 + private final Class<S> subjectClass;
31 + private final String subjectKey;
32 +
33 + /**
34 + * Creates a new configuration factory for the specified class of subjects
35 + * capable of generating the configurations of the specified class. The
36 + * subject and configuration class keys are used merely as keys for use in
37 + * composite JSON trees.
38 + *
39 + * @param subjectClass subject class
40 + * @param subjectKey subject class key
41 + */
42 + protected SubjectFactory(Class<S> subjectClass, String subjectKey) {
43 + this.subjectClass = subjectClass;
44 + this.subjectKey = subjectKey;
45 + }
46 +
47 + /**
48 + * Returns the class of the subject to which this factory applies.
49 + *
50 + * @return subject type
51 + */
52 + public Class<S> subjectClass() {
53 + return subjectClass;
54 + }
55 +
56 + /**
57 + * Returns the unique key of this configuration subject class.
58 + * This is primarily aimed for use in composite JSON trees in external
59 + * representations and has no bearing on the internal behaviours.
60 + *
61 + * @return configuration key
62 + */
63 + public String subjectKey() {
64 + return subjectKey;
65 + }
66 +
67 + /**
68 + * Creates a configuration subject from its key image.
69 + *
70 + * @return configuration subject
71 + */
72 + public abstract S createSubject(String key);
73 +
74 +}
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.incubator.net.config.basics;
17 +
18 +import org.onosproject.incubator.net.config.Config;
19 +
20 +/**
21 + * Base abstraction for network entities for which admission into control
22 + * domain can be selectively configured, e.g. devices, end-stations, links
23 + */
24 +public abstract class AllowedEntityConfig<S> extends Config<S> {
25 +
26 + private static final String ALLOWED = "allowed";
27 +
28 + /**
29 + * Indicates whether the element is allowed for admission into the control
30 + * domain.
31 + *
32 + * @return true if element is allowed
33 + */
34 + public boolean isAllowed() {
35 + return get(ALLOWED, true);
36 + }
37 +
38 + /**
39 + * Specifies whether the element is to be allowed for admission into the
40 + * control domain.
41 + *
42 + * @param isAllowed true to allow; false to forbid; null to clear
43 + * @return self
44 + */
45 + public AllowedEntityConfig isAllowed(Boolean isAllowed) {
46 + return (AllowedEntityConfig) setOrClear(ALLOWED, isAllowed);
47 + }
48 +
49 +}
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.incubator.net.config.basics;
17 +
18 +import org.onosproject.net.Device;
19 +import org.onosproject.net.DeviceId;
20 +
21 +/**
22 + * Basic configuration for network infrastructure devices.
23 + */
24 +public class BasicDeviceConfig extends BasicElementConfig<DeviceId> {
25 +
26 + public static final String TYPE = "type";
27 + public static final String DRIVER = "driver";
28 +
29 + /**
30 + * Returns the device type.
31 + *
32 + * @return device type override
33 + */
34 + public Device.Type type() {
35 + return get(TYPE, Device.Type.SWITCH, Device.Type.class);
36 + }
37 +
38 + /**
39 + * Sets the device type.
40 + *
41 + * @param type device type override
42 + * @return self
43 + */
44 + public BasicDeviceConfig type(Device.Type type) {
45 + return (BasicDeviceConfig) setOrClear(TYPE, type);
46 + }
47 +
48 + /**
49 + * Returns the device driver name.
50 + *
51 + * @return driver name of null if not set
52 + */
53 + public String driver() {
54 + return get(DRIVER, subject.toString());
55 + }
56 +
57 + /**
58 + * Sets the driver name.
59 + *
60 + * @param driverName new driver name; null to clear
61 + * @return self
62 + */
63 + public BasicElementConfig driver(String driverName) {
64 + return (BasicElementConfig) setOrClear(DRIVER, driverName);
65 + }
66 +
67 + // TODO: device port meta-data to be configured via BasicPortsConfig
68 + // TODO: device credentials/keys
69 +
70 +}
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.incubator.net.config.basics;
17 +
18 +/**
19 + * Basic configuration for network elements, e.g. devices, hosts. Such elements
20 + * can have a friendly name, geo-coordinates, logical rack coordinates and
21 + * an owner entity.
22 + */
23 +public abstract class BasicElementConfig<S> extends AllowedEntityConfig<S> {
24 +
25 + public static final String NAME = "name";
26 +
27 + public static final String LATITUDE = "latitude";
28 + public static final String LONGITUDE = "longitude";
29 +
30 + public static final String RACK_ADDRESS = "rackAddress";
31 + public static final String OWNER = "owner";
32 +
33 + /**
34 + * Returns friendly label for the element.
35 + *
36 + * @return friendly label or element id itself if not set
37 + */
38 + public String name() {
39 + return get(NAME, subject.toString());
40 + }
41 +
42 + /**
43 + * Sets friendly label for the element.
44 + *
45 + * @param name new friendly label; null to clear
46 + * @return self
47 + */
48 + public BasicElementConfig name(String name) {
49 + return (BasicElementConfig) setOrClear(NAME, name);
50 + }
51 +
52 + /**
53 + * Returns element latitude.
54 + *
55 + * @return element latitude; -1 if not set
56 + */
57 + public double latitude() {
58 + return get(LATITUDE, -1.0);
59 + }
60 +
61 + /**
62 + * Sets the element latitude.
63 + *
64 + * @param latitude new latitude; null to clear
65 + * @return self
66 + */
67 + public BasicElementConfig latitude(Double latitude) {
68 + return (BasicElementConfig) setOrClear(LATITUDE, latitude);
69 + }
70 +
71 + /**
72 + * Returns element latitude.
73 + *
74 + * @return element latitude; -1 if not set
75 + */
76 + public double longitude() {
77 + return get(LONGITUDE, -1.0);
78 + }
79 +
80 + /**
81 + * Sets the element longitude.
82 + *
83 + * @param longitude new longitude; null to clear
84 + * @return self
85 + */
86 + public BasicElementConfig longitude(Double longitude) {
87 + return (BasicElementConfig) setOrClear(LONGITUDE, longitude);
88 + }
89 +
90 + /**
91 + * Returns the element rack address.
92 + *
93 + * @return rack address; null if not set
94 + */
95 + public String rackAddress() {
96 + return get(RACK_ADDRESS, null);
97 + }
98 +
99 + /**
100 + * Sets element rack address.
101 + *
102 + * @param address new rack address; null to clear
103 + * @return self
104 + */
105 + public BasicElementConfig rackAddress(String address) {
106 + return (BasicElementConfig) setOrClear(RACK_ADDRESS, address);
107 + }
108 +
109 + /**
110 + * Returns owner of the element.
111 + *
112 + * @return owner or null if not set
113 + */
114 + public String owner() {
115 + return get(OWNER, null);
116 + }
117 +
118 + /**
119 + * Sets the owner of the element.
120 + *
121 + * @param owner new owner; null to clear
122 + * @return self
123 + */
124 + public BasicElementConfig owner(String owner) {
125 + return (BasicElementConfig) setOrClear(OWNER, owner);
126 + }
127 +
128 +}
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.incubator.net.config.basics;
17 +
18 +import org.onosproject.net.HostId;
19 +
20 +/**
21 + * Basic configuration for network end-station hosts.
22 + */
23 +public class BasicHostConfig extends BasicElementConfig<HostId> {
24 +
25 + // TODO: determine what aspects of configuration to add for hosts
26 +
27 +}
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.incubator.net.config.basics;
17 +
18 +import org.onosproject.net.Link;
19 +import org.onosproject.net.LinkKey;
20 +
21 +import java.time.Duration;
22 +
23 +/**
24 + * Basic configuration for network infrastructure link.
25 + */
26 +public class BasicLinkConfig extends AllowedEntityConfig<LinkKey> {
27 +
28 + public static final String TYPE = "type";
29 + public static final String LATENCY = "latency";
30 + public static final String BANDWIDTH = "bandwidth";
31 +
32 + /**
33 + * Returns the link type.
34 + *
35 + * @return link type override
36 + */
37 + public Link.Type type() {
38 + return get(TYPE, Link.Type.DIRECT, Link.Type.class);
39 + }
40 +
41 + /**
42 + * Sets the link type.
43 + *
44 + * @param type link type override
45 + * @return self
46 + */
47 + public BasicLinkConfig type(Link.Type type) {
48 + return (BasicLinkConfig) setOrClear(TYPE, type);
49 + }
50 +
51 + /**
52 + * Returns link latency in terms of nanos.
53 + *
54 + * @return link latency; -1 if not set
55 + */
56 + public Duration latency() {
57 + return Duration.ofNanos(get(LATENCY, -1));
58 + }
59 +
60 + /**
61 + * Sets the link latency.
62 + *
63 + * @param latency new latency; null to clear
64 + * @return self
65 + */
66 + public BasicElementConfig latency(Duration latency) {
67 + Long nanos = latency == null ? null : latency.toNanos();
68 + return (BasicElementConfig) setOrClear(LATENCY, nanos);
69 + }
70 +
71 + /**
72 + * Returns link bandwidth in terms of Mbps.
73 + *
74 + * @return link bandwidth; -1 if not set
75 + */
76 + public long bandwidth() {
77 + return get(BANDWIDTH, -1);
78 + }
79 +
80 + /**
81 + * Sets the link bandwidth.
82 + *
83 + * @param bandwidth new bandwidth; null to clear
84 + * @return self
85 + */
86 + public BasicElementConfig bandwidth(Long bandwidth) {
87 + return (BasicElementConfig) setOrClear(BANDWIDTH, bandwidth);
88 + }
89 +
90 +}
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.incubator.net.config.basics;
17 +
18 +import org.onosproject.core.ApplicationId;
19 +import org.onosproject.incubator.net.config.SubjectFactory;
20 +import org.onosproject.net.ConnectPoint;
21 +import org.onosproject.net.DeviceId;
22 +import org.onosproject.net.HostId;
23 +import org.onosproject.net.LinkKey;
24 +
25 +import static com.google.common.base.Preconditions.checkArgument;
26 +
27 +/**
28 + * Set of subject factories for potential configuration subjects.
29 + */
30 +public final class SubjectFactories {
31 +
32 + // Construction forbidden
33 + private SubjectFactories() {
34 + }
35 +
36 + public static final SubjectFactory<ApplicationId> APP_SUBJECT_FACTORY =
37 + new SubjectFactory<ApplicationId>(ApplicationId.class, "apps") {
38 + @Override
39 + public ApplicationId createSubject(String key) {
40 + // FIXME: figure out how to safely create sanctioned app ids
41 + return null;
42 + }
43 + };
44 +
45 + public static final SubjectFactory<DeviceId> DEVICE_SUBJECT_FACTORY =
46 + new SubjectFactory<DeviceId>(DeviceId.class, "devices") {
47 + @Override
48 + public DeviceId createSubject(String key) {
49 + return DeviceId.deviceId(key);
50 + }
51 + };
52 +
53 + public static final SubjectFactory<HostId> HOST_SUBJECT_FACTORY =
54 + new SubjectFactory<HostId>(HostId.class, "hosts") {
55 + @Override
56 + public HostId createSubject(String key) {
57 + return HostId.hostId(key);
58 + }
59 + };
60 +
61 + public static final SubjectFactory<LinkKey> LINK_SUBJECT_FACTORY =
62 + new SubjectFactory<LinkKey>(LinkKey.class, "links") {
63 + @Override
64 + public LinkKey createSubject(String key) {
65 + String[] cps = key.split("-");
66 + checkArgument(cps.length == 2, "Incorrect link key format: %s", key);
67 + return LinkKey.linkKey(ConnectPoint.deviceConnectPoint(cps[0]),
68 + ConnectPoint.deviceConnectPoint(cps[1]));
69 + }
70 + };
71 +
72 +}
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.incubator.net.config.impl;
17 +
18 +import com.google.common.collect.ImmutableSet;
19 +import org.apache.felix.scr.annotations.Activate;
20 +import org.apache.felix.scr.annotations.Component;
21 +import org.apache.felix.scr.annotations.Deactivate;
22 +import org.apache.felix.scr.annotations.Reference;
23 +import org.apache.felix.scr.annotations.ReferenceCardinality;
24 +import org.onosproject.incubator.net.config.ConfigFactory;
25 +import org.onosproject.incubator.net.config.NetworkConfigRegistry;
26 +import org.onosproject.incubator.net.config.basics.BasicDeviceConfig;
27 +import org.onosproject.incubator.net.config.basics.BasicHostConfig;
28 +import org.onosproject.incubator.net.config.basics.BasicLinkConfig;
29 +import org.onosproject.net.DeviceId;
30 +import org.onosproject.net.HostId;
31 +import org.onosproject.net.LinkKey;
32 +import org.slf4j.Logger;
33 +import org.slf4j.LoggerFactory;
34 +
35 +import java.util.Set;
36 +
37 +import static org.onosproject.incubator.net.config.basics.SubjectFactories.*;
38 +
39 +/**
40 + * Component for registration of builtin basic network configurations.
41 + */
42 +@Component(immediate = true)
43 +public class BasicNetworkConfigs {
44 +
45 + private final Logger log = LoggerFactory.getLogger(getClass());
46 +
47 + private final Set<ConfigFactory> factories = ImmutableSet.of(
48 + new ConfigFactory<DeviceId, BasicDeviceConfig>(DEVICE_SUBJECT_FACTORY,
49 + BasicDeviceConfig.class,
50 + "basic") {
51 + @Override
52 + public BasicDeviceConfig createConfig() {
53 + return new BasicDeviceConfig();
54 + }
55 + },
56 + new ConfigFactory<HostId, BasicHostConfig>(HOST_SUBJECT_FACTORY,
57 + BasicHostConfig.class,
58 + "basic") {
59 + @Override
60 + public BasicHostConfig createConfig() {
61 + return new BasicHostConfig();
62 + }
63 + },
64 + new ConfigFactory<LinkKey, BasicLinkConfig>(LINK_SUBJECT_FACTORY,
65 + BasicLinkConfig.class,
66 + "basic") {
67 + @Override
68 + public BasicLinkConfig createConfig() {
69 + return new BasicLinkConfig();
70 + }
71 + }
72 + );
73 +
74 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
75 + protected NetworkConfigRegistry registry;
76 +
77 + @Activate
78 + public void activate() {
79 + factories.forEach(registry::registerConfigFactory);
80 + log.info("Started");
81 + }
82 +
83 + @Deactivate
84 + public void deactivate() {
85 + factories.forEach(registry::unregisterConfigFactory);
86 + log.info("Stopped");
87 + }
88 +
89 +}
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.incubator.net.config.impl;
17 +
18 +import com.fasterxml.jackson.databind.node.ObjectNode;
19 +import com.google.common.collect.ImmutableSet;
20 +import com.google.common.collect.Maps;
21 +import org.apache.felix.scr.annotations.Activate;
22 +import org.apache.felix.scr.annotations.Component;
23 +import org.apache.felix.scr.annotations.Deactivate;
24 +import org.apache.felix.scr.annotations.Reference;
25 +import org.apache.felix.scr.annotations.ReferenceCardinality;
26 +import org.apache.felix.scr.annotations.Service;
27 +import org.onosproject.event.EventDeliveryService;
28 +import org.onosproject.event.ListenerRegistry;
29 +import org.onosproject.incubator.net.config.Config;
30 +import org.onosproject.incubator.net.config.ConfigFactory;
31 +import org.onosproject.incubator.net.config.NetworkConfigEvent;
32 +import org.onosproject.incubator.net.config.NetworkConfigListener;
33 +import org.onosproject.incubator.net.config.NetworkConfigRegistry;
34 +import org.onosproject.incubator.net.config.NetworkConfigService;
35 +import org.onosproject.incubator.net.config.NetworkConfigStore;
36 +import org.onosproject.incubator.net.config.NetworkConfigStoreDelegate;
37 +import org.onosproject.incubator.net.config.SubjectFactory;
38 +import org.slf4j.Logger;
39 +import org.slf4j.LoggerFactory;
40 +
41 +import java.util.Map;
42 +import java.util.Objects;
43 +import java.util.Set;
44 +
45 +import static com.google.common.base.Preconditions.checkNotNull;
46 +
47 +/**
48 + * Implementation of the network configuration subsystem.
49 + */
50 +@Component(immediate = true)
51 +@Service
52 +public class NetworkConfigManager implements NetworkConfigRegistry, NetworkConfigService {
53 +
54 + private final Logger log = LoggerFactory.getLogger(getClass());
55 +
56 + private static final String NULL_FACTORY_MSG = "Factory cannot be null";
57 + private static final String NULL_SCLASS_MSG = "Subject class cannot be null";
58 + private static final String NULL_CCLASS_MSG = "Config class cannot be null";
59 + private static final String NULL_SUBJECT_MSG = "Subject cannot be null";
60 +
61 + // Inventory of configuration factories
62 + private final Map<ConfigKey, ConfigFactory> factories = Maps.newConcurrentMap();
63 +
64 + // Secondary indeces to retrieve subject and config classes by keys
65 + private final Map<String, SubjectFactory> subjectClasses = Maps.newConcurrentMap();
66 + private final Map<Class, SubjectFactory> subjectClassKeys = Maps.newConcurrentMap();
67 + private final Map<String, Class<? extends Config>> configClasses = Maps.newConcurrentMap();
68 +
69 + private final ListenerRegistry<NetworkConfigEvent, NetworkConfigListener>
70 + listenerRegistry = new ListenerRegistry<>();
71 +
72 + private final NetworkConfigStoreDelegate storeDelegate = new InternalStoreDelegate();
73 +
74 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
75 + protected NetworkConfigStore store;
76 +
77 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
78 + protected EventDeliveryService eventDispatcher;
79 +
80 +
81 + @Activate
82 + public void activate() {
83 + eventDispatcher.addSink(NetworkConfigEvent.class, listenerRegistry);
84 + store.setDelegate(storeDelegate);
85 + log.info("Started");
86 + }
87 +
88 + @Deactivate
89 + public void deactivate() {
90 + eventDispatcher.removeSink(NetworkConfigEvent.class);
91 + store.unsetDelegate(storeDelegate);
92 + log.info("Stopped");
93 + }
94 +
95 +
96 + @Override
97 + @SuppressWarnings("unchecked")
98 + public void registerConfigFactory(ConfigFactory configFactory) {
99 + checkNotNull(configFactory, NULL_FACTORY_MSG);
100 + factories.put(key(configFactory), configFactory);
101 + configClasses.put(configFactory.configKey(), configFactory.configClass());
102 +
103 + SubjectFactory subjectFactory = configFactory.subjectFactory();
104 + subjectClasses.putIfAbsent(subjectFactory.subjectKey(), subjectFactory);
105 + subjectClassKeys.putIfAbsent(subjectFactory.subjectClass(), subjectFactory);
106 +
107 + store.addConfigFactory(configFactory);
108 + }
109 +
110 + @Override
111 + public void unregisterConfigFactory(ConfigFactory configFactory) {
112 + checkNotNull(configFactory, NULL_FACTORY_MSG);
113 + factories.remove(key(configFactory));
114 + configClasses.remove(configFactory.configKey());
115 +
116 + // Note that we are deliberately not removing subject factory key bindings.
117 + store.removeConfigFactory(configFactory);
118 + }
119 +
120 + @Override
121 + public Set<ConfigFactory> getConfigFactories() {
122 + return ImmutableSet.copyOf(factories.values());
123 + }
124 +
125 +
126 + @Override
127 + @SuppressWarnings("unchecked")
128 + public <S, C extends Config<S>> Set<ConfigFactory<S, C>> getConfigFactories(Class<S> subjectClass) {
129 + ImmutableSet.Builder<ConfigFactory<S, C>> builder = ImmutableSet.builder();
130 + factories.forEach((key, factory) -> {
131 + if (factory.subjectFactory().subjectClass().equals(subjectClass)) {
132 + builder.add(factory);
133 + }
134 + });
135 + return builder.build();
136 + }
137 +
138 + @Override
139 + public <S, C extends Config<S>> ConfigFactory<S, C> getConfigFactory(Class<C> configClass) {
140 + checkNotNull(configClass, NULL_CCLASS_MSG);
141 + return store.getConfigFactory(configClass);
142 + }
143 +
144 +
145 + @Override
146 + public Set<Class> getSubjectClasses() {
147 + ImmutableSet.Builder<Class> builder = ImmutableSet.builder();
148 + factories.forEach((k, v) -> builder.add(k.subjectClass));
149 + return builder.build();
150 + }
151 +
152 + @Override
153 + public SubjectFactory getSubjectFactory(String subjectKey) {
154 + return subjectClasses.get(subjectKey);
155 + }
156 +
157 + @Override
158 + public SubjectFactory getSubjectFactory(Class subjectClass) {
159 + return subjectClassKeys.get(subjectClass);
160 + }
161 +
162 + @Override
163 + public Class<? extends Config> getConfigClass(String configKey) {
164 + return configClasses.get(configKey);
165 + }
166 +
167 + @Override
168 + public <S> Set<S> getSubjects(Class<S> subjectClass) {
169 + checkNotNull(subjectClass, NULL_SCLASS_MSG);
170 + return store.getSubjects(subjectClass);
171 + }
172 +
173 + @Override
174 + public <S, C extends Config<S>> Set<S> getSubjects(Class<S> subjectClass, Class<C> configClass) {
175 + checkNotNull(subjectClass, NULL_SCLASS_MSG);
176 + checkNotNull(configClass, NULL_CCLASS_MSG);
177 + return store.getSubjects(subjectClass, configClass);
178 + }
179 +
180 + @Override
181 + public <S> Set<Config<S>> getConfigs(S subject) {
182 + checkNotNull(subject, NULL_SUBJECT_MSG);
183 + Set<Class<? extends Config<S>>> configClasses = store.getConfigClasses(subject);
184 + ImmutableSet.Builder<Config<S>> cfg = ImmutableSet.builder();
185 + configClasses.forEach(cc -> cfg.add(store.getConfig(subject, cc)));
186 + return cfg.build();
187 + }
188 +
189 + @Override
190 + public <S, T extends Config<S>> T getConfig(S subject, Class<T> configClass) {
191 + checkNotNull(subject, NULL_SUBJECT_MSG);
192 + checkNotNull(configClass, NULL_CCLASS_MSG);
193 + return store.getConfig(subject, configClass);
194 + }
195 +
196 +
197 + @Override
198 + public <S, C extends Config<S>> C addConfig(S subject, Class<C> configClass) {
199 + checkNotNull(subject, NULL_SUBJECT_MSG);
200 + checkNotNull(configClass, NULL_CCLASS_MSG);
201 + return store.createConfig(subject, configClass);
202 + }
203 +
204 + @Override
205 + public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, ObjectNode json) {
206 + checkNotNull(subject, NULL_SUBJECT_MSG);
207 + checkNotNull(configClass, NULL_CCLASS_MSG);
208 + return store.applyConfig(subject, configClass, json);
209 + }
210 +
211 + @Override
212 + public <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass) {
213 + checkNotNull(subject, NULL_SUBJECT_MSG);
214 + checkNotNull(configClass, NULL_CCLASS_MSG);
215 + store.clearConfig(subject, configClass);
216 + }
217 +
218 + @Override
219 + public void addListener(NetworkConfigListener listener) {
220 + listenerRegistry.addListener(listener);
221 + }
222 +
223 + @Override
224 + public void removeListener(NetworkConfigListener listener) {
225 + listenerRegistry.removeListener(listener);
226 + }
227 +
228 +
229 + // Auxiliary store delegate to receive notification about changes in
230 + // the network configuration store state - by the store itself.
231 + private class InternalStoreDelegate implements NetworkConfigStoreDelegate {
232 + @Override
233 + public void notify(NetworkConfigEvent event) {
234 + eventDispatcher.post(event);
235 + }
236 + }
237 +
238 +
239 + // Produces a key for uniquely tracking a config factory.
240 + private static ConfigKey key(ConfigFactory factory) {
241 + return new ConfigKey(factory.subjectFactory().subjectClass(), factory.configClass());
242 + }
243 +
244 + // Auxiliary key to track config factories.
245 + private static final class ConfigKey {
246 + final Class subjectClass;
247 + final Class configClass;
248 +
249 + private ConfigKey(Class subjectClass, Class configClass) {
250 + this.subjectClass = subjectClass;
251 + this.configClass = configClass;
252 + }
253 +
254 + @Override
255 + public int hashCode() {
256 + return Objects.hash(subjectClass, configClass);
257 + }
258 +
259 + @Override
260 + public boolean equals(Object obj) {
261 + if (this == obj) {
262 + return true;
263 + }
264 + if (obj instanceof ConfigKey) {
265 + final ConfigKey other = (ConfigKey) obj;
266 + return Objects.equals(this.subjectClass, other.subjectClass)
267 + && Objects.equals(this.configClass, other.configClass);
268 + }
269 + return false;
270 + }
271 + }
272 +
273 +}
...@@ -67,6 +67,7 @@ ...@@ -67,6 +67,7 @@
67 67
68 org.onosproject.rest.resources.ApplicationsWebResource, 68 org.onosproject.rest.resources.ApplicationsWebResource,
69 org.onosproject.rest.resources.ComponentConfigWebResource, 69 org.onosproject.rest.resources.ComponentConfigWebResource,
70 + org.onosproject.rest.resources.NetworkConfigWebResource,
70 org.onosproject.rest.resources.ClusterWebResource, 71 org.onosproject.rest.resources.ClusterWebResource,
71 org.onosproject.rest.resources.DevicesWebResource, 72 org.onosproject.rest.resources.DevicesWebResource,
72 org.onosproject.rest.resources.LinksWebResource, 73 org.onosproject.rest.resources.LinksWebResource,
......
1 +{
2 + "devices": {
3 + "of:001122334455667788": {
4 + "basic": {
5 + "name": "Test ROADM",
6 + "type": "ROADM",
7 + "latitude": -38.587,
8 + "longitude": 134.567
9 + }
10 + }
11 + }
12 +}
...\ No newline at end of file ...\ No newline at end of file