summaryrefslogtreecommitdiff
path: root/netmerge-xmlrpc.py
blob: ef2669168f94ddebc5c09e04e7fa7e94d3be0865 (plain)
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))