1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# netmerge-xmlrpc.py
#
# Copyright 2015 Neil Williams <codehelp@debian.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
#
"""
Run once per output file to merge the new data with the existing
device dictionary.
Remember: importing a device dictionary replaces the entire dictionary
with the new contents.
"""
import os
import re
import yaml
import argparse
import xmlrpclib
def jinja2_to_dict(data_dict):
"""
This could be an XMLRPC routine itself at some point.
"""
if type(data_dict) is not str:
return None
data = {}
data_dict = data_dict.replace('\n', '')
data_dict = data_dict.replace('%}', '%}\n')
for line in data_dict.replace('{% ', '').replace(' %}', '').split('\n'):
if line == '':
continue
if line.startswith('extends'):
base = line.replace('extends ', '')
base = base.replace('"', "'").replace("'", '')
data['extends'] = base
if line.startswith('set '):
key = line.replace('set ', '')
key = re.sub(' = .*$', '', key)
value = re.sub('^.* = ', '', line)
data[key] = yaml.load(value)
if 'extends' not in data:
return None
return data
def main(args):
parser = argparse.ArgumentParser(description='network map jinja2 merge')
parser.add_argument(
'--username', metavar='first.last', type=str,
dest='username', required=True,
help='superuser username')
parser.add_argument(
'--token', metavar='token', type=str,
dest='token', required=True,
help='superuser token')
parser.add_argument(
'--serverurl', metavar='url', type=str,
dest='server', required=True,
help='server holding existing content')
parser.add_argument(
'--hostname', metavar='NAME', type=str,
dest='hostname', required=True,
help='device hostname')
parser.add_argument(
'--protocol', metavar='protocol', type=str,
dest='protocol', default='http',
help='http or https')
args = parser.parse_args()
if not os.path.exists('./merged'):
os.mkdir('merged')
output_file = os.path.join('output', "%s.jinja2" % args.hostname)
if not os.path.exists(output_file):
print >> sys.stderr, "Failed to find output file for %s" % args.hostname
return 1
with open(output_file, 'r') as data:
jinja_str = data.read()
mapped_csv = jinja2_to_dict(jinja_str)
if not mapped_csv:
print >> sys.stderr, "Failed to parse output jinja string for %s" % args.hostname
return 1
connection = xmlrpclib.ServerProxy("%s://%s:%s@%s//RPC2" %
(args.protocol, args.username, args.token, args.server))
jinja_str = connection.scheduler.export_device_dictionary(args.hostname)
if not jinja_str:
print >> sys.stderr, "Failed to find device dictionary for %s" % args.hostname
return 1
map_data = jinja2_to_dict(str(jinja_str))
if not map_data:
print >> sys.stderr, "Failed to parse existing jinja string for %s" % args.hostname
return 1
mapped_csv['extends'] = map_data['extends']
map_data.update(mapped_csv)
with open('./merged/%s.jinja2' % args.hostname, 'w') as merge:
merge.write("{%% extends '%s' %%}\n" % map_data['extends'])
for key, value in map_data.items():
if key == 'extends':
continue
if isinstance(value, str):
merge.write("{%% set %s = '%s' %%}\n" % (key, value))
else:
merge.write("{%% set %s = %s %%}\n" % (key, value))
return 0
if __name__ == '__main__':
import sys
sys.exit(main(sys.argv))
|