[ONOS-3205] Migrate LLDP Link Discovery configuration to Network Configuration System
- deviceIds under suppression will be moved out to different location. (See ONOS-3461)
Change-Id: I6ebe0ce7f5f2d26e7ee7175974e19305f7c17fad
diff --git a/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LldpLinkProvider.java b/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LldpLinkProvider.java
index d723ce1..1b16e51 100644
--- a/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LldpLinkProvider.java
+++ b/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LldpLinkProvider.java
@@ -38,6 +38,9 @@
import org.onosproject.net.DeviceId;
import org.onosproject.net.LinkKey;
import org.onosproject.net.Port;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
@@ -58,12 +61,12 @@
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
-import java.io.IOException;
import java.util.Dictionary;
import java.util.EnumSet;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
@@ -75,6 +78,7 @@
import static org.onlab.util.Tools.get;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.Link.Type.DIRECT;
+import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
import static org.slf4j.LoggerFactory.getLogger;
/**
@@ -87,12 +91,11 @@
private static final String FORMAT =
"Settings: enabled={}, useBDDP={}, probeRate={}, " +
- "staleLinkAge={}, lldpSuppression={}";
+ "staleLinkAge={}";
// When a Device/Port has this annotation, do not send out LLDP/BDDP
public static final String NO_LLDP = "no-lldp";
-
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -152,13 +155,6 @@
label = "Number of millis beyond which links will be considered stale")
private int staleLinkAge = DEFAULT_STALE_LINK_AGE;
- // FIXME: convert to use network config subsystem instead
- private static final String PROP_LLDP_SUPPRESSION = "lldpSuppression";
- private static final String DEFAULT_LLDP_SUPPRESSION_CONFIG = "../config/lldp_suppression.json";
- @Property(name = PROP_LLDP_SUPPRESSION, value = DEFAULT_LLDP_SUPPRESSION_CONFIG,
- label = "Path to LLDP suppression configuration file")
- private String lldpSuppression = DEFAULT_LLDP_SUPPRESSION_CONFIG;
-
private final DiscoveryContext context = new InternalDiscoveryContext();
private final InternalRoleListener roleListener = new InternalRoleListener();
private final InternalDeviceListener deviceListener = new InternalDeviceListener();
@@ -171,9 +167,31 @@
// destination connection point is mastered by this controller instance.
private final Map<LinkKey, Long> linkTimes = Maps.newConcurrentMap();
- private SuppressionRules rules;
private ApplicationId appId;
+ static final SuppressionRules DEFAULT_RULES
+ = new SuppressionRules(ImmutableSet.of(),
+ EnumSet.of(Device.Type.ROADM),
+ ImmutableMap.of(NO_LLDP, SuppressionRules.ANY_VALUE));
+
+ private SuppressionRules rules = LldpLinkProvider.DEFAULT_RULES;
+
+ public static final String CONFIG_KEY = "suppression";
+
+ private final Set<ConfigFactory> factories = ImmutableSet.of(
+ new ConfigFactory<ApplicationId, SuppressionConfig>(APP_SUBJECT_FACTORY,
+ SuppressionConfig.class,
+ CONFIG_KEY) {
+ @Override
+ public SuppressionConfig createConfig() {
+ return new SuppressionConfig();
+ }
+ }
+ );
+
+ private final InternalConfigListener cfgListener = new InternalConfigListener();
+
+
/**
* Creates an OpenFlow link provider.
*/
@@ -185,12 +203,30 @@
public void activate(ComponentContext context) {
cfgService.registerProperties(getClass());
appId = coreService.registerApplication(PROVIDER_NAME);
+
+ cfgRegistry.addListener(cfgListener);
+ factories.forEach(cfgRegistry::registerConfigFactory);
+
+ SuppressionConfig cfg = cfgRegistry.getConfig(appId, SuppressionConfig.class);
+ if (cfg == null) {
+ // If no configuration is found, register default.
+ cfg = cfgRegistry.addConfig(appId, SuppressionConfig.class);
+ cfg.deviceIds(DEFAULT_RULES.getSuppressedDevice())
+ .deviceTypes(DEFAULT_RULES.getSuppressedDeviceType())
+ .annotation(DEFAULT_RULES.getSuppressedAnnotation())
+ .apply();
+ }
+ cfgListener.reconfigureSuppressionRules(cfg);
+
modified(context);
log.info("Started");
}
@Deactivate
public void deactivate() {
+ cfgRegistry.removeListener(cfgListener);
+ factories.forEach(cfgRegistry::unregisterConfigFactory);
+
cfgService.unregisterProperties(getClass(), false);
disable();
log.info("Stopped");
@@ -202,7 +238,6 @@
boolean newEnabled, newUseBddp;
int newProbeRate, newStaleLinkAge;
- String newLldpSuppression;
try {
String s = get(properties, PROP_ENABLED);
newEnabled = isNullOrEmpty(s) || Boolean.parseBoolean(s.trim());
@@ -216,16 +251,12 @@
s = get(properties, PROP_STALE_LINK_AGE);
newStaleLinkAge = isNullOrEmpty(s) ? staleLinkAge : Integer.parseInt(s.trim());
- s = get(properties, PROP_LLDP_SUPPRESSION);
- newLldpSuppression = isNullOrEmpty(s) ? DEFAULT_LLDP_SUPPRESSION_CONFIG : s;
-
} catch (NumberFormatException e) {
log.warn("Component configuration had invalid values", e);
newEnabled = enabled;
newUseBddp = useBddp;
newProbeRate = probeRate;
newStaleLinkAge = staleLinkAge;
- newLldpSuppression = lldpSuppression;
}
boolean wasEnabled = enabled;
@@ -234,23 +265,19 @@
useBddp = newUseBddp;
probeRate = newProbeRate;
staleLinkAge = newStaleLinkAge;
- lldpSuppression = newLldpSuppression;
if (!wasEnabled && enabled) {
enable();
} else if (wasEnabled && !enabled) {
disable();
} else {
- // reflect changes in suppression rules to discovery helpers
- // FIXME: After migrating to Network Configuration Subsystem,
- // it should be possible to update only changed subset
if (enabled) {
// update all discovery helper state
loadDevices();
}
}
- log.info(FORMAT, enabled, useBddp, probeRate, staleLinkAge, lldpSuppression);
+ log.info(FORMAT, enabled, useBddp, probeRate, staleLinkAge);
}
/**
@@ -262,7 +289,6 @@
deviceService.addListener(deviceListener);
packetService.addProcessor(packetProcessor, PacketProcessor.advisor(0));
- loadSuppressionRules();
loadDevices();
executor = newSingleThreadScheduledExecutor(groupedThreads("onos/link", "discovery-%d"));
@@ -285,6 +311,7 @@
deviceService.removeListener(deviceListener);
packetService.removeProcessor(packetProcessor);
+
if (executor != null) {
executor.shutdownNow();
}
@@ -298,6 +325,9 @@
* Loads available devices and registers their ports to be probed.
*/
private void loadDevices() {
+ if (!enabled) {
+ return;
+ }
deviceService.getAvailableDevices()
.forEach(d -> updateDevice(d)
.ifPresent(ld -> updatePorts(ld, d.id())));
@@ -333,7 +363,6 @@
private void removeDevice(final DeviceId deviceId) {
discoverers.computeIfPresent(deviceId, (did, ld) -> {
ld.stop();
- providerService.linksVanished(deviceId);
return null;
});
@@ -357,6 +386,7 @@
// silently ignore logical ports
return;
}
+
if (rules.isSuppressed(port)) {
log.trace("LinkDiscovery from {} disabled by configuration", port);
removePort(port);
@@ -383,35 +413,12 @@
if (ld != null) {
ld.removePort(port.number());
}
-
- ConnectPoint point = new ConnectPoint(d.id(), port.number());
- providerService.linksVanished(point);
} else {
log.warn("Attempted to remove non-Device port", port);
}
}
/**
- * Loads LLDP suppression rules.
- */
- private void loadSuppressionRules() {
- // FIXME: convert to use network configuration
- SuppressionRulesStore store = new SuppressionRulesStore(lldpSuppression);
- try {
- log.info("Reading suppression rules from {}", lldpSuppression);
- rules = store.read();
- } catch (IOException e) {
- log.info("Failed to load {}, using built-in rules", lldpSuppression);
- // default rule to suppress ROADM to maintain compatibility
- rules = new SuppressionRules(ImmutableSet.of(),
- EnumSet.of(Device.Type.ROADM),
- ImmutableMap.of(NO_LLDP, SuppressionRules.ANY_VALUE));
- }
-
- // should refresh discoverers when we need dynamic reconfiguration
- }
-
- /**
* Requests packet intercepts.
*/
private void requestIntercepts() {
@@ -438,6 +445,17 @@
packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
}
+ protected SuppressionRules rules() {
+ return rules;
+ }
+
+ protected void updateRules(SuppressionRules newRules) {
+ if (!rules.equals(newRules)) {
+ rules = newRules;
+ loadDevices();
+ }
+ }
+
/**
* Processes device mastership role changes.
*/
@@ -459,7 +477,6 @@
updateDevice(device).ifPresent(ld -> updatePorts(ld, device.id()));
}
}
-
}
/**
@@ -488,16 +505,21 @@
} else {
log.debug("Port down {}", port);
removePort(port);
+ providerService.linksVanished(new ConnectPoint(port.element().id(),
+ port.number()));
}
break;
case PORT_REMOVED:
log.debug("Port removed {}", port);
removePort(port);
+ providerService.linksVanished(new ConnectPoint(port.element().id(),
+ port.number()));
break;
case DEVICE_REMOVED:
case DEVICE_SUSPENDED:
log.debug("Device removed {}", deviceId);
removeDevice(deviceId);
+ providerService.linksVanished(deviceId);
break;
case DEVICE_AVAILABILITY_CHANGED:
if (deviceService.isAvailable(deviceId)) {
@@ -506,6 +528,7 @@
} else {
log.debug("Device down {}", deviceId);
removeDevice(deviceId);
+ providerService.linksVanished(deviceId);
}
break;
case PORT_STATS_UPDATED:
@@ -636,4 +659,30 @@
}
}
+ private class InternalConfigListener implements NetworkConfigListener {
+
+ private synchronized void reconfigureSuppressionRules(SuppressionConfig cfg) {
+ if (cfg == null) {
+ log.error("Suppression Config is null.");
+ return;
+ }
+
+ SuppressionRules newRules = new SuppressionRules(cfg.deviceIds(),
+ cfg.deviceTypes(),
+ cfg.annotation());
+
+ updateRules(newRules);
+ }
+
+ @Override
+ public void event(NetworkConfigEvent event) {
+ if (event.configClass().equals(SuppressionConfig.class) &&
+ (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
+ event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)) {
+ SuppressionConfig cfg = cfgRegistry.getConfig(appId, SuppressionConfig.class);
+ reconfigureSuppressionRules(cfg);
+ log.trace("Network config reconfigured");
+ }
+ }
+ }
}
diff --git a/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/SuppressionConfig.java b/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/SuppressionConfig.java
new file mode 100644
index 0000000..20bafb3
--- /dev/null
+++ b/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/SuppressionConfig.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2014-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.provider.lldp.impl;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.config.Config;
+import org.slf4j.Logger;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import static org.onosproject.provider.lldp.impl.LldpLinkProvider.DEFAULT_RULES;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * LLDP suppression config class.
+ */
+public class SuppressionConfig extends Config<ApplicationId> {
+ private static final String DEVICE_IDS = "deviceIds";
+ private static final String DEVICE_TYPES = "deviceTypes";
+ private static final String ANNOTATION = "annotation";
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+ private static final List<DeviceId> DEFAULT_DEVICE_IDS
+ = ImmutableList.copyOf(DEFAULT_RULES.getSuppressedDevice());
+ private static final List<Device.Type> DEFAULT_DEVICE_TYPES
+ = ImmutableList.copyOf(DEFAULT_RULES.getSuppressedDeviceType());
+
+ private final Logger log = getLogger(getClass());
+
+ /**
+ * Returns device IDs on which LLDP is suppressed.
+ *
+ * @return Set of DeviceId objects
+ */
+ @Deprecated
+ public Set<DeviceId> deviceIds() {
+ return ImmutableSet.copyOf(getList(DEVICE_IDS, DeviceId::deviceId, DEFAULT_DEVICE_IDS));
+ }
+
+ /**
+ * Sets device IDs on which LLDP is suppressed.
+ *
+ * @param deviceIds new set of device IDs; null to clear
+ * @return self
+ */
+ @Deprecated
+ public SuppressionConfig deviceIds(Set<DeviceId> deviceIds) {
+ return (SuppressionConfig) setOrClear(DEVICE_IDS, deviceIds);
+ }
+
+ /**
+ * Returns types of devices on which LLDP is suppressed.
+ *
+ * @return set of device types
+ */
+ public Set<Device.Type> deviceTypes() {
+ return ImmutableSet.copyOf(getList(DEVICE_TYPES, Device.Type::valueOf, DEFAULT_DEVICE_TYPES));
+ }
+
+ /**
+ * Sets types of devices on which LLDP is suppressed.
+ *
+ * @param deviceTypes new set of device types; null to clear
+ * @return self
+ */
+ public SuppressionConfig deviceTypes(Set<Device.Type> deviceTypes) {
+ return (SuppressionConfig) setOrClear(DEVICE_TYPES, deviceTypes);
+ }
+
+ /**
+ * Returns annotation of Ports on which LLDP is suppressed.
+ *
+ * @return key-value pairs of annotation
+ */
+ public Map<String, String> annotation() {
+ ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
+
+ String jsonAnnotation = get(ANNOTATION, null);
+ if (jsonAnnotation == null || jsonAnnotation.isEmpty()) {
+ return ImmutableMap.of();
+ }
+
+ JsonNode annotationNode;
+ try {
+ annotationNode = MAPPER.readTree(jsonAnnotation);
+ } catch (IOException e) {
+ log.error("Failed to read JSON tree from: {}", jsonAnnotation);
+ return ImmutableMap.of();
+ }
+
+ if (annotationNode.isObject()) {
+ ObjectNode obj = (ObjectNode) annotationNode;
+ Iterator<Map.Entry<String, JsonNode>> it = obj.fields();
+ while (it.hasNext()) {
+ Map.Entry<String, JsonNode> entry = it.next();
+ final String key = entry.getKey();
+ final JsonNode value = entry.getValue();
+
+ if (value.isValueNode()) {
+ if (value.isNull()) {
+ builder.put(key, SuppressionRules.ANY_VALUE);
+ } else {
+ builder.put(key, value.asText());
+ }
+ } else {
+ log.warn("Encountered unexpected JSON field {} for annotation", entry);
+ }
+ }
+ } else {
+ log.error("Encountered unexpected JSONNode {} for annotation", annotationNode);
+ return ImmutableMap.of();
+ }
+
+ return builder.build();
+ }
+
+ /**
+ * Sets annotation of Ports on which LLDP is suppressed.
+ *
+ * @param annotation new key-value pair of annotation; null to clear
+ * @return self
+ */
+ public SuppressionConfig annotation(Map<String, String> annotation) {
+
+ // ANY_VALUE should be null in JSON
+ Map<String, String> config = Maps.transformValues(annotation,
+ v -> (v == SuppressionRules.ANY_VALUE) ? null : v);
+
+ String jsonAnnotation = null;
+
+ try {
+ // TODO Store annotation as a Map instead of a String (which needs NetworkConfigRegistry modification)
+ jsonAnnotation = MAPPER.writeValueAsString(config);
+ } catch (JsonProcessingException e) {
+ log.error("Failed to write JSON from: {}", annotation);
+ }
+
+ return (SuppressionConfig) setOrClear(ANNOTATION, jsonAnnotation);
+ }
+}
diff --git a/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/SuppressionRules.java b/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/SuppressionRules.java
index 27c75eb..9cda07c 100644
--- a/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/SuppressionRules.java
+++ b/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/SuppressionRules.java
@@ -18,6 +18,7 @@
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Objects;
import java.util.Set;
import org.onosproject.net.Annotations;
@@ -28,6 +29,7 @@
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.base.MoreObjects;
public class SuppressionRules {
@@ -103,4 +105,34 @@
Map<String, String> getSuppressedAnnotation() {
return suppressedAnnotation;
}
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(suppressedDevice,
+ suppressedDeviceType,
+ suppressedAnnotation);
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (object != null && getClass() == object.getClass()) {
+ SuppressionRules that = (SuppressionRules) object;
+ return Objects.equals(this.suppressedDevice,
+ that.suppressedDevice)
+ && Objects.equals(this.suppressedDeviceType,
+ that.suppressedDeviceType)
+ && Objects.equals(this.suppressedAnnotation,
+ that.suppressedAnnotation);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("suppressedDevice", suppressedDevice)
+ .add("suppressedDeviceType", suppressedDeviceType)
+ .add("suppressedAnnotation", suppressedAnnotation)
+ .toString();
+ }
}
diff --git a/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/SuppressionRulesStore.java b/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/SuppressionRulesStore.java
deleted file mode 100644
index 360bebd..0000000
--- a/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/SuppressionRulesStore.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright 2014-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.provider.lldp.impl;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import com.fasterxml.jackson.core.JsonEncoding;
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.slf4j.Logger;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-/*
- * JSON file example
- *
-
-{
- "deviceId" : [ "of:2222000000000000" ],
- "deviceType" : [ "ROADM" ],
- "annotation" : { "no-lldp" : null, "sendLLDP" : "false" }
-}
- */
-
-/**
- * Allows for reading and writing LLDP suppression definition as a JSON file.
- */
-public class SuppressionRulesStore {
-
- private static final String DEVICE_ID = "deviceId";
- private static final String DEVICE_TYPE = "deviceType";
- private static final String ANNOTATION = "annotation";
-
- private final Logger log = getLogger(getClass());
-
- private final File file;
-
- /**
- * Creates a reader/writer of the LLDP suppression definition file.
- *
- * @param filePath location of the definition file
- */
- public SuppressionRulesStore(String filePath) {
- file = new File(filePath);
- }
-
- /**
- * Creates a reader/writer of the LLDP suppression definition file.
- *
- * @param file definition file
- */
- public SuppressionRulesStore(File file) {
- this.file = checkNotNull(file);
- }
-
- /**
- * Returns SuppressionRules.
- *
- * @return SuppressionRules
- * @throws IOException if error occurred while reading the data
- */
- public SuppressionRules read() throws IOException {
- final Set<DeviceId> suppressedDevice = new HashSet<>();
- final EnumSet<Device.Type> suppressedDeviceType = EnumSet.noneOf(Device.Type.class);
- final Map<String, String> suppressedAnnotation = new HashMap<>();
-
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode root = (ObjectNode) mapper.readTree(file);
-
- for (JsonNode deviceId : root.get(DEVICE_ID)) {
- if (deviceId.isTextual()) {
- suppressedDevice.add(DeviceId.deviceId(deviceId.asText()));
- } else {
- log.warn("Encountered unexpected JSONNode {} for deviceId", deviceId);
- }
- }
-
- for (JsonNode deviceType : root.get(DEVICE_TYPE)) {
- if (deviceType.isTextual()) {
- suppressedDeviceType.add(Device.Type.valueOf(deviceType.asText()));
- } else {
- log.warn("Encountered unexpected JSONNode {} for deviceType", deviceType);
- }
- }
-
- JsonNode annotation = root.get(ANNOTATION);
- if (annotation.isObject()) {
- ObjectNode obj = (ObjectNode) annotation;
- Iterator<Entry<String, JsonNode>> it = obj.fields();
- while (it.hasNext()) {
- Entry<String, JsonNode> entry = it.next();
- final String key = entry.getKey();
- final JsonNode value = entry.getValue();
-
- if (value.isValueNode()) {
- if (value.isNull()) {
- suppressedAnnotation.put(key, SuppressionRules.ANY_VALUE);
- } else {
- suppressedAnnotation.put(key, value.asText());
- }
- } else {
- log.warn("Encountered unexpected JSON field {} for annotation", entry);
- }
- }
- } else {
- log.warn("Encountered unexpected JSONNode {} for annotation", annotation);
- }
-
- return new SuppressionRules(suppressedDevice,
- suppressedDeviceType,
- suppressedAnnotation);
- }
-
- /**
- * Writes the given SuppressionRules.
- *
- * @param rules SuppressionRules
- * @throws IOException if error occurred while writing the data
- */
- public void write(SuppressionRules rules) throws IOException {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode root = mapper.createObjectNode();
- ArrayNode deviceIds = mapper.createArrayNode();
- ArrayNode deviceTypes = mapper.createArrayNode();
- ObjectNode annotations = mapper.createObjectNode();
- root.set(DEVICE_ID, deviceIds);
- root.set(DEVICE_TYPE, deviceTypes);
- root.set(ANNOTATION, annotations);
-
- rules.getSuppressedDevice()
- .forEach(deviceId -> deviceIds.add(deviceId.toString()));
-
- rules.getSuppressedDeviceType()
- .forEach(type -> deviceTypes.add(type.toString()));
-
- rules.getSuppressedAnnotation().forEach((key, value) -> {
- if (value == SuppressionRules.ANY_VALUE) {
- annotations.putNull(key);
- } else {
- annotations.put(key, value);
- }
- });
- mapper.writeTree(new JsonFactory().createGenerator(file, JsonEncoding.UTF8),
- root);
- }
-}