def get_interface_counters(self, interface): """Pull the counters for an interface :param interface: interface object or str with name of interface :return: Dictionary of counters, or None if no counters for interface """ interface_name = self._interface_name(interface) self.xapi.op("<show><counter><interface>%s</interface></counter></show>" % (interface_name,)) pconf = PanConfig(self.xapi.element_result) response = pconf.python() counters = response['result'] if counters: entry = {} # Check for entry in ifnet if 'entry' in counters.get('ifnet', {}): entry = counters['ifnet']['entry'][0] elif 'ifnet' in counters.get('ifnet', {}): if 'entry' in counters['ifnet'].get('ifnet', {}): entry = counters['ifnet']['ifnet']['entry'][0] # Convert strings to integers, if they are integers entry.update((k, PanDevice._convert_if_int(v)) for k, v in entry.iteritems()) # If empty dictionary (no results) it usually means the interface is not # configured, so return None return entry if entry else None
def get_counters(self): """Pull the counters for an interface Returns: dict: counter name as key, counter as value, None if interface is not configured """ from pan.config import PanConfig pconf = self.pandevice().op('show counter interface "%s"' % self.name) pconf = PanConfig(pconf) response = pconf.python() logger.debug("response: " + str(response)) counters = response['response']['result'] if counters is not None: entry = {} # Check for entry in ifnet if 'entry' in counters.get('ifnet', {}): entry = counters['ifnet']['entry'][0] elif 'ifnet' in counters.get('ifnet', {}): if 'entry' in counters['ifnet'].get('ifnet', {}): entry = counters['ifnet']['ifnet']['entry'][0] # Convert strings to integers, if they are integers entry.update( (k, pandevice.convert_if_int(v)) for k, v in entry.iteritems()) # If empty dictionary (no results) it usually means the interface is not # configured, so return None return entry if entry else None
def get_counters(self): """Pull the counters for an interface Returns: dict: counter name as key, counter as value, None if interface is not configured """ from pan.config import PanConfig pconf = self.pandevice().op('show counter interface "%s"' % self.name) pconf = PanConfig(pconf) response = pconf.python() logger.debug("response: " + str(response)) counters = response['response']['result'] if counters is not None: entry = {} # Check for entry in ifnet if 'entry' in counters.get('ifnet', {}): entry = counters['ifnet']['entry'][0] elif 'ifnet' in counters.get('ifnet', {}): if 'entry' in counters['ifnet'].get('ifnet', {}): entry = counters['ifnet']['ifnet']['entry'][0] # Convert strings to integers, if they are integers entry.update((k, pandevice.convert_if_int(v)) for k, v in entry.iteritems()) # If empty dictionary (no results) it usually means the interface is not # configured, so return None return entry if entry else None
def get_interface_counters(self, interface): """Pull the counters for an interface :param interface: interface object or str with name of interface :return: Dictionary of counters, or None if no counters for interface """ interface_name = self._interface_name(interface) self.xapi.op( "<show><counter><interface>%s</interface></counter></show>" % (interface_name, )) pconf = PanConfig(self.xapi.element_result) response = pconf.python() counters = response['result'] if counters: entry = {} # Check for entry in ifnet if 'entry' in counters.get('ifnet', {}): entry = counters['ifnet']['entry'][0] elif 'ifnet' in counters.get('ifnet', {}): if 'entry' in counters['ifnet'].get('ifnet', {}): entry = counters['ifnet']['ifnet']['entry'][0] # Convert strings to integers, if they are integers entry.update((k, PanDevice._convert_if_int(v)) for k, v in entry.iteritems()) # If empty dictionary (no results) it usually means the interface is not # configured, so return None return entry if entry else None
def show_interface(self, interface): self.set_config_changed() interface_name = self._interface_name(interface) self.xapi.op("<show><interface>%s</interface></show>" % (interface_name,)) pconf = PanConfig(self.xapi.element_result) response = pconf.python() return response['result']
def show_interface(self, interface): self.set_config_changed() interface_name = self._interface_name(interface) self.xapi.op("<show><interface>%s</interface></show>" % (interface_name, )) pconf = PanConfig(self.xapi.element_result) response = pconf.python() return response['result']
def _parse_version_list(self, response_element): all_versions = {} for software_version in response_element.findall(".//versions/entry"): # This line doesn't work correctly in pan-python < 0.7.0. newversion = PanConfig(software_version).python("./") all_versions[newversion["version"]] = newversion return all_versions
def refresh_interfaces(self): self.xapi.op('show interface "all"', cmd_xml=True) pconf = PanConfig(self.xapi.element_root) response = pconf.python() hw = {} interfaces = {} # Check if there is a response and result try: response = response['response']['result'] except KeyError as e: raise err.PanDeviceError( "Error reading response while refreshing interfaces", pan_device=self) if response: self._logger.debug("Refresh interfaces result: %s" % response) # Create a hw dict with all the 'hw' info hw_result = response.get('hw', {}) if hw_result is None: return hw_result = hw_result.get('entry', []) for hw_entry in hw_result: hw[hw_entry['name']] = hw_entry if_result = response.get('ifnet', {}) if if_result is None: return if_result = if_result.get('entry', []) for entry in if_result: try: router = entry['fwd'].split(":", 1)[1] except IndexError: router = entry['fwd'] interface = Interface(name=entry['name'], zone=entry['zone'], router=router, subnets=[entry['ip']], state=hw.get(entry['name'], {}).get('state')) interfaces[entry['name']] = interface else: raise err.PanDeviceError("Could not refresh interfaces", pan_device=self) self.interfaces = interfaces
def get_all_address_objects(self): """Return a list containing all address objects Return a list containing all address objects in the device configuration. Returns: Right now it just returns the python representation of the API call. Eventually it should return a santized list of objects Raises: PanXapiError: Raised by pan.xapi module for API errors """ # TODO: Currently returns raw results, but should return a list # and raise an exception on error address_xpath = self.xpath + "/address" self.xapi.get(xpath=address_xpath) pconf = PanConfig(self.xapi.element_result) response = pconf.python() return response['result']
def refresh_interfaces(self): self.xapi.op('show interface "all"', cmd_xml=True) pconf = PanConfig(self.xapi.element_root) response = pconf.python() hw = {} interfaces = {} # Check if there is a response and result try: response = response['response']['result'] except KeyError as e: raise err.PanDeviceError("Error reading response while refreshing interfaces", pan_device=self) if response: self._logger.debug("Refresh interfaces result: %s" % response) # Create a hw dict with all the 'hw' info hw_result = response.get('hw', {}) if hw_result is None: return hw_result = hw_result.get('entry', []) for hw_entry in hw_result: hw[hw_entry['name']] = hw_entry if_result = response.get('ifnet', {}) if if_result is None: return if_result = if_result.get('entry', []) for entry in if_result: try: router = entry['fwd'].split(":", 1)[1] except IndexError: router = entry['fwd'] interface = Interface(name=entry['name'], zone=entry['zone'], router=router, subnets=[entry['ip']], state=hw.get(entry['name'], {}).get('state') ) interfaces[entry['name']] = interface else: raise err.PanDeviceError("Could not refresh interfaces", pan_device=self) self.interfaces = interfaces
def system_info(self, all_info=False): """Get system information Returns: system information like version, platform, etc. """ self.xapi.op(cmd="<show><system><info></info></system></show>") pconf = PanConfig(self.xapi.element_result) system_info = pconf.python() self._logger.debug("Systeminfo: %s" % system_info) if not system_info: error_msg = 'Cannot detect device type, unable to get system info' self._logger.error(error_msg) raise err.PanDeviceError(error_msg, pan_device=self) if not all_info: version = system_info['result']['system']['sw-version'] model = system_info['result']['system']['model'] serial = system_info['result']['system']['serial'] return version, model, serial else: return system_info['result']
def syncjob(self, response, interval=0.5): """Block until job completes and return result response: XML response tag from firewall when job is created :returns True if job completed successfully, False if not """ if interval is not None: try: interval = float(interval) if interval < 0: raise ValueError except ValueError: raise err.PanDeviceError('Invalid interval: %s' % interval) job = response.find('./result/job') if job is None: return False job = job.text self._logger.debug('Syncing job: %s', job) cmd = 'show jobs id "%s"' % job start_time = time.time() while True: try: self.xapi.op(cmd=cmd, cmd_xml=True) except pan.xapi.PanXapiError as msg: raise pan.xapi.PanXapiError('commit %s: %s' % (cmd, msg)) path = './result/job/status' status = self.xapi.element_root.find(path) if status is None: raise pan.xapi.PanXapiError('No status element in ' + "'%s' response" % cmd) if status.text == 'FIN': pconf = PanConfig(self.xapi.element_result) response = pconf.python() job = response['result'] if job is None: return job = job['job'] success = True if job['result'] == "OK" else False messages = job['details']['line'] if issubclass(messages.__class__, basestring): messages = [messages] # Create the results dict result = { 'success': success, 'result': job['result'], 'jobid': job['id'], 'user': job['user'], 'warnings': job['warnings'], 'starttime': job['tenq'], 'endtime': job['tfin'], 'messages': messages, } return result self._logger.debug('Job %s status %s', job, status.text) if (self.timeout is not None and self.timeout != 0 and time.time() > start_time + self.timeout): raise pan.xapi.PanXapiError('Timeout waiting for ' + 'job %s completion' % job) self._logger.debug('Sleep %.2f seconds', interval) time.sleep(interval)
def _commit(self, cmd=None, exclude=None, commit_all=False, sync=False, sync_all=True, exception=False): """Internal use commit helper method. :param exclude: Can be: device-and-network policy-and-objects :param sync: Synchronous commit, ie. wait for job to finish :return: Result of commit as dict if synchronous. JobID if asynchronous. In either case, if no commit is needed, return None. Most important fields in dict: success: True or False result: OK or FAIL messages: list of warnings or errors """ if issubclass(cmd.__class__, pan.commit.PanCommit): cmd = cmd.cmd() elif issubclass(cmd.__class__, ET.Element): cmd = ET.tostring(cmd) elif issubclass(cmd.__class__, basestring): pass else: cmd = ET.Element("commit") if exclude is not None: excluded = ET.SubElement(cmd, "partial") excluded = ET.SubElement(excluded, exclude) cmd = ET.tostring(cmd) if commit_all: action = "all" else: action = None if sync: self._logger.debug("Waiting for commit job to finish...") self.xapi.commit(cmd=cmd, action=action, sync=sync, sync_all=sync_all, interval=self.interval, timeout=self.timeout) self.config_changed = False self.config_locked = False self.commit_locked = False if sync: pconf = PanConfig(self.xapi.element_result) response = pconf.python() job = response['result'] if job is None: if exception: raise err.PanCommitNotNeeded("Commit not needed", pan_device=self) else: return job = job['job'] # Create a boolean called success to make # testing for success easier devices_results = {} devices_success = True if commit_all and sync_all: devices = job['devices'] if devices is not None: devices = devices['entry'] for device in devices: success = True if device['result'] == "OK" else False if not success: devices_success = False devices_results[device['serial-no']] = { 'success': success, 'serial': device['serial-no'], 'name': device['devicename'], 'result': device['result'], 'starttime': device['tstart'], 'endtime': device['tfin'], } # Errors and warnings might not have a full structure. If it is just a string, then # a TypeError will be produced, so in that case, just grab the string. try: devices_results[device['serial-no']]['warnings'] = device['details']['msg']['warnings'] except TypeError as e: devices_results[device['serial-no']]['warnings'] = "" try: devices_results[device['serial-no']]['messages'] = device['details']['msg']['errors'][ 'line'] except TypeError as e: devices_results[device['serial-no']]['messages'] = device['details'] success = True if job['result'] == "OK" and devices_success else False if commit_all: messages = [] else: messages = job['details']['line'] if issubclass(messages.__class__, basestring): messages = [messages] # Create the results dict result = { 'success': success, 'result': job['result'], 'jobid': job['id'], 'user': job['user'], 'warnings': job['warnings'], 'starttime': job['tenq'], 'endtime': job['tfin'], 'messages': messages, 'devices': devices_results } if exception and not success: self._logger.debug("Commit failed - device: %s, job: %s, messages: %s, warnings: %s" % (self.hostname, result['jobid'], result['messages'], result['warnings'])) raise err.PanCommitFailed(pan_device=self, result=result) else: if success: self._logger.debug("Commit succeeded - device: %s, job: %s, messages: %s, warnings: %s" % (self.hostname, result['jobid'], result['messages'], result['warnings'])) else: self._logger.debug("Commit failed - device: %s, job: %s, messages: %s, warnings: %s" % (self.hostname, result['jobid'], result['messages'], result['warnings'])) return result else: jobid = self.xapi.element_root.find('./result/job') if jobid is None: if exception: raise err.PanCommitNotNeeded("Commit not needed", pan_device=self) else: return self._logger.debug("Commit initiated (async), job id: %s" % (jobid,)) return jobid
def refresh_devices_from_panorama(self, devices=()): try: # Test if devices is iterable test_iterable = iter(devices) except TypeError: # This probably means a single device was passed in, not an iterable. # Convert to an iterable with a single item. devices = (devices,) stats_by_ip = {} stats_by_host = {} devicegroup_stats_by_serial = {} template_stats_by_serial = {} # Get the list of managed devices self.xapi.op("show devices all", cmd_xml=True) pconf = PanConfig(self.xapi.element_root) response = pconf.python() try: for device in response['response']['result']['devices']['entry']: stats_by_ip[device['ip-address']] = device stats_by_host[device['ip-address']] = device stats_by_host[device['hostname']] = device # Populate the device objects with some of the data for device in devices: try: device.serial = stats_by_host[device.hostname]['serial'] device.connected_to_panorama = stats_by_host[device.hostname]['connected'] except KeyError as e: raise err.PanDeviceError("Can't determine serial for " "device", pan_device=device) # Ignore errors because it means there are no devices except KeyError: return {} # Get the list of device groups self.xapi.op("show devicegroups", cmd_xml=True) dg_element = self.xapi.element_result for dg in dg_element.findall("./devicegroups/entry"): for device in dg.findall("./devices/entry"): pconf = PanConfig(config=device) stats = pconf.python() # Save device stats stats = stats['entry'] # Save device serial serial = stats['serial'] # Save device ip-address ip = stats['ip-address'] # Save device's device-group dg_name = dg.get('name') # Save the device-group to the device's stats stats['devicegroup'] = dg_name devicegroup_stats_by_serial[serial] = stats stats_by_ip[ip]['devicegroup'] = dg_name # Set the device-group for each device for device in devices: if device.serial is not None: stats = devicegroup_stats_by_serial.get(device.serial) if stats is not None: device.devicegroup = stats['devicegroup'] sync_status = stats['shared-policy-status'] device.dg_in_sync = True if sync_status == "In Sync" else False return stats_by_ip
def pending_changes(self): self.xapi.op(cmd="check pending-changes", cmd_xml=True) pconf = PanConfig(self.xapi.element_result) response = pconf.python() return response['result']
def refresh_devices_from_panorama(self, devices=()): try: # Test if devices is iterable test_iterable = iter(devices) except TypeError: # This probably means a single device was passed in, not an iterable. # Convert to an iterable with a single item. devices = (devices, ) stats_by_ip = {} stats_by_host = {} devicegroup_stats_by_serial = {} template_stats_by_serial = {} # Get the list of managed devices self.xapi.op("show devices all", cmd_xml=True) pconf = PanConfig(self.xapi.element_root) response = pconf.python() try: for device in response['response']['result']['devices']['entry']: stats_by_ip[device['ip-address']] = device stats_by_host[device['ip-address']] = device stats_by_host[device['hostname']] = device # Populate the device objects with some of the data for device in devices: try: device.serial = stats_by_host[device.hostname]['serial'] device.connected_to_panorama = stats_by_host[ device.hostname]['connected'] except KeyError as e: raise err.PanDeviceError( "Can't determine serial for " "device", pan_device=device) # Ignore errors because it means there are no devices except KeyError: return {} # Get the list of device groups self.xapi.op("show devicegroups", cmd_xml=True) dg_element = self.xapi.element_result for dg in dg_element.findall("./devicegroups/entry"): for device in dg.findall("./devices/entry"): pconf = PanConfig(config=device) stats = pconf.python() # Save device stats stats = stats['entry'] # Save device serial serial = stats['serial'] # Save device ip-address ip = stats['ip-address'] # Save device's device-group dg_name = dg.get('name') # Save the device-group to the device's stats stats['devicegroup'] = dg_name devicegroup_stats_by_serial[serial] = stats stats_by_ip[ip]['devicegroup'] = dg_name # Set the device-group for each device for device in devices: if device.serial is not None: stats = devicegroup_stats_by_serial.get(device.serial) if stats is not None: device.devicegroup = stats['devicegroup'] sync_status = stats['shared-policy-status'] device.dg_in_sync = True if sync_status == "In Sync" else False return stats_by_ip
def _commit(self, cmd=None, exclude=None, commit_all=False, sync=False, sync_all=True, exception=False): """Internal use commit helper method. :param exclude: Can be: device-and-network policy-and-objects :param sync: Synchronous commit, ie. wait for job to finish :return: Result of commit as dict if synchronous. JobID if asynchronous. In either case, if no commit is needed, return None. Most important fields in dict: success: True or False result: OK or FAIL messages: list of warnings or errors """ if issubclass(cmd.__class__, pan.commit.PanCommit): cmd = cmd.cmd() elif issubclass(cmd.__class__, ET.Element): cmd = ET.tostring(cmd) elif issubclass(cmd.__class__, basestring): pass else: cmd = ET.Element("commit") if exclude is not None: excluded = ET.SubElement(cmd, "partial") excluded = ET.SubElement(excluded, exclude) cmd = ET.tostring(cmd) if commit_all: action = "all" else: action = None if sync: self._logger.debug("Waiting for commit job to finish...") self.xapi.commit(cmd=cmd, action=action, sync=sync, sync_all=sync_all, interval=self.interval, timeout=self.timeout) self.config_changed = False self.config_locked = False self.commit_locked = False if sync: pconf = PanConfig(self.xapi.element_result) response = pconf.python() job = response['result'] if job is None: if exception: raise err.PanCommitNotNeeded("Commit not needed", pan_device=self) else: return job = job['job'] # Create a boolean called success to make # testing for success easier devices_results = {} devices_success = True if commit_all and sync_all: devices = job['devices'] if devices is not None: devices = devices['entry'] for device in devices: success = True if device['result'] == "OK" else False if not success: devices_success = False devices_results[device['serial-no']] = { 'success': success, 'serial': device['serial-no'], 'name': device['devicename'], 'result': device['result'], 'starttime': device['tstart'], 'endtime': device['tfin'], } # Errors and warnings might not have a full structure. If it is just a string, then # a TypeError will be produced, so in that case, just grab the string. try: devices_results[ device['serial-no']]['warnings'] = device[ 'details']['msg']['warnings'] except TypeError as e: devices_results[ device['serial-no']]['warnings'] = "" try: devices_results[ device['serial-no']]['messages'] = device[ 'details']['msg']['errors']['line'] except TypeError as e: devices_results[device['serial-no']][ 'messages'] = device['details'] success = True if job[ 'result'] == "OK" and devices_success else False if commit_all: messages = [] else: messages = job['details']['line'] if issubclass(messages.__class__, basestring): messages = [messages] # Create the results dict result = { 'success': success, 'result': job['result'], 'jobid': job['id'], 'user': job['user'], 'warnings': job['warnings'], 'starttime': job['tenq'], 'endtime': job['tfin'], 'messages': messages, 'devices': devices_results } if exception and not success: self._logger.debug( "Commit failed - device: %s, job: %s, messages: %s, warnings: %s" % (self.hostname, result['jobid'], result['messages'], result['warnings'])) raise err.PanCommitFailed(pan_device=self, result=result) else: if success: self._logger.debug( "Commit succeeded - device: %s, job: %s, messages: %s, warnings: %s" % (self.hostname, result['jobid'], result['messages'], result['warnings'])) else: self._logger.debug( "Commit failed - device: %s, job: %s, messages: %s, warnings: %s" % (self.hostname, result['jobid'], result['messages'], result['warnings'])) return result else: jobid = self.xapi.element_root.find('./result/job') if jobid is None: if exception: raise err.PanCommitNotNeeded("Commit not needed", pan_device=self) else: return self._logger.debug("Commit initiated (async), job id: %s" % (jobid, )) return jobid