-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathDcim-to-netbox.py
164 lines (146 loc) · 7.24 KB
/
Dcim-to-netbox.py
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import sys
import json
import collections
from django.utils.http import urlquote
import requests
from slugify import slugify
import mysql.connector
import dns.resolver
import dns.zone
### OpenDCIM Database Connection Settings
dbHost = "openDcimDbHost.example.com"
dbUser = "openDcimDbUser"
dbPasswd = "openDcimDbPassword"
dbName = "OpenDcimDbName"
### Netbox API connection Settings ###
baseNetboxUrl = "http://netbox-app-p01.example.com:80/"
netboxToken = 'NetboxRootUserApiToken'
netboxUser = "NetboxAdminUser"
### Mapfile where the queries and the API output locations variables are set ###
queryMapFile = 'QueryMap.json'
### booleans for enabling various debug data output ###
ingestDebugFlag = True
dcimOutputEnableFlag = True
outputDebugFlag = True
outputResponseFlag = True
reQueryResponseFlag = False
### Locaion of output log dumps. Set to text file because output verbosity can overwhelm terminal buffers ###
debugOutputFile = open("DUMP.txt","w+")
sys.stdout = open('stdoutdump.txt', 'w+')
### Initialization of variables for data retrieval and requery ###
commonHeaders = {
'Authorization': 'Token ' + netboxToken,
'Accept': 'application/json; indent=4',
}
dcimRequeryTypes = ["device-roles/", "manufacturers/", "device-types/","sites/", "racks/", "rack-groups/", "devices/", "inventory-items/", "device-bays/",]
tenancyRequeryTypes = ["tenants/"]
netboxLoginURL = baseNetboxUrl + "login/"
postCountDict = collections.OrderedDict()
class apiEngine:
def __init__(self, sType, sSubType):
self.netboxAPIurl = baseNetboxUrl + "api/" + sType + sSubType
self.client = requests.session()
self.client.get(netboxLoginURL)
self.csrftoken = self.client.cookies['csrftoken']
self.retrieveHeaders = commonHeaders
self.retrieveHeaders.update({'X-CSRFToken': self.csrftoken})
self.submitHeaders = self.retrieveHeaders
self.submitHeaders.update({'Content-Type': 'application/json'})
def netboxSubmit(self, sObject):
if outputDebugFlag:
print("? ATTEMPTING TO POST \'" + sObject + "\'")
response = self.client.post(self.netboxAPIurl, data=sObject, headers=self.submitHeaders)
if outputResponseFlag:
print("! SUCCESSFUL POST OF THE FOLLOWING: \'" + response.text + "\'")
debugOutputFile.write(str(response.text))
def netboxRetrieve(self):
retrievalURL = self.netboxAPIurl + "?limit=100000"
response = self.client.get(retrievalURL, headers=self.retrieveHeaders)
jsonResponseDump = json.loads(response.text)
if reQueryResponseFlag:
print("+ API RESPONSE FOR REQUERY: \'" + retrievalURL + "\' Reads: \'" + str(jsonResponseDump) + "\'")
return jsonResponseDump
reQueryEngineInstanceDict = collections.OrderedDict()
for rqType in dcimRequeryTypes:
reQueryEngineInstanceDict[rqType] = apiEngine("dcim/", rqType)
postCountDict[rqType] = 0
for rqType in tenancyRequeryTypes:
reQueryEngineInstanceDict[rqType] = apiEngine("tenancy/", rqType)
postCountDict[rqType] = 0
class QueryEngine:
def __init__(self, sType, sSubType):
self.dbConnector = mysql.connector.connect(
host=dbHost,
user=dbUser,
passwd=dbPasswd,
database=dbName
)
### Instantiate cursor and apiEngine ###
self.dbCursor = self.dbConnector.cursor()
self.submitInstance = apiEngine(sType, sSubType)
def dbQuery(self, queryString, outputMapping, slugEnable, migrationType):
self.dbCursor.execute(queryString)
rows = self.dbCursor.fetchall()
objects_list = []
for row in rows:
d = collections.OrderedDict()
for outParam in outputMapping:
if isinstance(outputMapping[outParam], int):
if outParam == 'subdevice_role':
if row[(outputMapping[outParam])] == '1':
d[outParam] = True
elif row[(outputMapping[outParam])] == '0':
d[outParam] = False
else:
d[outParam] = "None"
else:
d[outParam] = row[(outputMapping[outParam])]
else:
reQueryObject = row[outputMapping[outParam]['reQueryIndexHeader']]
reQuerySubType = outputMapping[outParam]['sSubType']
rqParamName = reQueryLookupDict[reQuerySubType]
#print("SEARCHING FOR:" + rqParamName + reQueryObject + " SEARCHING IN: " + reQuerySubType)
reQueryReturnDict = next(item for item in postResponses[reQuerySubType]['results'] if item[rqParamName] == reQueryObject)
#print(reQueryReturnDict)
reQueryResult = reQueryReturnDict['id']
#print("RQRESULT: " + str(reQueryResult))
d[outParam] = reQueryResult
if slugEnable:
d['slug'] = slugify(row[0])
objects_list.append(d)
if dcimOutputEnableFlag:
for nbDataObject in objects_list:
nbDataObjectJsonDump = json.dumps(nbDataObject, sort_keys=True, indent=4)
self.submitInstance.netboxSubmit(nbDataObjectJsonDump)
postCountDict[sSubType] = postCountDict[sSubType] + 1
reQueryDump = reQueryEngineInstanceDict[sSubType].netboxRetrieve()
return reQueryDump
postResponses = collections.OrderedDict()
with open(queryMapFile) as json_file:
data = json.load(json_file)
reQueryLookupDict = data['reQueryLookupDict']
for mType in data['results']:
### set parameters for the submission and query engine based on the map file ###
migrationType = mType['querySubObjectID']
sType = mType['sType']
sSubType = mType['sSubType']
queryString = mType['queryString']
outputMapping = mType['outputMapping']
slugEnable = mType['slugEnable']
### submission mapping debug code ###
if ingestDebugFlag:
print("\n")
print("- MIGRATION DEBUG INFORMAION FOR: \'" + migrationType + "\'")
print(" - API SUBMISSION URL: \n \t" + "-\'api/" + sType + sSubType + "\'")
print(" - SQL QUERY STRING: \n \t \'-" + queryString + "\'")
print(" - THE SLUG ENABLE FLAG IS SET TO: \n \t -\'" + str(slugEnable) + "\'")
print(" - OUTPUT PARAMETER MAPPING: - [ Mapping Parameter : QueryIndex or sSubType : reQueryPointer (If Applicable) ]")
for outParam in outputMapping:
if isinstance(outputMapping[outParam], int):
print("\t" * 1 + " - \'" + outParam + "\' = \'" + str(outputMapping[outParam]) + "\'")
else:
print("\t" * 1 + " - \'" + outParam + "\' = SST \'" + outputMapping[outParam]['sSubType'] + "\' @ \'" + str(outputMapping[outParam]['reQueryIndexHeader']) + "\'")
### code for submitting the request group ###
queryEngineInstance = QueryEngine(sType, sSubType)
postResponses[sSubType] = queryEngineInstance.dbQuery(queryString, outputMapping, slugEnable, migrationType)
print("Successfully Posted: " + str(postCountDict[sSubType]) + "Items for type: " + str(sSubType))