views.py 3.9 KB
Newer Older
janis.streib's avatar
janis.streib committed
1
2
import json

janis.streib's avatar
fixup    
janis.streib committed
3
from . import macfinder
4
5
from net_suite.model import *
from net_suite import app
6
from net_suite.views import api_netdb_required, get_db_conn, db, get_current_mgr
7
import requests
8
from flask import request, jsonify, abort
9
10
import re
from . import OUI_DB
11
import redis
12

13

14
class MacFinderJob(DBObject):
janis.streib's avatar
janis.streib committed
15
    def __init__(self, job_id, mac, vlan, bcd):
16
17
18
19
20
        self.job_id = job_id
        self.finished = self.failed = False
        self.status = None
        self.mac = format_mac(mac)
        self.vendor = OUI_DB.get(self.mac[:8], None)
janis.streib's avatar
janis.streib committed
21
        self.vlan = VLAN(**vlan)
janis.streib's avatar
janis.streib committed
22
        self.bcd = bcd
23
24
25
26
27

    def poll(self, session, db, connection):
        if self.finished:
            return self.status
        self.status = session.get(app.config.get('MACFINDER_SERVER_URL') + '/status/{}'.format(self.job_id),
28
29
                                  cert=(app.config.get('MACFINDER_CERT'), app.config.get('MACFINDER_KEY')),
                                  verify=app.config.get('MACFINDER_CA')).json()
30
31
32
33
34
        self.finished = self.status['status'] == 'finished'
        self.failed = self.status['status'] == 'failed'
        return self.status


35
@macfinder.route('/job', methods=['post'])
36
@api_netdb_required
janis.streib's avatar
janis.streib committed
37
38
39
40
41
def create_job():
    if not len(format_mac(request.json['mac'])) == 17:
        return jsonify({'success': False, 'error': 'invalid_mac'}), 400
    vlan_valid = False
    vlans = VLAN.get_by_bcd(db, get_db_conn(), request.json['bcd'])
42
    user = get_current_mgr()
janis.streib's avatar
janis.streib committed
43
    for vlan in vlans:
44
45
46
47
48
        if not user.has_permission('nm.macfinder_global'):
            if user.has_bcd(vlan.bcd):
                vlan_valid = True
                break
        else:
49
            vlan_valid = True
janis.streib's avatar
janis.streib committed
50
51
52
53
    if not vlan_valid:
        return jsonify({'success': False, 'error': 'invalid_vlan'}), 404
    created_jobs = []
    for vlan in vlans:
54
55
56
57
58
59
60
61
62
63
64
65
        with redis.Redis(db=int(app.config.get('REDIS_DB_INDEX'))) as r:
            resp = requests.post(app.config.get('MACFINDER_SERVER_URL') + '/new_task',
                                 cert=(app.config.get('MACFINDER_CERT'), app.config.get('MACFINDER_KEY')),
                                 verify=app.config.get('MACFINDER_CA'),
                                 data={'mac': request.json['mac'], 'vlan': vlan.id, 'net_instnc': vlan.net_instnc,
                                       'tag_check': 'y'})
            if not resp.ok:
                return jsonify({'success': False, 'error': 'internal_error'}), 500
            job_id = resp.json()['job_id']
            created_jobs.append(job_id)
            pipe = r.pipeline()
            pipe.multi()
janis.streib's avatar
janis.streib committed
66
67
68
69
70
71
72
73
            pipe.set(job_id, json.dumps(
                {
                    'mac': request.json['mac'],
                    'job_id': job_id,
                    'vlan': {'id': vlan.id, 'name': vlan.name},
                    'bcd': vlan.bcd
                }
            ))
74
75
            pipe.expire(job_id, 60 * 60 * 12)
            pipe.execute()
janis.streib's avatar
janis.streib committed
76
77
78
    return jsonify({'success': True, 'job_ids': created_jobs})


79
@macfinder.route('/job/<job_id>')
80
@api_netdb_required
81
def poll(job_id):
82
    with redis.Redis(db=int(app.config.get('REDIS_DB_INDEX'))) as r:
83
        job = MacFinderJob(**json.loads(r.get(job_id)))
84
85
86
87
        session = requests.session()
        job.poll(session, db, get_db_conn())
        pipe = r.pipeline()
        pipe.multi()
janis.streib's avatar
janis.streib committed
88
        pipe.set(job_id, json.dumps(job.__dict__))
89
90
91
        pipe.expire(job_id, 60 * 60 * 12)
        pipe.execute()
        return jsonify(job)
92
93


janis.streib's avatar
janis.streib committed
94
95
96
@macfinder.route('/oui_lookup')
def oui_lookup():
    mac = format_mac(request.args['mac'])
97
98
    vendor = OUI_DB.get(mac[:8], None)
    if vendor is None:
99
        return jsonify({'mac': mac, 'vendor': None}), 404
100
    return jsonify({'mac': mac, 'vendor': vendor})
janis.streib's avatar
janis.streib committed
101
102


103
104
105
106
def format_mac(mac):
    mac = mac.lower().strip()
    mac = re.sub(r'(.*?)([0-9a-f]+|$|^)', lambda m: ('' * len(m.groups()[0]) + m.groups()[1]), mac)
    return ''.join(':' + c if i % 2 == 0 and not i == 0 else c for i, c in enumerate(mac, 0))