blob: 903b6452611ee3b97484ab88b041994da0720f7c [file] [log] [blame]
Radek Krejcicbbb1972017-09-21 13:25:19 +02001"""
2NETCONF connections
3File: connections.py
4Author: Radek Krejci <rkrejci@cesnet.cz>
5"""
6
Radek Krejci67c922d2017-09-21 13:56:41 +02007import json
8import os
9
Radek Krejcicbbb1972017-09-21 13:25:19 +020010from liberouterapi import auth
11from flask import request
12import netconf2 as nc
Radek Krejcicbbb1972017-09-21 13:25:19 +020013
14from .inventory import INVENTORY
15from .devices import devices_get
16from .error import NetopeerException
Radek Krejcia1339602017-11-02 13:52:38 +010017from .data import *
Radek Krejcicbbb1972017-09-21 13:25:19 +020018
19sessions = {}
20
Radek Krejcie20e4d82017-11-08 14:18:05 +010021def hostkey_check(hostname, state, keytype, hexa, priv):
22 # TODO real check
23 return True
24
Radek Krejcicbbb1972017-09-21 13:25:19 +020025@auth.required()
26def connect():
27 session = auth.lookup(request.headers.get('Authorization', None))
28 user = session['user']
29 path = os.path.join(INVENTORY, user.username)
30
Radek Krejcia6c8b412017-10-17 16:59:38 +020031 data = request.get_json()
32 if 'id' in data:
33 # stored device
34 device = devices_get(data['id'], user.username)
35 elif 'device' in data:
36 # one-time connect, the device is specified in request
37 device = data['device']
38 else:
39 raise NetopeerException('Invalid connection request.')
40
Radek Krejcicbbb1972017-09-21 13:25:19 +020041 if not device:
42 raise NetopeerException('Unknown device to connect to request.')
43
44 nc.setSearchpath(path)
45
46 ssh = nc.SSH(device['username'], password=device['password'])
Radek Krejcie20e4d82017-11-08 14:18:05 +010047 ssh.setAuthHostkeyCheckClb(hostkey_check)
Radek Krejcicbbb1972017-09-21 13:25:19 +020048 try:
49 session = nc.Session(device['hostname'], device['port'], ssh)
50 except Exception as e:
51 return(json.dumps({'success': False, 'error-msg': str(e)}))
52
53 if not user.username in sessions:
54 sessions[user.username] = {}
55
56 # use key (as hostname:port:session-id) to store the created NETCONF session
57 key = session.host + ":" + str(session.port) + ":" + session.id
Radek Krejci4d3896c2018-01-08 17:10:43 +010058 sessions[user.username][key] = {}
59 sessions[user.username][key]['session'] = session
Radek Krejcicbbb1972017-09-21 13:25:19 +020060
61 return(json.dumps({'success': True, 'session-key': key}))
62
63
64@auth.required()
65def session_get_capabilities():
66 session = auth.lookup(request.headers.get('Authorization', None))
67 user = session['user']
68 req = request.args.to_dict()
69
70 if not 'key' in req:
71 return(json.dumps({'success': False, 'error-msg': 'Missing session key.'}))
72
73 if not user.username in sessions:
74 sessions[user.username] = {}
75
76 key = req['key']
77 if not key in sessions[user.username]:
78 return(json.dumps({'success': False, 'error-msg': 'Invalid session key.'}))
79
80 cpblts = []
Radek Krejci4d3896c2018-01-08 17:10:43 +010081 for c in sessions[user.username][key]['session'].capabilities:
Radek Krejcicbbb1972017-09-21 13:25:19 +020082 cpblts.append(c)
83
84 return(json.dumps({'success': True, 'capabilities': cpblts}))
85
86@auth.required()
Radek Krejci2e578562017-10-17 11:11:13 +020087def session_get():
88 session = auth.lookup(request.headers.get('Authorization', None))
89 user = session['user']
90 req = request.args.to_dict()
91
92 if not 'key' in req:
93 return(json.dumps({'success': False, 'error-msg': 'Missing session key.'}))
Radek Krejcia1339602017-11-02 13:52:38 +010094 if not 'recursive' in req:
95 return(json.dumps({'success': False, 'error-msg': 'Missing recursive flag.'}))
Radek Krejci2e578562017-10-17 11:11:13 +020096
97 if not user.username in sessions:
98 sessions[user.username] = {}
99
100 key = req['key']
101 if not key in sessions[user.username]:
102 return(json.dumps({'success': False, 'error-msg': 'Invalid session key.'}))
103
Radek Krejci2e578562017-10-17 11:11:13 +0200104 try:
Radek Krejci4d3896c2018-01-08 17:10:43 +0100105 sessions[user.username][key]['data'] = sessions[user.username][key]['session'].rpcGet()
Radek Krejci2e578562017-10-17 11:11:13 +0200106 except nc.ReplyError as e:
107 reply = {'success': False, 'error': []}
108 for err in e.args[0]:
109 reply['error'].append(json.loads(str(err)))
110 return(json.dumps(reply))
111
Radek Krejcia1339602017-11-02 13:52:38 +0100112 if not 'path' in req:
Radek Krejci4d3896c2018-01-08 17:10:43 +0100113 return(dataInfoRoots(sessions[user.username][key]['data'], True if req['recursive'] == 'true' else False))
Radek Krejcia1339602017-11-02 13:52:38 +0100114 else:
Radek Krejci4d3896c2018-01-08 17:10:43 +0100115 return(dataInfoSubtree(sessions[user.username][key]['data'], req['path'], True if req['recursive'] == 'true' else False))
116
117
118@auth.required()
119def session_checkvalue():
120 session = auth.lookup(request.headers.get('Authorization', None))
121 user = session['user']
122 req = request.args.to_dict()
123
124 if not 'key' in req:
125 return(json.dumps({'success': False, 'error-msg': 'Missing session key.'}))
126 if not 'path' in req:
127 return(json.dumps({'success': False, 'error-msg': 'Missing path to validate value.'}))
128 if not 'value' in req:
129 return(json.dumps({'success': False, 'error-msg': 'Missing value to validate.'}))
130
131 if not user.username in sessions:
132 sessions[user.username] = {}
133
134 key = req['key']
135 if not key in sessions[user.username]:
136 return(json.dumps({'success': False, 'error-msg': 'Invalid session key.'}))
137
138 search = sessions[user.username][key]['data'].find_path(req['path'])
139 if search.number() != 1:
140 return(json.dumps({'success': False, 'error-msg': 'Invalid data path.'}))
141 node = search.data()[0]
142
143 try:
144 node.validate_value(req['value'])
145 except:
146 return(json.dumps({'success': False, 'error-msg': ly.Error().errmsg()}))
147
148 return(json.dumps({'success': True}))
Radek Krejci2e578562017-10-17 11:11:13 +0200149
150
151@auth.required()
Radek Krejcicbbb1972017-09-21 13:25:19 +0200152def session_close():
153 session = auth.lookup(request.headers.get('Authorization', None))
154 user = session['user']
155 req = request.args.to_dict()
156
157 if not 'key' in req:
158 return(json.dumps({'success': False, 'error-msg': 'Missing session key.'}))
159
160 if not user.username in sessions:
161 sessions[user.username] = {}
162
163 key = req['key']
164 if not key in sessions[user.username]:
165 return(json.dumps({'success': False, 'error-msg': 'Invalid session key.'}))
166
167 del sessions[user.username][key]
168 return(json.dumps({'success': True}))
169
170@auth.required()
171def session_alive():
172 session = auth.lookup(request.headers.get('Authorization', None))
173 user = session['user']
174 req = request.args.to_dict()
175
176 if not 'key' in req:
177 return(json.dumps({'success': False, 'error-msg': 'Missing session key.'}))
178
179 if not user.username in sessions:
180 sessions[user.username] = {}
181
182 key = req['key']
183 if not key in sessions[user.username]:
184 return(json.dumps({'success': False, 'error-msg': 'Invalid session key.'}))
185
186 return(json.dumps({'success': True}))