Code critique xmlrpclib
flagg
ianand0204 at gmail.com
Mon Feb 2 21:25:37 EST 2009
This xmlrpc server is designed to parse dns zone files and then
perform various actions on said files. \
It uses dnspython, and xmlrpclib
I'd like to know what some of the more experienced python users
think. Where I could improve code, make it more efficient, whatever.
All suggestions are welcome. This is my first functional python
program, and I have tons of questions to go along with whatever
suggestions. How could I do sanity checking; right now nothing
checks the input to these functions, error-handling in this program is
almost non-existant how do you integrate decent error handling into a
piece of software......ill shut up now.
Thanks
import dns.zone
from time import localtime, strftime, time
import os, sys
from dns.rdataclass import *
from dns.rdatatype import *
from string import Template
import xmlrpclib
from SimpleXMLRPCServer import SimpleXMLRPCServer
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
zoneDir = "/dns"
def openZoneFile(zoneFile):
"""
Opens a zone file. Then reads in zone file to dnspython zone
object.
"""
global zone
global host
global domain
domain = ".".join(zoneFile.split('.')[1:])
host = ".".join(zoneFile.split('.')[:1])
try:
zone = dns.zone.from_file(zoneDir + domain + '.zone',
domain)
except dns.exception, e:
print e.__class__, e
class DNSFunctions:
# Not exposed to xml-rpc calls, used internally only.
def _writeToZoneFile(self, record):
"""
Checks if zone file exists, if it does it write values to zone
file
"""
for (name, ttl, rdata) in zone.iterate_rdatas(SOA):
new_serial = int(strftime('%Y%m%d00', localtime(time())))
if new_serial <= rdata.serial:
new_serial = rdata.serial + 1
rdata.serial = new_serial
if os.path.exists(zoneDir + str(zone.origin) + "zone"):
f = open(zoneDir + str(zone.origin) + "zone", "w")
zone.to_file(f)
f.close()
else:
print "Zone: " + zone.origin + " does not exist, please
add first"
def showRecord(self, record):
"""
Shows a record for a given zone. Prints out
TTL, IN, Record Type, IP
"""
openZoneFile(record)
try:
rdataset = zone.get_node(host)
for rdata in rdataset:
return str(rdata)
except:
raise Exception("Record not found")
def changeRecord(self, record, type, target):
"""
Changes a dns entry.
@param record: which record to chance
@param type: what type of record, A, MX, NS, CNAME
@target: if CNAME target points to HOSTNAME, if A record
points to IP
"""
openZoneFile(record)
try:
rdataset = zone.find_rdataset(host, rdtype=type)
except:
raise Exception("You must enter a valid record and type.
See --usage for examples")
for rdata in rdataset:
if rdata.rdtype == CNAME:
rdata.target = dns.name.Name((target,))
elif rdata.rdtype == A:
rdata.address = target
else:
assert False
self._writeToZoneFile(host)
def deleteRecord(self, record):
"""
Delete Entry from zone file
"""
openZoneFile(record)
zone.delete_node(host)
self._writeToZoneFile(record)
def addRecord(self, record, type, target):
"""
Adds a new record to zone file
"""
openZoneFile(record)
rdataset = zone.find_rdataset(host, rdtype=type, create=True)
if rdataset.rdtype == A:
rdata = dns.rdtypes.IN.A.A(IN, A, address = target)
rdataset.add(rdata, ttl=300)
elif rdataset.rdtype == CNAME:
rdata = dns.rdtypes.ANY.CNAME.CNAME(IN, CNAME,
dns.name.Name((target,)))
rdataset.add(rdata, ttl=300)
else:
assert False
self._writeToZoneFile(host)
def addZoneFile(self, file):
"""
Function to create a new empty zone file, if none exists. If
exists
function will terminate.
"""
newZoneSerial = strftime("%Y%m%d00", localtime())
zoneTemplate = Template('''$$TTL ${ttltime}
$$ORIGIN ${domain}.
@ 5M IN SOA nsrepo1.foobar.priv.
dnsadmin.foobar.priv. (
; did you update reverse?!
${serial} ; Serial CCYYMMDDxx where xx is
todays edit
1H
10M
1D
60M
)''')
if not os.path.exists(zoneDir + file + ".zone"):
f = open(zoneDir + file + ".zone", "w")
f.write(zoneTemplate.substitute({'ttltime':'300',
'domain': file, 'serial': newZoneSerial}))
f.close()
else:
print "Zone: " + file + " already exists"
class RequestHandler(SimpleXMLRPCRequestHandler):
# rpc_paths = ('/RPC2',),
pass
server = SimpleXMLRPCServer(("localhost", 8080), requestHandler =
RequestHandler, allow_none=True)
print "Listening on port 8080..."
server.register_introspection_functions()
server.register_instance(DNSFunctions())
server.register_multicall_functions()
server.serve_forever()
### Client Script ###
## I will probably use a mix of multicalls and singlecalls<?> for
client activity. Muticalls will primarily be used for showing a
record, applying a change, then showing the same record again to
verify changes went through.
import xmlrpclib
proxy = xmlrpclib.ServerProxy('http://localhost:8080')
multicall = xmlrpclib.MultiCall(proxy)
print proxy.showRecord('host11.lab0.foobar.priv')
print proxy.showRecord('host12.lab0.foobar.priv')
multicall.showRecord('host11.lab0.foobar.priv')
multicall.changeRecord('host11.lab0.foorbar.priv', 'A', '127.0.0.1')
multicall.showRecord('host11.lab0.foobar.priv')
print proxy.system.listMethods
result = multicall()
print result[1], result[2]
More information about the Python-list
mailing list