#!/usr/bin/python

import sys
import json
import subprocess
import argparse
import hashlib
import exceptions

magic      = 'OVSDB JSON'
DEF_CONF   = '/var/lib/openvswitch/conf.db'
DEF_TARGET = ''

def get_ovsdb_schema(db):
    cmd = '/usr/bin/ovsdb-client get-schema %s' %db
    pr = subprocess.Popen(cmd.split(),
                          stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE)
    (sch, stderr) = pr.communicate()
    sch = sch + '\n'
    return sch

def get_ovsdb_raw_dump(db, schema):
    if schema is None:
        raise

    schema_json = json.loads(schema)
    schema_keys = sorted(schema_json["tables"].keys())
    cmd = '/usr/bin/ovsdb-client dump %s -f raw' %db

    pr = subprocess.Popen(cmd.split(),
                          stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE)
    (raw, stderr) = pr.communicate()
    rawdb = raw.splitlines()
    size = len(rawdb)

    newdb = ''
    for l in rawdb:
        t = {}
        j = json.loads(l)
        for e in j['rows']:
            k = e['_uuid'][1]
            v = dict(e)
            del v['_uuid']
            t[k] = v

        if len(j['rows']) != 0:
            o = json.dumps(t).replace(' ', '')
            idx = rawdb.index(l)
            newdb = newdb + '\"%s\":%s' %(schema_keys[idx], o)
            if idx != (size - 1):
                newdb = newdb + ','

    newdb = '{' + newdb + '}'
    return newdb

def write_to_conf(p, data):
    h = hashlib.sha1(data)
    header = '%s %d %s\n' % (magic, len(data), h.hexdigest())
    p.write(header)
    p.write(data)

def setup_arg_parser():
    parser = argparse.ArgumentParser()
    parser.add_argument('--target', dest='target', nargs='?', default=DEF_CONF,
                        help='new db file, default /var/lib/openvswitch/conf.db')
    parser.add_argument('--db', dest='db', nargs='?', default=DEF_TARGET,
                        help='db path e.g. tcp:10.0.0.1:1234')
    return parser

def main(args):
    parser = setup_arg_parser()
    args = parser.parse_args()

    try:
        schema = get_ovsdb_schema(args.db)
        db = get_ovsdb_raw_dump(args.db, schema)
    except Exception, e:
        print 'ovsdb backup from %s failed\n' % args.db
        exit(1)

    try:
        fp = open(args.target, 'w+')
        write_to_conf(fp, schema)
        write_to_conf(fp, db)
        fp.close()
    except Exception, e:
        print 'write ovsdb backup file failed\n'
        exit(1)

if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))
