aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ansible/group_vars/front-test.yml3
-rw-r--r--ansible/inventory-localhost1
-rw-r--r--ansible/playbook-test.yml4
-rw-r--r--ansible/roles/basics/tasks/main.yml7
-rw-r--r--ansible/roles/test/tasks/main.yml3
-rw-r--r--build/test/gondul-db-test.Dockerfile1
-rw-r--r--build/test/postgresql.conf616
-rw-r--r--build/test/snmpd.conf1
-rwxr-xr-xcollectors/ping.pl28
-rwxr-xr-xcollectors/snmpfetchng.pl27
-rw-r--r--extras/dx16-rows40
-rwxr-xr-xextras/fap/# DEPRECATED/database/README.md (renamed from extras/fap/database/README.md)0
-rwxr-xr-xextras/fap/# DEPRECATED/httpd/# DEPRECATED/server_http.py (renamed from extras/fap/httpd/# DEPRECATED/server_http.py)0
-rwxr-xr-xextras/fap/# DEPRECATED/httpd/# DEPRECATED/terminal.log (renamed from extras/fap/httpd/# DEPRECATED/terminal.log)0
-rw-r--r--extras/fap/# DEPRECATED/httpd/httpd_root/# create_queries - DEPRECATED/create_queries.php (renamed from extras/fap/httpd/httpd_root/# create_queries - DEPRECATED/create_queries.php)0
-rw-r--r--extras/fap/# DEPRECATED/httpd/httpd_root/# create_queries - DEPRECATED/ipcalc_functions.php (renamed from extras/fap/httpd/httpd_root/# create_queries - DEPRECATED/ipcalc_functions.php)0
-rw-r--r--extras/fap/# DEPRECATED/httpd/httpd_root/# create_queries - DEPRECATED/patchlist.txt (renamed from extras/fap/httpd/httpd_root/# create_queries - DEPRECATED/patchlist.txt)0
-rw-r--r--extras/fap/# DEPRECATED/httpd/httpd_root/# create_queries - DEPRECATED/switches.txt (renamed from extras/fap/httpd/httpd_root/# create_queries - DEPRECATED/switches.txt)0
-rwxr-xr-x[-rw-r--r--]extras/fap/README.md5
-rw-r--r--extras/fap/dhcpd/README.md9
-rwxr-xr-xextras/fap/dhcpd/module_lease.py78
-rwxr-xr-xextras/fap/dhcpd/server_dhcp.py27
-rwxr-xr-xextras/fap/httpd/README.md3
-rwxr-xr-xextras/fap/httpd/httpd_root/.htaccess4
-rwxr-xr-xextras/fap/httpd/httpd_root/ex2200.template150
-rwxr-xr-xextras/fap/httpd/httpd_root/ex2200_secure.template206
-rwxr-xr-xextras/fap/httpd/httpd_root/index.php (renamed from extras/fap/httpd/httpd_root/x.php)26
-rw-r--r--extras/fap/httpd/httpd_root/pg_connect.php2
-rw-r--r--extras/fap/httpd/httpd_root/tools/patchlist.txt131
-rw-r--r--extras/fap/httpd/httpd_root/tools/switches.txt131
-rw-r--r--extras/fap/httpd/httpd_root/tools/update_psql_from_switches_patchlist.php79
-rw-r--r--extras/fap/tools_temp/README.md3
-rwxr-xr-xextras/tools/make_switches.json.sh46
-rwxr-xr-xinclude/config.pm1
-rwxr-xr-xinclude/nms.pm2
-rw-r--r--include/nms/dbconfig.pm29
-rw-r--r--include/nms/oplog.pm34
-rw-r--r--include/nms/util.pm74
-rwxr-xr-xinclude/nms/web.pm2
-rwxr-xr-xweb/api/public/config3
-rwxr-xr-xweb/api/public/ping20
-rwxr-xr-xweb/api/read/switches-management2
-rwxr-xr-xweb/api/write/linknet-add32
-rwxr-xr-xweb/api/write/oplog2
-rwxr-xr-xweb/api/write/switch-add4
-rw-r--r--web/css/nms.css77
-rw-r--r--web/img/dx16-salkart.pngbin0 -> 96596 bytes
-rw-r--r--web/index.html168
-rw-r--r--web/js/nms-admin-pane.js19
-rw-r--r--web/js/nms-color-util.js48
-rw-r--r--web/js/nms-data.js3
-rw-r--r--web/js/nms-info-box.js298
-rw-r--r--web/js/nms-map-handlers.js336
-rw-r--r--web/js/nms-map.js34
-rw-r--r--web/js/nms-oplog.js48
-rw-r--r--web/js/nms-search.js159
-rw-r--r--web/js/nms-time.js150
-rw-r--r--web/js/nms.js364
58 files changed, 2498 insertions, 1042 deletions
diff --git a/ansible/group_vars/front-test.yml b/ansible/group_vars/front-test.yml
new file mode 100644
index 0000000..33d5011
--- /dev/null
+++ b/ansible/group_vars/front-test.yml
@@ -0,0 +1,3 @@
+---
+front_ports: [ "80:80" ]
+varnish_ports: []
diff --git a/ansible/inventory-localhost b/ansible/inventory-localhost
index 2302eda..7cc7a20 100644
--- a/ansible/inventory-localhost
+++ b/ansible/inventory-localhost
@@ -1 +1,2 @@
+[front-test]
localhost ansible_connection=local
diff --git a/ansible/playbook-test.yml b/ansible/playbook-test.yml
index c2a8aa5..f110435 100644
--- a/ansible/playbook-test.yml
+++ b/ansible/playbook-test.yml
@@ -11,10 +11,10 @@
ports: []
- name: "gondul-front-test"
links: [ "gondul-db-test:db" ]
- ports: []
+ ports: "{{ front_ports }}"
- name: "gondul-varnish-test"
links: [ "gondul-front-test:gondul-front" ]
- ports: []
+ ports: "{{ varnish_ports }}"
- name: "gondul-collector-test"
links: [ "gondul-db-test:db" ]
ports: []
diff --git a/ansible/roles/basics/tasks/main.yml b/ansible/roles/basics/tasks/main.yml
index 4037906..5dd5b5d 100644
--- a/ansible/roles/basics/tasks/main.yml
+++ b/ansible/roles/basics/tasks/main.yml
@@ -1,5 +1,9 @@
- command: pwd
register: pwd
+ tags:
+ - build
+ - start
+ - test
- name: make all
docker_image:
state: build
@@ -40,15 +44,18 @@
register: ip
tags:
- start
+ - test
- name: workaround to get gondul-front-ip
shell: "docker inspect gondul-front-test | grep IPAddress | sed 's/[^0-9.]//g' | grep 172.17 | uniq"
register: ipfront
tags:
- start
+ - test
- name: Display IP
tags:
- start
+ - test
debug:
msg: "Varnish test is available at http://{{ ip.stdout }}/ uncached ip: http://{{ ipfront.stdout }}/ "
diff --git a/ansible/roles/test/tasks/main.yml b/ansible/roles/test/tasks/main.yml
index 7bcf1c4..92eedb1 100644
--- a/ansible/roles/test/tasks/main.yml
+++ b/ansible/roles/test/tasks/main.yml
@@ -28,5 +28,6 @@
body_format: json
user: demo
password: demo
- body: "{{[ { 'sysname': 'foobar1', 'mgmt_v4_addr': '127.0.0.1' }, { 'sysname': 'foobar2', 'mgmt_v4_addr': '127.0.0.1' }, { 'sysname': 'foobar3', 'mgmt_v4_addr': '127.0.0.1' }, { 'sysname': 'foobar4', 'mgmt_v4_addr': '127.0.0.1' }, { 'sysname': 'foobar5', 'mgmt_v4_addr': '127.0.0.1' }, { 'sysname': 'foobar6', 'mgmt_v4_addr': '127.0.0.1' }, { 'sysname': 'foobar7', 'mgmt_v4_addr': '127.0.0.1' }, { 'sysname': 'foobar8', 'mgmt_v4_addr': '127.0.0.1' }, { 'sysname': 'foobar9', 'mgmt_v4_addr': '127.0.0.1' }, { 'sysname': 'foobar10', 'mgmt_v4_addr': '127.0.0.1' }, { 'sysname': 'foobar11', 'mgmt_v4_addr': '127.0.0.1' }, { 'sysname': 'foobar12', 'mgmt_v4_addr': '127.0.0.1' }, { 'sysname': 'foobar13', 'mgmt_v4_addr': '127.0.0.1' }, { 'sysname': 'foobar14', 'mgmt_v4_addr': '127.0.0.1' }, { 'sysname': 'foobar15', 'mgmt_v4_addr': '127.0.0.1' }, { 'sysname': 'foobar16', 'mgmt_v4_addr': '127.0.0.1' }, { 'sysname': 'foobar17', 'mgmt_v4_addr': '127.0.0.1' }, { 'sysname': 'foobar18', 'mgmt_v4_addr': '127.0.0.1' }, { 'sysname': 'foobar19', 'mgmt_v4_addr': '127.0.0.1' }]}}"
+ body: '[{"mgmt_v4_addr":"127.0.0.1","sysname":"core"},{"distro_name":"core","mgmt_v4_addr":"127.0.0.2","sysname":"distro0"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.3","sysname":"row1-1"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.4","sysname":"row1-2"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.5","sysname":"row3-1"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.6","sysname":"row3-2"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.7","sysname":"row5-1"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.8","sysname":"row5-2"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.9","sysname":"row7-1"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.10","sysname":"row7-2"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.11","sysname":"row9-1"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.12","sysname":"row9-2"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.14","sysname":"row11-1"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.15","sysname":"row11-2"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.16","sysname":"row13-1"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.17","sysname":"row13-2"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.18","sysname":"row15-1"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.19","sysname":"row15-2"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.20","sysname":"row17-1"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.21","sysname":"row17-2"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.22","sysname":"row19-1"},{"distro_name":"distro0","mgmt_v4_addr":"127.0.0.23","sysname":"row19-2"},{"distro_name":"core","mgmt_v4_addr":"127.0.0.24","sysname":"distro1"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.25","sysname":"row21-1"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.26","sysname":"row21-2"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.27","sysname":"row23-1"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.28","sysname":"row23-2"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.29","sysname":"row25-1"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.30","sysname":"row25-2"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.31","sysname":"row27-1"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.32","sysname":"row27-2"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.33","sysname":"row29-1"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.34","sysname":"row29-2"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.36","sysname":"row31-1"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.37","sysname":"row31-2"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.38","sysname":"row33-1"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.39","sysname":"row33-2"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.40","sysname":"row35-1"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.41","sysname":"row35-2"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.42","sysname":"row37-1"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.43","sysname":"row37-2"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.44","sysname":"row39-1"},{"distro_name":"distro1","mgmt_v4_addr":"127.0.0.45","sysname":"row39-2"},{"distro_name":"core","mgmt_v4_addr":"127.0.0.46","sysname":"noc"}]'
+
diff --git a/build/test/gondul-db-test.Dockerfile b/build/test/gondul-db-test.Dockerfile
index 2e0e0ce..b3d013b 100644
--- a/build/test/gondul-db-test.Dockerfile
+++ b/build/test/gondul-db-test.Dockerfile
@@ -5,6 +5,7 @@ RUN cat /pg_hba.tail >> /etc/postgresql/9.4/main/pg_hba.conf
RUN service postgresql start && su postgres -c "psql --command=\"CREATE ROLE nms PASSWORD 'risbrod' NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN;\"" && su postgres -c "createdb -O nms nms" && service postgresql stop
ADD build/schema.sql /schema.sql
RUN service postgresql start && su postgres -c "cat /schema.sql | psql nms" && service postgresql stop
+ADD build/test/postgresql.conf /etc/postgresql/9.4/main/postgresql.conf
RUN echo "listen_addresses = '*'" >> /etc/postgresql/9.4/main/postgresql.conf
CMD pg_ctlcluster --foreground 9.4 main start
EXPOSE 5432
diff --git a/build/test/postgresql.conf b/build/test/postgresql.conf
new file mode 100644
index 0000000..d7947c9
--- /dev/null
+++ b/build/test/postgresql.conf
@@ -0,0 +1,616 @@
+# -----------------------------
+# PostgreSQL configuration file
+# -----------------------------
+#
+# This file consists of lines of the form:
+#
+# name = value
+#
+# (The "=" is optional.) Whitespace may be used. Comments are introduced with
+# "#" anywhere on a line. The complete list of parameter names and allowed
+# values can be found in the PostgreSQL documentation.
+#
+# The commented-out settings shown in this file represent the default values.
+# Re-commenting a setting is NOT sufficient to revert it to the default value;
+# you need to reload the server.
+#
+# This file is read on server startup and when the server receives a SIGHUP
+# signal. If you edit the file on a running system, you have to SIGHUP the
+# server for the changes to take effect, or use "pg_ctl reload". Some
+# parameters, which are marked below, require a server shutdown and restart to
+# take effect.
+#
+# Any parameter can also be given as a command-line option to the server, e.g.,
+# "postgres -c log_connections=on". Some parameters can be changed at run time
+# with the "SET" SQL command.
+#
+# Memory units: kB = kilobytes Time units: ms = milliseconds
+# MB = megabytes s = seconds
+# GB = gigabytes min = minutes
+# TB = terabytes h = hours
+# d = days
+
+
+#------------------------------------------------------------------------------
+# FILE LOCATIONS
+#------------------------------------------------------------------------------
+
+# The default values of these variables are driven from the -D command-line
+# option or PGDATA environment variable, represented here as ConfigDir.
+
+data_directory = '/var/lib/postgresql/9.4/main' # use data in another directory
+ # (change requires restart)
+hba_file = '/etc/postgresql/9.4/main/pg_hba.conf' # host-based authentication file
+ # (change requires restart)
+ident_file = '/etc/postgresql/9.4/main/pg_ident.conf' # ident configuration file
+ # (change requires restart)
+
+# If external_pid_file is not explicitly set, no extra PID file is written.
+external_pid_file = '/var/run/postgresql/9.4-main.pid' # write an extra PID file
+ # (change requires restart)
+
+
+#------------------------------------------------------------------------------
+# CONNECTIONS AND AUTHENTICATION
+#------------------------------------------------------------------------------
+
+# - Connection Settings -
+
+#listen_addresses = 'localhost' # what IP address(es) to listen on;
+ # comma-separated list of addresses;
+ # defaults to 'localhost'; use '*' for all
+ # (change requires restart)
+port = 5432 # (change requires restart)
+max_connections = 100 # (change requires restart)
+# Note: Increasing max_connections costs ~400 bytes of shared memory per
+# connection slot, plus lock space (see max_locks_per_transaction).
+#superuser_reserved_connections = 3 # (change requires restart)
+unix_socket_directories = '/var/run/postgresql' # comma-separated list of directories
+ # (change requires restart)
+#unix_socket_group = '' # (change requires restart)
+#unix_socket_permissions = 0777 # begin with 0 to use octal notation
+ # (change requires restart)
+#bonjour = off # advertise server via Bonjour
+ # (change requires restart)
+#bonjour_name = '' # defaults to the computer name
+ # (change requires restart)
+
+# - Security and Authentication -
+
+#authentication_timeout = 1min # 1s-600s
+ssl = true # (change requires restart)
+#ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed SSL ciphers
+ # (change requires restart)
+#ssl_prefer_server_ciphers = on # (change requires restart)
+#ssl_ecdh_curve = 'prime256v1' # (change requires restart)
+#ssl_renegotiation_limit = 0 # amount of data between renegotiations
+ssl_cert_file = '/etc/ssl/certs/ssl-cert-snakeoil.pem' # (change requires restart)
+ssl_key_file = '/etc/ssl/private/ssl-cert-snakeoil.key' # (change requires restart)
+#ssl_ca_file = '' # (change requires restart)
+#ssl_crl_file = '' # (change requires restart)
+#password_encryption = on
+#db_user_namespace = off
+
+# GSSAPI using Kerberos
+#krb_server_keyfile = ''
+#krb_caseins_users = off
+
+# - TCP Keepalives -
+# see "man 7 tcp" for details
+
+#tcp_keepalives_idle = 0 # TCP_KEEPIDLE, in seconds;
+ # 0 selects the system default
+#tcp_keepalives_interval = 0 # TCP_KEEPINTVL, in seconds;
+ # 0 selects the system default
+#tcp_keepalives_count = 0 # TCP_KEEPCNT;
+ # 0 selects the system default
+
+
+#------------------------------------------------------------------------------
+# RESOURCE USAGE (except WAL)
+#------------------------------------------------------------------------------
+
+# - Memory -
+
+shared_buffers = 1024MB # min 128kB
+ # (change requires restart)
+#huge_pages = try # on, off, or try
+ # (change requires restart)
+temp_buffers = 64MB # min 800kB
+#max_prepared_transactions = 0 # zero disables the feature
+ # (change requires restart)
+# Note: Increasing max_prepared_transactions costs ~600 bytes of shared memory
+# per transaction slot, plus lock space (see max_locks_per_transaction).
+# It is not advisable to set max_prepared_transactions nonzero unless you
+# actively intend to use prepared transactions.
+work_mem = 16MB # min 64kB
+#maintenance_work_mem = 64MB # min 1MB
+#autovacuum_work_mem = -1 # min 1MB, or -1 to use maintenance_work_mem
+#max_stack_depth = 2MB # min 100kB
+dynamic_shared_memory_type = posix # the default is the first option
+ # supported by the operating system:
+ # posix
+ # sysv
+ # windows
+ # mmap
+ # use none to disable dynamic shared memory
+
+# - Disk -
+
+#temp_file_limit = -1 # limits per-session temp file space
+ # in kB, or -1 for no limit
+
+# - Kernel Resource Usage -
+
+#max_files_per_process = 1000 # min 25
+ # (change requires restart)
+#shared_preload_libraries = '' # (change requires restart)
+
+# - Cost-Based Vacuum Delay -
+
+#vacuum_cost_delay = 0 # 0-100 milliseconds
+#vacuum_cost_page_hit = 1 # 0-10000 credits
+#vacuum_cost_page_miss = 10 # 0-10000 credits
+#vacuum_cost_page_dirty = 20 # 0-10000 credits
+#vacuum_cost_limit = 200 # 1-10000 credits
+
+# - Background Writer -
+
+bgwriter_delay = 1000ms # 10-10000ms between rounds
+#bgwriter_lru_maxpages = 100 # 0-1000 max buffers written/round
+#bgwriter_lru_multiplier = 2.0 # 0-10.0 multipler on buffers scanned/round
+
+# - Asynchronous Behavior -
+
+#effective_io_concurrency = 1 # 1-1000; 0 disables prefetching
+#max_worker_processes = 8
+
+
+#------------------------------------------------------------------------------
+# WRITE AHEAD LOG
+#------------------------------------------------------------------------------
+
+# - Settings -
+
+#wal_level = minimal # minimal, archive, hot_standby, or logical
+ # (change requires restart)
+fsync = off # turns forced synchronization on or off
+synchronous_commit = off # synchronization level;
+ # off, local, remote_write, or on
+#wal_sync_method = fsync # the default is the first option
+ # supported by the operating system:
+ # open_datasync
+ # fdatasync (default on Linux)
+ # fsync
+ # fsync_writethrough
+ # open_sync
+#full_page_writes = on # recover from partial page writes
+#wal_log_hints = off # also do full page writes of non-critical updates
+ # (change requires restart)
+#wal_buffers = -1 # min 32kB, -1 sets based on shared_buffers
+ # (change requires restart)
+wal_writer_delay = 1000ms # 1-10000 milliseconds
+
+commit_delay = 10000 # range 0-100000, in microseconds
+commit_siblings = 50 # range 1-1000
+
+# - Checkpoints -
+
+#checkpoint_segments = 3 # in logfile segments, min 1, 16MB each
+#checkpoint_timeout = 5min # range 30s-1h
+#checkpoint_completion_target = 0.5 # checkpoint target duration, 0.0 - 1.0
+#checkpoint_warning = 30s # 0 disables
+
+# - Archiving -
+
+#archive_mode = off # allows archiving to be done
+ # (change requires restart)
+#archive_command = '' # command to use to archive a logfile segment
+ # placeholders: %p = path of file to archive
+ # %f = file name only
+ # e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'
+#archive_timeout = 0 # force a logfile segment switch after this
+ # number of seconds; 0 disables
+
+
+#------------------------------------------------------------------------------
+# REPLICATION
+#------------------------------------------------------------------------------
+
+# - Sending Server(s) -
+
+# Set these on the master and on any standby that will send replication data.
+
+#max_wal_senders = 0 # max number of walsender processes
+ # (change requires restart)
+#wal_keep_segments = 0 # in logfile segments, 16MB each; 0 disables
+#wal_sender_timeout = 60s # in milliseconds; 0 disables
+
+#max_replication_slots = 0 # max number of replication slots
+ # (change requires restart)
+
+# - Master Server -
+
+# These settings are ignored on a standby server.
+
+#synchronous_standby_names = '' # standby servers that provide sync rep
+ # comma-separated list of application_name
+ # from standby(s); '*' = all
+#vacuum_defer_cleanup_age = 0 # number of xacts by which cleanup is delayed
+
+# - Standby Servers -
+
+# These settings are ignored on a master server.
+
+#hot_standby = off # "on" allows queries during recovery
+ # (change requires restart)
+#max_standby_archive_delay = 30s # max delay before canceling queries
+ # when reading WAL from archive;
+ # -1 allows indefinite delay
+#max_standby_streaming_delay = 30s # max delay before canceling queries
+ # when reading streaming WAL;
+ # -1 allows indefinite delay
+#wal_receiver_status_interval = 10s # send replies at least this often
+ # 0 disables
+#hot_standby_feedback = off # send info from standby to prevent
+ # query conflicts
+#wal_receiver_timeout = 60s # time that receiver waits for
+ # communication from master
+ # in milliseconds; 0 disables
+
+
+#------------------------------------------------------------------------------
+# QUERY TUNING
+#------------------------------------------------------------------------------
+
+# - Planner Method Configuration -
+
+#enable_bitmapscan = on
+#enable_hashagg = on
+#enable_hashjoin = on
+#enable_indexscan = on
+#enable_indexonlyscan = on
+#enable_material = on
+#enable_mergejoin = on
+#enable_nestloop = on
+#enable_seqscan = on
+#enable_sort = on
+#enable_tidscan = on
+
+# - Planner Cost Constants -
+
+#seq_page_cost = 1.0 # measured on an arbitrary scale
+#random_page_cost = 4.0 # same scale as above
+#cpu_tuple_cost = 0.01 # same scale as above
+#cpu_index_tuple_cost = 0.005 # same scale as above
+#cpu_operator_cost = 0.0025 # same scale as above
+#effective_cache_size = 4GB
+
+# - Genetic Query Optimizer -
+
+#geqo = on
+#geqo_threshold = 12
+#geqo_effort = 5 # range 1-10
+#geqo_pool_size = 0 # selects default based on effort
+#geqo_generations = 0 # selects default based on effort
+#geqo_selection_bias = 2.0 # range 1.5-2.0
+#geqo_seed = 0.0 # range 0.0-1.0
+
+# - Other Planner Options -
+
+#default_statistics_target = 100 # range 1-10000
+#constraint_exclusion = partition # on, off, or partition
+#cursor_tuple_fraction = 0.1 # range 0.0-1.0
+#from_collapse_limit = 8
+#join_collapse_limit = 8 # 1 disables collapsing of explicit
+ # JOIN clauses
+
+
+#------------------------------------------------------------------------------
+# ERROR REPORTING AND LOGGING
+#------------------------------------------------------------------------------
+
+# - Where to Log -
+
+#log_destination = 'stderr' # Valid values are combinations of
+ # stderr, csvlog, syslog, and eventlog,
+ # depending on platform. csvlog
+ # requires logging_collector to be on.
+
+# This is used when logging to stderr:
+#logging_collector = off # Enable capturing of stderr and csvlog
+ # into log files. Required to be on for
+ # csvlogs.
+ # (change requires restart)
+
+# These are only used if logging_collector is on:
+#log_directory = 'pg_log' # directory where log files are written,
+ # can be absolute or relative to PGDATA
+#log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' # log file name pattern,
+ # can include strftime() escapes
+#log_file_mode = 0600 # creation mode for log files,
+ # begin with 0 to use octal notation
+#log_truncate_on_rotation = off # If on, an existing log file with the
+ # same name as the new log file will be
+ # truncated rather than appended to.
+ # But such truncation only occurs on
+ # time-driven rotation, not on restarts
+ # or size-driven rotation. Default is
+ # off, meaning append to existing files
+ # in all cases.
+#log_rotation_age = 1d # Automatic rotation of logfiles will
+ # happen after that time. 0 disables.
+#log_rotation_size = 10MB # Automatic rotation of logfiles will
+ # happen after that much log output.
+ # 0 disables.
+
+# These are relevant when logging to syslog:
+#syslog_facility = 'LOCAL0'
+#syslog_ident = 'postgres'
+
+# This is only relevant when logging to eventlog (win32):
+#event_source = 'PostgreSQL'
+
+# - When to Log -
+
+#client_min_messages = notice # values in order of decreasing detail:
+ # debug5
+ # debug4
+ # debug3
+ # debug2
+ # debug1
+ # log
+ # notice
+ # warning
+ # error
+
+#log_min_messages = warning # values in order of decreasing detail:
+ # debug5
+ # debug4
+ # debug3
+ # debug2
+ # debug1
+ # info
+ # notice
+ # warning
+ # error
+ # log
+ # fatal
+ # panic
+
+#log_min_error_statement = error # values in order of decreasing detail:
+ # debug5
+ # debug4
+ # debug3
+ # debug2
+ # debug1
+ # info
+ # notice
+ # warning
+ # error
+ # log
+ # fatal
+ # panic (effectively off)
+
+#log_min_duration_statement = -1 # -1 is disabled, 0 logs all statements
+ # and their durations, > 0 logs only
+ # statements running at least this number
+ # of milliseconds
+
+
+# - What to Log -
+
+#debug_print_parse = off
+#debug_print_rewritten = off
+#debug_print_plan = off
+#debug_pretty_print = on
+#log_checkpoints = off
+#log_connections = off
+#log_disconnections = off
+#log_duration = off
+#log_error_verbosity = default # terse, default, or verbose messages
+#log_hostname = off
+log_line_prefix = '%t [%p-%l] %q%u@%d ' # special values:
+ # %a = application name
+ # %u = user name
+ # %d = database name
+ # %r = remote host and port
+ # %h = remote host
+ # %p = process ID
+ # %t = timestamp without milliseconds
+ # %m = timestamp with milliseconds
+ # %i = command tag
+ # %e = SQL state
+ # %c = session ID
+ # %l = session line number
+ # %s = session start timestamp
+ # %v = virtual transaction ID
+ # %x = transaction ID (0 if none)
+ # %q = stop here in non-session
+ # processes
+ # %% = '%'
+ # e.g. '<%u%%%d> '
+#log_lock_waits = off # log lock waits >= deadlock_timeout
+#log_statement = 'none' # none, ddl, mod, all
+#log_temp_files = -1 # log temporary files equal or larger
+ # than the specified size in kilobytes;
+ # -1 disables, 0 logs all temp files
+log_timezone = 'UTC'
+
+
+#------------------------------------------------------------------------------
+# RUNTIME STATISTICS
+#------------------------------------------------------------------------------
+
+# - Query/Index Statistics Collector -
+
+#track_activities = on
+#track_counts = on
+#track_io_timing = off
+#track_functions = none # none, pl, all
+#track_activity_query_size = 1024 # (change requires restart)
+#update_process_title = on
+stats_temp_directory = '/var/run/postgresql/9.4-main.pg_stat_tmp'
+
+
+# - Statistics Monitoring -
+
+#log_parser_stats = off
+#log_planner_stats = off
+#log_executor_stats = off
+#log_statement_stats = off
+
+
+#------------------------------------------------------------------------------
+# AUTOVACUUM PARAMETERS
+#------------------------------------------------------------------------------
+
+#autovacuum = on # Enable autovacuum subprocess? 'on'
+ # requires track_counts to also be on.
+#log_autovacuum_min_duration = -1 # -1 disables, 0 logs all actions and
+ # their durations, > 0 logs only
+ # actions running at least this number
+ # of milliseconds.
+#autovacuum_max_workers = 3 # max number of autovacuum subprocesses
+ # (change requires restart)
+#autovacuum_naptime = 1min # time between autovacuum runs
+#autovacuum_vacuum_threshold = 50 # min number of row updates before
+ # vacuum
+#autovacuum_analyze_threshold = 50 # min number of row updates before
+ # analyze
+#autovacuum_vacuum_scale_factor = 0.2 # fraction of table size before vacuum
+#autovacuum_analyze_scale_factor = 0.1 # fraction of table size before analyze
+#autovacuum_freeze_max_age = 200000000 # maximum XID age before forced vacuum
+ # (change requires restart)
+#autovacuum_multixact_freeze_max_age = 400000000 # maximum multixact age
+ # before forced vacuum
+ # (change requires restart)
+#autovacuum_vacuum_cost_delay = 20ms # default vacuum cost delay for
+ # autovacuum, in milliseconds;
+ # -1 means use vacuum_cost_delay
+#autovacuum_vacuum_cost_limit = -1 # default vacuum cost limit for
+ # autovacuum, -1 means use
+ # vacuum_cost_limit
+
+
+#------------------------------------------------------------------------------
+# CLIENT CONNECTION DEFAULTS
+#------------------------------------------------------------------------------
+
+# - Statement Behavior -
+
+#search_path = '"$user",public' # schema names
+#default_tablespace = '' # a tablespace name, '' uses the default
+#temp_tablespaces = '' # a list of tablespace names, '' uses
+ # only default tablespace
+#check_function_bodies = on
+#default_transaction_isolation = 'read committed'
+#default_transaction_read_only = off
+#default_transaction_deferrable = off
+#session_replication_role = 'origin'
+#statement_timeout = 0 # in milliseconds, 0 is disabled
+#lock_timeout = 0 # in milliseconds, 0 is disabled
+#vacuum_freeze_min_age = 50000000
+#vacuum_freeze_table_age = 150000000
+#vacuum_multixact_freeze_min_age = 5000000
+#vacuum_multixact_freeze_table_age = 150000000
+#bytea_output = 'hex' # hex, escape
+#xmlbinary = 'base64'
+#xmloption = 'content'
+#gin_fuzzy_search_limit = 0
+
+# - Locale and Formatting -
+
+datestyle = 'iso, mdy'
+#intervalstyle = 'postgres'
+timezone = 'UTC'
+#timezone_abbreviations = 'Default' # Select the set of available time zone
+ # abbreviations. Currently, there are
+ # Default
+ # Australia (historical usage)
+ # India
+ # You can create your own file in
+ # share/timezonesets/.
+#extra_float_digits = 0 # min -15, max 3
+#client_encoding = sql_ascii # actually, defaults to database
+ # encoding
+
+# These settings are initialized by initdb, but they can be changed.
+lc_messages = 'C' # locale for system error message
+ # strings
+lc_monetary = 'C' # locale for monetary formatting
+lc_numeric = 'C' # locale for number formatting
+lc_time = 'C' # locale for time formatting
+
+# default configuration for text search
+default_text_search_config = 'pg_catalog.english'
+
+# - Other Defaults -
+
+#dynamic_library_path = '$libdir'
+#local_preload_libraries = ''
+#session_preload_libraries = ''
+
+
+#------------------------------------------------------------------------------
+# LOCK MANAGEMENT
+#------------------------------------------------------------------------------
+
+#deadlock_timeout = 1s
+#max_locks_per_transaction = 64 # min 10
+ # (change requires restart)
+# Note: Each lock table slot uses ~270 bytes of shared memory, and there are
+# max_locks_per_transaction * (max_connections + max_prepared_transactions)
+# lock table slots.
+#max_pred_locks_per_transaction = 64 # min 10
+ # (change requires restart)
+
+
+#------------------------------------------------------------------------------
+# VERSION/PLATFORM COMPATIBILITY
+#------------------------------------------------------------------------------
+
+# - Previous PostgreSQL Versions -
+
+#array_nulls = on
+#backslash_quote = safe_encoding # on, off, or safe_encoding
+#default_with_oids = off
+#escape_string_warning = on
+#lo_compat_privileges = off
+#quote_all_identifiers = off
+#sql_inheritance = on
+#standard_conforming_strings = on
+#synchronize_seqscans = on
+
+# - Other Platforms and Clients -
+
+#transform_null_equals = off
+
+
+#------------------------------------------------------------------------------
+# ERROR HANDLING
+#------------------------------------------------------------------------------
+
+#exit_on_error = off # terminate session on any error?
+#restart_after_crash = on # reinitialize after backend crash?
+
+
+#------------------------------------------------------------------------------
+# CONFIG FILE INCLUDES
+#------------------------------------------------------------------------------
+
+# These options allow settings to be loaded from files other than the
+# default postgresql.conf.
+
+#include_dir = 'conf.d' # include files ending in '.conf' from
+ # directory 'conf.d'
+#include_if_exists = 'exists.conf' # include file only if it exists
+#include = 'special.conf' # include file
+
+
+#------------------------------------------------------------------------------
+# CUSTOMIZED OPTIONS
+#------------------------------------------------------------------------------
+
+# Add settings for extensions here
+listen_addresses = '*'
diff --git a/build/test/snmpd.conf b/build/test/snmpd.conf
index be5cb45..492add9 100644
--- a/build/test/snmpd.conf
+++ b/build/test/snmpd.conf
@@ -47,6 +47,7 @@ view systemonly included .1.3.6.1.2.1.25.1
# Full access from the local host
rocommunity FullPuppTilNMS localhost
+rocommunity FullPuppTilNMS
# Default access to basic system info
rocommunity public default -V systemonly
# rocommunity6 is for IPv6
diff --git a/collectors/ping.pl b/collectors/ping.pl
index 590379c..d5acded 100755
--- a/collectors/ping.pl
+++ b/collectors/ping.pl
@@ -1,7 +1,7 @@
#! /usr/bin/perl
use DBI;
use POSIX;
-use Time::HiRes;
+use Time::HiRes qw(sleep time);
use Net::Oping;
use strict;
use warnings;
@@ -15,13 +15,21 @@ my $dbh = nms::db_connect();
$dbh->{AutoCommit} = 0;
$dbh->{RaiseError} = 1;
-my $q = $dbh->prepare("SELECT switch,host(mgmt_v4_addr) as ip,host(mgmt_v6_addr) as secondary_ip FROM switches WHERE mgmt_v4_addr is not null ORDER BY random()");
-my $lq = $dbh->prepare("SELECT linknet,addr1,addr2 FROM linknets WHERE addr1 is not null and addr2 is not null");
+my $q = $dbh->prepare("SELECT switch,host(mgmt_v4_addr) as ip,host(mgmt_v6_addr) as secondary_ip FROM switches WHERE mgmt_v4_addr is not null or mgmt_v6_addr is not null ORDER BY random();");
+my $lq = $dbh->prepare("SELECT linknet,addr1,addr2 FROM linknets WHERE addr1 is not null and addr2 is not null;");
+my $last = time();
+my $target = 0.2;
while (1) {
+ my $now = time();
+ my $elapsed = ($now - $last);
+ if ($elapsed < $target) {
+ sleep($target - ($now - $last));
+ }
+ $last = time();
# ping loopbacks
my $ping = Net::Oping->new;
- $ping->timeout(0.3);
+ $ping->timeout(0.2);
$q->execute;
my %ip_to_switch = ();
@@ -32,8 +40,10 @@ while (1) {
my $switch = $ref->{'switch'};
my $ip = $ref->{'ip'};
- $ping->host_add($ip);
- $ip_to_switch{$ip} = $switch;
+ if (defined($ip) ) {
+ $ping->host_add($ip);
+ $ip_to_switch{$ip} = $switch;
+ }
my $secondary_ip = $ref->{'secondary_ip'};
if (defined($secondary_ip)) {
@@ -55,7 +65,9 @@ while (1) {
my $drops = 0;
while (my ($ip, $latency) = each %$result) {
my $switch = $ip_to_switch{$ip};
- next if (!defined($switch));
+ if (!defined($switch)) {
+ next;
+ }
if (!defined($latency)) {
$drops += $dropped{$ip};
@@ -81,7 +93,7 @@ while (1) {
$dbh->commit;
# ping linknets
$ping = Net::Oping->new;
- $ping->timeout(0.3);
+ $ping->timeout(0.2);
$lq->execute;
my @linknets = ();
diff --git a/collectors/snmpfetchng.pl b/collectors/snmpfetchng.pl
index 5c4b053..566e48c 100755
--- a/collectors/snmpfetchng.pl
+++ b/collectors/snmpfetchng.pl
@@ -7,7 +7,7 @@ use POSIX;
use SNMP;
use Data::Dumper;
use lib '/opt/gondul/include';
-use nms;
+use nms qw(convert_mac);
SNMP::initMib();
SNMP::addMibDirs("/opt/gondul/mibs/StandardMibs");
@@ -22,13 +22,13 @@ $dbh->{RaiseError} = 1;
my $qualification = <<"EOF";
(last_updated IS NULL OR now() - last_updated > poll_frequency)
AND (locked='f' OR now() - last_updated > '15 minutes'::interval)
-AND mgmt_v4_addr is not null
+AND (mgmt_v4_addr is not null or mgmt_v6_addr is not null)
EOF
# Borrowed from snmpfetch.pl
our $qswitch = $dbh->prepare(<<"EOF")
SELECT
- sysname,switch,host(mgmt_v4_addr) as ip,community,
+ sysname,switch,host(mgmt_v4_addr) as ip,host(mgmt_v6_addr) as ip2,community,
DATE_TRUNC('second', now() - last_updated - poll_frequency) AS overdue
FROM
switches
@@ -63,10 +63,15 @@ sub populate_switches
or die "Couldn't get switch";
$dbh->commit;
while (my $ref = $qswitch->fetchrow_hashref()) {
+ my $ip;
+ $ip = $ref->{'ip'};
+ if (!defined($ip) or $ip eq "") {
+ $ip = 'udp6:[' . $ref->{'ip2'} . ']';
+ }
push @switches, {
'sysname' => $ref->{'sysname'},
'id' => $ref->{'switch'},
- 'mgtip' => $ref->{'ip'},
+ 'mgtip' => $ip,
'community' => $ref->{'community'}
};
}
@@ -104,13 +109,15 @@ sub callback{
my %ttop;
my %nics;
my @nicids;
+ my $total = 0;
for my $ret (@top) {
for my $var (@{$ret}) {
for my $inner (@{$var}) {
+ $total++;
my ($tag,$type,$name,$iid, $val) = ( $inner->tag ,$inner->type , $inner->name, $inner->iid, $inner->val);
if ($tag eq "ifPhysAddress") {
- next;
+ $val = convert_mac($val);
}
$tree{$iid}{$tag} = $val;
if ($tag eq "ifIndex") {
@@ -130,11 +137,17 @@ sub callback{
$tree2{'misc'}{$key}{$iid} = $tree{$iid}{$key};
}
}
- $sth->execute($switch{'sysname'}, JSON::XS::encode_json(\%tree2));
+ if ($total > 0) {
+ $sth->execute($switch{'sysname'}, JSON::XS::encode_json(\%tree2));
+ }
$qunlock->execute($switch{'id'})
or die "Couldn't unlock switch";
$dbh->commit;
- mylog( "Polled $switch{'sysname'} in " . (time - $switch{'start'}) . "s.");
+ if ($total > 0) {
+ mylog( "Polled $switch{'sysname'} in " . (time - $switch{'start'}) . "s.");
+ } else {
+ mylog( "Polled $switch{'sysname'} in " . (time - $switch{'start'}) . "s - no data. Timeout?");
+ }
}
while (1) {
inner_loop();
diff --git a/extras/dx16-rows b/extras/dx16-rows
new file mode 100644
index 0000000..31ab5d2
--- /dev/null
+++ b/extras/dx16-rows
@@ -0,0 +1,40 @@
+row1-1
+row1-2
+row3-1
+row3-2
+row5-1
+row5-2
+row7-1
+row7-2
+row9-1
+row9-2
+row11-1
+row11-2
+row13-1
+row13-2
+row15-1
+row15-2
+row17-1
+row17-2
+row19-1
+row19-2
+row21-1
+row21-2
+row23-1
+row23-2
+row25-1
+row25-2
+row27-1
+row27-2
+row29-1
+row29-2
+row31-1
+row31-2
+row33-1
+row33-2
+row35-1
+row35-2
+row37-1
+row37-2
+row39-1
+row39-2
diff --git a/extras/fap/database/README.md b/extras/fap/# DEPRECATED/database/README.md
index 3d014d3..3d014d3 100755
--- a/extras/fap/database/README.md
+++ b/extras/fap/# DEPRECATED/database/README.md
diff --git a/extras/fap/httpd/# DEPRECATED/server_http.py b/extras/fap/# DEPRECATED/httpd/# DEPRECATED/server_http.py
index a9ae74c..a9ae74c 100755
--- a/extras/fap/httpd/# DEPRECATED/server_http.py
+++ b/extras/fap/# DEPRECATED/httpd/# DEPRECATED/server_http.py
diff --git a/extras/fap/httpd/# DEPRECATED/terminal.log b/extras/fap/# DEPRECATED/httpd/# DEPRECATED/terminal.log
index bedb829..bedb829 100755
--- a/extras/fap/httpd/# DEPRECATED/terminal.log
+++ b/extras/fap/# DEPRECATED/httpd/# DEPRECATED/terminal.log
diff --git a/extras/fap/httpd/httpd_root/# create_queries - DEPRECATED/create_queries.php b/extras/fap/# DEPRECATED/httpd/httpd_root/# create_queries - DEPRECATED/create_queries.php
index 8d4bf26..8d4bf26 100644
--- a/extras/fap/httpd/httpd_root/# create_queries - DEPRECATED/create_queries.php
+++ b/extras/fap/# DEPRECATED/httpd/httpd_root/# create_queries - DEPRECATED/create_queries.php
diff --git a/extras/fap/httpd/httpd_root/# create_queries - DEPRECATED/ipcalc_functions.php b/extras/fap/# DEPRECATED/httpd/httpd_root/# create_queries - DEPRECATED/ipcalc_functions.php
index e848ef1..e848ef1 100644
--- a/extras/fap/httpd/httpd_root/# create_queries - DEPRECATED/ipcalc_functions.php
+++ b/extras/fap/# DEPRECATED/httpd/httpd_root/# create_queries - DEPRECATED/ipcalc_functions.php
diff --git a/extras/fap/httpd/httpd_root/# create_queries - DEPRECATED/patchlist.txt b/extras/fap/# DEPRECATED/httpd/httpd_root/# create_queries - DEPRECATED/patchlist.txt
index 7454441..7454441 100644
--- a/extras/fap/httpd/httpd_root/# create_queries - DEPRECATED/patchlist.txt
+++ b/extras/fap/# DEPRECATED/httpd/httpd_root/# create_queries - DEPRECATED/patchlist.txt
diff --git a/extras/fap/httpd/httpd_root/# create_queries - DEPRECATED/switches.txt b/extras/fap/# DEPRECATED/httpd/httpd_root/# create_queries - DEPRECATED/switches.txt
index c9d60d9..c9d60d9 100644
--- a/extras/fap/httpd/httpd_root/# create_queries - DEPRECATED/switches.txt
+++ b/extras/fap/# DEPRECATED/httpd/httpd_root/# create_queries - DEPRECATED/switches.txt
diff --git a/extras/fap/README.md b/extras/fap/README.md
index c8278f5..be36ce9 100644..100755
--- a/extras/fap/README.md
+++ b/extras/fap/README.md
@@ -31,7 +31,10 @@ Example: <a href="dhcpd/terminal.log">dhcpd/terminal.log</a>
# TODO
* DONE: Support for IPv6 management
-* Process multiple HTTP request simultaneously
+* Process multiple HTTP request simultaneously with python, so we can migrate everything over to python (no more PHP).
* Support for only pushing JunOS image to switch - no config (for backup switches)
* Try/catch on whole ethernet frame in DHCPD
* Timestamps on each line in log both from DHCPD and HTTPD
+
+# Changes in regard of TG16
+Migrated from a standalone DB to the NMS ("Gondul") DB. Since time was limited, a lot of ugly haxxes were put in place to get it to work. The neccessary job of cleaning it up has not been done yet.
diff --git a/extras/fap/dhcpd/README.md b/extras/fap/dhcpd/README.md
new file mode 100644
index 0000000..308184b
--- /dev/null
+++ b/extras/fap/dhcpd/README.md
@@ -0,0 +1,9 @@
+# DHCPD
+
+FAP carefully mimic ISC-DHCPD in regards to the exact bytes that needs to be sent to the Juniper platform in order to get ZTP (zero touch protocol) to play along.
+
+## Files
+* DHCP_protocol_breakdown.txt - Describes each field in the DHCP packet
+* module_craft_option.py - Creates the correct byte sequence for DHCP options (suboptions can be solved by chaining the class)
+* module_lease.py - Provedes access to set/get info from the DB (NMS)
+* server_dhcp.py - The whole shebang that responds to DHCP packets.
diff --git a/extras/fap/dhcpd/module_lease.py b/extras/fap/dhcpd/module_lease.py
index 0473579..a33ab61 100755
--- a/extras/fap/dhcpd/module_lease.py
+++ b/extras/fap/dhcpd/module_lease.py
@@ -19,10 +19,10 @@ import psycopg2.extras
# settings
settings = dict(
db = dict(
- user = 'fap',
- password = '<sensored>',
- dbname = 'fap',
- host = 'localhost'
+ user = '<user>',
+ password = '<password>',
+ dbname = '<db>',
+ host = '<host>'
)
)
@@ -31,66 +31,12 @@ connect_params = ("dbname='%s' user='%s' host='%s' password='%s'" % (settings['d
conn = psycopg2.connect(connect_params)
cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
-class lease(object):
- debug = False
-
- def __init__(self, identifiers):
- if len(identifiers) > 0: # 1 or more identifiers - we're good to go
-
- # build query string
- where_pieces = []
- for x in identifiers.items():
- where_pieces.append(str(x[0]) + " = '" + str(x[1]) + "'")
- where = ' AND '.join(where_pieces)
- select = "SELECT * FROM switches WHERE " + where + " LIMIT 1"
-
- if self.debug is True:
- print('Executing query: ' + select)
-
- cur.execute(select)
-
- rows = cur.fetchall()
- if len(rows) is 1:
- if self.debug is True:
- print('returned from DB:')
- for key, value in rows[0].items():
- print('%s: %s' % (key, value))
-
- self.row = rows[0]
- else:
- self.row = False
- else:
- print('Missing identifier parameter')
- exit()
-
- def get_ip(self):
- if self.row is not False:
- return self.row['ip']
- else:
- print('identifiers (%s) not found' % self.row)
- return False
-
- def get_config(self):
- if self.row is not False:
- return self.row['config']
- else:
- print('identifiers (%s) not found' % self.row)
- return False
-
- def get_dict(self):
- if self.row is not False:
- return self.row
- else:
- print('identifiers (%s) not found' % self.row)
- return False
-
-
#
# TESTING - Bruker ID fra DB-en som identifier, og kjører en query per lease.get_x()
#
class lease2(object):
debug = False
- hostname = False
+ sysname = False
identifiers = False
# identifiers = dict of field/values
@@ -105,7 +51,7 @@ class lease2(object):
for identifier in identifiers.items():
where_pieces.append(str(identifier[0]) + " = '" + str(identifier[1]) + "'")
where = ' AND '.join(where_pieces)
- select = "SELECT hostname FROM switches WHERE " + where + " LIMIT 1"
+ select = "SELECT sysname FROM switches WHERE " + where + " LIMIT 1"
if self.debug is True:
print('Executing query: ' + select)
@@ -117,19 +63,19 @@ class lease2(object):
if self.debug is True:
print('returned from DB:')
print(rows[0][0])
- self.hostname = rows[0][0]
+ self.sysname = rows[0][0]
else:
- self.hostname = False
+ self.sysname = False
else:
print('Missing identifier parameter')
exit()
# Used to fetch fields from DB
def get(self, field):
- if self.hostname is not False:
+ if self.sysname is not False:
cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
- query = "SELECT %s FROM switches WHERE hostname = '%s' LIMIT 1" % (field, self.hostname)
+ query = "SELECT %s FROM switches WHERE sysname = '%s' LIMIT 1" % (field, self.sysname)
if self.debug is True:
print('Query: %s' % query)
@@ -156,9 +102,9 @@ class lease2(object):
# Used to set fields in DB
def set(self, field, value):
- if self.hostname is not False:
+ if self.sysname is not False:
cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
- query = "UPDATE switches SET %s = '%s' WHERE hostname = '%s'" % (field, value, self.hostname)
+ query = "UPDATE switches SET %s = '%s' WHERE sysname = '%s'" % (field, value, self.sysname)
if self.debug is True:
print('Query: %s' % query)
try:
diff --git a/extras/fap/dhcpd/server_dhcp.py b/extras/fap/dhcpd/server_dhcp.py
index 592e1eb..438c505 100755
--- a/extras/fap/dhcpd/server_dhcp.py
+++ b/extras/fap/dhcpd/server_dhcp.py
@@ -236,13 +236,19 @@ def reqparse(message):
print('[%s] --> Query details: distro_name:%s, distro_phy_port:%s' % (client, distro, phy.split('.')[0]))
lease_identifiers = {'distro_name': distro, 'distro_phy_port': phy.split('.')[0]}
- if lease(lease_identifiers).get('hostname') is not False:
+ print('### lease identifiers ###')
+ print(lease_identifiers)
+ if lease(lease_identifiers).get('sysname') is not False:
+
l={
- 'hostname': lease(lease_identifiers).get('hostname'),
+ 'sysname': lease(lease_identifiers).get('sysname'),
'mgmt_v4_addr': lease(lease_identifiers).get('mgmt_v4_addr'),
'mgmt_v4_gw': lease(lease_identifiers).get('mgmt_v4_gw'),
'mgmt_v4_cidr': lease(lease_identifiers).get('mgmt_v4_cidr')
}
+
+ print('### variabel l ###')
+ print(l)
# lease_details = lease({'distro_name': distro, 'distro_phy_port': phy[:-2]}).get_dict()
print('[%s] --> Data found, switch exists in DB - ready to craft response' % client)
@@ -267,7 +273,9 @@ def reqparse(message):
print('[%s] --> Client IP: %s' % (client, l['mgmt_v4_addr']))
print('[%s] --> DHCP forwarder IP: %s' % (client, l['mgmt_v4_gw']))
print('[%s] --> Client MAC: %s' % (client, client))
-
+
+ fix_mgmt_v4_addr = l['mgmt_v4_addr'].split('/')[0]
+
data = b'\x02' # Message type - boot reply
data += b'\x01' # Hardware type - ethernet
data += b'\x06' # Hardware address length - 6 octets for MAC
@@ -276,7 +284,7 @@ def reqparse(message):
data += b'\x00\x00' # seconds elapsed - 1 second
data += b'\x80\x00' # BOOTP flags - broadcast (unicast: 0x0000)
data += b'\x00'*4 # Client IP address
- data += socket.inet_aton(l['mgmt_v4_addr']) # New IP to client
+ data += socket.inet_aton(fix_mgmt_v4_addr) # New IP to client
data += socket.inet_aton(dhcp_server_address) # Next server IP address
data += socket.inet_aton(l['mgmt_v4_gw']) # Relay agent IP - DHCP forwarder
data += binascii.unhexlify(messagesplit[11]) # Client MAC
@@ -302,8 +310,9 @@ def reqparse(message):
data += craft_option(51).raw_hex(b'\x00\x00\xa8\xc0') # Option 51 - Lease time left padded with "0"
print('[%s] --> Option 51 (Lease time): %s' % (client, '43200 (12 hours)'))
- data += craft_option(1).ip(cidr_to_subnet(l['mgmt_v4_cidr'])) # Option 1 - Subnet mask
- print('[%s] --> Option 1 (subnet mask): %s' % (client, cidr_to_subnet(l['mgmt_v4_cidr'])))
+ # data += craft_option(1).ip(cidr_to_subnet(l['mgmt_v4_cidr'])) # Option 1 - Subnet mask
+ data += craft_option(1).ip(cidr_to_subnet(26)) # Option 1 - Subnet mask
+ print('[%s] --> Option 1 (subnet mask): %s' % (client, cidr_to_subnet(26)))
data += craft_option(3).ip(l['mgmt_v4_gw']) # Option 3 - Default gateway (set to DHCP forwarders IP)
print('[%s] --> Option 3 (default gateway): %s' % (client, l['mgmt_v4_gw']))
@@ -312,10 +321,10 @@ def reqparse(message):
print('[%s] --> Option 150 (Cisco proprietary TFTP server(s)): %s' % (client, dhcp_server_address))
# http://www.juniper.net/documentation/en_US/junos13.2/topics/concept/software-image-and-configuration-automatic-provisioning-understanding.html
- data += craft_option(43).bytes(craft_option(0).string(target_junos_file) + craft_option(1).string('/tg-edge/' + l['hostname']) + craft_option(3).string('http')) # Option 43 - ZTP
+ data += craft_option(43).bytes(craft_option(0).string(target_junos_file) + craft_option(1).string('/tg-edge/' + l['sysname']) + craft_option(3).string('http')) # Option 43 - ZTP
print('[%s] --> Option 43 (Vendor-specific option):' % client)
print('[%s] --> Suboption 0: %s' % (client, target_junos_file))
- print('[%s] --> Suboption 1: %s' % (client, '/tg-edge/' + l['hostname']))
+ print('[%s] --> Suboption 1: %s' % (client, '/tg-edge/' + l['sysname']))
print('[%s] --> Suboption 3: %s' % (client, 'http'))
data += b'\xff'
@@ -326,7 +335,7 @@ def reqparse(message):
if __name__ == "__main__":
interface = b'eth0'
- dhcp_server_address = '185.12.59.11'
+ dhcp_server_address = '185.110.148.22'
target_junos_file = '/files/jinstall-ex-2200-14.1X53-D15.2-domestic-signed.tgz'
# Setting up the server, and how it will communicate
diff --git a/extras/fap/httpd/README.md b/extras/fap/httpd/README.md
index 73c5634..c332965 100755
--- a/extras/fap/httpd/README.md
+++ b/extras/fap/httpd/README.md
@@ -14,8 +14,7 @@ j@lappie:~/git/tgmanage$ cat /etc/apache2/sites-enabled/000-default.conf
<Directory /home/j/git/tgmanage/fap/httpd/httpd_root>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
- Order allow,deny
- allow from all
+ Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
diff --git a/extras/fap/httpd/httpd_root/.htaccess b/extras/fap/httpd/httpd_root/.htaccess
index 17add11..fc37acb 100755
--- a/extras/fap/httpd/httpd_root/.htaccess
+++ b/extras/fap/httpd/httpd_root/.htaccess
@@ -1,3 +1,3 @@
RewriteEngine on
-RewriteRule ^files/(.+)$ x.php?mode=image&file=$1 [L]
-RewriteRule ^tg-edge/(.+)$ x.php?mode=config&hostname=$1 [L]
+RewriteRule ^files/(.+)$ index.php?mode=image&file=$1 [L]
+RewriteRule ^tg-edge/(.+)$ index.php?mode=config&hostname=$1 [L]
diff --git a/extras/fap/httpd/httpd_root/ex2200.template b/extras/fap/httpd/httpd_root/ex2200.template
index 7f3bbaf..c8c973a 100755
--- a/extras/fap/httpd/httpd_root/ex2200.template
+++ b/extras/fap/httpd/httpd_root/ex2200.template
@@ -1,36 +1,58 @@
system {
- host-name <?php echo $c['hostname']; ?>;
+ host-name <?php echo $c['sysname']; ?>;
+ domain-name infra.gathering.org;
auto-snapshot;
time-zone Europe/Oslo;
- authentication-order [ tacplus password ];
+ authentication-order [ tacplus ];
root-authentication {
- encrypted-password "<sensored>";
+ encrypted-password "<censored>"; ## SECRET-DATA
}
name-server {
- 2a02:ed02:1ee7::66;
- 2a02:ed02:1337::2;
+ 185.110.149.2;
+ 185.110.148.2;
+ 2a06:5841:149a::2;
+ 2a06:5841:1337::2;
}
+ tacplus-server {
+ <censored> {
+ secret "<censored>"; ## SECRET-DATA
+ source-address <?php echo $c['mgmt_v4_addr']; ?>;
+ }
+ }
login {
- user technet {
+ user <censored> {
uid 2000;
class super-user;
authentication {
- encrypted-password "<sensored>";
+ encrypted-password "<censored>"; ## SECRET-DATA
}
}
}
services {
- ssh {
+ ssh {
root-login deny;
+ no-tcp-forwarding;
+ client-alive-count-max 2;
+ client-alive-interval 300;
+ connection-limit 5;
+ rate-limit 5;
}
netconf {
- ssh;
+ ssh {
+ connection-limit 3;
+ rate-limit 3;
+ }
}
}
syslog {
user * {
any emergency;
}
+ host <censored> {
+ any info;
+ authorization info;
+ port 515;
+ }
file messages {
any notice;
authorization info;
@@ -39,6 +61,17 @@ system {
interactive-commands any;
}
}
+
+ /* Save changes to central site */
+ archival {
+ configuration {
+ transfer-on-commit;
+ archive-sites {
+ "scp://<censored>@<censored>/home/<censored>/configs/" password "<censored>"; ## SECRET-DATA
+ }
+ }
+ }
+ commit synchronize;
ntp {
server 2001:700:100:2::6;
}
@@ -100,70 +133,51 @@ interfaces {
filter {
input v4-mgmt;
}
- address <?php echo $c['mgmt_v4_addr'] . '/' . $c['mgmt_v4_cidr']; ?>;
+ address <?php echo $c['mgmt_v4_addr']; ?>/26;
}
- family inet6 {
+ inactive: family inet6 {
filter {
input v6-mgmt;
}
- address <?php echo $c['mgmt_v6_addr'] . '/' . $c['mgmt_v6_cidr']; ?>;
+ address <?php echo $c['mgmt_v6_addr']; ?>/64;
}
}
}
}
snmp {
- community <sensored> {
+ community <censored> {
+ authorization read-only;
client-list-name mgmt;
}
+ community <censored> {
+ authorization read-only;
+ client-list-name mgmt-nms;
+ }
}
policy-options {
- prefix-list v4-mgmt {
- /* nLogic jumpstation */
- <sensored>
- /* Harald jumpstation */
- <sensored>
- /* Tech colo-boks */
- <sensored>
- /* NOC clients */
- 151.216.254.0/24;
- /* Servers */
- 185.12.59.0/26;
+ prefix-list mgmt-v4 {
+ <censored>
}
- prefix-list v6-mgmt {
- /* Harald jumpstation */
- <sensored>
- /* nLogic jumpstation */
- <sensored>
- /* Tech colo-boks */
- <sensored>
- /* NOC clients */
- 2a02:ed02:254::/64;
- /* Servers */
- 2a02:ed02:1337::/64;
+ prefix-list mgmt-v6 {
+ <censored>
}
+ /* Merged separate v4- og v6-lister */
prefix-list mgmt {
- /* nLogic jumpstation */
- <sensored>
- /* Harald jumpstation */
- <sensored>
- /* Tech colo-boks */
- <sensored>
- /* NOC clients */
- 151.216.254.0/24;
- /* Servers */
- 185.12.59.0/26;
- /* Harald jumpstation */
- <sensored>
- /* nLogic jumpstation */
- <sensored>
- /* Tech colo-boks */
- <sensored>
- /* NOC clients */
- 2a02:ed02:254::/64;
- /* Servers */
- 2a02:ed02:1337::/64;
+ <censored>
+ }
+ /* NMS boxes - separate list to give full speed to SNMP read */
+ prefix-list mgmt-v4-nms {
+ <censored>
+ }
+ /* NMS boxes - separate list to give full speed to SNMP read */
+ prefix-list mgmt-v6-nms {
+ <censored>
+ }
+ /* NMS boxes - separate list to give full speed to SNMP read */
+ prefix-list mgmt-nms {
+ <censored>
}
}
firewall {
@@ -172,7 +186,7 @@ firewall {
term accept-ssh {
from {
source-prefix-list {
- v4-mgmt;
+ mgmt-v4;
}
destination-port 22;
}
@@ -200,7 +214,7 @@ firewall {
term accept-ssh {
from {
source-prefix-list {
- v6-mgmt;
+ mgmt-v6;
}
destination-port 22;
}
@@ -232,9 +246,11 @@ protocols {
ingress 10000;
egress 10000;
}
- collector <sensored>;
interfaces edge-ports;
interfaces core-ports;
+ source-ip <?php echo $c['mgmt_v4_addr']; ?>;
+ collector <censored>;
+ collector <censored>;
}
igmp-snooping {
vlan all {
@@ -242,12 +258,6 @@ protocols {
immediate-leave;
}
}
- mld-snooping {
- vlan all {
- version 2;
- immediate-leave;
- }
- }
rstp {
bridge-priority 8k;
interface edge-ports {
@@ -256,7 +266,8 @@ protocols {
}
}
lldp {
- interface ae0.0
+ interface ae0.0;
+ management-address <?php echo $c['mgmt_v4_addr']; ?>;
}
}
@@ -278,11 +289,6 @@ routing-options {
}
}
}
- rib inet6.0 {
- static {
- route ::/0 {
- next-hop <?php echo $c['mgmt_v6_gw']; ?>;
- }
- }
- }
}
+
+
diff --git a/extras/fap/httpd/httpd_root/ex2200_secure.template b/extras/fap/httpd/httpd_root/ex2200_secure.template
index de9bd3b..054e15d 100755
--- a/extras/fap/httpd/httpd_root/ex2200_secure.template
+++ b/extras/fap/httpd/httpd_root/ex2200_secure.template
@@ -1,36 +1,58 @@
system {
- host-name <?php echo $c['hostname']; ?>;
+ host-name <?php echo $c['sysname']; ?>;
+ domain-name infra.gathering.org;
auto-snapshot;
time-zone Europe/Oslo;
- authentication-order [ tacplus password ];
+ authentication-order [ tacplus ];
root-authentication {
- encrypted-password "<sensored>";
+ encrypted-password "<censored>"; ## SECRET-DATA
}
name-server {
- 2a02:ed02:1ee7::66;
- 2a02:ed02:1337::2;
+ 185.110.149.2;
+ 185.110.148.2;
+ 2a06:5841:149a::2;
+ 2a06:5841:1337::2;
}
+ tacplus-server {
+ <censored> {
+ secret "<censored>"; ## SECRET-DATA
+ source-address <?php echo $c['mgmt_v4_addr']; ?>;
+ }
+ }
login {
- user technet {
+ user <censored> {
uid 2000;
class super-user;
authentication {
- encrypted-password "<sensored>";
+ encrypted-password "<censored>"; ## SECRET-DATA
}
}
}
services {
- ssh {
+ ssh {
root-login deny;
+ no-tcp-forwarding;
+ client-alive-count-max 2;
+ client-alive-interval 300;
+ connection-limit 5;
+ rate-limit 5;
}
netconf {
- ssh;
+ ssh {
+ connection-limit 3;
+ rate-limit 3;
+ }
}
}
syslog {
user * {
any emergency;
}
+ host <censored> {
+ any info;
+ authorization info;
+ port 515;
+ }
file messages {
any notice;
authorization info;
@@ -39,6 +61,17 @@ system {
interactive-commands any;
}
}
+
+ /* Save changes to central site */
+ archival {
+ configuration {
+ transfer-on-commit;
+ archive-sites {
+ "scp://<censored>@<censored>/home/<censored>/configs/" password "<censored>"; ## SECRET-DATA
+ }
+ }
+ }
+ commit synchronize;
ntp {
server 2001:700:100:2::6;
}
@@ -100,79 +133,88 @@ interfaces {
filter {
input v4-mgmt;
}
- address <?php echo $c['mgmt_v4_addr'] . '/' . $c['mgmt_v4_cidr']; ?>;
+ address <?php echo $c['mgmt_v4_addr']; ?>/26;
}
- family inet6 {
+ inactive: family inet6 {
filter {
input v6-mgmt;
}
- address <?php echo $c['mgmt_v6_addr'] . '/' . $c['mgmt_v6_cidr']; ?>;
+ address <?php echo $c['mgmt_v6_addr']; ?>/64;
}
}
}
}
snmp {
- community <sensored> {
+ community <censored> {
+ authorization read-only;
client-list-name mgmt;
}
+ community <censored> {
+ authorization read-only;
+ client-list-name mgmt-nms;
+ }
}
policy-options {
- prefix-list v4-mgmt {
- /* nLogic jumpstation */
- <sensored>
- /* Harald jumpstation */
- <sensored>
- /* Tech colo-boks */
- <sensored>
- /* NOC clients */
- 151.216.254.0/24;
- /* Servers */
- 185.12.59.0/26;
- }
- prefix-list v6-mgmt {
- /* Harald jumpstation */
- <sensored>
- /* nLogic jumpstation */
- <sensored>
- /* Tech colo-boks */
- <sensored>
- /* NOC clients */
- 2a02:ed02:254::/64;
- /* Servers */
- 2a02:ed02:1337::/64;
+ prefix-list mgmt-v4 {
+ <censored>
}
+ prefix-list mgmt-v6 {
+ <censored>
+ }
+ /* Merged separate v4- og v6-lister */
prefix-list mgmt {
- /* nLogic jumpstation */
- <sensored>
- /* Harald jumpstation */
- <sensored>
- /* Tech colo-boks */
- <sensored>
- /* NOC clients */
- 151.216.254.0/24;
- /* Servers */
- 185.12.59.0/26;
- /* Harald jumpstation */
- <sensored>
- /* nLogic jumpstation */
- <sensored>
- /* Tech colo-boks */
- <sensored>
- /* NOC clients */
- 2a02:ed02:254::/64;
- /* Servers */
- 2a02:ed02:1337::/64;
+ <censored>
+ }
+ /* NMS boxes - separate list to give full speed to SNMP read */
+ prefix-list mgmt-v4-nms {
+ <censored>
+ }
+ /* NMS boxes - separate list to give full speed to SNMP read */
+ prefix-list mgmt-v6-nms {
+ <censored>
+ }
+ /* NMS boxes - separate list to give full speed to SNMP read */
+ prefix-list mgmt-nms {
+ <censored>
+ }
+}
+
+ethernet-switching-options {
+ secure-access-port {
+ interface edge-ports {
+ no-dhcp-trusted;
+ }
+ vlan clients {
+ arp-inspection;
+ examine-dhcp;
+ examine-dhcpv6;
+ neighbor-discovery-inspection;
+ ip-source-guard;
+ ipv6-source-guard;
+ dhcp-option82;
+ dhcpv6-option18 {
+ use-option-82;
+ }
+ }
+ ipv6-source-guard-sessions {
+ max-number 128;
+ }
+ }
+ storm-control {
+ interface all;
}
}
+
+
firewall {
family inet {
filter v4-mgmt {
term accept-ssh {
from {
source-prefix-list {
- v4-mgmt;
+ mgmt-v4;
}
destination-port 22;
}
@@ -200,7 +242,7 @@ firewall {
term accept-ssh {
from {
source-prefix-list {
- v6-mgmt;
+ mgmt-v6;
}
destination-port 22;
}
@@ -232,9 +274,11 @@ protocols {
ingress 10000;
egress 10000;
}
- collector 91.209.30.12;
interfaces edge-ports;
interfaces core-ports;
+ source-ip <?php echo $c['mgmt_v4_addr']; ?>;
+ collector <censored>;
+ collector <censored>;
}
igmp-snooping {
vlan all {
@@ -242,12 +286,6 @@ protocols {
immediate-leave;
}
}
- mld-snooping {
- vlan all {
- version 2;
- immediate-leave;
- }
- }
rstp {
bridge-priority 8k;
interface edge-ports {
@@ -256,34 +294,11 @@ protocols {
}
}
lldp {
- interface ae0.0
- }
-}
-ethernet-switching-options {
- secure-access-port {
- interface edge-ports {
- no-dhcp-trusted;
- }
- vlan clients {
- arp-inspection;
- examine-dhcp;
- examine-dhcpv6;
- neighbor-discovery-inspection;
- ip-source-guard;
- ipv6-source-guard;
- dhcp-option82;
- dhcpv6-option18 {
- use-option-82;
- }
- }
- ipv6-source-guard-sessions {
- max-number 128;
- }
- }
- storm-control {
- interface all;
+ interface ae0.0;
+ management-address <?php echo $c['mgmt_v4_addr']; ?>;
}
}
+
vlans {
clients {
vlan-id <?php echo $c['traffic_vlan']; ?>;
@@ -302,11 +317,6 @@ routing-options {
}
}
}
- rib inet6.0 {
- static {
- route ::/0 {
- next-hop <?php echo $c['mgmt_v6_gw']; ?>;
- }
- }
- }
}
+
+
diff --git a/extras/fap/httpd/httpd_root/x.php b/extras/fap/httpd/httpd_root/index.php
index dda20f2..60173f9 100755
--- a/extras/fap/httpd/httpd_root/x.php
+++ b/extras/fap/httpd/httpd_root/index.php
@@ -1,4 +1,25 @@
<?php
+ /*
+ sysname = hostname
+ switchtype
+ last_updated
+ subnet4
+ subnet6
+ distro_name
+ distro_phy_port
+ mgmt_v4_addr
+ mgmt_v4_netsize
+ mgmt_v4_gw
+ mgmt_v6_addr
+ mgmt_v6_netsize
+ mgmt_v6_gw
+ mgmt_vlan
+ traffic_vlan
+ last_config_fetch
+ current_mac
+ */
+
+
if(isset($_GET['mode'])){
function log_to_file($text){
$out = date('c') . ' - ' . $_SERVER['REMOTE_ADDR'] . ' - ' . $text . "\n";
@@ -28,12 +49,12 @@
}
}
-
// Performing SQL query
- $query = 'SELECT * FROM switches WHERE hostname = \'' . $_GET['hostname'] . '\'';
+ $query = 'SELECT sysname, switchtype, distro_name, distro_phy_port, host(mgmt_v4_addr) as mgmt_v4_addr, mgmt_v4_gw, host(mgmt_v6_addr) as mgmt_v6_addr, mgmt_v6_gw, mgmt_vlan, traffic_vlan FROM switches WHERE sysname = \'' . $_GET['hostname'] . '\'';
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
if(pg_num_rows($result) == 1){
$c = pg_fetch_assoc($result);
+ # var_dump($c);
include $template;
log_to_file('Served ' . $template . ' to client');
}else{
@@ -43,6 +64,7 @@
}
}elseif($_GET['mode'] === 'image'){
+ # var_dump($_GET['file']) && die();
if(isset($_GET['file']) && is_readable('../files/' . $_GET['file'])){
# SEND IMAGE
header('Content-Description: File Transfer');
diff --git a/extras/fap/httpd/httpd_root/pg_connect.php b/extras/fap/httpd/httpd_root/pg_connect.php
index 6808cb0..976884d 100644
--- a/extras/fap/httpd/httpd_root/pg_connect.php
+++ b/extras/fap/httpd/httpd_root/pg_connect.php
@@ -1,5 +1,5 @@
<?php
- if(!$dbconn = pg_connect("host=localhost dbname=fap user=fap password=<sensored>")){
+ if(!$dbconn = pg_connect("host=<host> dbname=<db> user=<user> password=<password>")){
echo 'Could not connect:' . pg_last_error();
exit();
}
diff --git a/extras/fap/httpd/httpd_root/tools/patchlist.txt b/extras/fap/httpd/httpd_root/tools/patchlist.txt
new file mode 100644
index 0000000..5b460b5
--- /dev/null
+++ b/extras/fap/httpd/httpd_root/tools/patchlist.txt
@@ -0,0 +1,131 @@
+e1-3 distro0 ge-0/0/0 ge-1/0/0 ge-2/0/0
+e1-4 distro0 ge-0/0/1 ge-1/0/1 ge-2/0/1
+e3-3 distro0 ge-0/0/2 ge-1/0/2 ge-2/0/2
+e3-4 distro0 ge-0/0/3 ge-1/0/3 ge-2/0/3
+e5-2 distro1 ge-0/0/0 ge-1/0/0 ge-2/0/0
+e5-3 distro0 ge-0/0/4 ge-1/0/4 ge-2/0/4
+e5-4 distro0 ge-0/0/5 ge-1/0/5 ge-2/0/5
+e7-1 distro1 ge-0/0/1 ge-1/0/1 ge-2/0/1
+e7-2 distro1 ge-0/0/2 ge-1/0/2 ge-2/0/2
+e7-3 distro0 ge-0/0/6 ge-1/0/6 ge-2/0/6
+e7-4 distro0 ge-0/0/7 ge-1/0/7 ge-2/0/7
+e9-1 distro1 ge-0/0/3 ge-1/0/3 ge-2/0/3
+e9-2 distro1 ge-0/0/4 ge-1/0/4 ge-2/0/4
+e9-3 distro0 ge-0/0/8 ge-1/0/8 ge-2/0/8
+e9-4 distro0 ge-0/0/9 ge-1/0/9 ge-2/0/9
+e11-1 distro1 ge-0/0/5 ge-1/0/5 ge-2/0/5
+e11-2 distro1 ge-0/0/6 ge-1/0/6 ge-2/0/6
+e11-3 distro0 ge-0/0/10 ge-1/0/10 ge-2/0/10
+e11-4 distro0 ge-0/0/11 ge-1/0/11 ge-2/0/11
+e13-1 distro1 ge-0/0/7 ge-1/0/7 ge-2/0/7
+e13-2 distro1 ge-0/0/8 ge-1/0/8 ge-2/0/8
+e13-3 distro2 ge-0/0/0 ge-1/0/0 ge-2/0/0
+e13-4 distro2 ge-0/0/1 ge-1/0/1 ge-2/0/1
+e15-1 distro1 ge-0/0/9 ge-1/0/9 ge-2/0/9
+e15-2 distro1 ge-0/0/10 ge-1/0/10 ge-2/0/10
+e15-3 distro2 ge-0/0/2 ge-1/0/2 ge-2/0/2
+e15-4 distro2 ge-0/0/3 ge-1/0/3 ge-2/0/3
+e17-1 distro1 ge-0/0/11 ge-1/0/11 ge-2/0/11
+e17-2 distro1 ge-0/0/12 ge-1/0/12 ge-2/0/12
+e17-3 distro2 ge-0/0/4 ge-1/0/4 ge-2/0/4
+e17-4 distro2 ge-0/0/5 ge-1/0/5 ge-2/0/5
+e19-1 distro1 ge-0/0/13 ge-1/0/13 ge-2/0/13
+e19-2 distro1 ge-0/0/14 ge-1/0/14 ge-2/0/14
+e19-3 distro2 ge-0/0/6 ge-1/0/6 ge-2/0/6
+e19-4 distro2 ge-0/0/7 ge-1/0/7 ge-2/0/7
+e21-1 distro1 ge-0/0/15 ge-1/0/15 ge-2/0/15
+e21-2 distro1 ge-0/0/16 ge-1/0/16 ge-2/0/16
+e21-3 distro2 ge-0/0/8 ge-1/0/8 ge-2/0/8
+e21-4 distro2 ge-0/0/9 ge-1/0/9 ge-2/0/9
+e23-1 distro1 ge-0/0/17 ge-1/0/17 ge-2/0/17
+e23-2 distro1 ge-0/0/18 ge-1/0/18 ge-2/0/18
+e23-3 distro2 ge-0/0/10 ge-1/0/10 ge-2/0/10
+e23-4 distro2 ge-0/0/11 ge-1/0/11 ge-2/0/11
+e25-1 distro3 ge-0/0/0 ge-1/0/0 ge-2/0/0
+e25-2 distro3 ge-0/0/1 ge-1/0/1 ge-2/0/1
+e27-1 distro3 ge-0/0/2 ge-1/0/2 ge-2/0/2
+e27-2 distro3 ge-0/0/3 ge-1/0/3 ge-2/0/3
+e29-1 distro3 ge-0/0/4 ge-1/0/4 ge-2/0/4
+e29-2 distro3 ge-0/0/5 ge-1/0/5 ge-2/0/5
+e31-1 distro3 ge-0/0/6 ge-1/0/6 ge-2/0/6
+e31-2 distro3 ge-0/0/7 ge-1/0/7 ge-2/0/7
+e33-1 distro3 ge-0/0/8 ge-1/0/8 ge-2/0/8
+e33-2 distro3 ge-0/0/9 ge-1/0/9 ge-2/0/9
+e35-1 distro3 ge-0/0/10 ge-1/0/10 ge-2/0/10
+e35-2 distro3 ge-0/0/11 ge-1/0/11 ge-2/0/11
+e37-1 distro3 ge-0/0/12 ge-1/0/12 ge-2/0/12
+e37-2 distro3 ge-0/0/13 ge-1/0/13 ge-2/0/13
+e39-1 distro3 ge-0/0/14 ge-1/0/14 ge-2/0/14
+e39-2 distro3 ge-0/0/15 ge-1/0/15 ge-2/0/15
+e41-1 distro4 ge-0/0/0 ge-1/0/0 ge-2/0/0
+e41-2 distro4 ge-0/0/1 ge-1/0/1 ge-2/0/1
+e41-3 distro5 ge-0/0/0 ge-1/0/0 ge-2/0/0
+e41-4 distro5 ge-0/0/1 ge-1/0/1 ge-2/0/1
+e43-1 distro4 ge-0/0/2 ge-1/0/2 ge-2/0/2
+e43-2 distro4 ge-0/0/3 ge-1/0/3 ge-2/0/3
+e43-3 distro5 ge-0/0/2 ge-1/0/2 ge-2/0/2
+e43-4 distro5 ge-0/0/3 ge-1/0/3 ge-2/0/3
+e45-1 distro4 ge-0/0/4 ge-1/0/4 ge-2/0/4
+e45-2 distro4 ge-0/0/5 ge-1/0/5 ge-2/0/5
+e45-3 distro5 ge-0/0/4 ge-1/0/4 ge-2/0/4
+e45-4 distro5 ge-0/0/5 ge-1/0/5 ge-2/0/5
+e47-1 distro4 ge-0/0/6 ge-1/0/6 ge-2/0/6
+e47-2 distro4 ge-0/0/7 ge-1/0/7 ge-2/0/7
+e47-3 distro5 ge-0/0/6 ge-1/0/6 ge-2/0/6
+e47-4 distro5 ge-0/0/7 ge-1/0/7 ge-2/0/7
+e49-1 distro4 ge-0/0/8 ge-1/0/8 ge-2/0/8
+e49-2 distro4 ge-0/0/9 ge-1/0/9 ge-2/0/9
+e49-3 distro5 ge-0/0/8 ge-1/0/8 ge-2/0/8
+e49-4 distro5 ge-0/0/9 ge-1/0/9 ge-2/0/9
+e51-1 distro4 ge-0/0/10 ge-1/0/10 ge-2/0/10
+e51-2 distro4 ge-0/0/11 ge-1/0/11 ge-2/0/11
+e51-3 distro5 ge-0/0/10 ge-1/0/10 ge-2/0/10
+e51-4 distro5 ge-0/0/11 ge-1/0/11 ge-2/0/11
+e53-1 distro4 ge-0/0/12 ge-1/0/12 ge-2/0/12
+e53-2 distro4 ge-0/0/13 ge-1/0/13 ge-2/0/13
+e53-3 distro5 ge-0/0/12 ge-1/0/12 ge-2/0/12
+e53-4 distro5 ge-0/0/13 ge-1/0/13 ge-2/0/13
+e55-1 distro4 ge-0/0/14 ge-1/0/14 ge-2/0/14
+e55-2 distro4 ge-0/0/15 ge-1/0/15 ge-2/0/15
+e55-3 distro5 ge-0/0/14 ge-1/0/14 ge-2/0/14
+e55-4 distro5 ge-0/0/15 ge-1/0/15 ge-2/0/15
+e57-1 distro4 ge-0/0/16 ge-1/0/16 ge-2/0/16
+e57-2 distro4 ge-0/0/17 ge-1/0/17 ge-2/0/17
+e57-3 distro5 ge-0/0/16 ge-1/0/16 ge-2/0/16
+e57-4 distro5 ge-0/0/17 ge-1/0/17 ge-2/0/17
+e59-1 distro7 ge-0/0/0 ge-1/0/0 ge-2/0/0
+e59-2 distro7 ge-0/0/1 ge-1/0/1 ge-2/0/1
+e59-3 distro6 ge-0/0/0 ge-1/0/0 ge-2/0/0
+e59-4 distro6 ge-0/0/1 ge-1/0/1 ge-2/0/1
+e61-1 distro7 ge-0/0/2 ge-1/0/2 ge-2/0/2
+e61-2 distro7 ge-0/0/3 ge-1/0/3 ge-2/0/3
+e61-3 distro6 ge-0/0/2 ge-1/0/2 ge-2/0/2
+e61-4 distro6 ge-0/0/3 ge-1/0/3 ge-2/0/3
+e63-1 distro7 ge-0/0/4 ge-1/0/4 ge-2/0/4
+e63-2 distro7 ge-0/0/5 ge-1/0/5 ge-2/0/5
+e63-3 distro6 ge-0/0/4 ge-1/0/4 ge-2/0/4
+e63-4 distro6 ge-0/0/5 ge-1/0/5 ge-2/0/5
+e65-1 distro7 ge-0/0/6 ge-1/0/6 ge-2/0/6
+e65-2 distro7 ge-0/0/7 ge-1/0/7 ge-2/0/7
+e65-3 distro6 ge-0/0/6 ge-1/0/6 ge-2/0/6
+e65-4 distro6 ge-0/0/7 ge-1/0/7 ge-2/0/7
+e67-1 distro7 ge-0/0/8 ge-1/0/8 ge-2/0/8
+e67-2 distro7 ge-0/0/9 ge-1/0/9 ge-2/0/9
+e67-3 distro6 ge-0/0/8 ge-1/0/8 ge-2/0/8
+e67-4 distro6 ge-0/0/9 ge-1/0/9 ge-2/0/9
+e69-1 distro7 ge-0/0/10 ge-1/0/10 ge-2/0/10
+e69-2 distro7 ge-0/0/11 ge-1/0/11 ge-2/0/11
+e71-1 distro7 ge-0/0/12 ge-1/0/12 ge-2/0/12
+e71-2 distro7 ge-0/0/13 ge-1/0/13 ge-2/0/13
+e73-1 distro7 ge-0/0/14 ge-1/0/14 ge-2/0/14
+e73-2 distro7 ge-0/0/15 ge-1/0/15 ge-2/0/15
+e75-1 distro7 ge-0/0/16 ge-1/0/16 ge-2/0/16
+e75-2 distro7 ge-0/0/17 ge-1/0/17 ge-2/0/17
+e77-1 distro7 ge-0/0/18 ge-1/0/18 ge-2/0/18
+e77-2 distro7 ge-0/0/19 ge-1/0/19 ge-2/0/19
+e79-1 distro7 ge-0/0/20 ge-1/0/20 ge-2/0/20
+e79-2 distro7 ge-0/0/21 ge-1/0/21 ge-2/0/21
+e81-1 distro7 ge-0/0/22 ge-1/0/22 ge-2/0/22
+e81-2 distro7 ge-0/0/23 ge-1/0/23 ge-2/0/23
+e83-2 distro7 ge-0/0/24 ge-1/0/24 ge-2/0/24
+e85-2 distro7 ge-0/0/25 ge-1/0/25 ge-2/0/25
diff --git a/extras/fap/httpd/httpd_root/tools/switches.txt b/extras/fap/httpd/httpd_root/tools/switches.txt
new file mode 100644
index 0000000..67b49f4
--- /dev/null
+++ b/extras/fap/httpd/httpd_root/tools/switches.txt
@@ -0,0 +1,131 @@
+e1-3 88.92.0.0/26 2a06:5840:0a::/64 88.92.54.2/26 2a06:5840:54a::2/64 1013 distro0
+e1-4 88.92.0.64/26 2a06:5840:0b::/64 88.92.54.3/26 2a06:5840:54a::3/64 1014 distro0
+e3-3 88.92.0.128/26 2a06:5840:0c::/64 88.92.54.4/26 2a06:5840:54a::4/64 1033 distro0
+e3-4 88.92.0.192/26 2a06:5840:0d::/64 88.92.54.5/26 2a06:5840:54a::5/64 1034 distro0
+e5-2 88.92.1.0/26 2a06:5840:1a::/64 88.92.54.66/26 2a06:5840:54b::66/64 1052 distro1
+e5-3 88.92.1.64/26 2a06:5840:1b::/64 88.92.54.6/26 2a06:5840:54a::6/64 1053 distro0
+e5-4 88.92.1.128/26 2a06:5840:1c::/64 88.92.54.7/26 2a06:5840:54a::7/64 1054 distro0
+e7-1 88.92.1.192/26 2a06:5840:1d::/64 88.92.54.67/26 2a06:5840:54b::67/64 1071 distro1
+e7-2 88.92.2.0/26 2a06:5840:2a::/64 88.92.54.68/26 2a06:5840:54b::68/64 1072 distro1
+e7-3 88.92.2.64/26 2a06:5840:2b::/64 88.92.54.8/26 2a06:5840:54a::8/64 1073 distro0
+e7-4 88.92.2.128/26 2a06:5840:2c::/64 88.92.54.9/26 2a06:5840:54a::9/64 1074 distro0
+e9-1 88.92.2.192/26 2a06:5840:2d::/64 88.92.54.69/26 2a06:5840:54b::69/64 1091 distro1
+e9-2 88.92.3.0/26 2a06:5840:3a::/64 88.92.54.70/26 2a06:5840:54b::70/64 1092 distro1
+e9-3 88.92.3.64/26 2a06:5840:3b::/64 88.92.54.10/26 2a06:5840:54a::10/64 1093 distro0
+e9-4 88.92.3.128/26 2a06:5840:3c::/64 88.92.54.11/26 2a06:5840:54a::11/64 1094 distro0
+e11-1 88.92.3.192/26 2a06:5840:3d::/64 88.92.54.71/26 2a06:5840:54b::71/64 1111 distro1
+e11-2 88.92.4.0/26 2a06:5840:4a::/64 88.92.54.72/26 2a06:5840:54b::72/64 1112 distro1
+e11-3 88.92.4.64/26 2a06:5840:4b::/64 88.92.54.12/26 2a06:5840:54a::12/64 1113 distro0
+e11-4 88.92.4.128/26 2a06:5840:4c::/64 88.92.54.13/26 2a06:5840:54a::13/64 1114 distro0
+e13-1 88.92.4.192/26 2a06:5840:4d::/64 88.92.54.73/26 2a06:5840:54b::73/64 1131 distro1
+e13-2 88.92.5.0/26 2a06:5840:5a::/64 88.92.54.74/26 2a06:5840:54b::74/64 1132 distro1
+e13-3 88.92.5.64/26 2a06:5840:5b::/64 88.92.54.130/26 2a06:5840:54c::130/64 1133 distro2
+e13-4 88.92.5.128/26 2a06:5840:5c::/64 88.92.54.131/26 2a06:5840:54c::131/64 1134 distro2
+e15-1 88.92.5.192/26 2a06:5840:5d::/64 88.92.54.75/26 2a06:5840:54b::75/64 1151 distro1
+e15-2 88.92.6.0/26 2a06:5840:6a::/64 88.92.54.76/26 2a06:5840:54b::76/64 1152 distro1
+e15-3 88.92.6.64/26 2a06:5840:6b::/64 88.92.54.132/26 2a06:5840:54c::132/64 1153 distro2
+e15-4 88.92.6.128/26 2a06:5840:6c::/64 88.92.54.133/26 2a06:5840:54c::133/64 1154 distro2
+e17-1 88.92.6.192/26 2a06:5840:6d::/64 88.92.54.77/26 2a06:5840:54b::77/64 1171 distro1
+e17-2 88.92.7.0/26 2a06:5840:7a::/64 88.92.54.78/26 2a06:5840:54b::78/64 1172 distro1
+e17-3 88.92.7.64/26 2a06:5840:7b::/64 88.92.54.134/26 2a06:5840:54c::134/64 1173 distro2
+e17-4 88.92.7.128/26 2a06:5840:7c::/64 88.92.54.135/26 2a06:5840:54c::135/64 1174 distro2
+e19-1 88.92.7.192/26 2a06:5840:7d::/64 88.92.54.79/26 2a06:5840:54b::79/64 1191 distro1
+e19-2 88.92.8.0/26 2a06:5840:8a::/64 88.92.54.80/26 2a06:5840:54b::80/64 1192 distro1
+e19-3 88.92.8.64/26 2a06:5840:8b::/64 88.92.54.136/26 2a06:5840:54c::136/64 1193 distro2
+e19-4 88.92.8.128/26 2a06:5840:8c::/64 88.92.54.137/26 2a06:5840:54c::137/64 1194 distro2
+e21-1 88.92.8.192/26 2a06:5840:8d::/64 88.92.54.81/26 2a06:5840:54b::81/64 1211 distro1
+e21-2 88.92.9.0/26 2a06:5840:9a::/64 88.92.54.82/26 2a06:5840:54b::82/64 1212 distro1
+e21-3 88.92.9.64/26 2a06:5840:9b::/64 88.92.54.138/26 2a06:5840:54c::138/64 1213 distro2
+e21-4 88.92.9.128/26 2a06:5840:9c::/64 88.92.54.139/26 2a06:5840:54c::139/64 1214 distro2
+e23-1 88.92.9.192/26 2a06:5840:9d::/64 88.92.54.83/26 2a06:5840:54b::83/64 1231 distro1
+e23-2 88.92.10.0/26 2a06:5840:10a::/64 88.92.54.84/26 2a06:5840:54b::84/64 1232 distro1
+e23-3 88.92.10.64/26 2a06:5840:10b::/64 88.92.54.140/26 2a06:5840:54c::140/64 1233 distro2
+e23-4 88.92.10.128/26 2a06:5840:10c::/64 88.92.54.141/26 2a06:5840:54c::141/64 1234 distro2
+e25-1 88.92.10.192/26 2a06:5840:10d::/64 88.92.54.194/26 2a06:5840:54d::194/64 1251 distro3
+e25-2 88.92.11.0/26 2a06:5840:11a::/64 88.92.54.195/26 2a06:5840:54d::195/64 1252 distro3
+e27-1 88.92.11.64/26 2a06:5840:11b::/64 88.92.54.196/26 2a06:5840:54d::196/64 1271 distro3
+e27-2 88.92.11.128/26 2a06:5840:11c::/64 88.92.54.197/26 2a06:5840:54d::197/64 1272 distro3
+e29-1 88.92.11.192/26 2a06:5840:11d::/64 88.92.54.198/26 2a06:5840:54d::198/64 1291 distro3
+e29-2 88.92.12.0/26 2a06:5840:12a::/64 88.92.54.199/26 2a06:5840:54d::199/64 1292 distro3
+e31-1 88.92.12.64/26 2a06:5840:12b::/64 88.92.54.200/26 2a06:5840:54d::200/64 1311 distro3
+e31-2 88.92.12.128/26 2a06:5840:12c::/64 88.92.54.201/26 2a06:5840:54d::201/64 1312 distro3
+e33-1 88.92.12.192/26 2a06:5840:12d::/64 88.92.54.202/26 2a06:5840:54d::202/64 1331 distro3
+e33-2 88.92.13.0/26 2a06:5840:13a::/64 88.92.54.203/26 2a06:5840:54d::203/64 1332 distro3
+e35-1 88.92.13.64/26 2a06:5840:13b::/64 88.92.54.204/26 2a06:5840:54d::204/64 1351 distro3
+e35-2 88.92.13.128/26 2a06:5840:13c::/64 88.92.54.205/26 2a06:5840:54d::205/64 1352 distro3
+e37-1 88.92.13.192/26 2a06:5840:13d::/64 88.92.54.206/26 2a06:5840:54d::206/64 1371 distro3
+e37-2 88.92.14.0/26 2a06:5840:14a::/64 88.92.54.207/26 2a06:5840:54d::207/64 1372 distro3
+e39-1 88.92.14.64/26 2a06:5840:14b::/64 88.92.54.208/26 2a06:5840:54d::208/64 1391 distro3
+e39-2 88.92.14.128/26 2a06:5840:14c::/64 88.92.54.209/26 2a06:5840:54d::209/64 1392 distro3
+e41-1 88.92.14.192/26 2a06:5840:14d::/64 88.92.55.2/26 2a06:5840:55a::2/64 1411 distro4
+e41-2 88.92.15.0/26 2a06:5840:15a::/64 88.92.55.3/26 2a06:5840:55a::3/64 1412 distro4
+e41-3 88.92.15.64/26 2a06:5840:15b::/64 88.92.55.66/26 2a06:5840:55b::66/64 1413 distro5
+e41-4 88.92.15.128/26 2a06:5840:15c::/64 88.92.55.67/26 2a06:5840:55b::67/64 1414 distro5
+e43-1 88.92.15.192/26 2a06:5840:15d::/64 88.92.55.4/26 2a06:5840:55a::4/64 1431 distro4
+e43-2 88.92.16.0/26 2a06:5840:16a::/64 88.92.55.5/26 2a06:5840:55a::5/64 1432 distro4
+e43-3 88.92.16.64/26 2a06:5840:16b::/64 88.92.55.68/26 2a06:5840:55b::68/64 1433 distro5
+e43-4 88.92.16.128/26 2a06:5840:16c::/64 88.92.55.69/26 2a06:5840:55b::69/64 1434 distro5
+e45-1 88.92.16.192/26 2a06:5840:16d::/64 88.92.55.6/26 2a06:5840:55a::6/64 1451 distro4
+e45-2 88.92.17.0/26 2a06:5840:17a::/64 88.92.55.7/26 2a06:5840:55a::7/64 1452 distro4
+e45-3 88.92.17.64/26 2a06:5840:17b::/64 88.92.55.70/26 2a06:5840:55b::70/64 1453 distro5
+e45-4 88.92.17.128/26 2a06:5840:17c::/64 88.92.55.71/26 2a06:5840:55b::71/64 1454 distro5
+e47-1 88.92.17.192/26 2a06:5840:17d::/64 88.92.55.8/26 2a06:5840:55a::8/64 1471 distro4
+e47-2 88.92.18.0/26 2a06:5840:18a::/64 88.92.55.9/26 2a06:5840:55a::9/64 1472 distro4
+e47-3 88.92.18.64/26 2a06:5840:18b::/64 88.92.55.72/26 2a06:5840:55b::72/64 1473 distro5
+e47-4 88.92.18.128/26 2a06:5840:18c::/64 88.92.55.73/26 2a06:5840:55b::73/64 1474 distro5
+e49-1 88.92.18.192/26 2a06:5840:18d::/64 88.92.55.10/26 2a06:5840:55a::10/64 1491 distro4
+e49-2 88.92.19.0/26 2a06:5840:19a::/64 88.92.55.11/26 2a06:5840:55a::11/64 1492 distro4
+e49-3 88.92.19.64/26 2a06:5840:19b::/64 88.92.55.74/26 2a06:5840:55b::74/64 1493 distro5
+e49-4 88.92.19.128/26 2a06:5840:19c::/64 88.92.55.75/26 2a06:5840:55b::75/64 1494 distro5
+e51-1 88.92.19.192/26 2a06:5840:19d::/64 88.92.55.12/26 2a06:5840:55a::12/64 1511 distro4
+e51-2 88.92.20.0/26 2a06:5840:20a::/64 88.92.55.13/26 2a06:5840:55a::13/64 1512 distro4
+e51-3 88.92.20.64/26 2a06:5840:20b::/64 88.92.55.76/26 2a06:5840:55b::76/64 1513 distro5
+e51-4 88.92.20.128/26 2a06:5840:20c::/64 88.92.55.77/26 2a06:5840:55b::77/64 1514 distro5
+e53-1 88.92.20.192/26 2a06:5840:20d::/64 88.92.55.14/26 2a06:5840:55a::14/64 1531 distro4
+e53-2 88.92.21.0/26 2a06:5840:21a::/64 88.92.55.15/26 2a06:5840:55a::15/64 1532 distro4
+e53-3 88.92.21.64/26 2a06:5840:21b::/64 88.92.55.78/26 2a06:5840:55b::78/64 1533 distro5
+e53-4 88.92.21.128/26 2a06:5840:21c::/64 88.92.55.79/26 2a06:5840:55b::79/64 1534 distro5
+e55-1 88.92.21.192/26 2a06:5840:21d::/64 88.92.55.16/26 2a06:5840:55a::16/64 1551 distro4
+e55-2 88.92.22.0/26 2a06:5840:22a::/64 88.92.55.17/26 2a06:5840:55a::17/64 1552 distro4
+e55-3 88.92.22.64/26 2a06:5840:22b::/64 88.92.55.80/26 2a06:5840:55b::80/64 1553 distro5
+e55-4 88.92.22.128/26 2a06:5840:22c::/64 88.92.55.81/26 2a06:5840:55b::81/64 1554 distro5
+e57-1 88.92.22.192/26 2a06:5840:22d::/64 88.92.55.18/26 2a06:5840:55a::18/64 1571 distro4
+e57-2 88.92.23.0/26 2a06:5840:23a::/64 88.92.55.19/26 2a06:5840:55a::19/64 1572 distro4
+e57-3 88.92.23.64/26 2a06:5840:23b::/64 88.92.55.82/26 2a06:5840:55b::82/64 1573 distro5
+e57-4 88.92.23.128/26 2a06:5840:23c::/64 88.92.55.83/26 2a06:5840:55b::83/64 1574 distro5
+e59-1 88.92.23.192/26 2a06:5840:23d::/64 88.92.55.194/26 2a06:5840:55d::194/64 1591 distro7
+e59-2 88.92.24.0/26 2a06:5840:24a::/64 88.92.55.195/26 2a06:5840:55d::195/64 1592 distro7
+e59-3 88.92.24.64/26 2a06:5840:24b::/64 88.92.55.130/26 2a06:5840:55c::130/64 1593 distro6
+e59-4 88.92.24.128/26 2a06:5840:24c::/64 88.92.55.131/26 2a06:5840:55c::131/64 1594 distro6
+e61-1 88.92.24.192/26 2a06:5840:24d::/64 88.92.55.196/26 2a06:5840:55d::196/64 1611 distro7
+e61-2 88.92.25.0/26 2a06:5840:25a::/64 88.92.55.197/26 2a06:5840:55d::197/64 1612 distro7
+e61-3 88.92.25.64/26 2a06:5840:25b::/64 88.92.55.132/26 2a06:5840:55c::132/64 1613 distro6
+e61-4 88.92.25.128/26 2a06:5840:25c::/64 88.92.55.133/26 2a06:5840:55c::133/64 1614 distro6
+e63-1 88.92.25.192/26 2a06:5840:25d::/64 88.92.55.198/26 2a06:5840:55d::198/64 1631 distro7
+e63-2 88.92.26.0/26 2a06:5840:26a::/64 88.92.55.199/26 2a06:5840:55d::199/64 1632 distro7
+e63-3 88.92.26.64/26 2a06:5840:26b::/64 88.92.55.134/26 2a06:5840:55c::134/64 1633 distro6
+e63-4 88.92.26.128/26 2a06:5840:26c::/64 88.92.55.135/26 2a06:5840:55c::135/64 1634 distro6
+e65-1 88.92.26.192/26 2a06:5840:26d::/64 88.92.55.200/26 2a06:5840:55d::200/64 1651 distro7
+e65-2 88.92.27.0/26 2a06:5840:27a::/64 88.92.55.201/26 2a06:5840:55d::201/64 1652 distro7
+e65-3 88.92.27.64/26 2a06:5840:27b::/64 88.92.55.136/26 2a06:5840:55c::136/64 1653 distro6
+e65-4 88.92.27.128/26 2a06:5840:27c::/64 88.92.55.137/26 2a06:5840:55c::137/64 1654 distro6
+e67-1 88.92.27.192/26 2a06:5840:27d::/64 88.92.55.202/26 2a06:5840:55d::202/64 1671 distro7
+e67-2 88.92.28.0/26 2a06:5840:28a::/64 88.92.55.203/26 2a06:5840:55d::203/64 1672 distro7
+e67-3 88.92.28.64/26 2a06:5840:28b::/64 88.92.55.138/26 2a06:5840:55c::138/64 1673 distro6
+e67-4 88.92.28.128/26 2a06:5840:28c::/64 88.92.55.139/26 2a06:5840:55c::139/64 1674 distro6
+e69-1 88.92.28.192/26 2a06:5840:28d::/64 88.92.55.204/26 2a06:5840:55d::204/64 1691 distro7
+e69-2 88.92.29.0/26 2a06:5840:29a::/64 88.92.55.205/26 2a06:5840:55d::205/64 1692 distro7
+e71-1 88.92.29.64/26 2a06:5840:29b::/64 88.92.55.206/26 2a06:5840:55d::206/64 1711 distro7
+e71-2 88.92.29.128/26 2a06:5840:29c::/64 88.92.55.207/26 2a06:5840:55d::207/64 1712 distro7
+e73-1 88.92.29.192/26 2a06:5840:29d::/64 88.92.55.208/26 2a06:5840:55d::208/64 1731 distro7
+e73-2 88.92.30.0/26 2a06:5840:30a::/64 88.92.55.209/26 2a06:5840:55d::209/64 1732 distro7
+e75-1 88.92.30.64/26 2a06:5840:30b::/64 88.92.55.210/26 2a06:5840:55d::210/64 1751 distro7
+e75-2 88.92.30.128/26 2a06:5840:30c::/64 88.92.55.211/26 2a06:5840:55d::211/64 1752 distro7
+e77-1 88.92.30.192/26 2a06:5840:30d::/64 88.92.55.212/26 2a06:5840:55d::212/64 1771 distro7
+e77-2 88.92.31.0/26 2a06:5840:31a::/64 88.92.55.213/26 2a06:5840:55d::213/64 1772 distro7
+e79-1 88.92.31.64/26 2a06:5840:31b::/64 88.92.55.214/26 2a06:5840:55d::214/64 1791 distro7
+e79-2 88.92.31.128/26 2a06:5840:31c::/64 88.92.55.215/26 2a06:5840:55d::215/64 1792 distro7
+e81-1 88.92.31.192/26 2a06:5840:31d::/64 88.92.55.216/26 2a06:5840:55d::216/64 1811 distro7
+e81-2 88.92.32.0/26 2a06:5840:32a::/64 88.92.55.217/26 2a06:5840:55d::217/64 1812 distro7
+e83-2 88.92.32.64/26 2a06:5840:32b::/64 88.92.55.218/26 2a06:5840:55d::218/64 1832 distro7
+e85-2 88.92.32.128/26 2a06:5840:32c::/64 88.92.55.219/26 2a06:5840:55d::219/64 1852 distro7
diff --git a/extras/fap/httpd/httpd_root/tools/update_psql_from_switches_patchlist.php b/extras/fap/httpd/httpd_root/tools/update_psql_from_switches_patchlist.php
new file mode 100644
index 0000000..a787c33
--- /dev/null
+++ b/extras/fap/httpd/httpd_root/tools/update_psql_from_switches_patchlist.php
@@ -0,0 +1,79 @@
+<?php
+
+ /*
+ Ugliest implementation of a kind of ipcalc... FULHAX
+ */
+ function find_v4_def_route($subnet){
+ $subnet = array_shift(explode('/', $subnet));
+ $octets = explode('.', $subnet);
+ $octets[3]++;
+ return implode('.', $octets);
+ }
+ function find_v6_def_route($subnet){
+ $subnet = array_shift(explode('/', $subnet));
+ return str_replace('::', '::1', $subnet);
+ }
+
+ function x($input){
+ $parts = explode('.', $input);
+ if($parts[3] > 192){
+ $last = '193';
+ }elseif($parts[3] > 128){
+ $last = '129';
+ }elseif($parts[3] > 64){
+ $last = '65';
+ }else{
+ $last = '1';
+ }
+
+ return $parts[0] . '.' . $parts[1] . '.' . $parts[2] . '.' . $last;
+ }
+
+
+ require('../pg_connect.php');
+
+ $switches_array = file('switches.txt');
+ $patchlist_array = file('patchlist.txt');
+
+ /*
+ switches.txt: e41-3 88.92.15.64/26 2a06:5840:15b::/64 88.92.55.66/26 2a06:5840:55b::66/64 1413 distro5
+ patchlist.txt: e7-2 distro1 ge-0/0/2 ge-1/0/2 ge-2/0/2
+ */
+
+ $d1 = array(); # dataset
+ foreach($patchlist_array as $line){
+ $t = array(); # temp array in this loop
+ list($switch, $t['distro'], $t['distro_port_0'], $t['distro_port_1'], $t['distro_port_2']) = explode(' ', $line);
+ $t = array_map('trim', $t);
+ $d1[$switch] = $t;
+ }
+
+ $d2 = array(); # dataset
+ foreach($switches_array as $line){
+ $t = array(); # temp array in this loop
+ list($t['switch'], $t['v4_subnet'], $t['v6_subnet'], $t['mgmt_v4_addr'], $t['mgmt_v6_addr'], $t['vlan']) = explode(' ', $line);
+ $t = array_map('trim', $t);
+ $d2[$t['switch']] = $t;
+ }
+ $d = array_merge_recursive($d1, $d2);
+ # var_dump($d);
+
+ foreach($d as $switch => $prop){
+ $q = '
+ UPDATE switches SET
+ distro_phy_port = \'' . pg_escape_string($prop['distro_port_0']) . '\',
+ traffic_vlan = \'' . pg_escape_string($prop['vlan']) . '\',
+ mgmt_v4_gw = \'' . pg_escape_string(x($prop['mgmt_v4_addr'])) . '\'
+ WHERE sysname = \'' . pg_escape_string($switch) . '\'';
+
+ # var_dump($q);
+
+ $result = pg_query($dbconn, $q);
+ if (!$result){
+ echo 'NOPE: ' . $q . "\n";
+ exit;
+ }
+
+ }
+ echo 'done! - no errors';
+?>
diff --git a/extras/fap/tools_temp/README.md b/extras/fap/tools_temp/README.md
new file mode 100644
index 0000000..0c3897e
--- /dev/null
+++ b/extras/fap/tools_temp/README.md
@@ -0,0 +1,3 @@
+# Tools
+
+* get_info.php - snmp gets all devices in a given network to show the Junos versions. TG NMS ("Gundul"?) kinda makes this script redundant.
diff --git a/extras/tools/make_switches.json.sh b/extras/tools/make_switches.json.sh
new file mode 100755
index 0000000..4f7098a
--- /dev/null
+++ b/extras/tools/make_switches.json.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+CORE="core"
+DISTRO="distro"
+ROWS0="1 3 5 7 9"
+ROWS1="11 13 15 17 19"
+ROWS2="21 23 25 27 29"
+ROWS3="31 33 35 37 39"
+N=1
+inc() {
+ N=$(( $N + 1 ))
+}
+echo "[{\"sysname\": \"$core\", \"mgmt_v4_addr\": \"127.0.0.$N\"},"
+inc
+mkswitch() {
+ cat <<_EOF_
+{"sysname": "$1", "distro": "$2", "mgmt_v4_addr": "127.0.0.$N"},
+_EOF_
+inc
+}
+mkswitch ${DISTRO}0 core
+for a in $ROWS0; do
+ mkswitch row${a}-1 distro0
+ mkswitch row${a}-2 distro0
+done
+
+mkswitch ${DISTRO}1 core
+for a in $ROWS1; do
+ mkswitch row${a}-1 distro1
+ mkswitch row${a}-2 distro1
+done
+
+mkswitch ${DISTRO}2 core
+for a in $ROWS2; do
+ mkswitch row${a}-1 distro2
+ mkswitch row${a}-2 distro2
+done
+mkswitch ${DISTRO}3 core
+for a in $ROWS3; do
+ mkswitch row${a}-1 distro3
+ mkswitch row${a}-2 distro3
+done
+cat <<_WOF_
+{"sysname": "noc", "distro": "core", "mgmt_v4_addr": "127.0.0.$N" }]
+_WOF_
+
diff --git a/include/config.pm b/include/config.pm
index 9987d05..c8664cb 100755
--- a/include/config.pm
+++ b/include/config.pm
@@ -25,6 +25,7 @@ our @snmp_objects = [
['ifOperStatus'],
['ifAdminStatus'],
['ifLastChange'],
+ ['ifPhysAddress'],
['ifHCInOctets'],
['ifHCOutOctets'],
['ifInDiscards'],
diff --git a/include/nms.pm b/include/nms.pm
index 273d65d..eff61c3 100755
--- a/include/nms.pm
+++ b/include/nms.pm
@@ -8,7 +8,7 @@ use JSON;
package nms;
use base 'Exporter';
-our @EXPORT = qw(switch_disconnect switch_connect_ssh switch_connect_dlink switch_exec switch_exec_json switch_timeout db_connect);
+our @EXPORT = qw(db_connect convert_mac);
BEGIN {
require "config.pm";
diff --git a/include/nms/dbconfig.pm b/include/nms/dbconfig.pm
new file mode 100644
index 0000000..b67c040
--- /dev/null
+++ b/include/nms/dbconfig.pm
@@ -0,0 +1,29 @@
+# vim:ts=8:sw=8
+use strict;
+use warnings;
+use utf8;
+use DBI;
+use Data::Dumper;
+use JSON;
+use nms;
+package nms::dbconfig;
+
+use base 'Exporter';
+our @EXPORT = qw(%config);
+our %config;
+my $dbh;
+
+use Data::Dumper;
+
+
+BEGIN {
+ $dbh = nms::db_connect();
+ my $q2 = $dbh->prepare('select * from config order by id desc limit 1;');
+ $q2->execute();
+ while (my $ref = $q2->fetchrow_hashref()) {
+ %config = %$ref;
+ $config{'data'} = JSON::XS::decode_json($ref->{'data'});
+ }
+ $dbh->disconnect();
+}
+1;
diff --git a/include/nms/oplog.pm b/include/nms/oplog.pm
new file mode 100644
index 0000000..c5194cf
--- /dev/null
+++ b/include/nms/oplog.pm
@@ -0,0 +1,34 @@
+# vim:ts=8:sw=8
+use strict;
+use warnings;
+use utf8;
+use DBI;
+use Data::Dumper;
+use JSON;
+use nms;
+package nms::oplog;
+
+use base 'Exporter';
+our @EXPORT = qw(oplog);
+my $dbh;
+my $query;
+my $user;
+
+use Data::Dumper;
+
+
+sub oplog {
+ $query->execute($_[0], "[$user]" . $_[1]);
+ $dbh->commit;
+}
+
+BEGIN {
+ $user = $ENV{'REMOTE_USER'} || "internal";
+ $dbh = nms::db_connect();
+ $query = $dbh->prepare("INSERT INTO oplog (username, systems, log) VALUES('system',?,?)");
+}
+
+END {
+ $dbh->disconnect();
+}
+1;
diff --git a/include/nms/util.pm b/include/nms/util.pm
index d2382f9..f79df50 100644
--- a/include/nms/util.pm
+++ b/include/nms/util.pm
@@ -10,7 +10,6 @@ our @EXPORT = qw(guess_placement parse_switches_txt parse_switches parse_switch)
# Parse a single switches.txt-formatted switch
sub parse_switch {
my ($switch, $subnet4, $subnet6, $mgtmt4, $mgtmt6, $lolid, $distro) = split(/ /);
- my %foo = guess_placement($switch);
my %ret = (
'sysname' => "$switch",
'subnet4' => "$subnet4",
@@ -50,10 +49,77 @@ sub parse_switches {
return @switches;
}
-# Guesses placement from name to get a starting point
-#
-# FIXME: Move to configuration
+# FIXME: Derive which function from the config/db using the shortname.
+# If we care.
sub guess_placement {
+ return guess_placement_dx($_[0]);
+}
+# Guesses placement from name to get a starting point
+# Digitality X layout
+# FIXME: Basically a stub, since MRGLASS is too slow with the map.
+sub guess_placement_dx {
+ my ($x, $y, $xx, $yy);
+
+ my $name = $_[0];
+ my $src = "unknown";
+ if ($name =~ /^row\d+-\d+$/) {
+ $name =~ /row(\d+)-(\d+)/;
+ my ($e, $s) = ($1, $2);
+ $src = "main";
+
+ $x = int(1523 - (($e-1)/2) * 61);
+ $y = undef;
+
+ if ($s > 1) {
+ $y = 137;
+ } else {
+ $y = 410;
+ }
+
+ $xx = $x + 32;
+ $yy = $y + 200;
+
+ } elsif ($name =~ /^core$/) {
+ $src = "core";
+ $x = 1100;
+ $y = 650;
+ $xx = $x + 200;
+ $yy = $y + 100;
+ } elsif ($name =~ /^noc$/) {
+ $src = "noc";
+ $x = 300;
+ $y = 800;
+ $xx = $x + 230;
+ $yy = $y + 40;
+ } elsif ($name =~ /^distro(\d)$/) {
+ my $d = ($1);
+ $src = "distro";
+ $x = 1200 - $d * 700;
+ $y = 355;
+ $xx = $x + 230;
+ $yy = $y + 40;
+ } else {
+ # Fallback to have _some_ position
+ $src = "random";
+ $x = int(rand(1900));
+ $y = int(rand(900));
+ $xx = $x + 230;
+ $yy = $y + 40;
+ };
+
+
+ my %box = (
+ 'src' => "$src",
+ 'x1' => $x,
+ 'y1' => $y,
+ 'xx' => $xx,
+ 'yy' => $yy
+ );
+ return %box;
+}
+
+# Last updated for TG16
+sub guess_placement_tg {
my ($x, $y, $xx, $yy);
my $name = $_[0];
diff --git a/include/nms/web.pm b/include/nms/web.pm
index 8a20f50..18fe919 100755
--- a/include/nms/web.pm
+++ b/include/nms/web.pm
@@ -67,7 +67,7 @@ sub setwhen {
$offset = $_[1];
}
if (defined($get_params{'now'})) {
- $now = db_safe_quote('now') . "::timestamp with time zone ";
+ $now = "timestamp with time zone 'epoch' + " . db_safe_quote('now') . " * INTERVAL '1 second' ";
$cc{'max-age'} = "3600";
}
$now = "(" . $now . " - '" . $offset . "'::interval)";
diff --git a/web/api/public/config b/web/api/public/config
index dd8ccc1..0f0d322 100755
--- a/web/api/public/config
+++ b/web/api/public/config
@@ -15,6 +15,9 @@ my $hostname = $ENV{'HTTP_HOST'} || "";
my $q2 = $nms::web::dbh->prepare('select id, publicvhost, shortname, data from config order by id desc limit 1;');
$q2->execute();
+$nms::web::json{'config'}{'data'} = 0;
+$nms::web::json{'config'}{'shortname'} = "notset";
+$nms::web::json{'config'}{'publicvhost'} = "notset";
while (my $ref = $q2->fetchrow_hashref()) {
$nms::web::json{'config'} = $ref;
$nms::web::json{'config'}{'data'} = JSON::XS::decode_json($ref->{'data'});
diff --git a/web/api/public/ping b/web/api/public/ping
index 36e3334..1928368 100755
--- a/web/api/public/ping
+++ b/web/api/public/ping
@@ -11,20 +11,24 @@ my $q = $nms::web::dbh->prepare("SELECT DISTINCT ON (sysname) (" . $nms::web::no
$q->execute();
while (my $ref = $q->fetchrow_hashref()) {
- $nms::web::json{'switches'}{$ref->{'sysname'}}{'latency'} = $ref->{'latency_ms'};
+ $nms::web::json{'switches'}{$ref->{'sysname'}}{'latency4'} = $ref->{'latency_ms'};
# Get seconds, without decimlas, from timestamp.
# '00:01:01.435601' => 61 seconds.
my ( $h, $m, $s ) = split( ':|\.', $ref->{'age'} );
- $nms::web::json{'switches'}{$ref->{'sysname'}}{'age'} = ($h*60*60) + ($m*60) + $s; # $$ref->{'age'};
+ $nms::web::json{'switches'}{$ref->{'sysname'}}{'age4'} = ($h*60*60) + ($m*60) + $s; # $$ref->{'age'};
}
-my $qs = $nms::web::dbh->prepare("SELECT DISTINCT ON (switch) switch, latency_ms FROM ping_secondary_ip WHERE "
- . $nms::web::when . " ORDER BY switch, time DESC;");
-$qs->execute();
-while ( my $ref = $qs->fetchrow_hashref() ) {
- $nms::web::json{'switches'}{$ref->{'switch'}}{'latency_secondary'} = $ref->{'latency_ms'};
-}
+my $q2 = $nms::web::dbh->prepare("SELECT DISTINCT ON (sysname) (" . $nms::web::now . " - time) as age,sysname, latency_ms FROM ping_secondary_ip NATURAL JOIN switches WHERE time in (select max(time) from ping where "
+ . $nms::web::when . " group by switch)");
+$q2->execute();
+while (my $ref = $q2->fetchrow_hashref()) {
+ $nms::web::json{'switches'}{$ref->{'sysname'}}{'latency6'} = $ref->{'latency_ms'};
+ # Get seconds, without decimlas, from timestamp.
+ # '00:01:01.435601' => 61 seconds.
+ my ( $h, $m, $s ) = split( ':|\.', $ref->{'age'} );
+ $nms::web::json{'switches'}{$ref->{'sysname'}}{'age6'} = ($h*60*60) + ($m*60) + $s; # $$ref->{'age'};
+}
my $lq = $nms::web::dbh->prepare("SELECT DISTINCT ON (linknet) linknet, latency1_ms, latency2_ms FROM linknet_ping WHERE "
. $nms::web::when . " ORDER BY linknet, time DESC;");
$lq->execute();
diff --git a/web/api/read/switches-management b/web/api/read/switches-management
index 2dd329c..8d899b7 100755
--- a/web/api/read/switches-management
+++ b/web/api/read/switches-management
@@ -12,7 +12,7 @@ use Data::Dumper;
$nms::web::cc{'max-age'} = "60";
-my $q2 = $nms::web::dbh->prepare('select switch,sysname,mgmt_v4_addr,subnet4,subnet6,mgmt_v6_addr,mgmt_v4_gw,mgmt_v6_gw,mgmt_vlan,traffic_vlan,last_config_fetch,current_mac,poll_frequency,last_updated,distro_phy_port from switches where placement is not null');
+my $q2 = $nms::web::dbh->prepare('select sysname,mgmt_v4_addr,subnet4,subnet6,mgmt_v6_addr,mgmt_v4_gw,mgmt_v6_gw,mgmt_vlan,traffic_vlan,last_config_fetch,current_mac,poll_frequency,last_updated,distro_phy_port,community from switches where placement is not null');
$q2->execute();
while (my $ref = $q2->fetchrow_hashref()) {
diff --git a/web/api/write/linknet-add b/web/api/write/linknet-add
new file mode 100755
index 0000000..13ccd17
--- /dev/null
+++ b/web/api/write/linknet-add
@@ -0,0 +1,32 @@
+#! /usr/bin/perl
+# vim:ts=8:sw=8
+use lib '/opt/gondul/include';
+use utf8;
+use nms::web qw($dbh db_safe_quote get_input finalize_output);
+use strict;
+use warnings;
+
+my $in = get_input();
+my %tmp = %{JSON::XS::decode_json($in)};
+
+my $q = $nms::web::dbh->prepare("INSERT INTO linknets (switch1, switch2) VALUES((SELECT switch FROM switches WHERE sysname = ? LIMIT 1), (SELECT switch FROM switches WHERE sysname = ? LIMIT 1));");
+my $sth = $nms::web::dbh->prepare("SELECT linknet FROM linknets WHERE switch1 = (SELECT switch FROM switches WHERE sysname = ? LIMIT 1) and switch2 = (SELECT switch FROM switches WHERE sysname = ? LIMIT 1);");
+
+$sth->execute($tmp{'switch1'}, $tmp{'switch2'});
+my $affected = 0;
+while ( my @row = $sth->fetchrow_array ) {
+ $affected += 1;
+}
+
+print "X-affected: $affected\n";
+if ($affected eq 0) {
+ $q->execute($tmp{'switch1'}, $tmp{'switch2'});
+}
+
+$dbh->commit;
+$nms::web::cc{'max-age'} = '0';
+$nms::web::cc{'stale-while-revalidate'} = '0';
+$nms::web::json{'state'} = 'ok';
+
+print "X-ban: /api/public/.*\n";
+finalize_output();
diff --git a/web/api/write/oplog b/web/api/write/oplog
index 736ba2b..73b807b 100755
--- a/web/api/write/oplog
+++ b/web/api/write/oplog
@@ -9,7 +9,7 @@ use warnings;
my $in = get_input();
my %tmp = %{JSON::XS::decode_json($in)};
-my $user = $ENV{'REMOTE_USER'} || "undefined";
+my $user = $tmp{'user'} || $ENV{'REMOTE_USER'} || "undefined";
my $q = $nms::web::dbh->prepare("INSERT INTO oplog (username, systems, log) values (?,?,?);");
$q->execute($user, $tmp{'systems'}, $tmp{'log'});
diff --git a/web/api/write/switch-add b/web/api/write/switch-add
index 56e5cb2..f77df0a 100755
--- a/web/api/write/switch-add
+++ b/web/api/write/switch-add
@@ -11,6 +11,7 @@ use strict;
use warnings;
use JSON;
use Data::Dumper;
+use nms::oplog qw(oplog);
$nms::web::cc{'max-age'} = "0";
@@ -83,10 +84,11 @@ foreach my $tmp2 (@tmp) {
$nms::web::dbh->do("INSERT INTO SWITCHES (mgmt_v4_addr, sysname, poll_frequency, community, lldp_chassis_id, mgmt_v6_addr, placement,subnet4,subnet6,distro_name) VALUES ($template{'mgmt_v4_addr'}, $template{'sysname'}, $template{'poll_frequency'}, $template{'community'}, $template{'lldp_chassis_id'}, $template{'mgmt_v6_addr'}, $template{'placement'},$template{'subnet4'},$template{'subnet6'},$template{'distro_name'});");
push @added, $switch{'sysname'};
+ oplog("\"" . $switch{'sysname'} . "\"", "Switch added: " . $switch{'sysname'});
}
}
$json{'switches_addded'} = \@added;
-print "X-ban: /api/.*switches.*\n";
+print "X-ban: /api/.*\n";
finalize_output();
diff --git a/web/css/nms.css b/web/css/nms.css
new file mode 100644
index 0000000..c54dd98
--- /dev/null
+++ b/web/css/nms.css
@@ -0,0 +1,77 @@
+canvas {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ outline: none;
+ -webkit-tap-highlight-color: rgba(255, 255, 255, 0); /* mobile webkit */
+}
+tr.mgmt_v4_addr {
+ font-weight: 700;
+}
+h1.map-mode-title {
+ font-weight: 700;
+ font-size: 55px;
+ display: block;
+ position: absolute;
+ z-index: 55;
+ text-shadow: -4px -4px 5px white,-4px 0px 5px white,0px -4px 5px white,0px 0px 5px white,4px 4px 5px white,4px 0px 5px white,0px 4px 5px white;
+}
+.gondul-public .gondul-is-private {
+ display: none;
+}
+.vertical h1.map-mode-title {
+ left: 30px;
+ bottom: 0px;
+ position: absolute;
+ transform-origin: 0px 0% 0px;
+ transform: rotate(-90deg);
+}
+.nightmode { color: #ddd; }
+.nightmode h1.map-mode-title {
+ text-shadow: -4px -4px 5px black,-4px 0px 5px black,0px -4px 5px black,0px 0px 5px black,4px 4px 5px black,4px 0px 5px black,0px 4px 5px black;
+}
+.logbook {
+ background-color: rgba(255,255,255,0.1);
+ text-shadow: -4px -4px 5px white,-4px 0px 5px white,0px -4px 5px white,0px 0px 5px white,4px 4px 5px white,4px 0px 5px white,0px 4px 5px white;
+}
+.nightmode .logbook {
+ background-color: rgba(0,0,0,0.1);
+ text-shadow: -4px -4px 5px black,-4px 0px 5px black,0px -4px 5px black,0px 0px 5px black,4px 4px 5px black,4px 0px 5px black,0px 4px 5px black;
+}
+div.map-mode-legend {
+ position: fixed;
+ bottom: 5px;
+ right: 15px;
+ z-index: 999;
+}
+#admin, #oplog {
+ display: none;
+}
+.vertical div.map-mode-legend {
+ top: -10px;
+ right: 30px;
+ position: absolute;
+ transform-origin: 100% 100% 0;
+ transform: rotate(-90deg);
+ height: 40px;
+}
+div.map-mode-legend button {
+ font-size: 16px;
+ font-weight: 700;
+}
+.nightmode .panel {
+ background: #222;
+ border-color: #555;
+}
+
+.nightmode .panel .panel-heading {
+ background: #333;
+ border-color: #555;
+ color: #ddd;
+}
+.nightmode .table > tbody > tr > td {
+ border-top: 1px solid #555;
+}
diff --git a/web/img/dx16-salkart.png b/web/img/dx16-salkart.png
new file mode 100644
index 0000000..aecedd0
--- /dev/null
+++ b/web/img/dx16-salkart.png
Binary files differ
diff --git a/web/index.html b/web/index.html
index 63a9bd0..ca97ad0 100644
--- a/web/index.html
+++ b/web/index.html
@@ -20,84 +20,7 @@
<!-- Date-picker styles -->
<link href="css/jquery.datetimepicker.css" rel="stylesheet">
- <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
- <!--[if lt IE 9]>
- <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
- <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
- <![endif]-->
- <style type="text/css">
- canvas {
- -webkit-touch-callout: none;
- -webkit-user-select: none;
- -khtml-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- outline: none;
- -webkit-tap-highlight-color: rgba(255, 255, 255, 0); /* mobile webkit */
- }
- tr.mgmt_v4_addr {
- font-weight: 700;
- }
- h1.map-mode-title {
- font-weight: 700;
- font-size: 55px;
- color: black;
- display: block;
- position: absolute;
- z-index: 55;
- text-shadow: 4px 4px 5px white;
- }
- .gondul-public .gondul-is-private {
- display: none;
- }
- .vertical h1.map-mode-title {
- left: 30px;
- bottom: 0px;
- position: absolute;
- transform-origin: 0px 0% 0px;
- transform: rotate(-90deg);
- }
- .nightmode h1.map-mode-title {
- color: white;
- text-shadow: 4px 4px 5px black;
- }
- .logbook {
- background-color: rgba(255,255,255,0.7);
- color: black;
- }
- .nightmode .logbook {
- background-color: rgba(0,0,0,0.7);
- color: white;
- }
- .tvmode #topCanvas {
- display: none;
- }
- div.map-mode-legend {
- position: fixed;
- bottom: 5%;
- right: 5%;
- z-index: 999;
- }
- #admin {
- display: none;
- }
- #oplog {
- display: none;
- }
- .vertical div.map-mode-legend {
- top: -10px;
- right: 30px;
- position: absolute;
- transform-origin: 100% 100% 0;
- transform: rotate(-90deg);
- height: 40px;
- }
- div.map-mode-legend button {
- font-size: 20px;
- font-weight: 700;
- }
- </style>
+ <link href="css/nms.css" rel="stylesheet">
</head>
<body id="body">
@@ -121,18 +44,20 @@
<span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu">
- <li><a href="#ping" onclick="setUpdater(handler_ping)">Ping map</a></li>
- <li><a href="#uplink" onclick="setUpdater(handler_uplinks)">Uplink map</a></li>
- <li><a href="#dhcp" onclick="setUpdater(handler_dhcp)">DHCP map</a></li>
- <li><a href="#temp" onclick="setUpdater(handler_temp)">Temperature map</a></li>
- <li><a href="#traffic" onclick="setUpdater(handler_traffic)">Traffic map</a></li>
+ <li class="gondul-is-private"><a href="#health" onclick="setUpdater(handler_health)">Health</a></li>
+ <li><a href="#ping" onclick="setUpdater(handler_ping)">Ping</a></li>
+ <li><a href="#uplink" onclick="setUpdater(handler_uplinks)">Uplink</a></li>
+ <li><a href="#dhcp" onclick="setUpdater(handler_dhcp)">DHCP</a></li>
+ <li><a href="#temp" onclick="setUpdater(handler_temp)">Temperature</a></li>
+ <li><a href="#traffic" onclick="setUpdater(handler_traffic)">Traffic</a></li>
<li><a href="#traffictot" onclick="setUpdater(handler_traffic_tot)">Total switch traffic</a></li>
- <li class="gondul-is-private"><a href="#snmp" onclick="setUpdater(handler_snmp)">SNMP map</a></li>
- <li class="gondul-is-private"><a href="#cpu" onclick="setUpdater(handler_cpu)">CPU map</a></li>
+ <li class="gondul-is-private"><a href="#snmp" onclick="setUpdater(handler_snmp)">SNMP</a></li>
+ <li class="gondul-is-private"><a href="#cpu" onclick="setUpdater(handler_cpu)">CPU</a></li>
<li><a href="#disco" onclick="setUpdater(handler_disco)">DISCO</a></li>
<li class="divider"> </li>
- <li><a href="#" onclick="toggleLayer('nowPickerBox');startNowPicker();">Travel in time</a></li>
- <li><a href="#" onclick="nms.playback.startReplay('2016-03-21T09:00:00','2016-03-27T12:00:00');" title="Replay from opening 120 minutes per second">Replay TG</a></li>
+ <li class="dropdown-header">Time</li>
+ <li><a href="#" onclick="toggleLayer('nowPickerBox');nmsTime.startNowPicker();">Travel in time</a></li>
+ <li><a href="#" onclick="nmsTime.replayEvent();" title="Replay from opening 120 minutes per second">Replay event</a></li>
<li class="divider"> </li>
<li class="dropdown-header">View</li>
<li><a href="#" onclick="toggleNightMode()">Toggle Night Mode</a></li>
@@ -155,8 +80,9 @@
</li>
<div class="navbar-form navbar-left">
<div class="input-group input-group-sm">
- <input id="searchbox" type="text" class="form-control" placeholder="Filter" oninput="nmsInfoBox._search()" />
+ <input id="searchbox" type="text" class="form-control" placeholder="Filter" oninput="nmsSearch.search()" />
<span class="input-group-btn">
+ <button id="searchbox-x" class="btn btn-default" type="button" onclick="nmsSearch.reset();">X</button>
<button id="searchbox-help" class="btn btn-default" type="button" onclick="nmsInfoBox.showWindow('searchHelp');">?</button>
<button id="searchbox-submit" class="btn btn-default" type="button" onclick="nmsInfoBox.showWindow('switchInfo',document.getElementById('searchbox').value);">Go!</button>
</span>
@@ -173,6 +99,7 @@
</div>
<button id="logbox-submit" class="btn btn-default" type="button" onclick="nmsOplog.commit();">Log</button>
</div>
+ <p onclick="nmsOplog.getUser(true);" id="logbook-name" class="navbar-text navbar-right"></p>
</div><!--/.nav-collapse -->
</div>
@@ -180,19 +107,25 @@
<div class="container-fluid" id="admin">
- <div class="row-fluid" id="admin-row">
- </div>
+ <div class="row-fluid" id="admin-row">
+ <div>
+ <p>Add linknet</p>
+ <input id="admin-input-linknet1" type="text" placeholder="Switch 1" />
+ <input id="admin-input-linknet2" type="text" placeholder="Switch 2" />
+ <button class="btn btn-primary" onclick="nmsAdmin.addLinknet()">Add</button>
+ </div>
+ <hr>
+ </div>
</div>
<div class="container-fluid" id="oplog">
- <div class="row-fluid" id="oplog-row">
+ <div class="row-fluid" id="oplog-row">
<div id="oplog-parent" class="logbook">
- <table id="oplog-table" class="table table-condensed">
- </table>
+ <table id="oplog-table" class="table table-condensed">
+ </table>
</div>
- </div>
+ </div>
</div>
<div class="container-fluid" id="map">
-
<div class="row-fluid">
<div class="span12">
<div id="aboutKeybindings" class="col-md-4" style="position: absolute; display:none; z-index: 130;">
@@ -234,6 +167,10 @@
<td>View DHCP map</td>
</tr>
<tr>
+ <td>4</td>
+ <td>View super-map</td>
+ </tr>
+ <tr>
<td>5</td>
<td>View temperature map</td>
</tr>
@@ -287,40 +224,37 @@
<div id="nowPickerBox" style="position: absolute; display: none; z-index: 130;" class="col-sm-6 col-md-5">
<div class="panel panel-default">
<div class="panel-heading">
- <h3 class="panel-title">Time travel
- <button type="button" class="close" aria-labe="Close" onclick="document.getElementById('nowPickerBox').style.display = 'none';" style="float: right;">
- <span aria-hidden="true">&times;</span>
- </button>
- </h3>
+ <h3 class="panel-title">Time travel
+ <button type="button" class="close" aria-labe="Close" onclick="document.getElementById('nowPickerBox').style.display = 'none';" style="float: right;">
+ <span aria-hidden="true">&times;</span>
+ </button>
+ </h3>
</div>
<div class="panel-body row">
<div class="col-sm-12">
<div class="form-group">
<input type="text" class="form-control" placeholder="YYYY-MM-DDThh:mm:ss" id="nowPicker">
<div class="button-group">
- <button class="btn btn-primary" onclick="nms.playback.setNow(document.getElementById('nowPicker').dataset.iso);hideLayer('nowPickerBox');">Travel</button>
- <button class="btn btn-danger" onclick="startNowPicker(Date.now());nms.playback.setNow(false);nms.playback.play();">Back to reality</button>
+ <button class="btn btn-primary" onclick="nmsTime.setNow(document.getElementById('nowPicker').dataset.iso);hideLayer('nowPickerBox');">Travel</button>
+ <button class="btn btn-danger" onclick="nmsTime.realTime();hideLayer('nowPickerBox');">Back to reality</button>
<button class="btn btn-info" data-toggle="button" onclick="toggleLayer('nowPickerInfo');">Info</button>
</div>
</div>
</div>
<div id="nowPickerInfo" class="col-sm-12" style="display:none;">
- <p>Some features do not have time travel support (comment
- spotting and DHCP map at the moment). We also lack
- compatible SNMP data for the first day or so, so you'll
- only have ping data for the first day of TG15.</p>
- <p>It could take some time to load a specific point in time
- for the first time. See "About performance" under the help
- menu for more information.</p>
- <p>You can also step backwards and forwards in time, stop
- and start replay and go back to real time using keyboard
- shortcuts. See the help menu for an overview of keyboard
- shortcuts.</p>
+ <p>Time travel allows you to see the state of the network at a
+ given time, and even fast forward or rewind on the fly with
+ keyboard shortcuts (See the 'keyboard shortcuts' help
+ section).</p>
+ <p>Some features might not work perfectly with time travel, but
+ you should get a pretty good idea of what went on.</p>
+ <p>While we have more detailed data, time travel is limited to
+ five minute intervals by default for performance reasons.</p>
</div>
</div>
</div>
</div>
- <div id="info-box-container" class="col-md-5 hidden" style="position: absolute; z-index: 120;">
+ <div id="info-box-container" class="col-sm-8 col-md-6 col-lg-5 hidden" style="position: absolute; z-index: 120;">
</div>
</div>
@@ -349,7 +283,7 @@
</div>
</div>
- <div style="display:none;"><img id="source" src="img/tg16-salkart-clean-big.png" ></div>
+ <div style="display:none;"><img id="source" src="img/dx16-salkart.png" ></div>
</div>
</div><!--/.fluid-container-->
<script src="js/jquery.min.js" type="text/javascript"></script>
@@ -363,9 +297,11 @@
<script type="text/javascript" src="js/nms-ui.js"></script>
<script type="text/javascript" src="js/nms-admin-pane.js"></script>
<script type="text/javascript" src="js/nms-oplog.js"></script>
+ <script type="text/javascript" src="js/nms-search.js"></script>
+ <script type="text/javascript" src="js/nms-time.js"></script>
<script src="js/jquery.datetimepicker.full.js" type="text/javascript"></script>
<script type="text/javascript">
-initNMS();
+ initNMS();
</script>
</body>
</html>
diff --git a/web/js/nms-admin-pane.js b/web/js/nms-admin-pane.js
index 9edf9f9..235da8d 100644
--- a/web/js/nms-admin-pane.js
+++ b/web/js/nms-admin-pane.js
@@ -78,3 +78,22 @@ nmsAdmin.updateConfigPane = function() {
}
}
}
+
+nmsAdmin.addLinknet = function() {
+ var myData = {
+ "switch1": document.getElementById("admin-input-linknet1").value,
+ "switch2": document.getElementById("admin-input-linknet2").value
+ };
+ myData = JSON.stringify(myData);
+ $.ajax({
+ type: "POST",
+ url: "/api/write/linknet-add",
+ dataType: "text",
+ data:myData,
+ success: function (data, textStatus, jqXHR) {
+ nmsData.invalidate("switches");
+ document.getElementById("admin-input-linknet1").value = "";
+ document.getElementById("admin-input-linknet2").value = "";
+ }
+ });
+}
diff --git a/web/js/nms-color-util.js b/web/js/nms-color-util.js
index 6b5a4b5..ec7f619 100644
--- a/web/js/nms-color-util.js
+++ b/web/js/nms-color-util.js
@@ -1,34 +1,31 @@
-
+"use strict";
/*
* Some stolen colors that look OK.
*
* PS: Stolen from boostrap, because we use bootstrap and these look good
* and match.
*/
-var lightblue = "#d9edf7";
-var lightgreen = "#dff0d8";
-var lightred = "#f2dede";
-var lightorange = "#fcf8e3";
-var blue = "#337ab7";
-var green = "#5cb85c";
-var teal = "#5bc0de"; // Or whatever the hell that is
-var orange = "#f0ad4e";
-var red = "#d9534f";
-var white = "#ffffff";
-function gradient_from_latency(latency_ms, latency_secondary_ms)
-{
- if (latency_ms == undefined)
- return blue;
- return getColorStop(parseInt(latency_ms) * 10);
+var nmsColor = nmsColor || {
+ _cache: [],
+ lightblue: "#d9edf7",
+ lightgreen: "#dff0d8",
+ lightred: "#f2dede",
+ lightorange: "#fcf8e3",
+ blue: "#337ab7",
+ green: "#5cb85c",
+ teal: "#5bc0de",
+ orange: "#f0ad4e",
+ red: "#d9534f",
+ white: "#ffffff"
}
/*
* Return a random-ish color (for testing)
*/
-function getRandomColor()
+nmsColor.random = function()
{
- var colors = [ "white", red, teal, orange, green, blue ];
+ var colors = [ "white", nmsColor.red, nmsColor.teal, nmsColor.orange, nmsColor.green, nmsColor.blue ];
var i = Math.round(Math.random() * (colors.length-1));
return colors[i];
}
@@ -47,11 +44,11 @@ function getRandomColor()
* resize for the moment, because this canvas is also re-sized (which isn't
* really necessary, but avoids special handling).
*/
-function drawGradient(gradients)
-{
+nmsColor.drawGradient = function(gradients) {
var ctx = nmsMap._c.hidden.ctx; // FIXME: Move it away...
var gradient = ctx.createLinearGradient(0,0,1000,0);
var stops = gradients.length - 1;
+ nmsColor._cache = [];
nms.gradients = gradients;
for (var color in gradients) {
var i = color / stops;
@@ -70,24 +67,27 @@ function drawGradient(gradients)
/*
* Get the color of a gradient, range is from 0 to 999 (inclusive).
*/
-function getColorStop(x) {
+nmsColor.getColorStop = function(x) {
x = parseInt(x);
if (x > 999)
x = 999;
if (x < 0)
x = 0;
- return getColor(x,0);
+ return nmsColor._getColor(x,0);
}
/*
* Get the color on the hidden canvas at a specific point. Could easily be
* made generic.
*/
-function getColor(x,y) {
+nmsColor._getColor = function(x,y) {
+ if (nmsColor._cache[x] != undefined)
+ return nmsColor._cache[x];
var ctx = nmsMap._c.hidden.ctx; // FIXME: Move it away...
var imageData = ctx.getImageData(x, y, 1, 1);
var data = imageData.data;
if (data.length < 4)
return false;
- return 'rgb(' + data[0] + ',' + data[1] + ',' + data[2] + ')';
+ nmsColor._cache[x] = 'rgb(' + data[0] + ',' + data[1] + ',' + data[2] + ')';
+ return nmsColor._cache[x];
}
diff --git a/web/js/nms-data.js b/web/js/nms-data.js
index 14e5fed..e3c4106 100644
--- a/web/js/nms-data.js
+++ b/web/js/nms-data.js
@@ -231,7 +231,8 @@ nmsData._genericUpdater = function(name, cacheok) {
dataType: "json",
success: function (data, textStatus, jqXHR) {
if (nmsData[name] == undefined || nmsData[name]['hash'] != data['hash']) {
- nmsData._last = data['time'];
+ if (name == "ping")
+ nmsData._last = data['time'];
nmsData.old[name] = nmsData[name];
nmsData[name] = data;
nmsMap.drawNow();
diff --git a/web/js/nms-info-box.js b/web/js/nms-info-box.js
index e6817dc..cd5594e 100644
--- a/web/js/nms-info-box.js
+++ b/web/js/nms-info-box.js
@@ -13,15 +13,11 @@
/*
*
* Currently broken or needs reimplementing:
- * - Possibly: Comment CRUD, did not want to test writes on our "historic db copy"
- * - Comments popover
* - Handler unloading is not working correctly, and many are never removed
* - SSH-management link, this should propably be a custom "view" of sorts
- * - inventoryListing window is partially broken when first opened. Since it's
- * both a window type and a panel with different modes it has some conflicts.
*
* General TODO:
- * - Fix broken stuff
+ * - Move inventory into a separate tab.
* - Add external windows (timetravel, etc)
* - Take a critical look at what methods/variables should be marked as "_"
* - Currently argument is assumed to be a switch, this should not be the case
@@ -44,13 +40,9 @@ var nmsInfoBox = nmsInfoBox || {
'title': 'Switch info',
'views': {
'initial': {
- 'name': 'Switch summary',
+ 'name': 'Summary',
'panels': ['switchSummary','switchComments']
},
- 'details': {
- 'name': 'Switch details',
- 'panels': ['switchDetails']
- },
'ports': {
'name': 'SNMP - Ports',
'panels': ['switchSNMP:ports']
@@ -59,9 +51,9 @@ var nmsInfoBox = nmsInfoBox || {
'name': 'SNMP - Misc',
'panels': ['switchSNMP:misc']
},
- 'comments': {
- 'name': 'Comments',
- 'panels': ['switchComments']
+ 'details': {
+ 'name': 'Settings',
+ 'panels': ['switchDetails']
},
'edit': {
'name': 'Edit',
@@ -176,8 +168,10 @@ nmsInfoBox.addPanelType = function (id, obj) {
*/
nmsInfoBox.hide = function() {
this._sw = false;
- this._windowHandler.hide();
- this._windowHandler.unloadWindow();
+ if (this._windowHandler != undefined && this._windowHandler.hide != undefined) {
+ this._windowHandler.hide();
+ this._windowHandler.unloadWindow();
+ }
};
/*
@@ -194,7 +188,7 @@ nmsInfoBox.click = function(sw)
* Is based on a hierarchy of objects: Window (itself) > Views > Panels. Where
* any object should not interact with any other directly. Panels are special
* nmsInfoPanel-objects that handle their own rendering, refreshing, etc. The
- * window handler only makes shure these panels are loaded and unloaded when
+ * window handler only makes sure these panels are loaded and unloaded when
* needed in a window or view.
*
* Does primarily rely on an imported list of panel types and window types to
@@ -590,13 +584,7 @@ var searchHelpPanel = function() {
nmsInfoPanel.call(this,"searchHelp");
this.refresh = function(reason) {
var x = document.createElement("div");
- var searchHelp = [
- "The search box can be used to identify switches in several ways. The simplest is by name.",
- "If you are using the non-public version of Gondul, you can also perform smart searches.",
- "Distro search: Type the name of a distro-switch and all access switches registered to that distro switch will also be hilighted.",
- 'Active ports: Type "active>x", "active<x" or "active=x" to identify switch with "x" amount of active gigabit ethernet (ge) ports. E.g.: "active>30".',
- 'IP search: Start typing an IP and any switch with that IP registered either as management IP or part of its subnet will be identified',
- 'SNMP search: Type anything found in the "sysDescr" SNMP OID to hilight a switch matching that. Practical examples include version numbers for firmware (e.g.: "JUNOS 12." vs "JUNOS 14.").'];
+ var searchHelp = nmsSearch.helpText;
for (var a in searchHelp) {
var c = document.createElement("p");
c.innerText = searchHelp[a];
@@ -704,7 +692,7 @@ var inventoryListingPanel = function() {
for(var sw in nmsData.switches.switches) {
var value = '';
if(this.filter != '') {
- if(sw.toLowerCase().indexOf(this.filter) == -1 && !nmsInfoBox._searchSmart(this.filter,sw))
+ if(sw.toLowerCase().indexOf(this.filter) == -1 && !nmsSearch.searchTest(this.filter,sw))
continue;
}
try {
@@ -774,7 +762,7 @@ var switchEditPanel = function () {
var tmpsw = '\'' + this.sw + '\'';
var tmpv = '\'' + v + '\'';
var tmphandler = '"nmsInfoBox._editChange(' + tmpsw + ',' + tmpv + ');"';
- var html = '<input type="text" class="form-control" value="' + template[v] + '" id="edit-' + this.sw + '-' + v + '" onchange=' + tmphandler + ' oninput=' + tmphandler + '>';
+ var html = '<input type="text" class="form-control" value="' + template[v] + '" id="edit-' + this.sw + '-' + v + '" onchange=' + tmphandler + ' oninput=' + tmphandler + ' ' + (v == 'sysname' ? "readonly" : "") + '>';
content.push([v, html]);
}
@@ -794,6 +782,7 @@ var switchEditPanel = function () {
output.id = "edit-output";
domObj.appendChild(output);
+ this._render(domObj);
if (place) {
var pval = document.getElementById("edit-" + this.sw + "-placement");
if (pval) {
@@ -801,7 +790,6 @@ var switchEditPanel = function () {
}
}
- this._render(domObj);
};
this.save = function () {
var myData = nmsInfoBox._editStringify(this.sw);
@@ -828,8 +816,6 @@ nmsInfoBox.addPanelType("switchEdit",switchEditPanel);
*
* Displays the current comments and lets you interact with them or add new ones
*
- * TODO: Test with a dummy-db to make sure everything still works properly
- *
*/
var switchCommentsPanel = function () {
nmsInfoPanel.call(this,"switchComments");
@@ -837,28 +823,25 @@ var switchCommentsPanel = function () {
this.refresh = function (reason) {
var domObj = document.createElement("div");
var comments = [];
-
var logs = nmsOplog.getSwitchLogs(this.sw);
- // We have data
- var table = document.createElement("table");
- var tr;
- var td1;
- var td2;
- var td3;
- table.className = "table";
- table.classList.add("table");
- table.classList.add("table-condensed");
- for (var v in logs) {
- tr = table.insertRow(-1);
- tr.className =
- td1 = tr.insertCell(0);
- td2 = tr.insertCell(1);
- td1.textContent = logs[v]['timestamp'];
- td2.textContent = "[" + logs[v]['username'] + "] " + logs[v]['log'];
- }
- domObj.appendChild(table);
-
-
+ var table = document.createElement("table");
+ var tr;
+ var td1;
+ var td2;
+ var td3;
+ table.className = "table";
+ table.classList.add("table");
+ table.classList.add("table-condensed");
+ for (var v in logs) {
+ tr = table.insertRow(-1);
+ tr.className =
+ td1 = tr.insertCell(0);
+ td2 = tr.insertCell(1);
+ var date = new Date(logs[v]['timestamp']);
+ td1.textContent = date.toString();
+ td2.textContent = "[" + logs[v]['username'] + "] " + logs[v]['log'];
+ }
+ domObj.appendChild(table);
this._render(domObj);
};
};
@@ -878,97 +861,14 @@ var switchSummaryPanel = function() {
};
this.refresh = function(reason) {
var content = [];
-
- //Get DHCP info
- var lastDhcp = undefined;
- try {
- var tempDhcp = nmsData.dhcp.dhcp[this.sw];
- var now = Date.now();
- now = Math.floor(now / 1000);
- tempDhcp = now - parseInt(tempDhcp);
- tempDhcp = tempDhcp + " s";
- } catch(e) {}
-
- //Get SNMP status
- var snmpStatus = undefined;
- try {
- if (nmsData.snmp.snmp[this.sw].misc.sysName[0] != sw) {
- snmpStatus = "Sysname mismatch";
- } else {
- snmpStatus = "OK";
- }
- } catch(e) {}
-
- //Get CPU usage
- var cpuUsage = undefined;
- try {
- var cpu = 0;
- for (var u in nmsData.snmp.snmp[this.sw].misc.jnxOperatingCPU) {
- var local = nmsData.snmp.snmp[this.sw].misc['jnxOperatingCPU'][u];
- cpu = Math.max(nmsData.snmp.snmp[this.sw].misc.jnxOperatingCPU[u],cpu);
- }
- cpuUsage = cpu + " %";
- } catch (e) {}
-
- //Get traffic data
- var uplinkTraffic = undefined;
- try {
- var speed = 0;
- var t = parseInt(nmsData.switchstate.then[this.sw].uplinks.ifHCOutOctets);
- var n = parseInt(nmsData.switchstate.switches[this.sw].uplinks.ifHCOutOctets);
- var tt = parseInt(nmsData.switchstate.then[this.sw].time);
- var nt = parseInt(nmsData.switchstate.switches[this.sw].time);
- var tdiff = nt - tt;
- var diff = n - t;
- speed = diff / tdiff;
- if(!isNaN(speed)) {
- uplinkTraffic = byteCount(speed*8,0);
+ for ( var h in handlers ) {
+ if (handlers[h].getInfo != undefined) {
+ var tmp = handlers[h].getInfo(this.sw);
+ for (var x in tmp.data) {
+ content.push([tmp.data[x].description, tmp.data[x].value]);
+ }
}
- } catch (e) {};
-
- //Get uptime data
- var uptime = "";
- try {
- uptime = nmsData.snmp.snmp[this.sw]["misc"]["sysUpTimeInstance"][""] / 60 / 60 / 100;
- uptime = Math.floor(uptime) + " t";
- } catch(e) {}
-
- //Get temperature data
- var temp = "";
- try {
- temp = nmsData.switchstate.switches[this.sw].temp + " °C";
- } catch(e) {}
-
- //Get management data
- var mgmtV4 = "";
- var mgmtV6 = "";
- var subnetV4 = "";
- var subnetV6 = "";
- try {
- mgmtV4 = nmsData.smanagement.switches[this.sw].mgmt_v4_addr;
- mgmtV6 = nmsData.smanagement.switches[this.sw].mgmt_v6_addr;
- subnetV4 = nmsData.smanagement.switches[this.sw].subnet4;
- subnetV6 = nmsData.smanagement.switches[this.sw].subnet6;
- } catch(e) {}
-
- //Get ping data
- var ping = undefined;
- try {
- nmsData.ping.switches[this.sw].latency + " ms";
- } catch (e) {}
-
-
- content.push(["Ping latency:",ping]);
- content.push(["Last DHCP lease:",lastDhcp]);
- content.push(["SNMP status:",snmpStatus]);
- content.push(["CPU usage:",cpuUsage]);
- content.push(["Uplink traffic:",uplinkTraffic]);
- content.push(["System uptime:",uptime]);
- content.push(["Temperature",temp]);
- content.push(["Management (v4):",mgmtV4]);
- content.push(["Management (v6):",mgmtV6]);
- content.push(["Subnet (v4):",subnetV4]);
- content.push(["Subnet (v6):",subnetV6]);
+ }
var contentCleaned = [];
for(var i in content) {
@@ -978,7 +878,6 @@ var switchSummaryPanel = function() {
content[i][1] == "No data";
contentCleaned.push(content[i]);
}
-
var table = nmsInfoBox._makeTable(contentCleaned);
this._render(table);
@@ -1008,7 +907,7 @@ nmsInfoBox._makeTable = function(content, caption) {
}
for (var v in content) {
tr = table.insertRow(-1);
- tr.className = content[v][0].toLowerCase();
+ tr.className = content[v][0].toLowerCase().replace(/[^a-z0-9_]/g,"");
td1 = tr.insertCell(0);
td2 = tr.insertCell(1);
td1.innerHTML = content[v][0];
@@ -1017,123 +916,6 @@ nmsInfoBox._makeTable = function(content, caption) {
return table;
};
-nmsInfoBox.searchSmart = function(id, sw) {
- if (id == "")
- return false;
- return nmsInfoBox._searchSmart(id, sw);
-}
-
-nmsInfoBox._searchSmart = function(id, sw) {
- try {
- if(sw.toLowerCase().indexOf(id) > -1) {
- return true;
- }
- try {
- if (nmsData.switches.switches[sw].distro_name.toLowerCase() == id) {
- return true;
- }
- } catch (e) {}
- try {
- if (id.match("active")) {
- var limit = id;
- limit = limit.replace("active>","");
- limit = limit.replace("active<","");
- limit = limit.replace("active=","");
- var operator = id.replace("active","")[0];
- if (limit == parseInt(limit)) {
- var ports = parseInt(nmsData.switchstate.switches[sw].ifs.ge.live);
- limit = parseInt(limit);
- if (operator == ">" ) {
- if (ports > limit) {
- return true;
- }
- } else if (operator == "<") {
- if (ports < limit) {
- return true;
- }
- } else if (operator == "=") {
- if (ports == limit) {
- return true;
- }
- }
- }
- }
- } catch (e) {}
- try {
- if (nmsData.smanagement.switches[sw].mgmt_v4_addr.match(id)) {
- return true;
- }
- if (nmsData.smanagement.switches[sw].mgmt_v6_addr.match(id)) {
- return true;
- }
- } catch (e) {}
- try {
- if (nmsData.smanagement.switches[sw].subnet4.match(id)) {
- return true;
- }
- if (nmsData.smanagement.switches[sw].subnet6.match(id)) {
- return true;
- }
- } catch (e) {}
- if (nmsData.snmp.snmp[sw].misc.sysDescr[0].toLowerCase().match(id)) {
- return true;
- }
- } catch (e) {
- return false;
- }
- return false;
-};
-
-/*
- * FIXME: Not sure this belongs here, it's really part of the "Core" ui,
- * not just the infobox.
- */
-nmsInfoBox._search = function() {
- var el = document.getElementById("searchbox");
- var id = false;
- var matches = [];
- if (el) {
- id = el.value.toLowerCase();
- }
- if(id) {
- nmsMap.enableHighlights();
- for(var sw in nmsData.switches.switches) {
- if (nmsInfoBox._searchSmart(id,sw)) {
- matches.push(sw);
- nmsMap.setSwitchHighlight(sw,true);
- } else {
- nmsMap.setSwitchHighlight(sw,false);
- }
- }
- } else {
- nmsMap.disableHighlights();
- }
- if(matches.length == 1) {
- document.getElementById("searchbox-submit").classList.add("btn-primary");
- document.getElementById("searchbox").dataset.match = matches[0];
- } else {
- document.getElementById("searchbox-submit").classList.remove("btn-primary");
- document.getElementById("searchbox").dataset.match = '';
- }
-};
-
-nmsInfoBox._searchKeyListener = function(e) {
- switch (e.keyCode) {
- case 13:
- var sw = document.getElementById("searchbox").dataset.match;
- if(sw != '') {
- nmsInfoBox.showWindow("switchInfo",sw);
- }
- break;
- case 27:
- document.getElementById("searchbox").dataset.match = '';
- document.getElementById("searchbox").value = '';
- nmsInfoBox._search();
- nmsInfoBox.hide();
- break;
- }
-};
-
nmsInfoBox._nullBlank = function(x) {
if (x == null || x == false || x == undefined)
return "";
diff --git a/web/js/nms-map-handlers.js b/web/js/nms-map-handlers.js
index f4aba57..61a5a05 100644
--- a/web/js/nms-map-handlers.js
+++ b/web/js/nms-map-handlers.js
@@ -11,12 +11,6 @@
* utilize information from any aspect of NMS, and thus opens NMS up to the
* world of intelligent maps base don multiple data sources.
*
- * Warning: This paradigm will change. Handlers will be expected to
- * register their own callbacks for nmsData. Work in progress.
- *
- */
-
-/*
*/
var handler_uplinks = {
@@ -33,8 +27,9 @@ var handler_temp = {
var handler_ping = {
init:pingInit,
+ getInfo:pingInfo,
tag:"ping",
- name:"IPv4 Ping"
+ name:"Ping"
};
var handler_traffic = {
@@ -63,6 +58,7 @@ var handler_disco = {
var handler_snmp = {
init:snmpInit,
+ getInfo:snmpInfo,
tag:"snmp",
name:"SNMP state"
};
@@ -73,7 +69,51 @@ var handler_cpu = {
name:"CPU utilization"
};
+var handler_health = {
+ init:healthInit,
+ getInfo:healthInfo,
+ tag:"health",
+ name:"Health"
+};
+
+var handler_mgmt = {
+ getInfo:mgmtInfo,
+ name:"Management info"
+};
+
+var handlerInfo = function(tag,desc) {
+ /*
+ * Short name, typically matching the url anchor.
+ */
+ this.tag = tag;
+ this.description = desc || "Unknown";
+ this.data = [
+ {
+ value: undefined,
+ description: desc || "Generic info"
+ }];
+ /*
+ * 0: all good.
+ * 1000: messed up.
+ *
+ * This can be "intelligent". E.g.: pingInfo() takes latency and
+ * the age of the reply into account in addition to having a
+ * special handling of lack of a result.
+ */
+ this.score = 0;
+ /*
+ * Why the score is what it is. E.g.: If you have multiple
+ * conditions that set the score, what is the final value based on?
+ */
+ this.why = "0 score is the default";
+};
+
+/*
+ * Order matches what's seen in the infobox
+ */
var handlers = [
+ handler_health,
+ handler_mgmt,
handler_uplinks,
handler_temp,
handler_ping,
@@ -110,13 +150,13 @@ function uplinkUpdater()
if (uplinks == 0) {
nmsMap.setSwitchColor(sw,"white");
} else if (uplinks == 1) {
- nmsMap. setSwitchColor(sw, red);
+ nmsMap. setSwitchColor(sw, nmsColor.red);
} else if (uplinks == 2) {
- nmsMap.setSwitchColor(sw, orange);
+ nmsMap.setSwitchColor(sw, nmsColor.orange);
} else if (uplinks == 3) {
- nmsMap.setSwitchColor(sw,green);
+ nmsMap.setSwitchColor(sw, nmsColor.green);
} else if (uplinks > 3) {
- nmsMap.setSwitchColor(sw, blue);
+ nmsMap.setSwitchColor(sw, nmsColor.blue);
}
}
}
@@ -129,10 +169,10 @@ function uplinkInit()
nmsData.addHandler("switches","mapHandler",uplinkUpdater);
nmsData.addHandler("switchstate","mapHandler",uplinkUpdater);
setLegend(1,"white","0 uplinks");
- setLegend(2,red,"1 uplink");
- setLegend(3,orange,"2 uplinks");
- setLegend(4,green,"3 uplinks");
- setLegend(5,blue,"4 uplinks");
+ setLegend(2,nmsColor.red,"1 uplink");
+ setLegend(3,nmsColor.orange,"2 uplinks");
+ setLegend(4,nmsColor.green,"3 uplinks");
+ setLegend(5,nmsColor.blue,"4 uplinks");
}
/*
@@ -143,7 +183,7 @@ function trafficInit()
nmsData.addHandler("switches","mapHandler",trafficUpdater);
nmsData.addHandler("switchstate","mapHandler",trafficUpdater);
var m = 1024 * 1024 / 8;
- drawGradient([lightgreen,green,orange,red]);
+ nmsColor.drawGradient([nmsColor.lightgreen, nmsColor.green, nmsColor.orange, nmsColor.red]);
setLegend(1,colorFromSpeed(0),"0 (N/A)");
setLegend(5,colorFromSpeed(1100 * m) , "1100Mb/s");
setLegend(4,colorFromSpeed(600 * m),"600Mb/s");
@@ -178,7 +218,7 @@ function trafficTotInit()
nmsData.addHandler("switches","mapHandler",trafficTotUpdater);
nmsData.addHandler("switchstate","mapHandler",trafficTotUpdater);
var m = 1024 * 1024 / 8;
- drawGradient([lightgreen,green,orange,red]);
+ nmsColor.drawGradient([nmsColor.lightgreen, nmsColor.green, nmsColor.orange, nmsColor.red]);
setLegend(1,colorFromSpeed(0),"0 (N/A)");
setLegend(5,colorFromSpeed(5000 * m,5) , "5000Mb/s");
setLegend(4,colorFromSpeed(3000 * m,5),"3000Mb/s");
@@ -212,9 +252,9 @@ function colorFromSpeed(speed,factor)
if (factor == undefined)
factor = 1.1;
if (speed == 0)
- return blue;
+ return nmsColor.blue;
speed = speed < 0 ? 0 : speed;
- return getColorStop( 1000 * (speed / (factor * (1000 * m))));
+ return nmsColor.getColorStop( 1000 * (speed / (factor * (1000 * m))));
}
/*
@@ -226,11 +266,11 @@ function temp_color(t)
{
if (t == undefined) {
console.log("Temp_color, but temp is undefined");
- return blue;
+ return nmsColor.blue;
}
t = parseInt(t) - 12;
t = Math.floor((t / 23) * 1000);
- return getColorStop(t);
+ return nmsColor.getColorStop(t);
}
function tempUpdater()
@@ -257,7 +297,7 @@ function tempUpdater()
function tempInit()
{
//Padded the gradient with extra colors for the upper unused values
- drawGradient(["black",blue,lightblue,lightgreen,green,orange,red]);
+ nmsColor.drawGradient(["black", nmsColor.blue, nmsColor.lightblue, nmsColor.lightgreen, nmsColor.green, nmsColor.orange, nmsColor.red]);
setLegend(1,temp_color(15),"15 °C");
setLegend(2,temp_color(20),"20 °C");
setLegend(3,temp_color(25),"25 °C");
@@ -272,28 +312,68 @@ function pingUpdater()
return;
}
for (var sw in nmsData.switches.switches) {
- try {
- var c;
- if (nmsData.ping.switches[sw].age > 0) {
- c = red;
- } else {
- c = gradient_from_latency(nmsData.ping.switches[sw].latency);
- }
+ var c = nmsColor.getColorStop(pingInfo(sw).score);
+ if (c == 1000) {
+ nmsMap.setSwitchColor(sw, nmsColor.blue);
+ } else {
nmsMap.setSwitchColor(sw, c);
- } catch (e) {
- nmsMap.setSwitchColor(sw, blue);
}
}
}
+function pingInfo(sw)
+{
+ var ret = new handlerInfo("ping","Latency(ms)");
+ ret.why = "Latency";
+ if (testTree(nmsData,['ping','switches',sw])) {
+ var v4 = nmsData.ping.switches[sw].latency4;
+ var v6 = nmsData.ping.switches[sw].latency6;
+ if (v4 == undefined)
+ v4 = undefined;
+ if (v6 == undefined)
+ v6 = undefined;
+ ret.data[0].value = v4;
+ ret.data[0].description = "IPv4 latency(ms)";
+ ret.data[1] = {};
+ ret.data[1].value = v6;
+ ret.data[1].description = "IPv6 latency(ms)";
+ if (v4 == undefined && v6 == undefined) {
+ ret.score = 1000;
+ ret.why = "No IPv4 or IPv6 ping reply";
+ } else if(v6 == undefined) {
+ ret.score = 200;
+ ret.why = "No IPv6 ping reply";
+ } else if (v4 == undefined) {
+ ret.score = 199;
+ ret.why = "No IPv4 ping reply";
+ }
+
+ v4 = parseFloat(v4) * 10;
+ v6 = parseFloat(v6) * 10;
+ if (v4 > ret.score || v6 > ret.score) {
+ ret.why = "Latency";
+ ret.score = parseInt(v4 > v6 ? v4 : v6);
+ }
+ if (nmsData.ping.switches[sw].age4 > 5 || nmsData.ping.switches[sw].age6 > 5) {
+ ret.why = "Old ping";
+ ret.score = 900;
+ }
+ } else {
+ ret.data[0].value = "N/A - no ping replies";
+ ret.why = "No ping replies";
+ ret.score = 999;
+ }
+ return ret;
+}
+
function pingInit()
{
- drawGradient([green,lightgreen,orange,red]);
- setLegend(1,gradient_from_latency(1),"1ms");
- setLegend(2,gradient_from_latency(30),"30ms");
- setLegend(3,gradient_from_latency(60),"60ms");
- setLegend(4,gradient_from_latency(100),"100ms");
- setLegend(5,gradient_from_latency(undefined) ,"No response");
+ nmsColor.drawGradient([nmsColor.green,nmsColor.lightgreen, nmsColor.orange, nmsColor.red]);
+ setLegend(1,nmsColor.getColorStop(10),"1ms");
+ setLegend(2,nmsColor.getColorStop(300),"30ms");
+ setLegend(3,nmsColor.getColorStop(600),"60ms");
+ setLegend(4,nmsColor.getColorStop(1000),"100ms");
+ setLegend(5,nmsColor.blue,"No response");
nmsData.addHandler("ping","mapHandler",pingUpdater);
nmsData.addHandler("switches","mapHandler",pingUpdater);
nmsData.addHandler("ticker", "mapHandler", pingUpdater);
@@ -307,38 +387,31 @@ function getDhcpColor(stop)
stop = 1000;
if (stop > 1000)
stop = 1000;
- return getColorStop(stop);
+ return nmsColor.getColorStop(stop);
}
function dhcpUpdater()
{
- if (nmsData.dhcp == undefined || nmsData.dhcp.dhcp == undefined) {
+ if (!testTree(nmsData,['dhcp','dhcp']) || !testTree(nmsData,['switches','switches'])) {
return
}
- if (nmsData.switches == undefined || nmsData.switches.switches == undefined) {
- return;
- }
var now = nmsData.dhcp.time;
- try {
for (var sw in nmsData.switches.switches) {
- var c = blue;
- if (nmsData.dhcp.dhcp[sw] == undefined) {
+ var c = nmsColor.blue;
+ var s = nmsData.dhcp.dhcp[sw];
+ if (s == undefined) {
nmsMap.setSwitchColor(sw,c);
continue;
}
- var s = nmsData.dhcp.dhcp[sw];
var then = parseInt(s);
c = getDhcpColor(now - then);
nmsMap.setSwitchColor(sw, c);
}
- } catch(e) {
- console.log(e);
- }
}
function dhcpInit()
{
- drawGradient([green,lightgreen,orange,red]);
+ nmsColor.drawGradient([nmsColor.green, nmsColor.lightgreen, nmsColor.orange, nmsColor.red]);
nmsData.addHandler("dhcp","mapHandler",dhcpUpdater);
setLegend(1,"white","Undefined");
setLegend(2,getDhcpColor(1),"1 Second old");
@@ -360,47 +433,96 @@ function randomizeColors()
return;
}
for (var sw in nmsData.switches.switches) {
- nmsMap.setSwitchColor(sw, getRandomColor());
+ nmsMap.setSwitchColor(sw, nmsColor.random());
}
}
function discoDo() {
randomizeColors();
- setTimeout(randomizeColors,500);
}
function discoInit()
{
nmsData.addHandler("ticker", "mapHandler", discoDo);
setNightMode(true);
- setLegend(1,blue,"Y");
- setLegend(2,red, "M");
- setLegend(3,orange,"C");
- setLegend(4,green, "A");
+ setLegend(1,nmsColor.blue,"Y");
+ setLegend(2,nmsColor.red, "M");
+ setLegend(3,nmsColor.orange,"C");
+ setLegend(4,nmsColor.green, "A");
setLegend(5,"white","!");
}
function snmpUpdater() {
for (var sw in nmsData.switches.switches) {
if (nmsData.snmp.snmp[sw] == undefined || nmsData.snmp.snmp[sw].misc == undefined) {
- nmsMap.setSwitchColor(sw, red);
+ nmsMap.setSwitchColor(sw, nmsColor.red);
} else if (nmsData.snmp.snmp[sw].misc.sysName[0] != sw) {
- nmsMap.setSwitchColor(sw, orange);
+ nmsMap.setSwitchColor(sw, nmsColor.orange);
} else {
- nmsMap.setSwitchColor(sw, green);
+ nmsMap.setSwitchColor(sw, nmsColor.green);
+ }
+ }
+}
+
+function secondsToTime(input) {
+ var h, m, s;
+ h = Math.floor(input / 60 / 60);
+ m = Math.floor((input%3600)/60);
+ s = Math.floor(input%60);
+ var string = "";
+ if (h > 0)
+ string = h + " hours ";
+ if (h > 0 || m > 0)
+ string += m + " minutes ";
+ if (string == "")
+ string += s + " seconds";
+ return string;
+}
+
+function snmpInfo(sw) {
+ var ret = new handlerInfo("snmp","SNMP data");
+ ret.why = "No data";
+ if (!testTree(nmsData,['snmp','snmp',sw,'misc'])) {
+ ret.score = 800;
+ ret.why = "No data";
+ ret.data[0].value = "No data";
+ } else if (nmsData.snmp.snmp[sw].misc.sysName[0] != sw) {
+ ret.score = 200;
+ ret.why = "SNMP sysName doesn't match Gondul sysname";
+ ret.data[0].value = ret.why;
+ ret.data[1] = { description: "SNMP sysName", value: nmsData.snmp.snmp[sw].misc.sysName[0] };
+ } else {
+ ret.score = 0;
+ ret.data[0].value = "SNMP freshly updated";
+ ret.why = "SNMP all good";
+ }
+ if (testTree(nmsData,['snmp','snmp',sw,'misc','sysUpTimeInstance',''])) {
+ var uptime = parseInt(nmsData.snmp.snmp[sw]["misc"]["sysUpTimeInstance"][""]) / 100;
+ var upstring = secondsToTime(uptime);
+ ret.data.push({value: upstring, description: "System uptime"});
+ if (uptime < 60*5 && ret.score < 500) {
+ ret.score = 500;
+ ret.why = "System rebooted last 5 minutes";
+ }
+ if (uptime < 60*15 && ret.score < 250) {
+ ret.score = 250;
+ ret.why = "System rebooted last 15 minutes";
}
}
+ return ret;
}
+
function snmpInit() {
nmsData.addHandler("snmp", "mapHandler", snmpUpdater);
- setLegend(1,green,"OK");
- setLegend(2,orange, "Sysname mismatch");
- setLegend(3,red,"No SNMP data");
- setLegend(4,green, "");
- setLegend(5,green,"");
+ setLegend(1,nmsColor.green,"OK");
+ setLegend(2,nmsColor.orange, "Sysname mismatch");
+ setLegend(3,nmsColor.red,"No SNMP data");
+ setLegend(4,nmsColor.green, "");
+ setLegend(5,nmsColor.green,"");
}
+
function cpuUpdater() {
for (var sw in nmsData.switches.switches) {
try {
@@ -409,7 +531,7 @@ function cpuUpdater() {
var local = nmsData.snmp.snmp[sw].misc['jnxOperatingCPU'][u];
cpu = Math.max(nmsData.snmp.snmp[sw].misc.jnxOperatingCPU[u],cpu);
}
- nmsMap.setSwitchColor(sw, getColorStop(cpu * 10));
+ nmsMap.setSwitchColor(sw, nmsColor.getColorStop(cpu * 10));
nmsMap.setSwitchInfo(sw, cpu + " % ");
} catch (e) {
nmsMap.setSwitchColor(sw, "white");
@@ -418,12 +540,94 @@ function cpuUpdater() {
}
}
+function mgmtInfo(sw) {
+ var ret = new handlerInfo("mgmt","Management info");
+ ret.score = 0;
+ ret.why = "All good";
+ if (testTree(nmsData,['smanagement','switches',sw])) {
+ var mg = nmsData.smanagement.switches[sw];
+ ret.data =
+ [{
+ value: mg.mgmt_v4_addr || "",
+ description: "Management IP (v4)"
+ }, {
+ value: mg.mgmt_v6_addr || "",
+ description: "Management IP (v6)"
+ }, {
+ value: mg.subnet4 || "",
+ description: "Subnet (v4)"
+ }, {
+ value: mg.subnet6 || "",
+ description: "Subnet (v6)"
+ }];
+ if ((mg.mgmt_v4_addr == undefined || mg.mgmt_v4_addr == "") && (mg.mgmt_v6_addr == undefined || mg.mgmt_v6_addr == "")) {
+ ret.why = "No IPv4 or IPv6 mamagement IP";
+ ret.score = 1000;
+ } else if (mg.mgmt_v4_addr == undefined || mg.mgmt_v4_addr == "") {
+ ret.why = "No IPv4 management IP";
+ ret.score = 240;
+ } else if (mg.mgmt_v6_addr == undefined || mg.mgmt_v6_addr == "") {
+ ret.why = "No IPv6 management IP";
+ ret.score = 239;
+ }
+ } else {
+ ret.score = 1000;
+ ret.why = "No management info";
+ ret.data = [{}];
+ ret.data[0].value = "N/A";
+ ret.data[0].description = "Management info";
+ };
+ return ret;
+
+}
+
function cpuInit() {
nmsData.addHandler("snmp", "mapHandler", cpuUpdater);
- drawGradient([green,orange,red]);
+ nmsColor.drawGradient([nmsColor.green,nmsColor.orange,nmsColor.red]);
setLegend(1,getColorStop(0),"0 %");
setLegend(2,getColorStop(250),"25 %");
setLegend(3,getColorStop(600),"60 %");
setLegend(4,getColorStop(1000),"100 %");
setLegend(5,"white","N/A");
}
+
+function healthInfo(sw) {
+ var worst = new handlerInfo("health", "Health");
+ worst.score = 0;
+ worst.why = "All good";
+ for (var h in handlers) {
+ if (handlers[h].tag== "health")
+ continue;
+ if (handlers[h].getInfo == undefined)
+ continue;
+ var ret = handlers[h].getInfo(sw);
+ if (ret.score > worst.score) {
+ worst = ret;
+ }
+ }
+ worst.data = [{
+ description: "Health (lower is better): ",
+ value: worst.score + " (" + worst.why + ")"
+ }];
+ return worst;
+}
+
+function healthUpdater() {
+ if (nmsData.switches == undefined || nmsData.switches.switches == undefined)
+ return;
+ for (var sw in nmsData.switches.switches) {
+ var worst = healthInfo(sw);
+ nmsMap.setSwitchColor(sw, nmsColor.getColorStop(worst.score));
+ nmsMap.setSwitchInfo(sw, worst.tag);
+ }
+}
+
+function healthInit() {
+ nmsData.addHandler("ping", "mapHandler", healthUpdater);
+ nmsColor.drawGradient([nmsColor.green,nmsColor.orange,nmsColor.red]);
+ setLegend(1,nmsColor.getColorStop(0),"All good");
+ setLegend(2,nmsColor.getColorStop(250),"Ok-ish");
+ setLegend(3,nmsColor.getColorStop(600),"Ick-ish");
+ setLegend(4,nmsColor.getColorStop(800),"Nasty");
+ setLegend(5,nmsColor.getColorStop(1000),"WTF?");
+}
diff --git a/web/js/nms-map.js b/web/js/nms-map.js
index 224b3db..26782f8 100644
--- a/web/js/nms-map.js
+++ b/web/js/nms-map.js
@@ -180,6 +180,19 @@ nmsMap._resizeEvent = function() {
nmsMap.drawNow = function ()
{
var now = nmsData.now;
+ var ctx = nmsMap._c.top.ctx;
+ if (nmsTime.isRealTime()) {
+ if (!nmsMap._nowCleared) {
+ ctx.save();
+ ctx.scale(this.scale, this.scale);
+ ctx.clearRect(0,0,800,100);
+ ctx.restore();
+ nmsMap._nowCleared = true;
+ nmsMap._lastNow = undefined;
+ }
+ return true;
+ }
+ nmsMap._nowCleared = false;
if(String(now).indexOf('T') == -1) { //If now does not contain 'T' we assume its in epoch format
now = new Date(nmsData.now * 1000);
} else {
@@ -192,7 +205,6 @@ nmsMap.drawNow = function ()
}
nmsMap.stats.nows++;
- var ctx = nmsMap._c.top.ctx;
ctx.save();
ctx.scale(this.scale, this.scale);
ctx.font = (2 * this._settings.fontSize) + "px " + this._settings.fontFace;
@@ -273,13 +285,13 @@ nmsMap._drawSwitch = function(sw)
var color = nmsMap._color[sw];
if(this._highlightActive) {
if(nmsMap._highlight[sw]) {
- color = green;
+ color = nmsColor.green;
} else {
- color = white;
+ color = nmsColor.white;
}
}
if (color == undefined) {
- color = blue;
+ color = nmsColor.blue;
}
this._c.switch.ctx.fillStyle = color;
this._drawBox(this._c.switch.ctx, box['x'],box['y'],box['width'],box['height']);
@@ -311,7 +323,7 @@ nmsMap._drawText = function(ctx, text, box, align) {
if ((box['width'] + 10 )< box['height'])
rotate = true;
-
+
this._clearBox(ctx,box);
ctx.save();
ctx.scale(this.scale, this.scale);
@@ -320,7 +332,7 @@ nmsMap._drawText = function(ctx, text, box, align) {
ctx.fillStyle = "white";
ctx.strokeStyle = "black";
ctx.translate(box.x + this._settings.textMargin, box.y + box.height - this._settings.textMargin);
-
+
if (rotate) {
ctx.translate(box.width - this._settings.textMargin * 2,0);
ctx.rotate(Math.PI * 3/2);
@@ -361,8 +373,8 @@ nmsMap._setLinknetColor = function(l, color1, color2)
nmsMap._drawLinknet = function(l) {
try {
- var color1 = blue;
- var color2 = blue;
+ var color1 = nmsColor.blue;
+ var color2 = nmsColor.blue;
try {
color1 = nmsMap._linknets[l].sysname1;
color2 = nmsMap._linknets[l].sysname2;
@@ -408,7 +420,7 @@ nmsMap._drawBox = function(ctx, x, y, boxw, boxh) {
};
nmsMap._connectSwitches = function(sw1, sw2, color1, color2) {
- nmsMap._connectBoxes(this._getBox(sw1), this._getBox(sw2),
+ nmsMap._connectBoxes(nmsMap._getBox(sw1), nmsMap._getBox(sw2),
color1, color2);
};
@@ -419,9 +431,9 @@ nmsMap._connectSwitches = function(sw1, sw2, color1, color2) {
nmsMap._connectBoxes = function(box1, box2,color1, color2) {
var ctx = nmsMap._c.link.ctx;
if (color1 == undefined)
- color1 = blue;
+ color1 = nmsColor.blue;
if (color2 == undefined)
- color2 = blue;
+ color2 = nmsColor.blue;
var x0 = Math.floor(box1.x + box1.width/2);
var y0 = Math.floor(box1.y + box1.height/2);
var x1 = Math.floor(box2.x + box2.width/2);
diff --git a/web/js/nms-oplog.js b/web/js/nms-oplog.js
index 5da7893..83bda69 100644
--- a/web/js/nms-oplog.js
+++ b/web/js/nms-oplog.js
@@ -8,11 +8,38 @@ nmsOplog.init = function() {
nmsData.addHandler("oplog", "nmsOplogHandler", nmsOplog.updateComments);
}
+nmsOplog._reset = function() {
+ document.getElementById('logbox-id').value = "";
+ document.getElementById('logbox').value = "";
+ document.getElementById('searchbox').value = "";
+ document.getElementById('searchbox').oninput();
+}
+
+nmsOplog.getUser = function(force = false) {
+ var user = nms.user;
+ if (user == undefined || force) {
+ user = prompt("Who are you? Short nick for the record.");
+ if (user == null || user == undefined || user == "") {
+ console.log("empty prompt");
+ alert("No cake for you.");
+ return false;
+ }
+ nms.user = user;
+ saveSettings();
+ }
+ return nms.user;
+}
+
nmsOplog.commit = function() {
var s = document.getElementById('logbox-id').value;
var d = document.getElementById('logbox').value;
+ var user = nmsOplog.getUser();
+ if (user == undefined) {
+ nmsOplog._reset();
+ return;
+ }
- var myData = {"systems": s, "log": d};
+ var myData = {"user": user, "systems": s, "log": d};
myData = JSON.stringify(myData);
$.ajax({
type: "POST",
@@ -23,11 +50,7 @@ nmsOplog.commit = function() {
nmsData.invalidate("oplog");
}
});
- document.getElementById('logbox-id').value = "";
- document.getElementById('logbox').value = "";
- document.getElementById('searchbox').value = "";
- document.getElementById('searchbox').oninput();
-
+ nmsOplog._reset();
}
nmsOplog.updateComments = function() {
@@ -37,9 +60,11 @@ nmsOplog.updateComments = function() {
nmsOplog.getSwitchLogs = function(sw) {
var logs = [];
+ if (nmsData.oplog == undefined || nmsData['oplog']['oplog'] == undefined)
+ return [];
for (var v in nmsData['oplog']['oplog']) {
var log = nmsData['oplog']['oplog'][v];
- if (nmsInfoBox.searchSmart(log['systems'],sw)) {
+ if (nmsSearch.searchTest(log['systems'],sw)) {
logs.push(log);
}
}
@@ -60,10 +85,15 @@ nmsOplog._updateComments = function(limit,prefix,timefield) {
tr = table.insertRow(-1);
td1 = tr.insertCell(0);
td2 = tr.insertCell(1);
- td1.textContent = nmsData['oplog']['oplog'][v][timefield];
+ var date = new Date(nmsData.oplog.oplog[v]['timestamp']);
+ if (timefield == "time") {
+ td1.textContent = date.toTimeString().replace(/:\d\d .*$/,"");
+ } else {
+ td1.textContent = date.toString();
+ }
td2.textContent = "[" + nmsData['oplog']['oplog'][v]['username'] + "] " + nmsData['oplog']['oplog'][v]['log'];
td2.hiddenthing = v;
- td2.onclick = function(e){ console.log(e); var x = document.getElementById("searchbox"); var v = e.path[0].hiddenthing; console.log("KEK" + v); x.value = nmsData['oplog']['oplog'][v]['systems']; x.oninput(); }
+ td2.onclick = function(e){ var x = document.getElementById("searchbox"); var v = e.path[0].hiddenthing; x.value = nmsData['oplog']['oplog'][v]['systems']; x.oninput(); }
if (++i == limit)
break;
}
diff --git a/web/js/nms-search.js b/web/js/nms-search.js
new file mode 100644
index 0000000..6d61536
--- /dev/null
+++ b/web/js/nms-search.js
@@ -0,0 +1,159 @@
+"use strict";
+
+var nmsSearch = nmsSearch || {
+ _handler: false,
+ _lastId: false
+};
+
+nmsSearch.helpText = [
+ "The search box can be used to identify switches in several ways. The simplest is by name.",
+ "Searching by name can be done by just entering text, or if you want to match \"foobar1\" but not \"foobar15\" you can enclose the name in quotation marks. E.g.: foobar1 matches foobar1 and foobar1123123123, while \"foobar1\" only matches exactly foobar1.",
+ "All text-oriented searches are regular expressions. ^row\\d-2$ matches row1-2, row2-2, etc, but not row13-2 or rowx-2.",
+ "If you are using the non-public version of Gondul, you can also perform smart searches.",
+ "Distro search: Type the name of a distro-switch and all access switches registered to that distro switch will also be hilighted.",
+ 'Active ports: Type "active>x", "active<x" or "active=x" to identify switch with "x" amount of active gigabit ethernet (ge) ports. E.g.: "active>30".',
+ 'IP search: Start typing an IP and any switch with that IP registered either as management IP or part of its subnet will be identified',
+ 'SNMP search: Type anything found in the "sysDescr" SNMP OID to hilight a switch matching that. Practical examples include version numbers for firmware (e.g.: "JUNOS 12." vs "JUNOS 14.").'];
+
+/*
+ * Test if the search expression "id" matches the switch "sw"
+ *
+ * Return true if it does.
+ */
+nmsSearch.searchTest = function(id, sw) {
+ try {
+ var re = new RegExp(id,"i");
+ if(re.test(sw)) {
+ return true;
+ }
+ if (id[0] == "\"") {
+ if (("\"" + sw.toLowerCase() + "\"") == id.toLowerCase()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ try {
+ if (re.test(nmsData.switches.switches[sw].distro_name)) {
+ return true;
+ }
+ } catch (e) {}
+ try {
+ if (id.match("active")) {
+ var limit = id;
+ limit = limit.replace("active>","");
+ limit = limit.replace("active<","");
+ limit = limit.replace("active=","");
+ var operator = id.replace("active","")[0];
+ if (limit == parseInt(limit)) {
+ var ports = parseInt(nmsData.switchstate.switches[sw].ifs.ge.live);
+ limit = parseInt(limit);
+ if (operator == ">" ) {
+ if (ports > limit) {
+ return true;
+ }
+ } else if (operator == "<") {
+ if (ports < limit) {
+ return true;
+ }
+ } else if (operator == "=") {
+ if (ports == limit) {
+ return true;
+ }
+ }
+ }
+ }
+ } catch (e) {}
+ try {
+ if (re.test(nmsData.smanagement.switches[sw].mgmt_v4_addr)) {
+ return true;
+ }
+ if (re.test(nmsData.smanagement.switches[sw].mgmt_v6_addr)) {
+ return true;
+ }
+ } catch (e) {}
+ try {
+ if (re.test(nmsData.smanagement.switches[sw].subnet4)) {
+ return true;
+ }
+ if (re.test(nmsData.smanagement.switches[sw].subnet6)) {
+ return true;
+ }
+ } catch (e) {}
+ if (re.test(nmsData.snmp.snmp[sw].misc.sysDescr[0])) {
+ return true;
+ }
+ } catch (e) {
+ return false;
+ }
+ return false;
+};
+
+nmsSearch.reset = function() {
+ document.getElementById("searchbox").dataset.match = '';
+ document.getElementById("searchbox").value = '';
+ nmsSearch.search();
+}
+
+nmsSearch._enableTimer = function() {
+ if (nmsSearch._handler == false) {
+ nmsSearch._handler = setInterval(nmsSearch.search,1000);
+ }
+}
+
+nmsSearch._disableTimer = function() {
+ if (nmsSearch._handler != false) {
+ clearInterval(nmsSearch.search);
+ }
+}
+
+nmsSearch.search = function() {
+ var el = document.getElementById("searchbox");
+ var id = false;
+ var matches = [];
+ if (el) {
+ id = el.value.toLowerCase();
+ }
+ if(id) {
+ nmsMap.enableHighlights();
+ for(var sw in nmsData.switches.switches) {
+ if (nmsSearch.searchTest(id,sw)) {
+ matches.push(sw);
+ nmsMap.setSwitchHighlight(sw,true);
+ } else {
+ nmsMap.setSwitchHighlight(sw,false);
+ }
+ }
+ nmsSearch._enableTimer();
+ } else {
+ nmsSearch._disableTimer();
+ nmsMap.disableHighlights();
+ }
+ if(matches.length == 1) {
+ document.getElementById("searchbox-submit").classList.add("btn-primary");
+ document.getElementById("searchbox").dataset.match = matches[0];
+ } else {
+ document.getElementById("searchbox-submit").classList.remove("btn-primary");
+ document.getElementById("searchbox").dataset.match = '';
+ }
+};
+
+nmsSearch._searchKeyListener = function(e) {
+ switch (e.keyCode) {
+ case 13:
+ var sw = document.getElementById("searchbox").dataset.match;
+ if(sw != '') {
+ nmsInfoBox.showWindow("switchInfo",sw);
+ }
+ break;
+ case 27:
+ nmsSearch.reset();
+ break;
+ }
+}
+
+nmsSearch.init = function() {
+ $("#searchbox").keyup(function(e) {
+ nmsSearch._searchKeyListener(e);
+ });
+}
diff --git a/web/js/nms-time.js b/web/js/nms-time.js
new file mode 100644
index 0000000..315ac79
--- /dev/null
+++ b/web/js/nms-time.js
@@ -0,0 +1,150 @@
+"use strict";
+
+/*
+ * Deals with controlling time.
+ *
+ * More specifically: replaying of past events, fast forwarding, pausing,
+ * etc.
+ *
+ * The interface is a bit bloated at the moment, though.
+ */
+var nmsTime = nmsTime || {
+ _now: undefined,
+ _handle: undefined
+}
+
+nmsTime.replayEvent = function() {
+ throw "Not yet implemented.";
+}
+
+nmsTime.isRealTime = function() {
+ if (nmsTime._now == undefined && nmsTime._handle == undefined)
+ return true;
+ return false;
+}
+
+nmsTime.startNowPicker = function () {
+ $.datetimepicker.setLocale('no');
+ $('#nowPicker').datetimepicker('destroy');
+ var now;
+ if (nmsTime._now == undefined)
+ now = new Date();
+ else
+ now = nmsTime._now;
+ now.setSeconds(0);
+ now.setMilliseconds(0);
+ var datepicker = $('#nowPicker').datetimepicker({
+ value: now,
+ step: 5,
+ mask:false,
+ inline:true,
+ todayButton: true,
+ validateOnBlur:false,
+ dayOfWeekStart:1,
+ maxDate:'+1970/01/01',
+ onSelectDate: function(ct,$i){
+ document.getElementById('nowPicker').dataset.iso = new Date(ct.valueOf());
+ },
+ onSelectTime: function(ct,$i){
+ document.getElementById('nowPicker').dataset.iso = new Date(ct.valueOf());
+ },
+ onGenerate: function(ct,$i){
+ document.getElementById('nowPicker').dataset.iso = new Date(ct.valueOf());
+ }
+ });
+}
+
+nmsTime.setNow = function(now) {
+ var newDate = new Date(now);
+ newDate.setSeconds(0);
+ newDate.setMilliseconds(0);
+ newDate.setMinutes(newDate.getMinutes() - newDate.getMinutes()%5);
+ nmsTime._now = newDate;
+ nmsTime._updateData();
+}
+
+nmsTime._updateData = function() {
+ nmsData.now = nmsTime._now.getTime() / 1000;
+}
+
+nmsTime.realTime = function() {
+ nmsTime.stopPlayback();
+ nmsTime._now = undefined;
+ nmsData.now = undefined;
+}
+
+/*
+ * Step a fixed amount of time, measured in minutes.
+ *
+ * Try to align this to whole 5 minutes. It will be enforced in future
+ * backend versions to avoid bloating the cache and thus also stressing the
+ * database
+ */
+nmsTime.step = function(amount) {
+ if (nmsTime._now == null)
+ throw "Stepping without nmsTime._now";
+ if (amount == 0 || amount == undefined)
+ throw "Invalid step";
+ if (nmsTime._now.getTime() + (amount * 1000 * 60 ) > Date.now()) {
+ nmsTime.realTime();
+ return;
+ }
+ nmsTime._now.setMinutes(nmsTime._now.getMinutes() + amount);
+ nmsTime._updateData();
+}
+
+/*
+ * Step based on key-press. Same as step() but stops playback if it's
+ * active and allows you to rewind from a "live" map.
+ */
+nmsTime.stepKey = function(amount) {
+ nmsTime.stopPlayback();
+ if (nmsTime._now == undefined) {
+ nmsTime.setNow(Date.now());
+ }
+ nmsTime.step(amount);
+}
+
+/*
+ * Target of setInterval() when replaying.
+ */
+nmsTime._tick = function() {
+ nmsTime.step(nmsTime._speed);
+}
+
+/*
+ * We now have a time (presumably), start playback.
+ *
+ * Aborts if the time provided is greater than real time.
+ *
+ * Gondul does not _yet_ support fast forwarding into the future.
+ */
+nmsTime.startPlayback = function(speed) {
+ if (nmsTime._handle)
+ nmsTime.stopPlayback();
+ if (nmsTime._now.getTime() > Date.now()) {
+ nmsTime.stopPlayback();
+ return;
+ }
+ nmsTime._speed = speed;
+ nmsTime._handle = setInterval(nmsTime._tick,1000);
+}
+
+nmsTime.togglePause = function() {
+ if (nmsTime._handle) {
+ nmsTime.stopPlayback();
+ } else {
+ if (nmsTime.isRealTime()) {
+ nmsTime.setNow(Date.now());
+ } else {
+ nmsTime.startPlayback(nmsTime._speed ? nmsTime._speed : 5);
+ }
+ }
+}
+
+nmsTime.stopPlayback = function() {
+ if (nmsTime._handle)
+ clearInterval(nmsTime._handle);
+ nmsTime._handle = undefined;
+}
+
diff --git a/web/js/nms.js b/web/js/nms.js
index b979a32..9727c09 100644
--- a/web/js/nms.js
+++ b/web/js/nms.js
@@ -11,8 +11,6 @@
* - Move all pure UI stuff into nmsUi: nightMode, vertical mode,
* menushowing,
* - Get rid of "tvmode". As in: complete the merge
- * - Move all time-travel related code out into a separate entity.
- * - Remove nms.now: it belongs in nmsData.
* - nms.timers probably also deserves to die. It used to do a lot more,
* now it's just leftovers.
*/
@@ -21,23 +19,19 @@ var nms = {
get nightMode() { return this._nightMode; },
set nightMode(val) { if (val != this._nightMode) { this._nightMode = val; setNightMode(val); } },
/*
- * FIXME: This should be slightly smarter.
- */
- _now: false,
- get now() { return this._now },
- set now(v) { this._now = v; nmsData.now = v; },
- /*
* Various setInterval() handlers. See nmsTimer() for how they are
* used.
*
* FIXME: Should just stop using these.
*/
timers: {
- playback:false,
tvmode: false
},
menuShowing:true,
+ get uptime() {
+ return (Date.now() - this._startTime)/1000;
+ },
_vertical: 0,
get vertical() { return this._vertical },
set vertical(v) {
@@ -49,9 +43,14 @@ var nms = {
saveSettings();
},
- interval: 0,
- tvmodeToggle: false,
- views: "ping",
+ interval: 10,
+ _user: undefined,
+ get user() { return this._user; },
+ set user(u) {
+ this._user = u;
+ document.getElementById('logbook-name').textContent = u;
+ saveSettings();
+ },
/*
* This is a list of nms[x] variables that we store in our
* settings-cookie when altered and restore on load.
@@ -59,10 +58,9 @@ var nms = {
settingsList:[
'nightMode',
'menuShowing',
- 'tvmodeToggle',
'vertical',
- 'views',
- 'interval'
+ 'interval',
+ 'user'
],
keyBindings:{
'-':toggleMenu,
@@ -86,16 +84,6 @@ var nms = {
'Escape':hideWindow,
'?':toggleHelp
},
- /*
- * Playback controllers and variables
- */
- playback:{
- startTime: false,
- stopTime: false,
- playing: false,
- replayTime: 0,
- replayIncrement: 60 * 60
- },
tvmode: {
handlers: [],
currentIndex: 0,
@@ -108,8 +96,8 @@ var nms = {
/*
* Returns a handler object.
*
- * This might seem a bit much for 'setInterval()' etc, but it's really more
- * about self-documentation and predictable ways of configuring timers.
+ * FIXME: This is legacy-stuff, should get rid of it. DO NOT use this for
+ * new code.
*/
function nmsTimer(handler, interval, name, description) {
this.handler = handler;
@@ -166,193 +154,8 @@ function toggleNightMode()
}
/*
- * Parse 'now' from user-input.
- *
- * Should probably just use stringToEpoch() instead, but alas, not yet.
- */
-function parseNow(now)
-{
- if (Date.parse(now)) {
- // Adjust for timezone when converting from epoch (UTC) to string (local)
- var d = new Date(now);
- var timezoneOffset = d.getTimezoneOffset() * -60000;
- var d = new Date(Date.parse(now) - timezoneOffset);
- var str = d.getFullYear() + "-" + ("00" + (parseInt(d.getMonth())+1)).slice(-2) + "-" + ("00" + d.getDate()).slice(-2) + "T";
- str += ("00" + d.getHours()).slice(-2) + ":" + ("00" + d.getMinutes()).slice(-2) + ":" + ("00" + d.getSeconds()).slice(-2);
- return str;
-
- }
- if (now == "")
- return "";
- return false;
-}
-
-/*
- * Convert back and forth between epoch.
- *
- * There's no particular reason why I use seconds instead of javascript
- * microseconds, except to leave the mark of a C coder on this javascript
- * project.
- */
-function stringToEpoch(t)
-{
- var foo = t.toString();
-// foo = foo.replace('T',' ');
- var ret = new Date(Date.parse(foo));
- return parseInt(parseInt(ret.valueOf()) / 1000);
-}
-
-/*
- * Have to pad with zeroes to avoid "17:5:0" instead of the conventional
- * and more readable "17:05:00". I'm sure there's a better way, but this
- * works just fine.
- */
-function epochToString(t)
-{
- // Adjust for timezone when converting from epoch (UTC) to string (local)
- var date = new Date(parseInt(t) * parseInt(1000));
- var timezoneOffset = date.getTimezoneOffset() * -60;
- t = t - timezoneOffset;
-
- date = new Date(parseInt(t) * parseInt(1000));
- var str = date.getFullYear() + "-";
- if (parseInt(date.getMonth()) < 9)
- str += "0";
- str += (parseInt(date.getMonth())+1) + "-";
- if (date.getDate() < 10)
- str += "0";
- str += date.getDate() + "T";
- if (date.getHours() < 10)
- str += "0";
- str += date.getHours() + ":";
- if (date.getMinutes() < 10)
- str += "0";
- str += date.getMinutes() + ":";
- if (date.getSeconds() < 10)
- str += "0";
- str += date.getSeconds();
-
- return str;
-}
-
-function localEpochToString(t) {
- var d = new Date(parseInt(t) * parseInt(1000));
- var timezoneOffset = d.getTimezoneOffset() * -60;
- t = t + timezoneOffset;
-
- return epochToString(t);
-}
-
-/*
- * Start replaying historical data.
- */
-nms.playback.startReplay = function(startTime,stopTime) {
- if(!startTime || !stopTime)
- return false;
-
- nms.playback.pause();
- nms.playback.startTime = stringToEpoch(startTime);
- nms.playback.stopTime = stringToEpoch(stopTime);
- nms.now = epochToString(nms.playback.startTime);
- nms.playback.play();
-};
-
-/*
- * Pause playback
- */
-nms.playback.pause = function() {
- nms.timers.playback.stop();
- nms.playback.playing = false;
-};
-
-/*
- * Start playback
- */
-nms.playback.play = function() {
- nms.playback.tick();
- nms.timers.playback.start();
- nms.playback.playing = true;
-};
-
-/*
- * Toggle playback
- */
-nms.playback.toggle = function() {
- if(nms.playback.playing) {
- nms.playback.pause();
- } else {
- nms.playback.play();
- }
-};
-
-/*
- * Jump to place in time
- */
-nms.playback.setNow = function(now) {
- nms.now = parseNow(now);
-
- nms.playback.stopTime = false;
- nms.playback.startTime = false;
- nms.playback.tick();
-};
-
-/*
- * Step forwards or backwards in timer
- */
-nms.playback.stepTime = function(n)
-{
- var now = getNowEpoch();
- var newtime = parseInt(now) + parseInt(n);
- nms.now = epochToString(parseInt(newtime));
-
- if(!nms.playback.playing)
- nms.playback.tick();
-};
-
-/*
- * Ticker to trigger updates, and advance time if replaying
- *
- * This is run on a timer (nms.timers.tick) every second while unpaused
- */
-nms.playback.tick = function()
-{
- nms.playback.replayTime = getNowEpoch();
-
- // If outside start-/stopTime, remove limits and pause playback
- if (nms.playback.stopTime && (nms.playback.replayTime >= nms.playback.stopTime || nms.playback.replayTime < nms.playback.startTime)) {
- nms.playback.stopTime = false;
- nms.playback.startTime = false;
- nms.playback.pause();
- return;
- }
-
- // If past actual datetime, go live
- if (nms.playback.replayTime > parseInt(Date.now() / 1000)) {
- nms.now = false;
- }
-
- // If we are still replaying, advance time
- if(nms.now !== false && nms.playback.playing) {
- nms.playback.stepTime(nms.playback.replayIncrement);
- }
-};
-
-/*
- * Helper function for safely getting a valid now-epoch
- */
-function getNowEpoch() {
- if (nms.now && nms.now != 0)
- return stringToEpoch(nms.now);
- else
- return parseInt(Date.now() / 1000);
-}
-
-/*
* There are 4 legend-bars. This is a helper-function to set the color and
* description/name for each one. Used from handler init-functions.
- *
- * FIXME: Should be smarter, possibly use a canvas-writer so we can get
- * proper text (e.g.: not black text on dark blue).
*/
function setLegend(x,color,name)
{
@@ -371,7 +174,10 @@ function setLegend(x,color,name)
* Start TV-mode
*
* Loops trough a list of views/updaters at a set interval.
- * Arguments: array of views, interval in seconds, use nightmode, hide menus
+ * Arguments: array of views, interval in seconds
+ *
+ * FIXME: this is getting gradually stripped down from the original, so far
+ * we're not quite there yet with merging it with the regular code paths.
*/
nms.tvmode.start = function(views,interval) {
nms.tvmode.handlers = [];
@@ -395,21 +201,43 @@ nms.tvmode.tick = function() {
if(nms.tvmode.currentIndex > nms.tvmode.handlers.length - 1) {
nms.tvmode.currentIndex = 0;
}
- setUpdater(nms.tvmode.handlers[nms.tvmode.currentIndex]);
+ setUpdater(nms.tvmode.handlers[nms.tvmode.currentIndex],false);
nms.tvmode.currentIndex++;
}
nms.tvmode.stop = function() {
- nms.timers.tvmode.stop();
- document.body.classList.remove("tvmode");
- document.body.classList.remove("vertical");
- nms.tvmode.active = false;
+ if (nms.tvmode.active) {
+ nms.timers.tvmode.stop();
+ nms.tvmode.active = false;
+ }
+}
+
+/*
+ * Used when changing handler to ensure that the new handler is listed in
+ * the anchor. The anchor can contain a comma-separated list of views and
+ * we only overwrite it if the new view isn't present.
+ */
+function ensureAnchorHas(view) {
+ try {
+ var views = document.location.hash.slice(1);
+ views = views.split(",");
+ if (views.includes(view)) {
+ return true;
+ }
+ } catch(e) { }
+ document.location.hash = view;
+ return false;
}
/*
* Change map handler (e.g., change from uplink map to ping map)
+ *
+ * stopTv esnures that we don't conflict with the tvmode thing. If a
+ * user-initiated map is selected, tvmode is disabled.
*/
-function setUpdater(fo)
+function setUpdater(fo, stopTv = true)
{
+ if (stopTv)
+ nms.tvmode.stop();
nmsMap.reset();
nmsData.unregisterHandlerWildcard("mapHandler");
try {
@@ -425,7 +253,7 @@ function setUpdater(fo)
}
var foo = document.getElementById("map-mode-title");
foo.innerHTML = fo.name;
- document.location.hash = fo.tag;
+ ensureAnchorHas(fo.tag);
}
function toggleLayer(layer) {
@@ -436,6 +264,12 @@ function toggleLayer(layer) {
l.style.display = 'none';
}
+function hideLayer(layer) {
+ var l = document.getElementById(layer);
+ l.style.display = 'none';
+}
+
+
function toggleConnect() {
toggleLayer("linkCanvas");
}
@@ -498,6 +332,10 @@ function setNightMode(toggle) {
*
* If you add a configuration setting, use nmsData['config'] as much as
* possible. Avoid adding to this function.
+ *
+ * FIXME: If anyone has a way to remove the deprecation warnings, either by
+ * just silencing them or by moving this off the main thread, then go
+ * ahead and fix it. I don't consider it a real problem, though.
*/
function getInitialConfig() {
$.ajax({
@@ -510,7 +348,6 @@ function getInitialConfig() {
nms._public = true;
document.body.classList.add("gondul-public");
} else {
- console.log("Private");
nms._public = false;
document.body.classList.add("gondul-private");
}
@@ -526,7 +363,8 @@ function getInitialConfig() {
* yet.
*/
function initNMS() {
- nms.timers.playback = new nmsTimer(nms.playback.tick, 1000, "Playback ticker", "Handler used to advance time");
+ // Only used for dev-purposes now. Accessible through nms.uptime.
+ nms._startTime = Date.now();
// Public
nmsData.registerSource("config","/api/public/config");
@@ -558,23 +396,23 @@ function initNMS() {
restoreSettings();
nmsMap.init();
detectHandler();
- nms.playback.play();
setupKeyhandler();
- setupSearchKeyHandler();
+ nmsSearch.init();
}
function detectHandler() {
- if (nms.tvmodeToggle) {
- var views = nms.views;
- var interval = nms.interval;
-
- views = views.split(",");
-
+ var views = document.location.hash.slice(1);
+ var interval = nms.interval;
+ if (views == undefined || views == "")
+ views = "ping";
+ views = views.split(",");
+
+ if (views.length > 1) {
nms.tvmode.start(views,interval);
return;
} else {
for (var i in handlers) {
- if (('#' + handlers[i].tag) == document.location.hash) {
+ if (handlers[i].tag == views[0]) {
setUpdater(handlers[i]);
return;
}
@@ -623,6 +461,9 @@ function setMapModeFromN(e,key)
case '3':
setUpdater(handler_dhcp);
break;
+ case '4':
+ setUpdater(handler_health);
+ break;
case '5':
setUpdater(handler_temp);
break;
@@ -646,23 +487,22 @@ function moveTimeFromKey(e,key)
{
switch(key) {
case 'h':
- nms.playback.stepTime(-3600);
+ nmsTime.stepKey(-60);
break;
case 'j':
- nms.playback.stepTime(-300);
+ nmsTime.stepKey(-5);
break;
case 'k':
- nms.playback.stepTime(300);
+ nmsTime.stepKey(5);
break;
case 'l':
- nms.playback.stepTime(3600);
+ nmsTime.stepKey(60);
break;
case 'p':
- nms.playback.toggle();
+ nmsTime.togglePause();
break;
case 'r':
- nms.playback.setNow();
- nms.playback.play();
+ nmsTime.realTime();
break;
}
return true;
@@ -708,13 +548,6 @@ function setupKeyhandler()
});
}
-function setupSearchKeyHandler()
-{
- $("#searchbox").keyup(function(e) {
- nmsInfoBox._searchKeyListener(e);
- });
-}
-
function getCookie(cname) {
var name = cname + "=";
@@ -773,29 +606,22 @@ function restoreSettings()
}
/*
- * Time travel gui
+ * Test if the entire path specified in the arrary "ar" exists under the
+ * specified root.
+ *
+ * E.g.:
+ * if (!testTree(nmsData,['snmp','snmp',sw,'misc'])) {
+ * do stuff with nmsData.snmp.snmp[sw].misc
+ * }
+ *
*/
-function startNowPicker(now) {
- $.datetimepicker.setLocale('no');
- $('#nowPicker').datetimepicker('destroy');
- if(!now && nms.now)
- now = nms.now;
- var datepicker = $('#nowPicker').datetimepicker({
- value: now,
- mask:false,
- inline:true,
- todayButton: false,
- validateOnBlur:false,
- dayOfWeekStart:1,
- maxDate:'+1970/01/01',
- onSelectDate: function(ct,$i){
- document.getElementById('nowPicker').dataset.iso = localEpochToString(ct.valueOf()/1000);
- },
- onSelectTime: function(ct,$i){
- document.getElementById('nowPicker').dataset.iso = localEpochToString(ct.valueOf()/1000);
- },
- onGenerate: function(ct,$i){
- document.getElementById('nowPicker').dataset.iso = localEpochToString(ct.valueOf()/1000);
- }
- });
+function testTree(root, ar) {
+ if (ar == undefined || root == undefined)
+ return false;
+ for (var i in ar) {
+ root = root[ar[i]];
+ if (root == undefined)
+ return false;
+ }
+ return true;
}