From 4525190058372e43c9480e7d84675b35f56cf36a Mon Sep 17 00:00:00 2001 From: David Lobato Date: Fri, 13 Sep 2024 10:36:15 +0100 Subject: [PATCH] Initial cleanup of XMPP support --- README.md | 4 +- client/bootstrap | 179 ++--------------------------- conf/bootstrap.conf | 8 -- docs/api.rst | 11 -- docs/config.rst | 11 -- docs/cookbook/clientLogging.rst | 47 -------- docs/cookbook/definitions.rst | 18 +-- docs/cookbook/helloWorld.rst | 4 +- docs/index.rst | 4 +- docs/install.rst | 3 - docs/overview.rst | 6 +- docs/tips.rst | 9 +- docs/troubleshooting.rst | 2 +- requirements-node-py2.txt | 1 - requirements-node.txt | 1 - rpm/ztpserver.spec | 2 +- test/client/client_test_lib.py | 9 +- test/client/test_xmpp_bootstrap.py | 138 ---------------------- test/server/server_test_lib.py | 3 +- test/server/test_controller.py | 60 +--------- ztpserver/controller.py | 16 +-- 21 files changed, 30 insertions(+), 506 deletions(-) delete mode 100644 test/client/test_xmpp_bootstrap.py diff --git a/README.md b/README.md index 7b0c0867..eb43c4bf 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Quick Overview ===================== ZTPServer provides a bootstrap environment for Arista EOS based products. ZTPserver interacts with the ZeroTouch Provisioning (ZTP) mode of Arista EOS. The default ZTP start up mode triggers an unprovisioned Arista EOS nodes to enter a bootstrap readdy state if a valid configuration file is not already present on the internal flash storage. -ZTPServer provides a number of configurable bootstrap operation workflows that extend beyond simply loading an configuration and boot image. It provides the ability to define the target node through the introduction of definitions and templates that call pre-built actions and statically defined or dynamically generated attributes. The attributes and actions can also be extended to provide custom functionality that are specific to a given implementation. ZTPServer also provides a topology validation engine with a simple syntax to express LLDP neighbor adjacencies. It is written mostly in Python and leverages standard protocols like DHCP and DHCP options for boot functions, HTTP for bi-directional transport, and XMPP and syslog for logging. Most of the files that the user interacts with are YAML based. +ZTPServer provides a number of configurable bootstrap operation workflows that extend beyond simply loading an configuration and boot image. It provides the ability to define the target node through the introduction of definitions and templates that call pre-built actions and statically defined or dynamically generated attributes. The attributes and actions can also be extended to provide custom functionality that are specific to a given implementation. ZTPServer also provides a topology validation engine with a simple syntax to express LLDP neighbor adjacencies. It is written mostly in Python and leverages standard protocols like DHCP and DHCP options for boot functions, HTTP for bi-directional transport, and syslog for logging. Most of the files that the user interacts with are YAML based. ZTPServer Features ================== @@ -15,7 +15,7 @@ ZTPServer Features * Config and device templates with resource allocation for dynamic deployments * Zero touch replacement and upgrade capabilities * User extensible actions -* Email, XMPP, syslog based logging and accounting of all processes +* Syslog based logging and accounting of all processes Docs ==== diff --git a/client/bootstrap b/client/bootstrap index e4525bff..dd52c77f 100755 --- a/client/bootstrap +++ b/client/bootstrap @@ -61,7 +61,6 @@ from string import Template # pylint: disable=W0402 from subprocess import PIPE import jsonrpclib -import sleekxmpp from six import PY2, PY3, binary_type, raise_from, text_type from six.moves import urllib @@ -107,29 +106,14 @@ RESTORE_FACTORY_FLASH = True # pylint: disable=C0103 syslog_manager = None -xmpp_client = None # pylint: enable=C0103 -# --------------------------------XMPP------------------------ -# Uncomment this section in order to enable XMPP debug logging -# logging.basicConfig(level=logging.DEBUG, -# format='%(levelname)-8s %(message)s') - -# You will also have to comment out the following lines: -for logger in ["sleekxmpp.xmlstream.xmlstream", "sleekxmpp.basexmpp"]: - xmpp_log = logging.getLogger(logger) - xmpp_log.addHandler(logging.NullHandler()) -# --------------------------------XMPP------------------------ - # --------------------------------SYSLOG---------------------- # Comment out this section in order to enable syslog debug # logging logging.raiseExceptions = False -# --------------------------------XMPP------------------------ - - # ------------------Utilities--------------------------------- # pylint: disable=C0103,C0123,R1705 # ensure_str backport from six 1.6 as older EOS packs six 1.11 @@ -182,15 +166,6 @@ def ensure_text(s, encoding="utf-8", errors="strict"): def _exit(code): # pylint: disable=W0702 - # Wait for XMPP messages to drain - time.sleep(3) - - if xmpp_client: - try: - xmpp_client.abort() - except: - pass - if not RESTORE_FACTORY_FLASH: for path in [STARTUP_CONFIG, RC_EOS, BOOT_EXTENSIONS]: filename = os.path.basename(path) @@ -239,30 +214,13 @@ def _exit(code): sys.stderr.flush() # pylint: disable=W0212 - # Need to close background sleekxmpp threads as well sys.exit(code) SYSTEM_ID = None -XMPP_MSG_TYPE = None - - -def log_xmpp(): - return XMPP_MSG_TYPE == "debug" - - -def log(msg, error=False, xmpp=None): - if xmpp is None: - xmpp = log_xmpp() - - timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S") - xmpp_msg = "{}: {} - {}{}".format( - SYSTEM_ID if SYSTEM_ID else "N/A", timestamp, "ERROR: " if error else "", msg - ) - if xmpp and xmpp_client and xmpp_client.connected: - xmpp_client.message(xmpp_msg) +def log(msg, error=False): if SYSTEM_ID: syslog_msg = "{}: {}".format(SYSTEM_ID, msg) else: @@ -746,7 +704,7 @@ class Node: self._append_lines(RC_EOS, lines) def log_msg(self, msg, error=False): - """Log message via configured syslog/XMPP. + """Log message via configured syslog. Args: msg (string): Message @@ -1265,129 +1223,13 @@ class Server: self._save_file_contents(response, path, url) -class XmppClient(sleekxmpp.ClientXMPP): - def __init__(self, user, domain, password, rooms, nick, xmpp_server, xmpp_port): - self.xmpp_jid = "{}@{}".format(user, domain) - self.connected = False - - try: - sleekxmpp.ClientXMPP.__init__(self, self.xmpp_jid, password) - except sleekxmpp.jid.InvalidJID: - log( - "Unable to connect XMPP client because of invalid jid: {}".format(self.xmpp_jid), - xmpp=False, - ) - return - - self.xmpp_nick = nick - self.xmpp_rooms = rooms - - self.xmpp_rooms = [] - for room in rooms: - self.xmpp_rooms.append("{}@conference.{}".format(room, domain)) - - self.add_event_handler("session_start", self._session_connected) - self.add_event_handler("connect", self._session_connected) - self.add_event_handler("disconnected", self._session_disconnected) - - # Multi-User Chat - self.register_plugin("xep_0045") - # XMPP Ping - self.register_plugin("xep_0199") - # Service Discovery - self.register_plugin("xep_0030") - - log("XmppClient connecting to server...", xmpp=False) - if xmpp_server is not None: - self.connect((xmpp_server, xmpp_port), reattempt=False) - else: - self.connect(reattempt=False) - - self.process(block=False) - - retries = 3 - while not self.connected and retries: - # Wait to connect - time.sleep(1) - retries -= 1 - - def _session_connected(self, _): - log("XmppClient: Session connected ({})".format(self.xmpp_jid), xmpp=False) - self.send_presence() - self.get_roster() - - self.connected = True - - # Joining rooms - for room in self.xmpp_rooms: - self.plugin["xep_0045"].joinMUC(room, self.xmpp_nick, wait=True) - log("XmppClient: Joined room {} as {}".format(room, self.xmpp_nick), xmpp=False) - - def _session_disconnected(self, _): - log("XmppClient: Session disconnected ({})".format(self.xmpp_jid), xmpp=False) - self.connected = False - - def message(self, message): - for room in self.xmpp_rooms: - self.send_message(mto=room, mbody=message, mtype="groupchat") - - def apply_config(config, node): - global xmpp_client # pylint: disable=W0603 - log("Applying server config") - # XMPP not configured yet - xmpp_config = config.get("xmpp", {}) - - global XMPP_MSG_TYPE # pylint: disable=W0603 - XMPP_MSG_TYPE = xmpp_config.get("msg_type", "debug") - if XMPP_MSG_TYPE not in ["debug", "info"]: - log( - "XMPP configuration failed because of unexpected 'msg_type': " - "{} not in ['debug', 'info']".format(XMPP_MSG_TYPE), - error=True, - xmpp=False, - ) - else: - if xmpp_config: - log("Configuring XMPP", xmpp=False) - if ( - "username" in xmpp_config - and "domain" in xmpp_config - and "password" in xmpp_config - and "rooms" in xmpp_config - and xmpp_config["rooms"] - ): - nick = node.system()["serialnumber"] - if not nick: - # vEOS might not have a serial number configured - nick = node.system()["systemmac"] - xmpp_client = XmppClient( - xmpp_config["username"], - xmpp_config["domain"], - xmpp_config["password"], - xmpp_config["rooms"], - nick, - xmpp_config.get("server", None), - xmpp_config.get("port", 5222), - ) - else: - # XMPP not configured yet - log( - "XMPP configuration failed because server response is missing config details", - error=True, - xmpp=False, - ) - else: - log("No XMPP configuration received from server", xmpp=False) - log_config = config.get("logging", []) if log_config: log("Configuring syslog") syslog_manager.add_handlers(log_config) - else: - log("No XMPP configuration received from server") def load_module(module_name, source_path): @@ -1416,7 +1258,7 @@ def execute_action(server, action_details, special_attr): log("Executing action {}".format(action)) if "onstart" in action_details: - log("Action {}: {}".format(action, action_details["onstart"]), xmpp=True) + log("Action {}: {}".format(action, action_details["onstart"])) try: if action not in sys.modules: @@ -1432,10 +1274,10 @@ def execute_action(server, action_details, special_attr): log("Action executed succesfully ({})".format(action)) if "onsuccess" in action_details: - log("Action {}: {}".format(action, action_details["onsuccess"]), xmpp=True) + log("Action {}: {}".format(action, action_details["onsuccess"])) except Exception as err: # pylint: disable=W0703 if "onfailure" in action_details: - log("Action {}: {}".format(action, action_details["onfailure"]), xmpp=True) + log("Action {}: {}".format(action, action_details["onfailure"])) raise_from(ZtpActionError("executing action failed ({}): {}".format(action, err)), err) @@ -1459,21 +1301,18 @@ def main(): syslog_manager = SyslogManager() server = Server() - # Retrieve and apply logging/XMPP configuration from server - # XMPP not configured yet - log("Retrieving config from server", xmpp=False) + # Retrieve and apply logging configuration from server + log("Retrieving config from server") _, _, config = server.get_config() # Creating node node = Node(server) - # XMPP not configured yet - log("Config retrieved from server", xmpp=False) + log("Config retrieved from server") apply_config(config.json(), node) # Checking node on server - # XMPP not configured yet - log("Collecting node information", xmpp=False) + log("Collecting node information") _, _, location = server.post_nodes(node.details()) # Get definition diff --git a/conf/bootstrap.conf b/conf/bootstrap.conf index 3bbb8057..b1a76a44 100644 --- a/conf/bootstrap.conf +++ b/conf/bootstrap.conf @@ -5,13 +5,5 @@ # level: # ... # -# xmpp: -# username: -# password: -# domain: -# msg_type : [debug|info] # default is 'debug' -# rooms: -# - -# ... # # See documentation for the detailed list of possible values. diff --git a/docs/api.rst b/docs/api.rst index 7874c2e8..5fcdc7f4 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -98,17 +98,6 @@ GET bootstrap logging configuration //by default “level”*: , } ] - }, - “xmpp”*:{ - “server”: , - “port”: , // Optional, default 5222 - “username”*: , - “domain”*: , - “password”*: , - “nickname”: , // Optional, default ‘username’ - “rooms”*: [ , … ] - } - } } **Note**: \* Items are mandatory (even if value is empty list/dict) diff --git a/docs/config.rst b/docs/config.rst index 4cb75782..0c05d931 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -170,17 +170,6 @@ Bootstrap configuration level: CRITICAL - destination: 10.0.1.1:9000 level: CRITICAL - xmpp: - domain: im.ztps-test.com - username: bootstrap - password: eosplus - rooms: - - ztps - - ztps-room2 - -.. note:: - - In order for XMPP logging to work, a non-EOS user need to be connected to the room specified in bootstrap.conf, before the ZTP process starts. The room has to be created (by the non-EOS user) before the bootstrap client starts logging the ZTP process via XMPP. .. _static_provisioning: diff --git a/docs/cookbook/clientLogging.rst b/docs/cookbook/clientLogging.rst index facf8484..8b8fab4c 100644 --- a/docs/cookbook/clientLogging.rst +++ b/docs/cookbook/clientLogging.rst @@ -45,50 +45,3 @@ The node will request the contents of the ``bootstrap.conf`` when it performs send logs to the ``destination(s):`` listed under ``logging:``. .. End of Configure Syslog Logging - - -Configure XMPP Logging ------------------------- - -Objective -^^^^^^^^^ - -I want to send client logs to specific XMPP server rooms. - -Solution -^^^^^^^^ - -.. code-block:: console - - # Edit the bootstrap configuration file - admin@ztpserver:~# vi /usr/share/ztpserver/bootstrap/bootstrap.conf - -Add any XMPP servers and associated rooms: - -.. code-block:: yaml - - --- - xmpp: - domain: - username: bootstrap - password: eosplus - rooms: - - ztps - - devops - - admins - -Explanation -^^^^^^^^^^^ - -The node will request the contents of the ``bootstrap.conf`` when it performs -``GET /bootstrap/config`` file and try to join the rooms listed with the -credentials provided. Typically when joining a room, you would use a string -like, ``ztps@conference.xmpp-server.example.com``. Be sure to just provide the -``domain: xmpp-server.example.com`` leaving out the ``conference`` prefix. - -.. note:: In order for XMPP logging to work, a non-EOS user need to be connected - to the room specified in bootstrap.conf, before the ZTP process starts. - The room has to be created (by the non-EOS user) before the bootstrap - client starts logging the ZTP process via XMPP. - -.. End of Configure XMPP Logging diff --git a/docs/cookbook/definitions.rst b/docs/cookbook/definitions.rst index c9b1af87..27109ca2 100644 --- a/docs/cookbook/definitions.rst +++ b/docs/cookbook/definitions.rst @@ -100,22 +100,11 @@ and ``$dst`` variables. variables: ipaddress: $ip name: "configure ma1" - - - action: add_config - attributes: - url: files/templates/xmpp.template - variables: $variables - name: "configure ma1" attributes: dst: /mnt/flash mode: 777 ip: 192.168.0.50 - variables: - domain: im.example.com - user: myXmmpUser - passwd: secret - room: myAwesomeRoom Explanation @@ -125,8 +114,7 @@ This example shows how to use global variables within the definition. It's important to see the difference between using variables to define attributes of the action versus variables that get used within the template in an ``add_config`` action. See how the ``ipaddress`` variable is nested within -a ``variables`` key? Also, you can create a list in the ``attributes`` section -and pass the entire list into the action as shown in the XMPP config action. +a ``variables`` key?. .. note:: For more Action recipes see the Actions section. @@ -143,7 +131,7 @@ Add Custom Log Statements as Action Executes Objective ^^^^^^^^^ -I want to send specific messages to my syslog and/or XMPP servers while an action +I want to send specific messages to my syslog servers while an action is executing. Especially, if something goes wrong, I'd like to add a helpful message so the engineer knows who to contact. @@ -187,6 +175,6 @@ Here we make use of three specific keywords: ``onstart``, ``onsuccess`` and this message while it is being provisioned. As mentioned above, this message will be sent to all of the logging destinations defined in ``[data_root]/bootstrap/bootstrap.conf``. -.. note:: For help defining an XMPP or syslog endpoint, see :ref:`client-logging-label` +.. note:: For help defining a syslog endpoint, see :ref:`client-logging-label` .. End of Add an Action to a Definition diff --git a/docs/cookbook/helloWorld.rst b/docs/cookbook/helloWorld.rst index d166c099..c27b324e 100644 --- a/docs/cookbook/helloWorld.rst +++ b/docs/cookbook/helloWorld.rst @@ -20,7 +20,7 @@ using the ZTPServer. There are some assumptions: .. note:: If you would like to test this in a virtual environment, please see the `packer-ztpserver `_ Github repo to learn how to automatically install a ZTPServer with all - of the complementary services (DHCP, DNS, NTP, XMPP, and SYSLOG). Both + of the complementary services (DHCP, DNS, NTP, and SYSLOG). Both Virtual Box and VMware are supported. @@ -351,7 +351,7 @@ in the DHCP response, which lets the node know where to grab the bootstrap scrip **A Quick Overview of the Provisioning Process for this Node** #. **GET /bootstrap**: The node gets the bootstrap script and begins executing it. The following requests are made while the bootstrap script is being executed. - #. **GET /bootstrap/config**: The node gets the bootstrap config which contains XMPP and Syslog information for the node to send logs to. + #. **GET /bootstrap/config**: The node gets the bootstrap config which contains Syslog information for the node to send logs to. #. **POST /nodes**: The node sends information about itself in JSON format to the ZTPServer. The ZTPServer parses this info and finds the System MAC. It looks in the ``nodes/`` directory and finds a match. #. **GET /nodes/001122334455**: The node requests its definition and learns what resources it has to retrieve. #. **GET /actions/install_image**: The node retrieves the install_image script. diff --git a/docs/index.rst b/docs/index.rst index e1069908..c296a44c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,7 +6,7 @@ ZTPServer Overview ======================== -ZTPServer provides a bootstrap environment for Arista EOS based products. It is written mostly in Python and leverages standard protocols like DHCP (for boot functions), HTTP (for bi-directional transport), XMPP and syslog (for logging). Most of the configuration files are YAML based. +ZTPServer provides a bootstrap environment for Arista EOS based products. It is written mostly in Python and leverages standard protocols like DHCP (for boot functions), HTTP (for bi-directional transport), and syslog (for logging). Most of the configuration files are YAML based. This open source project is maintained by the `Arista Networks `_ EOS+ services organization. @@ -27,7 +27,7 @@ Features * Config and device templates with dynamic resource allocation * Zero-touch replacement and upgrade capabilities * User extensible actions -* Email, XMPP, syslog based +* Syslog based .. _an_introduction: diff --git a/docs/install.rst b/docs/install.rst index 6b324517..141712ad 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -55,9 +55,6 @@ VM Specification: * wildcard forwarding rule passing all other queries to 8.8.8.8 * SRV RR for im.ztps-test.com * rsyslog-ng installed; Listening on UDP and TCP (port 514) -* ejabberd (XMPP server) configured for im.ztps-test.com - - * XMPP admin user: ztpsadmin/eosplus * httpd installed and configured for ZTPServer (mod_wsgi) * ZTPServer installed * ztpserver-demo repo files pre-loaded diff --git a/docs/overview.rst b/docs/overview.rst index d921f40d..2d100000 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -12,7 +12,7 @@ ZTPServer provides a number of features that extend beyond simply loading a conf * validation topology using a simple syntax for expressing LLDP neighbor adjacencies * enabling Zero Touch Replacement, as well as configuration backup and management -ZTPServer is written in Python and leverages standard protocols like DHCP (DHCP options for boot functions), HTTP(S) (for bi-directional transport), XMPP and syslog (for logging). Most of the configuration files are YAML-based. +ZTPServer is written in Python and leverages standard protocols like DHCP (DHCP options for boot functions), HTTP(S) (for bi-directional transport), and syslog (for logging). Most of the configuration files are YAML-based. **Highlights:** @@ -30,7 +30,7 @@ ZTPServer is written in Python and leverages standard protocols like DHCP (DHCP * configuration templating with resource allocation (for dynamic deployments) * Zero Touch Replacement and software upgrade capabilities * user extensible actions -* XMPP and syslog-based logging and accounting +* Syslog-based logging and accounting ZTP Intro ````````` @@ -82,7 +82,7 @@ Client The client or **bootstrap file** is retrieved by the node via an HTTP GET request made to the ZTPServer (the URL of the file is retrieved via DHCP option 67). This file executes locally and gathers system and LLDP information from the node and sends it back to the ZTPServer. Once the ZTPServer processes the information and confirms that it can provision the node, the client makes a request to the server for a definition file - this file will contain the list of all actions which need to be executed by the node in order to provision itself. -Throughout the provisioning process the bootstrap client can log all steps via both local and remote syslogs, as well as XMPP. +Throughout the provisioning process the bootstrap client can log all steps via both local and remote syslogs. .. _message_flows: diff --git a/docs/tips.rst b/docs/tips.rst index 23db4b05..3cd01051 100644 --- a/docs/tips.rst +++ b/docs/tips.rst @@ -109,8 +109,6 @@ How do I debug the ZTP Server provisioning process? switch# bash chmod +x bootstrap switch# bash sudo ./bootstrap -* On the client side, make sure you use XMPP (best) or remove syslog (second best) logging - you can configure that in *bootstrap.conf*. - * When requesting support, please include the output from the server (running in debug mode) and the console/log output from the switch. How do I disable / enable ZTP mode on a switch @@ -148,12 +146,7 @@ If you setup your own environment, the following recommendations should assist g * During testing, only - run the standalone server in debug mode: ``ztps --debug`` in a buffered shell. NOTE: do NOT use this standalone server in production, however, except in the smallest environments ( Approx 10 nodes or less, consecutively). * Do not attempt any detailed debugging from a virtual or serial console. Due to the quantity of information and frequent lack of copy/paste access, this if often painful. Both suggested logging methods, below, can be configured in the :ref:`bootstrap_config`. - * (BEST) Setup XMPP logging. There are many XMPP services available, including `ejabberd `_, and even more clients, such as `Adium `_. This will give you a single pane view of what is happening on all of your test switches. Our demo includes ejabberd with the following configuration: - - * Server: im.ztps-test.com (or your ZTPServer IP) - * XMPP admin user: ztpsadmin@im.ztps-test.com, passwd eosplus - - * (Second) In place of XMPP, splecify a central syslog server in the bootstrap config. + * Specify a central syslog server in the bootstrap config. How do I override the default system-mac in vEOS? `````````````````````````````````````````````````` diff --git a/docs/troubleshooting.rst b/docs/troubleshooting.rst index 1e04ad30..7e281122 100644 --- a/docs/troubleshooting.rst +++ b/docs/troubleshooting.rst @@ -71,7 +71,7 @@ The location of server-side logs may vary depending on your specific environment Client-side logs ^^^^^^^^^^^^^^^^ -Ensure the bootstrap client is configured to log to syslog or XMPP via +Ensure the bootstrap client is configured to log to syslog via /usr/share/ztpserver/bootstrap/bootstrap.conf and include that output. Attempting to collect client side logs from the console frequently results in missing information due to scroll buffers or line length. diff --git a/requirements-node-py2.txt b/requirements-node-py2.txt index 47951708..2dc1301d 100644 --- a/requirements-node-py2.txt +++ b/requirements-node-py2.txt @@ -1,3 +1,2 @@ six -sleekxmpp jsonrpclib diff --git a/requirements-node.txt b/requirements-node.txt index 2345fdde..4610f670 100644 --- a/requirements-node.txt +++ b/requirements-node.txt @@ -1,4 +1,3 @@ six -sleekxmpp jsonrpclib aiosmtpd diff --git a/rpm/ztpserver.spec b/rpm/ztpserver.spec index d3c4baab..9f752a9d 100644 --- a/rpm/ztpserver.spec +++ b/rpm/ztpserver.spec @@ -82,7 +82,7 @@ custom functionality that are specific to a given implementation. ZTPServer also provides a topology validation engine with a simple syntax to express LLDP neighbor adjacencies. It is written mostly in Python and leverages standard protocols like DHCP and DHCP options for boot functions, HTTP for -bi-directional transport, and XMPP and syslog for logging. Most of the files +bi-directional transport, and syslog for logging. Most of the files that the user interacts with are YAML based. %prep diff --git a/test/client/client_test_lib.py b/test/client/client_test_lib.py index 6ce9650b..e286bcf4 100755 --- a/test/client/client_test_lib.py +++ b/test/client/client_test_lib.py @@ -539,16 +539,11 @@ def set_file_response(self, filename, output, content_type="text/plain", status= def set_action_response(self, action, output, content_type="text/x-python", status=STATUS_OK): self.responses["/actions/{}".format(action)] = Response(content_type, status, output, {}) - def set_config_response( - self, logging=None, xmpp=None, content_type="application/json", status=STATUS_OK - ): - response = {"logging": [], "xmpp": {}} + def set_config_response(self, logging=None, content_type="application/json", status=STATUS_OK): + response = {"logging": []} if logging: response["logging"] = logging - if xmpp: - response["xmpp"] = xmpp - self.responses["/bootstrap/config"] = Response( content_type, status, json.dumps(response), {} ) diff --git a/test/client/test_xmpp_bootstrap.py b/test/client/test_xmpp_bootstrap.py deleted file mode 100644 index c59db481..00000000 --- a/test/client/test_xmpp_bootstrap.py +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2015, Arista Networks, Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# - Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# - Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# - Neither the name of Arista Networks nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# pylint: disable=R0904,F0401,C0209 - -import unittest -from test.client.client_test_lib import Bootstrap, raise_exception - - -class XmppConfigTest(unittest.TestCase): - @classmethod - def bootstrap(cls, xmpp): - bootstrap = Bootstrap() - bootstrap.ztps.set_config_response(xmpp=xmpp) - bootstrap.ztps.set_node_check_response() - bootstrap.ztps.set_definition_response() - bootstrap.start_test() - return bootstrap - - def xmpp_sanity_test(self, xmpp): - bootstrap = self.bootstrap(xmpp) - - try: - self.assertTrue(bootstrap.eapi_node_information_collected()) - self.assertTrue(bootstrap.missing_startup_config_failure()) - self.assertFalse(bootstrap.error) - self.assertFalse("XmppClient" not in bootstrap.output) - except AssertionError as assertion: - print("Output: {}".format(bootstrap.output)) - print("Error: {}".format(bootstrap.error)) - raise_exception(assertion) - finally: - bootstrap.end_test() - - def test_full(self): - self.xmpp_sanity_test( - { - "server": "test-server", - "port": 112233, - "username": "test-username", - "password": "test-password", - "domain": "test-domain", - "rooms": ["test-room-1", "test-room-2"], - } - ) - - def test_msg_type_debug(self): - self.xmpp_sanity_test( - { - "server": "test-server", - "port": 112233, - "username": "test-username", - "password": "test-password", - "domain": "test-domain", - "rooms": ["test-room-1", "test-room-2"], - "msg_type": "debug", - } - ) - - def test_msg_type_info(self): - self.xmpp_sanity_test( - { - "server": "test-server", - "port": 112233, - "username": "test-username", - "password": "test-password", - "domain": "test-domain", - "rooms": ["test-room-1", "test-room-2"], - "msg_type": "debug", - } - ) - - def test_partial(self): - self.xmpp_sanity_test( - { - "rooms": ["test-room-1"], - "username": "test-username", - "password": "test-password", - "domain": "test-domain", - } - ) - - def test_erroneous_msg_type(self): - bootstrap = self.bootstrap( - { - "server": "test-server", - "port": 112233, - "username": "test-username", - "password": "test-password", - "domain": "test-domain", - "rooms": ["test-room-1", "test-room-2"], - "msg_type": "bogus", - } - ) - - try: - self.assertTrue(bootstrap.eapi_node_information_collected()) - self.assertTrue(bootstrap.missing_startup_config_failure()) - self.assertFalse(bootstrap.error) - self.assertFalse( - "XMPP configuration failed because of unexpected 'msg_type'" not in bootstrap.output - ) - except AssertionError as assertion: - print("Output: {}".format(bootstrap.output)) - print("Error: {}".format(bootstrap.error)) - raise_exception(assertion) - finally: - bootstrap.end_test() - - -if __name__ == "__main__": - unittest.main() diff --git a/test/server/server_test_lib.py b/test/server/server_test_lib.py index 9d0017e9..0308b19c 100644 --- a/test/server/server_test_lib.py +++ b/test/server/server_test_lib.py @@ -231,13 +231,12 @@ def mock_match( class BootstrapConf(SerializerMixin): def __init__(self, **kwargs): self.logging = kwargs.get("logging", []) - self.xmpp = kwargs.get("xmpp", {}) def add_logging(self, entry): self.logging.append(entry) def as_dict(self): - return {"logging": self.logging, "xmpp": self.xmpp} + return {"logging": self.logging} def create_bootstrap_conf(): diff --git a/test/server/test_controller.py b/test/server/test_controller.py index 832b872c..a0d3b56f 100644 --- a/test/server/test_controller.py +++ b/test/server/test_controller.py @@ -281,65 +281,9 @@ def test_no_config(self, m_repository): self.assertEqual(resp["body"], controller.DEFAULT_CONFIG) self.assertEqual(resp["content_type"], constants.CONTENT_TYPE_JSON) - @patch("ztpserver.controller.create_repository") - def test_no_xmpp(self, m_repository): - cfg = {"return_value.read.return_value": {"logging": []}} - m_repository.return_value.get_file.configure_mock(**cfg) - - controller = ztpserver.controller.BootstrapController() - - request = Request.blank("") - request.remote_addr = "" - resp = controller.config(request) - - self.assertEqual(resp["body"], controller.DEFAULT_CONFIG) - self.assertEqual(resp["content_type"], constants.CONTENT_TYPE_JSON) - - @patch("ztpserver.controller.create_repository") - def test_no_logging(self, m_repository): - cfg = {"return_value.read.return_value": {"xmpp": {}}} - m_repository.return_value.get_file.configure_mock(**cfg) - - controller = ztpserver.controller.BootstrapController() - - request = Request.blank("") - request.remote_addr = "" - resp = controller.config(request) - - self.assertEqual(resp["body"], controller.DEFAULT_CONFIG) - self.assertEqual(resp["content_type"], constants.CONTENT_TYPE_JSON) - - @patch("ztpserver.controller.create_repository") - def test_empty_xmpp(self, m_repository): - cfg = {"return_value.read.return_value": {"logging": [], "xmpp": None}} - m_repository.return_value.get_file.configure_mock(**cfg) - - controller = ztpserver.controller.BootstrapController() - - request = Request.blank("") - request.remote_addr = "" - resp = controller.config(request) - - self.assertEqual(resp["body"], controller.DEFAULT_CONFIG) - self.assertEqual(resp["content_type"], constants.CONTENT_TYPE_JSON) - @patch("ztpserver.controller.create_repository") def test_empty_logging(self, m_repository): - cfg = {"return_value.read.return_value": {"logging": None, "xmpp": {}}} - m_repository.return_value.get_file.configure_mock(**cfg) - - controller = ztpserver.controller.BootstrapController() - - request = Request.blank("") - request.remote_addr = "" - resp = controller.config(request) - - self.assertEqual(resp["body"], controller.DEFAULT_CONFIG) - self.assertEqual(resp["content_type"], constants.CONTENT_TYPE_JSON) - - @patch("ztpserver.controller.create_repository") - def test_empty_xmpp_logging(self, m_repository): - cfg = {"return_value.read.return_value": {"logging": None, "xmpp": None}} + cfg = {"return_value.read.return_value": {"logging": None}} m_repository.return_value.get_file.configure_mock(**cfg) controller = ztpserver.controller.BootstrapController() @@ -420,7 +364,7 @@ def test_get_bootstrap_config_defaults(self): request = Request.blank("/bootstrap/config") resp = request.get_response(ztpserver.controller.Router()) - defaultconfig = {"logging": [], "xmpp": {}} + defaultconfig = {"logging": []} self.assertEqual(resp.status_code, constants.HTTP_STATUS_OK) self.assertEqual(resp.content_type, constants.CONTENT_TYPE_JSON) diff --git a/ztpserver/controller.py b/ztpserver/controller.py index da75f2b5..1164091d 100644 --- a/ztpserver/controller.py +++ b/ztpserver/controller.py @@ -779,7 +779,7 @@ def finalize_response(self, response, *args, **kwargs): class BootstrapController(BaseController): - DEFAULT_CONFIG = {"logging": [], "xmpp": {}} + DEFAULT_CONFIG = {"logging": []} FOLDER = "bootstrap" @@ -803,20 +803,6 @@ def config(self, request, **kwargs): request.remote_addr, ) - if "xmpp" in config and config["xmpp"]: - body["xmpp"] = config["xmpp"] - for key in ["username", "password", "domain"]: - if key not in body["xmpp"]: - log.warning( - "Bootstrap config: '%s' missing from XMPP config", - key, - ) - if "rooms" not in body["xmpp"] or not body["xmpp"]["rooms"]: - log.warning("Bootstrap config: no XMPP rooms configured") - log.info( - "%s: xmpp info included in bootstrap config", - request.remote_addr, - ) resp = {"body": body, "content_type": CONTENT_TYPE_JSON} except FileObjectNotFound: log.warning("Bootstrap config file not found")