blob: 6c569d0c8e6b6aeffe5735963fc7cdd889a54d63 [file] [log] [blame]
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.incubator.net.config.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Maps;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onosproject.incubator.net.config.NetworkConfigEvent;
import org.onosproject.incubator.net.config.NetworkConfigListener;
import org.onosproject.incubator.net.config.NetworkConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
/**
* Component for loading the initial network configuration.
*/
@Component(immediate = true)
public class NetworkConfigLoader {
private static final File CFG_FILE = new File("../config/network-cfg.json");
private final Logger log = LoggerFactory.getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected NetworkConfigService networkConfigService;
// FIXME: Add mutual exclusion to make sure this happens only once per startup.
private Map<InnerConfigPosition, ObjectNode> jsons = Maps.newHashMap();
private final NetworkConfigListener configListener = new InnerConfigListener();
ObjectNode root;
@Activate
public void activate() {
//TODO Maybe this should be at the bottom to avoid a potential race
networkConfigService.addListener(configListener);
try {
if (CFG_FILE.exists()) {
root = (ObjectNode) new ObjectMapper().readTree(CFG_FILE);
populateConfigurations();
applyConfigurations();
log.info("Loaded initial network configuration from {}", CFG_FILE);
}
} catch (Exception e) {
log.warn("Unable to load initial network configuration from {}",
CFG_FILE, e);
}
}
@Deactivate
public void deactivate() {
networkConfigService.removeListener(configListener);
}
// sweep through pending config jsons and try to add them
/**
* Inner class that allows for handling of newly added NetConfig types.
*/
private final class InnerConfigListener implements NetworkConfigListener {
@Override
public void event(NetworkConfigEvent event) {
//TODO should this be done for other types of NetworkConfigEvents?
if (event.type() == NetworkConfigEvent.Type.CONFIG_REGISTERED ||
event.type() == NetworkConfigEvent.Type.CONFIG_ADDED) {
applyConfigurations();
}
}
}
/**
* Inner class that allows for tracking of JSON class configurations.
*/
private final class InnerConfigPosition {
private String subjectKey, subject, classKey;
private String getSubjectKey() {
return subjectKey;
}
private String getSubject() {
return subject;
}
private String getClassKey() {
return classKey;
}
private InnerConfigPosition(String subjectKey, String subject, String classKey) {
this.subjectKey = subjectKey;
this.subject = subject;
this.classKey = classKey;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof InnerConfigPosition) {
final InnerConfigPosition that = (InnerConfigPosition) obj;
return Objects.equals(this.subjectKey, that.subjectKey) && Objects.equals(this.subject, that.subject)
&& Objects.equals(this.classKey, that.classKey);
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(subjectKey, subject, classKey);
}
}
private void saveJson(String sk, ObjectNode node) {
node.fieldNames().forEachRemaining(s ->
saveSubjectJson(sk, s, (ObjectNode) node.path(s)));
}
private void saveSubjectJson(String sk,
String s, ObjectNode node) {
node.fieldNames().forEachRemaining(c ->
this.jsons.put(new InnerConfigPosition(sk, s, c), (ObjectNode) node.path(c)));
}
private void populateConfigurations() {
root.fieldNames().forEachRemaining(sk ->
saveJson(sk, (ObjectNode) root.path(sk)));
}
protected void applyConfigurations() {
Iterator<Map.Entry<InnerConfigPosition, ObjectNode>> iter = jsons.entrySet().iterator();
Map.Entry<InnerConfigPosition, ObjectNode> entry;
while (iter.hasNext()) {
entry = iter.next();
if (networkConfigService.getConfigClass(networkConfigService.getSubjectFactory(entry.getKey().
getSubjectKey()).subjectKey(), entry.getKey().getSubject()) != null) {
networkConfigService.applyConfig(networkConfigService.getSubjectFactory(
entry.getKey().getSubjectKey()).createSubject(entry.getKey().getSubject()),
networkConfigService.getConfigClass(networkConfigService.getSubjectFactory(entry.getKey().
getSubjectKey()).subjectKey(), entry.getKey().getClassKey()),
(ObjectNode) root.path(entry.getKey().getSubjectKey()).
path(entry.getKey().getSubject()).
path(entry.getKey().getClassKey()));
jsons.remove(entry.getKey());
}
}
}
}