aboutsummaryrefslogtreecommitdiffstats
path: root/fap/httpd
diff options
context:
space:
mode:
authorJonas Lindstad <jonaslindstad@gmail.com>2015-03-16 23:09:40 +0100
committerJonas Lindstad <jonaslindstad@gmail.com>2015-03-16 23:09:40 +0100
commit939b606944b6892d26581bce598c66c790786de9 (patch)
tree6780dc26bd26c22ca8dce6a7832841b5f4efc37a /fap/httpd
parent88dfb934e546d02d1f4356032e91277f9f5b94f1 (diff)
rename + fixes
Diffstat (limited to 'fap/httpd')
-rw-r--r--fap/httpd/ex2200.template249
-rw-r--r--fap/httpd/server_http.py143
-rw-r--r--fap/httpd/terminal.log14
3 files changed, 406 insertions, 0 deletions
diff --git a/fap/httpd/ex2200.template b/fap/httpd/ex2200.template
new file mode 100644
index 0000000..aa62ff2
--- /dev/null
+++ b/fap/httpd/ex2200.template
@@ -0,0 +1,249 @@
+system {
+ host-name $hostname;
+ auto-snapshot;
+ time-zone Europe/Oslo;
+ authentication-order [ tacplus password ];
+ root-authentication {
+ encrypted-password "$1$v1xWD3zI$OhStP6PnpgIUO3RLtMmIJ/";
+ }
+ name-server {
+ 1.1.1.1;
+ 2.2.2.2;
+ }
+ login {
+ user technet{
+ uid 2000;
+ class super-user;
+ authentication {
+ encrypted-password "$1$v1xWD3zI$OhStP6PnpgIUO3RLtMmIJ/";
+ }
+ }
+ }
+ services {
+ ssh {
+ root-login deny;
+ }
+ netconf {
+ ssh;
+ }
+ }
+ syslog {
+ user * {
+ any emergency;
+ }
+ file messages {
+ any notice;
+ authorization info;
+ }
+ file interactive-commands {
+ interactive-commands any;
+ }
+ }
+ ntp {
+ server 1.2.3.4;
+ server 2.3.4.5;
+ }
+}
+
+chassis {
+ aggregated-devices {
+ ethernet {
+ device-count 1;
+ }
+ }
+}
+
+interfaces {
+ interface-range edge-ports {
+ member-range ge-0/0/0 to ge-0/0/43;
+ unit 0 {
+ family ethernet-switching {
+ port-mode access;
+ vlan {
+ members deltagere;
+ }
+ }
+ }
+ }
+ interface-range core-ports {
+ member-range ge-0/0/44 to ge-0/0/47;
+ ether-options {
+ 802.3ad ae0;
+ }
+ }
+ ae0 {
+ description "Til $distro_name $distro_phy_port";
+ aggregated-ether-options {
+ lacp {
+ active;
+ }
+ }
+ unit 0 {
+ family ethernet-switching {
+ port-mode trunk;
+ vlan {
+ members deltagere;
+ }
+ native-vlan-id mgmt;
+ }
+ }
+ }
+ vlan {
+ unit $mgmt_vlan {
+ description "MGMT L3 interface";
+ family inet {
+ filter {
+ input v4-mgmt;
+ }
+ address $mgmt_addr/$mgmt_cidr;
+ }
+ family inet6 {
+ filter {
+ input v6-mgmt;
+ }
+ }
+ }
+ }
+}
+firewall {
+ family inet {
+ filter v4-mgmt {
+ term accept-noc {
+ from {
+ source-address {
+ 0.0.0.0/0;
+ }
+ }
+ then accept;
+ }
+ term accept-icmp {
+ from {
+ protocol icmp;
+ }
+ then {
+ accept;
+ }
+ }
+ term reject-all {
+ then {
+ log;
+ syslog;
+ reject;
+ }
+ }
+ }
+ }
+ family inet6 {
+ filter v6-mgmt {
+ term accept-noc {
+ from {
+ source-address {
+ ::/0;
+ }
+ }
+ then accept;
+ }
+ term accept-icmp {
+ from {
+ next-header icmp6;
+ }
+ then {
+ accept;
+ }
+ }
+ term reject-all {
+ then {
+ log;
+ syslog;
+ reject;
+ }
+ }
+ }
+ }
+}
+
+ethernet-switching-options {
+ secure-access-port {
+ interface edge-ports {
+ no-dhcp-trusted;
+ }
+ vlan deltagere {
+ 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;
+ }
+ }
+}
+
+protocols {
+ sflow {
+ sample-rate {
+ ingress 10000;
+ egress 10000;
+ }
+ collector 91.209.30.12;
+ interfaces edge-ports;
+ interfaces core-ports;
+ }
+ igmp-snooping {
+ vlan all {
+ version 3;
+ immediate-leave;
+ }
+ }
+ mld-snooping {
+ vlan all {
+ version 2;
+ immediate-leave;
+ }
+ }
+ rstp {
+ bridge-priority 8k;
+ interface edge-ports {
+ edge;
+ no-root-port;
+ }
+ }
+ lldp {
+ interface ae0.0
+ }
+}
+
+vlans {
+ deltagere {
+ vlan-id $traffic_vlan;
+ }
+ mgmt {
+ vlan-id $mgmt_vlan;
+ l3-interface vlan.$mgmt_vlan;
+ }
+}
+
+routing-options {
+ rib inet.0 {
+ static {
+ route 0.0.0.0/0 {
+ next-hop $mgmt_gw;
+ }
+ }
+ }
+ rib inet6.0 {
+ static {
+ route ::/0 {
+ next-hop 20a0:dead::beef;
+ }
+ }
+ }
+}
+
+
diff --git a/fap/httpd/server_http.py b/fap/httpd/server_http.py
new file mode 100644
index 0000000..bc9ceea
--- /dev/null
+++ b/fap/httpd/server_http.py
@@ -0,0 +1,143 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+from http.server import BaseHTTPRequestHandler, HTTPServer
+from string import Template
+import time
+import psycopg2
+import psycopg2.extras
+import sys
+import os
+
+def main():
+ #
+ # Settings
+ #
+ settings = {
+ 'db': {
+ 'user': 'bootstrap',
+ 'password': 'asdf',
+ 'dbname': 'bootstrap',
+ 'host': 'localhost'
+ },
+ 'http': {
+ 'host': '0.0.0.0',
+ 'port': 80
+ }
+ }
+
+ #
+ # Connect to DB
+ #
+ try:
+ connect_params = ("dbname='%s' user='%s' host='%s' password='%s'" % (settings['db']['dbname'], settings['db']['user'], settings['db']['host'], settings['db']['password']))
+ conn = psycopg2.connect(connect_params)
+ cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
+ # cur.execute("""SELECT * from switches""")
+ # rows = cur.fetchall()
+ # print ("\nSwitches in DB during server_http.py startup:")
+ # for row in rows:
+ # print (" --> %s, connected to %s port %s" % (row['hostname'], row['distro_name'], row['distro_phy_port']))
+
+ except (psycopg2.DatabaseError, psycopg2.OperationalError) as e:
+ print ('Error: %s' % e)
+ sys.exit(1)
+
+ except:
+ print(sys.exc_info()[0])
+ sys.exit(1)
+
+ def template_get(model):
+ return open('fap/httpd/' + model + '.template').read()
+
+ def template_parse(template_src, hostname):
+ cur.execute("SELECT * FROM switches WHERE hostname = '%s'" % hostname)
+ if(cur.rowcount == 1):
+ row = cur.fetchall()[0]
+ d={
+ 'hostname': row['hostname'],
+ 'distro_name': row['distro_name'],
+ 'distro_phy_port': row['distro_phy_port'],
+ 'mgmt_addr': row['mgmt_addr'],
+ 'mgmt_cidr': row['mgmt_cidr'],
+ 'mgmt_gw': row['mgmt_gw'],
+ 'mgmt_vlan': row['mgmt_vlan'],
+ 'traffic_vlan': row['traffic_vlan']
+ }
+ cur.execute("UPDATE switches SET last_config_fetch = '%s' WHERE hostname = '%s'" % (str(time.time()).split('.')[0], hostname)) # updated DB with last config fetch
+ conn.commit()
+ return Template(template_src).safe_substitute(d)
+ else:
+ return False
+
+ class httpd(BaseHTTPRequestHandler):
+ def do_GET(self):
+ print('[%s] [%s] Incoming HTTP GET URI:%s ' % (self.client_address[0], time.asctime(), self.path))
+
+ # Client asks for the config file
+ if '/tg-edge/' in self.path:
+ hostname = self.path.split('/tg-edge/')[1]
+ if len(hostname) > 0:
+ print('[%s] --> Hostname "%s" accepted, fetching info from DB' % (self.client_address[0], hostname))
+ template_parsed = template_parse(template_get('ex2200'), hostname)
+ if template_parsed:
+ print('[%s] --> Template successfully populated' % self.client_address[0])
+ print('[%s] --> Sending response to client' % self.client_address[0])
+ self.send_response(200)
+ self.send_header("Content-type", "text/plain")
+ self.end_headers()
+ self.wfile.write(bytes(template_parsed, "utf-8"))
+ print('[%s] --> Success - %s bytes sent to client' % (self.client_address[0], len(template_parsed)))
+ else:
+ print('[%s] --> Error - could not find hostname "%s" in DB' % (self.client_address[0], hostname))
+ else:
+ print('[%s] --> Rejected due to missing hostname' % self.client_address[0])
+
+ # Client asks for a file download - most likely a JunOS file
+ elif '/files/' in self.path:
+ # It seems that "http.server" escapes nastiness from the URL - ("/files/../../../root_file" => "/files/root_file")
+ requested_file = self.path.split('/files/')[1]
+ files_dir = 'fap/httpd/files/'
+ print('[%s] --> File request for "%s" in "%s"' % (self.client_address[0], requested_file, files_dir))
+ if os.path.isfile(files_dir + requested_file):
+ print('[%s] --> File found' % self.client_address[0])
+ try:
+ f = open(files_dir + requested_file)
+ self.send_response(200)
+ self.send_header('Content-type', 'application/x-gzip') # correct content type for tar.gz
+ self.end_headers()
+ print('[%s] --> File transfer started' % self.client_address[0])
+ f = open(files_dir + requested_file, 'rb')
+ self.wfile.write(f.read())
+ f.close()
+ print('[%s] --> File transfer completed' % self.client_address[0])
+ return
+ except IOError:
+ self.send_error(404,'File Not Found: %s' % self.path)
+ print('[%s] --> ERROR 404 - File not found' % self.client_address[0])
+ pass
+ except:
+ print('[%s] --> Generic error during file reading' % self.client_address[0])
+ pass
+ else:
+ print('[%s] --> File request rejected due to nonexisting file' % self.client_address[0])
+ else:
+ print('[%s] --> rejected due to bad URI' % self.client_address[0])
+ # silence stderr from BaseHTTPRequestHandler
+ # source: http://stackoverflow.com/questions/3389305/how-to-silent-quiet-httpserver-and-basichttprequesthandlers-stderr-output
+ def log_message(self, format, *args):
+ return
+
+ httpd_instance = HTTPServer((settings['http']['host'], settings['http']['port']), httpd)
+ print("\n[%s] Server Starts - %s:%s" % (time.asctime(), settings['http']['host'], settings['http']['port']))
+
+ try:
+ httpd_instance.serve_forever()
+ except KeyboardInterrupt:
+ pass
+
+ httpd_instance.server_close()
+ print("\n\n[%s] HTTP Server stopped\n" % time.asctime())
+
+if __name__ == "__main__":
+ main()
diff --git a/fap/httpd/terminal.log b/fap/httpd/terminal.log
new file mode 100644
index 0000000..bedb829
--- /dev/null
+++ b/fap/httpd/terminal.log
@@ -0,0 +1,14 @@
+j@lappie:~/git/tgmanage$ sudo python3 fap/httpd/server_http.py
+
+[Thu Feb 19 23:15:45 2015] Server Starts - 0.0.0.0:80
+[10.0.200.101] [Fri Feb 20 00:18:25 2015] Incoming HTTP GET URI://tg-edge/e-00-1
+[10.0.200.101] --> Hostname "e-00-1" accepted, fetching info from DB
+[10.0.200.101] --> Template successfully populated
+[10.0.200.101] --> Sending response to client
+[10.0.200.101] --> Success - 1437 bytes sent to client
+[10.0.200.101] [Fri Feb 20 00:18:26 2015] Incoming HTTP GET URI://files/jinstall-ex-2200-12.3R6.6-domestic-signed.tgz
+[10.0.200.101] --> File request for "jinstall-ex-2200-12.3R6.6-domestic-signed.tgz" in "fap/httpd/files/"
+[10.0.200.101] --> File found
+[10.0.200.101] --> File transfer started
+[10.0.200.101] --> File transfer completed
+