diff --git a/bon.py b/bon.py new file mode 100755 index 0000000..cd32ae5 --- /dev/null +++ b/bon.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python + +import requests +import json +from IPython import embed +from requests import Request, Session + + +tarball_url = 'https://github.com/kennethreitz/requests/tarball/master' +r = requests.get(tarball_url, stream=False) + +print r.content \ No newline at end of file diff --git a/multiSite/__init__.py b/multiSite/__init__.py new file mode 100644 index 0000000..515f3c4 --- /dev/null +++ b/multiSite/__init__.py @@ -0,0 +1 @@ +__author__ = 'bonhuan' diff --git a/multiSite/copy_application.py b/multiSite/copy_application.py new file mode 100644 index 0000000..56c3f80 --- /dev/null +++ b/multiSite/copy_application.py @@ -0,0 +1,176 @@ +import ast +import push_or_pull_github +from acitoolkit.acisession import Session +from credentials import * + +session = Session(URL, LOGIN, PASSWORD) +resp = session.login() +if not resp.ok: + print '%% Could not login to APIC' + + +def push_json_to_github(content): + git = push_or_pull_github.github_login(git_account, git_pw) + repo = push_or_pull_github.get_repo(git, git_account, git_repo) + json_file = push_or_pull_github.get_file(repo, git_file) + if json_file: + json_file.delete('delete') + push_or_pull_github.create_file(repo, git_file, 'test pushing json', content) + + +def pull_json_from_github(): + return push_or_pull_github.pull_from_github(user_acct=git_account, + user_passwood=git_pw, + repo_owner=git_account, + repo_name=git_repo, + file_name=git_file) + + +def push_json_to_apic(content): + session.login() + return session.push_to_apic('api/mo/uni.json', content) + + +def get_mo_json(mo_class, mo, mo_dn): + + class_query_url = '/api/node/class/'+mo_class+'.json' + ret = session.get(class_query_url) + data = ret.json()['imdata'] + + for fil in data: + dn = fil[mo_class]['attributes']['dn'] + tenant_name = dn.split('/')[1][3:] + mo_name = dn.split('/')[2][len(mo_dn)+1:] + if tenant_name == old_tenant and mo_name == mo: + ap_query_url = '/api/mo/uni/tn-%s/%s-%s.json?rsp-subtree=full&rsp-prop-include=config-only' % (tenant_name, mo_dn, mo_name) + ret = session.get(ap_query_url) + return ast.literal_eval(ret.text)['imdata'][0] + + +def get_app_json_from_apic(application): + + return get_mo_json('fvAp', application, 'ap') + + +def get_bridge_domain_json_from_apic(bridge_domain): + + return get_mo_json('fvBD', bridge_domain, 'BD') + + +def get_private_network_json_from_apic(private_network): + + return get_mo_json('fvCtx', private_network, 'ctx') + + +def get_contracts_json_from_apic(contract): + + return get_mo_json('vzBrCP', contract, 'brc') + + +def get_filters_json_from_apic(filter): + + return get_mo_json('vzFilter', filter, 'flt') + + +if __name__ == '__main__': + + def push_to_list(l, i): + if i not in l: + l.append(i) + +# ----------------------------------------------------------------------------- +# to obtain all the related json files from APIC + + app_json = get_app_json_from_apic(old_application) + # take out parameter 'dn': + del app_json['fvAp']['attributes']['dn'] + + cons = [] + filters = [] + bds = [] + private_networks = [] + + # look for the contracts and bridge domains that are in used + for epg in app_json['fvAp']['children']: + eliminated_children = [] + for child in epg['fvAEPg']['children']: + if child.has_key('fvRsCons'): + push_to_list(cons, child['fvRsCons']['attributes']['tnVzBrCPName']) + if child.has_key('fvRsProv'): + push_to_list(cons, child['fvRsProv']['attributes']['tnVzBrCPName']) + if child.has_key('fvRsBd'): + push_to_list(bds, child['fvRsBd']['attributes']['tnFvBDName']) + if child.has_key('fvRsNodeAtt') or child.has_key('fvRsPathAtt'): + eliminated_children.append(epg['fvAEPg']['children'].index(child)) + eliminated_children.sort(reverse=True) + for index in eliminated_children: + epg['fvAEPg']['children'].pop(index) + + if old_application != new_application: + app_json['fvAp']['attributes']['name'] = new_application + + # achieve all the bridge domain json + bds_json = [] + for bd in bds: + bd_json = get_bridge_domain_json_from_apic(bd) + del bd_json['fvBD']['attributes']['dn'] + bds_json.append(bd_json) + if bd_json['fvBD']['children'][0]['fvRsCtx']['attributes']['tnFvCtxName']: + private_networks.append(bd_json['fvBD']['children'][0]['fvRsCtx']['attributes']['tnFvCtxName']) + + private_networks_json = [] + for pn in private_networks: + pn_json = get_private_network_json_from_apic(pn) + del pn_json['fvCtx']['attributes']['dn'] + private_networks_json.append(pn_json) + + # achieve all the contracts json + contracts_json = [] + for con in cons: + con_json = get_contracts_json_from_apic(con) + del con_json['vzBrCP']['attributes']['dn'] + contracts_json.append(con_json) + # look for the filters that are in used + for subj in con_json['vzBrCP']['children']: + for filter in subj['vzSubj']['children']: + push_to_list(filters, filter['vzRsSubjFiltAtt']['attributes']['tnVzFilterName']) + + # achieve all the filters json + filters_json = [] + for filter in filters: + fil_json = get_filters_json_from_apic(filter) + del fil_json['vzFilter']['attributes']['dn'] + filters_json.append(fil_json) + + # combine all the achieved json into one json object + content = {'fvTenant': {'attributes': {'name': 'bonB'}, 'children': []}} + + def push_child_to_tenant(mo): + content['fvTenant']['children'].append(mo) + + push_child_to_tenant(app_json) + for p_n in private_networks_json: + push_child_to_tenant(p_n) + for b_j in bds_json: + push_child_to_tenant(b_j) + for c_j in contracts_json: + push_child_to_tenant(c_j) + for f_j in filters_json: + push_child_to_tenant(f_j) + + # remove some un-meaningful string + content = str(content) + content.replace('{},', '') + +# ----------------------------------------------------------------------------- + + push_json_to_github(content) + +# ----------------------------------------------------------------------------- + + content = pull_json_from_github() + +# ----------------------------------------------------------------------------- + + res = push_json_to_apic(ast.literal_eval(content)) + print res diff --git a/multiSite/copy_tenant.py b/multiSite/copy_tenant.py new file mode 100644 index 0000000..860de9d --- /dev/null +++ b/multiSite/copy_tenant.py @@ -0,0 +1,66 @@ +import ast +import push_or_pull_github +from acitoolkit.acisession import Session +from credentials import * + +session = Session(URL, LOGIN, PASSWORD) +resp = session.login() +if not resp.ok: + print '%% Could not login to APIC' + + +def push_to_github(content): + git = push_or_pull_github.github_login(git_account, git_pw) + repo = push_or_pull_github.get_repo(git, git_account, git_repo) + json_file = push_or_pull_github.get_file(repo, git_file) + if json_file: + json_file.delete('delete') + push_or_pull_github.create_file(repo, git_file, 'test pushing json', content) + + +def get_json_file_from_apic(): + def get_contract_json(): + class_query_url = '/api/node/class/fvTenant.json' + ret = session.get(class_query_url) + data = ret.json()['imdata'] + for ap in data: + dn = ap['fvTenant']['attributes']['dn'] + tenant_name = dn.split('/')[1][3:] + #class_query_url = '/api/mo/uni/tn-aci-toolkit-demo.json?query-target=subtree&rsp-subtree=full&rsp-subtree-include=audit-logs,no-scoped' + ap_query_url = '/api/mo/uni/tn-%s.json?rsp-subtree=full&rsp-prop-include=config-only' % (tenant_name) + ret = session.get(ap_query_url) + if tenant_name == old_tenant: + return ret + + json_file = get_contract_json() + return json_file.content + + +def pull_from_github(): + return push_or_pull_github.pull_from_github(user_acct=git_account, + user_passwood=git_pw, + repo_owner=git_account, + repo_name=git_repo, + file_name=git_file) + + +def push_to_apic(content): + session.login() + return session.push_to_apic('api/mo/uni.json', content) + + +contract_json = get_json_file_from_apic() +push_to_github(contract_json) + +pull_content = pull_from_github() +pull_content = ast.literal_eval(pull_content) +pull_content = pull_content['imdata'][0] +# take out some parameters: +for key in ['dn']: + del pull_content['fvTenant']['attributes'][key] +# change tenant name +pull_content['fvTenant']['attributes']['name'] = new_tenant + +content = pull_content +res = push_to_apic(content) +print res.text diff --git a/multiSite/credentials.py b/multiSite/credentials.py new file mode 100644 index 0000000..42c5ac9 --- /dev/null +++ b/multiSite/credentials.py @@ -0,0 +1,38 @@ +# Copyright (c) 2014 Cisco Systems +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +# Fill in with the APIC admin userid +LOGIN = 'admin' +# Fill in with the APIC admin password +PASSWORD = 'password' +# Fill in with the APIC IP address +IPADDR = '1.2.3.4' +URL = 'http://' + IPADDR + ':80/' + +# The github account your json file stored to. +git_account = 'github_account' +git_pw = 'password' +# File location in your git account +git_repo = 'repo_name' +git_file = 'file_name' + +# Tenant that to be copied +old_tenant = 'tenantA' +old_application = 'applicationA' + +# The new tenant +new_tenant = 'tenantB' +new_application = 'applicationB' diff --git a/multiSite/push_or_pull_github.py b/multiSite/push_or_pull_github.py new file mode 100644 index 0000000..4ffcadd --- /dev/null +++ b/multiSite/push_or_pull_github.py @@ -0,0 +1,84 @@ +from github3 import login +import sys + +DEFAULT_ACCT = '' +DEFAULT_PASSWORD = '' +DEFAULT_REPO_OWNER = '' +DEFAULT_REPO = '' +DEFAULT_FILE = '' +DEFAULT_MESSAGE = '' +DEFAULT_CONTENT = '' +DEFAULT_BRANCH = 'master' + + +# login to github +def github_login(acct, pw): + return login(acct, pw) + + +def get_repo(github, owner, repo_name): + return github.repository(owner, repo_name) + + +def create_repo(github, repo_name): + github.create_repo(repo_name) + + +def get_file(repo, file_name, branch=DEFAULT_BRANCH): + return repo.contents(file_name, ref='refs/heads/' + branch) + + +def create_file(repo, file_name, commit_msg, content, branch=DEFAULT_BRANCH): + repo.create_file(file_name, commit_msg, content, branch=branch) + + +def push_to_github(user_acct=DEFAULT_ACCT, + user_password=DEFAULT_PASSWORD, + repo_owner=DEFAULT_REPO_OWNER, + repo_name=DEFAULT_REPO, + file_name=DEFAULT_FILE, + commit_msg=DEFAULT_MESSAGE, + content=DEFAULT_CONTENT, + branch=DEFAULT_BRANCH): + + g = github_login(user_acct, user_password) + r = get_repo(g, repo_owner, repo_name) + if not r: + create_repo(g, repo_name) + r = get_repo(g, user_acct, repo_name) + f = get_file(r, file_name, branch=branch) + + # if file already exist, delete it. + if f: + f.delete('delete') + + create_file(r, file_name, commit_msg, content, branch=branch) + + +def get_file_content(file): + return file.decoded + + +def pull_from_github(user_acct=DEFAULT_ACCT, + user_passwood=DEFAULT_PASSWORD, + repo_owner=DEFAULT_REPO_OWNER, + repo_name=DEFAULT_REPO, + file_name=DEFAULT_FILE, + branch=DEFAULT_BRANCH): + + g = github_login(user_acct, user_passwood) + r = get_repo(g, repo_owner, repo_name) + if not r: + print('Requested repo does not exist.') + sys.exit() + + f = get_file(r, file_name, branch=branch) + if not f: + print('Requested file does not exist.') + sys.exit() + + return get_file_content(f) + + +if __name__ == '__main__': + pull_from_github()