Thomas Vachuska
Committed by Ray Milkey

Sketching out component configuration model & API.

Added initial cut of implementation.
Finished implementation; ready for merge.

Change-Id: I385181c0591604a5c44986b97fb881eba7e0528e
Showing 24 changed files with 1517 additions and 41 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 org.apache.karaf.shell.commands.Argument;
19 +import org.apache.karaf.shell.commands.Command;
20 +import org.onosproject.cfg.ComponentConfigService;
21 +import org.onosproject.cfg.ConfigProperty;
22 +import org.onosproject.cli.AbstractShellCommand;
23 +
24 +import java.util.Set;
25 +
26 +import static com.google.common.base.Strings.isNullOrEmpty;
27 +
28 +/**
29 + * Manages application inventory.
30 + */
31 +@Command(scope = "onos", name = "cfg",
32 + description = "Manages component configuration")
33 +public class ComponentConfigCommand extends AbstractShellCommand {
34 +
35 + static final String GET = "get";
36 + static final String SET = "set";
37 +
38 + private static final String FMT = " name=%s, type=%s, value=%s, defaultValue=%s, description=%s";
39 +
40 + @Argument(index = 0, name = "command",
41 + description = "Command name (activate|deactivate|uninstall)",
42 + required = false, multiValued = false)
43 + String command = null;
44 +
45 + @Argument(index = 1, name = "component", description = "Component name",
46 + required = false, multiValued = false)
47 + String component = null;
48 +
49 + @Argument(index = 2, name = "name", description = "Property name",
50 + required = false, multiValued = false)
51 + String name = null;
52 +
53 + @Argument(index = 3, name = "value", description = "Property value",
54 + required = false, multiValued = false)
55 + String value = null;
56 +
57 + ComponentConfigService service;
58 +
59 + @Override
60 + protected void execute() {
61 + service = get(ComponentConfigService.class);
62 + if (isNullOrEmpty(command)) {
63 + listComponents();
64 + } else if (command.equals(GET) && isNullOrEmpty(component)) {
65 + listAllComponentsProperties();
66 + } else if (command.equals(GET) && isNullOrEmpty(name)) {
67 + listComponentProperties(component);
68 + } else if (command.equals(GET)) {
69 + listComponentProperty(component, name);
70 + } else if (command.equals(SET) && isNullOrEmpty(value)) {
71 + service.unsetProperty(component, name);
72 + } else if (command.equals(SET)) {
73 + service.setProperty(component, name, value);
74 + } else {
75 + error("Illegal usage");
76 + }
77 + }
78 +
79 + private void listAllComponentsProperties() {
80 + service.getComponentNames().forEach(this::listComponentProperties);
81 + }
82 +
83 + private void listComponents() {
84 + service.getComponentNames().forEach(n -> print("%s", n));
85 + }
86 +
87 + private void listComponentProperties(String component) {
88 + Set<ConfigProperty> props = service.getProperties(component);
89 + print("%s", component);
90 + props.forEach(p -> print(FMT, p.name(), p.type().toString().toLowerCase(),
91 + p.value(), p.defaultValue(), p.description()));
92 + }
93 +
94 + private void listComponentProperty(String component, String name) {
95 + // FIXME: implement after getProperty is defined and implemented
96 + }
97 +
98 +}
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.console.Completer;
19 +import org.apache.karaf.shell.console.completer.StringsCompleter;
20 +
21 +import java.util.List;
22 +import java.util.SortedSet;
23 +
24 +import static org.onosproject.cli.cfg.ComponentConfigCommand.GET;
25 +import static org.onosproject.cli.cfg.ComponentConfigCommand.SET;
26 +
27 +/**
28 + * Component configuration command completer.
29 + */
30 +public class ComponentConfigCommandCompleter implements Completer {
31 + @Override
32 + public int complete(String buffer, int cursor, List<String> candidates) {
33 + // Delegate string completer
34 + StringsCompleter delegate = new StringsCompleter();
35 + SortedSet<String> strings = delegate.getStrings();
36 + strings.add(GET);
37 + strings.add(SET);
38 +
39 + // Now let the completer do the work for figuring out what to offer.
40 + return delegate.complete(buffer, cursor, candidates);
41 + }
42 +
43 +}
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.console.Completer;
19 +import org.apache.karaf.shell.console.completer.StringsCompleter;
20 +import org.onosproject.cfg.ComponentConfigService;
21 +import org.onosproject.cli.AbstractShellCommand;
22 +
23 +import java.util.List;
24 +import java.util.SortedSet;
25 +
26 +/**
27 + * Component name completer.
28 + */
29 +public class ComponentNameCompleter implements Completer {
30 + @Override
31 + public int complete(String buffer, int cursor, List<String> candidates) {
32 + // Delegate string completer
33 + StringsCompleter delegate = new StringsCompleter();
34 +
35 + // Fetch our service and feed it's offerings to the string completer
36 + ComponentConfigService service = AbstractShellCommand.get(ComponentConfigService.class);
37 + SortedSet<String> strings = delegate.getStrings();
38 + service.getComponentNames().forEach(strings::add);
39 +
40 + // Now let the completer do the work for figuring out what to offer.
41 + return delegate.complete(buffer, cursor, candidates);
42 + }
43 +
44 +}
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 +
17 +/**
18 + * CLI commands for managing centralized component configuration.
19 + */
20 +package org.onosproject.cli.cfg;
...\ No newline at end of file ...\ No newline at end of file
...@@ -33,33 +33,16 @@ ...@@ -33,33 +33,16 @@
33 </completers> 33 </completers>
34 </command> 34 </command>
35 35
36 - <!--
37 <command> 36 <command>
38 - <action class="org.onosproject.cli.app.ApplicationActivateCommand"/> 37 + <action class="org.onosproject.cli.cfg.ComponentConfigCommand"/>
39 <completers> 38 <completers>
40 - <ref component-id="appNameCompleter"/> 39 + <ref component-id="cfgCommandCompleter"/>
41 - <null/> 40 + <ref component-id="componentNameCompleter"/>
42 - </completers>
43 - </command>
44 -
45 - <command>
46 - <action class="org.onosproject.cli.app.ApplicationDeactivateCommand"/>
47 - <completers>
48 - <ref component-id="appNameCompleter"/>
49 <null/> 41 <null/>
50 </completers> 42 </completers>
51 </command> 43 </command>
52 44
53 <command> 45 <command>
54 - <action class="org.onosproject.cli.app.ApplicationUninstallCommand"/>
55 - <completers>
56 - <ref component-id="appNameCompleter"/>
57 - <null/>
58 - </completers>
59 - </command>
60 - -->
61 -
62 - <command>
63 <action class="org.onosproject.cli.MetricsListCommand"/> 46 <action class="org.onosproject.cli.MetricsListCommand"/>
64 </command> 47 </command>
65 48
...@@ -309,6 +292,8 @@ ...@@ -309,6 +292,8 @@
309 <bean id="appCommandCompleter" class="org.onosproject.cli.app.ApplicationCommandCompleter"/> 292 <bean id="appCommandCompleter" class="org.onosproject.cli.app.ApplicationCommandCompleter"/>
310 <bean id="appNameCompleter" class="org.onosproject.cli.app.ApplicationNameCompleter"/> 293 <bean id="appNameCompleter" class="org.onosproject.cli.app.ApplicationNameCompleter"/>
311 <bean id="appIdNameCompleter" class="org.onosproject.cli.app.ApplicationIdNameCompleter"/> 294 <bean id="appIdNameCompleter" class="org.onosproject.cli.app.ApplicationIdNameCompleter"/>
295 + <bean id="cfgCommandCompleter" class="org.onosproject.cli.cfg.ComponentConfigCommandCompleter"/>
296 + <bean id="componentNameCompleter" class="org.onosproject.cli.cfg.ComponentNameCompleter"/>
312 <bean id="nodeIdCompleter" class="org.onosproject.cli.NodeIdCompleter"/> 297 <bean id="nodeIdCompleter" class="org.onosproject.cli.NodeIdCompleter"/>
313 <bean id="deviceIdCompleter" class="org.onosproject.cli.net.DeviceIdCompleter"/> 298 <bean id="deviceIdCompleter" class="org.onosproject.cli.net.DeviceIdCompleter"/>
314 <bean id="clusterIdCompleter" class="org.onosproject.cli.net.ClusterIdCompleter"/> 299 <bean id="clusterIdCompleter" class="org.onosproject.cli.net.ClusterIdCompleter"/>
......
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.cfg;
17 +
18 +import org.onosproject.event.AbstractEvent;
19 +
20 +/**
21 + * Describes a component configuration event.
22 + */
23 +public class ComponentConfigEvent extends AbstractEvent<ComponentConfigEvent.Type, String> {
24 +
25 + private final String name;
26 + private final String value;
27 +
28 + public enum Type {
29 + /**
30 + * Signifies that a configuration property has set.
31 + */
32 + PROPERTY_SET,
33 +
34 + /**
35 + * Signifies that a configuration property has been unset.
36 + */
37 + PROPERTY_UNSET
38 + }
39 +
40 + /**
41 + * Creates an event of a given type and for the specified app and the
42 + * current time.
43 + *
44 + * @param type config property event type
45 + * @param componentName component name event subject
46 + * @param name config property name
47 + * @param value config property value
48 + */
49 + public ComponentConfigEvent(Type type, String componentName,
50 + String name, String value) {
51 + super(type, componentName);
52 + this.name = name;
53 + this.value = value;
54 + }
55 +
56 + /**
57 + * Returns the property name.
58 + *
59 + * @return property name
60 + */
61 + public String name() {
62 + return name;
63 + }
64 +
65 + /**
66 + * Returns the property value as a string.
67 + *
68 + * @return string value
69 + */
70 + public String value() {
71 + return value;
72 + }
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.cfg;
17 +
18 +import java.util.Set;
19 +
20 +/**
21 + * Service for tracking system-wide configurations for various software components.
22 + */
23 +public interface ComponentConfigService {
24 +
25 + /**
26 + * Returns names of all components that have registered their
27 + * configuration properties.
28 + *
29 + * @return set of component names
30 + */
31 + Set<String> getComponentNames();
32 +
33 + /**
34 + * Registers configuration properties for the specified component.
35 + *
36 + * @param componentClass class of configurable component
37 + */
38 + void registerProperties(Class<?> componentClass);
39 +
40 + /**
41 + * Unregisters configuration properties for the specified component.
42 + *
43 + * @param componentClass class of configurable component
44 + * @param clear true indicates any settings should be cleared
45 + */
46 + void unregisterProperties(Class<?> componentClass, boolean clear);
47 +
48 + /**
49 + * Returns configuration properties of the named components.
50 + *
51 + * @param componentName component name
52 + * @return set of configuration properties
53 + */
54 + Set<ConfigProperty> getProperties(String componentName);
55 +
56 + /**
57 + * Sets the value of the specified configuration property.
58 + *
59 + * @param componentName component name
60 + * @param name property name
61 + * @param value new property value
62 + */
63 + void setProperty(String componentName, String name, String value);
64 +
65 + /**
66 + * Clears the value of the specified configuration property thus making
67 + * the property take on its default value.
68 + *
69 + * @param componentName component name
70 + * @param name property name
71 + */
72 + void unsetProperty(String componentName, String name);
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.cfg;
17 +
18 +import org.onosproject.store.Store;
19 +
20 +/**
21 + * Service for storing and distributing system-wide configurations for various
22 + * software components.
23 + */
24 +public interface ComponentConfigStore
25 + extends Store<ComponentConfigEvent, ComponentConfigStoreDelegate> {
26 +
27 + /**
28 + * Sets the value of the specified configuration property.
29 + *
30 + * @param componentName component name
31 + * @param name property name
32 + * @param value new property value
33 + */
34 + void setProperty(String componentName, String name, String value);
35 +
36 + /**
37 + * Clears the value of the specified configuration property thus making
38 + * the property take on its default value.
39 + *
40 + * @param componentName component name
41 + * @param name property name
42 + */
43 + void unsetProperty(String componentName, String name);
44 +
45 +}
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.cfg;
17 +
18 +import org.onosproject.store.StoreDelegate;
19 +
20 +/**
21 + * Configuration property store delegate abstraction.
22 + */
23 +public interface ComponentConfigStoreDelegate extends StoreDelegate<ComponentConfigEvent> {
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.cfg;
17 +
18 +import com.google.common.base.MoreObjects;
19 +
20 +import java.util.Objects;
21 +
22 +import static com.google.common.base.Preconditions.checkNotNull;
23 +import static com.google.common.base.Preconditions.checkState;
24 +
25 +/**
26 + * Component configuration property.
27 + */
28 +public final class ConfigProperty {
29 +
30 + private final String name;
31 + private final Type type;
32 + private final String value;
33 + private final String defaultValue;
34 + private final String description;
35 + private final boolean isSet;
36 +
37 + /**
38 + * Representation of the type of property value.
39 + */
40 + public enum Type {
41 + /**
42 + * Indicates the value is a string.
43 + */
44 + STRING,
45 +
46 + /**
47 + * Indicates the value is an integer.
48 + */
49 + INTEGER,
50 +
51 + /**
52 + * Indicates the value is a long.
53 + */
54 + LONG,
55 +
56 + /**
57 + * Indicates the value is a float.
58 + */
59 + FLOAT,
60 +
61 + /**
62 + * Indicates the value is a double.
63 + */
64 + DOUBLE,
65 +
66 + /**
67 + * Indicates the value is a boolean.
68 + */
69 + BOOLEAN
70 + }
71 +
72 + /**
73 + * Creates a new configuration property with its default value.
74 + *
75 + * @param name property name
76 + * @param type value type
77 + * @param defaultValue default value as a string
78 + * @param description property description
79 + * @return newly defined property
80 + */
81 + public static ConfigProperty defineProperty(String name, Type type,
82 + String defaultValue,
83 + String description) {
84 + return new ConfigProperty(name, type, description, defaultValue, defaultValue, false);
85 + }
86 +
87 + /**
88 + * Creates a new configuration property as a copy of an existing one, but
89 + * with a new value.
90 + *
91 + * @param property property to be changed
92 + * @param newValue new value as a string
93 + * @return newly updated property
94 + */
95 + public static ConfigProperty setProperty(ConfigProperty property, String newValue) {
96 + return new ConfigProperty(property.name, property.type, property.description,
97 + property.defaultValue, newValue, true);
98 + }
99 +
100 + /**
101 + * Creates a new configuration property as a copy of an existing one, but
102 + * without a specific value, thus making it take its default value.
103 + *
104 + * @param property property to be reset
105 + * @return newly reset property
106 + */
107 + public static ConfigProperty resetProperty(ConfigProperty property) {
108 + return new ConfigProperty(property.name, property.type, property.description,
109 + property.defaultValue, property.defaultValue, false);
110 + }
111 +
112 + /**
113 + * Creates a new configuration property with its default value.
114 + *
115 + * @param name property name
116 + * @param type value type
117 + * @param defaultValue default value as a string
118 + * @param description property description
119 + * @param value property value
120 + * @param isSet indicates whether the property is set or not
121 + */
122 + private ConfigProperty(String name, Type type, String description,
123 + String defaultValue, String value, boolean isSet) {
124 + this.name = checkNotNull(name, "Property name cannot be null");
125 + this.type = checkNotNull(type, "Property type cannot be null");
126 + this.description = checkNotNull(description, "Property description cannot be null");
127 + this.defaultValue = defaultValue;
128 + this.value = value;
129 + this.isSet = isSet;
130 + }
131 +
132 + /**
133 + * Returns the property name.
134 + *
135 + * @return property name
136 + */
137 + public String name() {
138 + return name;
139 + }
140 +
141 + /**
142 + * Returns the property type.
143 + *
144 + * @return property type
145 + */
146 + public Type type() {
147 + return type;
148 + }
149 +
150 + /**
151 + * Returns the property description.
152 + *
153 + * @return string value
154 + */
155 + public String description() {
156 + return description;
157 + }
158 +
159 + /**
160 + * Returns the property default value as a string.
161 + *
162 + * @return string default value
163 + */
164 + public String defaultValue() {
165 + return defaultValue;
166 + }
167 +
168 + /**
169 + * Returns the property value as a string.
170 + *
171 + * @return string value
172 + */
173 + public String value() {
174 + return value;
175 + }
176 +
177 + /**
178 + * Indicates whether the property is set or whether it assumes its
179 + * default value.
180 + *
181 + * @return true if the property is set
182 + */
183 + public boolean isSet() {
184 + return isSet;
185 + }
186 +
187 + /**
188 + * Returns the property value as a string.
189 + *
190 + * @return string value
191 + */
192 + public String asString() {
193 + return value;
194 + }
195 +
196 + /**
197 + * Returns the property value as an integer.
198 + *
199 + * @return integer value
200 + */
201 + public int asInteger() {
202 + checkState(type == Type.INTEGER, "Value is not an integer");
203 + return Integer.parseInt(value);
204 + }
205 +
206 + /**
207 + * Returns the property value as a long.
208 + *
209 + * @return long value
210 + */
211 + public long asLong() {
212 + checkState(type == Type.INTEGER || type == Type.LONG, "Value is not a long or integer");
213 + return Long.parseLong(value);
214 + }
215 +
216 + /**
217 + * Returns the property value as a float.
218 + *
219 + * @return float value
220 + */
221 + public float asFloat() {
222 + checkState(type == Type.FLOAT, "Value is not a float");
223 + return Float.parseFloat(value);
224 + }
225 +
226 + /**
227 + * Returns the property value as a double.
228 + *
229 + * @return double value
230 + */
231 + public double asDouble() {
232 + checkState(type == Type.FLOAT || type == Type.DOUBLE, "Value is not a float or double");
233 + return Double.parseDouble(value);
234 + }
235 +
236 + /**
237 + * Returns the property value as a boolean.
238 + *
239 + * @return string value
240 + */
241 + public boolean asBoolean() {
242 + checkState(type == Type.BOOLEAN, "Value is not a boolean");
243 + return Boolean.parseBoolean(value);
244 + }
245 +
246 + @Override
247 + public int hashCode() {
248 + return Objects.hash(name);
249 + }
250 +
251 + /**
252 + * {@inheritDoc}
253 + *
254 + * Equality is considered only on the basis of property name.
255 + */
256 + @Override
257 + public boolean equals(Object obj) {
258 + if (this == obj) {
259 + return true;
260 + }
261 + if (obj instanceof ConfigProperty) {
262 + final ConfigProperty other = (ConfigProperty) obj;
263 + return Objects.equals(this.name, other.name);
264 + }
265 + return false;
266 + }
267 +
268 + @Override
269 + public String toString() {
270 + return MoreObjects.toStringHelper(this)
271 + .add("name", name)
272 + .add("type", type)
273 + .add("value", value)
274 + .add("defaultValue", defaultValue)
275 + .add("description", description)
276 + .add("isSet", isSet)
277 + .toString();
278 + }
279 +}
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 +
17 +/**
18 + * Set of abstractions for centrally managing component configurations.
19 + * Configuration properties are registered for a component resource which is
20 + * auto-generated during the build process based on information specified in
21 + * the @Property annotations. This provides an overall inventory of all
22 + * supported component configurations.
23 + */
24 +package org.onosproject.cfg;
...\ No newline at end of file ...\ No newline at end of file
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.cfg;
17 +
18 +import java.util.Set;
19 +
20 +/**
21 + * Adapter for testing against component configuration service.
22 + */
23 +public class ComponentConfigAdapter implements ComponentConfigService {
24 + @Override
25 + public Set<String> getComponentNames() {
26 + return null;
27 + }
28 +
29 + @Override
30 + public void registerProperties(Class<?> componentClass) {
31 +
32 + }
33 +
34 + @Override
35 + public void unregisterProperties(Class<?> componentClass, boolean clear) {
36 +
37 + }
38 +
39 + @Override
40 + public Set<ConfigProperty> getProperties(String componentName) {
41 + return null;
42 + }
43 +
44 + @Override
45 + public void setProperty(String componentName, String name, String value) {
46 +
47 + }
48 +
49 + @Override
50 + public void unsetProperty(String componentName, String name) {
51 +
52 + }
53 +}
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.cfg;
17 +
18 +import com.google.common.testing.EqualsTester;
19 +import org.junit.Test;
20 +import org.onosproject.cfg.ConfigProperty.Type;
21 +
22 +import static org.junit.Assert.*;
23 +import static org.onosproject.cfg.ConfigProperty.Type.*;
24 +import static org.onosproject.cfg.ConfigProperty.defineProperty;
25 +import static org.onosproject.cfg.ConfigProperty.resetProperty;
26 +import static org.onosproject.cfg.ConfigProperty.setProperty;
27 +
28 +/**
29 + * Set of tests of the configuration property class.
30 + */
31 +public class ConfigPropertyTest {
32 +
33 + @Test
34 + public void basics() {
35 + ConfigProperty p = defineProperty("foo", STRING, "bar", "Foo Prop");
36 + validate(p, "foo", STRING, "bar", "bar");
37 + p = setProperty(p, "BAR");
38 + validate(p, "foo", STRING, "BAR", "bar");
39 + p = resetProperty(p);
40 + validate(p, "foo", STRING, "bar", "bar");
41 + }
42 +
43 + @Test
44 + public void equality() {
45 + new EqualsTester()
46 + .addEqualityGroup(defineProperty("foo", STRING, "bar", "Desc"),
47 + defineProperty("foo", STRING, "goo", "Desc"))
48 + .addEqualityGroup(defineProperty("bar", STRING, "bar", "Desc"),
49 + defineProperty("bar", STRING, "goo", "Desc"))
50 + .testEquals();
51 + }
52 +
53 + private void validate(ConfigProperty p, String name, Type type, String v, String dv) {
54 + assertEquals("incorrect name", name, p.name());
55 + assertEquals("incorrect type", type, p.type());
56 + assertEquals("incorrect value", v, p.value());
57 + assertEquals("incorrect default", dv, p.defaultValue());
58 + assertEquals("incorrect description", "Foo Prop", p.description());
59 + }
60 +
61 + @Test
62 + public void asInteger() {
63 + ConfigProperty p = defineProperty("foo", INTEGER, "123", "Foo Prop");
64 + validate(p, "foo", INTEGER, "123", "123");
65 + assertEquals("incorrect value", 123, p.asInteger());
66 + assertEquals("incorrect value", 123L, p.asLong());
67 + }
68 +
69 + @Test
70 + public void asLong() {
71 + ConfigProperty p = defineProperty("foo", LONG, "123", "Foo Prop");
72 + validate(p, "foo", LONG, "123", "123");
73 + assertEquals("incorrect value", 123L, p.asLong());
74 + }
75 +
76 + @Test
77 + public void asFloat() {
78 + ConfigProperty p = defineProperty("foo", FLOAT, "123.0", "Foo Prop");
79 + validate(p, "foo", FLOAT, "123.0", "123.0");
80 + assertEquals("incorrect value", 123.0, p.asFloat(), 0.01);
81 + assertEquals("incorrect value", 123.0, p.asDouble(), 0.01);
82 + }
83 +
84 + @Test
85 + public void asDouble() {
86 + ConfigProperty p = defineProperty("foo", DOUBLE, "123.0", "Foo Prop");
87 + validate(p, "foo", DOUBLE, "123.0", "123.0");
88 + assertEquals("incorrect value", 123.0, p.asDouble(), 0.01);
89 + }
90 +
91 + @Test
92 + public void asBoolean() {
93 + ConfigProperty p = defineProperty("foo", BOOLEAN, "true", "Foo Prop");
94 + validate(p, "foo", BOOLEAN, "true", "true");
95 + assertEquals("incorrect value", true, p.asBoolean());
96 + }
97 +}
...\ No newline at end of file ...\ No newline at end of file
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.cfg.impl;
17 +
18 +import com.google.common.collect.ImmutableSet;
19 +import com.google.common.collect.Maps;
20 +import org.apache.felix.scr.annotations.Activate;
21 +import org.apache.felix.scr.annotations.Component;
22 +import org.apache.felix.scr.annotations.Deactivate;
23 +import org.apache.felix.scr.annotations.Reference;
24 +import org.apache.felix.scr.annotations.ReferenceCardinality;
25 +import org.apache.felix.scr.annotations.Service;
26 +import org.onosproject.cfg.ComponentConfigEvent;
27 +import org.onosproject.cfg.ComponentConfigService;
28 +import org.onosproject.cfg.ComponentConfigStore;
29 +import org.onosproject.cfg.ComponentConfigStoreDelegate;
30 +import org.onosproject.cfg.ConfigProperty;
31 +import org.osgi.service.cm.Configuration;
32 +import org.osgi.service.cm.ConfigurationAdmin;
33 +import org.slf4j.Logger;
34 +
35 +import java.io.IOException;
36 +import java.io.InputStream;
37 +import java.util.Dictionary;
38 +import java.util.Enumeration;
39 +import java.util.Hashtable;
40 +import java.util.Map;
41 +import java.util.Set;
42 +
43 +import static com.google.common.base.Preconditions.checkArgument;
44 +import static com.google.common.base.Preconditions.checkNotNull;
45 +import static org.slf4j.LoggerFactory.getLogger;
46 +
47 +/**
48 + * Implementation of the centralized component configuration service.
49 + */
50 +@Component(immediate = true)
51 +@Service
52 +public class ComponentConfigManager implements ComponentConfigService {
53 +
54 + private static final String COMPONENT_NULL = "Component name cannot be null";
55 + private static final String PROPERTY_NULL = "Property name cannot be null";
56 +
57 + private static final String RESOURCE_EXT = ".cfgdef";
58 +
59 + private final Logger log = getLogger(getClass());
60 +
61 + private final ComponentConfigStoreDelegate delegate = new InternalStoreDelegate();
62 +
63 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
64 + protected ComponentConfigStore store;
65 +
66 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 + protected ConfigurationAdmin cfgAdmin;
68 +
69 + // Locally maintained catalog of definitions.
70 + private final Map<String, Map<String, ConfigProperty>> properties =
71 + Maps.newConcurrentMap();
72 +
73 + @Activate
74 + public void activate() {
75 + store.setDelegate(delegate);
76 + log.info("Started");
77 + }
78 +
79 + @Deactivate
80 + public void deactivate() {
81 + store.unsetDelegate(delegate);
82 + log.info("Stopped");
83 + }
84 +
85 + @Override
86 + public Set<String> getComponentNames() {
87 + return ImmutableSet.copyOf(properties.keySet());
88 + }
89 +
90 + @Override
91 + public void registerProperties(Class<?> componentClass) {
92 + String componentName = componentClass.getName();
93 + String resourceName = componentClass.getSimpleName() + RESOURCE_EXT;
94 + try (InputStream ris = componentClass.getResourceAsStream(resourceName)) {
95 + checkArgument(ris != null, "Property definitions not found at resource %s",
96 + resourceName);
97 +
98 + // Read the definitions
99 + Set<ConfigProperty> defs = ConfigPropertyDefinitions.read(ris);
100 +
101 + // Produce a new map of the properties and register it.
102 + Map<String, ConfigProperty> map = Maps.newConcurrentMap();
103 + defs.forEach(p -> map.put(p.name(), p));
104 +
105 + properties.put(componentName, map);
106 + loadExistingValues(componentName);
107 + } catch (IOException e) {
108 + log.error("Unable to read property definitions from resource " + resourceName, e);
109 + }
110 + }
111 +
112 + @Override
113 + public void unregisterProperties(Class<?> componentClass, boolean clear) {
114 + String componentName = componentClass.getName();
115 + checkNotNull(componentName, COMPONENT_NULL);
116 + Map<String, ConfigProperty> cps = properties.remove(componentName);
117 + if (cps != null) {
118 + cps.keySet().forEach(name -> store.unsetProperty(componentName, name));
119 + }
120 +
121 + if (clear) {
122 + clearExistingValues(componentName);
123 + }
124 + }
125 +
126 + // Clears any existing values that may have been set.
127 + private void clearExistingValues(String componentName) {
128 + triggerUpdate(componentName);
129 + }
130 +
131 + @Override
132 + public Set<ConfigProperty> getProperties(String componentName) {
133 + return ImmutableSet.copyOf(properties.get(componentName).values());
134 + }
135 +
136 + @Override
137 + public void setProperty(String componentName, String name, String value) {
138 + checkNotNull(componentName, COMPONENT_NULL);
139 + checkNotNull(name, PROPERTY_NULL);
140 + store.setProperty(componentName, name, value);
141 + }
142 +
143 + @Override
144 + public void unsetProperty(String componentName, String name) {
145 + checkNotNull(componentName, COMPONENT_NULL);
146 + checkNotNull(name, PROPERTY_NULL);
147 + store.unsetProperty(componentName, name);
148 + }
149 +
150 + private class InternalStoreDelegate implements ComponentConfigStoreDelegate {
151 +
152 + @Override
153 + public void notify(ComponentConfigEvent event) {
154 + String componentName = event.subject();
155 + String name = event.name();
156 + String value = event.value();
157 +
158 + switch (event.type()) {
159 + case PROPERTY_SET:
160 + set(componentName, name, value);
161 + break;
162 + case PROPERTY_UNSET:
163 + reset(componentName, name);
164 + break;
165 + default:
166 + break;
167 + }
168 + }
169 + }
170 +
171 + // Locates the property in the component map and replaces it with an
172 + // updated copy.
173 + private void set(String componentName, String name, String value) {
174 + Map<String, ConfigProperty> map = properties.get(componentName);
175 + if (map != null) {
176 + ConfigProperty prop = map.get(name);
177 + if (prop != null) {
178 + map.put(name, ConfigProperty.setProperty(prop, value));
179 + triggerUpdate(componentName);
180 + return;
181 + }
182 + }
183 + log.warn("Unable to set non-existent property {} for component {}",
184 + name, componentName);
185 + }
186 +
187 + // Locates the property in the component map and replaces it with an
188 + // reset copy.
189 + private void reset(String componentName, String name) {
190 + Map<String, ConfigProperty> map = properties.get(componentName);
191 + if (map != null) {
192 + ConfigProperty prop = map.get(name);
193 + if (prop != null) {
194 + map.put(name, ConfigProperty.resetProperty(prop));
195 + triggerUpdate(componentName);
196 + return;
197 + }
198 + }
199 + log.warn("Unable to reset non-existent property {} for component {}",
200 + name, componentName);
201 + }
202 +
203 + // Loads existing property values that may have been set.
204 + private void loadExistingValues(String componentName) {
205 + // FIXME: implement this by talking to the config admin.
206 + try {
207 + Configuration cfg = cfgAdmin.getConfiguration(componentName);
208 + Map<String, ConfigProperty> map = properties.get(componentName);
209 + Dictionary<String, Object> props = cfg.getProperties();
210 + if (props != null) {
211 + Enumeration<String> it = props.keys();
212 + while (it.hasMoreElements()) {
213 + String name = it.nextElement();
214 + ConfigProperty p = map.get(name);
215 + if (p != null) {
216 + map.put(name, ConfigProperty.setProperty(p, (String) props.get(name)));
217 + }
218 + }
219 + }
220 + } catch (IOException e) {
221 + log.error("Unable to get configuration for " + componentName, e);
222 + }
223 +
224 + }
225 +
226 + // FIXME: This should be a slightly deferred execution to allow changing
227 + // values just once per component when a number of updates arrive shortly
228 + // after each other.
229 + private void triggerUpdate(String componentName) {
230 + try {
231 + Configuration cfg = cfgAdmin.getConfiguration(componentName);
232 + Map<String, ConfigProperty> map = properties.get(componentName);
233 + Dictionary<String, Object> props = new Hashtable<>();
234 + map.values().forEach(p -> props.put(p.name(), p.value()));
235 + cfg.update(props);
236 + } catch (IOException e) {
237 + log.warn("Unable to update configuration for " + componentName, e);
238 + }
239 + }
240 +
241 +}
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.cfg.impl;
17 +
18 +import com.google.common.collect.ImmutableSet;
19 +import org.onosproject.cfg.ConfigProperty;
20 +import org.onosproject.cfg.ConfigProperty.Type;
21 +
22 +import java.io.BufferedReader;
23 +import java.io.IOException;
24 +import java.io.InputStream;
25 +import java.io.InputStreamReader;
26 +import java.io.OutputStream;
27 +import java.io.OutputStreamWriter;
28 +import java.io.PrintWriter;
29 +import java.util.Set;
30 +
31 +import static org.onosproject.cfg.ConfigProperty.defineProperty;
32 +
33 +/**
34 + * Utility for writing and reading configuration property definition file.
35 + */
36 +public final class ConfigPropertyDefinitions {
37 +
38 + private static final String FMT = "%s|%s|%s|%s\n";
39 + private static final String SEP = "\\|";
40 + private static final String COMMENT = "#";
41 +
42 + private ConfigPropertyDefinitions() {
43 + }
44 +
45 + /**
46 + * Writes the specified set of property definitions into the given output
47 + * stream.
48 + *
49 + * @param stream output stream
50 + * @param props properties whose definitions are to be written
51 + * @throws java.io.IOException if unable to write the stream
52 + */
53 + public static void write(OutputStream stream, Set<ConfigProperty> props) throws IOException {
54 + try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(stream))) {
55 + props.forEach(p -> pw.format(FMT, p.name(), p.type(), p.description(), p.defaultValue()));
56 + }
57 + }
58 +
59 + /**
60 + * Reads the specified input stream and creates from its contents a
61 + * set of property definitions.
62 + *
63 + * @param stream input stream
64 + * @return properties whose definitions are contained in the stream
65 + * @throws java.io.IOException if unable to read the stream
66 + */
67 + public static Set<ConfigProperty> read(InputStream stream) throws IOException {
68 + ImmutableSet.Builder<ConfigProperty> builder = ImmutableSet.builder();
69 + try (BufferedReader br = new BufferedReader(new InputStreamReader(stream))) {
70 + String line;
71 + while ((line = br.readLine()) != null) {
72 + if (!line.isEmpty() && !line.startsWith(COMMENT)) {
73 + String[] f = line.split(SEP, 4);
74 + builder.add(defineProperty(f[0], Type.valueOf(f[1]), f[2], f[3]));
75 + }
76 + }
77 + }
78 + return builder.build();
79 + }
80 +
81 +}
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 +
17 +/**
18 + * Subsystem for central management of component configurations.
19 + */
20 +package org.onosproject.cfg.impl;
...\ No newline at end of file ...\ No newline at end of file
...@@ -40,6 +40,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; ...@@ -40,6 +40,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
40 import org.apache.felix.scr.annotations.Service; 40 import org.apache.felix.scr.annotations.Service;
41 import org.onlab.util.AbstractAccumulator; 41 import org.onlab.util.AbstractAccumulator;
42 import org.onlab.util.Accumulator; 42 import org.onlab.util.Accumulator;
43 +import org.onosproject.cfg.ComponentConfigService;
43 import org.onosproject.event.Event; 44 import org.onosproject.event.Event;
44 import org.onosproject.net.device.DeviceEvent; 45 import org.onosproject.net.device.DeviceEvent;
45 import org.onosproject.net.device.DeviceListener; 46 import org.onosproject.net.device.DeviceListener;
...@@ -59,13 +60,14 @@ import org.slf4j.Logger; ...@@ -59,13 +60,14 @@ import org.slf4j.Logger;
59 import com.google.common.collect.ImmutableList; 60 import com.google.common.collect.ImmutableList;
60 61
61 /** 62 /**
62 - * Default implementation of a network topology provider that feeds off device 63 + * Default implementation of a network topology provider that feeds off
63 - * and link subsystem events to trigger assembly and computation of new topology 64 + * device and link subsystem events to trigger assembly and computation of
64 - * snapshots. 65 + * new topology snapshots.
65 */ 66 */
66 @Component(immediate = true) 67 @Component(immediate = true)
67 @Service 68 @Service
68 -public class DefaultTopologyProvider extends AbstractProvider implements TopologyProvider { 69 +public class DefaultTopologyProvider extends AbstractProvider
70 + implements TopologyProvider {
69 71
70 private static final int MAX_THREADS = 8; 72 private static final int MAX_THREADS = 8;
71 private static final int DEFAULT_MAX_EVENTS = 1000; 73 private static final int DEFAULT_MAX_EVENTS = 1000;
...@@ -73,8 +75,7 @@ public class DefaultTopologyProvider extends AbstractProvider implements Topolog ...@@ -73,8 +75,7 @@ public class DefaultTopologyProvider extends AbstractProvider implements Topolog
73 private static final int DEFAULT_MAX_BATCH_MS = 50; 75 private static final int DEFAULT_MAX_BATCH_MS = 50;
74 76
75 // FIXME: Replace with a system-wide timer instance; 77 // FIXME: Replace with a system-wide timer instance;
76 - // TODO: Convert to use HashedWheelTimer or produce a variant of that; then 78 + // TODO: Convert to use HashedWheelTimer or produce a variant of that; then decide which we want to adopt
77 - // decide which we want to adopt
78 private static final Timer TIMER = new Timer("onos-topo-event-batching"); 79 private static final Timer TIMER = new Timer("onos-topo-event-batching");
79 80
80 @Property(name = "maxEvents", intValue = DEFAULT_MAX_EVENTS, 81 @Property(name = "maxEvents", intValue = DEFAULT_MAX_EVENTS,
...@@ -100,6 +101,9 @@ public class DefaultTopologyProvider extends AbstractProvider implements Topolog ...@@ -100,6 +101,9 @@ public class DefaultTopologyProvider extends AbstractProvider implements Topolog
100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 protected LinkService linkService; 102 protected LinkService linkService;
102 103
104 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 + protected ComponentConfigService cfgService;
106 +
103 private volatile boolean isStarted = false; 107 private volatile boolean isStarted = false;
104 108
105 private TopologyProviderService providerService; 109 private TopologyProviderService providerService;
...@@ -118,8 +122,8 @@ public class DefaultTopologyProvider extends AbstractProvider implements Topolog ...@@ -118,8 +122,8 @@ public class DefaultTopologyProvider extends AbstractProvider implements Topolog
118 122
119 @Activate 123 @Activate
120 public synchronized void activate(ComponentContext context) { 124 public synchronized void activate(ComponentContext context) {
121 - executor = newFixedThreadPool(MAX_THREADS, 125 + cfgService.registerProperties(DefaultTopologyProvider.class);
122 - groupedThreads("onos/topo", "build-%d")); 126 + executor = newFixedThreadPool(MAX_THREADS, groupedThreads("onos/topo", "build-%d"));
123 accumulator = new TopologyChangeAccumulator(); 127 accumulator = new TopologyChangeAccumulator();
124 logConfig("Configured"); 128 logConfig("Configured");
125 129
...@@ -136,6 +140,7 @@ public class DefaultTopologyProvider extends AbstractProvider implements Topolog ...@@ -136,6 +140,7 @@ public class DefaultTopologyProvider extends AbstractProvider implements Topolog
136 140
137 @Deactivate 141 @Deactivate
138 public synchronized void deactivate(ComponentContext context) { 142 public synchronized void deactivate(ComponentContext context) {
143 + cfgService.unregisterProperties(DefaultTopologyProvider.class, false);
139 isStarted = false; 144 isStarted = false;
140 145
141 deviceService.removeListener(deviceListener); 146 deviceService.removeListener(deviceListener);
...@@ -175,23 +180,21 @@ public class DefaultTopologyProvider extends AbstractProvider implements Topolog ...@@ -175,23 +180,21 @@ public class DefaultTopologyProvider extends AbstractProvider implements Topolog
175 newMaxIdleMs = DEFAULT_MAX_IDLE_MS; 180 newMaxIdleMs = DEFAULT_MAX_IDLE_MS;
176 } 181 }
177 182
178 - if ((newMaxEvents != maxEvents) || (newMaxBatchMs != maxBatchMs) 183 + if (newMaxEvents != maxEvents || newMaxBatchMs != maxBatchMs || newMaxIdleMs != maxIdleMs) {
179 - || (newMaxIdleMs != maxIdleMs)) {
180 maxEvents = newMaxEvents; 184 maxEvents = newMaxEvents;
181 maxBatchMs = newMaxBatchMs; 185 maxBatchMs = newMaxBatchMs;
182 maxIdleMs = newMaxIdleMs; 186 maxIdleMs = newMaxIdleMs;
183 - accumulator = maxEvents > 1 ? new TopologyChangeAccumulator() 187 + accumulator = maxEvents > 1 ? new TopologyChangeAccumulator() : null;
184 - : null;
185 logConfig("Reconfigured"); 188 logConfig("Reconfigured");
186 } 189 }
187 } 190 }
188 191
189 private void logConfig(String prefix) { 192 private void logConfig(String prefix) {
190 - log.info( 193 + log.info("{} with maxEvents = {}; maxBatchMs = {}; maxIdleMs = {}; accumulator={}",
191 - "{} with maxEvents = {}; maxBatchMs = {}; maxIdleMs = {}; accumulator={}",
192 prefix, maxEvents, maxBatchMs, maxIdleMs, accumulator != null); 194 prefix, maxEvents, maxBatchMs, maxIdleMs, accumulator != null);
193 } 195 }
194 196
197 +
195 @Override 198 @Override
196 public void triggerRecompute() { 199 public void triggerRecompute() {
197 triggerTopologyBuild(Collections.<Event>emptyList()); 200 triggerTopologyBuild(Collections.<Event>emptyList());
...@@ -201,8 +204,7 @@ public class DefaultTopologyProvider extends AbstractProvider implements Topolog ...@@ -201,8 +204,7 @@ public class DefaultTopologyProvider extends AbstractProvider implements Topolog
201 * Triggers assembly of topology data citing the specified events as the 204 * Triggers assembly of topology data citing the specified events as the
202 * reason. 205 * reason.
203 * 206 *
204 - * @param reasons 207 + * @param reasons events which triggered the topology change
205 - * events which triggered the topology change
206 */ 208 */
207 private synchronized void triggerTopologyBuild(List<Event> reasons) { 209 private synchronized void triggerTopologyBuild(List<Event> reasons) {
208 if (executor != null) { 210 if (executor != null) {
...@@ -236,8 +238,8 @@ public class DefaultTopologyProvider extends AbstractProvider implements Topolog ...@@ -236,8 +238,8 @@ public class DefaultTopologyProvider extends AbstractProvider implements Topolog
236 @Override 238 @Override
237 public void event(DeviceEvent event) { 239 public void event(DeviceEvent event) {
238 DeviceEvent.Type type = event.type(); 240 DeviceEvent.Type type = event.type();
239 - if ((type == DEVICE_ADDED) || (type == DEVICE_REMOVED) || 241 + if (type == DEVICE_ADDED || type == DEVICE_REMOVED ||
240 - (type == DEVICE_AVAILABILITY_CHANGED)) { 242 + type == DEVICE_AVAILABILITY_CHANGED) {
241 processEvent(event); 243 processEvent(event);
242 } 244 }
243 } 245 }
...@@ -276,8 +278,7 @@ public class DefaultTopologyProvider extends AbstractProvider implements Topolog ...@@ -276,8 +278,7 @@ public class DefaultTopologyProvider extends AbstractProvider implements Topolog
276 try { 278 try {
277 buildTopology(reasons); 279 buildTopology(reasons);
278 } catch (Exception e) { 280 } catch (Exception e) {
279 - log.warn("Unable to compute topology due to: {}", 281 + log.warn("Unable to compute topology due to: {}", e.getMessage());
280 - e.getMessage());
281 log.debug("Unable to compute topology", e); 282 log.debug("Unable to compute topology", e);
282 } 283 }
283 } 284 }
......
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 +
17 +# This is for temporary provision for testing purposes and will be auto-generated.
18 +maxEvents|INTEGER|1000|Maximum number of events to accumulate
19 +maxIdleMs|INTEGER|10|Maximum number of millis between events
20 +maxBatchMs|INTEGER|50|Maximum number of millis for whole batch
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.cfg.impl;
17 +
18 +import com.google.common.collect.ImmutableSet;
19 +import org.junit.Test;
20 +import org.onosproject.cfg.ConfigProperty;
21 +
22 +import java.io.ByteArrayInputStream;
23 +import java.io.ByteArrayOutputStream;
24 +import java.io.IOException;
25 +import java.util.Set;
26 +
27 +import static org.junit.Assert.*;
28 +import static org.onosproject.cfg.ConfigProperty.Type.STRING;
29 +import static org.onosproject.cfg.ConfigProperty.defineProperty;
30 +import static org.onosproject.cfg.impl.ConfigPropertyDefinitions.read;
31 +import static org.onosproject.cfg.impl.ConfigPropertyDefinitions.write;
32 +
33 +/**
34 + * Tests of the config property definitions utility.
35 + */
36 +public class ConfigPropertyDefinitionsTest {
37 +
38 + @Test
39 + public void basics() throws IOException {
40 + Set<ConfigProperty> original = ImmutableSet
41 + .of(defineProperty("foo", STRING, "dingo", "FOO"),
42 + defineProperty("bar", STRING, "bat", "BAR"));
43 + ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
44 + write(out, original);
45 + Set<ConfigProperty> read = read(new ByteArrayInputStream(out.toByteArray()));
46 + assertEquals("incorrect defs", original, read);
47 + }
48 +
49 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableSet; ...@@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableSet;
20 import org.junit.After; 20 import org.junit.After;
21 import org.junit.Before; 21 import org.junit.Before;
22 import org.junit.Test; 22 import org.junit.Test;
23 +import org.onosproject.cfg.ComponentConfigAdapter;
23 import org.onosproject.event.Event; 24 import org.onosproject.event.Event;
24 import org.onosproject.event.impl.TestEventDispatcher; 25 import org.onosproject.event.impl.TestEventDispatcher;
25 import org.onosproject.net.Device; 26 import org.onosproject.net.Device;
...@@ -67,6 +68,7 @@ public class DefaultTopologyProviderTest { ...@@ -67,6 +68,7 @@ public class DefaultTopologyProviderTest {
67 provider.deviceService = deviceService; 68 provider.deviceService = deviceService;
68 provider.linkService = linkService; 69 provider.linkService = linkService;
69 provider.providerRegistry = topologyService; 70 provider.providerRegistry = topologyService;
71 + provider.cfgService = new ComponentConfigAdapter();
70 provider.activate(null); 72 provider.activate(null);
71 } 73 }
72 74
...@@ -76,6 +78,7 @@ public class DefaultTopologyProviderTest { ...@@ -76,6 +78,7 @@ public class DefaultTopologyProviderTest {
76 provider.providerRegistry = null; 78 provider.providerRegistry = null;
77 provider.deviceService = null; 79 provider.deviceService = null;
78 provider.linkService = null; 80 provider.linkService = null;
81 + provider.cfgService = null;
79 } 82 }
80 83
81 private void validateSubmission() { 84 private void validateSubmission() {
......
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.store.cfg;
17 +
18 +import org.apache.felix.scr.annotations.Activate;
19 +import org.apache.felix.scr.annotations.Component;
20 +import org.apache.felix.scr.annotations.Deactivate;
21 +import org.apache.felix.scr.annotations.Reference;
22 +import org.apache.felix.scr.annotations.ReferenceCardinality;
23 +import org.apache.felix.scr.annotations.Service;
24 +import org.onlab.util.KryoNamespace;
25 +import org.onosproject.cfg.ComponentConfigEvent;
26 +import org.onosproject.cfg.ComponentConfigStore;
27 +import org.onosproject.cfg.ComponentConfigStoreDelegate;
28 +import org.onosproject.cluster.ClusterService;
29 +import org.onosproject.store.AbstractStore;
30 +import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
31 +import org.onosproject.store.ecmap.EventuallyConsistentMap;
32 +import org.onosproject.store.ecmap.EventuallyConsistentMapEvent;
33 +import org.onosproject.store.ecmap.EventuallyConsistentMapImpl;
34 +import org.onosproject.store.ecmap.EventuallyConsistentMapListener;
35 +import org.onosproject.store.impl.WallclockClockManager;
36 +import org.onosproject.store.serializers.KryoNamespaces;
37 +import org.slf4j.Logger;
38 +
39 +import static org.onosproject.cfg.ComponentConfigEvent.Type.PROPERTY_SET;
40 +import static org.onosproject.cfg.ComponentConfigEvent.Type.PROPERTY_UNSET;
41 +import static org.onosproject.store.ecmap.EventuallyConsistentMapEvent.Type.PUT;
42 +import static org.onosproject.store.ecmap.EventuallyConsistentMapEvent.Type.REMOVE;
43 +import static org.slf4j.LoggerFactory.getLogger;
44 +
45 +/**
46 + * Manages inventory of component configurations in a distributed data store
47 + * that uses optimistic replication and gossip based anti-entropy techniques.
48 + */
49 +@Component(immediate = true)
50 +@Service
51 +public class GossipComponentConfigStore
52 + extends AbstractStore<ComponentConfigEvent, ComponentConfigStoreDelegate>
53 + implements ComponentConfigStore {
54 +
55 + private static final String SEP = "#";
56 +
57 + private final Logger log = getLogger(getClass());
58 +
59 + private EventuallyConsistentMap<String, String> properties;
60 +
61 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
62 + protected ClusterCommunicationService clusterCommunicator;
63 +
64 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
65 + protected ClusterService clusterService;
66 +
67 + @Activate
68 + public void activate() {
69 + KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
70 + .register(KryoNamespaces.API);
71 +
72 + properties = new EventuallyConsistentMapImpl<>("cfg", clusterService,
73 + clusterCommunicator,
74 + serializer,
75 + new WallclockClockManager<>());
76 + properties.addListener(new InternalPropertiesListener());
77 + log.info("Started");
78 + }
79 +
80 + @Deactivate
81 + public void deactivate() {
82 + log.info("Stopped");
83 + }
84 +
85 + @Override
86 + public void setProperty(String componentName, String name, String value) {
87 + properties.put(key(componentName, name), value);
88 +
89 + }
90 +
91 + @Override
92 + public void unsetProperty(String componentName, String name) {
93 + properties.remove(key(componentName, name));
94 + }
95 +
96 + /**
97 + * Listener to component configuration properties distributed map changes.
98 + */
99 + private final class InternalPropertiesListener
100 + implements EventuallyConsistentMapListener<String, String> {
101 +
102 + @Override
103 + public void event(EventuallyConsistentMapEvent<String, String> event) {
104 + String[] keys = event.key().split(SEP);
105 + String value = event.value();
106 + if (event.type() == PUT) {
107 + delegate.notify(new ComponentConfigEvent(PROPERTY_SET, keys[0], keys[1], value));
108 + } else if (event.type() == REMOVE) {
109 + delegate.notify(new ComponentConfigEvent(PROPERTY_UNSET, keys[0], keys[1], null));
110 + }
111 + }
112 + }
113 +
114 + // Generates a key from component name and property name.
115 + private String key(String componentName, String name) {
116 + return componentName + SEP + name;
117 + }
118 +
119 +}
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 +
17 +/**
18 + * Implementation of distributed component configuration store.
19 + */
20 +package org.onosproject.store.cfg;
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.store.trivial.impl;
17 +
18 +import org.apache.felix.scr.annotations.Activate;
19 +import org.apache.felix.scr.annotations.Component;
20 +import org.apache.felix.scr.annotations.Deactivate;
21 +import org.apache.felix.scr.annotations.Service;
22 +import org.onosproject.cfg.ComponentConfigEvent;
23 +import org.onosproject.cfg.ComponentConfigStore;
24 +import org.onosproject.cfg.ComponentConfigStoreDelegate;
25 +import org.onosproject.store.AbstractStore;
26 +import org.slf4j.Logger;
27 +
28 +import static org.onosproject.cfg.ComponentConfigEvent.Type.PROPERTY_SET;
29 +import static org.onosproject.cfg.ComponentConfigEvent.Type.PROPERTY_UNSET;
30 +import static org.slf4j.LoggerFactory.getLogger;
31 +
32 +/**
33 + * Manages inventory of component configuration properties.
34 + */
35 +@Component(immediate = true)
36 +@Service
37 +public class SimpleComponentConfigStore
38 + extends AbstractStore<ComponentConfigEvent, ComponentConfigStoreDelegate>
39 + implements ComponentConfigStore {
40 +
41 + private final Logger log = getLogger(getClass());
42 +
43 + @Activate
44 + public void activate() {
45 + log.info("Started");
46 + }
47 +
48 + @Deactivate
49 + public void deactivate() {
50 + log.info("Stopped");
51 + }
52 +
53 + @Override
54 + public void setProperty(String componentName, String name, String value) {
55 + delegate.notify(new ComponentConfigEvent(PROPERTY_SET, componentName, name, value));
56 + }
57 +
58 + @Override
59 + public void unsetProperty(String componentName, String name) {
60 + delegate.notify(new ComponentConfigEvent(PROPERTY_UNSET, componentName, name, null));
61 + }
62 +}
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
61 <group> 61 <group>
62 <title>Core Subsystems</title> 62 <title>Core Subsystems</title>
63 <packages> 63 <packages>
64 - org.onosproject.impl:org.onosproject.core.impl:org.onosproject.cluster.impl:org.onosproject.net.device.impl:org.onosproject.net.link.impl:org.onosproject.net.host.impl:org.onosproject.net.topology.impl:org.onosproject.net.packet.impl:org.onosproject.net.flow.impl:org.onosproject.net.*.impl:org.onosproject.event.impl:org.onosproject.net.intent.impl*:org.onosproject.net.proxyarp.impl:org.onosproject.mastership.impl:org.onosproject.net.resource.impl:org.onosproject.json:org.onosproject.json.*:org.onosproject.provider.host.impl:org.onosproject.provider.lldp.impl:org.onosproject.net.statistic.impl:org.onosproject.app.impl:org.onosproject.common.*:org.onosproject.net.group.impl 64 + org.onosproject.impl:org.onosproject.core.impl:org.onosproject.cluster.impl:org.onosproject.net.device.impl:org.onosproject.net.link.impl:org.onosproject.net.host.impl:org.onosproject.net.topology.impl:org.onosproject.net.packet.impl:org.onosproject.net.flow.impl:org.onosproject.net.*.impl:org.onosproject.event.impl:org.onosproject.net.intent.impl*:org.onosproject.net.proxyarp.impl:org.onosproject.mastership.impl:org.onosproject.net.resource.impl:org.onosproject.json:org.onosproject.json.*:org.onosproject.provider.host.impl:org.onosproject.provider.lldp.impl:org.onosproject.net.statistic.impl:org.onosproject.app.impl:org.onosproject.common.*:org.onosproject.net.group.impl:org.onosproject.cfg.impl
65 </packages> 65 </packages>
66 </group> 66 </group>
67 <group> 67 <group>
......