Collection of CheckMK checks (see https://checkmk.com/). All checks and plugins are provided as is. Absolutely no warranty. Send any comments to thl-cmk[at]outlook[dot]com

Skip to content
Snippets Groups Projects
Commit 2d6e1a87 authored by thl-cmk's avatar thl-cmk :flag_na:
Browse files

adds command line arguments/cahnges logging

parent abf476fb
No related branches found
No related tags found
No related merge requests found
...@@ -11,5 +11,5 @@ ...@@ -11,5 +11,5 @@
2023-01-27: added default IOS/IOS-XE config file fallback 2023-01-27: added default IOS/IOS-XE config file fallback
2023-01-28: moved global variables to Settings class 2023-01-28: moved global variables to Settings class
integrated status_debug.html with status.html integrated status_debug.html with status.html
2023-01-29 rework of status page, make table body scrollable 2023-01-29: rework of status page, make table body scrollable
2023-02-01: added cli options, changed debug/log output
...@@ -102,7 +102,7 @@ You can check if the PnP server is running by opening a web browser and accessin ...@@ -102,7 +102,7 @@ You can check if the PnP server is running by opening a web browser and accessin
to use the PnP server you need to configure the server by modifying the following files to use the PnP server you need to configure the server by modifying the following files
- [**_settings.toml_**](/pnp/open-pnp.toml) - [**_open-pnp.toml_**](/pnp/open-pnp.toml)
- [**_images.toml_**](/pnp/images.toml) - [**_images.toml_**](/pnp/images.toml)
**NOTE:** after changing the PnP server configuration you need to restart the PnP server. **NOTE:** after changing the PnP server configuration you need to restart the PnP server.
...@@ -113,28 +113,28 @@ to use the PnP server you need to configure the server by modifying the followin ...@@ -113,28 +113,28 @@ to use the PnP server you need to configure the server by modifying the followin
#### Global settings [**open-pnp.toml**](/pnp/open-pnp.toml) #### Global settings [**open-pnp.toml**](/pnp/open-pnp.toml)
``` ```
# BIND_PNP_SERVER = "0.0.0.0" # bind_pnp_server = "0.0.0.0"
# PORT = 8080 # port = 8080
# TIME_FORMAT = "%Y-%m-%dT%H:%M:%S" # time_format = "%Y-%m-%dT%H:%M:%S"
# STATUS_REFRESH = 60 # status_refresh = 60
# DEBUG = false # debug = false
# LOG_TO_FILE = true # log_to_console = false
# LOG_FILE = "log/pnp_debug.log" # log_file = "log/pnp_debug.log"
# IMAGE_DATA = "images.toml" # image_data = "images.toml"
IMAGE_BASE_URL = "http://192.168.10.133:8080/images" # image_base_url = "http://192.168.10.133:8080/images"
CONFIG_BASE_URL = "http://192.168.10.133:8080/configs" # config_base_url = "http://192.168.10.133:8080/configs"
``` ```
- **BIND_PNP_SERVER**: the IP-address of your open-pnp server box. (Use `"::"` for IPv6) - **bind_pnp_server**: the IP-address of your open-pnp server box. (Use `"::"` for IPv6)
- **PORT**: the TCP port the server should listen on (remember for port 80 the server needs to run as root) - **port**: the TCP port the server should listen on (remember for port 80 the server needs to run as root)
- **TIME_FORMAT**: the time format used in the status page - **time_format**: the time format used in the status page
- **STATUS_REFRESH**: the interval in seconds the status page will automatically reload - **status_refresh**: the interval in seconds the status page will automatically reload
- **DEBUG**: enable debug output with `DEBUG = true`. Can be `true` or `false`. - **debug**: enable debug output with `debug = true`. Can be `true` or `false`.
- **LOG_FILE**: path/name of the log file - **log_file**: path/name of the log file
- **LOG_TO_FILE**: write log output to file. Can be `true` or `false`. - **log_to_console**: send debug output to stdout. Can be `true` or `false`.
- **IMAGE_DATA**: the file containing the data of your IOS/IOS-XE images - **image_data**: the file containing the data of your IOS/IOS-XE images
- **IMAGE_BASE_URL**: the base URL for your images - **image_base_url**: the base URL for your images
- **CONFIG_BASE_URL**: the base URL for your configuration files - **config_base_url**: the base URL for your configuration files
**Note**: you need to uncomment (remove `# `) the lines if you change the values. **Note**: you need to uncomment (remove `# `) the lines if you change the values.
...@@ -157,7 +157,58 @@ models = ["C1000-8T-2G-L", "C1000-24P-4G-L", "C1000-24T-4G-L", "C1000-24T-4X-L", ...@@ -157,7 +157,58 @@ models = ["C1000-8T-2G-L", "C1000-24P-4G-L", "C1000-24T-4G-L", "C1000-24T-4X-L",
``` ```
**NOTE:** By default _open-pnp_ expects the image data in _images.json_. You can change this with the key _IMAGE_DATA_ in _settings.ini_. **NOTE:** By default _open-pnp_ expects the image data in _images.toml_. You can change this with the key _image_data_ in _open-pnp.toml_.
---
### Command Line Options
With the Command Line Options you can override the default values, and the values from the _open-pnp.toml_ config file.
With the option --config_file CONFIG_FILE you can specify a costume config file to use instead of _open.pnp.toml_.
```
$ ./open-pnp.py -h
usage: open-pnp.py [-h] [--bind_pnp_server BIND_PNP_SERVER] [--port PORT]
[--time_format TIME_FORMAT]
[--status_refresh STATUS_REFRESH] [--debug]
[--log_to_console] [--log_file LOG_FILE]
[--image_data IMAGE_DATA] [--image_url IMAGE_URL]
[--config_url CONFIG_URL] [--config_file CONFIG_FILE]
This is a basic implementation of the Cisco PnP protocol. It is intended to
roll out image updates and configurations for Cisco IOS/IOS-XE devices on
day0.
optional arguments:
-h, --help show this help message and exit
--bind_pnp_server BIND_PNP_SERVER, -b BIND_PNP_SERVER
Bind PnP server to IP-address. (default: 0.0.0.0)
--port PORT, -p PORT TCP port to listen on. (default: 8080)
--time_format TIME_FORMAT
Format string to render time. (default:
%Y-%m-%dT%H:%M:%S)
--status_refresh STATUS_REFRESH, -r STATUS_REFRESH
Time in seconds to refresh PnP server status page.
(default: 60)
--debug Enable Debug output send to "log_file".
--log_to_console Enable debug output send to stdout (requires --debug).
--log_file LOG_FILE Path/name of the logfile. (default: log/pnp_debug.log,
requires --debug)
--image_data IMAGE_DATA
File containing the image description. (default:
images.toml)
--image_url IMAGE_URL
Download URL for image files. I.e.
http://192.168.10.133:8080/images
--config_url CONFIG_URL
Download URL for config files. I.e.
http://192.168.10.133:8080/configs
--config_file CONFIG_FILE
Path/name of open PnP server config file. (default:
open-pnp.toml)
Written by: thl-cmk, for more information see: https://thl-cmk.hopto.org
```
--- ---
### PnP server discovery ### PnP server discovery
......
...@@ -20,7 +20,7 @@ models = ["C1000-8T-2G-L", "C1000-24P-4G-L", "C1000-24T-4G-L", "C1000-24T-4X-L", ...@@ -20,7 +20,7 @@ models = ["C1000-8T-2G-L", "C1000-24P-4G-L", "C1000-24T-4G-L", "C1000-24T-4X-L",
version = "16.12.1a" version = "16.12.1a"
md5 = "045d73625025b4f77c65c7800b7faa2b" md5 = "045d73625025b4f77c65c7800b7faa2b"
size = 541469788 size = 541469788
models = ["C1117-4PMLTEEAWE"] models = []
["c1100-universalk9.17.06.04.SPA.bin"] ["c1100-universalk9.17.06.04.SPA.bin"]
version = "17.6.4" version = "17.6.4"
...@@ -32,7 +32,7 @@ models = [] ...@@ -32,7 +32,7 @@ models = []
version = "17.10.1a" version = "17.10.1a"
md5 = "a0cd6218c42f19bed425e3c63a11bcda" md5 = "a0cd6218c42f19bed425e3c63a11bcda"
size = 689542648 size = 689542648
models = [] models = ["C1117-4PMLTEEAWE"]
["c3560cx-universalk9-mz.152-7.E7.bin"] ["c3560cx-universalk9-mz.152-7.E7.bin"]
version = "15.2(7)E7" version = "15.2(7)E7"
......
...@@ -27,10 +27,12 @@ ...@@ -27,10 +27,12 @@
# 2023-01-27: added default IOS/IOS-XE config file fallback # 2023-01-27: added default IOS/IOS-XE config file fallback
# 2023-01-28: moved global variables to Settings class # 2023-01-28: moved global variables to Settings class
# integrated status_debug.html with status.html # integrated status_debug.html with status.html
# 2023-01-29 rework of status page, make table body scrollable # 2023-01-29: rework of status page, make table body scrollable
# 2023-02-01: added cli options, changed debug/log output
#
# pip install flask xmltodict requests ifaddr tomli # pip install flask xmltodict requests ifaddr tomli
# pip install python-dotenv # for vscode #
import logging import logging
from logging.handlers import RotatingFileHandler from logging.handlers import RotatingFileHandler
from re import compile as re_compile from re import compile as re_compile
...@@ -38,6 +40,8 @@ from pathlib import Path ...@@ -38,6 +40,8 @@ from pathlib import Path
from time import strftime from time import strftime
from typing import Optional, List, Dict, Any from typing import Optional, List, Dict, Any
from requests import head from requests import head
from sys import stdout
import argparse
from flask import Flask, request, send_from_directory, render_template, Response, redirect, cli from flask import Flask, request, send_from_directory, render_template, Response, redirect, cli
from xmltodict import parse as xml_parse from xmltodict import parse as xml_parse
...@@ -60,77 +64,83 @@ class Settings: ...@@ -60,77 +64,83 @@ class Settings:
time_format: Optional[str] = '%Y-%m-%dT%H:%M:%S', time_format: Optional[str] = '%Y-%m-%dT%H:%M:%S',
status_refresh: Optional[int] = 60, status_refresh: Optional[int] = 60,
debug: Optional[bool] = False, debug: Optional[bool] = False,
log_to_file: Optional[bool] = True, log_to_console: Optional[bool] = False,
log_file: Optional[str] = 'log/pnp_debug.log', log_file: Optional[str] = 'log/pnp_debug.log',
image_base_url: Optional[str] = '', image_url: Optional[str] = '',
config_base_url: Optional[str] = '', config_url: Optional[str] = '',
default_cfg_file: Optional[str] = 'DEFAULT.cfg', default_cfg_file: Optional[str] = 'DEFAULT.cfg',
): ):
self.__settings = { self.__settings = {
'CFG_FILE': cfg_file, 'cfg_file': cfg_file,
'IMAGE_DATA': image_data, 'image_data': image_data,
'BIND_PNP_SERVER': bind_pnp_server, 'bind_pnp_server': bind_pnp_server,
'PORT': port, 'port': port,
'TIME_FORMAT': time_format, 'time_format': time_format,
'STATUS_REFRESH': status_refresh, 'status_refresh': status_refresh,
'DEBUG': debug, 'debug': debug,
'LOG_TO_FILE': log_to_file, 'log_to_console': log_to_console,
'LOG_FILE': log_file, 'log_file': log_file,
'IMAGE_BASE_URL': image_base_url, 'image_url': image_url,
'CONFIG_BASE_URL': config_base_url, 'config_url': config_url,
'DEFAULT_CFG_FILE': default_cfg_file, 'default_cfg_file': default_cfg_file,
} }
self.__args = {}
def set_cli_args(self, cli_args: Dict[str, any]):
self.__args = ({k: v for k, v in cli_args.items() if v})
self.__settings.update(self.__args)
def update(self, settings: Dict[str, any]): def update(self, settings: Dict[str, any]):
self.__settings.update(settings) self.__settings.update(settings)
self.__settings.update(self.__args)
@property @property
def cfg_file(self) -> str: def cfg_file(self) -> str:
return self.__settings['CFG_FILE'] return self.__settings['cfg_file']
@property @property
def image_data(self) -> str: def image_data(self) -> str:
return self.__settings['IMAGE_DATA'] return self.__settings['image_data']
@property @property
def bind_pnp_server(self) -> str: def bind_pnp_server(self) -> str:
return self.__settings['BIND_PNP_SERVER'] return self.__settings['bind_pnp_server']
@property @property
def port(self) -> int: def port(self) -> int:
return self.__settings['PORT'] return self.__settings['port']
@property @property
def time_format(self) -> str: def time_format(self) -> str:
return self.__settings['TIME_FORMAT'] return self.__settings['time_format']
@property @property
def status_refresh(self) -> int: def status_refresh(self) -> int:
return self.__settings['STATUS_REFRESH'] return self.__settings['status_refresh']
@property @property
def debug(self) -> bool: def debug(self) -> bool:
return self.__settings['DEBUG'] return self.__settings['debug']
@property @property
def log_to_file(self) -> bool: def log_to_console(self) -> bool:
return self.__settings['LOG_TO_FILE'] return self.__settings['log_to_console']
@property @property
def log_file(self) -> str: def log_file(self) -> str:
return self.__settings['LOG_FILE'] return self.__settings['log_file']
@property @property
def image_base_url(self) -> str: def image_url(self) -> str:
return self.__settings['IMAGE_BASE_URL'] return self.__settings['image_url']
@property @property
def config_base_url(self) -> str: def config_url(self) -> str:
return self.__settings['CONFIG_BASE_URL'] return self.__settings['config_url']
@property @property
def default_cfg_file(self) -> str: def default_cfg_file(self) -> str:
return self.__settings['DEFAULT_CFG_FILE'] return self.__settings['default_cfg_file']
SETTINGS = Settings() SETTINGS = Settings()
...@@ -322,9 +332,12 @@ devices: Dict[str, Device] = {} ...@@ -322,9 +332,12 @@ devices: Dict[str, Device] = {}
def configure_logger(path): def configure_logger(path):
log_formatter = logging.Formatter('%(asctime)s :: %(levelname)s :: %(name)s :: %(module)s ::%(message)s') log_formatter = logging.Formatter('%(asctime)s :: %(levelname)s :: %(name)s :: %(module)s ::%(message)s')
log = logging.getLogger('root')
log.setLevel(logging.INFO)
log_file = path log_file = path
# create a new file > 5 mb size # create a new file > 5 mb size
log_handler = RotatingFileHandler( log_handler_file = RotatingFileHandler(
log_file, log_file,
mode='a', mode='a',
maxBytes=5 * 1024 * 1024, maxBytes=5 * 1024 * 1024,
...@@ -332,25 +345,28 @@ def configure_logger(path): ...@@ -332,25 +345,28 @@ def configure_logger(path):
# encoding=None, # encoding=None,
# delay=0 # delay=0
) )
log_handler.setFormatter(log_formatter)
log_handler.setLevel(logging.INFO) log_handler_file.setFormatter(log_formatter)
log = logging.getLogger('root') log_handler_file.setLevel(logging.INFO)
log.setLevel(logging.INFO) log.addHandler(log_handler_file)
log.addHandler(log_handler)
if SETTINGS.log_to_console:
log_handler_console = logging.StreamHandler(stdout)
log_handler_console.setFormatter(log_formatter)
log_handler_console.setLevel(logging.INFO)
log.addHandler(log_handler_console)
def log_info(message): def log_info(message):
if SETTINGS.debug: if SETTINGS.debug:
if SETTINGS.log_to_file: log = logging.getLogger('root')
log = logging.getLogger('root') log.info(message)
log.info(message)
def log_critical(message): def log_critical(message):
if SETTINGS.debug: if SETTINGS.debug:
if SETTINGS.log_to_file: log = logging.getLogger('root')
log = logging.getLogger('root') log.critical(message)
log.critical(message)
def load_data(): def load_data():
...@@ -378,6 +394,40 @@ def load_data(): ...@@ -378,6 +394,40 @@ def load_data():
exit(2) exit(2)
def parse_arguments() -> argparse.Namespace:
parser = argparse.ArgumentParser(
prog='open-pnp.py',
description='This is a basic implementation of the Cisco PnP protocol. It is intended to roll out image updates'
' and configurations for Cisco IOS/IOS-XE devices on day0.',
# formatter_class=argparse.ArgumentDefaultsHelpFormatter,
epilog='Written by: thl-cmk, for more information see: https://thl-cmk.hopto.org',
)
parser.add_argument('--bind_pnp_server', '-b', type=str,
help='Bind PnP server to IP-address. (default: 0.0.0.0)')
parser.add_argument('--port', '-p', type=int,
help='TCP port to listen on. (default: 8080)')
parser.add_argument('--time_format', type=str,
help='Format string to render time. (default: %%Y-%%m-%%dT%%H:%%M:%%S)')
parser.add_argument('--status_refresh', '-r', type=int,
help='Time in seconds to refresh PnP server status page. (default: 60)')
parser.add_argument('--debug', default=False, action="store_const", const=True,
help='Enable Debug output send to "log_file".')
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('--log_file', type=str,
help='Path/name of the logfile. (default: log/pnp_debug.log, requires --debug) ')
parser.add_argument('--image_data', type=str,
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('--config_url', type=str,
help='Download URL for config files. I.e. http://192.168.10.133:8080/configs')
parser.add_argument('--config_file', type=str,
help='Path/name of open PnP server config file. (default: open-pnp.toml)')
return parser.parse_args()
def pnp_device_info(udi: str, correlator: str, info_type: str) -> str: def pnp_device_info(udi: str, correlator: str, info_type: str) -> str:
# info_type can be one of: # info_type can be one of:
# image, hardware, filesystem, udi, profile, all # image, hardware, filesystem, udi, profile, all
...@@ -430,7 +480,7 @@ def pnp_backoff_terminate(udi: str, correlator: str) -> str: ...@@ -430,7 +480,7 @@ def pnp_backoff_terminate(udi: str, correlator: str) -> str:
def pnp_install_image(udi: str, correlator: str) -> Optional[str]: def pnp_install_image(udi: str, correlator: str) -> Optional[str]:
device = devices[udi] device = devices[udi]
response = head(f'{SETTINGS.image_base_url}/{device.target_image.image}') response = head(f'{SETTINGS.image_url}/{device.target_image.image}')
if response.status_code == 200: if response.status_code == 200:
device.current_job = 'urn:cisco:pnp:image-install' device.current_job = 'urn:cisco:pnp:image-install'
device.pnp_flow = PNPFLOW.UPDATE_START device.pnp_flow = PNPFLOW.UPDATE_START
...@@ -439,7 +489,7 @@ def pnp_install_image(udi: str, correlator: str) -> Optional[str]: ...@@ -439,7 +489,7 @@ def pnp_install_image(udi: str, correlator: str) -> Optional[str]:
jinja_context = { jinja_context = {
'udi': udi, 'udi': udi,
'correlator': correlator, 'correlator': correlator,
'base_url': SETTINGS.image_base_url, 'base_url': SETTINGS.image_url,
'image': device.target_image.image, 'image': device.target_image.image,
'md5': device.target_image.md5.lower(), 'md5': device.target_image.md5.lower(),
'destination': device.destination_name, 'destination': device.destination_name,
...@@ -456,10 +506,10 @@ def pnp_install_image(udi: str, correlator: str) -> Optional[str]: ...@@ -456,10 +506,10 @@ def pnp_install_image(udi: str, correlator: str) -> Optional[str]:
def pnp_config_upgrade(udi: str, correlator: str) -> Optional[str]: def pnp_config_upgrade(udi: str, correlator: str) -> Optional[str]:
device = devices[udi] device = devices[udi]
cfg_file = f'{device.serial}.cfg' cfg_file = f'{device.serial}.cfg'
response = head(f'{SETTINGS.config_base_url}/{cfg_file}') response = head(f'{SETTINGS.config_url}/{cfg_file}')
if response.status_code != 200: # SERIAL.cfg not found if response.status_code != 200: # SERIAL.cfg not found
cfg_file = SETTINGS.default_cfg_file cfg_file = SETTINGS.default_cfg_file
response = head(f'{SETTINGS.config_base_url}/{cfg_file}') response = head(f'{SETTINGS.config_url}/{cfg_file}')
if response.status_code != 200: # DEFAULT.cfg also not found if response.status_code != 200: # DEFAULT.cfg also not found
device.error_code = ERROR.ERROR_NO_CFG_FILE device.error_code = ERROR.ERROR_NO_CFG_FILE
device.hard_error = True device.hard_error = True
...@@ -470,7 +520,7 @@ def pnp_config_upgrade(udi: str, correlator: str) -> Optional[str]: ...@@ -470,7 +520,7 @@ def pnp_config_upgrade(udi: str, correlator: str) -> Optional[str]:
jinja_context = { jinja_context = {
'udi': udi, 'udi': udi,
'correlator': correlator, 'correlator': correlator,
'base_url': SETTINGS.config_base_url, 'base_url': SETTINGS.config_url,
'serial_number': cfg_file, 'serial_number': cfg_file,
'delay': 30, # reload in seconds 'delay': 30, # reload in seconds
'cfg_file': cfg_file, 'cfg_file': cfg_file,
...@@ -575,8 +625,8 @@ def status(): ...@@ -575,8 +625,8 @@ def status():
jinja_context = { jinja_context = {
'devices': device_list, 'devices': device_list,
'refresh': SETTINGS.status_refresh, 'refresh': SETTINGS.status_refresh,
'config_base_url': SETTINGS.config_base_url, 'config_url': SETTINGS.config_url,
'image_base_url': SETTINGS.image_base_url, 'image_url': SETTINGS.image_url,
'debug': SETTINGS.debug, 'debug': SETTINGS.debug,
} }
result = render_template('status.html', **jinja_context) result = render_template('status.html', **jinja_context)
...@@ -726,13 +776,15 @@ def pnp_work_response(): ...@@ -726,13 +776,15 @@ def pnp_work_response():
if __name__ == '__main__': if __name__ == '__main__':
SETTINGS.set_cli_args(vars(parse_arguments()))
load_data() load_data()
if SETTINGS.image_base_url == '': if SETTINGS.image_url == '':
print('IMAGE_BASE_URL not set, check ./vars/vars.py') print(f'image_url not set, check {SETTINGS.cfg_file}')
exit(1) exit(1)
if SETTINGS.config_base_url == '': if SETTINGS.config_url == '':
print('CONFIG_BASE_URL not set, check ./vars/vars.py') print(f'config_url not set, check {SETTINGS.cfg_file}')
exit(1) exit(1)
if SETTINGS.debug: if SETTINGS.debug:
...@@ -740,11 +792,12 @@ if __name__ == '__main__': ...@@ -740,11 +792,12 @@ if __name__ == '__main__':
log_info('STARTED LOGGER') log_info('STARTED LOGGER')
print() print()
print('Running PnP server. Stop with ctrl+c') print(f'Running open PnP server. Stop with ctrl+c')
print()
print(f'Bind to IP-address : {SETTINGS.bind_pnp_server}') print(f'Bind to IP-address : {SETTINGS.bind_pnp_server}')
print(f'Listen on port : {SETTINGS.port}') print(f'Listen on port : {SETTINGS.port}')
print(f'Image file(s) base URL : {SETTINGS.image_base_url}') print(f'Image file(s) base URL : {SETTINGS.image_url}')
print(f'Config file(s) base URL : {SETTINGS.config_base_url}') print(f'Config file(s) base URL : {SETTINGS.config_url}')
print() print()
print('The PnP server is running on the following URL(s)') print('The PnP server is running on the following URL(s)')
if SETTINGS.bind_pnp_server in ['0.0.0.0', '::']: if SETTINGS.bind_pnp_server in ['0.0.0.0', '::']:
...@@ -754,5 +807,6 @@ if __name__ == '__main__': ...@@ -754,5 +807,6 @@ if __name__ == '__main__':
else: else:
print(f'Status page running on : http://{SETTINGS.bind_pnp_server}:{SETTINGS.port}') print(f'Status page running on : http://{SETTINGS.bind_pnp_server}:{SETTINGS.port}')
print() print()
print(f'Writen by thl-cmk, see https://thl-cmk.hopto.org/gitlab/bits-and-bytes/cisco_day0_provision')
print() print()
app.run(host=SETTINGS.bind_pnp_server, port=SETTINGS.port) app.run(host=SETTINGS.bind_pnp_server, port=SETTINGS.port)
# [settings] # [settings]
# BIND_PNP_SERVER = "0.0.0.0" # bind_pnp_server = "0.0.0.0"
# BIND_PNP_SERVER = "::" # bind_pnp_server = "::"
# PORT = 8080 # port = 8080
# TIME_FORMAT = "%Y-%m-%dT%H:%M:%S" # time_format = "%y-%m-%dt%h:%m:%s"
STATUS_REFRESH = 10 status_refresh = 10
# DEBUG = false # debug = false
# LOG_TO_FILE = true # log_to_file = true
# LOG_FILE = "log/pnp_debug.log" # log_file = "log/pnp_debug.log"
# DEFAULT_CFG_FILE = "DEFAULT.cfg" # default_cfg_file = "default.cfg"
# IMAGE_DATA = "images.json" # image_data = "images.toml"
IMAGE_BASE_URL = "http://192.168.10.133:8080/images" image_url = "http://192.168.10.133:8080/images"
CONFIG_BASE_URL = "http://192.168.10.133:8080/configs" config_url = "http://192.168.10.133:8080/configs"
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
<meta http-equiv="refresh" content="{{ refresh }}"> <meta http-equiv="refresh" content="{{ refresh }}">
<style> <style>
body { body {
border-collapse: collapse;
background-color: rgb(141, 133, 133); background-color: rgb(141, 133, 133);
padding:0px; padding:0px;
margin:0px; margin:0px;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment