Refactor and modularize edgeconfig scripts

- Entirely new netbox helper functions, using pynetbox and objects,
  instead of previous spaghetti code
- Allow for VM interfaces
- Allow device names to specify more than one segment of the DNS subdomain
- Split out forward and reverse DNS
- Fix issues with DHCP zone creation
- Support advertising NTP server via DHCP option

Playbooks
- Add QA, router, DNS, and user creation/config playbook
- Fix YAML formatting issues with playbooks

Change-Id: Id6c010ef1e122f4fd1bd97e9bb2128c4271947d0
diff --git a/scripts/pxeconfig.py b/scripts/pxeconfig.py
new file mode 100644
index 0000000..34e45a0
--- /dev/null
+++ b/scripts/pxeconfig.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python3
+
+# SPDX-FileCopyrightText: © 2021 Open Networking Foundation <support@opennetworking.org>
+# SPDX-License-Identifier: Apache-2.0
+
+# pxeconfig.py
+# Given a yaml config file (same as ansible inventory for a site), create a
+# YAML file consumable by ansible that has input for the pxeboot role, for creating
+# preseed files for servers
+
+from __future__ import absolute_import
+
+import nbhelper
+import json
+import pprint
+
+from ruamel import yaml
+
+# main function that calls other functions
+if __name__ == "__main__":
+
+    # this is passed to argparse, key is option name, rest is kwargs
+    extra_args = {
+        "domain_extension": {
+            "default": "aetherproject.net",
+            "nargs": "?",
+            "type": ascii,
+            "help": "Domain extension (optional, default: aetherproject.net)",
+        },
+    }
+
+    args = nbhelper.parse_cli_args(extra_args)
+    nbh = nbhelper.NBHelper(args)
+
+    yaml_out = {}
+    pxeboot_hosts = []
+
+    prefixes = nbh.all_prefixes()
+    devices = nbhelper.NBDevice.all_devs()
+
+    for dev_id, device in devices.items():
+
+        # only pxeboot for servers
+        if device.data["device_role"]["slug"] == "server":
+
+            pxe_dev = {}
+            pxe_dev["serial"] = device.data["serial"]
+            pxe_dev["hostname"] = device.data["name"]
+            pxe_dev["domain"] = args.domain_extension
+            pxe_dev["mac_address"] = device.primary_iface()["mac_address"].lower()
+
+            pxeboot_hosts.append(pxe_dev)
+
+    #    yaml_out["devices"] = devices
+    yaml_out["pxeboot_hosts"] = pxeboot_hosts
+
+    print(yaml.safe_dump(yaml_out, indent=2))