gui CHANGE refactor work with schemas
- store all schemas as files in backend to unify work and keep all
dependencies in a single searchpath
- work with schemas as with dictionary - move key from the structure
itself to the dictionary key. However it is still possible to generate
the key from the schema itself
diff --git a/backend/schemas.py b/backend/schemas.py
index 7b12e9d..7dfef7c 100644
--- a/backend/schemas.py
+++ b/backend/schemas.py
@@ -8,6 +8,8 @@
import os
import errno
import time
+from subprocess import check_output
+from shutil import copy
from liberouterapi import auth
from flask import request
@@ -16,7 +18,7 @@
from .inventory import INVENTORY, inventory_check
from .error import NetopeerException
-__SCHEMAS_EMPTY = '{"schemas":{"timestamp":0,"schema":[]}}'
+__SCHEMAS_EMPTY = '{"timestamp":0, "schemas":{}}'
def __schema_parse(path, format = yang.LYS_IN_UNKNOWN):
@@ -36,9 +38,9 @@
raise NetopeerException(str(e))
return module
-
-def __schemas_init():
+
+def __schemas_init(path):
schemas = json.loads(__SCHEMAS_EMPTY)
try:
ctx = yang.Context()
@@ -48,7 +50,27 @@
# initialize the list with libyang's internal modules
modules = ctx.get_module_iter()
for module in modules:
- schemas['schemas']['schema'].append({'key':module.name() + '@' + module.rev().date(), 'name':module.name(), 'revision':module.rev().date()})
+ name_norm = module.name() + '@' + module.rev().date() + '.yang'
+ schemas['schemas'][name_norm] = {'name':module.name(), 'revision':module.rev().date()}
+ try:
+ with open(os.path.join(path, name_norm), 'w') as schema_file:
+ schema_file.write(module.print_mem(yang.LYS_OUT_YANG, 0))
+ except:
+ pass
+ try:
+ nc_schemas_dir = check_output("pkg-config --variable=LNC2_SCHEMAS_DIR libnetconf2", shell = True).decode()
+ nc_schemas_dir = nc_schemas_dir[:len(nc_schemas_dir) - 1]
+ for file in os.listdir(nc_schemas_dir):
+ if file[-5:] == '.yang' or file[-4:] == '.yin':
+ try:
+ copy(os.path.join(nc_schemas_dir, file), path)
+ except:
+ pass
+ else:
+ continue
+ except:
+ pass
+
return schemas
@@ -59,35 +81,37 @@
schemas = json.load(schemas_file)
except OSError as e:
if e.errno == errno.ENOENT:
- schemas = __schemas_init()
+ schemas = __schemas_init(path)
else:
raise NetopeerException('Unable to use user\'s schemas inventory ' + schemainv_path + ' (' + str(e) + ').')
except ValueError:
- schemas = __schemas_init()
+ schemas = __schemas_init(path)
return schemas
+
def __schemas_inv_save(path, schemas):
schemainv_path = os.path.join(path, 'schemas.json')
# update the timestamp
- schemas['schemas']['timestamp'] = time.time()
+ schemas['timestamp'] = time.time()
#store the list
try:
with open(schemainv_path, 'w') as schema_file:
- json.dump(schemas, schema_file)
+ json.dump(schemas, schema_file, sort_keys = True)
except Exception:
pass
return schemas
+
def __schemas_update(path):
# get schemas database
schemas = __schemas_inv_load(path)
# get the previous timestamp
- timestamp = schemas['schemas']['timestamp']
+ timestamp = schemas['timestamp']
# check the current content of the storage
for file in os.listdir(path):
@@ -104,22 +128,31 @@
try:
module = __schema_parse(schemapath, format)
if module.rev_size():
- schemas['schemas']['schema'].append({'key':module.name() + '@' + module.rev().date(),
- 'name':module.name(),
- 'revision':module.rev().date(),
- 'file':os.path.basename(schemapath)})
+ name_norm = module.name() + '@' + module.rev().date() + '.yang'
+ schemas['schemas'][name_norm] = {'name': module.name(), 'revision': module.rev().date()}
else:
- schemas['schemas']['schema'].append({'key':module.name() + '@',
- 'name':module.name(),
- 'file':os.path.basename(schemapath)})
- except Exception as e:
+ name_norm = module.name() + '.yang'
+ schemas['schemas'][name_norm] = {'name': module.name()}
+ if file != name_norm:
+ try:
+ with open(os.path.join(path, name_norm), 'w') as schema_file:
+ schema_file.write(module.print_mem(yang.LYS_OUT_YANG, 0))
+ except:
+ pass
+
+ try:
+ os.remove(schemapath)
+ except:
+ pass
+ except:
continue
#store the list
__schemas_inv_save(path, schemas)
# return the up-to-date list
- return schemas['schemas']['schema']
+ return schemas['schemas']
+
@auth.required()
def schemas_list():
@@ -130,7 +163,7 @@
inventory_check(path)
schemas = __schemas_update(path)
- return(json.dumps(schemas))
+ return(json.dumps(schemas, sort_keys = True))
@auth.required()
@@ -145,18 +178,13 @@
key = req['key']
schemas = __schemas_inv_load(path)
- for i in range(len(schemas['schemas']['schema'])):
- schema = schemas['schemas']['schema'][i]
- if schema['key'] == key:
- data = ""
- if 'file' in schema:
- with open(os.path.join(path, schema['file']), 'r') as schema_file:
- data = schema_file.read()
- else:
- ctx = yang.Context()
- data = ctx.get_module(schema['name']).print_mem(yang.LYS_OUT_YANG, 0)
+ if key in schemas['schemas']:
+ try:
+ with open(os.path.join(path, key), 'r') as schema_file:
+ data = schema_file.read()
return(json.dumps({'success': True, 'data': data}))
-
+ except:
+ pass;
return(json.dumps({'success': False, 'error-msg':'Schema ' + key + ' not found.'}))
@@ -182,13 +210,29 @@
else:
format = yang.LYS_IN_UNKNOWN
module = __schema_parse(path, format)
- # TODO: normalize file name to allow removing without remembering schema path
+
+ # normalize file name to allow removing without remembering schema path
+ if module.rev_size():
+ name_norm = module.name() + '@' + module.rev().date() + '.yang'
+ else:
+ name_norm = module.name() + '.yang'
+ if file.filename != name_norm:
+ with open(os.path.join(INVENTORY, user.username, name_norm), 'w') as schema_file:
+ schema_file.write(module.print_mem(yang.LYS_OUT_YANG, 0))
+ try:
+ os.remove(path)
+ except:
+ pass
except Exception:
- os.remove(path)
+ try:
+ os.remove(path)
+ except:
+ pass
return(json.dumps({'success': False}))
return(json.dumps({'success': True}))
+
@auth.required()
def schemas_rm():
session = auth.lookup(request.headers.get('Authorization', None))
@@ -200,15 +244,9 @@
raise NetopeerException('Invalid schema remove request.')
schemas = __schemas_inv_load(path)
- for i in range(len(schemas['schemas']['schema'])):
- schema = schemas['schemas']['schema'][i]
- if schema['key'] == key:
- schemas['schemas']['schema'].pop(i)
- break;
- else:
- schema = None;
-
- if not schema:
+ try:
+ schemas.pop(key)
+ except KeyError:
# schema not in inventory
return (json.dumps({'success': False}))
@@ -216,12 +254,11 @@
__schemas_inv_save(path, schemas)
# remove the schema file
- if 'revision' in schema:
- path = os.path.join(path, schema['name'] + '@' + schema['revision'] + '.yang')
- else:
- path = os.path.join(path, schema['name'] + '.yang')
- os.remove(path)
+ try:
+ os.remove(os.path.join(path, key))
+ except Exception as e:
+ print(e)
- # TODO: resolve dependencies
+ # TODO: resolve dependencies ?
return(json.dumps({'success': True}))