-
Notifications
You must be signed in to change notification settings - Fork 1
/
InfobloxAPI.py
221 lines (188 loc) · 7.55 KB
/
InfobloxAPI.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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
"""
A class object to abstract interaction with the Infoblox Grid Manager
Web API v1.1.
API v1.1 info:
Docs: https://support.infoblox.com/technical-documents
Spec: Infoblox_RESTful_API_Documentation_1.1
"""
import datetime
import json
import os
import requests
import sys
import time
class InfobloxAPI:
""" Return an object with all the information required to start
making WAPI calls.
Examples:
Generate a new hostname and assign it to the first available
IP address in a network. Start checking availble names from
prexix0010.example.com:
from InfobloxAPI import InfobloxAPI
i = InfobloxAPI('gridmgr.example.com', 'username', 'password')
network = '192.168.1.0/24'
i.rh_add( network,
i.next_available_ip(network),
i.next_available_name('prefix', 10, 'example.com') )
"""
def __init__(self, server, username, password,
verbose=False, debug=False, verify=True):
""" Initialize InfobloxAPI. Requires API server to connect to,
as well as username and password for authentication and
authorization. No calls are made yet, so there is no test
yet of the information the object is initialized with.
"""
self.server = server
self.username = username
self.password = password
self.verbose = verbose
self.debug = debug
self.verify = verify
self.url = 'https://' + self.server + '/wapi/v1.1/'
def rh_exists(self, hostname, like=False):
"""Test if a record:host for name=hostname exists.
Return True or False.
"""
if like:
data = { 'name~' : hostname }
else:
data = { 'name' : hostname }
self.r = requests.get(self.url + 'record:host',
params=data,
auth=(self.username, self.password),
verify=self.verify)
if self.debug:
print "inside rh_exists: " + hostname
print self.r.text
return self.r.json()
def ra_exists(self, hostname, like=False):
"""record:a_record for name=hostname exist?
Return True or False.
"""
if like:
data = { 'name~' : hostname }
else:
data = { 'name' : hostname }
self.r = requests.get(self.url + 'record:a',
params=data,
auth=(self.username, self.password),
verify=self.verify)
if self.debug:
print "inside ra_exists: " + hostname
print self.r.text
try:
return self.r.json()
except Exception as e:
print self.r.text
sys.exit(1)
def network_ref(self, network):
"""Return _ref where network=network"""
data = { 'network' : network }
self.r = requests.get(self.url + 'network',
params=data,
auth=(self.username, self.password),
verify=self.verify)
if self.debug:
print "inside network ref:"
print self.r.text
try:
return self.r.json()[0][u'_ref']
except Exception as e:
print self.r.text
sys.exit(1)
def next_available_ip(self, network, count=3):
"""Return next available IP in network
Look up the network reference, then get the count next
available IPs. Sequentially test each one via ping, and
return the first one that does not respond.
In verbose mode, it throws out a warning if one of the
available IPs responds to ping.
"""
netref = self.network_ref(network)
data = { '_function' : 'next_available_ip',
'num' : count }
self.r = requests.post(self.url + netref,
params=data,
auth=(self.username, self.password),
verify=self.verify)
if self.debug:
print "inside next_available:"
print self.r.text
for ipaddr in self.r.json()['ips']:
resp = os.system("ping -c 1 " + ipaddr + " >> /dev/null")
if resp == 0:
if self.debug:
print ipaddr, "is up!"
# Remove hardcode
if self.verbose:
print "\n"
print "========================================================\
"
print "Please open a case with the OCC. IP {0:s}".format(ipaddr)
print "is pingable, but is not listed in Infoblox Grid as a"
print "used IP address. (ignore for now)"
print "========================================================\
"
print "\n"
else:
if self.debug:
print ipaddr, "is down!"
return ipaddr
return False
def next_available_name(self, prefix, cnt_start, domain, digits=4, run=1024):
"""Find the next available name of form prefix + 0001 + domain
Starts at cnt_start and then checks sequentially up to
cnt_start + run, looking for available names.
Checks the Infoblox API for record:host entry, record:a
entry, and finally just a DNS lookup. The first name which
shows clear in all those is returned.
"""
for i in range(cnt_start, run):
if self.debug:
print "i: " + str(i)
fqdn = prefix + str(i).zfill(digits) + '.' + domain
if self.debug:
print fqdn
if self.rh_exists(fqdn):
continue
elif self.ra_exists(fqdn):
continue
elif True:
try:
socket.gethostbyname(fqdn)
continue
except:
return fqdn
else:
return fqdn
return False
def rh_add(self, network, ipaddr, fqdn):
"""Create record:host for network=network,
name=hostname and ipaddr=ipaddr"""
netr = self.network_ref(network)
data = {
'ipv4addrs' : [ { 'ipv4addr' : ipaddr }, ],
'name' : fqdn,
# removed hardcoded view and comment. Add date to comment. TODO
'view' : 'Infoblox Internal',
'comment' : 'Dynamically entered by ' + self.username + ' ' + datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')
}
headers = { 'content-type' : 'application/json' }
if self.debug:
print data
self.r = requests.post(self.url + 'record:host',
data=json.dumps(data),
auth=(self.username, self.password),
verify=self.verify)
if self.debug:
print "inside rh_add: " + fqdn
print self.r.text
try:
if self.r.json()['Error']:
print self.r.json()
raise Exception(self.r.json()['Error'])
# sys.exit(1)
except:
pass
return( { 'ipaddr' : ipaddr,
'name' : fqdn } )