Adding support for configurations added after the Net Config Loader has loaded.
Change-Id: I611f3b8f36805e2854485b694edffc8d93581c7e
Showing
1 changed file
with
112 additions
and
33 deletions
... | @@ -17,16 +17,22 @@ package org.onosproject.incubator.net.config.impl; | ... | @@ -17,16 +17,22 @@ package org.onosproject.incubator.net.config.impl; |
17 | 17 | ||
18 | import com.fasterxml.jackson.databind.ObjectMapper; | 18 | import com.fasterxml.jackson.databind.ObjectMapper; |
19 | import com.fasterxml.jackson.databind.node.ObjectNode; | 19 | import com.fasterxml.jackson.databind.node.ObjectNode; |
20 | +import com.google.common.collect.Maps; | ||
20 | import org.apache.felix.scr.annotations.Activate; | 21 | import org.apache.felix.scr.annotations.Activate; |
21 | import org.apache.felix.scr.annotations.Component; | 22 | import org.apache.felix.scr.annotations.Component; |
23 | +import org.apache.felix.scr.annotations.Deactivate; | ||
22 | import org.apache.felix.scr.annotations.Reference; | 24 | import org.apache.felix.scr.annotations.Reference; |
23 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 25 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
26 | +import org.onosproject.incubator.net.config.NetworkConfigEvent; | ||
27 | +import org.onosproject.incubator.net.config.NetworkConfigListener; | ||
24 | import org.onosproject.incubator.net.config.NetworkConfigService; | 28 | import org.onosproject.incubator.net.config.NetworkConfigService; |
25 | -import org.onosproject.incubator.net.config.SubjectFactory; | ||
26 | import org.slf4j.Logger; | 29 | import org.slf4j.Logger; |
27 | import org.slf4j.LoggerFactory; | 30 | import org.slf4j.LoggerFactory; |
28 | 31 | ||
29 | import java.io.File; | 32 | import java.io.File; |
33 | +import java.util.Iterator; | ||
34 | +import java.util.Map; | ||
35 | +import java.util.Objects; | ||
30 | 36 | ||
31 | /** | 37 | /** |
32 | * Component for loading the initial network configuration. | 38 | * Component for loading the initial network configuration. |
... | @@ -43,59 +49,132 @@ public class NetworkConfigLoader { | ... | @@ -43,59 +49,132 @@ public class NetworkConfigLoader { |
43 | 49 | ||
44 | // FIXME: Add mutual exclusion to make sure this happens only once per startup. | 50 | // FIXME: Add mutual exclusion to make sure this happens only once per startup. |
45 | 51 | ||
46 | - // TODO: add a field to track the collection of pending JSONS | 52 | + private Map<InnerConfigPosition, ObjectNode> jsons = Maps.newHashMap(); |
53 | + | ||
54 | + private final NetworkConfigListener configListener = new InnerConfigListener(); | ||
55 | + | ||
56 | + ObjectNode root; | ||
47 | 57 | ||
48 | @Activate | 58 | @Activate |
49 | public void activate() { | 59 | public void activate() { |
50 | - // Add listener to net config events | 60 | + //TODO Maybe this should be at the bottom to avoid a potential race |
61 | + networkConfigService.addListener(configListener); | ||
51 | try { | 62 | try { |
52 | if (CFG_FILE.exists()) { | 63 | if (CFG_FILE.exists()) { |
53 | - ObjectNode root = (ObjectNode) new ObjectMapper().readTree(CFG_FILE); | 64 | + root = (ObjectNode) new ObjectMapper().readTree(CFG_FILE); |
54 | - // Parse this JSON structure and accumulate a collection of all leaf config JSONs | 65 | + |
66 | + populateConfigurations(); | ||
55 | 67 | ||
56 | - // Perform initial iteration over all leaf configs and attempt to apply them, | 68 | + applyConfigurations(); |
57 | - // but do this only if they are valid. | ||
58 | -// networkConfigService.getConfigClass("foo"); | ||
59 | 69 | ||
60 | - // This code can be used for building the collection of jsons | ||
61 | - root.fieldNames().forEachRemaining(sk -> | ||
62 | - consumeJson(networkConfigService, (ObjectNode) root.path(sk), | ||
63 | - networkConfigService.getSubjectFactory(sk))); | ||
64 | log.info("Loaded initial network configuration from {}", CFG_FILE); | 70 | log.info("Loaded initial network configuration from {}", CFG_FILE); |
65 | } | 71 | } |
66 | } catch (Exception e) { | 72 | } catch (Exception e) { |
67 | log.warn("Unable to load initial network configuration from {}", | 73 | log.warn("Unable to load initial network configuration from {}", |
68 | - CFG_FILE, e); | 74 | + CFG_FILE, e); |
69 | } | 75 | } |
70 | } | 76 | } |
71 | 77 | ||
78 | + @Deactivate | ||
79 | + public void deactivate() { | ||
80 | + networkConfigService.removeListener(configListener); | ||
81 | + } | ||
82 | + // sweep through pending config jsons and try to add them | ||
72 | 83 | ||
73 | - // TODO: add deactivate which will remove listener | 84 | + /** |
85 | + * Inner class that allows for handling of newly added NetConfig types. | ||
86 | + */ | ||
87 | + private final class InnerConfigListener implements NetworkConfigListener { | ||
88 | + | ||
89 | + @Override | ||
90 | + public void event(NetworkConfigEvent event) { | ||
91 | + //TODO should this be done for other types of NetworkConfigEvents? | ||
92 | + if (event.type() == NetworkConfigEvent.Type.CONFIG_REGISTERED || | ||
93 | + event.type() == NetworkConfigEvent.Type.CONFIG_ADDED) { | ||
94 | + applyConfigurations(); | ||
95 | + } | ||
74 | 96 | ||
75 | - // TODO: implement event listener and as each config is registered, | 97 | + } |
76 | - // sweep through pending config jsons and try to add them | 98 | + } |
77 | 99 | ||
78 | /** | 100 | /** |
79 | - * Consumes configuration JSON for the specified subject factory. | 101 | + * Inner class that allows for tracking of JSON class configurations. |
80 | - * | ||
81 | - * @param service network configuration service | ||
82 | - * @param classNode subject class JSON node | ||
83 | - * @param subjectFactory subject factory | ||
84 | */ | 102 | */ |
85 | - static void consumeJson(NetworkConfigService service, ObjectNode classNode, | 103 | + private final class InnerConfigPosition { |
86 | - SubjectFactory subjectFactory) { | 104 | + private String subjectKey, subject, classKey; |
87 | - classNode.fieldNames().forEachRemaining(s -> | 105 | + |
88 | - consumeSubjectJson(service, (ObjectNode) classNode.path(s), | 106 | + private String getSubjectKey() { |
89 | - subjectFactory.createSubject(s), | 107 | + return subjectKey; |
90 | - subjectFactory.subjectKey())); | 108 | + } |
109 | + | ||
110 | + private String getSubject() { | ||
111 | + return subject; | ||
112 | + } | ||
113 | + | ||
114 | + private String getClassKey() { | ||
115 | + return classKey; | ||
116 | + } | ||
117 | + | ||
118 | + private InnerConfigPosition(String subjectKey, String subject, String classKey) { | ||
119 | + this.subjectKey = subjectKey; | ||
120 | + this.subject = subject; | ||
121 | + this.classKey = classKey; | ||
122 | + } | ||
123 | + | ||
124 | + @Override | ||
125 | + public boolean equals(Object obj) { | ||
126 | + if (this == obj) { | ||
127 | + return true; | ||
128 | + } | ||
129 | + if (obj instanceof InnerConfigPosition) { | ||
130 | + final InnerConfigPosition that = (InnerConfigPosition) obj; | ||
131 | + return Objects.equals(this.subjectKey, that.subjectKey) && Objects.equals(this.subject, that.subject) | ||
132 | + && Objects.equals(this.classKey, that.classKey); | ||
133 | + } | ||
134 | + return false; | ||
135 | + } | ||
136 | + | ||
137 | + @Override | ||
138 | + public int hashCode() { | ||
139 | + return Objects.hash(subjectKey, subject, classKey); | ||
140 | + } | ||
141 | + } | ||
142 | + | ||
143 | + private void saveJson(String sk, ObjectNode node) { | ||
144 | + node.fieldNames().forEachRemaining(s -> | ||
145 | + saveSubjectJson(sk, s, (ObjectNode) node.path(s))); | ||
91 | } | 146 | } |
92 | 147 | ||
93 | - private static void consumeSubjectJson(NetworkConfigService service, | 148 | + private void saveSubjectJson(String sk, |
94 | - ObjectNode subjectNode, Object subject, String subjectKey) { | 149 | + String s, ObjectNode node) { |
95 | - subjectNode.fieldNames().forEachRemaining(c -> | 150 | + node.fieldNames().forEachRemaining(c -> |
96 | - service.applyConfig(subject, | 151 | + this.jsons.put(new InnerConfigPosition(sk, s, c), (ObjectNode) node.path(c))); |
97 | - service.getConfigClass(subjectKey, c), | 152 | + } |
98 | - (ObjectNode) subjectNode.path(c))); | 153 | + |
154 | + private void populateConfigurations() { | ||
155 | + root.fieldNames().forEachRemaining(sk -> | ||
156 | + saveJson(sk, (ObjectNode) root.path(sk))); | ||
157 | + | ||
158 | + } | ||
159 | + | ||
160 | + protected void applyConfigurations() { | ||
161 | + Iterator<Map.Entry<InnerConfigPosition, ObjectNode>> iter = jsons.entrySet().iterator(); | ||
162 | + Map.Entry<InnerConfigPosition, ObjectNode> entry; | ||
163 | + while (iter.hasNext()) { | ||
164 | + entry = iter.next(); | ||
165 | + if (networkConfigService.getConfigClass(networkConfigService.getSubjectFactory(entry.getKey(). | ||
166 | + getSubjectKey()).subjectKey(), entry.getKey().getSubject()) != null) { | ||
167 | + networkConfigService.applyConfig(networkConfigService.getSubjectFactory( | ||
168 | + entry.getKey().getSubjectKey()).createSubject(entry.getKey().getSubject()), | ||
169 | + networkConfigService.getConfigClass(networkConfigService.getSubjectFactory(entry.getKey(). | ||
170 | + getSubjectKey()).subjectKey(), entry.getKey().getClassKey()), | ||
171 | + (ObjectNode) root.path(entry.getKey().getSubjectKey()). | ||
172 | + path(entry.getKey().getSubject()). | ||
173 | + path(entry.getKey().getClassKey())); | ||
174 | + jsons.remove(entry.getKey()); | ||
175 | + } | ||
176 | + | ||
177 | + } | ||
99 | } | 178 | } |
100 | 179 | ||
101 | } | 180 | } | ... | ... |
-
Please register or login to post a comment