Fixed an issue in basic host and basic link config validations.

Added validation for basic device config.

Made all concrete configurations final (as they should be).

Changed stc to use the new onos-netcfg as a method to re-locate and name devices and hosts.

Change-Id: I372e6c7e6c0fa6fa52301568af73342aaae6347b
diff --git a/core/api/src/main/java/org/onosproject/net/config/Config.java b/core/api/src/main/java/org/onosproject/net/config/Config.java
index 0a3d87f..aac1320 100644
--- a/core/api/src/main/java/org/onosproject/net/config/Config.java
+++ b/core/api/src/main/java/org/onosproject/net/config/Config.java
@@ -95,15 +95,15 @@
      * <p>
      * Default implementation returns true.
      * Subclasses are expected to override this with their own validation.
-     * </p>
+     * Implementations are free to throw a RuntimeException if data is invalid.
+     * * </p>
      *
      * @return true if the data is valid; false otherwise
+     * @throws RuntimeException if configuration is invalid or completely foobar
      */
     public boolean isValid() {
-        // TODO: figure out what assertions could be made in the base class
-        // NOTE: The thought is to have none, but instead to provide a set
-        // of predicates to allow configs to test validity of present fields,
-        // e.g.:
+        // Derivatives should use the provided set of predicates to test
+        // validity of their fields, e.g.:
         //      isString(path)
         //      isBoolean(path)
         //      isNumber(path, [min, max])
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/AllowedEntityConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/AllowedEntityConfig.java
index 6e6663c..ee4042c 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/AllowedEntityConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/AllowedEntityConfig.java
@@ -23,7 +23,7 @@
  */
 public abstract class AllowedEntityConfig<S> extends Config<S> {
 
-    private static final String ALLOWED = "allowed";
+    protected static final String ALLOWED = "allowed";
 
     /**
      * Indicates whether the element is allowed for admission into the control
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/BasicDeviceConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/BasicDeviceConfig.java
index afde9a9..add8cf3 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/BasicDeviceConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/BasicDeviceConfig.java
@@ -21,11 +21,17 @@
 /**
  * Basic configuration for network infrastructure devices.
  */
-public class BasicDeviceConfig extends BasicElementConfig<DeviceId> {
+public final class BasicDeviceConfig extends BasicElementConfig<DeviceId> {
 
-    public static final String TYPE = "type";
-    public static final String DRIVER = "driver";
-    public static final String MANAGEMENT_ADDRESS = "managementAddress";
+    private static final String TYPE = "type";
+    private static final String DRIVER = "driver";
+    private static final String MANAGEMENT_ADDRESS = "managementAddress";
+
+    @Override
+    public boolean isValid() {
+        return hasOnlyFields(ALLOWED, NAME, LATITUDE, LONGITUDE, RACK_ADDRESS, OWNER,
+                             TYPE, DRIVER, MANAGEMENT_ADDRESS);
+    }
 
     /**
      * Returns the device type.
@@ -85,6 +91,6 @@
     }
 
     // TODO: device port meta-data to be configured via BasicPortsConfig
-    // TODO: device credentials/keys
+    // TODO: device credentials/keys; in a separate config
 
 }
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/BasicElementConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/BasicElementConfig.java
index 7b3248c..10d753b 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/BasicElementConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/BasicElementConfig.java
@@ -22,13 +22,13 @@
  */
 public abstract class BasicElementConfig<S> extends AllowedEntityConfig<S> {
 
-    public static final String NAME = "name";
+    protected static final String NAME = "name";
 
-    public static final String LATITUDE = "latitude";
-    public static final String LONGITUDE = "longitude";
+    protected static final String LATITUDE = "latitude";
+    protected static final String LONGITUDE = "longitude";
 
-    public static final String RACK_ADDRESS = "rackAddress";
-    public static final String OWNER = "owner";
+    protected static final String RACK_ADDRESS = "rackAddress";
+    protected static final String OWNER = "owner";
 
     protected static final double DEFAULT_COORD = -1.0;
 
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/BasicHostConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/BasicHostConfig.java
index 9294631..8429630 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/BasicHostConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/BasicHostConfig.java
@@ -19,68 +19,62 @@
 import org.onlab.packet.IpAddress;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.HostId;
+
 import java.util.HashSet;
 import java.util.Set;
 
+import static org.onosproject.net.config.basics.AllowedEntityConfig.ALLOWED;
+
 /**
  * Basic configuration for network end-station hosts.
  */
-public class BasicHostConfig extends BasicElementConfig<HostId> {
+public final class BasicHostConfig extends BasicElementConfig<HostId> {
+
     private static final String IPS = "ips";
     private static final String LOCATION = "location";
 
     @Override
     public boolean isValid() {
-        return hasOnlyFields(IPS, LOCATION) &&
-                this.location() != null &&
-                this.ipAddresses() != null;
+        // Location and IP addresses can be absent, but if present must be valid.
+        this.location();
+        this.ipAddresses();
+        return hasOnlyFields(ALLOWED, NAME, LATITUDE, LONGITUDE, RACK_ADDRESS, OWNER,
+                             IPS, LOCATION);
     }
 
     /**
-     * Gets location of the host.
+     * Returns location of the host.
      *
-     * @return location of the host. Or null if not specified with correct format.
+     * @return location of the host or null if not set
+     * @throws IllegalArgumentException if not specified with correct format
      */
     public ConnectPoint location() {
         String location = get(LOCATION, null);
-
-        if (location != null) {
-            try {
-                return ConnectPoint.deviceConnectPoint(location);
-            } catch (Exception e) {
-                return null;
-            }
-        }
-        return null;
+        return location != null ? ConnectPoint.deviceConnectPoint(location) : null;
     }
 
     /**
      * Sets the location of the host.
      *
-     * @param location location of the host.
-     * @return the config of the host.
+     * @param location location of the host or null to unset
+     * @return the config of the host
      */
     public BasicHostConfig setLocation(String location) {
         return (BasicHostConfig) setOrClear(LOCATION, location);
     }
 
     /**
-     * Gets IP addresses of the host.
+     * Returns IP addresses of the host.
      *
-     * @return IP addresses of the host. Or null if not specified with correct format.
+     * @return IP addresses of the host or null if not set
+     * @throws IllegalArgumentException if not specified with correct format
      */
     public Set<IpAddress> ipAddresses() {
         HashSet<IpAddress> ipAddresses = new HashSet<>();
         if (object.has(IPS)) {
             ArrayNode ipNodes = (ArrayNode) object.path(IPS);
-            try {
-                ipNodes.forEach(ipNode -> {
-                    ipAddresses.add(IpAddress.valueOf(ipNode.asText()));
-                });
-                return ipAddresses;
-            } catch (Exception e) {
-                return null;
-            }
+            ipNodes.forEach(n -> ipAddresses.add(IpAddress.valueOf(n.asText())));
+            return ipAddresses;
         }
         return null;
     }
@@ -88,8 +82,8 @@
     /**
      * Sets the IP addresses of the host.
      *
-     * @param ipAddresses IP addresses of the host.
-     * @return the config of the host.
+     * @param ipAddresses IP addresses of the host or null to unset
+     * @return the config of the host
      */
     public BasicHostConfig setIps(Set<IpAddress> ipAddresses) {
         return (BasicHostConfig) setOrClear(IPS, ipAddresses);
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java
index ed807b8..0ad851a 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java
@@ -26,19 +26,19 @@
 /**
  * Basic configuration for network infrastructure link.
  */
-public class BasicLinkConfig extends AllowedEntityConfig<LinkKey> {
+public final class BasicLinkConfig extends AllowedEntityConfig<LinkKey> {
 
-    public static final String TYPE = "type";
-    public static final String METRIC = "metric";
-    public static final String LATENCY = "latency";
-    public static final String BANDWIDTH = "bandwidth";
-    public static final String IS_DURABLE = "durable";
+    private static final String TYPE = "type";
+    private static final String METRIC = "metric";
+    private static final String LATENCY = "latency";
+    private static final String BANDWIDTH = "bandwidth";
+    private static final String IS_DURABLE = "durable";
 
     @Override
     public boolean isValid() {
-        return hasOnlyFields(TYPE, METRIC, LATENCY, BANDWIDTH, IS_DURABLE) &&
-                isNumber(METRIC, OPTIONAL) && isNumber(LATENCY, OPTIONAL) &&
-                isNumber(BANDWIDTH, OPTIONAL);
+        return hasOnlyFields(ALLOWED, TYPE, METRIC, LATENCY, BANDWIDTH, IS_DURABLE) &&
+                isBoolean(ALLOWED, OPTIONAL) && isNumber(METRIC, OPTIONAL) &&
+                isNumber(LATENCY, OPTIONAL) && isNumber(BANDWIDTH, OPTIONAL);
     }
 
     /**
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/OpticalPortConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/OpticalPortConfig.java
index dfb494d..7a1b801 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/OpticalPortConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/OpticalPortConfig.java
@@ -23,11 +23,13 @@
 
 import com.fasterxml.jackson.databind.JsonNode;
 
+import static org.onosproject.net.config.Config.FieldPresence.OPTIONAL;
+
 
 /**
  * Configurations for an optical port on a device.
  */
-public class OpticalPortConfig extends Config<ConnectPoint> {
+public final class OpticalPortConfig extends Config<ConnectPoint> {
     // optical type {OMS, OCH, ODUClt, fiber}
     public static final String TYPE = "type";
 
@@ -42,6 +44,12 @@
     // **Linc-OE : remove if it's not needed after all.**
     public static final String SPEED = "speed";
 
+    @Override
+    public boolean isValid() {
+        return hasOnlyFields(TYPE, NAME, PORT, STATIC_PORT, STATIC_LAMBDA, SPEED) &&
+                isNumber(STATIC_LAMBDA, OPTIONAL) && isNumber(SPEED, OPTIONAL);
+    }
+
     /**
      * Returns the Enum value representing the type of port.
      *
diff --git a/core/net/src/main/java/org/onosproject/net/device/impl/BasicDeviceOperator.java b/core/net/src/main/java/org/onosproject/net/device/impl/BasicDeviceOperator.java
index a498b3f..108d68d 100644
--- a/core/net/src/main/java/org/onosproject/net/device/impl/BasicDeviceOperator.java
+++ b/core/net/src/main/java/org/onosproject/net/device/impl/BasicDeviceOperator.java
@@ -32,7 +32,7 @@
 
 /**
  * Implementations of merge policies for various sources of device configuration
- * information. This includes applications, provides, and network configurations.
+ * information. This includes applications, providers, and network configurations.
  */
 public final class BasicDeviceOperator implements ConfigOperator {
 
diff --git a/core/net/src/main/java/org/onosproject/net/host/impl/BasicHostOperator.java b/core/net/src/main/java/org/onosproject/net/host/impl/BasicHostOperator.java
index 68aa27f..14b86d2 100644
--- a/core/net/src/main/java/org/onosproject/net/host/impl/BasicHostOperator.java
+++ b/core/net/src/main/java/org/onosproject/net/host/impl/BasicHostOperator.java
@@ -15,25 +15,26 @@
  */
 package org.onosproject.net.host.impl;
 
-import static org.slf4j.LoggerFactory.getLogger;
-
-import org.slf4j.Logger;
+import org.onlab.packet.IpAddress;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.SparseAnnotations;
 import org.onosproject.net.config.ConfigOperator;
 import org.onosproject.net.config.basics.BasicHostConfig;
-import org.onosproject.net.AnnotationKeys;
-import org.onosproject.net.DefaultAnnotations;
-import org.onosproject.net.SparseAnnotations;
 import org.onosproject.net.host.DefaultHostDescription;
 import org.onosproject.net.host.HostDescription;
 
+import java.util.Set;
+
 /**
  * Implementations of merge policies for various sources of host configuration
- * information. This includes applications, provides, and network configurations.
+ * information. This includes applications, providers, and network configurations.
  */
 public final class BasicHostOperator implements ConfigOperator {
 
     protected static final double DEFAULT_COORD = -1.0;
-    private static final Logger log = getLogger(BasicHostOperator.class);
 
     private BasicHostOperator() {
     }
@@ -42,7 +43,7 @@
      * Generates a HostDescription containing fields from a HostDescription and
      * a HostConfig.
      *
-     * @param cfg the host config entity from network config
+     * @param cfg   the host config entity from network config
      * @param descr a HostDescription
      * @return HostDescription based on both sources
      */
@@ -50,16 +51,29 @@
         if (cfg == null) {
             return descr;
         }
+
+        HostLocation location = descr.location();
+        ConnectPoint cfgLocation = cfg.location();
+        if (cfgLocation != null) {
+            location = new HostLocation(cfgLocation, System.currentTimeMillis());
+        }
+
+        Set<IpAddress> ipAddresses = descr.ipAddress();
+        Set<IpAddress> cfgIpAddresses = cfg.ipAddresses();
+        if (cfgIpAddresses != null) {
+            ipAddresses = cfgIpAddresses;
+        }
+
         SparseAnnotations sa = combine(cfg, descr.annotations());
-        return new DefaultHostDescription(descr.hwAddress(), descr.vlan(), descr.location(),
-                descr.ipAddress(), sa);
+        return new DefaultHostDescription(descr.hwAddress(), descr.vlan(),
+                                          location, ipAddresses, sa);
     }
 
     /**
      * Generates an annotation from an existing annotation and HostConfig.
      *
      * @param cfg the device config entity from network config
-     * @param an the annotation
+     * @param an  the annotation
      * @return annotation combining both sources
      */
     public static SparseAnnotations combine(BasicHostConfig cfg, SparseAnnotations an) {
diff --git a/tools/dev/bash_profile b/tools/dev/bash_profile
index c9bca80..69f8c43 100644
--- a/tools/dev/bash_profile
+++ b/tools/dev/bash_profile
@@ -192,4 +192,4 @@
 
 
 # Load AT&T MPLS topo GEO data
-alias atttopo='onos-topo-cfg $OCI $ONOS_ROOT/tools/test/topos/attmpls.json'
\ No newline at end of file
+alias atttopo='onos-netcfg $OCI $ONOS_ROOT/tools/test/topos/attmpls-cfg.json'
\ No newline at end of file
diff --git a/tools/test/bin/onos-netcfg b/tools/test/bin/onos-netcfg
index 23900ec..3942428 100755
--- a/tools/test/bin/onos-netcfg
+++ b/tools/test/bin/onos-netcfg
@@ -10,6 +10,6 @@
 file="${2:-$ONOS_ROOT/tools/test/topos/oe-linear-3.json}"
 url="${3}"
 
-curl -sS --fail -L --user $ONOS_WEB_USER:$ONOS_WEB_PASS \
+curl --fail -L --user $ONOS_WEB_USER:$ONOS_WEB_PASS \
     -X POST -H 'Content-Type:application/json' \
     http://$node:8181/onos/v1/network/configuration/${url} -d@$file
diff --git a/tools/test/scenarios/net-pingall.xml b/tools/test/scenarios/net-pingall.xml
index 100ceba..eb2ec7a 100644
--- a/tools/test/scenarios/net-pingall.xml
+++ b/tools/test/scenarios/net-pingall.xml
@@ -30,8 +30,5 @@
 
         <step name="Check-Summary-For-Hosts" requires="~Ping-All-And-Verify"
               exec="onos-check-summary ${OC1} [0-9]* 25 140 25"/>
-
-        <step name="Config-Topo" requires="~Check-Summary-For-Hosts"
-              exec="onos-topo-cfg ${OC1} ${ONOS_ROOT}/tools/test/topos/attmpls.json"/>
     </group>
 </scenario>
diff --git a/tools/test/scenarios/net-setup.xml b/tools/test/scenarios/net-setup.xml
index ce15bf8..4e5125a 100644
--- a/tools/test/scenarios/net-setup.xml
+++ b/tools/test/scenarios/net-setup.xml
@@ -24,8 +24,11 @@
         <step name="Initial-Summary-Check" requires="~Wipe-Out-Data-Before"
               exec="onos-check-summary ${OC1} [0-9]* 0 0 0"/>
 
+        <step name="Config-Topo" requires="~Initial-Summary-Check"
+              exec="onos-netcfg ${OC1} ${ONOS_ROOT}/tools/test/topos/attmpls-cfg.json"/>
+
         <step name="Start-Mininet"
-              requires="Install-Apps,Initial-Summary-Check,Push-Topos,Stop-Mininet-If-Needed"
+              requires="Install-Apps,Config-Topo,Push-Topos,Stop-Mininet-If-Needed"
               exec="onos-mininet start topos/topo att-onos.py ${ONOS_INSTANCES}"/>
 
         <step name="Wait-For-Mininet" requires="Start-Mininet"
diff --git a/tools/test/topos/attmpls-cfg.json b/tools/test/topos/attmpls-cfg.json
new file mode 100644
index 0000000..c144606
--- /dev/null
+++ b/tools/test/topos/attmpls-cfg.json
@@ -0,0 +1,57 @@
+{
+  "devices": {
+    "of:0000000000000001": { "basic": { "name": "CMBR", "latitude": 42.373730, "longitude": -71.109734  }},
+    "of:0000000000000002": { "basic": { "name": "CHCG", "latitude": 41.877461, "longitude": -87.642892  }},
+    "of:0000000000000003": { "basic": { "name": "CLEV", "latitude": 41.498928, "longitude": -81.695217  }},
+    "of:0000000000000004": { "basic": { "name": "RLGH", "latitude": 35.780150, "longitude": -78.644026  }},
+    "of:0000000000000005": { "basic": { "name": "ATLN", "latitude": 33.749017, "longitude": -84.394168  }},
+    "of:0000000000000006": { "basic": { "name": "PHLA", "latitude": 39.952906, "longitude": -75.172278  }},
+    "of:0000000000000007": { "basic": { "name": "WASH", "latitude": 38.906696, "longitude": -77.035509  }},
+    "of:0000000000000008": { "basic": { "name": "NSVL", "latitude": 36.166410, "longitude": -86.787305  }},
+    "of:0000000000000009": { "basic": { "name": "STLS", "latitude": 38.626418, "longitude": -90.198143  }},
+    "of:000000000000000a": { "basic": { "name": "NWOR", "latitude": 29.951475, "longitude": -90.078434  }},
+    "of:000000000000000b": { "basic": { "name": "HSTN", "latitude": 29.763249, "longitude": -95.368332  }},
+    "of:000000000000000c": { "basic": { "name": "SNAN", "latitude": 29.424331, "longitude": -98.491745  }},
+    "of:000000000000000d": { "basic": { "name": "DLLS", "latitude": 32.777665, "longitude": -96.802064  }},
+    "of:000000000000000e": { "basic": { "name": "ORLD", "latitude": 28.538641, "longitude": -81.381110  }},
+    "of:000000000000000f": { "basic": { "name": "DNVR", "latitude": 39.736623, "longitude": -104.984887 }},
+    "of:0000000000000010": { "basic": { "name": "KSCY", "latitude": 39.100725, "longitude": -94.581228  }},
+    "of:0000000000000011": { "basic": { "name": "SNFN", "latitude": 37.779751, "longitude": -122.409791 }},
+    "of:0000000000000012": { "basic": { "name": "SCRM", "latitude": 38.581001, "longitude": -121.497844 }},
+    "of:0000000000000013": { "basic": { "name": "PTLD", "latitude": 45.523317, "longitude": -122.677768 }},
+    "of:0000000000000014": { "basic": { "name": "STTL", "latitude": 47.607326, "longitude": -122.331786 }},
+    "of:0000000000000015": { "basic": { "name": "SLKC", "latitude": 40.759577, "longitude": -111.895079 }},
+    "of:0000000000000016": { "basic": { "name": "LA03", "latitude": 34.056346, "longitude": -118.235951 }},
+    "of:0000000000000017": { "basic": { "name": "SNDG", "latitude": 32.714564, "longitude": -117.153528 }},
+    "of:0000000000000018": { "basic": { "name": "PHNX", "latitude": 33.448289, "longitude": -112.076299 }},
+    "of:0000000000000019": { "basic": { "name": "NY54", "latitude": 40.728270, "longitude": -73.994483  }}
+  },
+
+  "hosts": {
+    "00:00:00:00:00:01/-1": { "basic": { "location": "of:0000000000000001/1", "ips": [ "10.0.0.1" ],  "name": "CMBR", "latitude": 43.355715, "longitude":  -69.528243 }},
+    "00:00:00:00:00:02/-1": { "basic": { "location": "of:0000000000000002/1", "ips": [ "10.0.0.2" ],  "name": "CHCG", "latitude": 43.632679, "longitude":  -88.772526 }},
+    "00:00:00:00:00:03/-1": { "basic": { "location": "of:0000000000000003/1", "ips": [ "10.0.0.3" ],  "name": "CLEV", "latitude": 42.756945, "longitude":  -79.831317 }},
+    "00:00:00:00:00:04/-1": { "basic": { "location": "of:0000000000000004/1", "ips": [ "10.0.0.4" ],  "name": "RLGH", "latitude": 36.972249, "longitude":  -76.667163 }},
+    "00:00:00:00:00:05/-1": { "basic": { "location": "of:0000000000000005/1", "ips": [ "10.0.0.5" ],  "name": "ATLN", "latitude": 35.427493, "longitude":  -83.885831 }},
+    "00:00:00:00:00:06/-1": { "basic": { "location": "of:0000000000000006/1", "ips": [ "10.0.0.6" ],  "name": "PHLA", "latitude": 39.208113, "longitude":  -73.421341 }},
+    "00:00:00:00:00:07/-1": { "basic": { "location": "of:0000000000000007/1", "ips": [ "10.0.0.7" ],  "name": "WASH", "latitude": 40.133860, "longitude":  -79.238299 }},
+    "00:00:00:00:00:08/-1": { "basic": { "location": "of:0000000000000008/1", "ips": [ "10.0.0.8" ],  "name": "NSVL", "latitude": 37.407589, "longitude":  -84.415068 }},
+    "00:00:00:00:00:09/-1": { "basic": { "location": "of:0000000000000009/1", "ips": [ "10.0.0.9" ],  "name": "STLS", "latitude": 40.066810, "longitude":  -90.932405 }},
+    "00:00:00:00:00:0a/-1": { "basic": { "location": "of:000000000000000a/1", "ips": [ "10.0.0.10" ], "name": "NWOR", "latitude": 31.470982, "longitude":  -88.779353 }},
+    "00:00:00:00:00:0b/-1": { "basic": { "location": "of:000000000000000b/1", "ips": [ "10.0.0.11" ], "name": "HSTN", "latitude": 31.136858, "longitude":  -94.351656 }},
+    "00:00:00:00:00:0c/-1": { "basic": { "location": "of:000000000000000c/1", "ips": [ "10.0.0.12" ], "name": "SNAN", "latitude": 28.040975, "longitude":  -99.169527 }},
+    "00:00:00:00:00:0d/-1": { "basic": { "location": "of:000000000000000d/1", "ips": [ "10.0.0.13" ], "name": "DLLS", "latitude": 31.899825, "longitude":  -99.287263 }},
+    "00:00:00:00:00:0e/-1": { "basic": { "location": "of:000000000000000e/1", "ips": [ "10.0.0.14" ], "name": "ORLD", "latitude": 26.670509, "longitude":  -81.291920 }},
+    "00:00:00:00:00:0f/-1": { "basic": { "location": "of:000000000000000f/1", "ips": [ "10.0.0.15" ], "name": "DNVR", "latitude": 40.888148, "longitude": -103.459878 }},
+    "00:00:00:00:00:10/-1": { "basic": { "location": "of:0000000000000010/1", "ips": [ "10.0.0.16" ], "name": "KSCY", "latitude": 40.545088, "longitude":  -93.734002 }},
+    "00:00:00:00:00:11/-1": { "basic": { "location": "of:0000000000000011/1", "ips": [ "10.0.0.17" ], "name": "SNFN", "latitude": 39.081743, "longitude": -124.330172 }},
+    "00:00:00:00:00:12/-1": { "basic": { "location": "of:0000000000000012/1", "ips": [ "10.0.0.18" ], "name": "SCRM", "latitude": 40.107468, "longitude": -120.424689 }},
+    "00:00:00:00:00:13/-1": { "basic": { "location": "of:0000000000000013/1", "ips": [ "10.0.0.19" ], "name": "PTLD", "latitude": 44.383051, "longitude": -124.767594 }},
+    "00:00:00:00:00:14/-1": { "basic": { "location": "of:0000000000000014/1", "ips": [ "10.0.0.20" ], "name": "STTL", "latitude": 48.832627, "longitude": -120.298441 }},
+    "00:00:00:00:00:15/-1": { "basic": { "location": "of:0000000000000015/1", "ips": [ "10.0.0.21" ], "name": "SLKC", "latitude": 42.301734, "longitude": -111.217297 }},
+    "00:00:00:00:00:16/-1": { "basic": { "location": "of:0000000000000016/1", "ips": [ "10.0.0.22" ], "name": "LA03", "latitude": 33.224634, "longitude": -121.532943 }},
+    "00:00:00:00:00:17/-1": { "basic": { "location": "of:0000000000000017/1", "ips": [ "10.0.0.23" ], "name": "SNDG", "latitude": 31.834607, "longitude": -118.847982 }},
+    "00:00:00:00:00:18/-1": { "basic": { "location": "of:0000000000000018/1", "ips": [ "10.0.0.24" ], "name": "PHNX", "latitude": 34.662290, "longitude": -110.946662 }},
+    "00:00:00:00:00:19/-1": { "basic": { "location": "of:0000000000000019/1", "ips": [ "10.0.0.25" ], "name": "NY54", "latitude": 42.395459, "longitude":  -75.293563 }}
+  }
+}