diff options
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 Binary files differnew file mode 100644 index 0000000..aecedd0 --- /dev/null +++ b/web/img/dx16-salkart.png 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">×</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">×</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;  }  | 
