From 916f885ae433cf71166463af729ef2891dd1d557 Mon Sep 17 00:00:00 2001 From: Thl CMK <thl-cmk@outlook.com> Date: Thu, 23 Feb 2023 22:03:01 +0100 Subject: [PATCH] adds -v/--default_cfg options --- pnp/configs/DEFAULT.cfg | 48 ++++++++++++++----------- pnp/configs/DEFAULT_REMOVE_INACTIVE.cfg | 24 +++++++++++++ pnp/open-pnp.py | 42 +++++++++++++++------- pnp/open-pnp.toml | 1 + pnp/templates/status.html | 2 +- 5 files changed, 84 insertions(+), 33 deletions(-) create mode 100644 pnp/configs/DEFAULT_REMOVE_INACTIVE.cfg diff --git a/pnp/configs/DEFAULT.cfg b/pnp/configs/DEFAULT.cfg index 3643f1f..8aab374 100644 --- a/pnp/configs/DEFAULT.cfg +++ b/pnp/configs/DEFAULT.cfg @@ -1,24 +1,32 @@ version 17.6 -event manager applet remove_inactive authorization bypass - description remove inactive firmware after reload, rest-config - event timer cron cron-entry "@reboot" maxrun 600 name REMOVE-INACTIVE - ! event timer countdown time 60 maxrun 600 name REMOVE-INACTIVE - action 0000.00 cli command "enable" - action 0000.10 syslog facility "EEM" msg "remove inactive images" - action 0000.15 cli command "terminal length 0" - action 0000.20 cli command "terminal width 0" - ! - action 0010.00 syslog facility "EEM" msg "reset configuration (no reload) START" - action 0010.10 cli command "pnp service reset no-reload" pattern "\[yes/no\]" - action 0010.15 cli command "y" - action 0010.99 syslog facility "EEM" msg "reset configuration (no reload) DONE" - ! - action 0020.00 syslog facility "EEM" msg "remove inactive images start" - action 0020.05 cli command "install remove inactive" pattern "\[y/n\]" - action 0020.10 cli command "y" - action 0020.99 syslog facility "EEM" msg "remove inactive images done" - ! -exit +aaa new-model +username admin privilege 15 algorithm-type scrypt secret admin +aaa authentication login default local +aaa authorization exec default local +aaa authorization console + +crypto key generate rsa modulus 4096 label SSH-KEY +ip ssh version 2 +ip ssh rsa keypair-name SSH-KEY + +interface gi0/0/0 + no ip dhcp client client-id + ip address dhcp + no shutdown +! +interface vlan 1 + ip address dhcp + no shutdown +! +line con 0 + logging synchronous + width 0 +! +line vty 0 15 + logging synchronous + width 0 + transport input ssh +! end diff --git a/pnp/configs/DEFAULT_REMOVE_INACTIVE.cfg b/pnp/configs/DEFAULT_REMOVE_INACTIVE.cfg new file mode 100644 index 0000000..3643f1f --- /dev/null +++ b/pnp/configs/DEFAULT_REMOVE_INACTIVE.cfg @@ -0,0 +1,24 @@ +version 17.6 + +event manager applet remove_inactive authorization bypass + description remove inactive firmware after reload, rest-config + event timer cron cron-entry "@reboot" maxrun 600 name REMOVE-INACTIVE + ! event timer countdown time 60 maxrun 600 name REMOVE-INACTIVE + action 0000.00 cli command "enable" + action 0000.10 syslog facility "EEM" msg "remove inactive images" + action 0000.15 cli command "terminal length 0" + action 0000.20 cli command "terminal width 0" + ! + action 0010.00 syslog facility "EEM" msg "reset configuration (no reload) START" + action 0010.10 cli command "pnp service reset no-reload" pattern "\[yes/no\]" + action 0010.15 cli command "y" + action 0010.99 syslog facility "EEM" msg "reset configuration (no reload) DONE" + ! + action 0020.00 syslog facility "EEM" msg "remove inactive images start" + action 0020.05 cli command "install remove inactive" pattern "\[y/n\]" + action 0020.10 cli command "y" + action 0020.99 syslog facility "EEM" msg "remove inactive images done" + ! +exit + +end diff --git a/pnp/open-pnp.py b/pnp/open-pnp.py index b5c5667..33a9712 100755 --- a/pnp/open-pnp.py +++ b/pnp/open-pnp.py @@ -32,9 +32,12 @@ # cleanup: removed global variables # 2023-02-22: removed regex -> was not working with PID: ISR4451-X/K9 # added PNP_SERVER_VERSION -# +# 2023-02-23: added cli option -v/--version, --default_cfg + # pip install flask xmltodict requests ifaddr tomli # +# ToDo: +# add remove inactive job on IOS-XE devices if no space for image update # system libs import logging @@ -57,13 +60,14 @@ from ifaddr import get_adapters from tomli import load as toml_load from tomli import TOMLDecodeError -PNP_SERVER_VERSION = '20230222.v1.0.0' +PNP_SERVER_VERSION = '20230223.v1.0.1' class Settings: def __init__( self, cli_args: Dict[str, any], + version: bool = False, cfg_file: Optional[str] = 'open-pnp.toml', image_data: Optional[str] = 'images.toml', bind_pnp_server: Optional[str] = '0.0.0.0', @@ -75,10 +79,11 @@ class Settings: log_file: Optional[str] = 'log/pnp_debug.log', image_url: Optional[str] = '', config_url: Optional[str] = '', - default_cfg_file: Optional[str] = 'DEFAULT.cfg', + default_cfg: Optional[str] = 'DEFAULT.cfg', ): self.__settings = { 'cfg_file': cfg_file, + 'version': version, 'image_data': image_data, 'bind_pnp_server': bind_pnp_server, 'port': port, @@ -89,7 +94,7 @@ class Settings: 'log_file': log_file, 'image_url': image_url, 'config_url': config_url, - 'default_cfg_file': default_cfg_file, + 'default_cfg_file': default_cfg, } self.__args = {} self.__set_cli_args(cli_args) @@ -115,6 +120,10 @@ class Settings: def cfg_file(self) -> str: return self.__settings['cfg_file'] + @property + def version(self) -> bool: + return self.__settings['version'] + @property def image_data(self) -> str: return self.__settings['image_data'] @@ -156,8 +165,8 @@ class Settings: return self.__settings['config_url'] @property - def default_cfg_file(self) -> str: - return self.__settings['default_cfg_file'] + def default_cfg(self) -> str: + return self.__settings['default_cfg'] class SoftwareImage: @@ -391,8 +400,7 @@ def parse_arguments() -> arg_Namespace: description='This is a basic implementation of the Cisco PnP protocol. It is intended to' '\nroll out image updates and configurations for Cisco IOS/IOS-XE devices on day0.' '\n' - f'\nVersion: {PNP_SERVER_VERSION}' - ', Written by: thl-cmk, for more information see: https://thl-cmk.hopto.org', + f'\n{PNP_SERVER_VERSION} | Written by: thl-cmk, for more information see: https://thl-cmk.hopto.org', formatter_class=RawTextHelpFormatter, epilog='Usage: python open-pnp.py --config_url http://192.168.10.133:8080/configs ' '--image_url http://192.168.10.133:8080/images', @@ -403,6 +411,8 @@ def parse_arguments() -> arg_Namespace: help='TCP port to listen on. (default: 8080)') parser.add_argument('-r', '--status_refresh', type=int, help='Time in seconds to refresh PnP server status page. (default: 60)') + parser.add_argument('-v', '--version', default=False, action='store_const', const=True, + help='Print open-pnp-server version and exit') parser.add_argument('--config_file', type=str, help='Path/name of open PnP server config file. (default: open-pnp.toml)') parser.add_argument('--config_url', type=str, @@ -411,11 +421,13 @@ def parse_arguments() -> arg_Namespace: help='File containing the image description. (default: images.toml)') parser.add_argument('--image_url', type=str, help='Download URL for image files. I.e. http://192.168.10.133:8080/images') - parser.add_argument('--debug', default=False, action="store_const", const=True, + parser.add_argument('--debug', default=False, action='store_const', const=True, help='Enable Debug output send to "log_file".') + parser.add_argument('--default_cfg', type=str, + help='default config to use if no device specific config is found. (default: DEFAULT.cfg)') parser.add_argument('--log_file', type=str, help='Path/name of the logfile. (default: log/pnp_debug.log, requires --debug) ') - parser.add_argument('--log_to_console', default=False, action="store_const", const=True, + parser.add_argument('--log_to_console', default=False, action='store_const', const=True, help='Enable debug output send to stdout (requires --debug).') parser.add_argument('--time_format', type=str, help='Format string to render time. (default: %%Y-%%m-%%dT%%H:%%M:%%S)') @@ -503,7 +515,7 @@ def pnp_config_upgrade(udi: str, correlator: str) -> Optional[str]: cfg_file = f'{device.serial}.cfg' response = head(f'{SETTINGS.config_url}/{cfg_file}') if response.status_code != 200: # SERIAL.cfg not found - cfg_file = SETTINGS.default_cfg_file + cfg_file = SETTINGS.default_cfg response = head(f'{SETTINGS.config_url}/{cfg_file}') if response.status_code != 200: # DEFAULT.cfg also not found device.error_code = ERROR.ERROR_NO_CFG_FILE @@ -797,6 +809,11 @@ if __name__ == '__main__': PNPFLOW = PnpFlow() SETTINGS = Settings(vars(parse_arguments())) SETTINGS.update(SETTINGS.cfg_file) + + if SETTINGS.version: + print(PNP_SERVER_VERSION) + exit(0) + IMAGES = Images(SETTINGS.image_data) devices: Dict[str, Device] = {} @@ -835,6 +852,7 @@ if __name__ == '__main__': else: print(f'Status page running on : http://{SETTINGS.bind_pnp_server}:{SETTINGS.port}') print() - print(f'Writen by thl-cmk, see https://thl-cmk.hopto.org/gitlab/bits-and-bytes/cisco_day0_provision') + print(f'{PNP_SERVER_VERSION} | ' + f'Written by thl-cmk, see https://thl-cmk.hopto.org/gitlab/bits-and-bytes/cisco_day0_provision') print() app.run(host=SETTINGS.bind_pnp_server, port=SETTINGS.port) diff --git a/pnp/open-pnp.toml b/pnp/open-pnp.toml index 2f0fcde..16d301f 100644 --- a/pnp/open-pnp.toml +++ b/pnp/open-pnp.toml @@ -11,3 +11,4 @@ # image_data = "images.toml" # image_url = "http://192.168.10.133:8080/images" # config_url = "http://192.168.10.133:8080/configs" +# default_cfg = "DEFAULT.cfg" \ No newline at end of file diff --git a/pnp/templates/status.html b/pnp/templates/status.html index 9425757..5d43f80 100644 --- a/pnp/templates/status.html +++ b/pnp/templates/status.html @@ -214,7 +214,7 @@ </div> <div class="footer"> <footer> - <p>Version: {{pnp_server_version}} | Written by: <a href="mailto:thl-cmk@outlook.com?subject=About your PnP server“,">thl-cmk</a> | Date: 2022-12-10 | for more information see <a href="https://thl-cmk.hopto.org/gitlab/bits-and-bytes/cisco_day0_provision" target="_blank">Cisco Day0 provisioning</a></p> + <p>{{pnp_server_version}} | Written by: <a href="mailto:thl-cmk@outlook.com?subject=About your PnP server“,">thl-cmk</a> | for more information see <a href="https://thl-cmk.hopto.org/gitlab/bits-and-bytes/cisco_day0_provision" target="_blank">Cisco Day0 provisioning</a></p> </footer> <div class="reload_cfg"> <form class="reload_cfg" method="post" action="/buttons"> -- GitLab