def main(): parser = argparse.ArgumentParser() parser.add_argument('-c', '--creds', help='path to file containing credentials') parser.add_argument('-m', '--mac', help='MAC address') parser.add_argument('-n', '--name', help='Device name') parser.add_argument('-p', '--properties', help='Properties') parser.add_argument( '-l', '--loglevel', choices=['critical', 'error', 'warning', 'info', 'debug'], default='critical', help='enable logging') args = parser.parse_args() # Handle loading of credentials creds = pybluecat.get_creds(args.creds) hostname = creds['hostname'] username = creds['username'] password = creds['password'] # Enable logging if requested # if args.loglevel: # level = getattr(logging, args.loglevel.upper()) # logging.basicConfig(level=level) # Instantiate Bluecat REST Client bam = pybluecat.BAM(hostname, username, password, loglevel=args.loglevel) r = bam.create_mac_address(args.mac, args.name, args.properties) print(json.dumps(r, indent=2))
def main(): parser = argparse.ArgumentParser() parser.add_argument('hostname', help='hostname') parser.add_argument('-c', '--creds', help='path to file containing credentials') group_ME = parser.add_mutually_exclusive_group(required=True) group_ME.add_argument('-n', '--network', nargs=2, help='network address within desired subnet') group_ME.add_argument('-e', '--environment', help='environment from which to choose a network') parser.add_argument('-l', '--loglevel', choices=['warning', 'info', 'debug'], help='enable debugging') args = parser.parse_args() NETWORK_ENVS = { 'lab': [u'10.168.131.0/24', u'10.168.161.0/24'], 'dmz-vip': [u'167.73.15.0/24', u'167.73.31.0/24'] } if args.loglevel: level = getattr(logging, args.loglevel.upper()) logging.basicConfig(level=level) hostname = args.hostname.lower() creds = pybluecat.get_creds(args.creds) bam = pybluecat.BAM(creds['hostname'], creds['username'], creds['password']) # Get Networks List if args.network: net1 = args.network[0] net2 = args.network[1] elif args.environment: net1, net2 = NETWORK_ENVS[args.environment] # Reserve the pairs addresses = bam.assign_ip_address_pair(net1, net2, args.hostname) print(json.dumps(addresses, indent=2))
def main(): parser = argparse.ArgumentParser() parser.add_argument('hostname', help='hostname') parser.add_argument('mac_addr', help='MAC Address') parser.add_argument( 'ip_addr', help= 'IP desired for reservation, also defines the network if "first_available" flag is set' ) parser.add_argument('-c', '--creds', help='path to file containing credentials') parser.add_argument( '-l', '--loglevel', choices=['critical', 'error', 'warning', 'info', 'debug'], default='critical', help='enable logging') parser.add_argument('--location', default='', help='Location of Device') parser.add_argument('--notes', default='', help='Additional notes about the reservation') parser.add_argument('--owner', default='', help='Owner of the device') parser.add_argument('--request_num', default='', help='ServiceDesk Request Number') parser.add_argument('--no_wait', action='store_true', help='do NOT wait for deployment') parser.add_argument('--no_deploy', action='store_true', help='Do NOT deploy saved changes') args = parser.parse_args() # Setup console logging logger = logging.getLogger(__name__) loglevel = getattr(logging, args.loglevel.upper()) logger.setLevel(level=loglevel) console_handler = logging.StreamHandler() logger.addHandler(console_handler) logger.propagate = False # Setup args and vars hostname = args.hostname mac = args.mac_addr.replace('.', '').replace(':', '').replace('-', '') ip = ip_address(unicode(args.ip_addr)) action = 'MAKE_DHCP_RESERVED' creds = pybluecat.get_creds(args.creds) properties = { 'Location': args.location, 'Notes': args.notes, 'Owner': args.owner, 'RequestNum': args.request_num } output_object = {} # Initialize flow-control boolean vars deploy_needed = False ip_is_eligible = False mac_already_reserved = False desired_ip_reserved = False error_message = '' # Create instance using 'with' so cleanup of session is automatic with pybluecat.BAM(**creds) as bam: # Determine the Network of the IP Address try: logger.info('Getting Network info from ip: {}'.format(str(ip))) net_entity = bam.get_network(str(ip)) net_obj = pybluecat.entity_to_json(net_entity) network = ip_network(unicode(net_obj['properties']['CIDR'])) if network.prefixlen <= 24: dhcp_offset_ip = str(network.network_address + 31) else: dhcp_offset_ip = None logger.debug(json.dumps(net_obj, indent=2)) except pybluecat.exceptions.BluecatError as e: logger.error( 'Could not determine the target network or network did not exist' ) exit(str(e)) # Determine if IP eligible to be reserved, not Broadcast, Network, Gateway, etc... if ip == network.network_address: error_message = 'Cannot Update the Network Address: {}'.format( str(ip)) logger.info(error_message) elif ip == network.broadcast_address: error_message = 'Cannot Update the Broadcast Address: {}'.format( str(ip)) logger.info(error_message) elif ip == network.network_address + 1: error_message = 'Cannot Update the Gateway Address: {}'.format( str(ip)) logger.info(error_message) elif ip in [network.network_address + 2, network.network_address + 3]: error_message = 'Cannot Update a HSRP/VRRP Address: {}'.format( str(ip)) logger.info(error_message) elif network.prefixlen <= 24 and ip in [ network.network_address + i for i in xrange(4, 31) ]: error_message = 'Cannot Update Address in Telecom-Reserved Space: {}'.format( str(ip)) logger.info(error_message) else: ip_is_eligible = True # Assuming the IP is eligible, attempt the update if ip_is_eligible: try: logger.info('Getting current config for IP: {}'.format( str(ip))) ip_entity = bam.get_ip_address(str(ip)) old_reservation = pybluecat.entity_to_json(ip_entity) logger.debug( json.dumps(old_reservation, indent=2, sort_keys=True)) if old_reservation['properties'] is None: output_object = { 'state': 'No Update Performed', 'message': 'Target IP is not a DHCP_RESERVATION', 'existing_reservation': old_reservation } elif old_reservation['properties']['state'] != 'DHCP_RESERVED': output_object = { 'state': 'No Update Performed', 'message': 'Target IP is not a DHCP_RESERVATION', 'existing_reservation': old_reservation } else: response = bam.update_dhcp_reservation( old_reservation, hostname, mac, properties) new_reservation = bam.get_ip_address(str(ip)) new_reservation = pybluecat.entity_to_json(new_reservation) logger.debug( json.dumps(old_reservation, indent=2, sort_keys=True)) output_object = { 'status': 'Reservation Updated Successfully', 'message': 'Target IP was updated', 'old_reservation': old_reservation, 'new_reservation': new_reservation } deploy_needed = True except pybluecat.exceptions.BluecatError as e: output_object = { 'status': 'Error Occurred during Update', 'message': e.message } else: output_object = { 'status': 'No Update Performed', 'message': error_message } # Deploy DHCP changes if no_deploy flag isn't set if deploy_needed and not args.no_deploy: logger.info('Deploying Config changes') server_set = bam.queue_servers(net_obj['id']) for server in server_set: logger.info('Deploying changes to server: {}'.format( str(server))) bam.deploy_server_services(server, 'DHCP') # Monitor the deployment through completion unless no_wait flag is set if not args.no_wait: logger.info('Waiting for deployment to finish') bam.monitor_server_deployment(server_set) logger.info('Deployment finished') else: logger.info('Monitoring of deployment is being skipped') # Finally output the IP info #print_ip_info(ip_obj) print(json.dumps(output_object, indent=2, sort_keys=True))
def main(): parser = argparse.ArgumentParser() parser.add_argument('hostname', help='hostname') parser.add_argument('mac_addr', help='MAC Address') parser.add_argument( 'ip_addr', help= 'IP desired for reservation, also defines the network if "first_available" flag is set' ) parser.add_argument('-c', '--creds', help='path to file containing credentials') parser.add_argument( '-l', '--loglevel', choices=['critical', 'error', 'warning', 'info', 'debug'], default='critical', help='enable logging') parser.add_argument('--location', default='', help='Location of Device') parser.add_argument('--notes', default='', help='Additional notes about the reservation') parser.add_argument('--owner', default='', help='Owner of the device') parser.add_argument('--request_num', default='', help='ServiceDesk Request Number') parser.add_argument('--first_available', action='store_true', help='Use first available IP as fallback option') parser.add_argument('--no_wait', action='store_true', help='do NOT wait for deployment') parser.add_argument('--no_deploy', action='store_true', help='Do NOT deploy saved changes') args = parser.parse_args() # Setup console logging logger = logging.getLogger(__name__) loglevel = getattr(logging, args.loglevel.upper()) logger.setLevel(level=loglevel) console_handler = logging.StreamHandler() logger.addHandler(console_handler) logger.propagate = False # Setup args and vars hostname = args.hostname mac = args.mac_addr.replace('.', '').replace(':', '').replace('-', '') ip = ip_address(unicode(args.ip_addr)) action = 'MAKE_DHCP_RESERVED' creds = pybluecat.get_creds(args.creds) properties = { 'Location': args.location, 'Notes': args.notes, 'Owner': args.owner, 'RequestNum': args.request_num } output_object = {} # Initialize flow-control boolean vars deploy_needed = False ip_is_eligible = False mac_already_reserved = False desired_ip_reserved = False error_message = '' # Create instance using 'with' so cleanup of session is automatic with pybluecat.BAM(**creds) as bam: # Determine the Network of the IP Address try: logger.info('Getting Network info from ip: {}'.format(str(ip))) net_entity = bam.get_network(str(ip)) net_obj = pybluecat.entity_to_json(net_entity) network = ip_network(unicode(net_obj['properties']['CIDR'])) if network.prefixlen <= 24: dhcp_offset_ip = str(network.network_address + 31) else: dhcp_offset_ip = None logger.debug(json.dumps(net_obj, indent=2)) except pybluecat.exceptions.BluecatError as e: logger.error( 'Could not determine the target network or network did not exist' ) exit(str(e)) # Determine if IP eligible to be reserved, not Broadcast, Network, Gateway, etc... if ip == network.network_address: error_message = 'Cannot reserve the Network Address: {}'.format( str(ip)) logger.info(error_message) elif ip == network.broadcast_address: error_message = 'Cannot reserve the Broadcast Address: {}'.format( str(ip)) logger.info(error_message) elif ip == network.network_address + 1: error_message = 'Cannot reserve the Gateway Address: {}'.format( str(ip)) logger.info(error_message) elif ip in [network.network_address + 2, network.network_address + 3]: error_message = 'Cannot reserve a GSLB/VRRP Address: {}'.format( str(ip)) logger.info(error_message) elif network.prefixlen <= 24 and ip in [ network.network_address + i for i in xrange(4, 31) ]: error_message = 'Cannot reserve Address in Telecom-Reserved Space: {}'.format( str(ip)) logger.info(error_message) else: ip_is_eligible = True # Determine if MAC is already associated with a reservation in target network logger.info( 'Searching for existing reservations for MAC: {}'.format(mac)) try: linked_entities = search_mac(bam, mac) for entity in linked_entities: if entity['type'] == 'IP4Address': ip_obj = pybluecat.entity_to_json(entity) logger.debug(json.dumps(ip_obj, indent=2, sort_keys=True)) ip_obj_address = ip_address( unicode(ip_obj['properties']['address'])) # Break loop as soon as match is found, return the matched reservation if ip_obj_address in network and ip_obj['properties'][ 'state'] == 'DHCP_RESERVED': logger.info( 'Found existing reservation in target network') mac_already_reserved = True output_object = { 'status': 'Found existing reservation', 'message': 'MAC Address has existing reservation in current network.', 'reservation': ip_obj } break # If MAC not found handle the error, otherwise exit script with error code 1 except pybluecat.exceptions.BluecatError as e: if 'Object was not found' in e.message: logger.info('MAC address does not currently exist in Bluecat') else: logger.error('Failed searching for MAC') exit(str(e)) # If we didn't find an existing reservation, try to get a new one if not mac_already_reserved: logger.info( 'MAC address has no current reservations in target network') # Try to create the Reservation using the literal IP given as arg if ip_is_eligible: logger.info( 'Sending reservation request to Bluecat for IP: {}'.format( str(ip))) try: ip_id = bam.assign_ip_address(hostname, str(ip), mac, action, properties) ip_entity = bam.get_entity_by_id(ip_id) ip_obj = pybluecat.entity_to_json(ip_entity) desired_ip_reserved = True deploy_needed = True output_object = { 'status': 'New Reservation Create', 'message': 'Desired IP Address was Available and Assigned', 'reservation': ip_obj } # Handle Bluecat errors, shouldn't see anything other than Dupes at this point except pybluecat.exceptions.BluecatError as e: if 'Duplicate' in e.message: error_message = 'Desired IP is already in Use' logger.info(error_message) ip_entity = bam.get_ip_address(str(ip)) conflicting_ip = pybluecat.entity_to_json(ip_entity) elif 'already used by another IP within the same network' in e.message: # Should've been caught earlier error_message = e.message logger.error(error_message) else: # Probably a system failure :( logger.error(e.message) # If we were not able to reserve the desired IP for whatever reason... if not desired_ip_reserved: # Get next available IP if flag is set if args.first_available: try: logger.info( 'Sending request to Bluecat to assign next available address in network: {}' .format(str(network))) ip_entity = bam.assign_next_ip_address( net_obj['id'], hostname, mac, action, properties, dhcp_offset_ip) ip_obj = pybluecat.entity_to_json(ip_entity) logger.debug( json.dumps(ip_obj, indent=2, sort_keys=True)) output_object = { 'status': 'New Reservation Created', 'message': [ error_message, 'First Available IP Address was assigned' ], 'reservation': ip_obj } deploy_needed = True # Expected errors here would be network out of addresses except pybluecat.exceptions.BluecatError as e: output_object = { 'status': 'Reservation could not be completed', 'message': [error_message, e.message] } logger.error( 'Unable to assign next available IP address') # Should hit this only when target IP in ineligible and __first_available is not set else: output_object = { 'status': 'Reservation could not be completed', 'message': [ error_message, 'Try using the --first_available flag or choose a different IP Address' ], 'conflicting_ip': conflicting_ip } # Deploy DHCP changes if no_deploy flag isn't set if deploy_needed and not args.no_deploy: logger.info('Deploying Config changes') server_set = bam.queue_servers(net_obj['id']) for server in server_set: logger.info('Deploying changes to server: {}'.format( str(server))) bam.deploy_server_services(server, 'DHCP') # Monitor the deployment through completion unless no_wait flag is set if not args.no_wait: logger.info('Waiting for deployment to finish') bam.monitor_server_deployment(server_set) logger.info('Deployment finished') else: logger.info('Monitoring of deployment is being skipped') # Finally output the IP info #print_ip_info(ip_obj) print(json.dumps(output_object, indent=2, sort_keys=True))
def main(): parser = argparse.ArgumentParser() parser.add_argument('-c', '--creds', help='path to file containing credentials') parser.add_argument('-i', '--ip', help='IP address') parser.add_argument('-m', '--mac', help='MAC address') parser.add_argument('-n', '--name', help='Device name') parser.add_argument( '-l', '--loglevel', default='critical', help='enable logging', choices=['critical', 'error', 'warning', 'info', 'debug']) match_group = parser.add_mutually_exclusive_group() match_group.add_argument('--match_all', action='store_true') match_group.add_argument('--match_any', action='store_true') args = parser.parse_args() # Setup console logging logger = logging.getLogger(__name__) loglevel = getattr(logging, args.loglevel.upper()) logger.setLevel(level=loglevel) console_handler = logging.StreamHandler() logger.addHandler(console_handler) logger.propagate = False # Handle loading of credentials creds = pybluecat.get_creds(args.creds) hostname = creds['hostname'] username = creds['username'] password = creds['password'] # Instantiate Bluecat REST Client bam = pybluecat.BAM(hostname, username, password) # , loglevel=args.loglevel) # Normalizing Arguments due to Rundeck requirements if args.ip == '': ip = None else: ip = args.ip if args.mac == '': mac = None else: mac = args.mac if args.name == '': name = None else: name = args.name # Use provided fields to search Bluecat Objects results = [] if ip is not None: results += search_ip(bam, ip) if mac is not None: results += search_mac(bam, mac) if name is not None: results += search_name(bam, name) # Eliminate Dupes and conflicting filters matches = [] for result in results: ip_obj = bam.entity_to_json(result) # Skip NULL objects if ip_obj['properties'] is None: continue # Skip Duplicates if ip_obj in matches: continue # Gather details about the ip_object res_name = ip_obj['name'] res_ip = ip_obj['properties']['address'] if 'macAddress' in ip_obj['properties']: res_mac = ip_obj['properties']['macAddress'] else: res_mac = '' logger.info('NAME: {}, IP: {}, MAC: {}'.format(res_name, res_ip, res_mac)) # If IP Object state is not "DHCP_RESERVED" DO NOT DELETE if ip_obj['properties']['state'] != 'DHCP_RESERVED': logger.info( 'IP Object is NOT a DHCP Reservation, ignoring objects with state: {}' .format(ip_obj['properties']['state'])) continue # If --match_all is set, ensure ALL set fields match the reservation if args.match_all: # If --hostname is set and doesn't match, skip to next reservation if name is not None and res_name.lower() != name.lower(): logger.info( 'Reservation doesn\'t match --hostname filter with --match_all set, ignoring' ) continue # If --ip_addr is set and doesn't match, skip to next reservation if ip is not None and res_ip != str(ip): logger.info( 'Reservation doesn\'t match --ip_addr filter with --match_all set, ignoring' ) continue # If --mac_addr is set and doesn't match, skip to next reservation if mac is not None and format_mac(res_mac) != mac: logger.info( 'Reservation doesn\'t match --mac_addr filter with --match_all set, ignoring' ) continue matches.append(ip_obj) # Output the remaining matched ip objects print(json.dumps(matches, indent=2, sort_keys=True))
def main(): parser = argparse.ArgumentParser() field_group = parser.add_argument_group( 'Matchable Fields', 'Provide at least one of the following fields to delete a reservation') parser.add_argument('--hostname', help='hostname of reservation(s) to delete') parser.add_argument('--mac_addr', help='MAC Address of reservation(s) to delete') parser.add_argument('--ip_addr', help='IP Address of reservation to delete') match_group = parser.add_mutually_exclusive_group(required=True) match_group.add_argument( '--match_all', action='store_true', help='Delete only objects that match ALL conditions') match_group.add_argument( '--match_any', action='store_true', help='Delete any object that matches ANY condition') parser.add_argument('-c', '--creds', help='path to file containing credentials') parser.add_argument( '-l', '--loglevel', choices=['critical', 'error', 'warning', 'info', 'debug'], default='critical', help='enable logging') parser.add_argument('--no_wait', action='store_true', help='do NOT wait for deployment') parser.add_argument('--no_deploy', action='store_true', help='Do NOT deploy saved changes') args = parser.parse_args() # Setup console logging logger = logging.getLogger(__name__) loglevel = getattr(logging, args.loglevel.upper()) logger.setLevel(level=loglevel) console_handler = logging.StreamHandler() logger.addHandler(console_handler) logger.propagate = False # Setup args and vars # None values are passed along to be ignored later # Rundeck passes in empty strings instead, so translate those to None if args.hostname is not None: if args.hostname.strip() == '': hostname = None else: hostname = args.hostname else: hostname = None if args.mac_addr is not None: if args.mac_addr.strip() == '': mac = None else: mac = format_mac(args.mac_addr) else: mac = None if args.ip_addr is not None: if args.ip_addr.strip() == '': ip = None else: ip = ip_address(unicode(args.ip_addr)) else: ip = None creds = pybluecat.get_creds(args.creds) output_object = {'status': '', 'message': [], 'deleted_reservations': []} # Exit Immediately if no fields were provided if all(field is None for field in [hostname, mac, ip]): output_object['status'] = 'No Reservations were Deleted' output_object['message'].append('No Fields were populated') output_object['message'].append( 'Please provided at least a Hostname, MAC_Address, or IP_Address') print(json.dumps(output_object, indent=2, sort_keys=True)) exit() # Initialize flow-control boolean vars deploy_needed = False ip_is_eligible = False error_message = '' ips_seen_so_far = [] candidate_reservations = [] reservations_to_delete = [] deleted_reservations = [] # Create instance using 'with' so cleanup of session is automatic with pybluecat.BAM(**creds) as bam: # Get reservation matching the hostname, if given if hostname is not None: logger.info( 'Hostname provided ({}), searching for reservations'.format( hostname)) results = bam.search_ip_by_name(hostname) logger.debug(json.dumps(results, indent=2, sort_keys=True)) candidate_reservations += results # Get reservations matching the IP Address, if given if ip is not None: logger.info( 'IP Address provided ({}), searching for reservations'.format( str(ip))) result = bam.get_ip_address(str(ip)) logger.debug(json.dumps(result, indent=2, sort_keys=True)) candidate_reservations.append(result) # Get reservations matching the MAC Address, if given if mac is not None: logger.info( 'MAC Address provided ({}), searching for reservations'.format( args.mac_addr)) results = search_mac(bam, mac) logger.debug(json.dumps(results, indent=2, sort_keys=True)) candidate_reservations += results # Determine which of the matched reservations qualify for deletion logger.info( 'Checking all gathered reservations for deletion eligibility') for reservation in candidate_reservations: reservation = pybluecat.entity_to_json(reservation) # Skip NULL objects, can happen when MAC searches turn up nothing if reservation['properties'] is None: logger.info('Ignoring NULL object') continue # Gather details about the ip_object res_name = reservation['name'] res_ip = reservation['properties']['address'] if 'macAddress' in reservation['properties']: res_mac = reservation['properties']['macAddress'] else: res_mac = '' logger.info('NAME: {}, IP: {}, MAC: {}'.format( res_name, res_ip, res_mac)) # If IP Object state is not "DHCP_RESERVED" DO NOT DELETE if reservation['properties']['state'] != 'DHCP_RESERVED': logger.info( 'Reservation ineligible for deletion, ignoring objects with state: {}' .format(reservation['properties']['state'])) continue # Ignore duplicate objects from the multiple searches if res_ip in ips_seen_so_far: logger.info( 'Duplicate entry for IP {}, skipping'.format(res_ip)) continue # If --match_all is set, ensure ALL set fields match the reservation if args.match_all: # If --hostname is set and doesn't match, skip to next reservation if hostname is not None and res_name.lower() != hostname.lower( ): logger.info( 'Reservation doesn\'t match --hostname filter with --match_all set, ineligible for deletion' ) continue # If --ip_addr is set and doesn't match, skip to next reservation if ip is not None and res_ip != str(ip): logger.info( 'Reservation doesn\'t match --ip_addr filter with --match_all set, ineligible for deletion' ) continue # If --mac_addr is set and doesn't match, skip to next reservation if mac is not None and format_mac(res_mac) != mac: logger.info( 'Reservation doesn\'t match --mac_addr filter with --match_all set, ineligible for deletion' ) continue # Determine the Network of the IP Address try: logger.info('Getting Network info from ip: {}'.format(res_ip)) net_entity = bam.get_network(res_ip) net_obj = pybluecat.entity_to_json(net_entity) network = ip_network(unicode(net_obj['properties']['CIDR'])) logger.debug(json.dumps(net_obj, indent=2)) except pybluecat.exceptions.BluecatError as e: # This would be really odd... But try to continue with the other reservations logger.error( 'Could not determine the target network or network did not exist' ) logger.error(e.message) continue # Continue on with either all reservations (if --match_any) or whatever is left from the --match_all block off_limits, error_message = is_ip_off_limits(res_ip, network) if off_limits: logger.info('Reservation ineligible for deletion: {}'.format( error_message)) continue # Finally, mark the reservation for deletion reservations_to_delete.append((reservation, net_obj)) ips_seen_so_far.append(res_ip) # Start deleting! for reservation, net_obj in reservations_to_delete: logger.info('Deleting DHCP Reservation: {}'.format( json.dumps(reservation, indent=2, sort_keys=True))) response = bam.delete(reservation['id']) output_object['deleted_reservations'].append(reservation) output_object['message'].append('DELETED: {}, {}'.format( reservation['properties']['address'], reservation['name'])) deleted_reservations.append((reservation, net_obj)) if len(deleted_reservations) > 0: deploy_needed = True output_object[ 'status'] = 'Reservations have been deleted, config NOT deployed' else: output_object['status'] = 'No Reservations were Deleted' server_set = set() # Deploy DHCP changes if no_deploy flag isn't set if deploy_needed and not args.no_deploy: # Build unique set of DHCP servers logger.info( 'Gathering list of BAM servers to push updated configs to') for reservation, net_obj in deleted_reservations: server_set = server_set | bam.queue_servers(net_obj['id']) # Deploy changes to all servers in set logger.info('Deploying Config changes') for server in server_set: logger.info('Deploying changes to server: {}'.format( str(server))) bam.deploy_server_services(server, 'DHCP') output_object['message'].append( 'Server {} queued for deployment'.format(str(server))) # Monitor the deployment through completion unless no_wait flag is set if not args.no_wait: logger.info('Waiting for deployment to finish') bam.monitor_server_deployment(server_set) output_object[ 'status'] = 'Reservations have been deleted, configs have been deployed' logger.info('Deployment finished') else: output_object[ 'status'] = 'Reservations have been deleted, configs queued for deployment' logger.info('Monitoring of deployment is being skipped') # Finally output the IP info print(json.dumps(output_object, indent=2, sort_keys=True))
def main(): parser = argparse.ArgumentParser() parser.add_argument('hostname', help='hostname') parser.add_argument('-c', '--creds', help='path to file containing credentials') group_ME = parser.add_mutually_exclusive_group(required=True) group_ME.add_argument('-n', '--network', help='network address within desired subnet') group_ME.add_argument('-e', '--environment', help='environment from which to choose a network') parser.add_argument('-l', '--loglevel', choices=['warning', 'info', 'debug'], help='enable debugging') args = parser.parse_args() NETWORK_ENVS = { 'lab': [ip_network(u'10.168.131.0/24'), ip_network(u'10.168.161.0/24')], 'dev': [ip_network(u'10.57.128.0/23')], 'test': [ip_network(u'10.57.144.0/23')], 'stage': [ip_network(u'10.57.160.0/23')], 'prod-ctis': [ip_network(u'10.7.96.0/23'), ip_network(u'10.7.98.0/23')], 'prod-brad': [ip_network(u'10.107.96.0/23'), ip_network(u'10.107.98.0/23')], 'prod-both': [ip_network(u'10.200.112.0/24'), ip_network(u'10.200.113.0/24')], 'fmt': [ip_network(u'10.57.136.0/30'), ip_network(u'10.57.136.4/30')] } if args.loglevel: level = getattr(logging, args.loglevel.upper()) logging.basicConfig(level=level) hostname = args.hostname.lower() creds = pybluecat.get_creds(args.creds) c = pybluecat.BAM(creds['hostname'], creds['username'], creds['password']) # Get Networks List if args.network: netAddr = args.network.split('/')[0] netObj = c.get_network(netAddr) netObj = c.entity_to_json(netObj) networks = [ip_network(netObj['properties']['CIDR'])] elif args.environment: import requests base_url = 'http://infradevapi.spectrum-health.org/infrastructure/' env = args.environment.lower() url = base_url + env proxy = {'http': None, 'https': None} if 'dmz' in args.environment: dhcp_offset = 0 try: r = requests.get(url, proxies=proxy) logging.info(r.request.url) logging.info(r.status_code) logging.info(r.content) except: print('Environment Not Found. No Network Available.') exit() networks = [ ip_network(net['netaddr'] + '/' + net['netmask'], strict=False) for net in json.loads(r.text)[env] ] logging.info('Networks: {}'.format(str(networks))) foundIP = False # Check for existing IP reservations in target networks results = c.search_by_object_types(hostname, 'IP4Address', 0, 1000) logging.info(str(results)) for result in results: temp = c.entity_to_json(result) for net in networks: if ip_address(temp['properties']['address']) in net: foundIP = True ipObj = temp networks = [net] logging.info('Found IP already in existence: {}'.format( json.dumps(ipObj, indent=2))) break for network in networks: logging.info('Working through network: {}'.format(str(network))) # Get Network Object and set dhcp_offset based on CIDR netObj = c.get_network(str(network.network_address)) netObj = c.entity_to_json(netObj) if network.prefixlen > 24: dhcp_offset = 0 else: dhcp_offset = 30 logging.info('DHCP-Offsest: {}'.format(str(dhcp_offset))) # Ensure IPs in the offset are 'reserved' while not foundIP: logging.info('Checking Status of Offset Addreses') ip = c.get_next_ip_address(netObj['id']) logging.info('Address {}'.format(str(ip))) if ip is None or ip == '': break elif network.network_address + dhcp_offset >= ip_address( unicode(ip)): c.assign_ip_address('', ip, '', 'MAKE_RESERVED', '') logging.info('Setting IP Address as RESERVED: {}'.format(ip)) else: break # If an existing IP has not been found yet, start working through # every free IP in the BAM Network until one is assigned or net is # exhausted if not foundIP: logging.info('Determining next available IP Address') while True: ipObj = c.assign_next_ip_address(netObj['id'], hostname) # None as a result indicates network has no next IP, end loop if ipObj['id'] == 0: break ipObj = c.entity_to_json(ipObj) logging.info('IP Address free in BAM: {}'.format( ipObj['properties']['address'])) # Check if IP has existing PTR record, if True, write it to BAM, try next IP ptr = dns_PTR_exists(ipObj['properties']['address']) if ptr: logging.info( 'PTR Record found for Address: {}'.format(ptr)) ipObj['name'] = ptr.split('.')[0] ipObj = c.json_to_entity(ipObj) c.update(ipObj) # Try to Ping the IP address, if response, log in BAM, try next IP elif ping(ipObj['properties']['address']): logging.info('Address responded to ping') ipObj['name'] = 'IN-USE: something pinged' ipObj = c.json_to_entity(ipObj) c.update(ipObj) # Finally, reserve the IP in BAM for the hostname else: logging.info('Address doesn\'t ping or have PTR record') foundIP = True break # If an IP has been found, either new or existing, return results and exit if foundIP: network = ip_network(unicode(netObj['properties']['CIDR'])) output = { 'ip_addr': ipObj['properties']['address'], 'gateway': str(network.network_address + 1), 'net_mask': str(network.netmask), 'net_name': netObj['name'], '_ipobj': ipObj, '_netobj': netObj } print(json.dumps(output, sort_keys=True, indent=4)) c.logout() exit() if not foundIP: print('No Addresses Available.') exit(1)
def main(): # Get and Parse all CLI arguments parser = argparse.ArgumentParser() parser.add_argument('cidr', nargs='+', help='CIDR(s) to act as root for enumeration') parser.add_argument('-a', '--append', help='omit header for appending to previous output', action='store_true') parser.add_argument('-c', '--creds', help='path to file containing credentials') parser.add_argument('--minimum', type=int, default=32, help='Minimum size (inclusive) of subnets, e.g. "24"') parser.add_argument('--maximum', type=int, default=0, help='Maximum size (inclusive) of subnets, e.g. "24"') parser.add_argument('--ignore_blocks', action='store_true', help='omits IP4Blocks from output') parser.add_argument( '--cidr_blacklist', help='filepath to list of network blocks to not enumerate') kw_group = parser.add_mutually_exclusive_group() kw_group.add_argument( '--keyword_blacklist', help='filepath to list of name keywords to not enumerate') kw_group.add_argument( '--keyword_whitelist', help='filepath to list of name keywords to not enumerate') args = parser.parse_args() # Initialize the Global Ignore Blocks flag global IGNORE_BLOCKS IGNORE_BLOCKS = args.ignore_blocks # Initialize the Global CIDR Minimum size global MINIMUM MINIMUM = args.minimum # Initialize the Global CIDR Maximum size global MAXIMUM MAXIMUM = args.maximum # Initialize the Global CIDR Blacklist global CIDR_BLACKLIST if args.cidr_blacklist is not None: try: with open(args.cidr_blacklist) as f: CIDR_BLACKLIST = [ line.strip().split()[0] for line in f.readlines() if line.strip() != '' ] except Exception: sys.exit('blacklist {} could not be parsed'.format( args.cidr_blacklist)) else: CIDR_BLACKLIST = [] # Initialize the Global Keyword Blacklist global KW_BLACKLIST if args.keyword_blacklist is not None: try: with open(args.keyword_blacklist) as f: KW_BLACKLIST = [ line.strip().split()[0].lower() for line in f.readlines() if line.strip() != '' ] except Exception: sys.exit('blacklist {} could not be parsed'.format( args.keyword_blacklist)) else: KW_BLACKLIST = [] # Initialize the Global Keyword Whitelist global KW_WHITELIST if args.keyword_whitelist is not None: try: with open(args.keyword_whitelist) as f: KW_WHITELIST = [ line.strip().split()[0].lower() for line in f.readlines() if line.strip() != '' ] except Exception: sys.exit('whitelist {} could not be parsed'.format( args.keyword_blacklist)) else: KW_WHITELIST = [''] # Get Credentials creds = pybluecat.get_creds(args.creds) # Create the Bluecat sessions with pybluecat.BAM(creds['hostname'], creds['username'], creds['password']) as c: config = c.get_entity_by_name(0, 'Spectrum Health', 'Configuration') # Output headers if append flag not set if not args.append: print('Network,Name,Type,VLAN,Location') # Walk Bluecat from each starting block for cidr in args.cidr: startBlock = find_start_block(c, cidr, config['id']) if not IGNORE_BLOCKS: print(get_line(c, startBlock)) walk_networks(c, startBlock)