blob: 515b0545944db42084e85e07df702920578fc37f [file] [log] [blame]
Radek Krejcid23f0df2017-08-31 16:34:49 +02001"""
2Manipulation with the YANG schemas.
3File: schemas.py
4Author: Radek Krejci <rkrejci@cesnet.cz>
5"""
6
7from liberouterapi import auth, config
8from flask import request
9import libyang as ly
10import json
11import os, errno, time
12
13from .error import NetopeerException
14
15__INVENTORY = config.modules['netopeer']['usersdata_path']
16__SCHEMAS_EMPTY = '{"schemas":{"timestamp":0,"schema":[]}}'
17
18def __schema_parse(path):
19 try:
20 ctx = ly.Context()
21 except Exception as e:
22 raise NetopeerException(str(e))
23
24 return(ctx.parse_path(path, ly.LYS_IN_YANG, 0))
25
26
27def __schemas_init():
28 schemas = json.loads(__SCHEMAS_EMPTY)
29 try:
30 ctx = ly.Context()
31 except Exception as e:
32 raise NetopeerException(str(e))
33
34 # initialize the list with libyang's internal modules
35 modules = ctx.get_module_iter()
36 for module in modules:
37 schemas['schemas']['schema'].append({'name':module.name(),'revision':module.rev().date()})
38 return schemas
39
40
41def __schemas_update(path):
42 schemainv_path = os.path.join(path, '/schemas.json')
43 try:
44 with open(schemainv_path, 'r') as schemas_file:
45 schemas = json.load(schemas_file)
46 except OSError as e:
47 if e.errno == errno.ENOENT:
48 schemas = __schemas_init()
49 else:
50 raise NetopeerException('Unable to use user\'s schemas inventory ' + schemainv_path + ' (' + str(e) + ').')
51 except ValueError:
52 schemas = __schemas_init()
53
54 # get the previous timestamp
55 timestamp = schemas['schemas']['timestamp']
56
57 # check the current content of the storage
58 for file in os.listdir(path):
59 if file[-4] != 'yang':
60 continue
61
62 schemapath = os.path.join(path, file);
63 print(schemapath)
64 if os.path.getmtime(schemapath) > timestamp:
65 # update the list
66 try:
67 module = __schema_parse(schemapath)
68 schemas['schemas']['schema'].append({'name':module.name(),'revision':module.rev().date()})
69 except Exception:
70 pass
71
72 # update the timestamp
73 schemas['schemas']['timestamp'] = time.time()
74
75 #store the list
76 try:
77 with open(schemainv_path, 'w') as schema_file:
78 json.dump(schemas, schema_file)
79 except Exception:
80 pass
81
82 # return the up-to-date list
83 return schemas['schemas']['schema']
84
85def __schemas_check(path):
86 try:
87 os.makedirs(path, mode=0o750)
88 except OSError as e:
89 if e.errno == errno.EEXIST and os.path.isdir(path):
90 pass
91 elif e.errno == errno.EEXIST:
92 raise NetopeerException('User\'s schemas inventory (' + path + ') already exists and it\'s not a directory.')
93 else:
94 raise NetopeerException('Unable to use schemas inventory path ' + path +' (' + str(e) + ').')
95
96
97@auth.required()
98def schemas_list():
99 session = auth.lookup(request.headers.get('Authorization', None))
100 user = session['user']
101 path = os.path.join(__INVENTORY, user.username)
102
103 __schemas_check(path)
104 schemas = __schemas_update(path)
105
106 return(json.dumps(schemas))
107
108@auth.required()
109def schemas_add():
110 if 'schema' not in request.files:
111 raise NetopeerException('Missing schema file in upload request.')
112
113 session = auth.lookup(request.headers.get('Authorization', None))
114 user = session['user']
115 file = request.files['schema']
116
117 # store the file
118 path = os.path.join(__INVENTORY, user.username, file.filename)
119 file.save(path)
120
121 # parse file
122 try:
123 module = __schema_parse(path)
124 except Exception:
125 os.remove(path)
126 return(json.dumps({'success': False}))
127
128 return(json.dumps({'success': True}))