def get(self, view=None, domain=None, name=None): user = getattr(g, '_ibuser', None) auth_cookie = getattr(g, '_ibapauth', None) server = current_app.config.get('GRID_MASTER') link = url_for('by_ref', view=view, domain=domain, name=name) self.logger.debug("method=get,user=%s,link=%s/%s/%s" % (user, view, domain, name)) if auth_cookie == None: self.logger.debug("No Auth cookie") # User wasn't authenicated or another error happened return rest_error_response(401) record_host_query = { 'name': "%s.%s" % (name, domain), 'view': view, '_return_fields': "name,comment,view,ipv4addrs,extattrs" } ib = infoblox_session(master=server, ibapauth=auth_cookie) # TODO: At some point of time, this would be easier to do with # field marshaling but haven't figured it out just yet host = {} try: ret = ib.get("record:host", record_host_query) except infoblox.errors.BadCredentials: return rest_error_response(403) else: if len(ret) == 0: return rest_error_response(404) elif len(ret) == 1: record = ret[0] name = record.get('name').replace(".%s" % domain, "") host = { 'name': name, 'domain': domain, 'comment': record.get('comment'), 'view': record.get('view'), 'address': record.get('ipv4addrs')[0].get('ipv4addr'), 'link': url_for('by_ref', view=view, domain=domain, name=name) } else: self.logger.error("more than 1 record for %s" % link) return rest_error_response(400) return host, 200
def get(self, view=None, domain=None, name=None): user = getattr(g, '_ibuser', None) auth_cookie = getattr(g, '_ibapauth', None) server = current_app.config.get('GRID_MASTER') link = url_for('a_by_ref', view=view, domain=domain, name=name) self.logger.debug("method=get,user=%s,link=%s/%s/%s" % (user, view, domain, name)) if auth_cookie == None: self.logger.debug("No Auth cookie") # User wasn't authenicated or another error happened return rest_error_response(401) record_a_query = { 'name': "%s.%s" % (name, domain), 'view': view, '_return_fields': "name,comment,view,ipv4addr,extattrs" } ib = infoblox_session(master=server, ibapauth=auth_cookie) response = {} try: ret = ib.get("record:a", record_a_query) except infoblox.errors.BadCredentials: return rest_error_response(403) else: if len(ret) == 0: return rest_error_response(404, detail="DNS Record not found") response = { 'name': name, 'domain': domain, 'view': view, 'comment': ret[0].get('comment'), 'link': link } addresses = [] for record in ret: addresses.append(record.get('ipv4addr')) response['addresses'] = addresses return response, 200
def post(self): args = self.reqparse.parse_args() auth_cookie = getattr(g, '_ibapauth', None) user = getattr(g, '_ibuser', None) server = current_app.config.get('GRID_MASTER') domain = current_app.config.get('DEFAULT_DOMAIN') self.logger.debug( "method=post,user=%s,link=%s/%s/%s" % (user, args.get('view'), args.get('domain'), args.get('domain'))) if auth_cookie == None: # User wasn't authenicated or another error happened return rest_error_response(401) if args.get('domain') != None: domain = args.get('domain') fqdn = ("%s.%s" % (args.get('name'), domain)).lower() view = args.get('view') payload = { 'name': fqdn, 'view': view, 'comment': "host created by API", 'ipv4addrs': [{ 'ipv4addr': args.get('address') }], 'extattrs': { 'Owner': { 'value': "DNSAPI" }, 'change_number': { "value": args.get('change_control') }, } } ib = infoblox_session(master=server, ibapauth=auth_cookie) # Check to make sure that the hostname isn't in use # Or that the address isn't in use try: record_host = ib.get("record:host", {'name': fqdn, 'view': view}) record_addr = ib.get("record:host_ipv4addr", { 'ipv4addr': args.get('address'), 'network_view': "default" }) except infoblox.errors.BadCredentials: self.logger.error("BadCredentials") return rest_error_response(401) except Exception as e: return rest_error_response( 500, details="Something happened during checking existing: %s" % str(e)) else: if len(record_host) > 0: msg = "%s/%s - DNS Record in use" % (view, fqdn) self.logger.error(msg) return rest_error_response(400, detail=msg) if len(record_addr) > 0: msg = "%s - Address in use" % (args.get('address')) self.logger.error(msg) return rest_error_response(400, detail=msg) # Everything looks okay, add it in record = None try: # The reference will have quotes around them _ref = ib.add("record:host", payload).replace('"', '') ret = ib.get(_ref, { '_return_fields': "name,comment,ipv4addrs,disable,view,extattrs" }) except infoblox.errors.BadCredentials: self.logger.error("BadCredentials") return rest_error_response(403) except Exception as e: msg = "Unknown error: %s" % str(e) self.logger.error("%s, payload=%s" % (msg, str(payload))) return rest_error_response(500, detail=msg) else: if isinstance(ret, list): if len(ret) > 0: record = ret[0] else: # No records were found self.logger.error("%s/%s - Record created but not found" % (view, fqdn)) return rest_error_response( 400, detail="Unknown error, record creation is undefined") elif isinstance(ret, dict) and ret.get('_ref') != None: record = ret else: self.logger.error( "%s/%s - Invalid response from Infoblox: %s" % (view, fqdn, str(ret))) return rest_error_response(500) # We construct our successful response back to the client # Use the response back from infoblox but remove out the domain name = record.get('name').replace(".%s" % domain, "") host = { 'name': name, 'domain': domain, 'comment': record.get('comment'), 'address': record.get('ipv4addrs')[0].get('ipv4addr'), 'view': record.get('view'), "link": url_for('by_ref', view=view, domain=domain, name=name) } log_msg = "|".join([ view, domain, name, record['ipv4addrs'][0]['ipv4addr'], user, args.get('change_control') ]) self.logger.info("NEWHOST|%s" % log_msg) return host, 201
def delete(self, view=None, domain=None, name=None): args = self.delparse.parse_args() auth_cookie = getattr(g, '_ibapauth', None) user = getattr(g, '_ibuser', None) server = current_app.config.get('GRID_MASTER') self.logger.debug("method=delete,user=%s,link=%s/%s/%s" % (user, view, domain, name)) if auth_cookie == None: # User wasn't authenicated or another error happened return rest_error_response(401) ib = infoblox_session(master=server, ibapauth=auth_cookie) payload = { 'name': "%s.%s" % (name, domain), 'view': view, '_return_fields': 'name,ipv4addrs,extattrs' } record = None try: ret = ib.get("record:host", payload) except infoblox.errors.BadCredentials: return rest_error_response(403) except Exception as e: self.logger.error("Error logging for record %s/%s/%s: %s" % (view, domain, name, str(e))) return rest_error_response(500, detail="Unknown Error: %s" % str(e)) else: if isinstance(ret, list): if len(ret) > 0: record = ret[0] else: # No record was found msg = "%s/%s/%s Not found" self.logger.error(msg) return rest_error_response(404, detail=msg) elif isinstance(ret, dict): if ret.get('_ref') == None: # No record was found msg = "%s/%s/%s Not found" self.logger.error(msg) return rest_error_response(404, detail=msg) else: record = ret else: msg = "%s/%s/%s Unknown return type: %s" % (view, domain, name, type(ret)) self.logger.error(msg) return rest_error_response(500, detail=msg) # Check to see if we are permitted to delete this if record.get('extattrs') != None and record['extattrs'].get( 'Owner' ) != None and record['extattrs']['Owner']['value'] == "DNSAPI": pass else: msg = "%s/%s/%s - record not tagged for permission" % ( view, domain, name) self.logger.error(msg) return rest_error_response(403, detail=msg) try: ib.delete(record.get('_ref')) except Exception as e: msg = "%s/%s/%s - Error deleting record: %s" % (view, domain, name, str(e)) self.logger.error(msg) return rest_error_response(500, detail=msg) link = url_for('by_ref', view=view, domain=domain, name=name) host = { 'name': name, 'domain': domain, 'view': view, 'comment': record.get('comment'), 'address': record.get('ipv4addrs')[0]['ipv4addr'], 'link': link } log_msg = "|".join([view, domain, name, user, args['change_control']]) self.logger.info("DELETEHOST|%s" % log_msg) return host, 200
def put(self, view=None, domain=None, name=None): args = self.reqparse.parse_args() auth_cookie = getattr(g, '_ibapauth', None) user = getattr(g, '_ibuser', None) server = current_app.config.get('GRID_MASTER') self.logger.debug("method=put,user=%s,link=%s/%s/%s" % (user, view, domain, name)) if auth_cookie == None: # User wasn't authenicated or another error happened return rest_error_response(401) # Verify the view in the path and the view in the passed data # match new_view = view if args.get('view') != view: self.logger.error("Views don't match: (%s / %s)" % (view, args.get('view'))) return rest_error_response(400, detail="Mismatching views") # The "new" object can't already exist, so we need to determine # if this is a re-name (new name can't exist) or a re-address # (the new address can't be allocated) new_domain = domain.lower() # Domain from the URL path new_name = name.lower() # hostname from the URL path if args.get('domain') != None: # They passed the domain in the data new_domain = args.get('domain').lower() if args.get('name') != None: new_name = args.get('name').lower() src_fqdn = ("%s.%s" % (name, domain)).lower() new_fqdn = ("%s.%s" % (new_name, new_domain)).lower() new_link = url_for('by_ref', view=view, domain=new_domain, name=new_name) if src_fqdn == new_fqdn: # The old name and the new name match so it's a re-address oper. self.logger.debug("re-address %s => %s" % (new_link, args.get('address'))) dest_query_type = "record:host_ipv4addr" dest_query = { 'ipv4addr': args.get('address'), 'network_view': "default" } else: # The names mis-match so we're just going to assume it's a re-name self.logger.debug("re-name %s/%s => %s" % (view, src_fqdn, new_fqdn)) dest_query_type = "record:host" dest_query = {'name': new_fqdn, 'view': view} ib = infoblox_session(master=server, ibapauth=auth_cookie) src_query = { 'name': src_fqdn, 'view': view, '_return_fields': "name,ipv4addrs,extattrs" } record = None try: src_resp = ib.get("record:host", src_query) dst_resp = ib.get(dest_query_type, dest_query) except infoblox.errors.BadCredentials: return rest_error_response(403) except Exception as e: self.logger.error( "Unknown error looking for existing records: %s" % str(e)) return rest_error_response(500, detail="Unknown error: %s" % str(e)) else: # If we get an empty response for src_query throw a NOTFOUND error if isinstance(src_resp, list): if len(src_resp) > 0: record = src_resp[0] else: # No records were found self.logger.error("Modify can't find src object: %s/%s" % (view, src_fqdn)) return rest_error_response(404, detail="%s/%s%s not found" % (view, domain, name)) elif isinstance(src_resp, dict) and src_resp.get('_ref') != None: record = src_resp else: return rest_error_response(400, detail="Unknown return type") # We want an emtpy response for dest_query if isinstance(dst_resp, list): if len(dst_resp) > 0: msg = "Destination in use" self.logger.error(msg) return rest_error_response(400, detail=msg) elif isinstance(dest_rep, dict): # we got back just a diction, check if there's a _ref # attribute in the response, that'll tell us if it's empty # or not if dst_resp.get('_ref') != None: msg = "Destination in use" self.logger.error(msg) return rest_error_response(400, detail=msg) # Destination is clear # Check to see if we are permitted to touch the src if record.get('extattrs') != None and record['extattrs'].get( 'Owner' ) != None and record['extattrs']['Owner']['value'] == "DNSAPI": # We are good! pass else: msg = "Object not tagged for modification" self.logger.error(msg) return rest_error_response(403, detail=msg) payload = { 'name': new_fqdn, 'view': view, 'comment': "host updated by API", 'extattrs': { 'Owner': { 'value': "DNSAPI" }, 'change_number': { 'value': args.get('change_control') } } } if args.get('address') != None: payload['ipv4addrs'] = [{'ipv4addr': args.get('address')}] try: ib.update(record.get('_ref'), payload) except Exception as e: msg = "Error updating record %s: %s" % (new_fqdn, str(e)) self.logger.error(msg) return rest_error_response(400, detail=msg) host = { 'name': new_name, 'domain': new_domain, 'view': view, 'change_control': args.get('change_control'), 'address': args.get('address'), 'link': new_link } log_msg = "|".join([ view, domain, name, record['ipv4addrs'][0]['ipv4addr'], view, new_domain, new_name, "%s" % payload.get('ipv4addrs'), user, args['change_control'] ]) self.logger.info("UPDATEHOST|%s" % log_msg) return host, 200
def post(self): args = self.reqparse.parse_args() auth_cookie = getattr(g, '_ibapauth', None) user = getattr(g, '_ibuser', None) server = current_app.config.get('GRID_MASTER') domain = current_app.config.get('DEFAULT_DOMAIN') self.logger.debug( "method=post,user=%s,link=%s/%s/%s" % (user, args.get('view'), args.get('domain'), args.get('name'))) if auth_cookie == None: # User wasn't authenicated or another error happened return rest_error_response(401) if args.get('domain') != None: domain = args.get('domain') link = url_for('a_by_ref', view=args.get('view'), domain=domain, name=args.get('name')) fqdn = ("%s.%s" % (args.get('name'), domain)).lower() view = args.get('view') template = { 'name': fqdn, 'view': view, 'comment': "DNS A record created by API", 'extattrs': { 'Owner': { 'value': "DNSAPI" }, 'change_number': { "value": args.get('change_control') }, } } ib = infoblox_session(master=server, ibapauth=auth_cookie) # Check to make sure there's no existing records # We're not going to check the IP address just the hostname # we could be adding the records to give an address another name and # can't use aliases try: exist_record = ib.get("record:a", {"name": fqdn, 'view': view}) except infoblox.errors.BadCredentials: self.logger.error("BadCredentials") return rest_error_response(401) except Exception as e: return rest_error_response( 500, detail="Something happened during checking existing: %s" % str(e)) else: if len(exist_record) > 0: msg = "%s/%s - DNS Record in use" % (view, fqdn) self.logger.error(msg) return rest_error_response(400, detail=msg) # look through all the addresses, we need to add them separately ref_list = [] for addr in args.get('addresses'): payload = template.copy() payload['ipv4addr'] = addr try: _ref = ib.add("record:a", payload) ref_list.append(_ref) self.logger.debug("added: %s" % _ref) except infoblox.errors.BadCredentials: self.logger.error("BadCredentials") return rest_error_response(401) except Exception as e: return rest_error_response( 500, detail="Something happened during adding new: %s" % str(e)) # We construct our successful response back to the client # Use the response back from infoblox but remove out the domain # TODO: re-query the record to make sure it got in okay and build the response from that #name = record.get('name').replace(".%s" % domain, "") name = fqdn.replace(".%s" % domain, "") response = { 'name': name, 'domain': domain, 'comment': "DNS A record created by API", 'addresses': args.get('addresses'), 'view': view, "link": url_for('a_by_ref', view=view, domain=domain, name=name) } log_msg = "|".join([ view, domain, name, str(args.get('addresses')), user, args.get('change_control') ]) self.logger.info("NEWA|%s" % log_msg) return response, 201
def delete(self, view=None, domain=None, name=None): args = self.delparse.parse_args() auth_cookie = getattr(g, '_ibapauth', None) user = getattr(g, '_ibuser', None) server = current_app.config.get('GRID_MASTER') link = url_for('a_by_ref', view=view, domain=domain, name=name) self.logger.debug("method=delete,user=%s,link=%s/%s/%s" % (user, view, domain, name)) if auth_cookie == None: # User wasn't authenicated or another error happened return rest_error_response(401) record_a_query = { 'name': "%s.%s" % (name, domain), 'view': view, '_return_fields': "name,comment,view,ipv4addr,extattrs" } ib = infoblox_session(master=server, ibapauth=auth_cookie) # Retrieve all the existing Infoblox objects # While we're at it, we'll construct our response response = {'name': name, 'domain': domain, 'view': view, 'link': link} ref_to_delete = [] ref_to_nottouch = [] try: ret = ib.get("record:a", record_a_query) except infoblox.errors.BadCredentials: return rest_error_response(403) else: if len(ret) == 0: return rest_error_response(404, detail="DNS Record not found") addresses = [] response['comment'] = ret[0].get('comment') for record in ret: # Since there's multiple records for A records # Validate each one seperately if record.get('extattrs') != None and record['extattrs'].get( 'Owner' ) != None and record['extattrs']['Owner']['value'] == "DNSAPI": addresses.append(record.get('ipv4addr')) ref_to_delete.append( [record.get('_ref'), record.get('ipv4addr')]) else: ref_to_nottouch.append( [record.get('_ref'), record.get('ipv4addr')]) response['addresses'] = addresses if len(ref_to_delete) < 1: msg = "%s/%s/%s - record not tagged for permission" % ( view, domain, name) self.logger.error(msg) return rest_error_response(403, detail=msg) # Log for troubleshooting purposes if one of the records is not updatable if len(ref_to_nottouch) > 0: msg = "Error: The following records were marked as not updatble by the API: %s" % ( str(ref_to_nottouch)) self.logger.error(msg) # Delete the records for ref in ref_to_delete: try: ib.delete(ref[0]) except Exception as e: msg = "%s/%s/%s (%s) - Error deleting record: %s" % ( view, domain, name, ref[1], str(e)) self.logger.error(msg) return rest_error_response(500, detail=msg) return response, 200
def put(self, view=None, domain=None, name=None): args = self.reqparse.parse_args() auth_cookie = getattr(g, '_ibapauth', None) user = getattr(g, '_ibuser', None) server = current_app.config.get('GRID_MASTER') self.logger.debug("method=put,user=%s,link=%s/%s/%s" % (user, view, domain, name)) if auth_cookie == None: # User wasn't authenicated or another error happened return rest_error_response(401) # Verify the view in the path and the view in the passed data # match new_view = view if args.get('view') != view: self.logger.error("Views don't match: (%s / %s)" % (view, args.get('view'))) return rest_error_response(400, detail="Mismatching views") ib = infoblox_session(master=server, ibapauth=auth_cookie) # Check to see if this is a rename operation src_name = ("%s.%s" % (name, domain)).lower() dst_name = ("%s.%s" % (args.get('name'), args.get('domain'))).lower() if src_name != dst_name: # Re-name operation, We need to check to make sure there's nothing at the dest name try: dst_check = ib.get("record:a", { 'view': view, 'name': dst_name }) except Exception as e: msg = "Error checking to see if new name exists:%s:%s" % ( dst_name, str(e)) self.logger.error(msg) return rest_error_response(400, detail=msg) else: if len(dst_check) > 0: msg = "New Name already exists: %s" % dst_name self.logger.error(msg) return rest_error_response(400, detail=msg) # The Modify is going to be a delete and add operation, so delete out the old # and add in the new # Fetch existing try: existing_records = ib.get("record:a", { 'view': view, 'name': src_name }) except Exception as e: msg = "Error looking up existing name:%s:%s" % (src_name, str(e)) self.logger.error(msg) return rest_error_response(400, msg) else: if len(existing_records) == 0: msg = "Error new name exists:%s:%s" % (src_name, str(e)) self.logger.error(msg) return rest_error_response(400, msg) # Delete existing try: for record in existing_records: ib.delete(record.get('_ref')) self.logger.debug("deleting:%s:%s" % (src_name, record.get('_ref'))) except Exception as e: msg = "Error deleting record:%s:%s" % (src_name, str(e)) self.logger.error(msg) return rest_error_response(400, msg) # Create New Records template = { 'name': dst_name, 'view': view, 'comment': "DNS A record Updated by API", 'extattrs': { 'Owner': { 'value': "DNSAPI" }, 'change_number': { "value": args.get('change_control') }, } } try: for address in args.get('addresses'): payload = template.copy() payload['ipv4addr'] = address _ref = ib.add("record:a", payload) self.logger.debug("added:%s:%s:%s" % (dst_name, address, _ref.replace('"', ""))) except Exception as e: msg = "Error adding record:%s:%s" % (dst_name, str(e)) self.logger.error(msg) return rest_error_response(400, msg) response = { 'name': args.get('name'), 'domain': args.get('domain'), 'comment': "DNS A record Updated by API", 'addresses': args.get('addresses'), 'view': view, "link": url_for('a_by_ref', view=view, domain=args.get('domain'), name=args.get('name')) } return response, 200