diff --git a/.gitignore b/.gitignore index 5fc2ef0e..3614bec9 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ *.iml **/*.iml .idea +*.env +*.zip diff --git a/Quali/lanforge_resource/.gitignore b/Quali/lanforge_resource/.gitignore new file mode 100644 index 00000000..1e1a44c7 --- /dev/null +++ b/Quali/lanforge_resource/.gitignore @@ -0,0 +1,60 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ +cloudshell_config.yml diff --git a/Quali/lanforge_resource/TOSCA-Metadata/TOSCA.meta b/Quali/lanforge_resource/TOSCA-Metadata/TOSCA.meta new file mode 100644 index 00000000..5a9b442f --- /dev/null +++ b/Quali/lanforge_resource/TOSCA-Metadata/TOSCA.meta @@ -0,0 +1,4 @@ +TOSCA-Meta-File-Version: 1.0 +CSAR-Version: 0.1.0 +Created-By: Anonymous +Entry-Definitions: shell-definition.yaml \ No newline at end of file diff --git a/Quali/lanforge_resource/canvil2-64x64-gray-yel-ico.png b/Quali/lanforge_resource/canvil2-64x64-gray-yel-ico.png new file mode 100644 index 00000000..9abca242 Binary files /dev/null and b/Quali/lanforge_resource/canvil2-64x64-gray-yel-ico.png differ diff --git a/Quali/lanforge_resource/deployment.xml b/Quali/lanforge_resource/deployment.xml new file mode 100644 index 00000000..fa1f6a32 --- /dev/null +++ b/Quali/lanforge_resource/deployment.xml @@ -0,0 +1,53 @@ + + + + + localhost + + + 8029 + + + YOUR_USERNAME + YOUR_PASSWORD + Global + + + dont_upload_me.xml + + + + + + + + + + src + + + LanforgeResourceDriver + + + + + + + \ No newline at end of file diff --git a/Quali/lanforge_resource/docs/readme.rst b/Quali/lanforge_resource/docs/readme.rst new file mode 100644 index 00000000..4dc0eb5d --- /dev/null +++ b/Quali/lanforge_resource/docs/readme.rst @@ -0,0 +1,3 @@ +.. _readme: + +.. include:: ../README.rst diff --git a/Quali/lanforge_resource/shell-definition.yaml b/Quali/lanforge_resource/shell-definition.yaml new file mode 100644 index 00000000..2a0f9cbb --- /dev/null +++ b/Quali/lanforge_resource/shell-definition.yaml @@ -0,0 +1,45 @@ +tosca_definitions_version: tosca_simple_yaml_1_0 + +metadata: + template_name: Lanforge Resource + template_author: Anonymous + template_version: 0.1.0 + template_icon: shell-icon.png + +description: > + TOSCA based resource shell + +imports: + - cloudshell_standard: cloudshell_resource_standard_2_0_3.yaml + +node_types: + + vendor.resource.Lanforge Resource: + derived_from: cloudshell.nodes.GenericResource + #properties: + # my_property: + # type: string # optional values: string, integer, float, boolean, cloudshell.datatypes.Password + # default: fast + # description: Some attribute description + # constraints: + # - valid_values: [fast, slow] + capabilities: + auto_discovery_capability: + type: cloudshell.capabilities.AutoDiscovery + properties: + enable_auto_discovery: + type: boolean + default: true + auto_discovery_description: + type: string + default: Describe the auto discovery + inventory_description: + type: string + default: Describe the resource shell template + artifacts: + icon: + file: canvil2-64x64-gray-yel-ico.png + type: tosca.artifacts.File + driver: + file: LanforgeResourceDriver.zip + type: tosca.artifacts.File diff --git a/Quali/lanforge_resource/shell-icon.png b/Quali/lanforge_resource/shell-icon.png new file mode 100644 index 00000000..820b28fd Binary files /dev/null and b/Quali/lanforge_resource/shell-icon.png differ diff --git a/Quali/lanforge_resource/src/data_model.py b/Quali/lanforge_resource/src/data_model.py new file mode 100644 index 00000000..329bdfbb --- /dev/null +++ b/Quali/lanforge_resource/src/data_model.py @@ -0,0 +1,1029 @@ +from cloudshell.shell.core.driver_context import ResourceCommandContext, AutoLoadDetails, AutoLoadAttribute, \ + AutoLoadResource +from collections import defaultdict + + +class LegacyUtils(object): + def __init__(self): + self._datamodel_clss_dict = self.__generate_datamodel_classes_dict() + + def migrate_autoload_details(self, autoload_details, context): + model_name = context.resource.model + root_name = context.resource.name + root = self.__create_resource_from_datamodel(model_name, root_name) + attributes = self.__create_attributes_dict(autoload_details.attributes) + self.__attach_attributes_to_resource(attributes, '', root) + self.__build_sub_resoruces_hierarchy(root, autoload_details.resources, attributes) + return root + + def __create_resource_from_datamodel(self, model_name, res_name): + return self._datamodel_clss_dict[model_name](res_name) + + def __create_attributes_dict(self, attributes_lst): + d = defaultdict(list) + for attribute in attributes_lst: + d[attribute.relative_address].append(attribute) + return d + + def __build_sub_resoruces_hierarchy(self, root, sub_resources, attributes): + d = defaultdict(list) + for resource in sub_resources: + splitted = resource.relative_address.split('/') + parent = '' if len(splitted) == 1 else resource.relative_address.rsplit('/', 1)[0] + rank = len(splitted) + d[rank].append((parent, resource)) + + self.__set_models_hierarchy_recursively(d, 1, root, '', attributes) + + def __set_models_hierarchy_recursively(self, dict, rank, manipulated_resource, resource_relative_addr, attributes): + if rank not in dict: # validate if key exists + pass + + for (parent, resource) in dict[rank]: + if parent == resource_relative_addr: + sub_resource = self.__create_resource_from_datamodel( + resource.model.replace(' ', ''), + resource.name) + self.__attach_attributes_to_resource(attributes, resource.relative_address, sub_resource) + manipulated_resource.add_sub_resource( + self.__slice_parent_from_relative_path(parent, resource.relative_address), sub_resource) + self.__set_models_hierarchy_recursively( + dict, + rank + 1, + sub_resource, + resource.relative_address, + attributes) + + def __attach_attributes_to_resource(self, attributes, curr_relative_addr, resource): + for attribute in attributes[curr_relative_addr]: + setattr(resource, attribute.attribute_name.lower().replace(' ', '_'), attribute.attribute_value) + del attributes[curr_relative_addr] + + def __slice_parent_from_relative_path(self, parent, relative_addr): + if parent is '': + return relative_addr + return relative_addr[len(parent) + 1:] # + 1 because we want to remove the seperator also + + def __generate_datamodel_classes_dict(self): + return dict(self.__collect_generated_classes()) + + def __collect_generated_classes(self): + import sys, inspect + return inspect.getmembers(sys.modules[__name__], inspect.isclass) + + +class LanforgeResource(object): + def __init__(self, name): + """ + + """ + self.attributes = {} + self.resources = {} + self._cloudshell_model_name = 'Lanforge Resource' + self._name = name + + def add_sub_resource(self, relative_path, sub_resource): + self.resources[relative_path] = sub_resource + + @classmethod + def create_from_context(cls, context): + """ + Creates an instance of NXOS by given context + :param context: cloudshell.shell.core.driver_context.ResourceCommandContext + :type context: cloudshell.shell.core.driver_context.ResourceCommandContext + :return: + :rtype LanforgeResource + """ + result = LanforgeResource(name=context.resource.name) + for attr in context.resource.attributes: + result.attributes[attr] = context.resource.attributes[attr] + return result + + def create_autoload_details(self, relative_path=''): + """ + :param relative_path: + :type relative_path: str + :return + """ + resources = [AutoLoadResource(model=self.resources[r].cloudshell_model_name, + name=self.resources[r].name, + relative_address=self._get_relative_path(r, relative_path)) + for r in self.resources] + attributes = [AutoLoadAttribute(relative_path, a, self.attributes[a]) for a in self.attributes] + autoload_details = AutoLoadDetails(resources, attributes) + for r in self.resources: + curr_path = relative_path + '/' + r if relative_path else r + curr_auto_load_details = self.resources[r].create_autoload_details(curr_path) + autoload_details = self._merge_autoload_details(autoload_details, curr_auto_load_details) + return autoload_details + + def _get_relative_path(self, child_path, parent_path): + """ + Combines relative path + :param child_path: Path of a model within it parent model, i.e 1 + :type child_path: str + :param parent_path: Full path of parent model, i.e 1/1. Might be empty for root model + :type parent_path: str + :return: Combined path + :rtype str + """ + return parent_path + '/' + child_path if parent_path else child_path + + @staticmethod + def _merge_autoload_details(autoload_details1, autoload_details2): + """ + Merges two instances of AutoLoadDetails into the first one + :param autoload_details1: + :type autoload_details1: AutoLoadDetails + :param autoload_details2: + :type autoload_details2: AutoLoadDetails + :return: + :rtype AutoLoadDetails + """ + for attribute in autoload_details2.attributes: + autoload_details1.attributes.append(attribute) + for resource in autoload_details2.resources: + autoload_details1.resources.append(resource) + return autoload_details1 + + @property + def cloudshell_model_name(self): + """ + Returns the name of the Cloudshell model + :return: + """ + return 'LanforgeResource' + + @property + def user(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.User'] if 'Lanforge Resource.User' in self.attributes else None + + @user.setter + def user(self, value): + """ + User with administrative privileges + :type value: str + """ + self.attributes['Lanforge Resource.User'] = value + + @property + def password(self): + """ + :rtype: string + """ + return self.attributes['Lanforge Resource.Password'] if 'Lanforge Resource.Password' in self.attributes else None + + @password.setter + def password(self, value): + """ + + :type value: string + """ + self.attributes['Lanforge Resource.Password'] = value + + @property + def enable_password(self): + """ + :rtype: string + """ + return self.attributes['Lanforge Resource.Enable Password'] if 'Lanforge Resource.Enable Password' in self.attributes else None + + @enable_password.setter + def enable_password(self, value): + """ + The enable password is required by some CLI protocols such as Telnet and is required according to the device configuration. + :type value: string + """ + self.attributes['Lanforge Resource.Enable Password'] = value + + @property + def power_management(self): + """ + :rtype: bool + """ + return self.attributes['Lanforge Resource.Power Management'] if 'Lanforge Resource.Power Management' in self.attributes else None + + @power_management.setter + def power_management(self, value=True): + """ + Used by the power management orchestration, if enabled, to determine whether to automatically manage the device power status. Enabled by default. + :type value: bool + """ + self.attributes['Lanforge Resource.Power Management'] = value + + @property + def sessions_concurrency_limit(self): + """ + :rtype: float + """ + return self.attributes['Lanforge Resource.Sessions Concurrency Limit'] if 'Lanforge Resource.Sessions Concurrency Limit' in self.attributes else None + + @sessions_concurrency_limit.setter + def sessions_concurrency_limit(self, value='1'): + """ + The maximum number of concurrent sessions that the driver will open to the device. Default is 1 (no concurrency). + :type value: float + """ + self.attributes['Lanforge Resource.Sessions Concurrency Limit'] = value + + @property + def snmp_read_community(self): + """ + :rtype: string + """ + return self.attributes['Lanforge Resource.SNMP Read Community'] if 'Lanforge Resource.SNMP Read Community' in self.attributes else None + + @snmp_read_community.setter + def snmp_read_community(self, value): + """ + The SNMP Read-Only Community String is like a password. It is sent along with each SNMP Get-Request and allows (or denies) access to device. + :type value: string + """ + self.attributes['Lanforge Resource.SNMP Read Community'] = value + + @property + def snmp_write_community(self): + """ + :rtype: string + """ + return self.attributes['Lanforge Resource.SNMP Write Community'] if 'Lanforge Resource.SNMP Write Community' in self.attributes else None + + @snmp_write_community.setter + def snmp_write_community(self, value): + """ + The SNMP Write Community String is like a password. It is sent along with each SNMP Set-Request and allows (or denies) chaning MIBs values. + :type value: string + """ + self.attributes['Lanforge Resource.SNMP Write Community'] = value + + @property + def snmp_v3_user(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.SNMP V3 User'] if 'Lanforge Resource.SNMP V3 User' in self.attributes else None + + @snmp_v3_user.setter + def snmp_v3_user(self, value): + """ + Relevant only in case SNMP V3 is in use. + :type value: str + """ + self.attributes['Lanforge Resource.SNMP V3 User'] = value + + @property + def snmp_v3_password(self): + """ + :rtype: string + """ + return self.attributes['Lanforge Resource.SNMP V3 Password'] if 'Lanforge Resource.SNMP V3 Password' in self.attributes else None + + @snmp_v3_password.setter + def snmp_v3_password(self, value): + """ + Relevant only in case SNMP V3 is in use. + :type value: string + """ + self.attributes['Lanforge Resource.SNMP V3 Password'] = value + + @property + def snmp_v3_private_key(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.SNMP V3 Private Key'] if 'Lanforge Resource.SNMP V3 Private Key' in self.attributes else None + + @snmp_v3_private_key.setter + def snmp_v3_private_key(self, value): + """ + Relevant only in case SNMP V3 is in use. + :type value: str + """ + self.attributes['Lanforge Resource.SNMP V3 Private Key'] = value + + @property + def snmp_v3_authentication_protocol(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.SNMP V3 Authentication Protocol'] if 'Lanforge Resource.SNMP V3 Authentication Protocol' in self.attributes else None + + @snmp_v3_authentication_protocol.setter + def snmp_v3_authentication_protocol(self, value='No Authentication Protocol'): + """ + Relevant only in case SNMP V3 is in use. + :type value: str + """ + self.attributes['Lanforge Resource.SNMP V3 Authentication Protocol'] = value + + @property + def snmp_v3_privacy_protocol(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.SNMP V3 Privacy Protocol'] if 'Lanforge Resource.SNMP V3 Privacy Protocol' in self.attributes else None + + @snmp_v3_privacy_protocol.setter + def snmp_v3_privacy_protocol(self, value='No Privacy Protocol'): + """ + Relevant only in case SNMP V3 is in use. + :type value: str + """ + self.attributes['Lanforge Resource.SNMP V3 Privacy Protocol'] = value + + @property + def snmp_version(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.SNMP Version'] if 'Lanforge Resource.SNMP Version' in self.attributes else None + + @snmp_version.setter + def snmp_version(self, value=''): + """ + The version of SNMP to use. Possible values are v1, v2c and v3. + :type value: str + """ + self.attributes['Lanforge Resource.SNMP Version'] = value + + @property + def enable_snmp(self): + """ + :rtype: bool + """ + return self.attributes['Lanforge Resource.Enable SNMP'] if 'Lanforge Resource.Enable SNMP' in self.attributes else None + + @enable_snmp.setter + def enable_snmp(self, value=True): + """ + If set to True and SNMP isn???t enabled yet in the device the Shell will automatically enable SNMP in the device when Autoload command is called. SNMP must be enabled on the device for the Autoload command to run successfully. True by default. + :type value: bool + """ + self.attributes['Lanforge Resource.Enable SNMP'] = value + + @property + def disable_snmp(self): + """ + :rtype: bool + """ + return self.attributes['Lanforge Resource.Disable SNMP'] if 'Lanforge Resource.Disable SNMP' in self.attributes else None + + @disable_snmp.setter + def disable_snmp(self, value=False): + """ + If set to True SNMP will be disabled automatically by the Shell after the Autoload command execution is completed. False by default. + :type value: bool + """ + self.attributes['Lanforge Resource.Disable SNMP'] = value + + @property + def console_server_ip_address(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.Console Server IP Address'] if 'Lanforge Resource.Console Server IP Address' in self.attributes else None + + @console_server_ip_address.setter + def console_server_ip_address(self, value): + """ + The IP address of the console server, in IPv4 format. + :type value: str + """ + self.attributes['Lanforge Resource.Console Server IP Address'] = value + + @property + def console_user(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.Console User'] if 'Lanforge Resource.Console User' in self.attributes else None + + @console_user.setter + def console_user(self, value): + """ + + :type value: str + """ + self.attributes['Lanforge Resource.Console User'] = value + + @property + def console_port(self): + """ + :rtype: float + """ + return self.attributes['Lanforge Resource.Console Port'] if 'Lanforge Resource.Console Port' in self.attributes else None + + @console_port.setter + def console_port(self, value): + """ + The port on the console server, usually TCP port, which the device is associated with. + :type value: float + """ + self.attributes['Lanforge Resource.Console Port'] = value + + @property + def console_password(self): + """ + :rtype: string + """ + return self.attributes['Lanforge Resource.Console Password'] if 'Lanforge Resource.Console Password' in self.attributes else None + + @console_password.setter + def console_password(self, value): + """ + + :type value: string + """ + self.attributes['Lanforge Resource.Console Password'] = value + + @property + def cli_connection_type(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.CLI Connection Type'] if 'Lanforge Resource.CLI Connection Type' in self.attributes else None + + @cli_connection_type.setter + def cli_connection_type(self, value='Auto'): + """ + The CLI connection type that will be used by the driver. Possible values are Auto, Console, SSH, Telnet and TCP. If Auto is selected the driver will choose the available connection type automatically. Default value is Auto. + :type value: str + """ + self.attributes['Lanforge Resource.CLI Connection Type'] = value + + @property + def cli_tcp_port(self): + """ + :rtype: float + """ + return self.attributes['Lanforge Resource.CLI TCP Port'] if 'Lanforge Resource.CLI TCP Port' in self.attributes else None + + @cli_tcp_port.setter + def cli_tcp_port(self, value): + """ + TCP Port to user for CLI connection. If kept empty a default CLI port will be used based on the chosen protocol, for example Telnet will use port 23. + :type value: float + """ + self.attributes['Lanforge Resource.CLI TCP Port'] = value + + @property + def backup_location(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.Backup Location'] if 'Lanforge Resource.Backup Location' in self.attributes else None + + @backup_location.setter + def backup_location(self, value): + """ + Used by the save/restore orchestration to determine where backups should be saved. + :type value: str + """ + self.attributes['Lanforge Resource.Backup Location'] = value + + @property + def backup_type(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.Backup Type'] if 'Lanforge Resource.Backup Type' in self.attributes else None + + @backup_type.setter + def backup_type(self, value='File System'): + """ + Supported protocols for saving and restoring of configuration and firmware files. Possible values are 'File System' 'FTP' and 'TFTP'. Default value is 'File System'. + :type value: str + """ + self.attributes['Lanforge Resource.Backup Type'] = value + + @property + def backup_user(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.Backup User'] if 'Lanforge Resource.Backup User' in self.attributes else None + + @backup_user.setter + def backup_user(self, value): + """ + Username for the storage server used for saving and restoring of configuration and firmware files. + :type value: str + """ + self.attributes['Lanforge Resource.Backup User'] = value + + @property + def backup_password(self): + """ + :rtype: string + """ + return self.attributes['Lanforge Resource.Backup Password'] if 'Lanforge Resource.Backup Password' in self.attributes else None + + @backup_password.setter + def backup_password(self, value): + """ + Password for the storage server used for saving and restoring of configuration and firmware files. + :type value: string + """ + self.attributes['Lanforge Resource.Backup Password'] = value + + @property + def name(self): + """ + :rtype: str + """ + return self._name + + @name.setter + def name(self, value): + """ + + :type value: str + """ + self._name = value + + @property + def cloudshell_model_name(self): + """ + :rtype: str + """ + return self._cloudshell_model_name + + @cloudshell_model_name.setter + def cloudshell_model_name(self, value): + """ + + :type value: str + """ + self._cloudshell_model_name = value + + @property + def system_name(self): + """ + :rtype: str + """ + return self.attributes['CS_GenericResource.System Name'] if 'CS_GenericResource.System Name' in self.attributes else None + + @system_name.setter + def system_name(self, value): + """ + A unique identifier for the device, if exists in the device terminal/os. + :type value: str + """ + self.attributes['CS_GenericResource.System Name'] = value + + @property + def vendor(self): + """ + :rtype: str + """ + return self.attributes['CS_GenericResource.Vendor'] if 'CS_GenericResource.Vendor' in self.attributes else None + + @vendor.setter + def vendor(self, value=''): + """ + The name of the device manufacture. + :type value: str + """ + self.attributes['CS_GenericResource.Vendor'] = value + + @property + def contact_name(self): + """ + :rtype: str + """ + return self.attributes['CS_GenericResource.Contact Name'] if 'CS_GenericResource.Contact Name' in self.attributes else None + + @contact_name.setter + def contact_name(self, value): + """ + The name of a contact registered in the device. + :type value: str + """ + self.attributes['CS_GenericResource.Contact Name'] = value + + @property + def location(self): + """ + :rtype: str + """ + return self.attributes['CS_GenericResource.Location'] if 'CS_GenericResource.Location' in self.attributes else None + + @location.setter + def location(self, value=''): + """ + The device physical location identifier. For example Lab1/Floor2/Row5/Slot4. + :type value: str + """ + self.attributes['CS_GenericResource.Location'] = value + + @property + def model(self): + """ + :rtype: str + """ + return self.attributes['CS_GenericResource.Model'] if 'CS_GenericResource.Model' in self.attributes else None + + @model.setter + def model(self, value=''): + """ + The device model. This information is typically used for abstract resource filtering. + :type value: str + """ + self.attributes['CS_GenericResource.Model'] = value + + @property + def model_name(self): + """ + :rtype: str + """ + return self.attributes['CS_GenericResource.Model Name'] if 'CS_GenericResource.Model Name' in self.attributes else None + + @model_name.setter + def model_name(self, value=''): + """ + The catalog name of the device model. This attribute will be displayed in CloudShell instead of the CloudShell model. + :type value: str + """ + self.attributes['CS_GenericResource.Model Name'] = value + + +class ResourcePort(object): + def __init__(self, name): + """ + + """ + self.attributes = {} + self.resources = {} + self._cloudshell_model_name = 'Lanforge Resource.ResourcePort' + self._name = name + + def add_sub_resource(self, relative_path, sub_resource): + self.resources[relative_path] = sub_resource + + @classmethod + def create_from_context(cls, context): + """ + Creates an instance of NXOS by given context + :param context: cloudshell.shell.core.driver_context.ResourceCommandContext + :type context: cloudshell.shell.core.driver_context.ResourceCommandContext + :return: + :rtype ResourcePort + """ + result = ResourcePort(name=context.resource.name) + for attr in context.resource.attributes: + result.attributes[attr] = context.resource.attributes[attr] + return result + + def create_autoload_details(self, relative_path=''): + """ + :param relative_path: + :type relative_path: str + :return + """ + resources = [AutoLoadResource(model=self.resources[r].cloudshell_model_name, + name=self.resources[r].name, + relative_address=self._get_relative_path(r, relative_path)) + for r in self.resources] + attributes = [AutoLoadAttribute(relative_path, a, self.attributes[a]) for a in self.attributes] + autoload_details = AutoLoadDetails(resources, attributes) + for r in self.resources: + curr_path = relative_path + '/' + r if relative_path else r + curr_auto_load_details = self.resources[r].create_autoload_details(curr_path) + autoload_details = self._merge_autoload_details(autoload_details, curr_auto_load_details) + return autoload_details + + def _get_relative_path(self, child_path, parent_path): + """ + Combines relative path + :param child_path: Path of a model within it parent model, i.e 1 + :type child_path: str + :param parent_path: Full path of parent model, i.e 1/1. Might be empty for root model + :type parent_path: str + :return: Combined path + :rtype str + """ + return parent_path + '/' + child_path if parent_path else child_path + + @staticmethod + def _merge_autoload_details(autoload_details1, autoload_details2): + """ + Merges two instances of AutoLoadDetails into the first one + :param autoload_details1: + :type autoload_details1: AutoLoadDetails + :param autoload_details2: + :type autoload_details2: AutoLoadDetails + :return: + :rtype AutoLoadDetails + """ + for attribute in autoload_details2.attributes: + autoload_details1.attributes.append(attribute) + for resource in autoload_details2.resources: + autoload_details1.resources.append(resource) + return autoload_details1 + + @property + def cloudshell_model_name(self): + """ + Returns the name of the Cloudshell model + :return: + """ + return 'ResourcePort' + + @property + def mac_address(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.ResourcePort.MAC Address'] if 'Lanforge Resource.ResourcePort.MAC Address' in self.attributes else None + + @mac_address.setter + def mac_address(self, value=''): + """ + + :type value: str + """ + self.attributes['Lanforge Resource.ResourcePort.MAC Address'] = value + + @property + def ipv4_address(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.ResourcePort.IPv4 Address'] if 'Lanforge Resource.ResourcePort.IPv4 Address' in self.attributes else None + + @ipv4_address.setter + def ipv4_address(self, value): + """ + + :type value: str + """ + self.attributes['Lanforge Resource.ResourcePort.IPv4 Address'] = value + + @property + def ipv6_address(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.ResourcePort.IPv6 Address'] if 'Lanforge Resource.ResourcePort.IPv6 Address' in self.attributes else None + + @ipv6_address.setter + def ipv6_address(self, value): + """ + + :type value: str + """ + self.attributes['Lanforge Resource.ResourcePort.IPv6 Address'] = value + + @property + def port_speed(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.ResourcePort.Port Speed'] if 'Lanforge Resource.ResourcePort.Port Speed' in self.attributes else None + + @port_speed.setter + def port_speed(self, value): + """ + The port speed (e.g 10Gb/s, 40Gb/s, 100Mb/s) + :type value: str + """ + self.attributes['Lanforge Resource.ResourcePort.Port Speed'] = value + + @property + def name(self): + """ + :rtype: str + """ + return self._name + + @name.setter + def name(self, value): + """ + + :type value: str + """ + self._name = value + + @property + def cloudshell_model_name(self): + """ + :rtype: str + """ + return self._cloudshell_model_name + + @cloudshell_model_name.setter + def cloudshell_model_name(self, value): + """ + + :type value: str + """ + self._cloudshell_model_name = value + + @property + def model_name(self): + """ + :rtype: str + """ + return self.attributes['CS_Port.Model Name'] if 'CS_Port.Model Name' in self.attributes else None + + @model_name.setter + def model_name(self, value=''): + """ + The catalog name of the device model. This attribute will be displayed in CloudShell instead of the CloudShell model. + :type value: str + """ + self.attributes['CS_Port.Model Name'] = value + + +class GenericPowerPort(object): + def __init__(self, name): + """ + + """ + self.attributes = {} + self.resources = {} + self._cloudshell_model_name = 'Lanforge Resource.GenericPowerPort' + self._name = name + + def add_sub_resource(self, relative_path, sub_resource): + self.resources[relative_path] = sub_resource + + @classmethod + def create_from_context(cls, context): + """ + Creates an instance of NXOS by given context + :param context: cloudshell.shell.core.driver_context.ResourceCommandContext + :type context: cloudshell.shell.core.driver_context.ResourceCommandContext + :return: + :rtype GenericPowerPort + """ + result = GenericPowerPort(name=context.resource.name) + for attr in context.resource.attributes: + result.attributes[attr] = context.resource.attributes[attr] + return result + + def create_autoload_details(self, relative_path=''): + """ + :param relative_path: + :type relative_path: str + :return + """ + resources = [AutoLoadResource(model=self.resources[r].cloudshell_model_name, + name=self.resources[r].name, + relative_address=self._get_relative_path(r, relative_path)) + for r in self.resources] + attributes = [AutoLoadAttribute(relative_path, a, self.attributes[a]) for a in self.attributes] + autoload_details = AutoLoadDetails(resources, attributes) + for r in self.resources: + curr_path = relative_path + '/' + r if relative_path else r + curr_auto_load_details = self.resources[r].create_autoload_details(curr_path) + autoload_details = self._merge_autoload_details(autoload_details, curr_auto_load_details) + return autoload_details + + def _get_relative_path(self, child_path, parent_path): + """ + Combines relative path + :param child_path: Path of a model within it parent model, i.e 1 + :type child_path: str + :param parent_path: Full path of parent model, i.e 1/1. Might be empty for root model + :type parent_path: str + :return: Combined path + :rtype str + """ + return parent_path + '/' + child_path if parent_path else child_path + + @staticmethod + def _merge_autoload_details(autoload_details1, autoload_details2): + """ + Merges two instances of AutoLoadDetails into the first one + :param autoload_details1: + :type autoload_details1: AutoLoadDetails + :param autoload_details2: + :type autoload_details2: AutoLoadDetails + :return: + :rtype AutoLoadDetails + """ + for attribute in autoload_details2.attributes: + autoload_details1.attributes.append(attribute) + for resource in autoload_details2.resources: + autoload_details1.resources.append(resource) + return autoload_details1 + + @property + def cloudshell_model_name(self): + """ + Returns the name of the Cloudshell model + :return: + """ + return 'GenericPowerPort' + + @property + def model(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.GenericPowerPort.Model'] if 'Lanforge Resource.GenericPowerPort.Model' in self.attributes else None + + @model.setter + def model(self, value): + """ + The device model. This information is typically used for abstract resource filtering. + :type value: str + """ + self.attributes['Lanforge Resource.GenericPowerPort.Model'] = value + + @property + def serial_number(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.GenericPowerPort.Serial Number'] if 'Lanforge Resource.GenericPowerPort.Serial Number' in self.attributes else None + + @serial_number.setter + def serial_number(self, value): + """ + + :type value: str + """ + self.attributes['Lanforge Resource.GenericPowerPort.Serial Number'] = value + + @property + def version(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.GenericPowerPort.Version'] if 'Lanforge Resource.GenericPowerPort.Version' in self.attributes else None + + @version.setter + def version(self, value): + """ + The firmware version of the resource. + :type value: str + """ + self.attributes['Lanforge Resource.GenericPowerPort.Version'] = value + + @property + def port_description(self): + """ + :rtype: str + """ + return self.attributes['Lanforge Resource.GenericPowerPort.Port Description'] if 'Lanforge Resource.GenericPowerPort.Port Description' in self.attributes else None + + @port_description.setter + def port_description(self, value): + """ + The description of the port as configured in the device. + :type value: str + """ + self.attributes['Lanforge Resource.GenericPowerPort.Port Description'] = value + + @property + def name(self): + """ + :rtype: str + """ + return self._name + + @name.setter + def name(self, value): + """ + + :type value: str + """ + self._name = value + + @property + def cloudshell_model_name(self): + """ + :rtype: str + """ + return self._cloudshell_model_name + + @cloudshell_model_name.setter + def cloudshell_model_name(self, value): + """ + + :type value: str + """ + self._cloudshell_model_name = value + + @property + def model_name(self): + """ + :rtype: str + """ + return self.attributes['CS_PowerPort.Model Name'] if 'CS_PowerPort.Model Name' in self.attributes else None + + @model_name.setter + def model_name(self, value=''): + """ + The catalog name of the device model. This attribute will be displayed in CloudShell instead of the CloudShell model. + :type value: str + """ + self.attributes['CS_PowerPort.Model Name'] = value + + + diff --git a/Quali/lanforge_resource/src/driver.py b/Quali/lanforge_resource/src/driver.py new file mode 100755 index 00000000..a081a4f3 --- /dev/null +++ b/Quali/lanforge_resource/src/driver.py @@ -0,0 +1,379 @@ +from cloudshell.shell.core.resource_driver_interface import ResourceDriverInterface +from cloudshell.shell.core.driver_context import InitCommandContext, ResourceCommandContext, AutoLoadResource, \ + AutoLoadAttribute, AutoLoadDetails, CancellationContext +from cloudshell.shell.core.session.cloudshell_session import CloudShellSessionContext +from cloudshell.api.cloudshell_api import CloudShellAPISession +from cloudshell.helpers.scripts.cloudshell_scripts_helpers import get_api_session, get_reservation_context_details +from cloudshell.shell.core.session.cloudshell_session import CloudShellSessionContext +import cloudshell.helpers.scripts.cloudshell_scripts_helpers as script_help +import cloudshell.helpers.scripts.cloudshell_dev_helpers as dev_helpers +# from cloudshell.shell.core.resource_driver_interface import ResourceDriverInterface +# from cloudshell.shell.core.context import InitCommandContext, ResourceCommandContext +import mock +from data_model import * +# run 'shellfoundry generate' to generate data model classes +import subprocess +import sys +import os +import importlib +import paramiko +from scp import SCPClient +import requests +import datetime +import os + +# command = "./lanforge-scripts/py-scripts/update_dependencies.py" +# print("running:[{}]".format(command)) +# process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) +# outs, errs = process.communicate() +# print(outs) +# print(errs) + +# if 'lanforge-scripts' not in sys.path: +# sys.path.append('./lanforge-scripts') + +# create_wanlink = importlib.import_module("lanforge-scripts.py-json.create_wanlink") +# create_l3 = importlib.import_module("lanforge-scripts.py-scripts.create_l3") +# CreateL3 = create_l3.CreateL3 +class LanforgeResourceDriver (ResourceDriverInterface): + + def __init__(self): + """ + ctor must be without arguments, it is created with reflection at run time + """ + pass + + def initialize(self, context): + """ + Initialize the driver session, this function is called everytime a new instance of the driver is created + This is a good place to load and cache the driver configuration, initiate sessions etc. + :param InitCommandContext context: the context the command runs on + """ + pass + + def cleanup(self): + """ + Destroy the driver session, this function is called everytime a driver instance is destroyed + This is a good place to close any open sessions, finish writing to log files + """ + pass + + def get_inventory(self, context): + """ + Discovers the resource structure and attributes. + :param AutoLoadCommandContext context: the context the command runs on + :return Attribute and sub-resource information for the Shell resource you can return an AutoLoadDetails object + :rtype: AutoLoadDetails + """ + # See below some example code demonstrating how to return the resource structure and attributes + # In real life, this code will be preceded by SNMP/other calls to the resource details and will not be static + # run 'shellfoundry generate' in order to create classes that represent your data model + + ''' + resource = LanforgeResource.create_from_context(context) + resource.vendor = 'specify the shell vendor' + resource.model = 'specify the shell model' + + port1 = ResourcePort('Port 1') + port1.ipv4_address = '192.168.10.7' + resource.add_sub_resource('1', port1) + + return resource.create_autoload_details() + ''' + return AutoLoadDetails([], []) + + def orchestration_save(self, context, cancellation_context, mode, custom_params): + """ + Saves the Shell state and returns a description of the saved artifacts and information + This command is intended for API use only by sandbox orchestration scripts to implement + a save and restore workflow + :param ResourceCommandContext context: the context object containing resource and reservation info + :param CancellationContext cancellation_context: Object to signal a request for cancellation. Must be enabled in drivermetadata.xml as well + :param str mode: Snapshot save mode, can be one of two values 'shallow' (default) or 'deep' + :param str custom_params: Set of custom parameters for the save operation + :return: SavedResults serialized as JSON + :rtype: OrchestrationSaveResult + """ + + # See below an example implementation, here we use jsonpickle for serialization, + # to use this sample, you'll need to add jsonpickle to your requirements.txt file + # The JSON schema is defined at: + # https://github.com/QualiSystems/sandbox_orchestration_standard/blob/master/save%20%26%20restore/saved_artifact_info.schema.json + # You can find more information and examples examples in the spec document at + # https://github.com/QualiSystems/sandbox_orchestration_standard/blob/master/save%20%26%20restore/save%20%26%20restore%20standard.md + ''' + # By convention, all dates should be UTC + created_date = datetime.datetime.utcnow() + + # This can be any unique identifier which can later be used to retrieve the artifact + # such as filepath etc. + + # By convention, all dates should be UTC + created_date = datetime.datetime.utcnow() + + # This can be any unique identifier which can later be used to retrieve the artifact + # such as filepath etc. + identifier = created_date.strftime('%y_%m_%d %H_%M_%S_%f') + + orchestration_saved_artifact = OrchestrationSavedArtifact('REPLACE_WITH_ARTIFACT_TYPE', identifier) + + saved_artifacts_info = OrchestrationSavedArtifactInfo( + resource_name="some_resource", + created_date=created_date, + restore_rules=OrchestrationRestoreRules(requires_same_resource=True), + saved_artifact=orchestration_saved_artifact) + + return OrchestrationSaveResult(saved_artifacts_info) + ''' + pass + + def orchestration_restore(self, context, cancellation_context, saved_artifact_info, custom_params): + """ + Restores a saved artifact previously saved by this Shell driver using the orchestration_save function + :param ResourceCommandContext context: The context object for the command with resource and reservation info + :param CancellationContext cancellation_context: Object to signal a request for cancellation. Must be enabled in drivermetadata.xml as well + :param str saved_artifact_info: A JSON string representing the state to restore including saved artifacts and info + :param str custom_params: Set of custom parameters for the restore operation + :return: None + """ + ''' + # The saved_details JSON will be defined according to the JSON Schema and is the same object returned via the + # orchestration save function. + # Example input: + # { + # "saved_artifact": { + # "artifact_type": "REPLACE_WITH_ARTIFACT_TYPE", + # "identifier": "16_08_09 11_21_35_657000" + # }, + # "resource_name": "some_resource", + # "restore_rules": { + # "requires_same_resource": true + # }, + # "created_date": "2016-08-09T11:21:35.657000" + # } + + # The example code below just parses and prints the saved artifact identifier + saved_details_object = json.loads(saved_details) + return saved_details_object[u'saved_artifact'][u'identifier'] + ''' + pass + + def attach_file(self, report_server, resid, file_path, user, password, domain, filename): + + # st = datetime.datetime.fromtimestamp(ts).strftime('%Y%m%d%H%M%S') + data = { + 'username': user, + 'password': password, + 'domain': domain + } + qq = 'Basic ' + requests.put( + url='http://' + report_server + ':9000/API/Auth/Login', + data=data + ).text[1:-1] + head = { + 'Authorization': qq, + } + dat_json ={ + "reservationId": resid, + "saveFileAs": filename, + "overwriteIfExists": "true", + } + + with open(file_path, 'rb') as upload_file: + xx = requests.post( + url='http://' + report_server + ':9000/API/Package/AttachFileToReservation', + headers=head, + data=dat_json, + files={'QualiPackage': upload_file} + ) + return xx + + def send_command(self, context, cmd): + + msg = "" + resource = LanforgeResource.create_from_context(context) + session = CloudShellAPISession(host=context.connectivity.server_address, + token_id=context.connectivity.admin_auth_token, + domain=context.reservation.domain) + resource_model_name = resource.cloudshell_model_name + terminal_ip = context.resource.address + terminal_user = context.resource.attributes[f'{resource_model_name}.User'] + terminal_pass = session.DecryptPassword(context.resource.attributes[f'{resource_model_name}.Password']).Value + + msg += f"Initializing SSH connection to {terminal_ip}, with user {terminal_user} and password {terminal_pass}\n" + s = paramiko.SSHClient() + s.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + s.connect(hostname=terminal_ip, username=terminal_user, password=terminal_pass) + + print(f"running:[{cmd}]") + (stdin, stdout, stderr) = s.exec_command(cmd) + + output = '' + errors = '' + for line in stdout.readlines(): + output += line + for line in stderr.readlines(): + errors += line + msg += output + errors + s.close() + return msg + + def example_command(self, context): + """ + this is my example command + :param ResourceCommandContext context + :return: str + """ + resource = LanforgeResource.create_from_context(context) + session = CloudShellAPISession(host=context.connectivity.server_address, + token_id=context.connectivity.admin_auth_token, + domain=context.reservation.domain) + + resource_model_name = resource.cloudshell_model_name + password = session.DecryptPassword(context.resource.attributes[f'{resource_model_name}.Password']).Value + username = context.resource.attributes[f'{resource_model_name}.User'] + + msg = f"My resource {resource.name} at address {context.resource.address} has model name {resource_model_name}. " + msg += f"The username is {username} and password is {password}." + return msg + + + def create_wanlink(self, context, name, latency, rate): + + cmd = "/home/lanforge/lanforge-scripts/py-json/create_wanlink.py --host {host} --port_A {port_A} --port_B {port_B} --name \"{name}\" --latency \"{latency}\" --latency_A \"{latency_A}\" --latency_B \"{latency_B}\" --rate {rate} --rate_A {rate_A} --rate_B {rate_B} --jitter {jitter} --jitter_A {jitter_A} --jitter_B {jitter_B} --jitter_freq_A {jitter_freq_A} --jitter_freq_B {jitter_freq_B} --drop_A {drop_A} --drop_B {drop_B}".format( + host="localhost", + port_A="eth1", + port_B="eth2", + name=name, + latency=latency, + latency_A=latency, + latency_B=latency, + rate=rate, + rate_A=rate, + rate_B=rate, + jitter="0", + jitter_A="0", + jitter_B="0", + jitter_freq_A="0", + jitter_freq_B="0", + drop_A="0", + drop_B="0" + ) + + output = self.send_command(context, cmd) + print(output) + return output + + def create_l3(self, context, name, min_rate_a, min_rate_b, endp_a, endp_b): + + cmd = f"/home/lanforge/lanforge-scripts/py-scripts/create_l3.py --endp_a \"{endp_a}\" --endp_b \"{endp_b}\" --min_rate_a \"{min_rate_a}\" --min_rate_b \"{min_rate_b}\"" + + output = self.send_command(context, cmd) + print(output) + return output + + def pull_reports(self, hostname="", port=22, + username="lanforge", password="lanforge", + report_location="/home/lanforge/html-reports/", + report_dir="./"): + + ssh = paramiko.SSHClient() + ssh.load_system_host_keys() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect(hostname="juicer", username=username, password=password, port=port, allow_agent=False, look_for_keys=False) + + with SCPClient(ssh.get_transport()) as scp: + scp.get(remote_path=report_location, local_path=report_dir, recursive=True) + scp.close() + + def dataplane_test(self, context, instance_name, upstream, station, duration, download_speed, upload_speed, traffic_types, local_lf_report_dir, output_report_dir, mgr): + + cmd = '''/home/lanforge/lanforge-scripts/py-scripts/lf_dataplane_test.py --mgr {mgr} --port 8080 --lf_user lanforge --lf_password lanforge \ + --instance_name {instance_name} --config_name test_con \ + --upstream {upstream} --station {station} --duration {duration}\ + --download_speed {download_speed} --upload_speed {upload_speed} \ + --raw_line 'pkts: 256;1024' \ + --raw_line 'directions: DUT Transmit' \ + --raw_line 'traffic_types: {traffic_types}' \ + --test_rig juicer --pull_report \ + --local_lf_report_dir {local_lf_report_dir}'''.format( + instance_name=instance_name, + mgr=mgr, + upstream=upstream, + station=station, + duration=duration, + download_speed=download_speed, + upload_speed=upload_speed, + traffic_types=traffic_types, + local_lf_report_dir=local_lf_report_dir + ) + + output = self.send_command(context, cmd) + print(output) + + resource = LanforgeResource.create_from_context(context) + session = CloudShellAPISession(host=context.connectivity.server_address, + token_id=context.connectivity.admin_auth_token, + domain=context.reservation.domain) + terminal_ip = context.resource.address + resource_model_name = resource.cloudshell_model_name + terminal_pass = session.DecryptPassword(context.resource.attributes[f'{resource_model_name}.Password']).Value + terminal_user = context.resource.attributes[f'{resource_model_name}.User'] + reservation_id = context.reservation.reservation_id + api = CloudShellSessionContext(context).get_api() + cwd = os.getcwd() + # session.AttachFileToReservation(context.reservation.reservation_id, f"C:/Users/Administrator/{output_report_dir}", "C:/Users/Administrator/AppData/Local/Temp", True) + self.pull_reports(hostname=context.resource.address, port=22, + username=terminal_user, password=terminal_pass, + report_location="/home/lanforge/html-reports/", + report_dir=f"C:/Users/Administrator/{output_report_dir}") + + # api = get_api_session() + # api.WriteMessageToReservationOutput(reservation_id, f"Attaching report to sandbox.") + api.WriteMessageToReservationOutput(reservation_id, f"The current working directory is {cwd}") + self.attach_file( + report_server=context.connectivity.server_address, + resid=context.reservation.reservation_id, + user='admin', + password='admin', + domain=context.reservation.domain, + file_path="C:/Users/Administrator/Desktop/My_Reports/html-reports/dataplane-2021-10-13-03-32-40/dataplane-report-2021-10-13-03-31-50.pdf", + filename="C:/Users/Administrator/Desktop/test_report.txt" + ) + return output + + def scenario(self, context, load): + cmd = f"/home/lanforge/lanforge-scripts/py-scripts/scenario.py --load {load}" + + output = self.send_command(context, cmd) + print(output) + return output + +if __name__ == "__main__": + # setup for mock-debug environment + shell_name = "LanforgeResource" + cancellation_context = mock.create_autospec(CancellationContext) + context = mock.create_autospec(ResourceCommandContext) + context.resource = mock.MagicMock() + context.reservation = mock.MagicMock() + context.connectivity = mock.MagicMock() + context.reservation.reservation_id = "" + context.resource.address = "192.168.100.176" + context.resource.name = "Lanforge_Resource" + context.resource.attributes = dict() + context.resource.attributes["{}.User".format(shell_name)] = "lanforge" + context.resource.attributes["{}.Password".format(shell_name)] = "lanforge" + context.resource.attributes["{}.SNMP Read Community".format(shell_name)] = "" + + # add information for api connectivity + context.reservation.domain = "Global" + context.connectivity.server_address = "192.168.100.131" + driver = LanforgeResourceDriver() + # print driver.run_custom_command(context, custom_command="sh run", cancellation_context=cancellation_context) + # result = driver.example_command_with_api(context) + + # driver.create_l3(context, "my_fire", "69000", "41000", "eth1", "eth2") + # driver.create_wanlink(context, name="my_wanlin", latency="49", rate="6000") + driver.dataplane_test(context, "instance", "upstream", "station", "duration") + print("done") + diff --git a/Quali/lanforge_resource/src/drivermetadata.xml b/Quali/lanforge_resource/src/drivermetadata.xml new file mode 100644 index 00000000..39632850 --- /dev/null +++ b/Quali/lanforge_resource/src/drivermetadata.xml @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Quali/lanforge_resource/src/importlib b/Quali/lanforge_resource/src/importlib new file mode 100644 index 00000000..e69de29b diff --git a/Quali/lanforge_resource/src/requirements.txt b/Quali/lanforge_resource/src/requirements.txt new file mode 100644 index 00000000..22ab2921 --- /dev/null +++ b/Quali/lanforge_resource/src/requirements.txt @@ -0,0 +1,7 @@ +mock +cloudshell-shell-core>=5.0.3,<6.0.0 +cloudshell-automation-api +cloudshell-orch-core +requests +paramiko +scp diff --git a/Quali/lanforge_resource/src/sys b/Quali/lanforge_resource/src/sys new file mode 100644 index 00000000..e69de29b diff --git a/Quali/lanforge_resource/test_requirements.txt b/Quali/lanforge_resource/test_requirements.txt new file mode 100644 index 00000000..7d963ba7 --- /dev/null +++ b/Quali/lanforge_resource/test_requirements.txt @@ -0,0 +1,7 @@ +nose +coverage +unittest2 +mock +teamcity-messages +jsonpickle +nose-exclude \ No newline at end of file diff --git a/Quali/lanforge_resource/tests/__init__.py b/Quali/lanforge_resource/tests/__init__.py new file mode 100644 index 00000000..40a96afc --- /dev/null +++ b/Quali/lanforge_resource/tests/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/Quali/lanforge_resource/tests/test_lanforge-resource.py b/Quali/lanforge_resource/tests/test_lanforge-resource.py new file mode 100644 index 00000000..de11d725 --- /dev/null +++ b/Quali/lanforge_resource/tests/test_lanforge-resource.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Tests for `LanforgeResourceDriver` +""" + +import unittest + +from driver import LanforgeResourceDriver + + +class TestLanforgeResourceDriver(unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_000_something(self): + pass + + +if __name__ == '__main__': + import sys + sys.exit(unittest.main()) diff --git a/check_large_files.bash b/check_large_files.bash index 888f6695..bdf83b60 100755 --- a/check_large_files.bash +++ b/check_large_files.bash @@ -339,6 +339,14 @@ clean_old_kernels() { echo "/lib/modules/$f" done | xargs rm -rf fi + if [ -d "/boot2" ]; then + rm -rf /boot2/* + rsync -a /boot/. /boot2/ + local dev2=`df /boot2/ |awk '/dev/{print $1}'` + if [ x$dev2 != x ]; then + /usr/sbin/grub2-install $dev2 ||: + fi + fi } clean_core_files() { @@ -348,7 +356,7 @@ clean_core_files() { return 0 fi - local counter=0 + local counter=0 if [ ! -f "$lf_core_log" ]; then touch "$lf_core_log" fi diff --git a/desktop-hostname.bash b/desktop-hostname.bash new file mode 100755 index 00000000..4cbf2397 --- /dev/null +++ b/desktop-hostname.bash @@ -0,0 +1,44 @@ +#!/bin/bash +Q='"' +A="'" +function set_background() { + gsettings set "org.mate.background" "$1" "$2" +} + +SourceFile="/usr/share/backgrounds/mate/desktop/Ubuntu-Mate-Cold-no-logo.png" +DesktopFile="/home/lanforge/desktop.png" +my_hostname=`hostname` +my_os="[os]" +if [ -f /etc/os-release ]; then + my_os=`egrep '^VERSION=' /etc/os-release` + if [ ! -z "$my_os" ]; then + my_os="${my_os/VERSION=/}" + my_os="${my_os//\"/}" + fi +fi + +my_inver="[lfver]" +if [ -f "/var/www/html/installed-ver.txt" ]; then + my_inver=`cat /var/www/html/installed-ver.txt`; +fi +my_kver=`uname -r` +my_dev=`ip ro sho | awk '/default via/{print $5}'` +my_ip=`ip a sho $my_dev | awk '/inet /{print $2}'` +my_mac=`ip a sho | grep -A1 "$my_dev" | awk '/ether /{print $2}'` +fill_color=${my_mac//:/} +fill_color=${fill_color:6:12} +X=220 +Y=150 +convert -pointsize 80 -fill "#$fill_color" -stroke black -strokewidth 1 \ + -draw "text $X,$Y \"$my_hostname\"" \ + -draw "text $X,$(( Y + 75 )) \"LANForge $my_inver\"" \ + -draw "text $X,$(( Y + 155 )) \"Kernel $my_kver $my_os\"" \ + -draw "text $X,$(( Y + 225 )) \"$my_dev $my_ip\"" \ + -draw "text $X,$(( Y + 295 )) \"$my_mac\"" \ + $SourceFile \ + -scale 1600x900 \ + $DesktopFile + +set_background picture-filename ${A}${DesktopFile}${A} +set_background picture-options 'stretched' +# diff --git a/lanforge_client/__init__.py b/lanforge_client/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/py-json/LANforge/lf_json_autogen.py b/lanforge_client/lanforge_api.py similarity index 61% rename from py-json/LANforge/lf_json_autogen.py rename to lanforge_client/lanforge_api.py index 7d3cb307..be1d6d46 100644 --- a/py-json/LANforge/lf_json_autogen.py +++ b/lanforge_client/lanforge_api.py @@ -1,67 +1,827 @@ #!/usr/bin/env python3 """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Generated by LANforge JsonApiPythonGenerator, Mon Sep 13 15:28:41 PDT 2021 - - - WORK IN PROGRESS - - - The API this library provides is actively being changed. - This file expects to live in py-json/LANforge directory. + + LANforge-GUI Source Code + Copyright (C) 1999-2021 Candela Technologies Inc + http:www.candelatech.com + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Contact: Candela Technologies if you have any + questions. + + LANforge JSON API + + A distinct difference from previous LF scripts is the notion of a session. + Please create a session instance before connecting to your LANforge client. + The session is informative for a GUI user how many scripts are actively + using the GUI. It also provides logging to diagnose how many scripts are + potentially accessing the GUI at the same time. + + EXAMPLE PYTHON USAGE: + ----- ----- ----- 8< ----- ----- ----- 8< ----- ----- ----- + session = LFSession(lfclient_url="http://localhost:8080", + connect_timeout_sec=20, + proxy_map={ + 'http':'http://192.168.1.250:3128' + }, + debug=True, + die_on_error=False); + lf_command = session.get_command() + full_response = [] + first_response = lf_command.json_post( url="/nc_show_ports", + post_data={ + "shelf": 1, + "resource": 1, + "ports": "all" + }, + full_response) + pprint(first_response) + + lf_query = session.get_query() + response = lf_query.get_as_json(url="/port/1/1/list", + debug=True) + pprint(response) + ----- ----- ----- 8< ----- ----- ----- 8< ----- ----- ----- + + The API that this library provides is ACTIVELY BEING CHANGED. + + MAINTENANCE: + To maintain this library, please refer to these files: + * client/candela/lanforge/json_api.py + - the basis for many of the auto-generated python classes + that follow after these class definitions. + * client/candela/lanforge/JsonApiPythonGenerator.java + - the builder class that produces lf_json_autogen + The file json_api.py is intended to be bundled in lfclient.jar and + not to be extracted. It is sourced during build by the JsonApiPythonGenerator + class which appends subclasses to it. + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + import sys -import os -import importlib -from enum import Enum -from enum import IntFlag if sys.version_info[0] != 3: print("This script requires Python 3") exit() - -sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../../"))) +from datetime import datetime +from enum import Enum +from enum import IntFlag +import http.client +from http.client import HTTPResponse +import json +import logging +from logging import Logger +from .logg import Logg +from .strutil import nott, iss +from pprint import pprint, pformat +import time +import traceback +from typing import Optional +import urllib +from urllib import request, error, parse -lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") -LFCliBase = lfcli_base.LFCliBase +SESSION_HEADER = 'X-LFJson-Session' +LOGGER = Logger('json_api') -class LFJsonGet(LFCliBase): - def __init__(self, lfclient_host='localhost', - lfclient_port=8080, - debug_=False, - _exit_on_error=False, - _exit_on_fail=False, - _proxy_str=None, - _capture_signal_list=()): - super().__init__(_lfjson_host=lfclient_host, - _lfjson_port=lfclient_port, - _debug=debug_, - _exit_on_error=_exit_on_error, - _exit_on_fail=_exit_on_fail, - _proxy_str=_proxy_str, - _capture_signal_list=_capture_signal_list) +def _now_ms() -> int: + return round(time.time() * 1000) - @staticmethod - def extract_values(response: dict = None, + +def _now_sec() -> int: + return round(time.time() * 1000 * 1000) + + +def default_proxies() -> dict: + return { + # 'http': 'http://example.com', + # 'https': 'https://example.com' + } + + +def print_diagnostics(url_: str = None, + request_: urllib.request.Request = None, + responses_: list = None, + error_=None, + error_list_: list = None, + debug_: bool = False, + die_on_error_: bool = False): + if debug_: + print("::print_diagnostics: error_.__class__: %s" % error_.__class__) + pprint(error_) + + if url_ is None: + print("WARNING:print_diagnostics: url_ is None") + if request_ is None: + print("WARNING:print_diagnostics: request_ is None") + if error_ is None: + print("WARNING:print_diagnostics: error_ is None") + + method = 'NA' + if hasattr(request_, 'method'): + method = request_.method + err_code = 0 + err_reason = 'NA' + err_headers = [] + err_full_url = url_ + if hasattr(error_, 'code'): + err_code = error_.code + if hasattr(error_, 'reason'): + err_reason = error_.reason + if hasattr(error_, 'headers'): + err_headers = error_.headers + if hasattr(error_, 'get_full_url'): + err_full_url = error_.get_full_url() + xerrors = [] + if err_code == 404: + xerrors.append("[%s HTTP %s] <%s> : %s" % (method, err_code, err_full_url, err_reason)) + else: + if len(err_headers) > 0: + for headername in sorted(err_headers.keys()): + if headername.startswith("X-Error-"): + xerrors.append("%s: %s" % (headername, err_headers.get(headername))) + if len(xerrors) > 0: + print(" = = LANforge Error Messages = =") + print(" = = URL: %s" % err_full_url) + for xerr in xerrors: + print(xerr) + if (error_list_ is not None) and isinstance(error_list_, list): + error_list_.append(xerr) + print(" = = = = = = = = = = = = = = = =") + + if error_.__class__ is urllib.error.HTTPError: + if debug_: + print("----- HTTPError: ------------------------------------ print_diagnostics:") + print("%s <%s> HTTP %s: %s" % (method, err_full_url, err_code, err_reason)) + + if err_code == 404: + if (error_list_ is not None) and isinstance(error_list_, list): + error_list_.append("[%s HTTP %s] <%s> : %s" % (method, err_code, err_full_url, err_reason)) + else: + if debug_: + print(" Content-type:[%s] Accept[%s]" % ( + request_.get_header('Content-type'), request_.get_header('Accept'))) + + if hasattr(request_, "data") and (request_.data is not None): + print(" Data:") + pprint(request_.data) + elif debug_: + print(" ") + + if debug_ and (len(err_headers) > 0): + # the HTTPError is of type HTTPMessage a subclass of email.message + print(" Response Headers: ") + for headername in sorted(err_headers.keys()): + print(" %s: %s" % (headername, err_headers.get(headername))) + + if len(responses_) > 0: + print("----- Response: --------------------------------------------------------") + pprint(responses_[0].reason) + if debug_: + print("------------------------------------------------------------------------") + if die_on_error_: + exit(1) + return + + if error_.__class__ is urllib.error.URLError: + print("----- URLError: ---------------------------------------------") + print("%s <%s> HTTP %s: %s" % (method, err_full_url, err_code, err_reason)) + print("------------------------------------------------------------------------") + if die_on_error_: + exit(1) + + +class BaseLFJsonRequest: + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Perform HTTP get/post/put/delete with extensions specific to LANforge JSON + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + No_Data: dict = {'No Data': 0} + OK_STATUSES = (100, 200, 201, 204, 205, 206, 301, 302, 303, 304, 307, 308, 404) + subclasses = [] + + def __init_subclass__(cls, **kwargs): + super().__init_subclass__(**kwargs) + cls.subclasses.append(cls) + + def __init__(self, + session_obj: 'BaseSession' = None, + debug: bool = False, + stream_errors: bool = True, + stream_warnings: bool = False, + exit_on_error: bool = False): + self.default_headers: dict = {'Accept': 'application/json'} + self.debug_on: bool = False + self.error_list: list = [] + # post_data: dict = No_Data + self.proxies_installed: bool = False + self.session_instance: 'BaseSession' + self.session_instance = None + self.stream_errors: bool = True + self.stream_warnings: bool = False + + if not session_obj: + logging.getLogger(__name__).warning("BaseLFJsonRequest: no session instance") + else: + self.session_instance = session_obj + self.session_id = session_obj.get_session_id() + self.proxies_installed = session_obj.proxies_installed + + self.die_on_error: bool + self.die_on_error = exit_on_error + if session_obj: + self.die_on_error |= session_obj.is_exit_on_error() + + self.lfclient_url = session_obj.get_lfclient_url() + + self.stream_errors = stream_errors + self.warnings = [] + self.stream_warnings = stream_warnings + self.logger = Logg(name="LFJsonRequest-@", debug=debug) + self.debug_on = debug + + def get_corrected_url(self, + url: str = None, + debug: bool = False): + """ + + :param url: If you have a session you can provide the abbreviated URL optionally starting with a slash + :param debug: turn on debugging + :return: full url prepended with + """ + + if nott(url): + raise Exception("%s: Bad url[%s]" % (__name__, url)) + + corrected_url: str = url + + if not url.startswith(self.session_instance.get_lfclient_url()): + if url.startswith('/'): + corrected_url = self.session_instance.get_lfclient_url() + url + else: + corrected_url = self.session_instance.get_lfclient_url() + '/' + url + + if nott(corrected_url): + raise Exception("%s: Bad url[%s]" % (__name__, url)) + + if corrected_url.find('//'): + protopos = corrected_url.find("://") + corrected_url = corrected_url[:protopos + 2] + corrected_url[protopos + 2:].replace("//", "/") + + # finding '#' prolly indicates a macvlan (eth1#0) + # finding ' ' prolly indicates a field name that should imply %20 + if corrected_url.find('#') >= 1: + corrected_url = corrected_url.replace('#', '%23') + if corrected_url.find(' ') >= 1: + corrected_url = corrected_url.replace(' ', '%20') + if debug: + self.logger.by_method("%s: url [%s] now [%s]" % (str(__class__), url, corrected_url)) + return corrected_url + + def add_error(self, message: str = None): + if not message: + return + if self.stream_errors: + self.logger.error(message=message) + self.error_list.append(message) + + def add_warning(self, message: str = None): + self.logger.warning(message) + if self.stream_errors: + self.logger.warning(message=message) + self.warnings.append(message) + + def get_errors(self) -> list: + return self.error_list + + def get_warnings(self) -> list: + return self.warnings + + def clear_warnings_errors(self, flush_to_session=False): + """ erase errors and warnings """ + if flush_to_session: + if not self.session_instance: + self.logger.error(message="cannot flush messages to session when there is no session instance") + else: + self.session_instance.session_error_list.extend(self.error_list) + self.session_instance.session_warnings_list.extend(self.warnings) + self.error_list = [] + self.warnings = [] + self.logger.info(message='BaseLFJsonRequest.clear()') + + def extract_values(self, + response: dict = None, singular_key: str = None, plural_key: str = None) -> list: """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Extract fields from this response using the expected keys: ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - if (singular_key is None) or (plural_key is None) or (not singular_key) or (not plural_key): - raise ValueError("extract_values wants non-empty response, singular_key and plural_key") - if (singular_key in response) and (not response[singular_key]): - return [] - elif (singular_key in response) and (type(response[singular_key]) is dict): - return [response[singular_key]] - elif (plural_key in response) and (not response[plural_key]): - return [] - else: - return response[plural_key] + if not singular_key: + raise ValueError("extract_values wants non-empty singular_key") + if not plural_key: + raise ValueError("extract_values wants non-empty plural_key") + + if singular_key not in response: + if plural_key not in response: + self.add_warning("response did not contain <{}> or <{}>".format(singular_key, plural_key)) + return [] + if not response[plural_key]: + self.add_warning("response[{}] is empty".format(plural_key)) + return response[plural_key] + if not response[singular_key]: + self.add_warning("response[{}] is empty".format(singular_key)) + return response[singular_key] + + def form_post(self, + url: str = None, + post_data: dict = None, + debug: bool = False, + die_on_error_: bool = False): + die_on_error_ |= self.die_on_error + debug |= self.debug_on + responses = [] + # https://stackoverflow.com/a/59635684/11014343 + if (self.session_instance.proxy_map is not None) and (len(self.session_instance.proxy_map) > 0): + # https://stackoverflow.com/a/59635684/11014343 + opener = request.build_opener(request.ProxyHandler(self.session_instance.proxy_map)) + request.install_opener(opener) + + # if debug: + self.logger.by_method("form_post: url: " + url) + if (post_data is not None) and (post_data is not self.No_Data): + urlenc_data = urllib.parse.urlencode(post_data).encode("utf-8") + self.logger.by_method("formPost: data looks like:" + str(urlenc_data)) + if debug: + print("formPost: url: " + url) + myrequest = request.Request(url=url, + data=urlenc_data, + headers=self.default_headers) + else: + myrequest = request.Request(url=url, headers=self.default_headers) + self.logger.by_method("json_post: No data sent to [%s]" % url) + + myrequest.headers['Content-type'] = 'application/x-www-form-urlencoded' + + try: + resp = urllib.request.urlopen(myrequest) + responses.append(resp) + return responses[0] + + except urllib.error.HTTPError as herror: + print_diagnostics(url_=url, + request_=myrequest, + responses_=responses, + error_=herror, + error_list_=self.error_list, + debug_=debug, + die_on_error_=die_on_error_) + if die_on_error_ and (herror.code != 404): + exit(1) + except urllib.error.URLError as uerror: + print_diagnostics(url_=url, + request_=myrequest, + responses_=responses, + error_=uerror, + error_list_=self.error_list, + debug_=debug, + die_on_error_=die_on_error_) + if die_on_error_: + exit(1) + if die_on_error_: + exit(1) + return None + + def json_post(self, + url: str = "", + post_data: dict = None, + debug: bool = False, + wait_sec: float = None, + connection_timeout_sec: float = None, + max_timeout_sec: float = None, + die_on_error: bool = False, + errors_warnings: list = None, # p3.9 list[str] + response_json_list: list = None, + method_: str = 'POST', + session_id_: str = "") -> Optional: # p3.9 Optional[HTTPResponse] + """ + + :param url: URL to post to + :param post_data: data to send in post + :param debug: turn on diagnostics + :param wait_sec: pause before making request + :param connection_timeout_sec: immediate connection timeout + :param max_timeout_sec: retry for this many seconds before returning + :param errors_warnings: list to collect errors and warnings with + :param die_on_error: exit() if the return status is not 200 + :param response_json_list: pass in a list to store json data in the response + :param method_: override HTTP method, please do not override + :param session_id_: insert a session to the header; this is useful in the case where we are + operating outside a session context, like during the __del__ constructor + :return: returns first set of http.client.HTTPResponse data + """ + debug |= self.debug_on + die_on_error |= self.die_on_error + + if self.session_id != self.session_instance.get_session_id(): + self.logger.error("BaseLFJsonRequest.session_id[%s] != session.get_session_id: [%s]" + % (self.session_id, self.session_instance.get_session_id())) + if die_on_error: + exit(1) + responses: list = [] # p3.9 list[HTTPResponse] + url = self.get_corrected_url(url) + self.logger.by_method("url: "+url) + if (post_data is not None) and (post_data is not self.No_Data): + myrequest = request.Request(url=url, + method=method_, + data=json.dumps(post_data).encode("utf-8"), + headers=self.default_headers) + else: + myrequest = request.Request(url=url, + headers=self.default_headers, + method=method_, + data=post_data) + self.logger.by_method("empty post sent to [%s]" % url) + + if not connection_timeout_sec: + if self.session_instance.get_timeout_sec(): + connection_timeout_sec = self.session_instance.get_timeout_sec() + else: + connection_timeout_sec = 120 + if connection_timeout_sec: + myrequest.timeout = connection_timeout_sec + + myrequest.headers['Content-type'] = 'application/json' + sess_id = self.session_instance.get_session_id() + if iss(sess_id): + myrequest.headers[SESSION_HEADER] = str(sess_id) + elif iss(session_id_): + myrequest.headers[SESSION_HEADER] = str(session_id_) + else: + self.logger.warning("Request sent without X-LFJson-ID header: " + url) + if debug: + self.logger.by_method("headers sent to: " + url) + self.logger.by_method(pformat(myrequest.headers)) + + # https://stackoverflow.com/a/59635684/11014343 + + response: http.client.HTTPResponse + + if wait_sec: + time.sleep(wait_sec) + begin_time_ms = time.time() * 1000 + if not max_timeout_sec: + max_timeout_sec = self.session_instance.max_timeout_sec + finish_time_ms = (max_timeout_sec * 1000) + begin_time_ms + attempt = 1 + while (time.time() * 1000) < finish_time_ms: + try: + response = urllib.request.urlopen(myrequest) + resp_data = response.read().decode('utf-8') + jzon_data = None + if debug and die_on_error: + self.logger.warning(__name__ + + " ----- json_post: %d debug: --------------------------------------------" % + attempt) + self.logger.warning("URL: %s :%d " % (url, response.status)) + self.logger.warning(__name__ + " ----- headers -------------------------------------------------") + if response.status != 200: + self.logger.error(pformat(response.getheaders())) + self.logger.error(__name__ + " ----- response -------------------------------------------------") + self.logger.error(pformat(resp_data)) + self.logger.error(" ----- -------------------------------------------------") + responses.append(response) + header_items = response.getheaders() + if debug: + self.logger.by_method("BaseJsonRequest::json_post: response headers:") + self.logger.by_method(pformat(header_items)) + if SESSION_HEADER in header_items: + if self.session_id != response.getheader(SESSION_HEADER): + self.logger.warning("established session header [%s] different from response session header[%s]" + % (self.session_id, response.getheader(SESSION_HEADER))) + if errors_warnings: + for header in header_items: + if header[0].startswith("X-Error") == 0: + errors_warnings.append(header) + if header[0].startswith("X-Warning") == 0: + errors_warnings.append(header) + + if response_json_list is not None: + if type(response_json_list) is not list: + raise ValueError("reponse_json_list needs to be type list") + jzon_data = json.loads(resp_data) + if debug: + self.logger.debug( + __name__ + ":----- json_post debug: ------------------------------------------") + self.logger.debug("URL: %s :%d " % (url, response.status)) + self.logger.debug( + __name__ + " ----- headers -------------------------------------------------") + self.logger.debug(pformat(response.getheaders())) + self.logger.debug( + __name__ + " ----- response -------------------------------------------------") + self.logger.debug(pformat(jzon_data)) + self.logger.debug("-------------------------------------------------") + response_json_list.append(jzon_data) + + if response.status not in self.OK_STATUSES: + if errors_warnings: + if "errors" in jzon_data: + errors_warnings.extend(jzon_data["errors"]) + if "warnings" in jzon_data: + errors_warnings.extend(jzon_data["warnings"]) + self.logger.debug("----------------- BAD STATUS --------------------------------") + if die_on_error: + exit(1) + return responses[0] + + except urllib.error.HTTPError as herror: + print_diagnostics(url_=url, + request_=myrequest, + responses_=responses, + error_=herror, + debug_=debug, + die_on_error_=die_on_error) + if die_on_error: + exit(1) + + except urllib.error.URLError as uerror: + print_diagnostics(url_=url, + request_=myrequest, + responses_=responses, + error_=uerror, + debug_=debug, + die_on_error_=die_on_error) + if die_on_error: + exit(1) + + if die_on_error: + exit(1) + return None + + def json_put(self, + url: str = None, + debug: bool = False, + wait_sec: float = None, + request_timeout_sec: float = None, + max_timeout_sec: float = None, + errors_warnings: list = None, + die_on_error: bool = False, + response_json_list: list = None) -> Optional: # Optional[HTTPResponse] + if not url: + raise ValueError("json_put requires url") + return self.json_post(url=url, + debug=debug | self.debug_on, + wait_sec=wait_sec, + connection_timeout_sec=request_timeout_sec, + max_timeout_sec=max_timeout_sec, + die_on_error=die_on_error | self.die_on_error, + response_json_list=response_json_list, + errors_warnings=errors_warnings, + method_='PUT') + + def json_delete(self, + url: str = None, + debug: bool = False, + die_on_error: bool = False, + wait_sec: float = None, + request_timeout_sec: float = None, + max_timeout_sec: float = None, + errors_warnings: list = None): + """ + Perform a HTTP DELETE call + :param url: fully qualified URL to request + :param debug: turn on diagnostic info + :param die_on_error: call exit if response is nither 100, 200, or 404 + :param wait_sec: time to pause before making call + :param request_timeout_sec: time to override default request timeout + :param max_timeout_sec: time after which to stop making more requests + :param errors_warnings: provide a list into which API errors and warnings are placed + :return: as get_as_json() returns (a native decoding of JSON document: dict, list, str, float or int) + """ + if wait_sec and (wait_sec > 0): + time.sleep(wait_sec) + return self.get_as_json(url=url, + debug=debug | self.debug_on, + die_on_error=die_on_error, + request_timeout_sec=request_timeout_sec, + max_timeout_sec=max_timeout_sec, + method_='DELETE', + errors_warnings=errors_warnings) + + def get(self, + url: str = None, + debug: bool = False, + die_on_error: bool = False, + method_: str = 'GET', + connection_timeout_sec: int = None) -> Optional: # Optional[HTTPResponse] + """ + Makes a HTTP GET request with specified timeout. + :param url: Fully qualified URL to request + :param debug: if true, print out diagnostic information + :param die_on_error: call exit() if query fails to connect, is a 400 or 500 response status. + Responses with 404 status are expected to be normal and will not cause an exit. + :param method_: Override the HTTP METHOD. Please do not override. + :param connection_timeout_sec: number of seconds to have an outstanding request + :return: returns an urllib.response or None + """ + debug |= self.debug_on + die_on_error |= self.die_on_error + + if debug: + self.logger.debug(message="%s url:[%s]" % (__name__, url)) + + if not connection_timeout_sec: + if self.session_instance.get_timeout_sec(): + connection_timeout_sec = self.session_instance.get_timeout_sec() + else: + connection_timeout_sec = 120 + + requested_url = self.get_corrected_url(url, + debug=debug | self.debug_on) + myrequest = request.Request(url=requested_url, + headers=self.default_headers, + method=method_) + if connection_timeout_sec: + myrequest.timeout = connection_timeout_sec + + myresponses: list = [] # list[HTTPResponse] + try: + myresponses.append(request.urlopen(myrequest)) + return myresponses[0] + + except urllib.error.HTTPError as herror: + print_diagnostics(url_=requested_url, + request_=myrequest, + responses_=myresponses, + error_=herror, + error_list_=self.error_list, + debug_=debug, + die_on_error_=die_on_error) + if die_on_error: + exit(1) + except urllib.error.URLError as uerror: + print_diagnostics(url_=requested_url, + request_=myrequest, + responses_=myresponses, + error_=uerror, + error_list_=self.error_list, + debug_=debug, + die_on_error_=die_on_error) + if die_on_error: + exit(1) + if die_on_error: + exit(1) + return None + + def get_as_json(self, + url: str = None, + die_on_error: bool = False, + debug: bool = False, + wait_sec: float = None, + request_timeout_sec: float = None, + max_timeout_sec: float = None, # TODO: use if we do retries + method_='GET', + errors_warnings: list = None): + """ + :param url: url to do GET request on + :param die_on_error: exit immediate if result status is BAD RESPONSE + :param debug: print diagnostic information about query + :param wait_sec: wait before requesting + :param request_timeout_sec: number of seconds to wait for a response + :param method_: Overrides the HTTP method used. Please do not override. + :param errors_warnings: if present, this list gets populated with errors and warnings from the result + :param max_timeout_sec: if there is no response, this request can retry every request_timeout_sec + :return: get response as a python object decoded from Json data + This often is a dict, but it could be any primitive Python type such as str, int, float or list. + """ + begin_sec = time.time() * 1000 + responses = [] + while (time.time() * 1000) < (begin_sec + max_timeout_sec): + if wait_sec and (wait_sec > 0): + time.sleep(wait_sec) + responses = [self.get(url=url, + debug=debug, + die_on_error=die_on_error, + connection_timeout_sec=request_timeout_sec, + method_=method_)] + if (len(responses) > 0) and responses[0]: + break + + if responses[0] is None: + if debug: + self.logger.debug(message="No response from " + url) + return None + + json_data = json.loads(responses[0].read().decode('utf-8')) + if errors_warnings is not None: + if "errors" in json_data: + errors_warnings.extend(json_data["errors"]) + if "warnings" in responses[0]: + errors_warnings.extend(json_data["warnings"]) + + return json_data + + def json_get(self, + url: str = None, + debug: bool = False, + wait_sec: float = None, + request_timeout_sec: float = None, + max_timeout_sec: float = None, + errors_warnings: list = None): + """ + Returns json record from GET request. This will retry until timeout_sec + :param url: URL to make GET request to + :param debug: print diagnostic information if true + :param wait_sec: time to wait before making request, or waiting until you get a non-404 response + :param request_timeout_sec: maximum time each request can take + :param max_timeout_sec: maximum time to spend making requests + :param errors_warnings: if present, fill this with error and warning messages from the response JSON + :return: dictionary of json response from server + """ + debug |= self.debug_on + json_response = None + if not max_timeout_sec: + max_timeout_sec = self.session_instance.max_timeout_sec + + if nott(url): + raise ValueError("json_get called withou url") + + url = self.get_corrected_url(url=url) + + deadline_sec: float = (_now_ms() * 1000) + max_timeout_sec + self.error_list.clear() + attempt_counter = 1 + while _now_sec() < deadline_sec: + if wait_sec: + time.sleep(wait_sec) + try: + json_response = self.get_as_json(url=url, + debug=debug, + die_on_error=False, + request_timeout_sec=request_timeout_sec, + max_timeout_sec=max_timeout_sec, + errors_warnings=errors_warnings) + if debug: + self.logger.debug("[%s] json_get: URL[%s]" % (attempt_counter, url)) + self.logger.debug(pformat(json_response)) + if json_response is None: + if errors_warnings: + errors_warnings.append("No json_response") + errors_warnings.extend(self.error_list) + if debug: + if hasattr(self, 'print_errors'): + self.print_errors() + else: + self.logger.error("json_get: [%s] no response, check other errors" % url) + time.sleep(wait_sec) + return None + else: + return json_response + except ValueError as ve: + if debug or self.die_on_error: + self.logger.error("json_get: [%s] " % url) + self.logger.error("Exception %s:" % ve) + self.logger.error(traceback.format_exception(ValueError, ve, ve.__traceback__, chain=True)) + # traceback.print_exception(ValueError, ve, ve.__traceback__, chain=True) + if self.die_on_error: + sys.exit(1) + return json_response + + # def set_post_data(self, data): + # """ + # :param data: dictionary of parameters for post + # :return: nothing + # """ + # self.post_data = data + + def has_errors(self): + return (True, False)[len(self.error_list) > 0] + + def print_errors(self): + if not self.has_errors: + self.logger.debug("---------- no errors ----------") + return + for err in self.error_list: + Logg.error("error: %s" % err) - # TODO: rename me to make_port_eid_url @staticmethod - def make_eid_url(eid_list=()): - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Convert a list of EIDs into a URL: - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + def create_port_eid_url(eid_list: list = None) -> str: + """ ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Convert a list of EIDs into a URL: + :param eid_list + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- """ if not len(eid_list): return "/list" url = "/" @@ -69,2424 +829,41 @@ class LFJsonGet(LFCliBase): return url + eid_list.replace('.', '/') # The first in a series has to define the resource number, - # but the remainder of a series has to match that resource number + # but the remainder of a series has to match that resource number for i in range(0, len(eid_list)): eid = eid_list[i] if i == 0: url += eid.replace('.', '/') elif eid.find('.') > 0: - url += ',' + eid.split('.')[-1] + url += str(',' + eid.split('.')[-1]) else: - url += ','+eid - + url += str(',' + eid) return url - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - If you need to call the URL directly, - request one of these URLs: - /attenuator/ - /attenuator/$shelf_id - /attenuator/$shelf_id/$resource_id - /attenuator/$shelf_id/$resource_id/$port_id - /attenuators/ - /attenuators/$shelf_id - /attenuators/$shelf_id/$resource_id - /attenuators/$shelf_id/$resource_id/$port_id - When requesting specific column names, they need to be URL encoded: - entity+id, module+1, module+2, module+3, module+4, module+5, module+6, module+7, - module+8, name, script, state, temperature - Example URL: /attenuator?fields=entity+id,module+1 - - Example py-json call (it knows the URL): - record = LFJsonGet.get_attenuator(eid_list=['1.234', '1.344'], - requested_col_names=['entity id'], - debug_=True) - - The record returned will have these members: - { - 'entity id': # Entity ID - 'module 1': # Reported attenuator dB settings. - 'module 2': # Reported attenuator dB settings. - 'module 3': # Reported attenuator dB settings. - 'module 4': # Reported attenuator dB settings. - 'module 5': # Reported attenuator dB settings. - 'module 6': # Reported attenuator dB settings. - 'module 7': # Reported attenuator dB settings. - 'module 8': # Reported attenuator dB settings. - 'name': # Attenuator module identifier (shelf . resource . serial-num). - 'script': # Attenuator script state. - 'state': # Attenuator state. - 'temperature': # Temperature in degres Farenheight reported in Attenuator unit. - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_attenuator(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/attenuator" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="attenuator", - plural_key="attenuators") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /chamber/ - /chamber/$chamber_name - - When requesting specific column names, they need to be URL encoded: - chamber, chamber+connections, chamber+resources, chamber+type, duts, entity+id, - flags, hide, isolation, marked, open, reported+rotation+%28deg%29, reported+rpm, - reported+tilt+%28deg%29, resource, rotation+%28deg%29, rpm, smas, tilt+%28deg%29, turntable, - turntable+type, virtual - Example URL: /chamber?fields=chamber,chamber+connections - - Example py-json call (it knows the URL): - record = LFJsonGet.get_chamber(eid_list=['1.234', '1.344'], - requested_col_names=['entity id'], - debug_=True) - - The record returned will have these members: - { - 'chamber': # - - 'chamber connections': # - - 'chamber resources': # - - 'chamber type': # - - 'duts': # - - 'entity id': # - - 'flags': # - - 'hide': # - - 'isolation': # - - 'marked': # - - 'open': # - - 'reported rotation (deg)': # - - 'reported rpm ': # - - 'reported tilt (deg)': # - - 'resource': # - - 'rotation (deg)': # - - 'rpm': # - - 'smas': # - - 'tilt (deg)': # - - 'turntable': # - - 'turntable type': # - - 'virtual': # - - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_chamber(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/chamber" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="chamber", - plural_key="chambers") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /control/$command - - - Example py-json call (it knows the URL): - record = LFJsonGet.get_control(eid_list=['1.234', '1.344'], - debug_=True) - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_control(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/control" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="", - plural_key="") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /cx/ - /cx/$cx_id - - When requesting specific column names, they need to be URL encoded: - avg+rtt, bps+rx+a, bps+rx+b, drop+pkts+a, drop+pkts+b, eid, endpoints+%28a%C2%A0%E2%86%94%C2%A0b%29, - entity+id, name, pkt+rx+a, pkt+rx+b, rpt+timer, rx+drop+%25+a, rx+drop+%25+b, - state, type - Example URL: /cx?fields=avg+rtt,bps+rx+a - - Example py-json call (it knows the URL): - record = LFJsonGet.get_cx(eid_list=['1.234', '1.344'], - requested_col_names=['entity id'], - debug_=True) - - The record returned will have these members: - { - 'avg rtt': # Average Round-Trip-Time (latency) for this connection (ms). - 'bps rx a': # Endpoint A's real receive rate (bps). - 'bps rx b': # Endpoint B's real receive rate (bps). - 'drop pkts a': # The number of packets Endpoint B sent minus the number Endpoint A - # received.This number is not 100% correct as long as packets are in - # flight.After a Quiesce of the test, the number should be perfectly - # accurate. - 'drop pkts b': # The number of packets Endpoint A sent minus the number Endpoint B - # received.This number is not 100% correct as long as packets are in - # flight.After a Quiesce of the test, the number should be perfectly - # accurate. - 'eid': # Cross Connect's Name. - 'endpoints (a ↔ b)': # Endpoints that make up this Cross Connect. - 'entity id': # Cross Connect's Name. - 'name': # Cross Connect's Name. - 'pkt rx a': # Endpoint A's Packets Recieved. - 'pkt rx b': # Endpoint B's Packets Recieved. - 'rpt timer': # Cross Connect's Report Timer (milliseconds).This is how often the GUI - # will ask for updates from the LANforge processes.If the GUI is sluggish, - # increasing the report timers may help. - 'rx drop % a': # Endpoint A percentage packet loss.Calculated using the number of PDUs - # Endpoint B sent minus the number Endpoint A received.This number is not - # 100% correct as long as packets are in flight.After a Quiesce of the - # test, the number should be perfectly accurate. - 'rx drop % b': # Endpoint B percentage packet loss.Calculated using the number of PDUs - # Endpoint A sent minus the number Endpoint B received.This number is not - # 100% correct as long as packets are in flight.After a Quiesce of the - # test, the number should be perfectly accurate. - 'state': # Current State of the connection.UninitializedHas not yet been - # started/stopped.InitializingBeing set up.StartingStarting the - # test.RunningTest is actively running.StoppedTest has been - # stopped.QuiesceTest will gracefully stop soon.HW-BYPASSTest is in - # hardware-bypass mode (WanLinks only)FTM_WAITTest wants to run, but is - # phantom, probably due to non-existent interface or resource.WAITINGWill - # restart as soon as resources are available.PHANTOMTest is stopped, and - # is phantom, probably due to non-existent interface or resource. - 'type': # Cross-Connect type. - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_cx(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/cx" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="", - plural_key="") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /dut/ - /dut/$name - - When requesting specific column names, they need to be URL encoded: - api+version, bssid-1, bssid-2, bssid-3, bssid-4, bssid-5, bssid-6, bssid-7, - bssid-8, dut, eap-id, entity+id, hw+info, image+file, lan, mgt+ip, model+number, - notes, num+ant+radio+1, num+ant+radio+2, num+ant+radio+3, password-1, password-2, - password-3, password-4, password-5, password-6, password-7, password-8, serial+number, - serial+port, ssid-1, ssid-2, ssid-3, ssid-4, ssid-5, ssid-6, ssid-7, ssid-8, - sw+info, wan - Example URL: /dut?fields=api+version,bssid-1 - - Example py-json call (it knows the URL): - record = LFJsonGet.get_dut(eid_list=['1.234', '1.344'], - requested_col_names=['entity id'], - debug_=True) - - The record returned will have these members: - { - 'api version': # API Version - 'bssid-1': # WiFi BSSID for DUT. - 'bssid-2': # WiFi BSSID for DUT. - 'bssid-3': # WiFi BSSID for DUT. - 'bssid-4': # WiFi BSSID for DUT. - 'bssid-5': # WiFi BSSID for DUT. - 'bssid-6': # WiFi BSSID for DUT. - 'bssid-7': # WiFi BSSID for DUT. - 'bssid-8': # WiFi BSSID for DUT. - 'dut': # Devices Under Test - 'eap-id': # EAP Identifier, only used when one of the EAP options are selected. - 'entity id': # Entity ID - 'hw info': # DUT Hardware Info - 'image file': # Image file name. Relative paths assume directory /home/lanforge. Fully - # qualified pathnames begin with a slash (eg - # /usr/lib/share/icons/icon.png).File format should be PNG, JPG or BMP. - 'lan': # IP/Mask for LAN port (192.168.2.1/24). - 'mgt ip': # DUT Management IP address. - 'model number': # DUT model number or product name - 'notes': # Notes - 'num ant radio 1': # Antenna count for DUT radio(s). - 'num ant radio 2': # Antenna count for DUT radio(s). - 'num ant radio 3': # Antenna count for DUT radio(s). - 'password-1': # WiFi Password needed to connect to DUT. - 'password-2': # WiFi Password needed to connect to DUT. - 'password-3': # WiFi Password needed to connect to DUT. - 'password-4': # WiFi Password needed to connect to DUT. - 'password-5': # WiFi Password needed to connect to DUT. - 'password-6': # WiFi Password needed to connect to DUT. - 'password-7': # WiFi Password needed to connect to DUT. - 'password-8': # WiFi Password needed to connect to DUT. - 'serial number': # DUT Identifier (serial-number, or similar) - 'serial port': # Resource and name of LANforge serial port that connects to this DUT. - # (1.1.ttyS0). Does not need to belong to lan_port or wan_port resource. - 'ssid-1': # WiFi SSID advertised by DUT. - 'ssid-2': # WiFi SSID advertised by DUT. - 'ssid-3': # WiFi SSID advertised by DUT. - 'ssid-4': # WiFi SSID advertised by DUT. - 'ssid-5': # WiFi SSID advertised by DUT. - 'ssid-6': # WiFi SSID advertised by DUT. - 'ssid-7': # WiFi SSID advertised by DUT. - 'ssid-8': # WiFi SSID advertised by DUT. - 'sw info': # DUT Software Info - 'wan': # IP/Mask for WAN port (192.168.3.2/24). - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_dut(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/dut" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="dut", - plural_key="duts") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /endp/ - /endp/$endp_id - - When requesting specific column names, they need to be URL encoded: - 1st+rx, a%2Fb, bursty, crc+fail, cwnd, cx+active, cx+estab, cx+estab%2Fs, cx+to, - delay, destination+addr, dropped, dup+pkts, eid, elapsed, entity+id, jitter, - max+pdu, max+rate, min+pdu, min+rate, mng, name, ooo+pkts, pattern, pdu%2Fs+rx, - pdu%2Fs+tx, pps+rx+ll, pps+tx+ll, rcv+buf, replays, run, rx+ber, rx+bytes, - rx+drop+%25, rx+dup+%25, rx+ooo+%25, rx+pdus, rx+pkts+ll, rx+rate, rx+rate+%281%C2%A0min%29, - rx+rate+%28last%29, rx+rate+ll, rx+wrong+dev, script, send+buf, source+addr, - tcp+mss, tcp+rtx, tx+bytes, tx+pdus, tx+pkts+ll, tx+rate, tx+rate+%281%C2%A0min%29, - tx+rate+%28last%29, tx+rate+ll # hidden columns: - drop-count-5m, latency-5m, rt-latency-5m, rx-silence-5m - Example URL: /endp?fields=1st+rx,a%2Fb - - Example py-json call (it knows the URL): - record = LFJsonGet.get_endp(eid_list=['1.234', '1.344'], - requested_col_names=['entity id'], - debug_=True) - - The record returned will have these members: - { - '1st rx': # Miliseconds between starting the endpoint and receiving the first - # packet.Note that LANforge UDP connections (not including multicast) will - # wait 20msbefore sending first frame to make sure receiver has adequate - # time to start. - 'a/b': # Display side (A or B) for the endpoint. - 'bursty': # Is the transmit rate bursty or not? - 'crc fail': # Total packets received with a bad payload CRC. - 'cwnd': # Sender's TCP Current Window Size. In units of Maximum Segment Size. - 'cx active': # Total number of active connections for this endpoint. - 'cx estab': # Total times the connection between the endpoints has been established. - 'cx estab/s': # Connections established per second, averaged over the last 30 seconds. - 'cx to': # Number of TCP connection attemtps timed out by LANforge. - 'delay': # Average latency in milliseconds for packets received by this endpoint. - 'destination addr': # Destination Address (MAC, ip/port, VoIP destination). - 'dropped': # Total dropped packets, as identified by gaps in packet sequence numbers. - 'dup pkts': # Total duplicate packets received. Only an estimate, but never less than - # this value. - 'eid': # Entity ID - 'elapsed': # Amount of time (seconds) this endpoint has been running (or ran.) - 'entity id': # Entity ID - 'jitter': # Exponential decaying average jitter calculated per RFC3393(old_jitter * - # 15/16 + new_jitter * 1/16) - 'max pdu': # The maximum write size.For Ethernet protocols, this is the entire - # Ethernet frame. For UDP, it is the UDP payload size, and for TCP, it - # just means the maximum amount of data that is written per socket - # write.In all cases, the packets on the wire will not exceed theport's - # MTU + Ethernet-Header-Size (typically 1514 for Ethernet) - 'max rate': # Maximum desired transmit rate, in bits per second (bps). - 'min pdu': # The minimum write size.For Ethernet protocols, this is the entire - # Ethernet frame. For UDP, it is the UDP payload size, and for TCP, it - # just means the maximum amount of data that is written per socket - # write.In all cases, the packets on the wire will not exceed theport's - # MTU + Ethernet-Header-Size (typically 1514 for Ethernet) - 'min rate': # Minimum desired transmit rate, in bits per second (bps). - 'mng': # Is the Endpoint managed or not? - 'name': # Endpoint's Name. - 'ooo pkts': # Total out of order packets received. Only an estimate, but never less - # than this value. - 'pattern': # Pattern of bytes this endpoint transmits. - 'pdu/s rx': # Received PDU per second.This counts the protocol reads, such as UDP - # PDUs. - 'pdu/s tx': # Transmitted PDU per second.This counts the protocol writes, such as UDP - # PDUs. - 'pps rx ll': # Estimated total received packets per second (on the wire).For TCP, this - # is an estimate.UDP and Ethernet protocols should be quite accurate on - # normal networks. - 'pps tx ll': # Estimated total transmitted packets per second (on the wire).For TCP, - # this is an estimate.UDP and Ethernet protocols should be quite accurate - # on normal networks. - 'rcv buf': # Configured/Actual values for receiving buffer size (bytes). - 'replays': # Total number of files replayed. - 'run': # Is the Endpoint is Running or not. - 'rx ber': # Received bit-errors. These are only calculated in the LANforge payload - # portion starting 28 bytes into the UDP or TCP payload. In addition, the - # bit-errors are only checked when LANforge CRCis enabled and detected to - # be invalid. If the 28-byte header is corrupted, LANforge will not - # detectit, and may also give false positives for other packet errors. - # Bit-Errors are only calculated forcertain payload patterns: Increasing, - # Decreasing, Zeros, Ones, and the PRBS patterns. - 'rx bytes': # Total received bytes count. - 'rx drop %': # Percentage of packets that should have been received by Endpoint, but - # were not, as calculated by the Cross-Connect. - 'rx dup %': # Percentage of duplicate packets, as detected by sequence numbers. - 'rx ooo %': # Percentage of packets received out of order, as detected by sequence - # numbers. - 'rx pdus': # Total received PDU count.This counts the protocol reads, such as UDP - # PDUs (aka goodput). - 'rx pkts ll': # Estimated total received packet count (on the wire).For TCP, this is an - # estimate.UDP and Ethernet protocols should be quite accurate on normal - # networks. - 'rx rate': # Real receive rate (bps) for this run.This includes only the protocol - # payload (goodput). - 'rx rate (1 min)': # Real receive rate (bps) over the last minute.This includes only the - # protocol payload (goodput). - 'rx rate (last)': # Real receive rate (bps) over the last report interval.This includes only - # the protocol payload (goodput). - 'rx rate ll': # Estimated low-level receive rate (bps) over the last minute.This - # includes any Ethernet, IP, TCP, UDP or similar headers. - 'rx wrong dev': # Total packets received on the wrong device (port). - 'script': # Endpoint script state. - 'send buf': # Configured/Actual values for sending buffer size (bytes). - 'source addr': # - 'tcp mss': # Sender's TCP-MSS (max segment size) setting.This cooresponds to the - # TCP_MAXSEGS socket option,and TCP-MSS plus 54 is the maximum packet size - # on the wirefor Ethernet frames.This is a good option to efficiently - # limit TCP packet size. - 'tcp rtx': # Total packets retransmitted by the TCP stack for this connection.These - # were likely dropped or corrupted in transit. - 'tx bytes': # Total transmitted bytes count. - 'tx pdus': # Total transmitted PDU count.This counts the protocol writes, such as UDP - # PDUs (aka goodput). - 'tx pkts ll': # Estimated total transmitted packet count (on the wire).For TCP, this is - # an estimate.UDP and Ethernet protocols should be quite accurate on - # normal networks. - 'tx rate': # Real transmit rate (bps) for this run.This includes only the protocol - # payload (goodput). - 'tx rate (1 min)': # Real transmit rate (bps) over the last minute.This includes only the - # protocol payload (goodput). - 'tx rate (last)': # Real transmit rate (bps) over the last report interval.This includes - # only the protocol payload (goodput). - 'tx rate ll': # Estimated low-level transmit rate (bps) over the last minute.This - # includes any Ethernet, IP, TCP, UDP or similar headers. - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_endp(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/endp" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="endpoint", - plural_key="endpoint") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /events/ - /events/$event_id - /events/before/$event_id - /events/between/$start_event_id/$end_event_id - /events/last/$event_count - /events/since/$event_id - - When requesting specific column names, they need to be URL encoded: - eid, entity+id, event, event+description, id, name, priority, time-stamp, - type - Example URL: /events?fields=eid,entity+id - - Example py-json call (it knows the URL): - record = LFJsonGet.get_events(eid_list=['1.234', '1.344'], - requested_col_names=['entity id'], - debug_=True) - - The record returned will have these members: - { - 'eid': # Time at which this event was created.This uses the clock on the source - # machine. - 'entity id': # Entity IdentifierExact format depends on the - # type.(shelf.resource.port.endpoint.extra) - 'event': # Event Type - 'event description': # Text description for this event. - 'id': # Unique ID for this event. - 'name': # Name of the entity associated with this event. - 'priority': # Event priority. - 'time-stamp': # Time at which this event was created.This uses the clock on the source - # machine. - 'type': # Entity type. - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_events(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/events" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="alert", - plural_key="alerts") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /fileio/ - /fileio/$endp_id - - When requesting specific column names, they need to be URL encoded: - buf-rd, buf-wr, bytes-rd, bytes-wr, crc+fail, eid, entity+id, files+%23, files-read, - files-wr, io+fail, max-file-sz, max-rd-bps, max-rw-sz, max-wr-bps, min-file-sz, - min-rd-bps, min-rw-sz, min-wr-bps, name, read-bps, rpt+timer, rx-bps-20s, - status, tx-bps-20s, type, write-bps - Example URL: /fileio?fields=buf-rd,buf-wr - - Example py-json call (it knows the URL): - record = LFJsonGet.get_fileio(eid_list=['1.234', '1.344'], - requested_col_names=['entity id'], - debug_=True) - - The record returned will have these members: - { - 'buf-rd': # Buffer reads. When doing CRC, it takes two reads per 'packet', because - # we first read the header, then the payload. Non-CRC reads ignore the - # header. - 'buf-wr': # Buffer writes. - 'bytes-rd': # Bytes read. - 'bytes-wr': # Bytes written. - 'crc fail': # 32-bit CRC Errors detected upon READ. - 'eid': # Entity ID - 'entity id': # Entity ID - 'files #': # Number of files to write. - 'files-read': # Files read. - 'files-wr': # Files written. - 'io fail': # Amount of time in miliseconds this test has been experiencing IO - # failures. - 'max-file-sz': # Maximum configured file size (bytes). - 'max-rd-bps': # Maximum configured read rate (bps). - 'max-rw-sz': # Maximum configured size for each call to read(2) or write(2) (bytes). - 'max-wr-bps': # Maximum configured write rate (bps). - 'min-file-sz': # Minimum configured file size (bytes). - 'min-rd-bps': # Minimum configured read rate (bps). - 'min-rw-sz': # Minimum configured size for each call to read(2) or write(2) (bytes). - 'min-wr-bps': # Minimum configured write rate (bps). - 'name': # File Endpoint's Name. - 'read-bps': # File read rate for this endpoint over the duration of the test. - 'rpt timer': # Report Timer (milliseconds).This is how often the GUI will ask for - # updates from the LANforge processes.If the GUI is sluggish, increasing - # the report timers may help. - 'rx-bps-20s': # File read rate for this endpoint over the last 20 seconds. - 'status': # Current State of the connection.UninitializedHas not yet been - # started/stopped.InitializingBeing set up.StartingStarting the - # test.RunningTest is actively running.StoppedTest has been - # stopped.QuiesceTest will gracefully stop soon.HW-BYPASSTest is in - # hardware-bypass mode (WanLinks only)FTM_WAITTest wants to run, but is - # phantom, probably due to non-existent interface or resource.WAITINGWill - # restart as soon as resources are available.PHANTOMTest is stopped, and - # is phantom, probably due to non-existent interface or resource. - 'tx-bps-20s': # File write rate for this endpoint over the last 20 seconds. - 'type': # The specific type of this File Endpoint. - 'write-bps': # File write rate for this endpoint over the duration of the test. - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_fileio(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/fileio" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="endpoint", - plural_key="endpoint") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /generic/ - /generic/$endp_id - - When requesting specific column names, they need to be URL encoded: - bps+rx, bps+tx, command, dropped, eid, elapsed, entity+id, last+results, - name, pdu%2Fs+rx, pdu%2Fs+tx, rpt+timer, rpt%23, rx+bytes, rx+pkts, status, tx+bytes, - tx+pkts, type - Example URL: /generic?fields=bps+rx,bps+tx - - Example py-json call (it knows the URL): - record = LFJsonGet.get_generic(eid_list=['1.234', '1.344'], - requested_col_names=['entity id'], - debug_=True) - - The record returned will have these members: - { - 'bps rx': # Receive rate reported by this endpoint. - 'bps tx': # Transmit rate reported by this endpoint. - 'command': # The command that this endpoint executes. - 'dropped': # Dropped PDUs reported by this endpoint. - 'eid': # Entity ID - 'elapsed': # Amount of time (seconds) this endpoint has been running (or ran.) - 'entity id': # Entity ID - 'last results': # Latest output from the Generic Endpoint. - 'name': # Endpoint's Name. - 'pdu/s rx': # Received packets-per-second reported by this endpoint. - 'pdu/s tx': # Transmitted packets-per-second reported by this endpoint. - 'rpt timer': # Report Timer (milliseconds).This is how often the GUI will ask for - # updates from the LANforge processes.If the GUI is sluggish, increasing - # the report timers may help. - 'rpt#': # The N_th report that we have received. (Some cmds will produce only one - # report, others will produce continuous reports.) - 'rx bytes': # Received bytes reported by this endpoint. - 'rx pkts': # Received PDUs reported by this endpoint. - 'status': # Current State of the connection.UninitializedHas not yet been - # started/stopped.InitializingBeing set up.StartingStarting the - # test.RunningTest is actively running.StoppedTest has been - # stopped.QuiesceTest will gracefully stop soon.HW-BYPASSTest is in - # hardware-bypass mode (WanLinks only)FTM_WAITTest wants to run, but is - # phantom, probably due to non-existent interface or resource.WAITINGWill - # restart as soon as resources are available.PHANTOMTest is stopped, and - # is phantom, probably due to non-existent interface or resource. - 'tx bytes': # Transmitted bytes reported by this endpoint. - 'tx pkts': # Transmitted PDUs reported by this endpoint. - 'type': # The specific type of this Generic Endpoint. - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_generic(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/generic" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="endpoint", - plural_key="endpoints") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /gui-cli/ - - - Example py-json call (it knows the URL): - record = LFJsonGet.get_gui_cli(eid_list=['1.234', '1.344'], - debug_=True) - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_gui_cli(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/gui-cli" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="", - plural_key="") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /layer4/ - /layer4/$endp_id - - When requesting specific column names, they need to be URL encoded: - %21conn, acc.+denied, bad-proto, bad-url, bytes-rd, bytes-wr, dns-avg, dns-max, - dns-min, eid, elapsed, entity+id, fb-avg, fb-max, fb-min, ftp-host, ftp-port, - ftp-stor, http-p, http-r, http-t, login-denied, name, nf+%284xx%29, other-err, - read, redir, rpt+timer, rslv-h, rslv-p, rx+rate, rx+rate+%281%C2%A0min%29, status, - timeout, total-err, total-urls, tx+rate, tx+rate+%281%C2%A0min%29, type, uc-avg, - uc-max, uc-min, urls%2Fs, write # hidden columns: - rpt-time - Example URL: /layer4?fields=%21conn,acc.+denied - - Example py-json call (it knows the URL): - record = LFJsonGet.get_layer4(eid_list=['1.234', '1.344'], - requested_col_names=['entity id'], - debug_=True) - - The record returned will have these members: - { - '!conn': # Could not establish connection. - 'acc. denied': # Access Access Denied Error.This could be password, user-name, - # file-permissions or other error. - 'bad-proto': # Bad protocol. - 'bad-url': # Bad URL format. - 'bytes-rd': # Bytes read. - 'bytes-wr': # Bytes written. - 'dns-avg': # Average time in milliseconds to complete resolving the DNS lookupfor the - # last 100 requests. - 'dns-max': # Maximum time in milliseconds to complete resolving the DNS lookupfor - # requests made in the last 30 seconds. - 'dns-min': # Minimum time in milliseconds to complete resolving the DNS lookupfor - # requests made in the last 30 seconds. - 'eid': # EID - 'elapsed': # Amount of time (seconds) this endpoint has been running (or ran.) - 'entity id': # Entity ID - 'fb-avg': # Average time in milliseconds for receiving the first byte of the URLfor - # the last 100 requests. - 'fb-max': # Maximum time in milliseconds for receiving the first byte of the URLfor - # requests made in the last 30 seconds. - 'fb-min': # Minimum time in milliseconds for receiving the first byte of the URLfor - # requests made in the last 30 seconds. - 'ftp-host': # FTP HOST Error - 'ftp-port': # FTP PORT Error. - 'ftp-stor': # FTP STOR Error. - 'http-p': # HTTP Post error. - 'http-r': # HTTP RANGE error. - 'http-t': # HTTP PORT Error. - 'login-denied': # Login attempt was denied.Probable cause is user-name or password errors. - 'name': # Endpoint's Name. - 'nf (4xx)': # File not found.For HTTP, an HTTP 4XX error was returned. This is only - # counted when the endpoint has 'Enable 4XX' selected.Includes 403 - # permission denied and 404 not found errors.For other protocols, it - # should be returned any time a file is not found. - 'other-err': # Error not otherwise specified. The actual error code may be found - # inl4helper logs. Contact support if you see these errors:we would like - # to account for all possible errors. - 'read': # Error attempting to read file or URL. - 'redir': # Noticed redirect loop! - 'rpt timer': # Cross Connect's Report Timer (milliseconds).This is how often the GUI - # will ask for updates from the LANforge processes.If the GUI is sluggish, - # increasing the report timers may help. - 'rslv-h': # Couldn't resolve host. - 'rslv-p': # Couldn't resolve Proxy. - 'rx rate': # Payload receive rate (bps). - 'rx rate (1 min)': # Payload receive rate over the last minute (bps). - 'status': # Current State of the connection.UninitializedHas not yet been - # started/stopped.InitializingBeing set up.StartingStarting the - # test.RunningTest is actively running.StoppedTest has been - # stopped.QuiesceTest will gracefully stop soon.HW-BYPASSTest is in - # hardware-bypass mode (WanLinks only)FTM_WAITTest wants to run, but is - # phantom, probably due to non-existent interface or resource.WAITINGWill - # restart as soon as resources are available.PHANTOMTest is stopped, and - # is phantom, probably due to non-existent interface or resource. - 'timeout': # Operation timed out. - 'total-err': # Total Errors. - 'total-urls': # URLs processed. - 'tx rate': # Payload transmit rate (bps). - 'tx rate (1 min)': # Payload transmit rate over the last minute (bps). - 'type': # The specific type of this Layer 4-7 Endpoint. - 'uc-avg': # Average time in milliseconds to complete processing of the URLfor the - # last 100 requests. - 'uc-max': # Maximum time in milliseconds to complete processing of the URLfor - # requests made in the last 30 seconds. - 'uc-min': # Minimum time in milliseconds to complete processing of the URLfor - # requests made in the last 30 seconds. - 'urls/s': # URLs processed per second over the last minute. - 'write': # Error attempting to write file or URL. - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_layer4(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/layer4" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="endpoint", - plural_key="endpoint") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /port/ - /port/$shelf_id - /port/$shelf_id/$resource_id - /port/$shelf_id/$resource_id/$port_id - /portprobe/ - /portprobe/$shelf_id/$resource_id/$port_id - /ports/ - /ports/$shelf_id - /ports/$shelf_id/$resource_id - /ports/$shelf_id/$resource_id/$port_id - - When requesting specific column names, they need to be URL encoded: - 4way+time+%28us%29, activity, alias, anqp+time+%28us%29, ap, beacon, bps+rx, bps+rx+ll, - bps+tx, bps+tx+ll, bytes+rx+ll, bytes+tx+ll, channel, collisions, connections, - crypt, cx+ago, cx+time+%28us%29, device, dhcp+%28ms%29, down, entity+id, gateway+ip, - ip, ipv6+address, ipv6+gateway, key%2Fphrase, login-fail, login-ok, logout-fail, - logout-ok, mac, mask, misc, mode, mtu, no+cx+%28us%29, noise, parent+dev, phantom, - port, port+type, pps+rx, pps+tx, qlen, reset, retry+failed, rx+bytes, rx+crc, - rx+drop, rx+errors, rx+fifo, rx+frame, rx+length, rx+miss, rx+over, rx+pkts, - rx-rate, sec, signal, ssid, status, time-stamp, tx+abort, tx+bytes, tx+crr, - tx+errors, tx+fifo, tx+hb, tx+pkts, tx+wind, tx-failed+%25, tx-rate, wifi+retries, - # hidden columns: - beacon_rx_signal, port_cur_flags_h, port_cur_flags_l, port_supported_flags_h, - port_supported_flags_l, resource, rx_multicast, tx_dropped - Example URL: /port?fields=4way+time+%28us%29,activity - - Example py-json call (it knows the URL): - record = LFJsonGet.get_port(eid_list=['1.234', '1.344'], - requested_col_names=['entity id'], - debug_=True) - - The record returned will have these members: - { - '4way time (us)': # TIme (in micro-seconds) it took to complete the last WiFi 4-way - # authentication. - 'activity': # Percent of the channel that is utilized over the last minute.This - # includes locally generated traffic as well as anyother systems active on - # this channel.This is a per-radio value. - 'alias': # User-specified alias for this Port. - 'anqp time (us)': # Time (in micro-seconds) it took to complete the last WiFi ANQP - # request/response session. - 'ap': # BSSID of AP for connected stations. - 'beacon': # Number of Wireless beacons from Cell or AP that have been missed. - 'bps rx': # Average bits per second received for the last 30 seconds. - 'bps rx ll': # Bits per second received, including low-level framing (Ethernet Only). - 'bps tx': # Average bits per second transmitted for the last 30 seconds. - 'bps tx ll': # Bits per second transmitted, including low-level framing (Ethernet - # Only). - 'bytes rx ll': # Bytes received, including low-level framing (Ethernet Only). - 'bytes tx ll': # Bytes transmitted, including low-level framing (Ethernet Only). - 'channel': # Channel at the device is currently on, if known. - 'collisions': # Total number of collisions reported by this Interface.For WiFi devices, - # this is number of re-transmit attempts. - 'connections': # Number of wireless connections completed. - 'crypt': # Number of Wireless packets dropped due to inability to decrypt. - 'cx ago': # How long ago was the last WiFi connection attempt started?This relates - # only to the network interface, not any higher level protocol traffic - # upon it. - 'cx time (us)': # Time (in micro-seconds) it took to complete the last WiFi connection to - # the AP. - 'device': # Ethernet device name, as seen by the kernel. - 'dhcp (ms)': # Time (in miliseconds) it took to acquire DHCP lease,or to time out while - # trying to acquire lease. - 'down': # The interface is configured DOWN. It must be configured UP to be in - # active use. - 'entity id': # Entity ID - 'gateway ip': # Default Router/Gateway IP for the Interface. - 'ip': # IP Address of the Interface. - 'ipv6 address': # IPv6 Address for this interface. If global-scope address exists, it - # will be displayed,otherwise link-local will be displayed. - 'ipv6 gateway': # IPv6 default gateway. - 'key/phrase': # WEP Key or WPA Phrase (if enabled). - 'login-fail': # The 'ifup-post' script reported failure. This is usually used for WiFi - # portallogins, but may be customized by the user for other needs. - 'login-ok': # The 'ifup-post' script reported OK. This is usually used for WiFi - # portallogins, but may be customized by the user for other needs. - 'logout-fail': # The 'ifup-post --logout' script reported failure. This is usually used - # for WiFi portallogouts, but may be customized by the user for other - # needs. - 'logout-ok': # The 'ifup-post --logout' script reported OK. This is usually used for - # WiFi portallogouts, but may be customized by the user for other needs. - 'mac': # Ethernet MAC address of the Interface. - 'mask': # IP Mask of the Interface. - 'misc': # Number of Wireless packets dropped on receive due to unspecified - # reasons. - 'mode': # Wireless radio mode (802.11a/b/g). - 'mtu': # MTU (Maximum Transmit Unit) size, in bytes. - 'no cx (us)': # How long was the WiFi disconnect duration for the last disconnection? - 'noise': # Wireless noise level. - 'parent dev': # Parent device or port of this port. Blank if this device is not a child - # of another device or port. - 'phantom': # Is the port PHANTOM (no hardware found) or not. - 'port': # Entity ID - 'port type': # Ports can be Ethernet, Radio, vAP, vSTA, Redirect, or Bridges - 'pps rx': # Average packets per second received for the last 30 seconds. - 'pps tx': # Average packets per second transmitted for the last 30 seconds. - 'qlen': # "Transmit Queue Length for this Interface. - 'reset': # Current Reset-State. - 'retry failed': # Number of Wireless packets that the interface failed to send due to - # excessive retries. - 'rx bytes': # Total number of bytes received by this Interface. - 'rx crc': # Total number of packets dropped because of a bad CRC/FCS. - 'rx drop': # Total number of dropped packets on recieve. Usually means driver/kernel - # is being over-worked. - 'rx errors': # Total number of all types of Receive Errors. - 'rx fifo': # Total number of packets dropped because driver/kernel queues are full. - 'rx frame': # Total number of packets dropped because of framing errors at the - # physical layer. - 'rx length': # Total number of packets dropped because their length was invalid. - 'rx miss': # Total number of packets dropped because of a missed interrupt. - 'rx over': # Total number of packets dropped because of framing errors at the - # physical layer. - 'rx pkts': # Total number of packets received by this Interface. - 'rx-rate': # Reported network device RX link speed. - 'sec': # Number of secondary IP addresses configured or detected. - 'signal': # Wireless signal strength (RSSI). - 'ssid': # WiFi SSID identifier.Use [BLANK] for empty SSID, which means use any - # available SSID when associating. - 'status': # Wireless link status. - 'time-stamp': # Time-Stamp - 'tx abort': # Total packets dropped on transmit because of driver abort. - 'tx bytes': # Total number of bytes sent by this Interface. - 'tx crr': # Total packets dropped on transmit because of carrier error. - 'tx errors': # Total number of all types of Transmit Errors. - 'tx fifo': # Total packets dropped on transmit because outgoing queue was full. - 'tx hb': # Total packets dropped on transmit because of transceiver heartbeat - # errors. - 'tx pkts': # Total number of packets sent by this Interface. - 'tx wind': # Total number dropped on transmit because of Out-of-Window collision. - 'tx-failed %': # Percentage of transmitted Wireless packets that were not ACKed.They - # might have succeeded on retry. - 'tx-rate': # Reported network device TX link speed. - 'wifi retries': # Number of Wireless packets that the wifi radio retried.One packet may be - # tried multiple times and each try would be counted in this stat.Not all - # radios can properly report this statistic. - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_port(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/port" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="interface", - plural_key="interfaces") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /probe/ - /probe/$shelf_id/$resource_id/$port_id - - When requesting specific column names, they need to be URL encoded: - entity+id, probe+results - Example URL: /probe?fields=entity+id,probe+results - - Example py-json call (it knows the URL): - record = LFJsonGet.get_probe(eid_list=['1.234', '1.344'], - requested_col_names=['probe results'], - debug_=True) - - The record returned will have these members: - { - 'entity id': # Entity ID - 'probe results': # Probe the low level information about the port. - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_probe(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/probe" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="probe-results", - plural_key="probe-results") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /quit - - - Example py-json call (it knows the URL): - record = LFJsonGet.get_quit(eid_list=['1.234', '1.344'], - debug_=True) - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_quit(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/quit" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="", - plural_key="") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /radiostatus/ - /radiostatus/$eid - /radiostatus/$shelf_id/$resource_id/$port_id - - When requesting specific column names, they need to be URL encoded: - _links, antenna, ap, capabilities, channel, country, driver, entity+id, firmware+version, - frag, frequency, max_sta, max_vap, max_vifs, monitors_down, monitors_up, - phantom, port, resource, rts, stations_down, stations_up, tx-power, vaps_down, - vaps_up, verbose+debug - Example URL: /radiostatus?fields=_links,antenna - - Example py-json call (it knows the URL): - record = LFJsonGet.get_radiostatus(eid_list=['1.234', '1.344'], - requested_col_names=['firmware version'], - debug_=True) - - The record returned will have these members: - { - '_links': # - - 'antenna': # - - 'ap': # - - 'capabilities': # - - 'channel': # - - 'country': # - - 'driver': # - - 'entity id': # - - 'firmware version': # - - 'frag': # - - 'frequency': # - - 'max_sta': # - - 'max_vap': # - - 'max_vifs': # - - 'monitors_down': # - - 'monitors_up': # - - 'phantom': # - - 'port': # - - 'resource': # - - 'rts': # - - 'stations_down': # - - 'stations_up': # - - 'tx-power': # - - 'vaps_down': # - - 'vaps_up': # - - 'verbose debug': # - - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_radiostatus(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/radiostatus" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="radio", - plural_key="radios") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /resource/ - /resource/$shelf_id - /resource/$shelf_id/$resource_id - - When requesting specific column names, they need to be URL encoded: - bps-rx-3s, bps-tx-3s, cli-port, cpu, ctrl-ip, ctrl-port, eid, entity+id, - free+mem, free+swap, gps, hostname, hw+version, load, max+if-up, max+staged, - mem, phantom, ports, rx+bytes, shelf, sta+up, sw+version, swap, tx+bytes, - # hidden columns: - timestamp - Example URL: /resource?fields=bps-rx-3s,bps-tx-3s - - Example py-json call (it knows the URL): - record = LFJsonGet.get_resource(eid_list=['1.234', '1.344'], - requested_col_names=['entity id'], - debug_=True) - - The record returned will have these members: - { - 'bps-rx-3s': # Rate in bits-per-second that the manager issending management data to - # the resource, averaged over the last 3 seconds.This is TCP payload data, - # and does not count the IP and Ethernet overhead. - 'bps-tx-3s': # Rate in bits-per-second that the manager isreceiving management data - # from the resource, averaged over the last 3 seconds.This is TCP payload - # data, and does not count the IP and Ethernet overhead. - 'cli-port': # Text (telnet) interface IP Port. - 'cpu': # CPU information for the machine. - 'ctrl-ip': # IP Address of the Control Interface. - 'ctrl-port': # Binary interface IP Port. - 'eid': # Resource EID (Shelf.Resource). - 'entity id': # Entity ID - 'free mem': # Free Memory (Kbytes) in the machine. If this is too low, performance - # will be degraded. - 'free swap': # Free Swap (Kbytes) in the machine. If this is too low, performance will - # be degraded. - 'gps': # GPS Info for this machine, if GPS is attached. - 'hostname': # The name for this resource, as reported by the resource. - 'hw version': # Hardware version on the machine. - 'load': # Unix process load.. - 'max if-up': # Max number of interface-config scripts try to run at once. - 'max staged': # Max number of interfaces the system will try to bringup at once. - 'mem': # Total memory (Kbytes) on the machine. - 'phantom': # Is the resource PHANTOM (undiscovered) or not. - 'ports': # All real and phantom ports on this machine. - 'rx bytes': # Total management TCP payload bytes received from the manager process by - # this resource. - 'shelf': # Number of shelf that this resource belongs to. - 'sta up': # Max number of stations to bring up per radio per 0.25s tick. - 'sw version': # LANforge Software version running on the machine. - 'swap': # Total swap space (Kbytes) on the machine. - 'tx bytes': # Total management TCP payload bytes sent from this resource to the - # manager process. - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_resource(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/resource" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="resource", - plural_key="resources") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /scan-results/ - /scan-results/$shelf_id/$resource_id/$port_id - /scan-results/$shelf_id/$resource_id/$port_id/$bssid - /scan/ - /scan/$shelf_id/$resource_id/$port_id - /scan/$shelf_id/$resource_id/$port_id/$bssid - /scanresults/ - /scanresults/$shelf_id/$resource_id/$port_id - /scanresults/$shelf_id/$resource_id/$port_id/$bssid - - - Example py-json call (it knows the URL): - record = LFJsonGet.get_scan(eid_list=['1.234', '1.344'], - debug_=True) - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_scan(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/scan" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="scan-results", - plural_key="scan-results") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /stations/ - /stations/$mac - - When requesting specific column names, they need to be URL encoded: - ap, auth-for, capabilities, entity+id, idle, roam-duration, rx+bytes, rx+pkts, - rx+rate, signal, station+bssid, tx+bytes, tx+pkts, tx+rate, tx+retries, tx-failed, - - Example URL: /stations?fields=ap,auth-for - - Example py-json call (it knows the URL): - record = LFJsonGet.get_stations(eid_list=['1.234', '1.344'], - requested_col_names=['entity id'], - debug_=True) - - The record returned will have these members: - { - 'ap': # The Port that owns this station. - 'auth-for': # Duration in seconds this station has been authenticated. - 'capabilities': # Station's negotiated capabilities. - 'entity id': # Entity ID - 'idle': # Miliseconds since this station last received a frame from the peer. - 'roam-duration': # The difference between the authenticate-time on the new APand the last - # frame received on old AP, in milliseconds.It is not always possible to - # compute this accurately,especially if traffic is not flowing during the - # roam. - 'rx bytes': # RX Byte counter for this station. - 'rx pkts': # RX Packets counter for this station. - 'rx rate': # Station last received encoding rate. - 'signal': # Station signal quality. - 'station bssid': # Station's MAC address (BSSID). - 'tx bytes': # TX Byte counter for this station. - 'tx pkts': # TX Packets counter for this station. - 'tx rate': # Station transmit encoding rate. - 'tx retries': # TX Retries counter for this station.This counts retries at the driver - # level.Retries made by the WiFi hardware and/or firmware is not counted. - 'tx-failed': # TX Failed counter for this station.This counts TX failures at the driver - # level.The hardware and/or firmware may have made several failed attempts - # that are not included in this counter. - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_stations(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/stations" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="station", - plural_key="stations") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /status-msg/ - /status-msg/$session - /status-msg/$session/$id - /status-msg/$session/$id/ws-msg,... - /status-msg/$session/all - /status-msg/$session/this - /status-msg/sessions - - - Example py-json call (it knows the URL): - record = LFJsonGet.get_status_msg(eid_list=['1.234', '1.344'], - debug_=True) - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_status_msg(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/status-msg" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="sessions/messages", - plural_key="sessions/messages") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /test-group/ - /test-group/$id - /test-groups/ - /test-groups/$id - - When requesting specific column names, they need to be URL encoded: - cross+connects, entity+id, name, run, script - Example URL: /test-group?fields=cross+connects,entity+id - - Example py-json call (it knows the URL): - record = LFJsonGet.get_test_group(eid_list=['1.234', '1.344'], - requested_col_names=['entity id'], - debug_=True) - - The record returned will have these members: - { - 'cross connects': # List of Test Manager's Cross-Connects. - 'entity id': # Entity ID - 'name': # Test Group's Name. - 'run': # Is Test Group running or not. - 'script': # Endpoint script state. - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_test_group(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/test-group" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="groups", - plural_key="groups") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /text/ - /text/$group - /text/$group/$class - /text/$group/$class/$key - - When requesting specific column names, they need to be URL encoded: - eid, name, text, type - Example URL: /text?fields=eid,name - - Example py-json call (it knows the URL): - record = LFJsonGet.get_text(eid_list=['1.234', '1.344'], - requested_col_names=['text'], - debug_=True) - - The record returned will have these members: - { - 'eid': # - - 'name': # - - 'text': # - - 'type': # - - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_text(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/text" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="record", - plural_key="records") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /voip-endp/ - /voip-endp/$endp_id - /voip-ep/ - /voip-ep/$endp_id - /voip/ - /voip/$cx_id - /voip_endp/ - /voip_endp/$endp_id - /voip_ep/ - /voip_ep/$endp_id - - When requesting specific column names, they need to be URL encoded: - bps+rx+a, bps+rx+b, delay+a+%E2%86%90+b, delay+a+%E2%86%92+b, eid, endpoints+%28a%C2%A0%E2%86%94%C2%A0b%29, - entity+id, jitter+a+%E2%86%90+b, jitter+a+%E2%86%92+b, name, pkt+tx+a%C2%A0%E2%86%90%C2%A0b, - pkt+tx+a%C2%A0%E2%86%92%C2%A0b, rpt+timer, rx+drop+%25+a, rx+drop+%25+b, state, - type - Example URL: /voip?fields=bps+rx+a,bps+rx+b - - Example py-json call (it knows the URL): - record = LFJsonGet.get_voip(eid_list=['1.234', '1.344'], - requested_col_names=['entity id'], - debug_=True) - - The record returned will have these members: - { - 'bps rx a': # Endpoint B's real transmit rate (bps).Measured at the CX Type layer. - 'bps rx b': # Endpoint A's real transmit rate (bps).Measured at the CX Type layer. - 'delay a ← b': # Average Latency in milliseconds for traffic from Endpoint B to Endpoint - # A - 'delay a → b': # Average Latency in milliseconds for traffic from Endpoint A to Endpoint - # B - 'eid': # Entity ID - 'endpoints (a ↔ b)': # Endpoints that make up this Cross Connect. - 'entity id': # Entity ID - 'jitter a ← b': # Average Jitter in milliseconds for traffic from Endpoint B to Endpoint A - 'jitter a → b': # Average Jitter in milliseconds for traffic from Endpoint A to Endpoint B - 'name': # Cross Connect's Name. - 'pkt tx a ← b': # Endpoint B's Packets Transmitted. - 'pkt tx a → b': # Endpoint A's Packets Transmitted. - 'rpt timer': # Cross Connect's Report Timer (milliseconds).This is how often the GUI - # will ask for updates from the LANforge processes.If the GUI is sluggish, - # increasing the report timers may help. - 'rx drop % a': # Endpoint A percentage packet loss.Calculated using the number of PDUs - # Endpoint B sent minus the number Endpoint A received.This number is not - # 100% correct as long as packets are in flight.After a Quiesce of the - # test, the number should be perfectly accurate. - 'rx drop % b': # Endpoint B percentage packet loss.Calculated using the number of PDUs - # Endpoint A sent minus the number Endpoint B received.This number is not - # 100% correct as long as packets are in flight.After a Quiesce of the - # test, the number should be perfectly accurate. - 'state': # Current State of the connection.UninitializedHas not yet been - # started/stopped.InitializingBeing set up.StartingStarting the - # test.RunningTest is actively running.StoppedTest has been - # stopped.QuiesceTest will gracefully stop soon.HW-BYPASSTest is in - # hardware-bypass mode (WanLinks only)FTM_WAITTest wants to run, but is - # phantom, probably due to non-existent interface or resource.WAITINGWill - # restart as soon as resources are available.PHANTOMTest is stopped, and - # is phantom, probably due to non-existent interface or resource. - 'type': # Cross-Connect type. - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_voip(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/voip" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="connection", - plural_key="connections") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /voip-endp/ - /voip-endp/$endp_id - - When requesting specific column names, they need to be URL encoded: - calls+answered, calls+attempted, calls+completed, calls+failed, cf+404, cf+408, - cf+busy, cf+canceled, delay, destination+addr, dropped, dup+pkts, eid, elapsed, - entity+id, jb+cur, jb+over, jb+silence, jb+under, jitter, mng, name, ooo+pkts, - pesq, pesq+bklg, pesq%23, reg+state, rst, rtp+rtt, run, rx+bytes, rx+pkts, - source+addr, state, tx+bytes, tx+pkts, vad+pkts - Example URL: /voip-endp?fields=calls+answered,calls+attempted - - Example py-json call (it knows the URL): - record = LFJsonGet.get_voip_endp(eid_list=['1.234', '1.344'], - requested_col_names=['entity id'], - debug_=True) - - The record returned will have these members: - { - 'calls answered': # Number of calls that where the remote answered - 'calls attempted': # Number of calls that have been attempted - 'calls completed': # Number of calls that have been successfully completed - 'calls failed': # Number of calls that did not succeed for any reason. - 'cf 404': # Number of calls failed for '404': callee not found. - 'cf 408': # Number of calls failed for '408': callee did not answer. - 'cf busy': # Number of calls failed because callee is busy. - 'cf canceled': # Number of calls failed because they were canceled. - 'delay': # Average latency in milliseconds for packets received by this endpoint. - 'destination addr': # Destination Address (MAC, ip/port, VoIP destination). - 'dropped': # Total dropped packets, as identified by gaps in RTP sequence numbers - # (pre jitter buffer). - 'dup pkts': # Total duplicate packets, as identified by RTP sequence numbers (pre - # jitter buffer). - 'eid': # Entity ID - 'elapsed': # Amount of time (seconds) this endpoint has been running (or ran.) - 'entity id': # Entity ID - 'jb cur': # Current number of packets in the jitter buffer waiting to be played / - # Jitter Buffer Size. - 'jb over': # Total times the jitter buffer was given more packets than it could hold. - 'jb silence': # Silence is played when there is no valid voice packet, due to drop, or - # reorder/jitter/latency out of range of the jitter buffer. - 'jb under': # Total times the reader asked for a packet to play but the jitter buffer - # was empty. - 'jitter': # Average interpacket variation, calculated per RFC 1889 A.8. - 'mng': # Is the Endpoint managed or not? - 'name': # Endpoint's Name. - 'ooo pkts': # Total out-of-order packets, as identified by RTP sequence numbers (pre - # jitter buffer). - 'pesq': # PESQ Report score for the PESQ report number (PESQ#). - 'pesq bklg': # PESQ server call processing backlog. - 'pesq#': # The pesq-report-number to which the PESQ value cooresponds. - 'reg state': # Current State of the Endpoint. - 'rst': # How many times has the endpoint been restarted due to abnormal - # termination. - 'rtp rtt': # Round trip latency as reported by RTCP - 'run': # Is the Endpoint is Running or not. - 'rx bytes': # Total received bytes count. - 'rx pkts': # Total received packet count. - 'source addr': # Source Address (MAC, ip/port, VoIP source). - 'state': # Phone registration state - 'tx bytes': # Total transmitted bytes count. - 'tx pkts': # Total transmitted packet count. - 'vad pkts': # Total VAD (Silence Suppression) packets suppressed before transmit. - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_voip_endp(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/voip-endp" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="endpoint", - plural_key="endpoints") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /vr-cx/ - /vr-cx/$shelf_id/$resource_id/$port_id - /vr/ - /vr/$shelf_id/$resource_id - /vrcx/ - /vrcx/$shelf_id/$resource_id/$port_id - - When requesting specific column names, they need to be URL encoded: - active+ipv6+router, bgp+4byte+as, bgp+damping, bgp+peers, cluster+id, collision+domain+id, - confederation+id, damping+half+life, damping+max+suppress, damping+reuse, - damping+suppress, entity+id, height, ipv6+radv, is+bgp+reflector, local+as, - multicast+routing, name, netsmith-state, notes, pad, ripv2, router+connections, - router+id, router+id, use+confederation, use+existing+cfg, use+ospf, use+rip+dft+route, - using+bgp, using+olsr, width, x, xorp+sha, y - Example URL: /vr?fields=active+ipv6+router,bgp+4byte+as - - Example py-json call (it knows the URL): - record = LFJsonGet.get_vr(eid_list=['1.234', '1.344'], - requested_col_names=['netsmith-state'], - debug_=True) - - The record returned will have these members: - { - 'active ipv6 router': # - - 'bgp 4byte as': # - - 'bgp damping': # lc_key > lc_col_name- - 'bgp peers': # - - 'cluster id': # - - 'collision domain id': # - - 'confederation id': # - - 'damping half life': # - - 'damping max suppress': # - - 'damping reuse': # - - 'damping suppress': # - - 'entity id': # Entity ID - 'height': # - - 'ipv6 radv': # - - 'is bgp reflector': # - - 'local as': # - - 'multicast routing': # - - 'name': # Name - 'netsmith-state': # - - 'notes': # - - 'pad': # - - 'ripv2': # - - 'router connections': # - - 'router id': # - - 'router id': # - - 'use confederation ': # - - 'use existing cfg': # - - 'use ospf': # - - 'use rip dft route': # - - 'using bgp': # - - 'using olsr': # - - 'width': # - - 'x': # - - 'xorp sha': # - - 'y': # - - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_vr(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/vr" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="virtual-routers", - plural_key="virtual-routers") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /vrcx/ - /vrcx/$shelf_id/$resource_id/$port_id - - When requesting specific column names, they need to be URL encoded: - entity+id, height, interface+cost, local-a, local-b, netsmith-state, remote-a, - remote-b, resource, rip+metric, vrrp+id, vrrp+interval, vrrp+ip, vrrp+ip-prefix, - vrrp+priority, wan+link, width, x, y - Example URL: /vrcx?fields=entity+id,height - - Example py-json call (it knows the URL): - record = LFJsonGet.get_vrcx(eid_list=['1.234', '1.344'], - requested_col_names=['netsmith-state'], - debug_=True) - - The record returned will have these members: - { - 'entity id': # - - 'height': # - - 'interface cost': # - - 'local-a': # - - 'local-b': # - - 'netsmith-state': # - - 'remote-a': # - - 'remote-b': # - - 'resource': # - - 'rip metric': # - - 'vrrp id': # - - 'vrrp interval': # - - 'vrrp ip': # - - 'vrrp ip-prefix': # - - 'vrrp priority': # - - 'wan link': # - - 'width': # - - 'x': # - - 'y': # - - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_vrcx(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/vrcx" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="router-connections", - plural_key="router-connections") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /wl-endp/ - /wl-endp/$wl_ep_id - /wl-ep/ - /wl-ep/$wl_ep_id - /wl/ - /wl/$wl_id - /wl_endp/ - /wl_endp/$wl_ep_id - /wl_ep/ - /wl_ep/$wl_ep_id - /wlendp/$wl_ep_id - - When requesting specific column names, they need to be URL encoded: - bps+rx+a, bps+rx+b, eid, endpoints+%28a%C2%A0%E2%86%94%C2%A0b%29, entity+id, k-m, - name, pkt+tx+a%C2%A0%E2%86%90%C2%A0b, pkt+tx+a%C2%A0%E2%86%92%C2%A0b, rpt+timer, - state - Example URL: /wl?fields=bps+rx+a,bps+rx+b - - Example py-json call (it knows the URL): - record = LFJsonGet.get_wl(eid_list=['1.234', '1.344'], - requested_col_names=['entity id'], - debug_=True) - - The record returned will have these members: - { - 'bps rx a': # Endpoint B's Max transmit rate (bps). - 'bps rx b': # Endpoint A's Max transmit rate (bps). - 'eid': # Entity ID - 'endpoints (a ↔ b)': # Endpoints that make up this WanLink. - 'entity id': # Entity ID - 'k-m': # Whether the WanLink is Kernel-Mode or not. - 'name': # WanLink's Name. - 'pkt tx a ← b': # Packets received on endpoint B and transmitted out endpoint A. - 'pkt tx a → b': # Packets received on endpoint A and transmitted out endpoint B. - 'rpt timer': # Cross Connect's Report Timer (milliseconds).This is how often the GUI - # will ask for updates from the LANforge processes.If the GUI is sluggish, - # increasing the report timers may help. - 'state': # Current State of the connection.UninitializedHas not yet been - # started/stopped.InitializingBeing set up.StartingStarting the - # test.RunningTest is actively running.StoppedTest has been - # stopped.QuiesceTest will gracefully stop soon.HW-BYPASSTest is in - # hardware-bypass mode (WanLinks only)FTM_WAITTest wants to run, but is - # phantom, probably due to non-existent interface or resource.WAITINGWill - # restart as soon as resources are available.PHANTOMTest is stopped, and - # is phantom, probably due to non-existent interface or resource. - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_wl(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/wl" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="", - plural_key="") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /wl-endp/ - /wl-endp/$wl_ep_id - - When requesting specific column names, they need to be URL encoded: - buffer, corrupt+1, corrupt+2, corrupt+3, corrupt+4, corrupt+5, corrupt+6, - delay, dropfreq+%25, dropped, dup+pkts, dupfreq+%25, eid, elapsed, extrabuf, - failed-late, jitfreq+%25, max+rate, maxjitter, maxlate, name, ooo+pkts, qdisc, - reordfrq+%25, run, rx+bytes, rx+pkts, script, serdelay, tx+bytes, tx+drop+%25, - tx+pkts, tx+rate, tx-failed, wps - Example URL: /wl-endp?fields=buffer,corrupt+1 - - Example py-json call (it knows the URL): - record = LFJsonGet.get_wl_endp(eid_list=['1.234', '1.344'], - requested_col_names=['eid'], - debug_=True) - - The record returned will have these members: - { - 'buffer': # Maximum size of receive buffer, in bytes.This is the sum of the amount - # needed for the transit buffers (delay * bandwidth)plus the WanLink - # "Backlog Buffer:" queue size which handles bursts. - 'corrupt 1': # Counters for how many times this corruption has been applied. - 'corrupt 2': # Counters for how many times this corruption has been applied. - 'corrupt 3': # Counters for how many times this corruption has been applied. - 'corrupt 4': # Counters for how many times this corruption has been applied. - 'corrupt 5': # Counters for how many times this corruption has been applied. - 'corrupt 6': # Counters for how many times this corruption has been applied. - 'delay': # Base induced latency on received packets, in microseconds. - 'dropfreq %': # Frequency out of 1,000,000 to drop a received packet.Select a preset - # value or enter your own. - 'dropped': # Total dropped packets on receive.This does not include the tx-failed - # counters. - 'dup pkts': # Total duplicate packets generated. - 'dupfreq %': # Frequency out of 1,000,000 to duplicate a received packet.Select a - # preset value or enter your own. - 'eid': # Entity ID - 'elapsed': # Amount of time (seconds) this endpoint has been running (or ran.) - 'extrabuf': # Size of "Backlog Buffer:" setting in WanLink configuration in bytes. - 'failed-late': # Total amount of received packets that could not be transmitted out the - # peer becausethe emulator was overloaded and could not transmit within - # the specified 'lateness' - 'jitfreq %': # Frequency out of 1,000,000 that packets should have jitter applied to - # them.Select a preset value or enter your own. - 'max rate': # Max transmit rate (bps) for this Endpoint. - 'maxjitter': # Maximum additional delay, in microseconds. See Jitter-Frequency as - # well. - 'maxlate': # The maximum lateness in milliseconds allowed before packets will be - # dropped on transmit.If lateness is configured to be automatic, this - # variable will change based onconfigured bandwidth and backlog buffer, - # but will not go below 10ms. - 'name': # Endpoint's Name. - 'ooo pkts': # Total out of order packets generated. - 'qdisc': # Queueing discipline (FIFO, WRR, etc). - 'reordfrq %': # Frequency out of 1,000,000 to re-order a received packet.Select a preset - # value or enter your own. - 'run': # Is the Endpoint is Running or not. - 'rx bytes': # Total received bytes count. - 'rx pkts': # Total received packet count. - 'script': # Endpoint script state. - 'serdelay': # Additional serialization delay for a 1514 byte packet at the configured - # speed (microseconds). - 'tx bytes': # Total transmitted bytes count. - 'tx drop %': # Packet drop percentage over the last 1 minute. - 'tx pkts': # Packets received on the peer interface and transmitted out this - # endpoint's interface. - 'tx rate': # The average speed over the last 30 seconds at which we are - # transmittingout the peer interface.This can be thought of as the actual - # transfer rate for packets entering the interfaceassociated with this - # Endpoint. - 'tx-failed': # Total amount of received packets that could not be transmitted out the - # peer.This includes any tx-failed-late packets. - 'wps': # Enable/Disable showing of WanPaths for individual endpoints. - } - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_wl_endp(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/wl-endp" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="endpoint", - plural_key="endpoint") - # - """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - Notes for type requests - - If you need to call the URL directly, - request one of these URLs: - /ws-msg/ - /ws-msg/$sessionid - - - Example py-json call (it knows the URL): - record = LFJsonGet.get_ws_msg(eid_list=['1.234', '1.344'], - debug_=True) - ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - def get_ws_msg(self, - eid_list=None, - requested_col_names=(), - debug_=False): - debug_ |= self.debug - url = "/ws-msg" - if (eid_list is None) or (len(eid_list) < 1): - raise ValueError("no entity id in request") - trimmed_fields = [] - if isinstance(requested_col_names, str): - if not requested_col_names.strip(): - raise ValueError("column name cannot be blank") - trimmed_fields.append(requested_col_names.strip()) - if isinstance(requested_col_names, list): - for field in requested_col_names: - if not field.strip(): - raise ValueError("column names cannot be blank") - field = field.strip() - if field.find(" ") > -1: - raise ValueError("field should be URL encoded: [%s]" % field) - trimmed_fields.append(field) - url += self.make_eid_url(eid_list=eid_list) - - if len(trimmed_fields) > 0: - url += "?fields=%s" % (",".join(trimmed_fields)) - - response = self.json_get(url, debug_=debug_) - if response is None: - return None - return self.extract_values(response=response, - singular_key="", - plural_key="") - # - - -"""----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - - These are POST requests - ------ ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - - -class LFJsonPost(LFCliBase): - def __init__(self, lfclient_host='localhost', - lfclient_port=8080, - debug_=False, - _exit_on_error=False, - _exit_on_fail=False, - _proxy_str=None, - _capture_signal_list=()): - super().__init__(_lfjson_host=lfclient_host, - _lfjson_port=lfclient_port, - _debug=debug_, - _exit_on_error=_exit_on_error, - _exit_on_fail=_exit_on_fail, - _proxy_str=_proxy_str, - _capture_signal_list=_capture_signal_list) +class JsonQuery(BaseLFJsonRequest): + """ ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + request LANforge JSON data with knowledge of the LANforge JSON headers + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- """ + + def __init__(self, + session_obj: 'BaseSession' = None, + debug=False, + exit_on_error=False): + super().__init__(session_obj=session_obj, + debug=debug | session_obj.is_debug(), + exit_on_error=exit_on_error) + + +class JsonCommand(BaseLFJsonRequest): + def __init__(self, + session_obj: object = None, + debug: bool = False, + exit_on_error: bool = False): + super().__init__(session_obj=session_obj, + debug=debug, + exit_on_error=exit_on_error) + self.logger.debug("%s new instance " % str(__class__)) @staticmethod def set_flags(flag_class: IntFlag, starting_value: int, flag_names=None): @@ -2495,7 +872,7 @@ class LFJsonPost(LFCliBase): :param starting_value: integer flag value to OR values into :param flag_names: list of flag names to convert to integers to OR onto starting_value - Example Usage: + Example Usage: value = LFJsonPost.add_flags(SetPortMumble, 0, flag_names=['bridge', 'dhcp']) print('value now: '+value) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" @@ -2511,13 +888,13 @@ class LFJsonPost(LFCliBase): raise ValueError("%s lacks member:[%s]" % (flag_class.__class__.__name__, flag)) selected_flags.extend([flag_class[member].value - for member in flag_class.__members__ if member == flag]) + for member in flag_class.__members__ if member == flag]) if isinstance(flag, IntFlag): if flag not in flag_class: raise ValueError("%s lacks member:[%s]" % (flag_class.__class__.__name__, flag)) selected_flags.extend([member.value - for member in flag_class.__members___ if member == flag]) + for member in flag_class.__members___ if member == flag]) selected_flags.append(starting_value) result_flags = 0 for i in selected_flags: @@ -2541,7 +918,7 @@ class LFJsonPost(LFCliBase): :param starting_value: integer flag value to OR values into :param flag_names: list of flag names to convert to integers to OR onto starting_value - Example Usage: + Example Usage: value = LFJsonPost.clear_flags(SetPortMumble, 0, flag_names=['bridge', 'dhcp']) print('value now: '+value) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" @@ -2575,29 +952,266 @@ class LFJsonPost(LFCliBase): unselected_val = starting_value unselected_val &= ~flag_names.value return unselected_val + + def start_session(self, + debug: bool = False, + die_without_session_id_: bool = False) -> bool: + responses = [] + debug |= self.debug_on + if not self.session_instance: + raise ValueError("JsonCommand::start_session lacks self.session_instance") + + first_response: HTTPResponse + errors_warnings: list = [] + first_response = self.json_post(url="/newsession", + debug=False, + errors_warnings=errors_warnings, + response_json_list=responses) + if not first_response: + self.logger.warning("No session established.") + self.logger.debug(pformat(first_response)) + self.logger.debug(pformat(responses)) + self.logger.warning(pformat(errors_warnings)) + if die_without_session_id_: + exit(1) + return False + # first_response.msg is HttpMessage not a string + elif first_response.status != 200: + self.logger.error("Error starting session msg: %s" % pformat(first_response.headers)) + self.logger.warning(pformat(errors_warnings)) + if die_without_session_id_: + exit(1) + return False + + if debug: + self.logger.debug("%s: newsession: %s" % (__name__, pformat(first_response))) + # self.session_instance.session_id = first_response["session_id"] + self.logger.debug(pformat(("start_session headers:", + first_response.getheaders()))) + if SESSION_HEADER not in first_response.headers: + self.logger.error("start_session: no %s in response headers:" % SESSION_HEADER) + self.logger.error(pformat(first_response.headers)) + self.logger.warning(pformat(errors_warnings)) + if die_without_session_id_: + exit(1) + return False + + self.session_id = first_response.getheader(SESSION_HEADER) + self.session_instance.session_id = first_response.getheader(SESSION_HEADER) + return True + + +class BaseSession: + """ + Use this class to make your initial connection to a LANforge GUI. This class can + will create a session id and hold errors and warnings as needed. + """ + + Default_Base_URL: str = "http://localhost:8080" + Default_Retry_Sec: float = 1.0 + Default_Request_Timeout_Sec: float = 120.0 + Default_Max_Timeout_Sec: float = 240.0 + subclasses = [] + + def __init_subclass__(cls, **kwargs): + super().__init_subclass__(**kwargs) + cls.subclasses.append(cls) + + def __init__(self, lfclient_url: str = 'http://localhost:8080', + debug: bool = False, + proxy_map: dict = None, + connection_timeout_sec: float = Default_Request_Timeout_Sec, + max_timeout_sec: float = Default_Max_Timeout_Sec, + retry_sec: float = Default_Retry_Sec, + stream_errors: bool = True, + stream_warnings: bool = False, + exit_on_error: bool = False): + self.debug_on = debug + self.logger = Logg(name='json_api_session') + if debug: + self.logger.level = logging.DEBUG + self.exit_on_error = exit_on_error + self.command_instance: JsonCommand + self.connection_timeout_sec: int = 10 + self.debug_on: bool + self.debug_on = False + self.exit_on_error: bool + self.exit_on_error = False + self.lfclient_url: str + self.max_timeout_sec: float + self.max_timeout_sec = max_timeout_sec + self.proxies_installed: bool + self.proxies_installed = False + self.proxy_map: dict + self.query_instance: JsonQuery + self.query_instance = None + self.retry_sec: float + self.retry_sec = retry_sec + self.session_error_list: list = [] + self.session_id: str + self.session_id = None + self.session_warnings_list: list = [] + self.stream_errors: bool + self.stream_errors = True + self.stream_warnings: bool + self.stream_warnings = False + self.session_connection_check: bool + self.session_connection_check = False + self.session_started_at: int = 0 + + # please see this discussion on ProxyHandlers: + # https://docs.python.org/3/library/urllib.request.html#urllib.request.ProxyHandler + # but this makes much more sense: + # https://gist.github.com/aleiphoenix/4159510 + + if debug: + if proxy_map is None: + self.logger.debug("%s: no proxy_str" % __class__) + else: + self.logger.debug("BaseSession.__init__: proxies_: %s" % pformat(proxy_map)) + + if (proxy_map is not None) and (len(proxy_map) > 0): + if ("http" not in proxy_map) and ("https" not in proxy_map): + raise ValueError("Neither http or https set in proxy definitions. Expects proxy={'http':, 'https':, }") + self.proxy_map = proxy_map + if (proxy_map is not None) and (len(proxy_map) > 0): + opener = urllib.request.build_opener(request.ProxyHandler(proxy_map)) + urllib.request.install_opener(opener) + self.proxies_installed = True + + if connection_timeout_sec: + self.connection_timeout_sec = connection_timeout_sec + self.logger.debug("%s connection timeout sec now [%f]" % (__name__, connection_timeout_sec)) + + self.stream_errors = stream_errors + self.stream_warnings = stream_warnings + + # if debug: + # if self.proxies is None: + # print("BaseSession _init_: no proxies") + # else: + # print("BaseSession _init_: proxies: ") + # pprint.pprint(self.proxies) + + if not lfclient_url.startswith("http://") and not lfclient_url.startswith("https://"): + self.logger.warning("No http:// or https:// found, prepending http:// to " + lfclient_url) + lfclient_url = "http://" + lfclient_url + + # we do not want the lfclient_url to end with a slash + if lfclient_url.endswith('/'): + self.lfclient_url = lfclient_url[0: len(lfclient_url) - 1] + else: + self.lfclient_url = lfclient_url + + # test connection with GUI to get a session id, then set our session ids in those instances + # self.session_connection_check = self.command_instance.start_session(debug=debug) + self.command_instance = None + self.query_instance = None + + # indicate session destroyed if possible + def __del__(self): + if not self.session_connection_check: + self.logger.warning("%s no connection established, exiting" % self.session_connection_check) + return + self.logger.debug("%s: asking for session %s to end" % (__name__, self.session_id)) + BaseSession.end_session(command_obj=self.command_instance, + session_id_=self.session_id, + debug=False) + + def get_command(self) -> 'JsonCommand': + """ + Remember to override this method with your session subclass, it should return LFJsonCommand + :return: registered instance of JsonCommand + """ + if self.command_instance: + return self.command_instance + self.command_instance = JsonCommand(session_obj=self) + return self.command_instance + + def get_query(self) -> 'JsonQuery': + """ + Remember to override this method with your session subclass, it should return LFJsonQuery + :return: registered instance of JsonQuery + """ + if self.query_instance: + return self.query_instance + self.query_instance = JsonQuery(session_obj=self, debug=self.debug_on) + return self.query_instance + + def is_exit_on_error(self) -> bool: + return self.exit_on_error + + def get_lfclient_url(self) -> str: + return self.lfclient_url + + def get_lf_client_error(self) -> str: + return self.lfclient_url + + def is_debug(self) -> bool: + return self.debug_on + + def get_session_id(self) -> str: + return self.session_id + + def get_proxies(self): + return self.proxy_map + + def get_timeout_sec(self) -> float: + return self.connection_timeout_sec + + @classmethod + def end_session(cls, + command_obj: JsonCommand = None, + session_id_: str = "", + debug: bool = False): + responses = [] + command_obj.debug_on = False + command_obj.json_post(url="endsession", + debug=debug, + response_json_list=responses, + session_id_=session_id_) + +# End of json_api.py; subclasses defined below + + +class LFJsonCommand(JsonCommand): + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + LFJsonCommand inherits from JsonCommand + Commands are used for POST requests. + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + def __init__(self, + session_obj: object = None, + debug: bool = False, + exit_on_error: bool = False): + super().__init__(session_obj=session_obj, + debug=debug, + exit_on_error=exit_on_error) + + # Auto generated methods follow: + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Notes for type requests https://www.candelatech.com/lfcli_ug.php#add_arm_endp ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_arm_endp(self, - alias=None, # Name of endpoint. - cpu_id=None, # Preferred CPU ID on which this endpoint should run. - mx_pkt_sz=None, # Maximum packet size, including all Ethernet headers. - pkt_sz=None, # Minimum packet size, including all Ethernet headers. - port=None, # Port number. - pps=None, # Packets per second to generate. - resource=None, # Resource number. - shelf=None, # Shelf name/id. - tos=None, # The Type of Service, can be HEX. See set_endp_tos for details. - p_type=None, # Endpoint Type : arm_udp - debug_=False): + alias: str = None, # Name of endpoint. [R] + cpu_id: str = None, # Preferred CPU ID on which this endpoint should run. + mx_pkt_sz: str = None, # Maximum packet size, including all Ethernet headers. + pkt_sz: str = None, # Minimum packet size, including all Ethernet headers. + port: str = None, # Port number. [W] + pps: str = None, # Packets per second to generate. + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf name/id. Required. [R][D:1] + tos: str = None, # The Type of Service, can be HEX. See set_endp_tos for details. + p_type: str = None, # Endpoint Type : arm_udp. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_arm_endp(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if alias is not None: data["alias"] = alias @@ -2621,9 +1235,10 @@ class LFJsonPost(LFCliBase): data["type"] = p_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_arm_endp", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_arm_endp", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -2656,25 +1271,25 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_add_bgp_peer(self, - p_as=None, # BGP Peer Autonomous System number, 0-65535 - delay_open_time=None, # BGP Peer delay open time. - flags=None, # Virtual router BGP Peer flags, see above for definitions. - holdtime=None, # BGP Peer hold-time. - local_dev=None, # BGP Peer Local interface. - nexthop=None, # BGP Peer Nexthop, IPv4 Address. - nexthop6=None, # BGP Peer IPv6 Nexthop address. - peer_id=None, # BGP Peer Identifier: IPv4 Address - peer_index=None, # Peer index in this virtual router (0-7). - resource=None, # Resource number. - shelf=None, # Shelf name/id. - vr_id=None, # Name of virtual router. - debug_=False): + p_as: str = None, # BGP Peer Autonomous System number, 0-65535 + delay_open_time: str = None, # BGP Peer delay open time. + flags: str = None, # Virtual router BGP Peer flags, see above for definitions. + holdtime: str = None, # BGP Peer hold-time. + local_dev: str = None, # BGP Peer Local interface. + nexthop: str = None, # BGP Peer Nexthop, IPv4 Address. + nexthop6: str = None, # BGP Peer IPv6 Nexthop address. + peer_id: str = None, # BGP Peer Identifier: IPv4 Address + peer_index: str = None, # Peer index in this virtual router (0-7). + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf name/id. [R][D:1] + vr_id: str = None, # Name of virtual router. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_bgp_peer(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if p_as is not None: data["as"] = p_as @@ -2702,9 +1317,10 @@ class LFJsonPost(LFCliBase): data["vr_id"] = vr_id if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_bgp_peer", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_bgp_peer", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -2714,17 +1330,17 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_bond ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_bond(self, - network_devs=None, # Comma-separated list of network devices: eth1,eth2,eth3... - port=None, # Name of the bond device. - resource=None, # Resource number. - shelf=None, # Shelf number. - debug_=False): + network_devs: str = None, # Comma-separated list of network devices: eth1,eth2,eth3... [W] + port: str = None, # Name of the bond device. [W] + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_bond(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if network_devs is not None: data["network_devs"] = network_devs @@ -2736,9 +1352,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_bond", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_bond", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -2756,23 +1373,23 @@ class LFJsonPost(LFCliBase): stp_enabled = 1 # Enable Spanning Tree Protocol (STP) def post_add_br(self, - br_aging_time=None, # MAC aging time, in seconds, 32-bit number. - br_flags=None, # Bridge flags, see above. - br_forwarding_delay=None, # How long to wait until the bridge will start forwarding packets. - br_hello_time=None, # How often does the bridge send out STP hello packets. - br_max_age=None, # How long until STP considers a non-responsive bridge dead. - br_priority=None, # Bridge priority, 16-bit number. - network_devs=None, # Comma-separated list of network devices: eth1,eth2,eth3... - port=None, # Name of the bridge device. - resource=None, # Resource number. - shelf=None, # Shelf number. - debug_=False): + br_aging_time: str = None, # MAC aging time, in seconds, 32-bit number. + br_flags: str = None, # Bridge flags, see above. + br_forwarding_delay: str = None, # How long to wait until the bridge will start forwarding packets. + br_hello_time: str = None, # How often does the bridge send out STP hello packets. + br_max_age: str = None, # How long until STP considers a non-responsive bridge dead. + br_priority: str = None, # Bridge priority, 16-bit number. + network_devs: str = None, # Comma-separated list of network devices: eth1,eth2,eth3... + port: str = None, # Name of the bridge device. [W] + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_br(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if br_aging_time is not None: data["br_aging_time"] = br_aging_time @@ -2796,9 +1413,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_br", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_br", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -2816,22 +1434,22 @@ class LFJsonPost(LFCliBase): RUNNING = 1 # Set to running state. def post_add_cd(self, - alias=None, # Name of Collision Domain. - bps=None, # Maximum speed at which this collision domain can run. - flags=None, # See above. Leave blank or use 'NA' for no default values. - report_timer=None, # How often to report stats. - resource=None, # Resource number. - shelf=None, # Shelf name/id. - state=None, # RUNNING or STOPPED (default is RUNNING). Use this to start/stop. - p_type=None, # CD Type: WIFI, WISER_SURFACE, WISER_SURFACE_AIR, WISER_AIR_AIR, + alias: str = None, # Name of Collision Domain. [W] + bps: str = None, # Maximum speed at which this collision domain can run. + flags: str = None, # See above. Leave blank or use 'NA' for no default values. + report_timer: int = None, # How often to report stats. + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf name/id. [R][D:1] + state: str = None, # RUNNING or STOPPED (default is RUNNING). Use this to start/stop. + p_type: str = None, # CD Type: WIFI, WISER_SURFACE, WISER_SURFACE_AIR, WISER_AIR_AIR, # WISER_NCW - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_cd(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if alias is not None: data["alias"] = alias @@ -2851,9 +1469,10 @@ class LFJsonPost(LFCliBase): data["type"] = p_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_cd", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_cd", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -2863,15 +1482,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_cd_endp ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_cd_endp(self, - cd=None, # Name of Collision Domain. - endp=None, # Endpoint name/id. - debug_=False): + cd: str = None, # Name of Collision Domain. [R] + endp: str = None, # Endpoint name/id. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_cd_endp(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if cd is not None: data["cd"] = cd @@ -2879,9 +1498,10 @@ class LFJsonPost(LFCliBase): data["endp"] = endp if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_cd_endp", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_cd_endp", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -2891,15 +1511,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_cd_vr ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_cd_vr(self, - cd=None, # Name of Collision Domain. - vr=None, # Virtual-Router name/ID. - debug_=False): + cd: str = None, # Name of Collision Domain. [R] + vr: str = None, # Virtual-Router name/ID. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_cd_vr(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if cd is not None: data["cd"] = cd @@ -2907,9 +1527,10 @@ class LFJsonPost(LFCliBase): data["vr"] = vr if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_cd_vr", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_cd_vr", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -2940,35 +1561,56 @@ class LFJsonPost(LFCliBase): raise ValueError("AddChamberChamberFlags has no member:[%s]" % name) return (cls[member].value for member in cls.__members__ if member == name) + class AddChamberTurntableType(IntFlag): + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + This class is stateless. It can do binary flag math, returning the integer value. + Example Usage: + int:flag_val = 0 + flag_val = LFPost.set_flags(AddChamberTurntableType0, flag_names=['bridge', 'dhcp']) + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + COMXIM = 0x1 # ComXim stand-alone USB connected turn-table. + CT840A = 0x2 # Modbus API turntable in CT840A 2D chamber. + CT850A = 0x0 # TCP-IP Connected turntable in CT850A 2D chamber. + + # use to get in value of flag + @classmethod + def valueof(cls, name=None): + if name is None: + return name + if name not in cls.__members__: + raise ValueError("AddChamberTurntableType has no member:[%s]" % name) + return (cls[member].value for member in cls.__members__ if member == name) + def post_add_chamber(self, - chamber_type=None, # Chamber type, see above. Use 1 for Medium if uncertain. - dut_name1=None, # Name of first DUT in this chamber or NA - dut_name2=None, # Name of second DUT in this chamber or NA - dut_name3=None, # Name of third DUT in this chamber or NA - dut_name4=None, # Name of fourth DUT in this chamber or NA - flags=None, # Flag field for Chamber, see above. - flags_mask=None, # Mask of what flags to pay attention to, or NA for all. - height=None, # Height to be used when drawn in the LANforge-GUI. - isolation=None, # Estimated isolation in db for this chamber. - lanforge1=None, # EID of first LANforge Resource in this chamber or NA - lanforge2=None, # EID of second LANforge Resource in this chamber or NA - lanforge3=None, # EID of third LANforge Resource in this chamber or NA - lanforge4=None, # EID of fourth LANforge Resource in this chamber or NA - name=None, # Name of Chamber, unique identifier. - resource=None, # LANforge Resource ID for controlling turn-table via serial + chamber_type: str = None, # Chamber type, see above. Use 1 for Medium if uncertain. [W] + dut_name1: str = None, # Name of first DUT in this chamber or NA + dut_name2: str = None, # Name of second DUT in this chamber or NA + dut_name3: str = None, # Name of third DUT in this chamber or NA + dut_name4: str = None, # Name of fourth DUT in this chamber or NA + flags: str = None, # Flag field for Chamber, see above. [W] + flags_mask: str = None, # Mask of what flags to pay attention to, or NA for all. + height: str = None, # Height to be used when drawn in the LANforge-GUI. + isolation: str = None, # Estimated isolation in db for this chamber. + lanforge1: str = None, # EID of first LANforge Resource in this chamber or NA + lanforge2: str = None, # EID of second LANforge Resource in this chamber or NA + lanforge3: str = None, # EID of third LANforge Resource in this chamber or NA + lanforge4: str = None, # EID of fourth LANforge Resource in this chamber or NA + name: str = None, # Name of Chamber, unique identifier. [R] + resource: int = None, # LANforge Resource ID for controlling turn-table via serial # protocol. - sma_count=None, # Number of SMA connectors on this chamber, default is 16. - turntable_type=None, # Turn-Table type: see above. - width=None, # Width to be used when drawn in the LANforge-GUI. - x=None, # X coordinate to be used when drawn in the LANforge-GUI. - y=None, # Y coordinate to be used when drawn in the LANforge-GUI. - debug_=False): + sma_count: str = None, # Number of SMA connectors on this chamber, default is 16. + turntable_type: str = None, # Turn-Table type: see above. + width: str = None, # Width to be used when drawn in the LANforge-GUI. + x: str = None, # X coordinate to be used when drawn in the LANforge-GUI. + y: str = None, # Y coordinate to be used when drawn in the LANforge-GUI. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_chamber(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if chamber_type is not None: data["chamber_type"] = chamber_type @@ -3012,9 +1654,10 @@ class LFJsonPost(LFCliBase): data["y"] = y if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_chamber", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_chamber", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -3033,30 +1676,30 @@ class LFJsonPost(LFCliBase): TERMINATED = 2 # (2) Connection is terminated, signal shall not pass! def post_add_chamber_cx(self, - a_id=None, # EidAntenna in string format for A side connection. - atten_id=None, # EID for the Attenuator module if one is inline on this + a_id: str = None, # EidAntenna in string format for A side connection. + atten_id: str = None, # EID for the Attenuator module if one is inline on this # connection. - b_id=None, # EidAntenna in string format for B side connection. - connection_idx=None, # Connection index, currently up to 32 connections supported - # (0-31) - flags=None, # Flag field for Chamber Connection, see above. - flags_mask=None, # Mask of what flags to pay attention to, or NA for all. - internal=None, # Internal (1) or not (0): Internal connections are no longer + b_id: str = None, # EidAntenna in string format for B side connection. + connection_idx: str = None, # Connection index, currently up to 32 connections supported + # (0-31) [R] + flags: str = None, # Flag field for Chamber Connection, see above. + flags_mask: str = None, # Mask of what flags to pay attention to, or NA for all. + internal: str = None, # Internal (1) or not (0): Internal connections are no longer # supported. - min_atten=None, # Specify minimum attenuation in 10ths of a db. Distance logic - # will not set atten below this. - name=None, # Name of Chamber, unique identifier. - zrssi2=None, # Specify 2.4Ghz zero-attenuation RSSI in 10ths of a db. + min_atten: str = None, # Specify minimum attenuation in 10ths of a db. Distance + # logic will not set atten below this. + name: str = None, # Name of Chamber, unique identifier. [R] + zrssi2: str = None, # Specify 2.4Ghz zero-attenuation RSSI in 10ths of a db. # Distance logic will consider this in its calculations. - zrssi5=None, # Specify 5Ghz zero-attenuation RSSI in 10ths of a db. Distance - # logic will consider this in its calculations. - debug_=False): + zrssi5: str = None, # Specify 5Ghz zero-attenuation RSSI in 10ths of a db. + # Distance logic will consider this in its calculations. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_chamber_cx(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if a_id is not None: data["a_id"] = a_id @@ -3082,9 +1725,10 @@ class LFJsonPost(LFCliBase): data["zrssi5"] = zrssi5 if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_chamber_cx", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_chamber_cx", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -3094,17 +1738,17 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_chamber_path ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_chamber_path(self, - chamber=None, # Chamber Name. - content=None, # [BLANK] will erase all content, any other text will be appended - # to existing text. Unescaped Value - path=None, # Path Name - debug_=False): + chamber: str = None, # Chamber Name. [R] + content: str = None, # [BLANK] will erase all content, any other text will + # be appended to existing text. + path: str = None, # Path Name [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_chamber_path(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if chamber is not None: data["chamber"] = chamber @@ -3114,9 +1758,10 @@ class LFJsonPost(LFCliBase): data["path"] = path if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_chamber_path", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_chamber_path", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -3145,22 +1790,23 @@ class LFJsonPost(LFCliBase): unused = "unused" # No signalling is performed, each channel in the list remains idle def post_add_channel_group(self, - alias=None, # Name for this Channel Group. - channels=None, # List of channels to add to this group. - idle_flag=None, # Idle flag (byte) for this channel group, for instance: 0x7e - mtu=None, # MTU (and MRU) for this channel group. Must be a multiple of - # the number of channels if configuring a T1 WanLink. - resource=None, # Resource number. - shelf=None, # Shelf name/id. - span_num=None, # The span number. First span is 1, second is 2... - p_type=None, # The channel-type. Use 'clear' for PPP links. - debug_=False): + alias: str = None, # Name for this Channel Group. [R] + channels: str = None, # List of channels to add to this group. + idle_flag: str = None, # Idle flag (byte) for this channel group, for instance: + # 0x7e + mtu: str = None, # MTU (and MRU) for this channel group. Must be a multiple + # of the number of channels if configuring a T1 WanLink. + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf name/id. [R][D:1] + span_num: str = None, # The span number. First span is 1, second is 2... [W] + p_type: str = None, # The channel-type. Use 'clear' for PPP links. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_channel_group(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if alias is not None: data["alias"] = alias @@ -3180,9 +1826,10 @@ class LFJsonPost(LFCliBase): data["type"] = p_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_channel_group", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_channel_group", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -3192,17 +1839,17 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_cx ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_cx(self, - alias=None, # Name of the Cross Connect to create. - rx_endp=None, # Name of Receiving endpoint. - test_mgr=None, # Name of test-manager to create the CX on. - tx_endp=None, # Name of Transmitting endpoint. - debug_=False): + alias: str = None, # Name of the Cross Connect to create. [R] + rx_endp: str = None, # Name of Receiving endpoint. [W] + test_mgr: str = None, # Name of test-manager to create the CX on. [W][D:default_tm] + tx_endp: str = None, # Name of Transmitting endpoint. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_cx(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if alias is not None: data["alias"] = alias @@ -3214,9 +1861,10 @@ class LFJsonPost(LFCliBase): data["tx_endp"] = tx_endp if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_cx", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_cx", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -3258,43 +1906,42 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_add_dut(self, - antenna_count1=None, # Antenna count for first radio. - antenna_count2=None, # Antenna count for second radio. - antenna_count3=None, # Antenna count for third radio. - api_id=None, # DUT API Identifier (none specified yet) - bssid1=None, # BSSID for first radio. - bssid2=None, # BSSID for second radio. - bssid3=None, # BSSID for third radio. - eap_id=None, # EAP Identifier, for EAP-PEAP. - flags=None, # Flag field for DUT, see above. - flags_mask=None, # Optional mask to specify what DUT flags are being set. - hw_version=None, # DUT Hardware Version information - img_file=None, # File-Name for image to represent DUT. - lan_port=None, # IP/Mask for LAN port - mgt_ip=None, # Management IP Address to access DUT - model_num=None, # DUT Model information - name=None, # Name of DUT, cannot contain '.' - passwd1=None, # WiFi Password that can be used to connect to DUT - passwd2=None, # WiFi Password that can be used to connect to DUT - passwd3=None, # WiFi Password that can be used to connect to DUT - serial_num=None, # DUT Identifier (serial-number, etc) - serial_port=None, # Resource and Serial port name on LANforge that connects to DUT - # (1.2.ttyS0). Serial port does not need to be on resource holding - # wan_port or lan_port - ssid1=None, # WiFi SSID that can be used to connect to DUT - ssid2=None, # WiFi SSID that can be used to connect to DUT - ssid3=None, # WiFi SSID that can be used to connect to DUT - sw_version=None, # DUT Software Version information - top_left_x=None, # X Location for Chamber View. - top_left_y=None, # X Location for Chamber View. - wan_port=None, # IP/Mask for WAN port - debug_=False): + antenna_count1: str = None, # Antenna count for first radio. + antenna_count2: str = None, # Antenna count for second radio. + antenna_count3: str = None, # Antenna count for third radio. + api_id: str = None, # DUT API Identifier (none specified yet) + bssid1: str = None, # BSSID for first radio. + bssid2: str = None, # BSSID for second radio. + bssid3: str = None, # BSSID for third radio. + eap_id: str = None, # EAP Identifier, for EAP-PEAP. + flags: str = None, # Flag field for DUT, see above. [W] + flags_mask: str = None, # Optional mask to specify what DUT flags are being set. + hw_version: str = None, # DUT Hardware Version information + img_file: str = None, # File-Name for image to represent DUT. + lan_port: str = None, # IP/Mask for LAN port + mgt_ip: str = None, # Management IP Address to access DUT + model_num: str = None, # DUT Model information + name: str = None, # Name of DUT, cannot contain '.' [R] + passwd1: str = None, # WiFi Password that can be used to connect to DUT + passwd2: str = None, # WiFi Password that can be used to connect to DUT + passwd3: str = None, # WiFi Password that can be used to connect to DUT + serial_num: str = None, # DUT Identifier (serial-number, etc) + serial_port: str = None, # Resource and Serial port name on LANforge that connects to DUT + # (1.2.ttyS0). + ssid1: str = None, # WiFi SSID that can be used to connect to DUT + ssid2: str = None, # WiFi SSID that can be used to connect to DUT + ssid3: str = None, # WiFi SSID that can be used to connect to DUT + sw_version: str = None, # DUT Software Version information + top_left_x: str = None, # X Location for Chamber View. + top_left_y: str = None, # X Location for Chamber View. + wan_port: str = None, # IP/Mask for WAN port + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_dut(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if antenna_count1 is not None: data["antenna_count1"] = antenna_count1 @@ -3354,9 +2001,10 @@ class LFJsonPost(LFCliBase): data["wan_port"] = wan_port if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_dut", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_dut", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -3366,16 +2014,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_dut_notes ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_dut_notes(self, - dut=None, # DUT Name. - text=None, # [BLANK] will erase all, any other text will be appended to existing - # text. Unescaped Value - debug_=False): + dut: str = None, # DUT Name. [R] + text: str = None, # [BLANK] will erase all, any other text will be appended to + # existing text. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_dut_notes(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if dut is not None: data["dut"] = dut @@ -3383,9 +2031,10 @@ class LFJsonPost(LFCliBase): data["text"] = text if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_dut_notes", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_dut_notes", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -3421,20 +2070,20 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_add_dut_ssid(self, - bssid=None, # BSSID for cooresponding SSID. - name=None, # Name of DUT, cannot contain '.' - passwd=None, # WiFi Password that can be used to connect to DUT - ssid=None, # WiFi SSID that can be used to connect to DUT - ssid_flags=None, # SSID flags, see above. - ssid_flags_mask=None, # SSID flags mask - ssid_idx=None, # Index of the SSID. Zero-based indexing: (0 - 7) - debug_=False): + bssid: str = None, # BSSID for cooresponding SSID. + name: str = None, # Name of DUT, cannot contain '.' [R] + passwd: str = None, # WiFi Password that can be used to connect to DUT + ssid: str = None, # WiFi SSID that can be used to connect to DUT + ssid_flags: str = None, # SSID flags, see above. + ssid_flags_mask: str = None, # SSID flags mask + ssid_idx: str = None, # Index of the SSID. Zero-based indexing: (0 - 7) [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_dut_ssid(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if bssid is not None: data["bssid"] = bssid @@ -3452,9 +2101,10 @@ class LFJsonPost(LFCliBase): data["ssid_idx"] = ssid_idx if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_dut_ssid", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_dut_ssid", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -3498,36 +2148,36 @@ class LFJsonPost(LFCliBase): mc_udp = "mc_udp" # LF Multicast IPv4 def post_add_endp(self, - alias=None, # Name of endpoint. - ip_port=None, # IP Port: IP port for layer three endpoints. Use -1 to let the - # LANforge server automatically configure the ip_port. Layer 2 - # endpoints will ignore - is_pkt_sz_random=None, # Yes means use random sized packets, anything else means NO. - is_rate_bursty=None, # Yes means bursty, anything else means NO. - max_pkt=None, # Maximum packet size, including all headers. 0 means 'same', -1 - # means AUTO (5.3.2+) - max_rate=None, # Maximum transmit rate (bps), used if in bursty mode. - min_pkt=None, # Minimum packet size, including all headers. -1 means AUTO - # (5.3.2+) - min_rate=None, # Minimum transmit rate (bps), or only rate if not bursty. - multi_conn=None, # If > 0, will create separate process with this many connections - # per endpoint. See AUTO_HELPER flag - payload_pattern=None, # Payload pattern, see above. - port=None, # Port/Interface name or number. - resource=None, # Resource number. - send_bad_crc_per_million=None, # If NIC supports it, will randomly send X per million packets + alias: str = None, # Name of endpoint. [R] + ip_port: str = None, # IP Port: IP port for layer three endpoints. Use -1 to let + # the LANforge server automatically configure the ip_port. + # Layer 2 endpoints will ignore + is_pkt_sz_random: str = None, # Yes means use random sized packets, anything else means NO. + is_rate_bursty: str = None, # Yes means bursty, anything else means NO. + max_pkt: str = None, # Maximum packet size, including all headers. 0 means 'same', + # -1 means AUTO (5.3.2+) [D:0] + max_rate: str = None, # Maximum transmit rate (bps), used if in bursty mode. + min_pkt: str = None, # Minimum packet size, including all headers. -1 means AUTO + # (5.3.2+) [W][D:-1] + min_rate: str = None, # Minimum transmit rate (bps), or only rate if not bursty. [W] + multi_conn: str = None, # If > 0, will create separate process with this many + # connections per endpoint. See AUTO_HELPER flag + payload_pattern: str = None, # Payload pattern, see above. + port: str = None, # Port/Interface name or number. [R] + resource: int = None, # Resource number. [W] + send_bad_crc_per_million: str = None, # If NIC supports it, will randomly send X per million packets # with bad ethernet Frame Check Sum. - shelf=None, # Shelf name/id. - ttl=None, # Time-to-live, used by UDP Multicast Endpoints only. - p_type=None, # Endpoint Type: See above. - use_checksum=None, # Yes means checksum the payload, anything else means NO. - debug_=False): + shelf: int = 1, # Shelf name/id. [R][D:1] + ttl: str = None, # Time-to-live, used by UDP Multicast Endpoints only. + p_type: str = None, # Endpoint Type: See above. [W] + use_checksum: str = None, # Yes means checksum the payload, anything else means NO. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_endp(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if alias is not None: data["alias"] = alias @@ -3565,9 +2215,10 @@ class LFJsonPost(LFCliBase): data["use_checksum"] = use_checksum if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_endp", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_endp", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -3577,17 +2228,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_event ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_event(self, - details=None, # Event text description. Cannot include double-quote characters. - event_id=None, # Numeric ID for the event to modify, or 'new' if creating a new one. - name=None, # Event entity name. - priority=None, # See set_event_priority for available priorities. - debug_=False): + details: str = None, # Event text description. Cannot include double-quote characters. [R] + event_id: str = None, # Numeric ID for the event to modify, or 'new' if creating a new one. + # [W][D:new] + name: str = None, # Event entity name. + priority: str = None, # See set_event_priority for available priorities. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_event(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if details is not None: data["details"] = details @@ -3599,9 +2251,10 @@ class LFJsonPost(LFCliBase): data["priority"] = priority if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_event", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_event", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -3658,36 +2311,56 @@ class LFJsonPost(LFCliBase): random_fixed = "random_fixed" # Means generate one random payload, and send it over zeros = "zeros" # Payload is all zeros (00). + class AddFileEndpType(Enum): + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Example Usage: + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + fe_cifs = "fe_cifs" # Does a CIFS (Samba) mount + fe_cifs_ip6 = "fe_cifs/ip6" # Does an IPv6 CIFS mount + fe_generic = "fe_generic" # Uses unspecified file protocol + fe_iscsi = "fe_iscsi" # Does a ISCSI mount + fe_nfs = "fe_nfs" # Does an NFSv3 mount + fe_nfs_ip6 = "fe_nfs/ip6" # Does a NFSv3 IPv6 mount + fe_nfs4 = "fe_nfs4" # Does an NFSv4 mount + fe_nfs4_ip6 = "fe_nfs4/ip6" # Does a NFSv4 IPv6 mount + fe_smb2 = "fe_smb2" # Does a SMB v2.0 mount + fe_smb2_ip6 = "fe_smb2/ip6" # Does a SMB v2.0 IPv6 mount + fe_smb21 = "fe_smb21" # Does a SMB v2.1 mount + fe_smb21_ip6 = "fe_smb21/ip6" # Does a SMB v2.1 IPv6 mount + fe_smb30 = "fe_smb30" # Does a SMB v3.0 mount + fe_smb30_ip6 = "fe_smb30/ip6" # Does a SMB v3.0 IPv6 mount + def post_add_file_endp(self, - alias=None, # Name of endpoint. - directory=None, # The directory to read/write in. Absolute path suggested. - fio_flags=None, # File-IO flags, see above for details. - max_read_rate=None, # Maximum read rate, bits-per-second. - max_write_rate=None, # Maximum write rate, bits-per-second. - min_read_rate=None, # Minimum read rate, bits-per-second. - min_write_rate=None, # Minimum write rate, bits-per-second. - mount_dir=None, # Directory to mount/unmount (if blank, will use 'directory'). - mount_options=None, # Optional mount options, passed to the mount command. 'NONE' + alias: str = None, # Name of endpoint. [R] + directory: str = None, # The directory to read/write in. Absolute path suggested. + # [W] + fio_flags: str = None, # File-IO flags, see above for details. + max_read_rate: str = None, # Maximum read rate, bits-per-second. + max_write_rate: str = None, # Maximum write rate, bits-per-second. + min_read_rate: str = None, # Minimum read rate, bits-per-second. + min_write_rate: str = None, # Minimum write rate, bits-per-second. + mount_dir: str = None, # Directory to mount/unmount (if blank, will use + # 'directory'). + mount_options: str = None, # Optional mount options, passed to the mount command. 'NONE' # clears. - payload_pattern=None, # Payload pattern, see above. - port=None, # Port number. - prefix=None, # The prefix of the file(s) to read/write. - resource=None, # Resource number. - retry_timer=None, # Number of miliseconds to retry errored IO calls before giving - # up. - server_mount=None, # The server to mount, ex: 192.168.100.5/exports/test1 - shelf=None, # Shelf name/id. - p_type=None, # Endpoint Type : fe_generic, fe_nfs, fe_nfs4, fe_cifs, fe_iscsi, - # fe_cifs/ip6, fe_nfs/ip6, fe_nfs4/ip6, fe_smb2, fe_smb2/ip6 - # fe_smb21 fe_smb21/ip6 fe_smb30 fe_smb30/ip6 - volume=None, # iSCSI volume to mount - debug_=False): + payload_pattern: str = None, # Payload pattern, see above. + port: str = None, # Port number. [W] + prefix: str = None, # The prefix of the file(s) to read/write. + resource: int = None, # Resource number. [W] + retry_timer: str = None, # Number of miliseconds to retry errored IO calls before + # giving up. + server_mount: str = None, # The server to mount, ex: + # 192.168.100.5/exports/test1 [W] + shelf: int = 1, # Shelf name/id. [R][D:1] + p_type: str = None, # Endpoint Type (like fe_nfs) [W] + volume: str = None, # iSCSI volume to mount + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_file_endp(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if alias is not None: data["alias"] = alias @@ -3727,9 +2400,10 @@ class LFJsonPost(LFCliBase): data["volume"] = volume if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_file_endp", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_file_endp", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -3739,18 +2413,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_gen_endp ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_gen_endp(self, - alias=None, # Name of endpoint. - port=None, # Port number. - resource=None, # Resource number. - shelf=None, # Shelf name/id. - p_type=None, # Endpoint Type : gen_generic - debug_=False): + alias: str = None, # Name of endpoint. [R] + port: str = None, # Port number. [W] + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf name/id. [R][D:1] + p_type: str = None, # Endpoint Type : gen_generic [W][D:gen_generic] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_gen_endp(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if alias is not None: data["alias"] = alias @@ -3764,9 +2438,10 @@ class LFJsonPost(LFCliBase): data["type"] = p_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_gen_endp", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_gen_endp", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -3776,19 +2451,19 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_gre ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_gre(self, - local_lower_ip=None, # The local lower-level IP to use. - port=None, # Name of the GRE to create, suggested to start with 'gre' - remote_lower_ip=None, # The remote lower-level IP to use. - report_timer=None, # Report timer for this port, leave blank or use NA for defaults. - resource=None, # Resource number. - shelf=None, # Shelf number. - debug_=False): + local_lower_ip: str = None, # The local lower-level IP to use. + port: str = None, # Name of the GRE to create, suggested to start with 'gre' [W] + remote_lower_ip: str = None, # The remote lower-level IP to use. + report_timer: int = None, # Report timer for this port, leave blank or use NA for defaults. + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_gre(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if local_lower_ip is not None: data["local_lower_ip"] = local_lower_ip @@ -3804,9 +2479,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_gre", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_gre", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -3836,17 +2512,17 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_add_group(self, - flags=None, # Flags for this group, see above. - flags_mask=None, # Mask for flags that we care about, use 0xFFFFFFFF or leave blank for - # all. - name=None, # The name of the test group. Must be unique across all groups. - debug_=False): + flags: str = None, # Flags for this group, see above. + flags_mask: str = None, # Mask for flags that we care about, use 0xFFFFFFFF or leave blank + # for all. + name: str = None, # The name of the test group. Must be unique across all groups. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_group(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if flags is not None: data["flags"] = flags @@ -3856,9 +2532,10 @@ class LFJsonPost(LFCliBase): data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_group", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_group", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -3940,40 +2617,40 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_add_l4_endp(self, - alias=None, # Name of endpoint. - block_size=None, # TFTP Block size, in bytes. - dns_cache_timeout=None, # In seconds, how long to cache DNS lookups. 0 means no caching at - # all. - http_auth_type=None, # Bit-field for allowable http-authenticate methods. - ip_addr=None, # Local IP address, for binding to specific secondary IP. - max_speed=None, # In bits-per-second, can rate limit upload or download speed of - # the URL contents. 0 means infinite. - port=None, # Port number. - proxy_auth_type=None, # Bit-field for allowable proxy-authenticate methods. - proxy_port=None, # HTTP Proxy port if you are using a proxy. - proxy_server=None, # The name of our proxy server if using one. - proxy_userpwd=None, # The user-name and password for proxy authentication, format: + alias: str = None, # Name of endpoint. [R] + block_size: str = None, # TFTP Block size, in bytes. + dns_cache_timeout: str = None, # In seconds, how long to cache DNS lookups. 0 means no + # caching at all. + http_auth_type: str = None, # Bit-field for allowable http-authenticate methods. + ip_addr: str = None, # Local IP address, for binding to specific secondary IP. + max_speed: str = None, # In bits-per-second, can rate limit upload or download speed + # of the URL contents. 0 means infinite. + port: str = None, # Port number. [W] + proxy_auth_type: str = None, # Bit-field for allowable proxy-authenticate methods. + proxy_port: str = None, # HTTP Proxy port if you are using a proxy. + proxy_server: str = None, # The name of our proxy server if using one. + proxy_userpwd: str = None, # The user-name and password for proxy authentication, format: # user:passwd. - quiesce_after=None, # Quiesce test after this many URLs have been processed. - resource=None, # Resource number. - shelf=None, # Shelf name/id. - smtp_from=None, # SMTP From address. - ssl_cert_fname=None, # Name of SSL Certs file. - timeout=None, # How long to wait for a connection, in milliseconds - p_type=None, # Endpoint Type : l4_generic - url=None, # The URL, see syntax above. Can also be a local file. - url_rate=None, # How often should we process the URL(s), per 10 + quiesce_after: str = None, # Quiesce test after this many URLs have been processed. + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf name/id. [R][D:1] + smtp_from: str = None, # SMTP From address. + ssl_cert_fname: str = None, # Name of SSL Certs file. + timeout: str = None, # How long to wait for a connection, in milliseconds + p_type: str = None, # Endpoint Type : l4_generic [W] + url: str = None, # The URL, see syntax above. Can also be a local file. + url_rate: str = None, # How often should we process the URL(s), per 10 # minutes.
  • 600: 1/s
  • 1200: 2/s
  • 1800: 3/s
  • 2400: - # 4/s
- user_agent=None, # User-Agent string. Leave blank for default. Also SMTP-TO: + # 4/s [R][D:600] + user_agent: str = None, # User-Agent string. Leave blank for default. Also SMTP-TO: # <a@b.com><c@d.com>...<q@x.com> - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_l4_endp(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if alias is not None: data["alias"] = alias @@ -4019,9 +2696,10 @@ class LFJsonPost(LFCliBase): data["user_agent"] = user_agent if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_l4_endp", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_l4_endp", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -4053,21 +2731,21 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_add_monitor(self, - aid=None, # AID, may be used when sniffing on /AX radios. - ap_name=None, # Name for this Monitor interface, for example: moni0 - bssid=None, # BSSID to use when sniffing on /AX radios, optional. - flags=None, # Flags for this monitor interface. - flags_mask=None, # Flags mask for this monitor interface. - radio=None, # Name of the physical radio interface, for example: wiphy0 - resource=None, # Resource number. - shelf=None, # Shelf number. - debug_=False): + aid: str = None, # AID, may be used when sniffing on /AX radios. + ap_name: str = None, # Name for this Monitor interface, for example: moni0 [W] + bssid: str = None, # BSSID to use when sniffing on /AX radios, optional. + flags: str = None, # Flags for this monitor interface. + flags_mask: str = None, # Flags mask for this monitor interface. + radio: str = None, # Name of the physical radio interface, for example: wiphy0 [W] + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_monitor(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if aid is not None: data["aid"] = aid @@ -4087,9 +2765,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_monitor", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_monitor", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -4099,22 +2778,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_mvlan ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_mvlan(self, - flags=None, # 0x1: Create admin-down. - index=None, # Optional: The index of the VLAN, (the 4 in eth0#4) - mac=None, # The MAC address, can also use parent-pattern in 5.3.8 and higher: - # xx:xx:xx:*:*:xx - old_name=None, # The temporary name, used for configuring un-discovered hardware. - port=None, # Port number of an existing Ethernet interface. - report_timer=None, # Report timer for this port, leave blank or use NA for defaults. - resource=None, # Resource number. - shelf=None, # Shelf number. - debug_=False): + flags: str = None, # 0x1: Create admin-down. + index: str = None, # Optional: The index of the VLAN, (the 4 in + # eth0#4) + mac: str = None, # The MAC address, can also use parent-pattern in 5.3.8 and higher: + # xx:xx:xx:*:*:xx [W] + old_name: str = None, # The temporary name, used for configuring un-discovered hardware. + port: str = None, # Port number of an existing Ethernet interface. [W] + report_timer: int = None, # Report timer for this port, leave blank or use NA for defaults. + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_mvlan(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if flags is not None: data["flags"] = flags @@ -4134,9 +2814,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_mvlan", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_mvlan", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -4146,48 +2827,49 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_ppp_link ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_ppp_link(self, - auth=None, # YES if you want to authenticate. Default is NO. - channel_groups=None, # List of channel groups, see above. - debug=None, # YES for debug, otherwise debugging for the ppp connection is - # off. - down_time_max_ms=None, # Maximum length of downtime (ms) for PPP link between runs, or - # 0 for the link to be always up. - down_time_min_ms=None, # Minimum length of downtime (ms) for PPP link between runs, or - # 0 for the link to be always up. - dst_ip=None, # Destination IP address for this PPP connection. - extra_args=None, # Extra arguments to be passed directly to the pppd server. - holdoff=None, # Seconds between attempt to bring link back up if it dies, + auth: str = None, # YES if you want to authenticate. Default is NO. + channel_groups: str = None, # List of channel groups, see above. + p_debug: bool = False, # YES for debug, otherwise debugging for the ppp connection + # is off. + down_time_max_ms: str = None, # Maximum length of downtime (ms) for PPP link between runs, + # or 0 for the link to be always up. + down_time_min_ms: str = None, # Minimum length of downtime (ms) for PPP link between runs, + # or 0 for the link to be always up. + dst_ip: str = None, # Destination IP address for this PPP connection. + extra_args: str = None, # Extra arguments to be passed directly to the pppd server. + holdoff: str = None, # Seconds between attempt to bring link back up if it dies, # suggest 1. - lcp_echo_failure=None, # LCP echo failures before we determine links is dead, suggest - # 5. - lcp_echo_interval=None, # Seconds between LCP echos, suggest 1. - mlppp_descriptor=None, # A unique key for use with multi-link PPP connections. - persist=None, # YES if you want to persist the connection. This is suggested. - pppoe_transport_port=None, # Port number (or name) for underlying PPPoE transport. - resource=None, # Resource (machine) number. - run_time_max_ms=None, # Maximum uptime (ms) for PPP link during an experiment, or 0 - # for the link to be always up. - run_time_min_ms=None, # Minimum uptime (ms) for PPP link during an experiment, or 0 - # for the link to be always up. - shelf=None, # Shelf name/id. - src_ip=None, # Source IP address for this PPP connection. - transport_type=None, # What sort of transport this ppp link uses. - tty_transport_device=None, # TTY device for PPP links associated with TTYs. - unit=None, # Unit number for the PPP link. ie, the 7 in ppp7. - debug_=False): + lcp_echo_failure: str = None, # LCP echo failures before we determine links is dead, + # suggest 5. + lcp_echo_interval: str = None, # Seconds between LCP echos, suggest 1. + mlppp_descriptor: str = None, # A unique key for use with multi-link PPP connections. + persist: str = None, # YES if you want to persist the connection. This is + # suggested. + pppoe_transport_port: str = None, # Port number (or name) for underlying PPPoE transport. + resource: int = None, # Resource (machine) number. [W] + run_time_max_ms: str = None, # Maximum uptime (ms) for PPP link during an experiment, or + # 0 for the link to be always up. + run_time_min_ms: str = None, # Minimum uptime (ms) for PPP link during an experiment, or + # 0 for the link to be always up. + shelf: int = 1, # Shelf name/id. [R] + src_ip: str = None, # Source IP address for this PPP connection. + transport_type: str = None, # What sort of transport this ppp link uses. + tty_transport_device: str = None, # TTY device for PPP links associated with TTYs. + unit: str = None, # Unit number for the PPP link. ie, the 7 in ppp7. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_ppp_link(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if auth is not None: data["auth"] = auth if channel_groups is not None: data["channel_groups"] = channel_groups - if debug is not None: - data["debug"] = debug + if p_debug is not None: + data["debug"] = p_debug if down_time_max_ms is not None: data["down_time_max_ms"] = down_time_max_ms if down_time_min_ms is not None: @@ -4226,9 +2908,10 @@ class LFJsonPost(LFCliBase): data["unit"] = unit if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_ppp_link", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_ppp_link", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -4247,6 +2930,7 @@ class LFJsonPost(LFCliBase): ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" p_11r = 0x40 # Use 802.11r roaming setup. + ALLOW_11W = 0x800 # Set 11w (MFP/PMF) to optional. BSS_TRANS = 0x400 # Enable BSS Transition logic DHCP_SERVER = 0x1 # This should provide DHCP server. EAP_PEAP = 0x200 # Enable EAP-PEAP @@ -4305,28 +2989,28 @@ class LFJsonPost(LFCliBase): vlan = "vlan" # 802.1q VLAN. Specify VID with the 'freq' option. def post_add_profile(self, - alias_prefix=None, # Port alias prefix, aka hostname prefix. - antenna=None, # Antenna count for this profile. - bandwidth=None, # 0 (auto), 20, 40, 80 or 160 - eap_id=None, # EAP Identifier - flags_mask=None, # Specify what flags to set. - freq=None, # WiFi frequency to be used, 0 means default. - instance_count=None, # Number of devices (stations, vdevs, etc) - mac_pattern=None, # Optional MAC-Address pattern, for instance: xx:xx:xx:*:*:xx - name=None, # Profile Name. - passwd=None, # WiFi Password to be used (AP Mode), [BLANK] means no password. - profile_flags=None, # Flags for this profile, see above. - profile_type=None, # Profile type: See above. - ssid=None, # WiFi SSID to be used, [BLANK] means any. - vid=None, # Vlan-ID (only valid for vlan profiles). - wifi_mode=None, # WiFi Mode for this profile. - debug_=False): + alias_prefix: str = None, # Port alias prefix, aka hostname prefix. + antenna: str = None, # Antenna count for this profile. + bandwidth: str = None, # 0 (auto), 20, 40, 80 or 160 + eap_id: str = None, # EAP Identifier + flags_mask: str = None, # Specify what flags to set. + freq: str = None, # WiFi frequency to be used, 0 means default. + instance_count: str = None, # Number of devices (stations, vdevs, etc) + mac_pattern: str = None, # Optional MAC-Address pattern, for instance: xx:xx:xx:*:*:xx + name: str = None, # Profile Name. [R] + passwd: str = None, # WiFi Password to be used (AP Mode), [BLANK] means no password. + profile_flags: str = None, # Flags for this profile, see above. + profile_type: str = None, # Profile type: See above. [W] + ssid: str = None, # WiFi SSID to be used, [BLANK] means any. + vid: str = None, # Vlan-ID (only valid for vlan profiles). + wifi_mode: str = None, # WiFi Mode for this profile. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_profile(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if alias_prefix is not None: data["alias_prefix"] = alias_prefix @@ -4360,9 +3044,10 @@ class LFJsonPost(LFCliBase): data["wifi_mode"] = wifi_mode if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_profile", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_profile", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -4372,16 +3057,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_profile_notes ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_profile_notes(self, - dut=None, # Profile Name. - text=None, # [BLANK] will erase all, any other text will be appended to + dut: str = None, # Profile Name. [R] + text: str = None, # [BLANK] will erase all, any other text will be appended to # existing text. Unescaped Value - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_profile_notes(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if dut is not None: data["dut"] = dut @@ -4389,9 +3074,10 @@ class LFJsonPost(LFCliBase): data["text"] = text if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_profile_notes", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_profile_notes", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -4401,18 +3087,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_rdd ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_rdd(self, - peer_ifname=None, # The peer (other) RedirectDevice in this pair. - port=None, # Name of the Redirect Device to create. - report_timer=None, # Report timer for this port, leave blank or use NA for defaults. - resource=None, # Resource number. - shelf=None, # Shelf number. - debug_=False): + peer_ifname: str = None, # The peer (other) RedirectDevice in this pair. + port: str = None, # Name of the Redirect Device to create. [W] + report_timer: int = None, # Report timer for this port, leave blank or use NA for defaults. + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_rdd(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if peer_ifname is not None: data["peer_ifname"] = peer_ifname @@ -4426,9 +3112,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_rdd", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_rdd", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -4438,17 +3125,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_sec_ip ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_sec_ip(self, - ip_list=None, # IP1/prefix,IP2/prefix,...IPZ/prefix. - port=None, # Name of network device (Port) to which these IPs will be added. - resource=None, # Resource number. - shelf=None, # Shelf number. - debug_=False): + ip_list: str = None, # IP1/prefix,IP2/prefix,...IPZ/prefix. [W] + port: str = None, # Name of network device (Port) to which these IPs will be added. + # [W] + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_sec_ip(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if ip_list is not None: data["ip_list"] = ip_list @@ -4460,9 +3148,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_sec_ip", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_sec_ip", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -4493,6 +3182,7 @@ class LFJsonPost(LFCliBase): p_8021x_radius = 0x2000000 # Use 802.1x (RADIUS for AP). create_admin_down = 0x1000000000 # Station should be created admin-down. custom_conf = 0x20 # Use Custom wpa_supplicant config file. + disable_obss_scan = 0x400000000000 # Disable OBSS SCAN feature in supplicant. disable_ofdma = 0x200000000000 # Disable OFDMA mode disable_twt = 0x100000000000 # Disable TWT mode disable_fast_reauth = 0x200000000 # Disable fast_reauth option for virtual stations. @@ -4567,43 +3257,44 @@ class LFJsonPost(LFCliBase): p_bitmap_ = "[bitmap]" # '0xff 00 ...' to directly specify the MCS bitmap. def post_add_sta(self, - ampdu_density=None, # 0-7, or 0xFF to not set. - ampdu_factor=None, # 0-3, or 0xFF to not set. - ap=None, # The Access Point BSSID this Virtual STA should be associated with - # (example: 00:11:22:33:4:55, or DEFAULT for any). - flags=None, # Flags for this interface (see above.) - flags_mask=None, # If set, only these flags will be considered. - ieee80211w=None, # Management Frame Protection: 0: disabled, 1: optional, 2: Required. - key=None, # Encryption key (WEP, WPA, WPA2, WPA3, etc) for this Virtual STA. + ampdu_density: str = None, # 0-7, or 0xFF to not set. + ampdu_factor: str = None, # 0-3, or 0xFF to not set. + ap: str = None, # The Access Point BSSID this Virtual STA should be associated with + flags: str = None, # Flags for this interface (see above.) [W] + flags_mask: str = None, # If set, only these flags will be considered. + ieee80211w: str = None, # Management Frame Protection: 0: disabled, 1: optional, 2: + # Required. + key: str = None, # Encryption key (WEP, WPA, WPA2, WPA3, etc) for this Virtual STA. # Prepend with 0x for ascii-hex input. - mac=None, # The MAC address, can also use parent-pattern in 5.3.8 and higher: - # xx:xx:xx:*:*:xx - max_amsdu=None, # 1 == enabled, 0 == disabled, 0xFF == do not set. - mode=None, # WiFi mode:
  • 0: AUTO,
  • 1: 802.11a
  • 2: b
  • 3: - # g
  • 4: abg
  • 5: abgn
  • 6: bgn
  • 7: bg
  • - #
  • 8: abgnAC
  • 9 anAC
  • 10 an
  • 11 - # bgnAC
  • 12 abgnAX
  • 13 bgnAX
  • 14 anAX
  • 15 - # aAX
- nickname=None, # Nickname for this Virtual STA. (No longer used) - radio=None, # Name of the physical radio interface, for example: wiphy0 - rate=None, # Max rate, see help above. - resource=None, # Resource number. - shelf=None, # Shelf number. - ssid=None, # SSID for this Virtual STA. Use [BLANK] for empty SSID. Start with - # 0x for HEX interpretation. - sta_br_ip=None, # IP Address for station bridging. Set to 0.0.0.0 to use MAC bridging. - sta_name=None, # Name for this Virtual STA, for example: sta0 - wpa_cfg_file=None, # WPA Supplicant config file. - x_coord=None, # Floating point number. - y_coord=None, # Floating point number. - z_coord=None, # Floating point number. - debug_=False): + mac: str = None, # The MAC address, can also use parent-pattern in 5.3.8 and higher: + # xx:xx:xx:*:*:xx [W] + max_amsdu: str = None, # 1 == enabled, 0 == disabled, 0xFF == do not set. + mode: str = None, # WiFi mode:
  • 0: AUTO,
  • 1: 802.11a
  • 2: b
  • + #
  • 3: g
  • 4: abg
  • 5: abgn
  • 6: bgn
  • + #
  • 7: bg
  • 8: abgnAC
  • 9 anAC
  • 10 + # an
  • 11 bgnAC
  • 12 abgnAX
  • 13 bgnAX
  • 14 + # anAX
  • 15 aAX
[D:0] + nickname: str = None, # Nickname for this Virtual STA. (No longer used) + radio: str = None, # Name of the physical radio interface, for example: wiphy0 [W] + rate: str = None, # Max rate, see help above. + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + ssid: str = None, # SSID for this Virtual STA. Use [BLANK] for empty SSID. Start with + # 0x for HEX interpretation. [W] + sta_br_ip: str = None, # IP Address for station bridging. Set to 0.0.0.0 to use MAC + # bridging. + sta_name: str = None, # Name for this Virtual STA, for example: sta0 [W] + wpa_cfg_file: str = None, # WPA Supplicant config file. + x_coord: str = None, # Floating point number. + y_coord: str = None, # Floating point number. + z_coord: str = None, # Floating point number. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_sta(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if ampdu_density is not None: data["ampdu_density"] = ampdu_density @@ -4651,9 +3342,10 @@ class LFJsonPost(LFCliBase): data["z_coord"] = z_coord if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_sta", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_sta", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -4677,27 +3369,35 @@ class LFJsonPost(LFCliBase): p_533_ft = 3 # 399-533 feet p_655_ft = 4 # 533-655 feet + class AddT1SpanType(Enum): + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Example Usage: + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + Digium_T1 = "Digium_T1" # + Sangoma_E1 = "Sangoma_E1" # + Sangoma_T1 = "Sangoma_T1" # + def post_add_t1_span(self, - buildout=None, # Buildout, Integer, see above. - coding=None, # Coding: T1: ami or b8zs. E1: ami or hdb3 - cpu_id=None, # CPU identifier (A, B, etc) for multiport Sangoma resources. - first_channel=None, # The first DS0 channel for this span. - framing=None, # Framing: T1: esf or d4. E1: cas or ccs. - mtu=None, # MTU for this span (used by in-band management, if at all). - pci_bus=None, # PCI Bus number, needed for Sangoma resources. - pci_slot=None, # PCI slot number, needed for Sangoma resources. - resource=None, # Resource number. - shelf=None, # Shelf name/id. - span_num=None, # The span number. First span is 1, second is 2... - timing=None, # Timing: 0 == do not use, 1 == primary, 2 == secondary.. - p_type=None, # Currently supported types are: Sangoma_T1, Sangoma_E1, Digium_T1 - debug_=False): + buildout: str = None, # Buildout, Integer, see above. + coding: str = None, # Coding: T1: ami or b8zs. E1: ami or hdb3 + cpu_id: str = None, # CPU identifier (A, B, etc) for multiport Sangoma resources. + first_channel: str = None, # The first DS0 channel for this span. + framing: str = None, # Framing: T1: esf or d4. E1: cas or ccs. + mtu: str = None, # MTU for this span (used by in-band management, if at all). + pci_bus: str = None, # PCI Bus number, needed for Sangoma resources. + pci_slot: str = None, # PCI slot number, needed for Sangoma resources. + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf name/id. [R][D:1] + span_num: str = None, # The span number. First span is 1, second is 2... [W] + timing: str = None, # Timing: 0 == do not use, 1 == primary, 2 == secondary.. + p_type: str = None, # Currently supported types listed above. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_t1_span(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if buildout is not None: data["buildout"] = buildout @@ -4727,9 +3427,10 @@ class LFJsonPost(LFCliBase): data["type"] = p_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_t1_span", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_t1_span", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -4739,17 +3440,17 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_text_blob ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_text_blob(self, - name=None, # Text name, for instance '2-AP-test-case' - text=None, # [BLANK] will erase all, any other text will be appended to existing - # text. Unescaped Value - p_type=None, # Text type identifier stream, for instance 'cv-connectivity' - debug_=False): + name: str = None, # Text name, for instance '2-AP-test-case' [R] + text: str = None, # [BLANK] will erase all, any other text will be appended to + # existing text. Unescaped Value + p_type: str = None, # Text type identifier stream, for instance 'cv-connectivity' [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_text_blob(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name @@ -4759,9 +3460,10 @@ class LFJsonPost(LFCliBase): data["type"] = p_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_text_blob", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_text_blob", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -4771,15 +3473,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_tgcx ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_tgcx(self, - cxname=None, # The name of the CX. - tgname=None, # The name of the test group. - debug_=False): + cxname: str = None, # The name of the CX. [R] + tgname: str = None, # The name of the test group. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_tgcx(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if cxname is not None: data["cxname"] = cxname @@ -4787,9 +3489,10 @@ class LFJsonPost(LFCliBase): data["tgname"] = tgname if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_tgcx", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_tgcx", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -4821,19 +3524,19 @@ class LFJsonPost(LFCliBase): TX_BPS_RATE_OOR_3S = 0 # tx-bps over last 3 seconds is out of range. def post_add_threshold(self, - endp=None, # Endpoint name or ID. - thresh_id=None, # Threshold ID. If adding new threshold, use -1, otherwise use - # correct ID. - thresh_max=None, # Maximum acceptable value for this threshold. - thresh_min=None, # Minimum acceptable value for this threshold. - thresh_type=None, # Threshold type, integer, (see above). - debug_=False): + endp: str = None, # Endpoint name or ID. [R] + thresh_id: str = None, # Threshold ID. If adding new threshold, use -1, otherwise use + # correct ID. [W] + thresh_max: str = None, # Maximum acceptable value for this threshold. + thresh_min: str = None, # Minimum acceptable value for this threshold. + thresh_type: str = None, # Threshold type, integer, (see above). + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_threshold(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endp is not None: data["endp"] = endp @@ -4847,9 +3550,10 @@ class LFJsonPost(LFCliBase): data["thresh_type"] = thresh_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_threshold", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_threshold", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -4859,22 +3563,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_tm ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_tm(self, - name=None, # The name of the test manager. Must be unique across test managers. - debug_=False): + name: str = None, # The name of the test manager. Must be unique across test managers. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_tm(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_tm", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_tm", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -4918,23 +3623,24 @@ class LFJsonPost(LFCliBase): udp = "udp" # def post_add_traffic_profile(self, - instance_count=None, # Number of connections per device - max_pdu=None, # Minimum PDU size - max_speed=None, # Opposite-Direction Speed in bps. - min_pdu=None, # Minimum PDU size - min_speed=None, # Opposite-Direction Speed in bps. - name=None, # Profile Name. - tos=None, # IP Type-of-Service - traffic_profile_flags=None, # Flags for this profile, none defined at this point. - traffic_profile_flags_mask=None, # Specify what flags to set. - p_type=None, # Profile type: See above.. - debug_=False): + instance_count: str = None, # Number of connections per device + max_pdu: str = None, # Minimum PDU size + max_speed: str = None, # Opposite-Direction Speed in bps. + min_pdu: str = None, # Minimum PDU size + min_speed: str = None, # Opposite-Direction Speed in bps. + name: str = None, # Profile Name. [R] + tos: str = None, # IP Type-of-Service + traffic_profile_flags: str = None, # Flags for this profile, none defined at this + # point. + traffic_profile_flags_mask: str = None, # Specify what flags to set. + p_type: str = None, # Profile type: See above. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_traffic_profile(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if instance_count is not None: data["instance_count"] = instance_count @@ -4958,9 +3664,10 @@ class LFJsonPost(LFCliBase): data["type"] = p_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_traffic_profile", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_traffic_profile", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -4970,17 +3677,17 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_traffic_profile_notes ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_traffic_profile_notes(self, - dut=None, # Profile Name. - text=None, # [BLANK] will erase all, any other text will be appended - # to existing text. Unescaped - # Value - debug_=False): + dut: str = None, # Profile Name. [R] + text: str = None, # [BLANK] will erase all, any other text will be + # appended to existing text. Unescaped Value + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_traffic_profile_notes(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if dut is not None: data["dut"] = dut @@ -4988,9 +3695,10 @@ class LFJsonPost(LFCliBase): data["text"] = text if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_traffic_profile_notes", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_traffic_profile_notes", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -5074,36 +3782,37 @@ class LFJsonPost(LFCliBase): g = 3 # 802.11g def post_add_vap(self, - ap_name=None, # Name for this Virtual AP, for example: vap0 - beacon=None, # The beacon interval, in 1kus (1.024 ms), default 100, range: 15..65535 - custom_cfg=None, # Custom hostapd config file, if you want to craft your own config. - dtim_period=None, # DTIM period, range 1..255. Default 2. - flags=None, # Flags for this interface (see above.) - flags_mask=None, # If set, only these flags will be considered. - frag_thresh=None, # UN-USED, Was Fragmentation threshold, which is now set with - # set_wifi_radio, use NA - ieee80211w=None, # Management Frame Protection: 0: disabled, 1: optional, 2: Required. - key=None, # Encryption key for this Virtual AP. Prepend with 0x for ascii-hex + ap_name: str = None, # Name for this Virtual AP, for example: vap0 [W] + beacon: str = None, # The beacon interval, in 1kus (1.024 ms), default 100, range: + # 15..65535 + custom_cfg: str = None, # Custom hostapd config file, if you want to craft your own config. + dtim_period: str = None, # DTIM period, range 1..255. Default 2. + flags: str = None, # Flags for this interface (see above.) [W] + flags_mask: str = None, # If set, only these flags will be considered. + frag_thresh: str = None, # UN-USED, Was Fragmentation threshold, which is now set with + # set_wifi_radio, use NA [W] + ieee80211w: str = None, # Management Frame Protection: 0: disabled, 1: optional, 2: Required. + key: str = None, # Encryption key for this Virtual AP. Prepend with 0x for ascii-hex # representation. - mac=None, # The MAC address, can also use parent-pattern in 5.3.8 and higher: + mac: str = None, # The MAC address, can also use parent-pattern in 5.3.8 and higher: # xx:xx:xx:*:*:xx - max_sta=None, # Maximum number of Stations allowed to join this AP (1..2007) - mode=None, # WiFi mode: see table - radio=None, # Name of the physical radio interface, for example: wiphy0 - rate=None, # Max rate, see help for add_vsta - resource=None, # Resource number. - shelf=None, # Shelf number. - ssid=None, # SSID for this Virtual AP. - x_coord=None, # Floating point number. - y_coord=None, # Floating point number. - z_coord=None, # Floating point number. - debug_=False): + max_sta: str = None, # Maximum number of Stations allowed to join this AP (1..2007) + mode: str = None, # WiFi mode: see table [W] + radio: str = None, # Name of the physical radio interface, for example: wiphy0 [W] + rate: str = None, # Max rate, see help for add_vsta + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + ssid: str = None, # SSID for this Virtual AP. [W] + x_coord: str = None, # Floating point number. + y_coord: str = None, # Floating point number. + z_coord: str = None, # Floating point number. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_vap(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if ap_name is not None: data["ap_name"] = ap_name @@ -5147,9 +3856,10 @@ class LFJsonPost(LFCliBase): data["z_coord"] = z_coord if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_vap", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_vap", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -5227,24 +3937,24 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_add_venue(self, - description=None, # User-supplied description, ie: Big City Ball Park; + description: str = None, # User-supplied description, ie: Big City Ball Park; # 47-characters max. - freq_24=None, # Frequency list for 2.4Ghz band, see above. - freq_5=None, # Frequency list for 5Ghz band, see above. - resource=None, # Resource number. - shelf=None, # Shelf number. - venu_id=None, # Number to uniquely identify this venue on this resource. - x1=None, # Floating point coordinate for lower-left corner. - x2=None, # Floating point coordinate for upper-right corner. - y1=None, # Floating point coordinate for lower-left corner. - y2=None, # Floating point coordinate for upper-right corner. - debug_=False): + freq_24: str = None, # Frequency list for 2.4Ghz band, see above. + freq_5: str = None, # Frequency list for 5Ghz band, see above. + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + venu_id: str = None, # Number to uniquely identify this venue on this resource. [W] + x1: str = None, # Floating point coordinate for lower-left corner. + x2: str = None, # Floating point coordinate for upper-right corner. + y1: str = None, # Floating point coordinate for lower-left corner. + y2: str = None, # Floating point coordinate for upper-right corner. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_venue(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if description is not None: data["description"] = description @@ -5268,9 +3978,10 @@ class LFJsonPost(LFCliBase): data["y2"] = y2 if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_venue", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_venue", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -5280,19 +3991,19 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_vlan ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_vlan(self, - old_name=None, # The temporary name, used for configuring un-discovered hardware. - port=None, # Port number of an existing Ethernet interface. - report_timer=None, # Report timer for this port, leave blank or use NA for defaults. - resource=None, # Resource number. - shelf=None, # Shelf number. - vid=None, # The VLAN-ID for this 802.1Q VLAN interface. - debug_=False): + old_name: str = None, # The temporary name, used for configuring un-discovered hardware. + port: str = None, # Port number of an existing Ethernet interface. [W] + report_timer: int = None, # Report timer for this port, leave blank or use NA for defaults. + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + vid: str = None, # The VLAN-ID for this 802.1Q VLAN interface. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_vlan(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if old_name is not None: data["old_name"] = old_name @@ -5308,9 +4019,10 @@ class LFJsonPost(LFCliBase): data["vid"] = vid if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_vlan", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_vlan", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -5320,34 +4032,35 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_voip_endp ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_voip_endp(self, - alias=None, # Name of endpoint. - auth_user_name=None, # Use this field for authentication user name. AUTO or blank mean - # use phone number. - display_name=None, # User-Name to be displayed. Use AUTO to display phone number. - gateway_port=None, # IP Port for SIP gateway (defaults to 5060). - ip_addr=None, # Use this IP for local IP address. Useful when there are + alias: str = None, # Name of endpoint. [R] + auth_user_name: str = None, # Use this field for authentication user name. AUTO or blank + # mean use phone number. + display_name: str = None, # User-Name to be displayed. Use AUTO to display phone number. + gateway_port: str = None, # IP Port for SIP gateway (defaults to 5060). + ip_addr: str = None, # Use this IP for local IP address. Useful when there are # multiple IPs on a port. - peer_phone_num=None, # Use AUTO to use phone number of peer endpoint, otherwise + peer_phone_num: str = None, # Use AUTO to use phone number of peer endpoint, otherwise # specify a number: user[@host[:port]] - phone_num=None, # Phone number for Endpoint - port=None, # Port number or name. - proxy_passwd=None, # Password to be used when registering with proxy/gateway. - resource=None, # Resource number. - rtp_port=None, # RTP port to use for send and receive. - rx_sound_file=None, # File name to save received PCM data to. Will be in WAV format, - # or AUTO - shelf=None, # Shelf name/id. - sip_gateway=None, # SIP Gateway/Proxy Name, this is who to register with, or AUTO - tx_sound_file=None, # File name containing the sound sample we will be playing. - vad_max_timer=None, # How often should we force a packet, even if VAD is on. - vad_timer=None, # How much silence (milliseconds) before VAD is enabled. - debug_=False): + phone_num: str = None, # Phone number for Endpoint [W] + port: str = None, # Port number or name. [W] + proxy_passwd: str = None, # Password to be used when registering with proxy/gateway. + resource: int = None, # Resource number. [W] + rtp_port: str = None, # RTP port to use for send and receive. + rx_sound_file: str = None, # File name to save received PCM data to. Will be in WAV + # format, or AUTO + shelf: int = 1, # Shelf name/id. [R][D:1] + sip_gateway: str = None, # SIP Gateway/Proxy Name, this is who to register with, or + # AUTO + tx_sound_file: str = None, # File name containing the sound sample we will be playing. + vad_max_timer: str = None, # How often should we force a packet, even if VAD is on. + vad_timer: str = None, # How much silence (milliseconds) before VAD is enabled. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_voip_endp(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if alias is not None: data["alias"] = alias @@ -5385,9 +4098,10 @@ class LFJsonPost(LFCliBase): data["vad_timer"] = vad_timer if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_voip_endp", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_voip_endp", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -5429,25 +4143,25 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_add_vr(self, - alias=None, # Name of virtual router. - flags=None, # Virtual router flags, see above for definitions. - height=None, # Height to be used when drawn in the LANforge-GUI. - notes=None, # Notes for this Virtual Router. Put in quotes if the notes include + alias: str = None, # Name of virtual router. [R] + flags: str = None, # Virtual router flags, see above for definitions. + height: str = None, # Height to be used when drawn in the LANforge-GUI. + notes: str = None, # Notes for this Virtual Router. Put in quotes if the notes include # white-space. - resource=None, # Resource number. - shelf=None, # Shelf name/id. - vr_id=None, # Leave blank, use NA or 0xFFFF unless you are certain of the value you + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf name/id. [R][D:1] + vr_id: str = None, # Leave blank, use NA or 0xFFFF unless you are certain of the value you # want to enter. - width=None, # Width to be used when drawn in the LANforge-GUI. - x=None, # X coordinate to be used when drawn in the LANforge-GUI. - y=None, # Y coordinate to be used when drawn in the LANforge-GUI. - debug_=False): + width: str = None, # Width to be used when drawn in the LANforge-GUI. + x: str = None, # X coordinate to be used when drawn in the LANforge-GUI. + y: str = None, # Y coordinate to be used when drawn in the LANforge-GUI. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_vr(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if alias is not None: data["alias"] = alias @@ -5471,9 +4185,10 @@ class LFJsonPost(LFCliBase): data["y"] = y if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_vr", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_vr", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -5507,25 +4222,25 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_add_vr_bgp(self, - bgp_id=None, # BGP Identifier: IPv4 Address - cluster_id=None, # Cluster ID, IPv4 Address. Use NA if not clustering. - confed_id=None, # Confederation ID 1-65535. Use NA if not in a confederation. - flags=None, # Virtual router BGP flags, see above for definitions. - half_life=None, # Halflife in minutes for damping configuration. - local_as=None, # BGP Autonomous System number, 1-65535 - max_suppress=None, # Maximum hold down time in minutes for damping configuration. - resource=None, # Resource number. - reuse=None, # Route flag damping reuse threshold, in minutes. - shelf=None, # Shelf name/id. - suppress=None, # Route flag damping cutoff threshold, in minutes. - vr_id=None, # Name of virtual router. - debug_=False): + bgp_id: str = None, # BGP Identifier: IPv4 Address [W] + cluster_id: str = None, # Cluster ID, IPv4 Address. Use NA if not clustering. + confed_id: str = None, # Confederation ID 1-65535. Use NA if not in a confederation. + flags: str = None, # Virtual router BGP flags, see above for definitions. + half_life: str = None, # Halflife in minutes for damping configuration. + local_as: str = None, # BGP Autonomous System number, 1-65535 + max_suppress: str = None, # Maximum hold down time in minutes for damping configuration. + resource: int = None, # Resource number. [W] + reuse: str = None, # Route flag damping reuse threshold, in minutes. + shelf: int = 1, # Shelf name/id. [R][D:1] + suppress: str = None, # Route flag damping cutoff threshold, in minutes. + vr_id: str = None, # Name of virtual router. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_vr_bgp(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if bgp_id is not None: data["bgp_id"] = bgp_id @@ -5553,9 +4268,10 @@ class LFJsonPost(LFCliBase): data["vr_id"] = vr_id if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_vr_bgp", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_vr_bgp", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -5598,47 +4314,48 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_add_vrcx(self, - dhcp_dns=None, # IP Address of DNS server. - dhcp_dns6=None, # IPv6 Address of DNS server. - dhcp_domain=None, # DHCP Domain name to serve. - dhcp_lease_time=None, # DHCP Lease time (in seconds) - dhcp_max=None, # Minimum IP address range to serve. - dhcp_max6=None, # Minimum IPv6 address to serve. - dhcp_min=None, # Minimum IP address range to serve. - dhcp_min6=None, # Minimum IPv6 address to serve. - flags=None, # Flags, specify if subnets 0-7 are in use, see above for others. - height=None, # Height to be used when drawn in the LANforge-GUI. - interface_cost=None, # If using OSPF, this sets the cost for this link (1-65535). - local_dev=None, # Name of port A, the local network device pair. - local_dev_b=None, # Name of port B for the local redirect device pair. - nexthop=None, # The next-hop to use when routing packets out this interface. - ospf_area=None, # If using OSPF, this sets the OSPF area for this interface. Default - # is 0.0.0.0. - remote_dev=None, # Name the remote network device. - remote_dev_b=None, # Name of port B for the remote network device. - resource=None, # Resource number. - rip_metric=None, # If using RIP, this determines the RIP metric (cost), (1-15, 15 is - # infinite). - shelf=None, # Shelf name/id. - subnets=None, # Subnets associated with this link, format: 1.1.1.1/24,1.1.2.1/16... - vr_name=None, # Virtual Router this endpoint belongs to. Use 'FREE_LIST' to add a - # stand-alone endpoint. - vrrp_id=None, # VRRP id, must be unique in this virtual router (1-255) - vrrp_interval=None, # VRRP broadcast message interval, in seconds (1-255) - vrrp_ip=None, # VRRP IPv4 address..ignored if not flagged for VRRP. - vrrp_ip_prefix=None, # Number of bits in subnet mask, ie 24 for 255.255.255.0 - vrrp_priority=None, # VRRP Priority (1-255, higher is more priority.) - wanlink=None, # The name of the WanLink that connects the two B ports. - width=None, # Width to be used when drawn in the LANforge-GUI. - x=None, # X coordinate to be used when drawn in the LANforge-GUI. - y=None, # Y coordinate to be used when drawn in the LANforge-GUI. - debug_=False): + dhcp_dns: str = None, # IP Address of DNS server. + dhcp_dns6: str = None, # IPv6 Address of DNS server. + dhcp_domain: str = None, # DHCP Domain name to serve. + dhcp_lease_time: str = None, # DHCP Lease time (in seconds) + dhcp_max: str = None, # Minimum IP address range to serve. + dhcp_max6: str = None, # Minimum IPv6 address to serve. + dhcp_min: str = None, # Minimum IP address range to serve. + dhcp_min6: str = None, # Minimum IPv6 address to serve. + flags: str = None, # Flags, specify if subnets 0-7 are in use, see above for others. + height: str = None, # Height to be used when drawn in the LANforge-GUI. + interface_cost: str = None, # If using OSPF, this sets the cost for this link (1-65535). + local_dev: str = None, # Name of port A, the local network device pair. [W] + local_dev_b: str = None, # Name of port B for the local redirect device pair. [W] + nexthop: str = None, # The next-hop to use when routing packets out this interface. + ospf_area: str = None, # If using OSPF, this sets the OSPF area for this interface. + # Default is 0.0.0.0. + remote_dev: str = None, # Name the remote network device. [W] + remote_dev_b: str = None, # Name of port B for the remote network device. [W] + resource: int = None, # Resource number. [W] + rip_metric: str = None, # If using RIP, this determines the RIP metric (cost), (1-15, 15 + # is infinite). + shelf: int = 1, # Shelf name/id. [R][D:1] + subnets: str = None, # Subnets associated with this link, format: + # 1.1.1.1/24,1.1.2.1/16... + vr_name: str = None, # Virtual Router this endpoint belongs to. Use 'FREE_LIST' to add + # a stand-alone endpoint. [R][D:FREE_LIST] + vrrp_id: str = None, # VRRP id, must be unique in this virtual router (1-255) + vrrp_interval: str = None, # VRRP broadcast message interval, in seconds (1-255) + vrrp_ip: str = None, # VRRP IPv4 address..ignored if not flagged for VRRP. + vrrp_ip_prefix: str = None, # Number of bits in subnet mask, ie 24 for 255.255.255.0 + vrrp_priority: str = None, # VRRP Priority (1-255, higher is more priority.) + wanlink: str = None, # The name of the WanLink that connects the two B ports. [W] + width: str = None, # Width to be used when drawn in the LANforge-GUI. + x: str = None, # X coordinate to be used when drawn in the LANforge-GUI. + y: str = None, # Y coordinate to be used when drawn in the LANforge-GUI. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_vrcx(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if dhcp_dns is not None: data["dhcp_dns"] = dhcp_dns @@ -5704,9 +4421,10 @@ class LFJsonPost(LFCliBase): data["y"] = y if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_vrcx", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_vrcx", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -5716,21 +4434,21 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#add_vrcx2 ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_add_vrcx2(self, - local_dev=None, # Name of port A for the connection. - nexthop6=None, # The IPv6 next-hop to use when routing packets out this interface. - resource=None, # Resource number. - shelf=None, # Shelf name/id. - subnets6=None, # IPv6 Subnets associated with this link, format: + local_dev: str = None, # Name of port A for the connection. [W] + nexthop6: str = None, # The IPv6 next-hop to use when routing packets out this interface. + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf name/id. [R][D:1] + subnets6: str = None, # IPv6 Subnets associated with this link, format: # aaaa:bbbb::0/64,cccc:dddd:eeee::0/64... - vr_name=None, # Virtual Router this endpoint belongs to. Use 'FREE_LIST' to add a - # stand-alone endpoint. - debug_=False): + vr_name: str = None, # Virtual Router this endpoint belongs to. Use 'FREE_LIST' to add a + # stand-alone endpoint. [W][D:FREE_LIST] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_vrcx2(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if local_dev is not None: data["local_dev"] = local_dev @@ -5746,9 +4464,10 @@ class LFJsonPost(LFCliBase): data["vr_name"] = vr_name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_vrcx2", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_vrcx2", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -5765,68 +4484,72 @@ class LFJsonPost(LFCliBase): SHOW_WP = 1 # Show WanPaths in wanlink endpoint table in GUI def post_add_wl_endp(self, - alias=None, # Name of WanPath. - cpu_id=None, # The CPU/thread that this process should run on (kernel-mode - # only). - description=None, # Description for this endpoint, put in single quotes if it + alias: str = None, # Name of WanPath. [R] + cpu_id: str = None, # The CPU/thread that this process should run on + # (kernel-mode only). + description: str = None, # Description for this endpoint, put in single quotes if it # contains spaces. - dest_ip=None, # Selection filter: Destination IP. - dest_ip_mask=None, # Selection filter: Destination IP MASK. - drop_every_xth_pkt=None, # YES to periodically drop every Xth pkt, NO to drop packets + dest_ip: str = None, # Selection filter: Destination IP. + dest_ip_mask: str = None, # Selection filter: Destination IP MASK. + drop_every_xth_pkt: str = None, # YES to periodically drop every Xth pkt, NO to drop packets # randomly. - drop_freq=None, # How often, out of 1,000,000 packets, should we purposefully - # drop a packet. - dup_every_xth_pkt=None, # YES to periodically duplicate every Xth pkt, NO to duplicate - # packets randomly. - dup_freq=None, # How often, out of 1,000,000 packets, should we purposefully - # duplicate a packet. - extra_buffer=None, # The extra amount of bytes to buffer before dropping pkts, in - # units of 1024, use -1 for AUTO. - ignore_bandwidth=None, # Should we ignore the bandwidth settings from the playback + drop_freq: str = None, # How often, out of 1,000,000 packets, should we + # purposefully drop a packet. [W] + dup_every_xth_pkt: str = None, # YES to periodically duplicate every Xth pkt, NO to + # duplicate packets randomly. + dup_freq: str = None, # How often, out of 1,000,000 packets, should we + # purposefully duplicate a packet. [W] + extra_buffer: str = None, # The extra amount of bytes to buffer before dropping pkts, + # in units of 1024, use -1 for AUTO. [D:-1] + ignore_bandwidth: str = None, # Should we ignore the bandwidth settings from the playback # file? YES, NO, or NA. - ignore_dup=None, # Should we ignore the Duplicate Packet settings from the + ignore_dup: str = None, # Should we ignore the Duplicate Packet settings from the # playback file? YES, NO, or NA. - ignore_latency=None, # Should we ignore the latency settings from the playback file? - # YES, NO, or NA. - ignore_loss=None, # Should we ignore the packet-loss settings from the playback + ignore_latency: str = None, # Should we ignore the latency settings from the playback # file? YES, NO, or NA. - jitter_freq=None, # How often, out of 1,000,000 packets, should we apply random - # jitter. - latency=None, # The base latency added to all packets, in milliseconds (or add - # 'us' suffix for microseconds) - max_drop_amt=None, # Maximum amount of packets to drop in a row. Default is 1. - max_jitter=None, # The maximum jitter, in milliseconds (or add 'us' suffix for - # microseconds) - max_lateness=None, # Maximum amount of un-intentional delay before pkt is dropped. - # Default is AUTO - max_rate=None, # Maximum transmit rate (bps) for this WanLink. - max_reorder_amt=None, # Maximum amount of packets by which to reorder, Default is 10. - min_drop_amt=None, # Minimum amount of packets to drop in a row. Default is 1. - min_reorder_amt=None, # Minimum amount of packets by which to reorder, Default is 1. - playback_capture=None, # ON or OFF, should we play back a WAN capture file? - playback_capture_file=None, # Name of the WAN capture file to play back. - playback_loop=None, # Should we loop the playback file, YES or NO or NA. - port=None, # Port number. - reorder_every_xth_pkt=None, # YES to periodically reorder every Xth pkt, NO to reorder + ignore_loss: str = None, # Should we ignore the packet-loss settings from the + # playback file? YES, NO, or NA. + jitter_freq: str = None, # How often, out of 1,000,000 packets, should we apply + # random jitter. + latency: str = None, # The base latency added to all packets, in milliseconds (or + # add 'us' suffix for microseconds) [W] + max_drop_amt: str = None, # Maximum amount of packets to drop in a row. Default is 1. + # [D:1] + max_jitter: str = None, # The maximum jitter, in milliseconds (or add 'us' suffix + # for microseconds) [W] + max_lateness: str = None, # Maximum amount of un-intentional delay before pkt is + # dropped. Default is AUTO + max_rate: str = None, # Maximum transmit rate (bps) for this WanLink. + max_reorder_amt: str = None, # Maximum amount of packets by which to reorder, Default is + # 10. [D:10] + min_drop_amt: str = None, # Minimum amount of packets to drop in a row. Default is 1. + # [D:1] + min_reorder_amt: str = None, # Minimum amount of packets by which to reorder, Default is + # 1. [D:1] + playback_capture: str = None, # ON or OFF, should we play back a WAN capture file? + playback_capture_file: str = None, # Name of the WAN capture file to play back. + playback_loop: str = None, # Should we loop the playback file, YES or NO or NA. + port: str = None, # Port number. [W] + reorder_every_xth_pkt: str = None, # YES to periodically reorder every Xth pkt, NO to reorder # packets randomly. - reorder_freq=None, # How often, out of 1,000,000 packets, should we make a packet - # out of order. - resource=None, # Resource number. - shelf=None, # Shelf name/id. - source_ip=None, # Selection filter: Source IP. - source_ip_mask=None, # Selection filter: Source IP MASK. - speed=None, # The maximum speed this WanLink will accept (bps). - test_mgr=None, # The name of the Test-Manager this WanPath is to use. Leave + reorder_freq: str = None, # How often, out of 1,000,000 packets, should we make a + # packet out of order. [W] + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf name/id. [R][D:1] + source_ip: str = None, # Selection filter: Source IP. + source_ip_mask: str = None, # Selection filter: Source IP MASK. + speed: str = None, # The maximum speed this WanLink will accept (bps). [W] + test_mgr: str = None, # The name of the Test-Manager this WanPath is to use. Leave # blank for no restrictions. - wanlink=None, # Name of WanLink to which we are adding this WanPath. - wle_flags=None, # WanLink Endpoint specific flags, see above. - debug_=False): + wanlink: str = None, # Name of WanLink to which we are adding this WanPath. [R] + wle_flags: str = None, # WanLink Endpoint specific flags, see above. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_add_wl_endp(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if alias is not None: data["alias"] = alias @@ -5904,9 +4627,10 @@ class LFJsonPost(LFCliBase): data["wle_flags"] = wle_flags if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/add_wl_endp", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/add_wl_endp", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -5916,20 +4640,20 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#admin ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_admin(self, - arg1=None, # Argument 1: xorp-port | scan-rslts-file | iface-name | iface-eid | + arg1: str = None, # Argument 1: xorp-port | scan-rslts-file | iface-name | iface-eid | # rfgen-message | id - arg2=None, # Argument 2: scan key | message | angle | dest-radio - arg3=None, # Argument 3: noprobe | migrate-sta-mac-pattern - arg5=None, # Argument 4: table-speed - cmd=None, # Admin command: + arg2: str = None, # Argument 2: scan key | message | angle | dest-radio + arg3: str = None, # Argument 3: noprobe | migrate-sta-mac-pattern + arg5: str = None, # Argument 4: table-speed + cmd: str = None, # Admin command: # resync_clock|write_xorp_cfg|scan_complete|ifup_post_complete|flush_complete|req_migrate|rfgen|chamber|clean_logs - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_admin(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if arg1 is not None: data["arg1"] = arg1 @@ -5943,9 +4667,10 @@ class LFJsonPost(LFCliBase): data["cmd"] = cmd if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/admin", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/admin", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -5955,15 +4680,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#apply_vr_cfg ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_apply_vr_cfg(self, - resource=None, # The number of the resource in question, or 'ALL'. - shelf=None, # The number of the shelf in question, or 'ALL'. - debug_=False): + resource: int = None, # The number of the resource in question, or 'ALL'. [W] + shelf: int = 1, # The number of the shelf in question, or 'ALL'. [R][D:ALL] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_apply_vr_cfg(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -5971,9 +4696,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/apply_vr_cfg", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/apply_vr_cfg", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -5983,16 +4709,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#blink_attenuator ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_blink_attenuator(self, - resource=None, # Resource number. - serno=None, # Serial number for requested Attenuator, or 'all'. - shelf=None, # Shelf number, usually 1. - debug_=False): + resource: int = None, # Resource number. [W] + serno: str = None, # Serial number for requested Attenuator, or 'all'. [W] + shelf: int = 1, # Shelf number, usually 1. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_blink_attenuator(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -6002,9 +4728,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/blink_attenuator", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/blink_attenuator", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6040,18 +4767,18 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_c_show_ports(self, - port=None, # Port number, or 'all'. - probe_flags=None, # See above, add them together for multiple probings. Leave blank if - # you want stats only. - resource=None, # Resource number, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - debug_=False): + port: str = None, # Port number, or 'all'. [W] + probe_flags: str = None, # See above, add them together for multiple probings. Leave + # blank if you want stats only. + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_c_show_ports(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if port is not None: data["port"] = port @@ -6063,9 +4790,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/c_show_ports", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/c_show_ports", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6075,15 +4803,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#cancel_vr_cfg ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_cancel_vr_cfg(self, - resource=None, # The number of the resource in question, or 'ALL'. - shelf=None, # The number of the shelf in question, or 'ALL'. - debug_=False): + resource: int = None, # The number of the resource in question, or 'ALL'. [W] + shelf: int = 1, # The number of the shelf in question, or 'ALL'. [R][D:ALL] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_cancel_vr_cfg(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -6091,9 +4819,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/cancel_vr_cfg", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/cancel_vr_cfg", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6103,23 +4832,24 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#clear_cd_counters ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_clear_cd_counters(self, - cd_name=None, # Name of Collision Domain, or 'all'. Null argument is same as - # 'all'. - debug_=False): + cd_name: str = None, # Name of Collision Domain, or 'all'. Null argument is same + # as 'all'. [W][D:all] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_clear_cd_counters(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if cd_name is not None: data["cd_name"] = cd_name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/clear_cd_counters", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/clear_cd_counters", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6129,23 +4859,24 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#clear_cx_counters ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_clear_cx_counters(self, - cx_name=None, # Name of Cross Connect, or 'all'. Null argument is same as - # 'all'. - debug_=False): + cx_name: str = None, # Name of Cross Connect, or 'all'. Null argument is same as + # 'all'. [W][D:all] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_clear_cx_counters(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if cx_name is not None: data["cx_name"] = cx_name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/clear_cx_counters", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/clear_cx_counters", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6155,19 +4886,19 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#clear_endp_counters ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_clear_endp_counters(self, - endp_name=None, # Name of Endpoint, or 'all'. Null argument is same as - # 'all'. - incr_seqno=None, # Enter 'YES' if you want the target to increment the + endp_name: str = None, # Name of Endpoint, or 'all'. Null argument is same as + # 'all'. [W][D:all] + incr_seqno: str = None, # Enter 'YES' if you want the target to increment the # cfg-seq-no. - just_latency=None, # Enter 'YES' if you only want to clear latency counters, + just_latency: str = None, # Enter 'YES' if you only want to clear latency counters, # and see above for RXGAP. - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_clear_endp_counters(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endp_name is not None: data["endp_name"] = endp_name @@ -6177,9 +4908,10 @@ class LFJsonPost(LFCliBase): data["just_latency"] = just_latency if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/clear_endp_counters", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/clear_endp_counters", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6189,22 +4921,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#clear_group ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_clear_group(self, - name=None, # The name of the test group. - debug_=False): + name: str = None, # The name of the test group. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_clear_group(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/clear_group", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/clear_group", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6223,18 +4956,18 @@ class LFJsonPost(LFCliBase): dhcp_leases = "dhcp_leases" # Remove dhcp lease files for IPv4 and IPv6 DHCP def post_clear_port_counters(self, - extra=None, # Clear something else instead: dhcp4_lease | dhcp6_lease | + extra: str = None, # Clear something else instead: dhcp4_lease | dhcp6_lease | # dhcp_leases - port=None, # The number of the port in question, or 'ALL'. - resource=None, # The number of the resource in question, or 'ALL'. - shelf=None, # The number of the shelf in question, or 'ALL'. - debug_=False): + port: str = None, # The number of the port in question, or 'ALL'. [W] + resource: int = None, # The number of the resource in question, or 'ALL'. [W] + shelf: int = 1, # The number of the shelf in question, or 'ALL'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_clear_port_counters(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if extra is not None: data["extra"] = extra @@ -6246,9 +4979,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/clear_port_counters", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/clear_port_counters", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6258,15 +4992,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#clear_resource_counters ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_clear_resource_counters(self, - resource=None, # The number of the resource in question, or 'ALL'. - shelf=None, # The number of the shelf in question, or 'ALL'. - debug_=False): + resource: int = None, # The number of the resource in question, or 'ALL'. [W] + shelf: int = 1, # The number of the shelf in question, or 'ALL'. + # [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_clear_resource_counters(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -6274,9 +5009,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/clear_resource_counters", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/clear_resource_counters", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6286,15 +5022,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#clear_wp_counters ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_clear_wp_counters(self, - endp_name=None, # Name of WanLink Endpoint. - wp_name=None, # Name of WanPath to clear. - debug_=False): + endp_name: str = None, # Name of WanLink Endpoint. [W] + wp_name: str = None, # Name of WanPath to clear. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_clear_wp_counters(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endp_name is not None: data["endp_name"] = endp_name @@ -6302,9 +5038,10 @@ class LFJsonPost(LFCliBase): data["wp_name"] = wp_name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/clear_wp_counters", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/clear_wp_counters", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6314,18 +5051,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#create_client ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_create_client(self, - name=None, # A single name with no white-spaces (15 characters or less) - password=None, # Can be blank or 'NA' if no password is set, otherwise must be the - # password. Use IGNORE for no change. - super_user=None, # 1 If you want this user to have Administrative powers, 0 or blank - # otherwise. - debug_=False): + name: str = None, # A single name with no white-spaces (15 characters or less) [W] + password: str = None, # Can be blank or 'NA' if no password is set, otherwise must be + # the password. Use IGNORE for no change. + super_user: str = None, # 1 If you want this user to have Administrative powers, 0 or + # blank otherwise. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_create_client(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name @@ -6335,9 +5072,10 @@ class LFJsonPost(LFCliBase): data["super_user"] = super_user if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/create_client", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/create_client", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6346,17 +5084,32 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#diag ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + class DiagType(Enum): + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Example Usage: + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + NA = "NA" # everything (default) + alerts = "alerts" # alert messages + clients = "clients" # connected clients + counters = "counters" # endpoint counters + endpoints = "endpoints" # list of endpoints + fds = "fds" # file descriptors + iobuffer = "iobuffer" # + license = "license" # license contents + shelf = "shelf" # + def post_diag(self, - arg1=None, # Optional: Endpoint name to diag. - p_type=None, # Default (blank) is everything, options: alerts, license, counters, fds, + arg1: str = None, # Optional: Endpoint name to diag. + p_type: str = None, # Default (blank) is everything, options: alerts, license, counters, fds, # clients, endpoints, shelf, iobuffer. - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_diag(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if arg1 is not None: data["arg1"] = arg1 @@ -6364,9 +5117,10 @@ class LFJsonPost(LFCliBase): data["type"] = p_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/diag", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/diag", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6376,16 +5130,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#discover ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_discover(self, - disconnect=None, # Set to 'disconnect' to force disconnect to remote resource process. - resource=None, # Resource ID. Use if discovering Attenuators. - shelf=None, # Shelf-ID, only used if discovering Attenuators. - debug_=False): + disconnect: str = None, # Set to 'disconnect' to force disconnect to remote resource process. + resource: int = None, # Resource ID. Use if discovering Attenuators. [W] + shelf: int = 1, # Shelf-ID, only used if discovering Attenuators. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_discover(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if disconnect is not None: data["disconnect"] = disconnect @@ -6395,9 +5149,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/discover", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/discover", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6407,15 +5162,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#do_pesq ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_do_pesq(self, - endp_name=None, # Name of Endpoint. - result_file_name=None, # The name of the file received by the endpoint. - debug_=False): + endp_name: str = None, # Name of Endpoint. [W] + result_file_name: str = None, # The name of the file received by the endpoint. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_do_pesq(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endp_name is not None: data["endp_name"] = endp_name @@ -6423,9 +5178,10 @@ class LFJsonPost(LFCliBase): data["result_file_name"] = result_file_name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/do_pesq", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/do_pesq", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6435,17 +5191,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#file ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_file(self, - card=None, # Card ID - cmd=None, # Only 'Download' supported for now, 'Upload' reserved for future use. - filename=None, # File to transfer. - shelf=None, # Shelf ID - debug_=False): + card: int = None, # Resource ID [W] + cmd: str = None, # Only 'Download' supported for now, 'Upload' reserved for future use. + # [W][D:Download] + filename: str = None, # File to transfer. [W] + shelf: int = 1, # Shelf ID [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_file(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if card is not None: data["card"] = card @@ -6457,9 +5214,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/file", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/file", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6469,17 +5227,17 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#flash_attenuator ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_flash_attenuator(self, - filename=None, # File to use when uploading to attenuator. - resource=None, # Resource number. - serno=None, # Serial number for requested Attenuator, or 'all'. - shelf=None, # Shelf number, usually 1. - debug_=False): + filename: str = None, # File to use when uploading to attenuator. + resource: int = None, # Resource number. [W] + serno: str = None, # Serial number for requested Attenuator, or 'all'. [W] + shelf: int = 1, # Shelf number, usually 1. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_flash_attenuator(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if filename is not None: data["filename"] = filename @@ -6491,9 +5249,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/flash_attenuator", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/flash_attenuator", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6503,15 +5262,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#getavglatency ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_getavglatency(self, - aorb=None, # For AtoB, enter 'B', for BtoA, enter 'A'. - cx=None, # Cross-connect or Test-Group name - debug_=False): + aorb: str = None, # For AtoB, enter 'B', for BtoA, enter 'A'. + cx: str = None, # Cross-connect or Test-Group name [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_getavglatency(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if aorb is not None: data["aorb"] = aorb @@ -6519,9 +5278,10 @@ class LFJsonPost(LFCliBase): data["cx"] = cx if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/getavglatency", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/getavglatency", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6531,15 +5291,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#getinrxbps ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_getinrxbps(self, - aorb=None, # For endpoint a, enter 'A', for endpoint b, enter 'B'. - cx=None, # Cross-connect or Test-Group name - debug_=False): + aorb: str = None, # For endpoint a, enter 'A', for endpoint b, enter 'B'. + cx: str = None, # Cross-connect or Test-Group name [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_getinrxbps(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if aorb is not None: data["aorb"] = aorb @@ -6547,9 +5307,10 @@ class LFJsonPost(LFCliBase): data["cx"] = cx if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/getinrxbps", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/getinrxbps", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6559,15 +5320,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#getinrxrate ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_getinrxrate(self, - aorb=None, # For endpoint a, enter 'A', for endpoint b, enter 'B'. - cx=None, # Cross-connect or Test-Group name - debug_=False): + aorb: str = None, # For endpoint a, enter 'A', for endpoint b, enter 'B'. + cx: str = None, # Cross-connect or Test-Group name [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_getinrxrate(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if aorb is not None: data["aorb"] = aorb @@ -6575,9 +5336,10 @@ class LFJsonPost(LFCliBase): data["cx"] = cx if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/getinrxrate", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/getinrxrate", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6587,15 +5349,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#getintxrate ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_getintxrate(self, - aorb=None, # For endpoint a, enter 'A', for endpoint b, enter 'B'. - cx=None, # Cross-connect or Test-Group name - debug_=False): + aorb: str = None, # For endpoint a, enter 'A', for endpoint b, enter 'B'. + cx: str = None, # Cross-connect or Test-Group name [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_getintxrate(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if aorb is not None: data["aorb"] = aorb @@ -6603,9 +5365,10 @@ class LFJsonPost(LFCliBase): data["cx"] = cx if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/getintxrate", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/getintxrate", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6615,15 +5378,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#getipadd ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_getipadd(self, - aorb=None, # For endpoint a, enter 'A', for endpoint b, enter 'B'. - cx=None, # Cross-connect name - debug_=False): + aorb: str = None, # For endpoint a, enter 'A', for endpoint b, enter 'B'. + cx: str = None, # Cross-connect name [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_getipadd(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if aorb is not None: data["aorb"] = aorb @@ -6631,9 +5394,10 @@ class LFJsonPost(LFCliBase): data["cx"] = cx if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/getipadd", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/getipadd", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6643,15 +5407,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#getmac ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_getmac(self, - aorb=None, # For endpoint a, enter 'A', for endpoint b, enter 'B'. - cx=None, # Cross-connect name - debug_=False): + aorb: str = None, # For endpoint a, enter 'A', for endpoint b, enter 'B'. + cx: str = None, # Cross-connect name [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_getmac(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if aorb is not None: data["aorb"] = aorb @@ -6659,9 +5423,10 @@ class LFJsonPost(LFCliBase): data["cx"] = cx if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/getmac", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/getmac", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6671,15 +5436,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#getmask ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_getmask(self, - aorb=None, # For endpoint a, enter 'A', for endpoint b, enter 'B'. - cx=None, # Cross-connect name - debug_=False): + aorb: str = None, # For endpoint a, enter 'A', for endpoint b, enter 'B'. + cx: str = None, # Cross-connect name + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_getmask(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if aorb is not None: data["aorb"] = aorb @@ -6687,9 +5452,10 @@ class LFJsonPost(LFCliBase): data["cx"] = cx if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/getmask", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/getmask", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6699,15 +5465,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#getpktdrops ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_getpktdrops(self, - aorb=None, # For AtoB, enter 'B', for BtoA, enter 'A'. - cx=None, # Cross-connect or Test-Group name - debug_=False): + aorb: str = None, # For AtoB, enter 'B', for BtoA, enter 'A'. + cx: str = None, # Cross-connect or Test-Group name [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_getpktdrops(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if aorb is not None: data["aorb"] = aorb @@ -6715,9 +5481,10 @@ class LFJsonPost(LFCliBase): data["cx"] = cx if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/getpktdrops", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/getpktdrops", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6727,15 +5494,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#getrxendperrpkts ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_getrxendperrpkts(self, - aorb=None, # For AtoB, enter 'B', for BtoA, enter 'A'. - cx=None, # Cross-connect or Test-Group name - debug_=False): + aorb: str = None, # For AtoB, enter 'B', for BtoA, enter 'A'. + cx: str = None, # Cross-connect or Test-Group name [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_getrxendperrpkts(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if aorb is not None: data["aorb"] = aorb @@ -6743,9 +5510,10 @@ class LFJsonPost(LFCliBase): data["cx"] = cx if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/getrxendperrpkts", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/getrxendperrpkts", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6755,15 +5523,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#getrxpkts ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_getrxpkts(self, - aorb=None, # For endpoint a, enter 'A', for endpoint b, enter 'B'. - cx=None, # Cross-connect or Test-Group name - debug_=False): + aorb: str = None, # For endpoint a, enter 'A', for endpoint b, enter 'B'. + cx: str = None, # Cross-connect or Test-Group name [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_getrxpkts(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if aorb is not None: data["aorb"] = aorb @@ -6771,9 +5539,10 @@ class LFJsonPost(LFCliBase): data["cx"] = cx if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/getrxpkts", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/getrxpkts", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6783,15 +5552,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#getrxporterrpkts ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_getrxporterrpkts(self, - aorb=None, # For AtoB, enter 'B', for BtoA, enter 'A'. - cx=None, # Cross-connect name - debug_=False): + aorb: str = None, # For AtoB, enter 'B', for BtoA, enter 'A'. + cx: str = None, # Cross-connect name [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_getrxporterrpkts(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if aorb is not None: data["aorb"] = aorb @@ -6799,9 +5568,10 @@ class LFJsonPost(LFCliBase): data["cx"] = cx if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/getrxporterrpkts", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/getrxporterrpkts", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6811,15 +5581,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#gettxpkts ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_gettxpkts(self, - aorb=None, # For endpoint a, enter 'A', for endpoint b, enter 'B'. - cx=None, # Cross-connect or Test-Group name - debug_=False): + aorb: str = None, # For endpoint a, enter 'A', for endpoint b, enter 'B'. + cx: str = None, # Cross-connect or Test-Group name [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_gettxpkts(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if aorb is not None: data["aorb"] = aorb @@ -6827,9 +5597,10 @@ class LFJsonPost(LFCliBase): data["cx"] = cx if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/gettxpkts", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/gettxpkts", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6839,23 +5610,24 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#gossip ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_gossip(self, - message=None, # Message to show to others currently logged on. Unescaped Value - debug_=False): + message: str = None, # Message to show to others currently logged on. Unescaped Value [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_gossip(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if message is not None: data["message"] = message if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/gossip", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/gossip", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6865,22 +5637,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#help ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_help(self, - command=None, # The command to get help for. Can be 'all', or blank. - debug_=False): + command: str = None, # The command to get help for. Can be 'all', or blank. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_help(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if command is not None: data["command"] = command if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/help", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/help", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6890,19 +5663,19 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#init_wiser ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_init_wiser(self, - file_name=None, # The WISER file name for the desired emulation, or 'NA' for empty + file_name: str = None, # The WISER file name for the desired emulation, or 'NA' for empty # string. - node_count=None, # The number of WISER nodes for the desired emulation, or 'NA' for + node_count: str = None, # The number of WISER nodes for the desired emulation, or 'NA' for # empty string. - resource=None, # The number of the resource in question. - shelf=None, # The number of the shelf in question. - debug_=False): + resource: int = None, # The number of the resource in question. [W] + shelf: int = 1, # The number of the shelf in question. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_init_wiser(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if file_name is not None: data["file_name"] = file_name @@ -6914,9 +5687,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/init_wiser", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/init_wiser", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6926,16 +5700,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#licenses ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_licenses(self, - popup=None, # If 'popup', then cause a GUI popup msg, otherwise, just show text. - show_file=None, # If 'yes', then show the license file, not the parsed license + popup: str = None, # If 'popup', then cause a GUI popup msg, otherwise, just show text. + show_file: str = None, # If 'yes', then show the license file, not the parsed license # information. - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_licenses(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if popup is not None: data["popup"] = popup @@ -6943,9 +5717,10 @@ class LFJsonPost(LFCliBase): data["show_file"] = show_file if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/licenses", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/licenses", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -6955,21 +5730,21 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#load ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_load(self, - action=None, # Should be 'append' or 'overwrite'. - clean_chambers=None, # If yes, then Chambers will be cleaned up when overwrite is selected, + action: str = None, # Should be 'append' or 'overwrite'. [W] + clean_chambers: str = None, # If yes, then Chambers will be cleaned up when overwrite is selected, # otherwise they will be kept. - clean_dut=None, # If yes, then DUT will be cleaned up when overwrite is selected, + clean_dut: str = None, # If yes, then DUT will be cleaned up when overwrite is selected, # otherwise they will be kept. - clean_profiles=None, # If yes, then clean all profiles when overwrite is selected, otherwise + clean_profiles: str = None, # If yes, then clean all profiles when overwrite is selected, otherwise # they will be kept. - name=None, # The name of the database to load. (DFLT is the default) - debug_=False): + name: str = None, # The name of the database to load. (DFLT is the default) [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_load(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if action is not None: data["action"] = action @@ -6983,9 +5758,10 @@ class LFJsonPost(LFCliBase): data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/load", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/load", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7031,15 +5807,15 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_log_level(self, - level=None, # Integer corresponding to the logging flags. - target=None, # Options: 'gnu' | [file-endp-name]. - debug_=False): + level: str = None, # Integer corresponding to the logging flags. [W] + target: str = None, # Options: 'gnu' | [file-endp-name]. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_log_level(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if level is not None: data["level"] = level @@ -7047,9 +5823,10 @@ class LFJsonPost(LFCliBase): data["target"] = target if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/log_level", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/log_level", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7059,22 +5836,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#log_msg ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_log_msg(self, - message=None, # Message to log. Unescaped Value - debug_=False): + message: str = None, # Message to log. Unescaped Value [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_log_msg(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if message is not None: data["message"] = message if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/log_msg", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/log_msg", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7084,16 +5862,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#login ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_login(self, - name=None, # A single name with no white-spaces (15 characters or less) - password=None, # Can be blank or 'NA' if no password is set, otherwise must be the + name: str = None, # A single name with no white-spaces (15 characters or less) [W] + password: str = None, # Can be blank or 'NA' if no password is set, otherwise must be the # password. - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_login(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name @@ -7101,9 +5879,10 @@ class LFJsonPost(LFCliBase): data["password"] = password if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/login", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/login", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7113,17 +5892,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#motd ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_motd(self, - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_motd(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} - response = self.json_post("/cli-json/motd", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/motd", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7133,16 +5913,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#nc_show_cd ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_nc_show_cd(self, - collision_domain=None, # Name of the Collision Domain, or 'all'. - resource=None, # Resource number, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - debug_=False): + collision_domain: str = None, # Name of the Collision Domain, or 'all'. [W] + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_nc_show_cd(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if collision_domain is not None: data["collision_domain"] = collision_domain @@ -7152,9 +5932,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/nc_show_cd", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/nc_show_cd", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7164,16 +5945,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#nc_show_channel_groups ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_nc_show_channel_groups(self, - channel_name=None, # Name of the channel, or 'all'. - resource=None, # Resource number, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - debug_=False): + channel_name: str = None, # Name of the channel, or 'all'. [W] + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_nc_show_channel_groups(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if channel_name is not None: data["channel_name"] = channel_name @@ -7183,9 +5964,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/nc_show_channel_groups", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/nc_show_channel_groups", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7195,15 +5977,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#nc_show_endpoints ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_nc_show_endpoints(self, - endpoint=None, # Name of endpoint, or 'all'. - extra=None, # See above. - debug_=False): + endpoint: str = None, # Name of endpoint, or 'all'. [W] + extra: str = None, # See above. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_nc_show_endpoints(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endpoint is not None: data["endpoint"] = endpoint @@ -7211,9 +5993,10 @@ class LFJsonPost(LFCliBase): data["extra"] = extra if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/nc_show_endpoints", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/nc_show_endpoints", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7223,22 +6006,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#nc_show_pesq ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_nc_show_pesq(self, - endpoint=None, # Name of endpoint, or 'all'. - debug_=False): + endpoint: str = None, # Name of endpoint, or 'all'. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_nc_show_pesq(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endpoint is not None: data["endpoint"] = endpoint if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/nc_show_pesq", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/nc_show_pesq", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7274,18 +6058,18 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_nc_show_ports(self, - port=None, # Port number, or 'all'. - probe_flags=None, # See above, add them together for multiple probings. Leave blank - # if you want stats only. - resource=None, # Resource number, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - debug_=False): + port: str = None, # Port number, or 'all'. [W] + probe_flags: str = None, # See above, add them together for multiple probings. Leave + # blank if you want stats only. + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_nc_show_ports(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if port is not None: data["port"] = port @@ -7297,9 +6081,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/nc_show_ports", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/nc_show_ports", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7309,16 +6094,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#nc_show_ppp_links ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_nc_show_ppp_links(self, - link_num=None, # Ppp-Link number of the span, or 'all'. - resource=None, # Resource number, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - debug_=False): + link_num: str = None, # Ppp-Link number of the span, or 'all'. [W] + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_nc_show_ppp_links(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if link_num is not None: data["link_num"] = link_num @@ -7328,9 +6113,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/nc_show_ppp_links", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/nc_show_ppp_links", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7340,16 +6126,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#nc_show_spans ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_nc_show_spans(self, - resource=None, # Resource number, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - span_number=None, # Span-Number of the span, or 'all'. - debug_=False): + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + span_number: str = None, # Span-Number of the span, or 'all'. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_nc_show_spans(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -7359,9 +6145,10 @@ class LFJsonPost(LFCliBase): data["span_number"] = span_number if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/nc_show_spans", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/nc_show_spans", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7371,16 +6158,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#nc_show_vr ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_nc_show_vr(self, - resource=None, # Resource number, or 'all'. - router=None, # Name of the Virtual Router, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - debug_=False): + resource: int = None, # Resource number, or 'all'. [W] + router: str = None, # Name of the Virtual Router, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_nc_show_vr(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -7390,9 +6177,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/nc_show_vr", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/nc_show_vr", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7402,16 +6190,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#nc_show_vrcx ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_nc_show_vrcx(self, - cx_name=None, # Name of the Virtual Router Connection, or 'all'. - resource=None, # Resource number, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - debug_=False): + cx_name: str = None, # Name of the Virtual Router Connection, or 'all'. [W] + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_nc_show_vrcx(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if cx_name is not None: data["cx_name"] = cx_name @@ -7421,9 +6209,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/nc_show_vrcx", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/nc_show_vrcx", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7433,22 +6222,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#notify_dhcp ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_notify_dhcp(self, - cmd=None, # set/down/timeout/info: What does DHCP want us to do? - netmask=None, # New subnet mask. - new_dns=None, # New DNS server(s) for use by this interface. - new_ip=None, # New IP address. - new_ip6=None, # New Global IPv6 address: ipv6/prefix - new_mtu=None, # New MTU. - new_router=None, # One or more default routers. LANforge will only use the first one. - port=None, # Interface name. - reason=None, # DHCP reason, informational mostly. - debug_=False): + cmd: str = None, # set/down/timeout/info: What does DHCP want us to do? [W] + netmask: str = None, # New subnet mask. + new_dns: str = None, # New DNS server(s) for use by this interface. + new_ip: str = None, # New IP address. + new_ip6: str = None, # New Global IPv6 address: ipv6/prefix + new_mtu: str = None, # New MTU. + new_router: str = None, # One or more default routers. LANforge will only use the first + # one. + port: str = None, # Interface name. [W] + reason: str = None, # DHCP reason, informational mostly. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_notify_dhcp(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if cmd is not None: data["cmd"] = cmd @@ -7470,9 +6260,10 @@ class LFJsonPost(LFCliBase): data["reason"] = reason if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/notify_dhcp", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/notify_dhcp", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7482,17 +6273,17 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#port_reset_completed ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_port_reset_completed(self, - extra=None, # IP for SECIP, blank for others. - port=None, # The port in question. - p_type=None, # SUNOS, NORMAL, or SECIP..let us know what kind of reset + extra: str = None, # IP for SECIP, blank for others. + port: str = None, # The port in question. [W] + p_type: str = None, # SUNOS, NORMAL, or SECIP..let us know what kind of reset # completed. - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_port_reset_completed(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if extra is not None: data["extra"] = extra @@ -7502,9 +6293,10 @@ class LFJsonPost(LFCliBase): data["type"] = p_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/port_reset_completed", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/port_reset_completed", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7514,17 +6306,17 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#probe_port ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_probe_port(self, - key=None, # Unique identifier for this request. Usually left blank.
- port=None, # Port number or name - resource=None, # Resource number. - shelf=None, # Shelf number. - debug_=False): + key: str = None, # Unique identifier for this request. Usually left blank.
+ port: str = None, # Port number or name [W] + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_probe_port(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if key is not None: data["key"] = key @@ -7536,9 +6328,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/probe_port", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/probe_port", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7548,15 +6341,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#probe_ports ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_probe_ports(self, - resource=None, # Resource number, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - debug_=False): + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_probe_ports(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -7564,9 +6357,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/probe_ports", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/probe_ports", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7576,22 +6370,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#quiesce_endp ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_quiesce_endp(self, - endp_name=None, # Name of the endpoint, or 'all'. - debug_=False): + endp_name: str = None, # Name of the endpoint, or 'all'. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_quiesce_endp(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endp_name is not None: data["endp_name"] = endp_name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/quiesce_endp", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/quiesce_endp", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7601,22 +6396,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#quiesce_group ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_quiesce_group(self, - name=None, # The name of the test group, or 'all' - debug_=False): + name: str = None, # The name of the test group, or 'all' [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_quiesce_group(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/quiesce_group", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/quiesce_group", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7626,17 +6422,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#quit ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_quit(self, - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_quit(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} - response = self.json_post("/cli-json/quit", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/quit", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7646,15 +6443,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#reboot_os ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_reboot_os(self, - resource=None, # Resource number, or ALL. - shelf=None, # Shelf number, or ALL. - debug_=False): + resource: int = None, # Resource number, or ALL. [W] + shelf: int = 1, # Shelf number, or ALL. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_reboot_os(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -7662,9 +6459,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/reboot_os", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/reboot_os", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7674,18 +6472,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#report ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_report(self, - reporting_on=None, # Should we globally enable/disable reporting. (YES, NO or NA) - rpt_dir=None, # Directory in which reports should be saved. - save_endps=None, # Should we save endpoint reports or not. (YES, NO or NA) - save_ports=None, # Should we save Port reports or not. (YES, NO or NA) - save_resource=None, # Should we save Resource reports or not. (YES, NO or NA) - debug_=False): + reporting_on: str = None, # Should we globally enable/disable reporting. (YES, NO or NA) + rpt_dir: str = None, # Directory in which reports should be saved. [W] + save_endps: str = None, # Should we save endpoint reports or not. (YES, NO or NA) + save_ports: str = None, # Should we save Port reports or not. (YES, NO or NA) + save_resource: str = None, # Should we save Resource reports or not. (YES, NO or NA) + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_report(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if reporting_on is not None: data["reporting_on"] = reporting_on @@ -7699,9 +6497,10 @@ class LFJsonPost(LFCliBase): data["save_resource"] = save_resource if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/report", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/report", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7720,19 +6519,19 @@ class LFJsonPost(LFCliBase): YES = "YES" # (include logout) Call portal-bot.pl ... --logout before going down. def post_reset_port(self, - port=None, # Port number to reset, or ALL. - pre_ifdown=None, # See above. Leave blank or use NA if unsure. - reset_ospf=None, # If set to 'NO' or 'NA', then OSPF will not be updated. Otherwise, it - # will be updated. - resource=None, # Resource number, or ALL. - shelf=None, # Shelf number, or ALL. - debug_=False): + port: str = None, # Port number to reset, or ALL. [W] + pre_ifdown: str = None, # See above. Leave blank or use NA if unsure. + reset_ospf: str = None, # If set to 'NO' or 'NA', then OSPF will not be updated. Otherwise, + # it will be updated. + resource: int = None, # Resource number, or ALL. [W] + shelf: int = 1, # Shelf number, or ALL. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_reset_port(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if port is not None: data["port"] = port @@ -7746,9 +6545,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/reset_port", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/reset_port", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7758,16 +6558,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#reset_serial_span ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_reset_serial_span(self, - resource=None, # Resource (machine) number. - shelf=None, # Shelf number - span=None, # Serial-Span number to reset. - debug_=False): + resource: int = None, # Resource (machine) number. [W] + shelf: int = 1, # Shelf number [R][D:1] + span: str = None, # Serial-Span number to reset. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_reset_serial_span(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -7777,9 +6577,10 @@ class LFJsonPost(LFCliBase): data["span"] = span if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/reset_serial_span", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/reset_serial_span", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7789,16 +6590,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_attenuator ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_attenuator(self, - resource=None, # Resource number - serno=None, # Serial number for requested Attenuator. - shelf=None, # Shelf number, usually 1 - debug_=False): + resource: int = None, # Resource number [W] + serno: str = None, # Serial number for requested Attenuator. [W] + shelf: int = 1, # Shelf number, usually 1 [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_attenuator(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -7808,9 +6609,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_attenuator", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_attenuator", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7820,22 +6622,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_cd ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_cd(self, - cd=None, # Name of Collision Domain. - debug_=False): + cd: str = None, # Name of Collision Domain. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_cd(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if cd is not None: data["cd"] = cd if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_cd", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_cd", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7845,15 +6648,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_cd_endp ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_cd_endp(self, - cd=None, # Name of Collision Domain. - endp=None, # Endpoint name/id. - debug_=False): + cd: str = None, # Name of Collision Domain. [W] + endp: str = None, # Endpoint name/id. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_cd_endp(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if cd is not None: data["cd"] = cd @@ -7861,9 +6664,10 @@ class LFJsonPost(LFCliBase): data["endp"] = endp if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_cd_endp", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_cd_endp", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7873,15 +6677,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_cd_vr ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_cd_vr(self, - cd=None, # Name of Collision Domain. - endp=None, # Virtual-Router name/id. - debug_=False): + cd: str = None, # Name of Collision Domain. [W] + endp: str = None, # Virtual-Router name/id. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_cd_vr(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if cd is not None: data["cd"] = cd @@ -7889,9 +6693,10 @@ class LFJsonPost(LFCliBase): data["endp"] = endp if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_cd_vr", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_cd_vr", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7901,22 +6706,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_chamber ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_chamber(self, - chamber=None, # Chamber name, or 'ALL' - debug_=False): + chamber: str = None, # Chamber name, or 'ALL' [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_chamber(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if chamber is not None: data["chamber"] = chamber if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_chamber", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_chamber", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7926,15 +6732,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_chamber_path ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_chamber_path(self, - chamber=None, # Chamber Name. - path=None, # Path Name, use 'ALL' to delete all paths. - debug_=False): + chamber: str = None, # Chamber Name. [W] + path: str = None, # Path Name, use 'ALL' to delete all paths. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_chamber_path(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if chamber is not None: data["chamber"] = chamber @@ -7942,9 +6748,10 @@ class LFJsonPost(LFCliBase): data["path"] = path if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_chamber_path", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_chamber_path", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7954,16 +6761,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_channel_group ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_channel_group(self, - channel_name=None, # Name of the channel, or 'all'. - resource=None, # Resource number, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - debug_=False): + channel_name: str = None, # Name of the channel, or 'all'. [W] + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_channel_group(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if channel_name is not None: data["channel_name"] = channel_name @@ -7973,9 +6780,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_channel_group", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_channel_group", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -7985,15 +6793,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_client ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_client(self, - client_name=None, # Name of the client profile you wish to remove. - client_password=None, # Client password. Not required if we are super-user. - debug_=False): + client_name: str = None, # Name of the client profile you wish to remove. [W] + client_password: str = None, # Client password. Not required if we are super-user. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_client(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if client_name is not None: data["client_name"] = client_name @@ -8001,9 +6809,10 @@ class LFJsonPost(LFCliBase): data["client_password"] = client_password if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_client", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_client", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8013,15 +6822,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_cx ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_cx(self, - cx_name=None, # Name of the cross-connect, or 'all'. - test_mgr=None, # Name of test-mgr, or 'all'. - debug_=False): + cx_name: str = None, # Name of the cross-connect, or 'all'. [W] + test_mgr: str = None, # Name of test-mgr, or 'all'. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_cx(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if cx_name is not None: data["cx_name"] = cx_name @@ -8029,9 +6838,10 @@ class LFJsonPost(LFCliBase): data["test_mgr"] = test_mgr if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_cx", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_cx", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8041,22 +6851,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_db ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_db(self, - db_name=None, # Name of the database to delete. - debug_=False): + db_name: str = None, # Name of the database to delete. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_db(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if db_name is not None: data["db_name"] = db_name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_db", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_db", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8066,22 +6877,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_dut ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_dut(self, - shelf=None, # DUT name, or 'ALL' - debug_=False): + shelf: int = 1, # DUT name, or 'ALL' [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_dut(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if shelf is not None: data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_dut", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_dut", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8091,22 +6903,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_endp ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_endp(self, - endp_name=None, # Name of the endpoint, or 'YES_ALL'. - debug_=False): + endp_name: str = None, # Name of the endpoint, or 'YES_ALL'. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_endp(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endp_name is not None: data["endp_name"] = endp_name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_endp", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_endp", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8116,22 +6929,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_event ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_event(self, - event_id=None, # Numeric event-id, or 'all' - debug_=False): + event_id: str = None, # Numeric event-id, or 'all' [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_event(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if event_id is not None: data["event_id"] = event_id if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_event", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_event", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8141,22 +6955,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_group ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_group(self, - name=None, # The name of the test group. - debug_=False): + name: str = None, # The name of the test group. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_group(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_group", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_group", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8166,16 +6981,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_ppp_link ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_ppp_link(self, - resource=None, # Resource number that holds this PppLink. - shelf=None, # Name/id of the shelf. - unit_num=None, # Unit-Number for the PppLink to be deleted. - debug_=False): + resource: int = None, # Resource number that holds this PppLink. [W] + shelf: int = 1, # Name/id of the shelf. [R][D:1] + unit_num: str = None, # Unit-Number for the PppLink to be deleted. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_ppp_link(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -8185,9 +7000,10 @@ class LFJsonPost(LFCliBase): data["unit_num"] = unit_num if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_ppp_link", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_ppp_link", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8197,22 +7013,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_profile ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_profile(self, - name=None, # Profile name, or 'ALL' - debug_=False): + name: str = None, # Profile name, or 'ALL' [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_profile(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_profile", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_profile", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8222,15 +7039,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_resource ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_resource(self, - resource=None, # Resource number. - shelf=None, # Shelf number. - debug_=False): + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_resource(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -8238,9 +7055,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_resource", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_resource", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8250,15 +7068,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_rfgen ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_rfgen(self, - resource=None, # Resource number - shelf=None, # Shelf number, usually 1 - debug_=False): + resource: int = None, # Resource number [W] + shelf: int = 1, # Shelf number, usually 1 [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_rfgen(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -8266,9 +7084,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_rfgen", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_rfgen", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8278,17 +7097,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_sec_ip ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_sec_ip(self, - ip_list=None, # IP1/prefix,IP2/prefix,...IPZ/prefix, or ALL - port=None, # Name of network device (Port) from which these IPs will be removed. - resource=None, # Resource number. - shelf=None, # Shelf number. - debug_=False): + ip_list: str = None, # IP1/prefix,IP2/prefix,...IPZ/prefix, or ALL [W] + port: str = None, # Name of network device (Port) from which these IPs will be removed. + # [W] + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_sec_ip(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if ip_list is not None: data["ip_list"] = ip_list @@ -8300,9 +7120,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_sec_ip", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_sec_ip", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8312,16 +7133,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_span ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_span(self, - resource=None, # Resource number, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - span_num=None, # Span-Number of the channel, or 'all'. - debug_=False): + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + span_num: str = None, # Span-Number of the channel, or 'all'. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_span(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -8331,9 +7152,10 @@ class LFJsonPost(LFCliBase): data["span_num"] = span_num if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_span", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_span", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8343,22 +7165,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_test_mgr ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_test_mgr(self, - test_mgr=None, # Name of the test manager to be removed. - debug_=False): + test_mgr: str = None, # Name of the test manager to be removed. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_test_mgr(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if test_mgr is not None: data["test_mgr"] = test_mgr if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_test_mgr", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_test_mgr", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8368,15 +7191,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_text_blob ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_text_blob(self, - name=None, # Text Blob Name, or 'ALL' - p_type=None, # Text Blob type, or 'ALL' - debug_=False): + name: str = None, # Text Blob Name, or 'ALL' [W] + p_type: str = None, # Text Blob type, or 'ALL' [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_text_blob(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name @@ -8384,9 +7207,10 @@ class LFJsonPost(LFCliBase): data["type"] = p_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_text_blob", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_text_blob", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8396,15 +7220,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_tgcx ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_tgcx(self, - cxname=None, # The name of the CX. - tgname=None, # The name of the test group. - debug_=False): + cxname: str = None, # The name of the CX. [W] + tgname: str = None, # The name of the test group. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_tgcx(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if cxname is not None: data["cxname"] = cxname @@ -8412,9 +7236,10 @@ class LFJsonPost(LFCliBase): data["tgname"] = tgname if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_tgcx", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_tgcx", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8424,15 +7249,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_threshold ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_threshold(self, - endp=None, # Endpoint name or ID. - thresh_id=None, # Threshold ID to remove. Use 'all' to remove all. - debug_=False): + endp: str = None, # Endpoint name or ID. [W] + thresh_id: str = None, # Threshold ID to remove. Use 'all' to remove all. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_threshold(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endp is not None: data["endp"] = endp @@ -8440,9 +7265,10 @@ class LFJsonPost(LFCliBase): data["thresh_id"] = thresh_id if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_threshold", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_threshold", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8452,22 +7278,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_traffic_profile ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_traffic_profile(self, - name=None, # Profile name, or 'ALL' - debug_=False): + name: str = None, # Profile name, or 'ALL' [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_traffic_profile(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_traffic_profile", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_traffic_profile", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8477,16 +7304,17 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_venue ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_venue(self, - resource=None, # Resource number, or 'ALL' - shelf=None, # Shelf number. - venu_id=None, # Number to uniquely identify this venue on this resource, or 'ALL' - debug_=False): + resource: int = None, # Resource number, or 'ALL' [W] + shelf: int = 1, # Shelf number. [R][D:1] + venu_id: str = None, # Number to uniquely identify this venue on this resource, or 'ALL' + # [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_venue(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -8496,9 +7324,10 @@ class LFJsonPost(LFCliBase): data["venu_id"] = venu_id if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_venue", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_venue", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8508,16 +7337,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_vlan ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_vlan(self, - port=None, # Port number or name of the virtual interface. - resource=None, # Resource number. - shelf=None, # Shelf number. - debug_=False): + port: str = None, # Port number or name of the virtual interface. [W] + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_vlan(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if port is not None: data["port"] = port @@ -8527,9 +7356,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_vlan", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_vlan", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8539,16 +7369,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_vr ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_vr(self, - resource=None, # Resource number, or 'all'. - router_name=None, # Virtual Router name, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - debug_=False): + resource: int = None, # Resource number, or 'all'. [W] + router_name: str = None, # Virtual Router name, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_vr(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -8558,9 +7388,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_vr", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_vr", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8570,20 +7401,20 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_vrcx ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_vrcx(self, - connection_name=None, # Virtual Router Connection name, or 'all'. - resource=None, # Resource number, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - vr_id=None, # If not removing from the free-list, then supply the virtual-router - # name/ID here. Leave blank or use NA for free-list. - vrcx_only=None, # If we should NOT delete underlying auto-created objects, enter + connection_name: str = None, # Virtual Router Connection name, or 'all'. [W] + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + vr_id: str = None, # If not removing from the free-list, then supply the + # virtual-router name/ID here. Leave blank or use NA for free-list. + vrcx_only: str = None, # If we should NOT delete underlying auto-created objects, enter # 'vrcx_only' here, otherwise leave blank or use NA. - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_vrcx(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if connection_name is not None: data["connection_name"] = connection_name @@ -8597,9 +7428,10 @@ class LFJsonPost(LFCliBase): data["vrcx_only"] = vrcx_only if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_vrcx", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_vrcx", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8609,15 +7441,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rm_wanpath ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rm_wanpath(self, - endp_name=None, # Name of the endpoint. - wp_name=None, # Name of the wanpath. - debug_=False): + endp_name: str = None, # Name of the endpoint. [W] + wp_name: str = None, # Name of the wanpath. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rm_wanpath(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endp_name is not None: data["endp_name"] = endp_name @@ -8625,9 +7457,10 @@ class LFJsonPost(LFCliBase): data["wp_name"] = wp_name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rm_wanpath", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rm_wanpath", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8637,20 +7470,20 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#rpt_script ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_rpt_script(self, - endp=None, # Endpoint name or ID. - flags=None, # See above for description of the defined flags. - group_action=None, # All or Sequential. - loop_count=None, # How many times to loop before stopping (0 is infinite). - name=None, # Script name. - private=None, # Private encoding for the particular script. - p_type=None, # One of: NONE, Script2544, ScriptHunt, ScriptWL - debug_=False): + endp: str = None, # Endpoint name or ID. [W] + flags: str = None, # See above for description of the defined flags. + group_action: str = None, # All or Sequential. + loop_count: str = None, # How many times to loop before stopping (0 is infinite). + name: str = None, # Script name. [W] + private: str = None, # Private encoding for the particular script. + p_type: str = None, # One of: NONE, Script2544, ScriptHunt, ScriptWL + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_rpt_script(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endp is not None: data["endp"] = endp @@ -8668,9 +7501,10 @@ class LFJsonPost(LFCliBase): data["type"] = p_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/rpt_script", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/rpt_script", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8689,18 +7523,18 @@ class LFJsonPost(LFCliBase): trigger_freq__freq_ = "trigger freq [freq]" # scan exactly those frequencies def post_scan_wifi(self, - extra=None, # Extra arguments to the scan script, see above. - key=None, # Unique identifier for this request. Usually left blank. - port=None, # Port number or name of the virtual interface. - resource=None, # Resource number. - shelf=None, # Shelf number. - debug_=False): + extra: str = None, # Extra arguments to the scan script, see above. + key: str = None, # Unique identifier for this request. Usually left blank. + port: str = None, # Port number or name of the virtual interface. [W] + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_scan_wifi(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if extra is not None: data["extra"] = extra @@ -8714,9 +7548,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/scan_wifi", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/scan_wifi", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8751,37 +7586,37 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_set_arm_info(self, - arm_flags=None, # Armageddon-related flags, see above for details. - burst=None, # Burst amount, can significantly improve throughput with some - # modern drivers, similar to 'multi_pkts', and uses the 'xmit_more' - # linux skb option. - dst_mac=None, # The destination MAC address. - dst_mac_count=None, # How many destination MACs to iterate through. - ip_dst_max=None, # Maximum destination IP address to use. - ip_dst_min=None, # Minimum destination IP address to use. - ip_src_max=None, # Maximum source IP address to use. - ip_src_min=None, # Minimum source IP address to use. - max_pkt_size=None, # Maximum packet size, including all Ethernet headers (but not + arm_flags: str = None, # Armageddon-related flags, see above for details. + burst: str = None, # Burst amount, can significantly improve throughput with some + # modern drivers, similar to 'multi_pkts', and uses the + # 'xmit_more' linux skb option. + dst_mac: str = None, # The destination MAC address. + dst_mac_count: str = None, # How many destination MACs to iterate through. + ip_dst_max: str = None, # Maximum destination IP address to use. + ip_dst_min: str = None, # Minimum destination IP address to use. + ip_src_max: str = None, # Maximum source IP address to use. + ip_src_min: str = None, # Minimum source IP address to use. + max_pkt_size: str = None, # Maximum packet size, including all Ethernet headers (but not # CRC). - min_pkt_size=None, # Minimum packet size, including all Ethernet headers (but not + min_pkt_size: str = None, # Minimum packet size, including all Ethernet headers (but not # CRC). - multi_pkts=None, # The number of identical packets to send before creating a new + multi_pkts: str = None, # The number of identical packets to send before creating a new # one. - name=None, # Name of the Endpoint we are setting. - pkts_to_send=None, # The number of packets to send. Set to zero for infinite. - src_mac=None, # The source MAC address. - src_mac_count=None, # How many source MACs to iterate through. - udp_dst_max=None, # Minimum destination UDP port. - udp_dst_min=None, # Minimum destination UDP port. - udp_src_max=None, # Maximum source UDP port. - udp_src_min=None, # Minimum source UDP port. - debug_=False): + name: str = None, # Name of the Endpoint we are setting. [R] + pkts_to_send: str = None, # The number of packets to send. Set to zero for infinite. + src_mac: str = None, # The source MAC address. + src_mac_count: str = None, # How many source MACs to iterate through. + udp_dst_max: str = None, # Minimum destination UDP port. + udp_dst_min: str = None, # Minimum destination UDP port. + udp_src_max: str = None, # Maximum source UDP port. + udp_src_min: str = None, # Minimum source UDP port. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_arm_info(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if arm_flags is not None: data["arm_flags"] = arm_flags @@ -8823,9 +7658,10 @@ class LFJsonPost(LFCliBase): data["udp_src_min"] = udp_src_min if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_arm_info", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_arm_info", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8834,26 +7670,35 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_attenuator ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + class SetAttenuatorMode(Enum): + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Example Usage: + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + p_0 = "0" # Normal + p_1 = "1" # Pulse mode (API Tech 4205A modules directly connected via USB only) + def post_set_attenuator(self, - atten_idx=None, # Attenuator index, or 'all'. - mode=None, # 0 == normal attenuator, 1 == pulse mode (API Tech 4205A + atten_idx: str = None, # Attenuator index, or 'all'. [W] + mode: str = None, # 0 == normal attenuator, 1 == pulse mode (API Tech 4205A # modules directly connected via USB only) - pulse_count=None, # Number of pulses (0-255) - pulse_interval_ms=None, # Time between pulses, in mili-seconds (0-60000). - pulse_time_ms=None, # Time interval between pulse groups in miliseconds (1-60000) - pulse_width_us5=None, # Pulse width in units of 1/2 micro second. So, if you want + pulse_count: str = None, # Number of pulses (0-255) + pulse_interval_ms: str = None, # Time between pulses, in mili-seconds (0-60000). + pulse_time_ms: str = None, # Time interval between pulse groups in miliseconds + # (1-60000) + pulse_width_us5: str = None, # Pulse width in units of 1/2 micro second. So, if you want # 1.5us, use value 3 (0-60000) - resource=None, # Resource number. - serno=None, # Serial number for requested Attenuator, or 'all'. - shelf=None, # Shelf number, usually 1. - val=None, # Requested attenution in 1/10ths of dB (ddB). - debug_=False): + resource: int = None, # Resource number. [W] + serno: str = None, # Serial number for requested Attenuator, or 'all'. [W] + shelf: int = 1, # Shelf number, usually 1. [R][D:1] + val: str = None, # Requested attenution in 1/10ths of dB (ddB). [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_attenuator(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if atten_idx is not None: data["atten_idx"] = atten_idx @@ -8877,9 +7722,10 @@ class LFJsonPost(LFCliBase): data["val"] = val if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_attenuator", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_attenuator", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8889,21 +7735,20 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_chamber ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_chamber(self, - chamber=None, # Chamber name - cur_rotation=None, # Primarily used to store the last known rotation for turntables - # that do not report absolute position. Use NA or leave blank if - # unsure. - position=None, # Absolute position in degrees. - speed_rpm=None, # Speed in rpm (floating point number is accepted - tilt=None, # Absolute tilt in degrees. - turntable=None, # Turn-table address, for instance: 192.168.1.22:3001 - debug_=False): + chamber: str = None, # Chamber name [W] + cur_rotation: str = None, # Primarily used to store the last known rotation for turntables + # that do not report absolute position. + position: str = None, # Absolute position in degrees. + speed_rpm: str = None, # Speed in rpm (floating point number is accepted + tilt: str = None, # Absolute tilt in degrees. + turntable: str = None, # Turn-table address, for instance: 192.168.1.22:3001 + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_chamber(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if chamber is not None: data["chamber"] = chamber @@ -8919,9 +7764,10 @@ class LFJsonPost(LFCliBase): data["turntable"] = turntable if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_chamber", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_chamber", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8931,17 +7777,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_cx_report_timer ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_cx_report_timer(self, - cx_name=None, # Name of cross-connect, or 'all'. - cxonly=None, # If you want to set the timer for ONLY the CX, and not - milliseconds=None, # Report timer length in milliseconds. - test_mgr=None, # Name of the test manager, or 'all'. - debug_=False): + cx_name: str = None, # Name of cross-connect, or 'all'. [W] + cxonly: str = None, # If you want to set the timer for ONLY the CX, and not + milliseconds: str = None, # Report timer length in milliseconds. + # [W,250-60000][D:5000] + test_mgr: str = None, # Name of the test manager, or 'all'. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_cx_report_timer(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if cx_name is not None: data["cx_name"] = cx_name @@ -8953,9 +7800,10 @@ class LFJsonPost(LFCliBase): data["test_mgr"] = test_mgr if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_cx_report_timer", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_cx_report_timer", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -8976,16 +7824,16 @@ class LFJsonPost(LFCliBase): SWITCH = "SWITCH" # Sets the CX(s) in the running state, stopping any conflicting tests. def post_set_cx_state(self, - cx_name=None, # Name of the cross-connect, or 'all'. - cx_state=None, # One of: RUNNING, SWITCH, QUIESCE, STOPPED, or DELETED. - test_mgr=None, # Name of the test-manager, or 'all'. - debug_=False): + cx_name: str = None, # Name of the cross-connect, or 'all'. [W] + cx_state: str = None, # One of: RUNNING, SWITCH, QUIESCE, STOPPED, or DELETED. [W] + test_mgr: str = None, # Name of the test-manager, or 'all'. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_cx_state(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if cx_name is not None: data["cx_name"] = cx_name @@ -8995,9 +7843,10 @@ class LFJsonPost(LFCliBase): data["test_mgr"] = test_mgr if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_cx_state", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_cx_state", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9007,18 +7856,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_endp_addr ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_endp_addr(self, - ip=None, # The IP Address. Used for TCP/IP and UDP/IP protocols. - mac=None, # The MAC address. Only needed for LANforge protocol Endpoints. - max_port=None, # The Maximum IP Port. Used for TCP/IP and UDP/IP protocols. - min_port=None, # The Minimum IP Port. Used for TCP/IP and UDP/IP protocols. - name=None, # The name of the endpoint we are configuring. - debug_=False): + ip: str = None, # The IP Address. Used for TCP/IP and UDP/IP protocols. + mac: str = None, # The MAC address. Only needed for LANforge protocol Endpoints. + max_port: str = None, # The Maximum IP Port. Used for TCP/IP and UDP/IP protocols. + min_port: str = None, # The Minimum IP Port. Used for TCP/IP and UDP/IP protocols. + name: str = None, # The name of the endpoint we are configuring. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_endp_addr(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if ip is not None: data["ip"] = ip @@ -9032,9 +7881,10 @@ class LFJsonPost(LFCliBase): data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_endp_addr", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_endp_addr", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9044,40 +7894,41 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_endp_details ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_endp_details(self, - conn_timeout=None, # For TCP, the max time in miliseconds to wait for connection - # to establish. - dst_mac=None, # Destination MAC address, used for custom Ethernet replays. - max_conn_timer=None, # The maximum duration (in ms) this connection should run + conn_timeout: str = None, # For TCP, the max time in miliseconds to wait for + # connection to establish. + dst_mac: str = None, # Destination MAC address, used for custom Ethernet + # replays. + max_conn_timer: str = None, # The maximum duration (in ms) this connection should run # before re-establishing. - max_ip_port=None, # The maximum IP Port value. (The value for min ip port is + max_ip_port: str = None, # The maximum IP Port value. (The value for min ip port is # set through the add_endp/ip_port parameter.) If greater - # than min, each connection will use a random value between - # min and max. - max_reconn_pause=None, # The maximum time between re-connects, in ms. - mcast_src_ip=None, # Multicast source address (used in SSM mode, multicast + # than min, each connection will use a random value + # between min and max. + max_reconn_pause: str = None, # The maximum time between re-connects, in ms. + mcast_src_ip: str = None, # Multicast source address (used in SSM mode, multicast # endpoints only) - mcast_src_port=None, # Multicast source address (used in SSM mode, multicast + mcast_src_port: str = None, # Multicast source address (used in SSM mode, multicast # endpoints only) - min_conn_timer=None, # The minimum duration (in ms) this connection should run + min_conn_timer: str = None, # The minimum duration (in ms) this connection should run # before re-establishing. - min_reconn_pause=None, # The minimum time between re-connects, in ms. - name=None, # The name of the endpoint we are configuring. - pkts_to_send=None, # Number of packets to send before stopping. 0 means + min_reconn_pause: str = None, # The minimum time between re-connects, in ms. + name: str = None, # The name of the endpoint we are configuring. [R] + pkts_to_send: str = None, # Number of packets to send before stopping. 0 means # infinite. - rcvbuf_size=None, # The receive buffer (window) size. Zero for AUTO - sndbuf_size=None, # The sending buffer (window) size. Zero for AUTO - tcp_delack_segs=None, # NA: No longer supported. - tcp_max_delack=None, # NA: No longer supported. - tcp_min_delack=None, # NA: No longer supported. - tcp_mss=None, # TCP Maximum Segment Size, affects packet size on the wire - # (88 - 32767). - debug_=False): + rcvbuf_size: str = None, # The receive buffer (window) size. Zero for AUTO + sndbuf_size: str = None, # The sending buffer (window) size. Zero for AUTO + tcp_delack_segs: str = None, # NA: No longer supported. + tcp_max_delack: str = None, # NA: No longer supported. + tcp_min_delack: str = None, # NA: No longer supported. + tcp_mss: str = None, # TCP Maximum Segment Size, affects packet size on the + # wire (88 - 32767). + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_endp_details(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if conn_timeout is not None: data["conn_timeout"] = conn_timeout @@ -9115,9 +7966,10 @@ class LFJsonPost(LFCliBase): data["tcp_mss"] = tcp_mss if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_endp_details", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_endp_details", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9126,17 +7978,25 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_endp_file ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + class SetEndpFilePlayback(Enum): + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Example Usage: + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + OFF = "OFF" # off + ON = "ON" # on + def post_set_endp_file(self, - file=None, # The file name to read the playback packets from. - name=None, # The name of the endpoint we are configuring. - playback=None, # Should we playback the capture or not? ON or OFF. - debug_=False): + file: str = None, # The file name to read the playback packets from. + name: str = None, # The name of the endpoint we are configuring. [R] + playback: str = None, # Should we playback the capture or not? ON or OFF. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_endp_file(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if file is not None: data["file"] = file @@ -9146,9 +8006,10 @@ class LFJsonPost(LFCliBase): data["playback"] = playback if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_endp_file", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_endp_file", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9176,16 +8037,16 @@ class LFJsonPost(LFCliBase): UseAutoNAT = "UseAutoNAT" # NAT friendly behavior def post_set_endp_flag(self, - flag=None, # The name of the flag. - name=None, # The name of the endpoint we are configuring. - val=None, # Either 1 (for on), or 0 (for off). - debug_=False): + flag: str = None, # The name of the flag. [R] + name: str = None, # The name of the endpoint we are configuring. [R] + val: str = None, # Either 1 (for on), or 0 (for off). [R,0-1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_endp_flag(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if flag is not None: data["flag"] = flag @@ -9195,9 +8056,10 @@ class LFJsonPost(LFCliBase): data["val"] = val if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_endp_flag", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_endp_flag", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9224,17 +8086,17 @@ class LFJsonPost(LFCliBase): zeros = "zeros" # Payload is all zeros (00). def post_set_endp_payload(self, - name=None, # The name of the endpoint we are configuring. - payload=None, # For custom payloads, enter the payload in hex, up to 2048 + name: str = None, # The name of the endpoint we are configuring. [R] + payload: str = None, # For custom payloads, enter the payload in hex, up to 2048 # bytes. Unescaped Value - payload_type=None, # The payload type. See help for add_endp. - debug_=False): + payload_type: str = None, # The payload type. See help for add_endp. [W][D:increasing] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_endp_payload(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name @@ -9244,9 +8106,10 @@ class LFJsonPost(LFCliBase): data["payload_type"] = payload_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_endp_payload", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_endp_payload", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9256,18 +8119,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_endp_pld_bounds ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_endp_pld_bounds(self, - is_random=None, # YES if random, anything else for NO. - max_pld_size=None, # The maximum payload size, in bytes. - min_pld_size=None, # The minimum payload size, in bytes. - name=None, # The name of the endpoint we are configuring. - use_checksum=None, # YES if use checksum on payload, anything else for NO. - debug_=False): + is_random: str = None, # YES if random, anything else for NO. + max_pld_size: str = None, # The maximum payload size, in bytes. + min_pld_size: str = None, # The minimum payload size, in bytes. + name: str = None, # The name of the endpoint we are configuring. [R] + use_checksum: str = None, # YES if use checksum on payload, anything else for NO. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_endp_pld_bounds(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if is_random is not None: data["is_random"] = is_random @@ -9281,9 +8144,10 @@ class LFJsonPost(LFCliBase): data["use_checksum"] = use_checksum if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_endp_pld_bounds", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_endp_pld_bounds", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9293,17 +8157,17 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_endp_proxy ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_endp_proxy(self, - enabled=None, # YES or NO to enable or disable proxying. - endp_name=None, # Name of endpoint. - proxy_ip=None, # Proxy IP Address. - proxy_ip_port=None, # Proxy IP Port. - debug_=False): + enabled: str = None, # YES or NO to enable or disable proxying. + endp_name: str = None, # Name of endpoint. [W] + proxy_ip: str = None, # Proxy IP Address. + proxy_ip_port: str = None, # Proxy IP Port. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_endp_proxy(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if enabled is not None: data["enabled"] = enabled @@ -9315,9 +8179,10 @@ class LFJsonPost(LFCliBase): data["proxy_ip_port"] = proxy_ip_port if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_endp_proxy", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_endp_proxy", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9327,16 +8192,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_endp_quiesce ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_endp_quiesce(self, - name=None, # The name of the endpoint we are configuring. - quiesce=None, # The number of seconds to quiesce this endpoint when told to - # quiesce. - debug_=False): + name: str = None, # The name of the endpoint we are configuring. [R] + quiesce: str = None, # The number of seconds to quiesce this endpoint when told to + # quiesce. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_endp_quiesce(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name @@ -9344,9 +8209,10 @@ class LFJsonPost(LFCliBase): data["quiesce"] = quiesce if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_endp_quiesce", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_endp_quiesce", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9356,15 +8222,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_endp_report_timer ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_endp_report_timer(self, - endp_name=None, # Name of endpoint. - milliseconds=None, # Report timer length in milliseconds. - debug_=False): + endp_name: str = None, # Name of endpoint. [R] + milliseconds: str = None, # Report timer length in milliseconds. + # [W,250-60000][D:5000] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_endp_report_timer(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endp_name is not None: data["endp_name"] = endp_name @@ -9372,9 +8239,10 @@ class LFJsonPost(LFCliBase): data["milliseconds"] = milliseconds if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_endp_report_timer", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_endp_report_timer", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9394,16 +8262,16 @@ class LFJsonPost(LFCliBase): THROUGHPUT = "THROUGHPUT" # def post_set_endp_tos(self, - name=None, # The name of the endpoint we are configuring. - priority=None, # The socket priority, can be any positive number. - tos=None, # The Type of Service, can be HEX, see above. - debug_=False): + name: str = None, # The name of the endpoint we are configuring. [R] + priority: str = None, # The socket priority, can be any positive number. + tos: str = None, # The Type of Service, can be HEX, see above. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_endp_tos(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name @@ -9413,9 +8281,10 @@ class LFJsonPost(LFCliBase): data["tos"] = tos if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_endp_tos", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_endp_tos", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9425,17 +8294,17 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_endp_tx_bounds ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_endp_tx_bounds(self, - is_bursty=None, # YES if bursty, anything else for NO. - max_tx_rate=None, # The maximum transmit rate, in bits per second (bps). - min_tx_rate=None, # The minimum transmit rate, in bits per second (bps). - name=None, # The name of the endpoint we are configuring. - debug_=False): + is_bursty: str = None, # YES if bursty, anything else for NO. + max_tx_rate: str = None, # The maximum transmit rate, in bits per second (bps). + min_tx_rate: str = None, # The minimum transmit rate, in bits per second (bps). + name: str = None, # The name of the endpoint we are configuring. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_endp_tx_bounds(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if is_bursty is not None: data["is_bursty"] = is_bursty @@ -9447,9 +8316,10 @@ class LFJsonPost(LFCliBase): data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_endp_tx_bounds", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_endp_tx_bounds", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9565,20 +8435,20 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_set_event_interest(self, - ei_flags=None, # Event Interest flags, see above. - event_cnt=None, # Maximum number of events to store. - events1=None, # See description for possible values. - events2=None, # See description for possible values. - events3=None, # See description for possible values. - events4=None, # See description for possible values. - var1=None, # Currently un-used. - debug_=False): + ei_flags: str = None, # Event Interest flags, see above. [W] + event_cnt: str = None, # Maximum number of events to store. + events1: str = None, # See description for possible values. + events2: str = None, # See description for possible values. + events3: str = None, # See description for possible values. + events4: str = None, # See description for possible values. + var1: str = None, # Currently un-used. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_event_interest(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if ei_flags is not None: data["ei_flags"] = ei_flags @@ -9596,9 +8466,10 @@ class LFJsonPost(LFCliBase): data["var1"] = var1 if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_event_interest", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_event_interest", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9647,15 +8518,15 @@ class LFJsonPost(LFCliBase): WARNING = "WARNING" # def post_set_event_priority(self, - event=None, # Number or name for the event, see above. - priority=None, # Number or name for the priority. - debug_=False): + event: str = None, # Number or name for the event, see above. [R,0-21] + priority: str = None, # Number or name for the priority. [R,0-5] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_event_priority(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if event is not None: data["event"] = event @@ -9663,9 +8534,10 @@ class LFJsonPost(LFCliBase): data["priority"] = priority if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_event_priority", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_event_priority", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9675,24 +8547,24 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_fe_info ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_fe_info(self, - directory=None, # The directory to read/write in. Absolute path suggested. - io_direction=None, # Should we be reading or writing: options: read, write - max_file_size=None, # The maximum file size, in bytes. - max_rw_sz=None, # Maximum read/write size, in bytes. - min_file_size=None, # The minimum file size, in bytes. - min_rw_sz=None, # Minimum read/write size, in bytes. - name=None, # The name of the file endpoint we are configuring. - num_files=None, # Number of files to create when writing. - prefix=None, # The prefix of the file(s) to read/write. - quiesce_after_files=None, # If non-zero, quiesce test after this many files have been + directory: str = None, # The directory to read/write in. Absolute path suggested. + io_direction: str = None, # Should we be reading or writing: options: read, write + max_file_size: str = None, # The maximum file size, in bytes. + max_rw_sz: str = None, # Maximum read/write size, in bytes. + min_file_size: str = None, # The minimum file size, in bytes. + min_rw_sz: str = None, # Minimum read/write size, in bytes. + name: str = None, # The name of the file endpoint we are configuring. [R] + num_files: str = None, # Number of files to create when writing. + prefix: str = None, # The prefix of the file(s) to read/write. + quiesce_after_files: str = None, # If non-zero, quiesce test after this many files have been # read/written. - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_fe_info(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if directory is not None: data["directory"] = directory @@ -9716,9 +8588,10 @@ class LFJsonPost(LFCliBase): data["quiesce_after_files"] = quiesce_after_files if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_fe_info", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_fe_info", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9741,17 +8614,17 @@ class LFJsonPost(LFCliBase): # +Event def post_set_flag(self, - client=None, # Specify the user, if it is not the current user. Requires admin + client: str = None, # Specify the user, if it is not the current user. Requires admin # privileges. - flag=None, # The name of the flag. - val=None, # Either 1 (for on), or 0 (for off). - debug_=False): + flag: str = None, # The name of the flag. [R] + val: str = None, # Either 1 (for on), or 0 (for off). [R,0-1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_flag(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if client is not None: data["client"] = client @@ -9761,9 +8634,10 @@ class LFJsonPost(LFCliBase): data["val"] = val if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_flag", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_flag", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9773,16 +8647,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_gen_cmd ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_gen_cmd(self, - command=None, # The rest of the command line arguments. Unescaped Value - name=None, # The name of the file endpoint we are configuring. - debug_=False): + command: str = None, # The rest of the command line arguments. Unescaped Value [R] + name: str = None, # The name of the file endpoint we are configuring. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_gen_cmd(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if command is not None: data["command"] = command @@ -9790,9 +8664,10 @@ class LFJsonPost(LFCliBase): data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_gen_cmd", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_gen_cmd", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9802,20 +8677,20 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_gps_info ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_gps_info(self, - altitude=None, # Altitude, assumes units are Meters. - ew=None, # East or west (Longitude). - lattitude=None, # The lattitude, as read from a GPS device. - longitude=None, # The longitude, as ready from a GPS device. - ns=None, # North or South (Latitude). - resource=None, # Resource number for the port to be modified. - shelf=None, # Shelf number for the port to be modified, or SELF. - debug_=False): + altitude: str = None, # Altitude, assumes units are Meters. + ew: str = None, # East or west (Longitude). + lattitude: str = None, # The lattitude, as read from a GPS device. + longitude: str = None, # The longitude, as ready from a GPS device. + ns: str = None, # North or South (Latitude). + resource: int = None, # Resource number for the port to be modified. [W] + shelf: int = 1, # Shelf number for the port to be modified, or SELF. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_gps_info(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if altitude is not None: data["altitude"] = altitude @@ -9833,9 +8708,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_gps_info", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_gps_info", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9845,20 +8721,19 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_ifup_script ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_ifup_script(self, - flags=None, # Currently un-defined, use NA - port=None, # WiFi interface name or number. - post_ifup_script=None, # Script name with optional args, will run after interface - # comes up and gets IP. Unescaped - # Value - resource=None, # Resource number. - shelf=None, # Shelf number. - debug_=False): + flags: str = None, # Currently un-defined, use NA + port: str = None, # WiFi interface name or number. [W] + post_ifup_script: str = None, # Script name with optional args, will run after interface + # comes up and gets IP. + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_ifup_script(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if flags is not None: data["flags"] = flags @@ -9872,9 +8747,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_ifup_script", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_ifup_script", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9884,23 +8760,24 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_license ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_license(self, - licenses=None, # License keys all appended into a single line. Unescaped Value - debug_=False): + licenses: str = None, # License keys all appended into a single line. Unescaped Value [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_license(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if licenses is not None: data["licenses"] = licenses if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_license", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_license", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9910,18 +8787,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_mc_endp ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_mc_endp(self, - mcast_dest_port=None, # Multicast destination IP Port, for example: 55000 - mcast_group=None, # Multicast group IP, ie: 224.1.1.2 IPv6 supported as well. - name=None, # The name of the endpoint we are configuring. - rcv_mcast=None, # Should we attempt to receive? Values: Yes or No - ttl=None, # Time to live for the multicast packets generated. - debug_=False): + mcast_dest_port: str = None, # Multicast destination IP Port, for example: 55000 + mcast_group: str = None, # Multicast group IP, ie: 224.1.1.2 IPv6 supported as well. + name: str = None, # The name of the endpoint we are configuring. [R] + rcv_mcast: str = None, # Should we attempt to receive? Values: Yes or No + ttl: str = None, # Time to live for the multicast packets generated. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_mc_endp(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if mcast_dest_port is not None: data["mcast_dest_port"] = mcast_dest_port @@ -9935,9 +8812,10 @@ class LFJsonPost(LFCliBase): data["ttl"] = ttl if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_mc_endp", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_mc_endp", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9947,16 +8825,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_password ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_password(self, - client=None, # Specify the client. If left blank, will use current client. - new_password=None, # New password, or 'NA' for blank password. - old_password=None, # Old password, or 'NA' for blank password. - debug_=False): + client: str = None, # Specify the client. If left blank, will use current client. + new_password: str = None, # New password, or 'NA' for blank password. [W] + old_password: str = None, # Old password, or 'NA' for blank password. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_password(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if client is not None: data["client"] = client @@ -9966,9 +8844,10 @@ class LFJsonPost(LFCliBase): data["old_password"] = old_password if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_password", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_password", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -9977,23 +8856,32 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_poll_mode ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + class SetPollModeMode(Enum): + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Example Usage: + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + polling = "polling" # + push = "push" # + def post_set_poll_mode(self, - mode=None, # 'polling' or 'push'. - debug_=False): + mode: str = None, # 'polling' or 'push'. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_poll_mode(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if mode is not None: data["mode"] = mode if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_poll_mode", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_poll_mode", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -10190,65 +9078,68 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_set_port(self, - alias=None, # A user-defined name for this interface. Can be BLANK or NA. - br_aging_time=None, # MAC aging time, in seconds, 32-bit number (or peer IP for GRE). - br_forwarding_delay=None, # How long to wait until the bridge will start forwarding packets. - br_hello_time=None, # How often does the bridge send out STP hello packets. - br_max_age=None, # How long until STP considers a non-responsive bridge dead. - br_port_cost=None, # STP Port cost for a port (this applies only to NON-BRIDGE + alias: str = None, # A user-defined name for this interface. Can be BLANK or NA. + br_aging_time: str = None, # MAC aging time, in seconds, 32-bit number (or peer IP for + # GRE). + br_forwarding_delay: str = None, # How long to wait until the bridge will start forwarding + # packets. + br_hello_time: str = None, # How often does the bridge send out STP hello packets. + br_max_age: str = None, # How long until STP considers a non-responsive bridge dead. + br_port_cost: str = None, # STP Port cost for a port (this applies only to NON-BRIDGE # interfaces). - br_port_priority=None, # STP Port priority for a port (this applies only to NON-BRIDGE + br_port_priority: str = None, # STP Port priority for a port (this applies only to NON-BRIDGE # interfaces). - br_priority=None, # Bridge priority, 16-bit number. - bypass_wdt=None, # Watch Dog Timer (in seconds) for this port. Zero (0) to disable. - cmd_flags=None, # Command Flags: See above, or NA. - cpu_mask=None, # CPU Mask for CPUs that should service this interface. Zero is - # don't set (let OS make the decision). This value will be applied - # to the proper /proc/irq/[irq-num]/smp_affinity file by the - # pin_irq.pl script. - current_flags=None, # See above, or NA. - current_flags_msk=None, # This sets 'interest' for flags 'Enable RADIUS service' and higher. - # See above, or NA. - dhcp_client_id=None, # Optional string of up to 63 bytes in length to be passed to the - # dhclient process. See above. - dhcp_hostname=None, # Optional string of up to 63 bytes in length to be passed to the - # dhclient process. Option 12, see above. - dhcp_vendor_id=None, # Optional string of up to 63 bytes in length to be passed to the - # dhclient process. See above. - dns_servers=None, # DNS servers for use by traffic on this port, comma-separated list, - # BLANK means zero-length string. - flags2=None, # Bridge & other flags, see above. - gateway=None, # IP address of the gateway device - used for IP routing, or NA. - interest=None, # Which things are we really interested in setting. Can over-ride - # defaults based on the other arguments. - ip_addr=None, # IP address for the port, or NA. - ipsec_concentrator=None, # IP Address of IPSec concentrator. - ipsec_local_id=None, # Local Identifier for this IPSec tunnel. - ipsec_passwd=None, # Password for IPSec, for pubkey, use: pubkey:[pem-file-name], for - # instance: pubkey:station.pem - ipsec_remote_id=None, # Remote Identifier for this IPSec tunnel. - ipv6_addr_global=None, # Global scoped IPv6 address. - ipv6_addr_link=None, # Link scoped IPv6 address. - ipv6_dflt_gw=None, # IPv6 default gateway. - mac=None, # MAC address to set this port to, or leave blank to not set it, or - # NA. - mtu=None, # Maximum Transmit Unit (MTU) for this interface. Can be blank or - # NA. - netmask=None, # Netmask which this port should use, or NA. - port=None, # Port number for the port to be modified. - report_timer=None, # How often, in milliseconds, should we poll stats on this + br_priority: str = None, # Bridge priority, 16-bit number. + bypass_wdt: str = None, # Watch Dog Timer (in seconds) for this port. Zero (0) to + # disable. + cmd_flags: str = None, # Command Flags: See above, or NA. + cpu_mask: str = None, # CPU Mask for CPUs that should service this interface. Zero is + # don't set (let OS make the decision). This value will be + # applied to the proper /proc/irq/[irq-num]/smp_affinity file by + # the pin_irq.pl script. + current_flags: str = None, # See above, or NA. + current_flags_msk: str = None, # This sets 'interest' for flags 'Enable RADIUS service' and + # higher. See above, or NA. + dhcp_client_id: str = None, # Optional string of up to 63 bytes in length to be passed to + # the dhclient process. See above. + dhcp_hostname: str = None, # Optional string of up to 63 bytes in length to be passed to + # the dhclient process. Option 12, see above. + dhcp_vendor_id: str = None, # Optional string of up to 63 bytes in length to be passed to + # the dhclient process. See above. + dns_servers: str = None, # DNS servers for use by traffic on this port, comma-separated + # list, BLANK means zero-length string. + flags2: str = None, # Bridge & other flags, see above. + gateway: str = None, # IP address of the gateway device - used for IP routing, or NA. + interest: str = None, # Which things are we really interested in setting. Can + # over-ride defaults based on the other arguments. + ip_addr: str = None, # IP address for the port, or NA. + ipsec_concentrator: str = None, # IP Address of IPSec concentrator. + ipsec_local_id: str = None, # Local Identifier for this IPSec tunnel. + ipsec_passwd: str = None, # Password for IPSec, for pubkey, use: pubkey:[pem-file-name], + # for instance: pubkey:station.pem + ipsec_remote_id: str = None, # Remote Identifier for this IPSec tunnel. + ipv6_addr_global: str = None, # Global scoped IPv6 address. + ipv6_addr_link: str = None, # Link scoped IPv6 address. + ipv6_dflt_gw: str = None, # IPv6 default gateway. + mac: str = None, # MAC address to set this port to, or leave blank to not set it, + # or NA. + mtu: str = None, # Maximum Transmit Unit (MTU) for this interface. Can be blank + # or NA. + netmask: str = None, # Netmask which this port should use, or NA. + port: str = None, # Port number for the port to be modified. [W] + report_timer: int = None, # How often, in milliseconds, should we poll stats on this # interface? - resource=None, # Resource number for the port to be modified. - shelf=None, # Shelf number for the port to be modified. - sta_br_id=None, # WiFi STAtion bridge ID. Zero means none. - tx_queue_len=None, # Transmit Queue Length for this interface. Can be blank or NA. - debug_=False): + resource: int = None, # Resource number for the port to be modified. [W] + shelf: int = 1, # Shelf number for the port to be modified. [R][D:1] + sta_br_id: str = None, # WiFi STAtion bridge ID. Zero means none. + tx_queue_len: str = None, # Transmit Queue Length for this interface. Can be blank or NA. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_port(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if alias is not None: data["alias"] = alias @@ -10326,9 +9217,10 @@ class LFJsonPost(LFCliBase): data["tx_queue_len"] = tx_queue_len if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_port", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_port", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -10338,19 +9230,19 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_port_alias ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_port_alias(self, - alias=None, # New alias to assign to this virtual interface. - port=None, # Physical Port identifier that owns the virtual interface. - resource=None, # Resource number for the port to be modified. - shelf=None, # Shelf number for the port to be modified. - vport=None, # Virtual port identifier. MAC for MAC-VLANs, VLAN-ID for 802.1Q + alias: str = None, # New alias to assign to this virtual interface. [W] + port: str = None, # Physical Port identifier that owns the virtual interface. [R] + resource: int = None, # Resource number for the port to be modified. [W] + shelf: int = 1, # Shelf number for the port to be modified. [R][D:1] + vport: str = None, # Virtual port identifier. MAC for MAC-VLANs, VLAN-ID for 802.1Q # vlans. - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_port_alias(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if alias is not None: data["alias"] = alias @@ -10364,9 +9256,10 @@ class LFJsonPost(LFCliBase): data["vport"] = vport if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_port_alias", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_port_alias", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -10376,17 +9269,17 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_ppp_link_state ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_ppp_link_state(self, - link=None, # Unit Number of the PPP Link, or 'all'. - ppp_state=None, # One of: RUNNING, STOPPED, or DELETED. - resource=None, # Number of the Resource, or 'all'. - shelf=None, # Name of the Shelf, or 'all'. - debug_=False): + link: str = None, # Unit Number of the PPP Link, or 'all'. [W] + ppp_state: str = None, # One of: RUNNING, STOPPED, or DELETED. [R] + resource: int = None, # Number of the Resource, or 'all'. [W] + shelf: int = 1, # Name of the Shelf, or 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_ppp_link_state(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if link is not None: data["link"] = link @@ -10398,9 +9291,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_ppp_link_state", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_ppp_link_state", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -10417,29 +9311,29 @@ class LFJsonPost(LFCliBase): skip_load_db_on_start = 1 # Should we skip loading the DB on start? def post_set_resource(self, - device_profiles=None, # List of profiles, see above - max_helper_count=None, # Maximum number of helper traffic generation processes. 0 means - # CPU-core-count (AUTO). - max_staged_bringup=None, # Maximum amount of interfaces attempting to come up at once. - # Default is 50 - max_station_bringup=None, # Maximum amount of stations to bring up per radio per tick. + device_profiles: str = None, # List of profiles, see above + max_helper_count: str = None, # Maximum number of helper traffic generation processes. 0 + # means CPU-core-count (AUTO). + max_staged_bringup: str = None, # Maximum amount of interfaces attempting to come up at + # once. Default is 50 + max_station_bringup: str = None, # Maximum amount of stations to bring up per radio per tick. # Default is 12. - max_trying_ifup=None, # Maximum amount of interfaces running the network config 'ifup' - # logic. Default is 15 - resource=None, # Number of the Resource, or all. - resource_flags=None, # System wide flags, often requires a reboot for changes to take - # effect. - resource_flags_mask=None, # What flags to change. If unset, default is all. - shelf=None, # Name of the Shelf, or all. - top_left_x=None, # X Location for Chamber View. - top_left_y=None, # X Location for Chamber View. - debug_=False): + max_trying_ifup: str = None, # Maximum amount of interfaces running the network config + # 'ifup' logic. Default is 15 + resource: int = None, # Number of the Resource, or all. [W] + resource_flags: str = None, # System wide flags, often requires a reboot for changes to + # take effect. + resource_flags_mask: str = None, # What flags to change. If unset, default is all. + shelf: int = 1, # Name of the Shelf, or all. [R][D:1] + top_left_x: str = None, # X Location for Chamber View. + top_left_y: str = None, # X Location for Chamber View. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_resource(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if device_profiles is not None: data["device_profiles"] = device_profiles @@ -10465,9 +9359,10 @@ class LFJsonPost(LFCliBase): data["top_left_y"] = top_left_y if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_resource", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_resource", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -10498,26 +9393,27 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_set_rfgen(self, - bb_gain=None, # RX Gain, 0 - 62 in 2dB steps - freq_khz=None, # Center frequency in Khz - gain=None, # Main TX/RX Amp, 0 or 14 (dB), default is 14 - p_id=None, # RF Generator ID, not used at this time, enter 'NA' or 0. - if_gain=None, # Fine-tune TX/RX Gain, 0 - 40 dB - pulse_count=None, # Number of pulses (0-255) - pulse_interval_us=None, # Time between pulses, in micro-seconds. - pulse_width_us=None, # Requested pulse width, units are in micro-seconds. - resource=None, # Resource number. - rfgen_flags=None, # RF Generator flags, see above. - rfgen_flags_mask=None, # Mask of what flags to set, see above. - shelf=None, # Shelf number, usually 1. - sweep_time_ms=None, # Time interval between pulse groups in miliseconds - debug_=False): + bb_gain: str = None, # RX Gain, 0 - 62 in 2dB steps + freq_khz: str = None, # Center frequency in Khz + gain: str = None, # Main TX/RX Amp, 0 or 14 (dB), default is 14 + p_id: str = None, # RF Generator ID, not used at this time, enter 'NA' or 0. + # [D:NA] + if_gain: str = None, # Fine-tune TX/RX Gain, 0 - 40 dB + pulse_count: str = None, # Number of pulses (0-255) + pulse_interval_us: str = None, # Time between pulses, in micro-seconds. + pulse_width_us: str = None, # Requested pulse width, units are in micro-seconds. + resource: int = None, # Resource number. [W] + rfgen_flags: str = None, # RF Generator flags, see above. + rfgen_flags_mask: str = None, # Mask of what flags to set, see above. + shelf: int = 1, # Shelf number, usually 1. [R][D:1] + sweep_time_ms: str = None, # Time interval between pulse groups in miliseconds + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_rfgen(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if bb_gain is not None: data["bb_gain"] = bb_gain @@ -10547,9 +9443,10 @@ class LFJsonPost(LFCliBase): data["sweep_time_ms"] = sweep_time_ms if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_rfgen", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_rfgen", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -10607,20 +9504,20 @@ class LFJsonPost(LFCliBase): ScriptWL = "ScriptWL" # For iterating through WanLink settings def post_set_script(self, - endp=None, # Endpoint, Test Group or Attenuator name or ID. - flags=None, # See above for description of the defined flags. - group_action=None, # How to handle group script operations: ALL, Sequential - loop_count=None, # How many times to loop before stopping (0 is infinite). - name=None, # Script name. - private=None, # Private encoding for the particular script. - p_type=None, # One of: NONE, Script2544, ScriptHunt, ScriptWL, ScriptAtten - debug_=False): + endp: str = None, # Endpoint, Test Group or Attenuator name or ID. [R] + flags: str = None, # See above for description of the defined flags. + group_action: str = None, # How to handle group script operations: ALL, Sequential + loop_count: str = None, # How many times to loop before stopping (0 is infinite). + name: str = None, # Script name. [W] + private: str = None, # Private encoding for the particular script. + p_type: str = None, # One of: NONE, Script2544, ScriptHunt, ScriptWL, ScriptAtten + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_script(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endp is not None: data["endp"] = endp @@ -10638,9 +9535,10 @@ class LFJsonPost(LFCliBase): data["type"] = p_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_script", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_script", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -10650,17 +9548,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_sec_ip ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_sec_ip(self, - ip_list=None, # IP1/prefix,IP2/prefix,...IPZ/prefix. - port=None, # Name of network device (Port) to which these IPs will be added. - resource=None, # Resource number. - shelf=None, # Shelf number. - debug_=False): + ip_list: str = None, # IP1/prefix,IP2/prefix,...IPZ/prefix. [W] + port: str = None, # Name of network device (Port) to which these IPs will be added. + # [R] + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_sec_ip(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if ip_list is not None: data["ip_list"] = ip_list @@ -10672,9 +9571,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_sec_ip", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_sec_ip", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -10684,35 +9584,38 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_voip_info ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_voip_info(self, - codec=None, # Codec to use for the voice stream, supported values: G711U, - # G711A, SPEEX, g726-16, g726-24, g726-32, g726-40, g729a. - first_call_delay=None, # How long to wait before making first call, in seconds. - jitter_buffer_sz=None, # The size of the jitter buffer in packets. Default value is 8. - local_sip_port=None, # Local SIP UDP port. Default is min-rtp-port + 2. - loop_call_count=None, # How many calls to make, zero means infinite. - loop_wavefile_count=None, # How many times to play the wave file, zero means infinite. - max_call_duration=None, # How long should the call be, in seconds. - max_inter_call_gap=None, # Maximum time to wait between calls, in seconds. - messaging_protocol=None, # Messaging protocol, supported values: SIP. - min_call_duration=None, # How long should the call be, in seconds. - min_inter_call_gap=None, # Minimum time to wait between calls, in seconds. - name=None, # The name of the endpoint we are configuring. - pesq_server_ip=None, # LANforge PESQ server IP address. - pesq_server_passwd=None, # LANforge PESQ server password. Default is to use no + codec: str = None, # Codec to use for the voice stream, supported values: + # G711U, G711A, SPEEX, g726-16, g726-24, g726-32, g726-40, + # g729a. + first_call_delay: str = None, # How long to wait before making first call, in seconds. + jitter_buffer_sz: str = None, # The size of the jitter buffer in packets. Default value + # is 8. + local_sip_port: str = None, # Local SIP UDP port. Default is min-rtp-port + 2. + loop_call_count: str = None, # How many calls to make, zero means infinite. + loop_wavefile_count: str = None, # How many times to play the wave file, zero means + # infinite. + max_call_duration: str = None, # How long should the call be, in seconds. + max_inter_call_gap: str = None, # Maximum time to wait between calls, in seconds. + messaging_protocol: str = None, # Messaging protocol, supported values: SIP. + min_call_duration: str = None, # How long should the call be, in seconds. + min_inter_call_gap: str = None, # Minimum time to wait between calls, in seconds. + name: str = None, # The name of the endpoint we are configuring. [R] + pesq_server_ip: str = None, # LANforge PESQ server IP address. + pesq_server_passwd: str = None, # LANforge PESQ server password. Default is to use no # authentication (blank entry). - pesq_server_port=None, # LANforge PESQ server port, default is 3998. - reg_expire_timer=None, # SIP Registration expire timer, in seconds. - ringing_timer=None, # How long (milliseconds) to wait in the ringing state before - # flagging call as no-answer. - sound_dev=None, # Which sound device should we play sound to. (see + pesq_server_port: str = None, # LANforge PESQ server port, default is 3998. + reg_expire_timer: str = None, # SIP Registration expire timer, in seconds. + ringing_timer: str = None, # How long (milliseconds) to wait in the ringing state + # before flagging call as no-answer. + sound_dev: str = None, # Which sound device should we play sound to. (see # set_endp_flags). - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_voip_info(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if codec is not None: data["codec"] = codec @@ -10752,9 +9655,10 @@ class LFJsonPost(LFCliBase): data["sound_dev"] = sound_dev if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_voip_info", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_voip_info", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -10764,23 +9668,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_vrcx_cost ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_vrcx_cost(self, - interface_cost=None, # If using OSPF, this sets the cost for this link (1-65535). - local_dev=None, # Name of port A for the local redirect device pair. - local_dev_b=None, # Name of port B for the local redirect device pair. - remote_dev=None, # Name of port B for the remote redirect device pair. - remote_dev_b=None, # Name of port B for the remote redirect device pair. - resource=None, # Resource number. - shelf=None, # Shelf name/id. - vr_name=None, # Virtual Router this endpoint belongs to. Use 'FREE_LIST' to add - # a stand-alone endpoint. - wanlink=None, # The name of the WanLink that connects the two B ports. - debug_=False): + interface_cost: str = None, # If using OSPF, this sets the cost for this link (1-65535). + local_dev: str = None, # Name of port A for the local redirect device pair. + local_dev_b: str = None, # Name of port B for the local redirect device pair. + remote_dev: str = None, # Name of port B for the remote redirect device pair. + remote_dev_b: str = None, # Name of port B for the remote redirect device pair. + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf name/id. [R][D:1] + vr_name: str = None, # Virtual Router this endpoint belongs to. Use 'FREE_LIST' to + # add a stand-alone endpoint. [W][D:FREE_LIST] + wanlink: str = None, # The name of the WanLink that connects the two B ports. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_vrcx_cost(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if interface_cost is not None: data["interface_cost"] = interface_cost @@ -10802,9 +9706,10 @@ class LFJsonPost(LFCliBase): data["wanlink"] = wanlink if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_vrcx_cost", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_vrcx_cost", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -10814,39 +9719,41 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_wanlink_info ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_wanlink_info(self, - drop_freq=None, # How often, out of 1,000,000 packets, should we + drop_freq: str = None, # How often, out of 1,000,000 packets, should we # purposefully drop a packet. - dup_freq=None, # How often, out of 1,000,000 packets, should we + dup_freq: str = None, # How often, out of 1,000,000 packets, should we # purposefully duplicate a packet. - extra_buffer=None, # The extra amount of bytes to buffer before dropping pkts, - # in units of 1024. Use -1 for AUTO. - jitter_freq=None, # How often, out of 1,000,000 packets, should we apply + extra_buffer: str = None, # The extra amount of bytes to buffer before dropping + # pkts, in units of 1024. Use -1 for AUTO. + jitter_freq: str = None, # How often, out of 1,000,000 packets, should we apply # jitter. - latency=None, # The base latency added to all packets, in milliseconds - # (or add 'us' suffix for microseconds - max_drop_amt=None, # Maximum amount of packets to drop in a row. Default is 1. - max_jitter=None, # The maximum jitter, in milliseconds (or ad 'us' suffix - # for microseconds) - max_lateness=None, # Maximum amount of un-intentional delay before pkt is + latency: str = None, # The base latency added to all packets, in + # milliseconds (or add 'us' suffix for microseconds + max_drop_amt: str = None, # Maximum amount of packets to drop in a row. Default + # is 1. + max_jitter: str = None, # The maximum jitter, in milliseconds (or ad 'us' + # suffix for microseconds) + max_lateness: str = None, # Maximum amount of un-intentional delay before pkt is # dropped. Default is AUTO - max_reorder_amt=None, # Maximum amount of packets by which to reorder, Default is - # 10. - min_drop_amt=None, # Minimum amount of packets to drop in a row. Default is 1. - min_reorder_amt=None, # Minimum amount of packets by which to reorder, Default is - # 1. - name=None, # The name of the endpoint we are configuring. - playback_capture_file=None, # Name of the WAN capture file to play back. - reorder_freq=None, # How often, out of 1,000,000 packets, should we make a + max_reorder_amt: str = None, # Maximum amount of packets by which to reorder, + # Default is 10. + min_drop_amt: str = None, # Minimum amount of packets to drop in a row. Default + # is 1. + min_reorder_amt: str = None, # Minimum amount of packets by which to reorder, + # Default is 1. + name: str = None, # The name of the endpoint we are configuring. [R] + playback_capture_file: str = None, # Name of the WAN capture file to play back. + reorder_freq: str = None, # How often, out of 1,000,000 packets, should we make a # packet out of order. - speed=None, # The maximum speed of traffic this endpoint will accept - # (bps). - debug_=False): + speed: str = None, # The maximum speed of traffic this endpoint will + # accept (bps). + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_wanlink_info(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if drop_freq is not None: data["drop_freq"] = drop_freq @@ -10880,9 +9787,10 @@ class LFJsonPost(LFCliBase): data["speed"] = speed if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_wanlink_info", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_wanlink_info", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -10891,18 +9799,26 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_wanlink_pcap ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + class SetWanlinkPcapCapture(Enum): + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Example Usage: + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + OFF = "OFF" # stop capturing + ON = "ON" # start capturing + def post_set_wanlink_pcap(self, - capture=None, # Should we capture or not? ON or OFF. - directory=None, # The directory name in which packet capture files will be + capture: str = None, # Should we capture or not? ON or OFF. [R] + directory: str = None, # The directory name in which packet capture files will be # written. - name=None, # The name of the endpoint we are configuring. - debug_=False): + name: str = None, # The name of the endpoint we are configuring. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_wanlink_pcap(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if capture is not None: data["capture"] = capture @@ -10912,9 +9828,10 @@ class LFJsonPost(LFCliBase): data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_wanlink_pcap", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_wanlink_pcap", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -10949,24 +9866,24 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_set_wanpath_corruption(self, - byte=None, # The byte to use for OVERWRITE_FIXED (or NA). - flags=None, # The flags for this corruption. - index=None, # The corruption to modify (0-5). - max_offset=None, # The maximum offset from start of Ethernet packet for the - # byte to be modified. - min_offset=None, # The minimum offset from start of Ethernet packet for the - # byte to be modified. - name=None, # WanLink name - path=None, # WanPath name - rate=None, # Specifies how often, per million, this corruption should - # be applied. - debug_=False): + byte: str = None, # The byte to use for OVERWRITE_FIXED (or NA). + flags: str = None, # The flags for this corruption. + index: str = None, # The corruption to modify (0-5). [R,0-5] + max_offset: str = None, # The maximum offset from start of Ethernet packet for + # the byte to be modified. + min_offset: str = None, # The minimum offset from start of Ethernet packet for + # the byte to be modified. + name: str = None, # WanLink name [R] + path: str = None, # WanPath name [R] + rate: str = None, # Specifies how often, per million, this corruption + # should be applied. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_wanpath_corruption(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if byte is not None: data["byte"] = byte @@ -10986,9 +9903,10 @@ class LFJsonPost(LFCliBase): data["rate"] = rate if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_wanpath_corruption", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_wanpath_corruption", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -10998,23 +9916,25 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_wanpath_filter ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_wanpath_filter(self, - defer_flush=None, # Enter 'YES' if you do NOT want this flushed to the remote. - dst_filter=None, # The destination MAC or IP/Mask, 'NA' for PCAP. - filter_type=None, # The filter type, one of: MAC, IP, PCAP. - passive=None, # Enter 'YES' if you do NOT want to use this filter currently. - reverse=None, # If you want the logic reversed, use 'ON', otherwise set to - # 'OFF' - src_filter=None, # The source MAC or IP/Mask. For PCAP, this is the only + defer_flush: str = None, # Enter 'YES' if you do NOT want this flushed to the + # remote. + dst_filter: str = None, # The destination MAC or IP/Mask, 'NA' for PCAP. + filter_type: str = None, # The filter type, one of: MAC, IP, PCAP. + passive: str = None, # Enter 'YES' if you do NOT want to use this filter + # currently. + reverse: str = None, # If you want the logic reversed, use 'ON', otherwise set + # to 'OFF' + src_filter: str = None, # The source MAC or IP/Mask. For PCAP, this is the only # filter. - wl_name=None, # The name of the WanLink endpoint we are configuring. - wp_name=None, # The name of the WanPath we are configuring. - debug_=False): + wl_name: str = None, # The name of the WanLink endpoint we are configuring. [R] + wp_name: str = None, # The name of the WanPath we are configuring. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_wanpath_filter(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if defer_flush is not None: data["defer_flush"] = defer_flush @@ -11034,9 +9954,10 @@ class LFJsonPost(LFCliBase): data["wp_name"] = wp_name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_wanpath_filter", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_wanpath_filter", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -11055,16 +9976,16 @@ class LFJsonPost(LFCliBase): STOPPED = "STOPPED" # then it will not be running at any time. def post_set_wanpath_running(self, - running=None, # The state, one of: AS_PARENT, RUNNING, STOPPED. - wl_name=None, # The name of the WanLink endpoint we are configuring. - wp_name=None, # The name of the WanPath we are configuring. - debug_=False): + running: str = None, # The state, one of: AS_PARENT, RUNNING, STOPPED. [R] + wl_name: str = None, # The name of the WanLink endpoint we are configuring. [R] + wp_name: str = None, # The name of the WanPath we are configuring. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_wanpath_running(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if running is not None: data["running"] = running @@ -11074,9 +9995,10 @@ class LFJsonPost(LFCliBase): data["wp_name"] = wp_name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_wanpath_running", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_wanpath_running", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -11119,31 +10041,31 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_set_wifi_corruptions(self, - corrupt_flags=None, # Specify packet types to corrupt (see flags above). - corrupt_per_mil=None, # Per-million: Station to randomly corrupt selected + corrupt_flags: str = None, # Specify packet types to corrupt (see flags above). + corrupt_per_mil: str = None, # Per-million: Station to randomly corrupt selected # message types by this amount. - delay_flags=None, # Specify packet types to delay (see flags above). - delay_max=None, # miliseconds: Station to randomly delay processing + delay_flags: str = None, # Specify packet types to delay (see flags above). + delay_max: str = None, # miliseconds: Station to randomly delay processing # received messages, max time - delay_min=None, # miliseconds: Station to randomly delay processing + delay_min: str = None, # miliseconds: Station to randomly delay processing # received messages, min time - dup_flags=None, # Specify packet types to duplicate (see flags above). - dup_per_65535=None, # Percentage, represented as x per 65535 of packets we + dup_flags: str = None, # Specify packet types to duplicate (see flags above). + dup_per_65535: str = None, # Percentage, represented as x per 65535 of packets we # should duplicate. - ignore_flags=None, # Specify packet types to ignore (see flags above). - ignore_per_mil=None, # Per-million: Station to randomly ignore selected message - # types by this amount. - port=None, # WiFi interface name or number. - req_flush=None, # Set to 1 if you wish to flush changes to kernel now. - resource=None, # Resource number. - shelf=None, # Shelf number. - debug_=False): + ignore_flags: str = None, # Specify packet types to ignore (see flags above). + ignore_per_mil: str = None, # Per-million: Station to randomly ignore selected + # message types by this amount. + port: str = None, # WiFi interface name or number. [W] + req_flush: str = None, # Set to 1 if you wish to flush changes to kernel now. + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_wifi_corruptions(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if corrupt_flags is not None: data["corrupt_flags"] = corrupt_flags @@ -11173,9 +10095,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_wifi_corruptions", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_wifi_corruptions", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -11185,19 +10108,19 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_wifi_custom ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_wifi_custom(self, - port=None, # WiFi interface name or number. - resource=None, # Resource number. - shelf=None, # Shelf number. - text=None, # [BLANK] will erase all, any other text will be appended to - # existing text. Unescaped Value - p_type=None, # NA for now, may specify specific locations later. - debug_=False): + port: str = None, # WiFi interface name or number. [W] + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + text: str = None, # [BLANK] will erase all, any other text will be appended to + # existing text. + p_type: str = None, # NA for now, may specify specific locations later. [D:NA] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_wifi_custom(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if port is not None: data["port"] = port @@ -11211,9 +10134,10 @@ class LFJsonPost(LFCliBase): data["type"] = p_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_wifi_custom", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_wifi_custom", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -11223,55 +10147,55 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_wifi_extra ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_wifi_extra(self, - anonymous_identity=None, # Anonymous identity string for EAP. - anqp_3gpp_cell_net=None, # 802.11u 3GCPP Cellular Network Info, VAP only. - ca_cert=None, # CA-CERT file name. - client_cert=None, # 802.11u Client cert file: /etc/wpa_supplicant/ca.pem - domain=None, # 802.11u domain: mytelco.com - eap=None, # EAP method: MD5, MSCHAPV2, OTP, GTC, TLS, PEAP, TTLS. - group=None, # Group cyphers: CCMP, TKIP, WEP104, WEP40, or combination. - hessid=None, # 802.11u HESSID (MAC address format) (or peer for WDS + anonymous_identity: str = None, # Anonymous identity string for EAP. + anqp_3gpp_cell_net: str = None, # 802.11u 3GCPP Cellular Network Info, VAP only. + ca_cert: str = None, # CA-CERT file name. + client_cert: str = None, # 802.11u Client cert file: /etc/wpa_supplicant/ca.pem + domain: str = None, # 802.11u domain: mytelco.com + eap: str = None, # EAP method: MD5, MSCHAPV2, OTP, GTC, TLS, PEAP, TTLS. + group: str = None, # Group cyphers: CCMP, TKIP, WEP104, WEP40, or combination. + hessid: str = None, # 802.11u HESSID (MAC address format) (or peer for WDS # stations). - identity=None, # EAP Identity string. - imsi=None, # 802.11u IMSI: 310026-000000000 - ipaddr_type_avail=None, # 802.11u network type available, integer, VAP only. - key=None, # WEP key0. This should be entered in ascii-hex. Use this only - # for WEP. - key_mgmt=None, # Key management: WPA-PSK, WPA-EAP, IEEE8021X, NONE, + identity: str = None, # EAP Identity string. + imsi: str = None, # 802.11u IMSI: 310026-000000000 + ipaddr_type_avail: str = None, # 802.11u network type available, integer, VAP only. + key: str = None, # WEP key0. This should be entered in ascii-hex. Use this + # only for WEP. + key_mgmt: str = None, # Key management: WPA-PSK, WPA-EAP, IEEE8021X, NONE, # WPA-PSK-SHA256, WPA-EAP-SHA256 or combo. - milenage=None, # 802.11u milenage: + milenage: str = None, # 802.11u milenage: # 90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82 - network_auth_type=None, # 802.11u network authentication type, VAP only. - network_type=None, # 802.11u network type, integer, VAP only. - pac_file=None, # EAP-FAST PAC-File name. (For AP, this field is the RADIUS + network_auth_type: str = None, # 802.11u network authentication type, VAP only. + network_type: str = None, # 802.11u network type, integer, VAP only. + pac_file: str = None, # EAP-FAST PAC-File name. (For AP, this field is the RADIUS # secret password) - pairwise=None, # Pairwise ciphers: CCMP, TKIP, NONE, or combination. - password=None, # EAP Password string. - phase1=None, # Outer-authentication, ie TLS tunnel parameters. - phase2=None, # Inner authentication with TLS tunnel. - pin=None, # EAP-SIM pin string. (For AP, this field is HS20 Operating + pairwise: str = None, # Pairwise ciphers: CCMP, TKIP, NONE, or combination. + password: str = None, # EAP Password string. + phase1: str = None, # Outer-authentication, ie TLS tunnel parameters. + phase2: str = None, # Inner authentication with TLS tunnel. + pin: str = None, # EAP-SIM pin string. (For AP, this field is HS20 Operating # Class) - pk_passwd=None, # EAP private key password. (For AP, this field is HS20 + pk_passwd: str = None, # EAP private key password. (For AP, this field is HS20 # connection capability) - port=None, # WiFi interface name or number. - private_key=None, # EAP private key certificate file name. (For AP, this field - # is HS20 WAN Metrics) - psk=None, # WPA(2) pre-shared key. If unsure, use this field for any + port: str = None, # WiFi interface name or number. [W] + private_key: str = None, # EAP private key certificate file name. (For AP, this + # field is HS20 WAN Metrics) + psk: str = None, # WPA(2) pre-shared key. If unsure, use this field for any # password entry. Prepend with 0x for ascii-hex # representation. - realm=None, # 802.11u realm: mytelco.com - resource=None, # Resource number. - roaming_consortium=None, # 802.11u roaming consortium: 223344 (15 characters max) - shelf=None, # Shelf number. - venue_group=None, # 802.11u Venue Group, integer. VAP only. - venue_type=None, # 802.11u Venue Type, integer. VAP only. - debug_=False): + realm: str = None, # 802.11u realm: mytelco.com + resource: int = None, # Resource number. [W] + roaming_consortium: str = None, # 802.11u roaming consortium: 223344 (15 characters max) + shelf: int = 1, # Shelf number. [R][D:1] + venue_group: str = None, # 802.11u Venue Group, integer. VAP only. + venue_type: str = None, # 802.11u Venue Type, integer. VAP only. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_wifi_extra(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if anonymous_identity is not None: data["anonymous_identity"] = anonymous_identity @@ -11339,9 +10263,10 @@ class LFJsonPost(LFCliBase): data["venue_type"] = venue_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_wifi_extra", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_wifi_extra", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -11351,34 +10276,34 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_wifi_extra2 ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_wifi_extra2(self, - corrupt_gtk_rekey_mic=None, # Per-million: AP corrupts GTK Rekey MIC. - freq_24=None, # Frequency list for 2.4Ghz band, see above. - freq_5=None, # Frequency list for 5Ghz band, see above. - ignore_assoc=None, # Per-million: AP ignore assoc request percentage. - ignore_auth=None, # Per-million: AP ignore auth request percentage. - ignore_probe=None, # Per-million: AP ignore probe percentage. - ignore_reassoc=None, # Per-million: AP ignore re-assoc request percentage. - ocsp=None, # OCSP settings: 0=disabled, 1=try, but to not require + corrupt_gtk_rekey_mic: str = None, # Per-million: AP corrupts GTK Rekey MIC. + freq_24: str = None, # Frequency list for 2.4Ghz band, see above. + freq_5: str = None, # Frequency list for 5Ghz band, see above. + ignore_assoc: str = None, # Per-million: AP ignore assoc request percentage. + ignore_auth: str = None, # Per-million: AP ignore auth request percentage. + ignore_probe: str = None, # Per-million: AP ignore probe percentage. + ignore_reassoc: str = None, # Per-million: AP ignore re-assoc request percentage. + ocsp: str = None, # OCSP settings: 0=disabled, 1=try, but to not require # response, 2=require valid OCSP stapling response. - port=None, # WiFi interface name or number. - post_ifup_script=None, # Script name with optional args, will run after interface - # comes up and gets IP. - radius_ip=None, # RADIUS server IP Address (AP Only) - radius_port=None, # RADIUS server IP Port (AP Only) - req_flush=None, # Set to 1 if you wish to flush changes to kernel now. - resource=None, # Resource number. - sae_pwe=None, # Set SAE-PWE, 0 == hunting-and-pecking, 1 == + port: str = None, # WiFi interface name or number. [W] + post_ifup_script: str = None, # Script name with optional args, will run after + # interface comes up and gets IP. + radius_ip: str = None, # RADIUS server IP Address (AP Only) + radius_port: str = None, # RADIUS server IP Port (AP Only) + req_flush: str = None, # Set to 1 if you wish to flush changes to kernel now. + resource: int = None, # Resource number. [W] + sae_pwe: str = None, # Set SAE-PWE, 0 == hunting-and-pecking, 1 == # hash-to-element, 2 allow both. - shelf=None, # Shelf number. - venue_id=None, # Venue-ID for this wifi device. VAP in same venue will + shelf: int = 1, # Shelf number. [R][D:1] + venue_id: str = None, # Venue-ID for this wifi device. VAP in same venue will # share neigh reports as appropriate. - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_wifi_extra2(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if corrupt_gtk_rekey_mic is not None: data["corrupt_gtk_rekey_mic"] = corrupt_gtk_rekey_mic @@ -11416,9 +10341,10 @@ class LFJsonPost(LFCliBase): data["venue_id"] = venue_id if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_wifi_extra2", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_wifi_extra2", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -11478,57 +10404,58 @@ class LFJsonPost(LFCliBase): g = 3 # 802.11g def post_set_wifi_radio(self, - active_peer_count=None, # Number of locally-cached peer objects for this radio. - ampdu_factor=None, # ax200/ax210 only, currently. Requires module reload. OS + active_peer_count: str = None, # Number of locally-cached peer objects for this radio. + ampdu_factor: str = None, # ax200/ax210 only, currently. Requires module reload. OS # Default: 0xFF - antenna=None, # Antenna configuration: 0 Diversity/All, 1 Fixed-A (1x1), 4 - # AB (2x2), 7 ABC (3x3), 8 ABCD (4x4), 9 8x8 - channel=None, # Channel number for this radio device. Frequency takes + antenna: str = None, # Antenna configuration: 0 Diversity/All, 1 Fixed-A (1x1), + # 4 AB (2x2), 7 ABC (3x3), 8 ABCD (4x4), 9 8x8 + channel: str = None, # Channel number for this radio device. Frequency takes # precedence if both are set to non-default values. - # 0xFFFF, AUTO or DEFAULT means ANY. - const_tx=None, # RF Pattern Generator , encoded as a single 32-bit integer. - # See above. - country=None, # Country number for this radio device. - flags=None, # Flags for this interface (see above.) - flags_mask=None, # If set, only these flags will be considered. - frag_thresh=None, # Fragmentation Threshold (256 - 2346, 2346 == disabled). - frequency=None, # Frequency for this radio. 0xFFFF, AUTO or DEFAULT - # means ANY. - fwname=None, # Firmware name (for example: firmware-5.bin) - fwver=None, # Firmware API version (for example, 5 if firmware is based on - # firmware-5.bin - mac=None, # Used to identify when name cannot be trusted (2.6.34+ + const_tx: str = None, # RF Pattern Generator , encoded as a single 32-bit + # integer. See above. + country: str = None, # Country number for this radio device. + flags: str = None, # Flags for this interface (see above.) + flags_mask: str = None, # If set, only these flags will be considered. + frag_thresh: str = None, # Fragmentation Threshold (256 - 2346, 2346 == disabled). + frequency: str = None, # Frequency for this radio. 0xFFFF, AUTO or + # DEFAULT means ANY. + fwname: str = None, # Firmware name (for example: firmware-5.bin) + fwver: str = None, # Firmware API version (for example, 5 if firmware is based + # on firmware-5.bin + mac: str = None, # Used to identify when name cannot be trusted (2.6.34+ # kernels). - max_amsdu=None, # Maximum number of frames per AMSDU that may be transmitted. - # See above. - mode=None, # WiFi mode, see table - peer_count=None, # Number of peer objects for this radio. - pref_ap=None, # Preferred AP BSSID for all station vdevs on this radio. - pulse2_interval_us=None, # Pause between pattern burst for RF noise generator. - pulse_interval=None, # RF Pattern generator: interval between pulses in usecs. - pulse_width=None, # RF Pattern generator: pulse width in usecs. - radio=None, # Name of the physical radio interface, for example: wiphy0 - rate=None, # No longer used, specify the rate on the virtual station(s) - # instead. - rate_ctrl_count=None, # Number of rate-ctrl objects for this radio. - resource=None, # Resource number. - rts=None, # The RTS Threshold for this radio (off, or 1-2347). - shelf=None, # Shelf number. - skid_limit=None, # Firmware hash-table Skid Limit for this radio. - stations_count=None, # Number of stations supported by this radio. - tids_count=None, # TIDs count for this radio. - tx_pulses=None, # Number of pattern pulses per burst for RF noise generator. - txdesc_count=None, # Transmit descriptor count for this radio. - txpower=None, # The transmit power setting for this radio. (AUTO for system - # defaults) - vdev_count=None, # Configure radio vdev count. - debug_=False): + max_amsdu: str = None, # Maximum number of frames per AMSDU that may be + # transmitted. See above. + mode: str = None, # WiFi mode, see table + peer_count: str = None, # Number of peer objects for this radio. + pref_ap: str = None, # Preferred AP BSSID for all station vdevs on this radio. + pulse2_interval_us: str = None, # Pause between pattern burst for RF noise generator. + pulse_interval: str = None, # RF Pattern generator: interval between pulses in usecs. + pulse_width: str = None, # RF Pattern generator: pulse width in usecs. + radio: str = None, # Name of the physical radio interface, for example: wiphy0 + # [W] + rate: str = None, # No longer used, specify the rate on the virtual + # station(s) instead. + rate_ctrl_count: str = None, # Number of rate-ctrl objects for this radio. + resource: int = None, # Resource number. [W] + rts: str = None, # The RTS Threshold for this radio (off, or 1-2347). + shelf: int = 1, # Shelf number. [R][D:1] + skid_limit: str = None, # Firmware hash-table Skid Limit for this radio. + stations_count: str = None, # Number of stations supported by this radio. + tids_count: str = None, # TIDs count for this radio. + tx_pulses: str = None, # Number of pattern pulses per burst for RF noise + # generator. + txdesc_count: str = None, # Transmit descriptor count for this radio. + txpower: str = None, # The transmit power setting for this radio. (AUTO for + # system defaults) + vdev_count: str = None, # Configure radio vdev count. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_wifi_radio(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if active_peer_count is not None: data["active_peer_count"] = active_peer_count @@ -11598,9 +10525,10 @@ class LFJsonPost(LFCliBase): data["vdev_count"] = vdev_count if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_wifi_radio", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_wifi_radio", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -11610,27 +10538,30 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#set_wifi_txo ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_set_wifi_txo(self, - port=None, # WiFi interface name or number. - resource=None, # Resource number. - shelf=None, # Shelf number. - txo_bw=None, # Configure bandwidth: 0 == 20, 1 == 40, 2 == 80, 3 == 160, 4 == + port: str = None, # WiFi interface name or number. [W] + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + txo_bw: str = None, # Configure bandwidth: 0 == 20, 1 == 40, 2 == 80, 3 == 160, 4 == # 80+80. - txo_enable=None, # Set to 1 if you wish to enable transmit override, 0 to disable. - txo_mcs=None, # Configure the MCS (0-3 for CCK, 0-7 for OFDM, 0-7 for HT, 0-9 for - # VHT, 0-11 for HE - txo_nss=None, # Configure number of spatial streams (0 == nss1, 1 == nss2, ...). - txo_pream=None, # Select rate preamble: 0 == OFDM, 1 == CCK, 2 == HT, 3 == VHT, 4 == - # HE_SU. - txo_retries=None, # Configure number of retries. 0 or 1 means no retries). - txo_sgi=None, # Should rates be sent with short-guard-interval or not? - txo_txpower=None, # Configure TX power in db. Use 255 for system defaults. - debug_=False): + txo_enable: str = None, # Set to 1 if you wish to enable transmit override, 0 to + # disable. + txo_mcs: str = None, # Configure the MCS (0-3 for CCK, 0-7 for OFDM, 0-7 for HT, 0-9 + # for VHT, 0-11 for HE + txo_nss: str = None, # Configure number of spatial streams (0 == nss1, 1 == nss2, + # ...). + txo_pream: str = None, # Select rate preamble: 0 == OFDM, 1 == CCK, 2 == HT, 3 == VHT, + # 4 == HE_SU. + txo_retries: str = None, # Configure number of retries. 0 or 1 means no retries). + txo_sgi: str = None, # Should rates be sent with short-guard-interval or not? + txo_txpower: str = None, # Configure TX power in db. Use 255 for system defaults. See + # notes above. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_wifi_txo(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if port is not None: data["port"] = port @@ -11656,9 +10587,10 @@ class LFJsonPost(LFCliBase): data["txo_txpower"] = txo_txpower if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_wifi_txo", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_wifi_txo", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -11693,23 +10625,23 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_set_wl_corruption(self, - byte=None, # The byte to use for OVERWRITE_FIXED (or NA). - flags=None, # The flags for this corruption. - index=None, # The corruption to modify (0-5). - max_offset=None, # The maximum offset from start of Ethernet packet for the byte - # to be modified. - min_offset=None, # The minimum offset from start of Ethernet packet for the byte - # to be modified. - name=None, # WanLink name - rate=None, # Specifies how often, per million, this corruption should be - # applied. - debug_=False): + byte: str = None, # The byte to use for OVERWRITE_FIXED (or NA). + flags: str = None, # The flags for this corruption. + index: str = None, # The corruption to modify (0-5). [R,0-5] + max_offset: str = None, # The maximum offset from start of Ethernet packet for the + # byte to be modified. + min_offset: str = None, # The minimum offset from start of Ethernet packet for the + # byte to be modified. + name: str = None, # WanLink name [R] + rate: str = None, # Specifies how often, per million, this corruption should + # be applied. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_wl_corruption(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if byte is not None: data["byte"] = byte @@ -11727,9 +10659,10 @@ class LFJsonPost(LFCliBase): data["rate"] = rate if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_wl_corruption", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_wl_corruption", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -11747,15 +10680,15 @@ class LFJsonPost(LFCliBase): WRR__queue_queue_____ = "WRR,[queue,queue,...]" # Weighted Round Robbin is also available def post_set_wl_qdisc(self, - name=None, # WanLink name - qdisc=None, # FIFO, WRR,a,b,c,d,e,f,g etc - debug_=False): + name: str = None, # WanLink name [R] + qdisc: str = None, # FIFO, WRR,a,b,c,d,e,f,g etc [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_set_wl_qdisc(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name @@ -11763,9 +10696,10 @@ class LFJsonPost(LFCliBase): data["qdisc"] = qdisc if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/set_wl_qdisc", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/set_wl_qdisc", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -11793,19 +10727,19 @@ class LFJsonPost(LFCliBase): Test_Mgr = "Test_Mgr" # def post_show_alerts(self, - card=None, # Alert resource filter. - endp=None, # Alert endpoint filter. - extra=None, # Extra filter, currently ignored. - port=None, # Alert port filter (can be port name or number). - shelf=None, # Alert shelf filter. - p_type=None, # Alert type filter. - debug_=False): + card: int = None, # Alert resource filter. + endp: str = None, # Alert endpoint filter. + extra: str = None, # Extra filter, currently ignored. + port: str = None, # Alert port filter (can be port name or number). + shelf: int = 1, # Alert shelf filter. + p_type: str = None, # Alert type filter. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_alerts(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if card is not None: data["card"] = card @@ -11821,9 +10755,10 @@ class LFJsonPost(LFCliBase): data["type"] = p_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_alerts", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_alerts", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -11833,16 +10768,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_attenuators ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_attenuators(self, - resource=None, # Resource number, or 'all'. - serno=None, # Serial number for requested Attenuator, or 'all'. - shelf=None, # Shelf number or alias, can be 'all'. - debug_=False): + resource: int = None, # Resource number, or 'all'. [W] + serno: str = None, # Serial number for requested Attenuator, or 'all'. [W] + shelf: int = 1, # Shelf number or alias, can be 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_attenuators(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -11852,9 +10787,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_attenuators", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_attenuators", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -11864,16 +10800,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_cd ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_cd(self, - collision_domain=None, # Name of the Collision Domain, or 'all'. - resource=None, # Resource number, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - debug_=False): + collision_domain: str = None, # Name of the Collision Domain, or 'all'. [W] + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_cd(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if collision_domain is not None: data["collision_domain"] = collision_domain @@ -11883,9 +10819,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_cd", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_cd", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -11895,22 +10832,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_chamber ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_chamber(self, - name=None, # Chamber Name or 'ALL'. - debug_=False): + name: str = None, # Chamber Name or 'ALL'. [W][D:ALL] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_chamber(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_chamber", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_chamber", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -11920,16 +10858,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_channel_groups ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_channel_groups(self, - channel_name=None, # Name of the channel, or 'all'. - resource=None, # Resource number, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - debug_=False): + channel_name: str = None, # Name of the channel, or 'all'. [W] + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_channel_groups(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if channel_name is not None: data["channel_name"] = channel_name @@ -11939,9 +10877,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_channel_groups", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_channel_groups", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -11951,17 +10890,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_clients ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_clients(self, - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_clients(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} - response = self.json_post("/cli-json/show_clients", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_clients", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -11971,15 +10911,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_cx ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_cx(self, - cross_connect=None, # Specify cross-connect to act on, or 'all'. - test_mgr=None, # Specify test-mgr to act on, or 'all'. - debug_=False): + cross_connect: str = None, # Specify cross-connect to act on, or 'all'. [W] + test_mgr: str = None, # Specify test-mgr to act on, or 'all'. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_cx(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if cross_connect is not None: data["cross_connect"] = cross_connect @@ -11987,9 +10927,10 @@ class LFJsonPost(LFCliBase): data["test_mgr"] = test_mgr if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_cx", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_cx", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -11999,15 +10940,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_cxe ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_cxe(self, - cross_connect=None, # Specify cross-connect to show, or 'all'. - test_mgr=None, # Specify test-mgr to use, or 'all'. - debug_=False): + cross_connect: str = None, # Specify cross-connect to show, or 'all'. [W] + test_mgr: str = None, # Specify test-mgr to use, or 'all'. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_cxe(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if cross_connect is not None: data["cross_connect"] = cross_connect @@ -12015,9 +10956,10 @@ class LFJsonPost(LFCliBase): data["test_mgr"] = test_mgr if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_cxe", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_cxe", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12027,17 +10969,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_dbs ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_dbs(self, - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_dbs(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} - response = self.json_post("/cli-json/show_dbs", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_dbs", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12047,22 +10990,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_dut ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_dut(self, - name=None, # DUT Name or 'ALL'. - debug_=False): + name: str = None, # DUT Name or 'ALL'. [W][D:ALL] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_dut(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_dut", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_dut", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12072,15 +11016,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_endp_payload ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_endp_payload(self, - max_bytes=None, # The max number of payload bytes to print out, default is 128. - name=None, # The name of the endpoint we are configuring. - debug_=False): + max_bytes: str = None, # The max number of payload bytes to print out, default is + # 128. [R][D:128] + name: str = None, # The name of the endpoint we are configuring. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_endp_payload(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if max_bytes is not None: data["max_bytes"] = max_bytes @@ -12088,9 +11033,10 @@ class LFJsonPost(LFCliBase): data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_endp_payload", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_endp_payload", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12100,15 +11046,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_endpoints ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_endpoints(self, - endpoint=None, # Name of endpoint, or 'all'. - extra=None, # See above. - debug_=False): + endpoint: str = None, # Name of endpoint, or 'all'. [R] + extra: str = None, # See above. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_endpoints(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endpoint is not None: data["endpoint"] = endpoint @@ -12116,9 +11062,10 @@ class LFJsonPost(LFCliBase): data["extra"] = extra if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_endpoints", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_endpoints", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12128,23 +11075,24 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_err ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_err(self, - message=None, # Message to show to others currently logged on. Unescaped Value - debug_=False): + message: str = None, # Message to show to others currently logged on. Unescaped Value [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_err(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if message is not None: data["message"] = message if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_err", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_err", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12154,17 +11102,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_event_interest ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_event_interest(self, - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_event_interest(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} - response = self.json_post("/cli-json/show_event_interest", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_event_interest", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12192,19 +11141,19 @@ class LFJsonPost(LFCliBase): Test_Mgr = "Test_Mgr" # def post_show_events(self, - card=None, # Event resource filter. - endp=None, # Event endpoint filter. - extra=None, # Extra filter, currently ignored. - port=None, # Event port filter (can be port name or number). - shelf=None, # Event shelf filter. - p_type=None, # Event type filter. - debug_=False): + card: int = None, # Event resource filter. + endp: str = None, # Event endpoint filter. + extra: str = None, # Extra filter, currently ignored. + port: str = None, # Event port filter (can be port name or number). + shelf: int = 1, # Event shelf filter. + p_type: str = None, # Event type filter. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_events(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if card is not None: data["card"] = card @@ -12220,9 +11169,10 @@ class LFJsonPost(LFCliBase): data["type"] = p_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_events", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_events", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12232,19 +11182,20 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_files ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_files(self, - dir_flags=None, # Determines format of listing, see above. - directory=None, # The sub-directory in which to list. - p_filter=None, # An optional filter, as used by the 'ls' command. - key=None, # A special key, can be used for scripting. - resource=None, # The machine to search in. - shelf=None, # The virtual shelf to search in. Use 0 for manager machine. - debug_=False): + dir_flags: str = None, # Determines format of listing, see above. + directory: str = None, # The sub-directory in which to list. + p_filter: str = None, # An optional filter, as used by the 'ls' command. + key: str = None, # A special key, can be used for scripting. + resource: int = None, # The machine to search in. [W] + shelf: int = 1, # The virtual shelf to search in. Use 0 for manager machine. + # [R,0-1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_files(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if dir_flags is not None: data["dir_flags"] = dir_flags @@ -12260,9 +11211,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_files", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_files", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12272,22 +11224,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_group ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_group(self, - group=None, # Can be name of test group. Use 'all' or leave blank for all groups. - debug_=False): + group: str = None, # Can be name of test group. Use 'all' or leave blank for all groups. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_group(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if group is not None: data["group"] = group if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_group", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_group", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12297,22 +11250,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_pesq ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_pesq(self, - endpoint=None, # Name of endpoint, or 'all'. - debug_=False): + endpoint: str = None, # Name of endpoint, or 'all'. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_pesq(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endpoint is not None: data["endpoint"] = endpoint if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_pesq", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_pesq", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12322,18 +11276,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_ports ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_ports(self, - port=None, # Port number, or 'all'. - probe_flags=None, # See above, add them together for multiple probings. Leave blank if - # you want stats only. - resource=None, # Resource number, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - debug_=False): + port: str = None, # Port number, or 'all'. [W] + probe_flags: str = None, # See above, add them together for multiple probings. Leave blank + # if you want stats only. + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_ports(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if port is not None: data["port"] = port @@ -12345,9 +11299,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_ports", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_ports", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12357,16 +11312,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_ppp_links ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_ppp_links(self, - link_num=None, # Ppp-Link number of the span, or 'all'. - resource=None, # Resource number, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - debug_=False): + link_num: str = None, # Ppp-Link number of the span, or 'all'. [W] + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_ppp_links(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if link_num is not None: data["link_num"] = link_num @@ -12376,9 +11331,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_ppp_links", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_ppp_links", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12388,22 +11344,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_profile ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_profile(self, - name=None, # Profile Name or 'ALL'. - debug_=False): + name: str = None, # Profile Name or 'ALL'. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_profile(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_profile", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_profile", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12413,15 +11370,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_resources ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_resources(self, - resource=None, # Resource number, or 'all'. - shelf=None, # Shelf number or alias, can be 'all'. - debug_=False): + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Shelf number or alias, can be 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_resources(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -12429,9 +11386,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_resources", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_resources", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12441,15 +11399,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_rfgen ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_rfgen(self, - resource=None, # Resource number, or 'all'. - shelf=None, # Shelf number or alias, can be 'all'. - debug_=False): + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Shelf number or alias, can be 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_rfgen(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -12457,9 +11415,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_rfgen", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_rfgen", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12469,17 +11428,17 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_rt ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_rt(self, - key=None, # Unique identifier for this request. Usually left blank. - resource=None, # Resource number. - shelf=None, # Shelf number. - virtual_router=None, # Name of the virtual router. - debug_=False): + key: str = None, # Unique identifier for this request. Usually left blank. + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + virtual_router: str = None, # Name of the virtual router. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_rt(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if key is not None: data["key"] = key @@ -12491,9 +11450,10 @@ class LFJsonPost(LFCliBase): data["virtual_router"] = virtual_router if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_rt", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_rt", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12503,15 +11463,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_script_results ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_script_results(self, - endpoint=None, # Name of endpoint, test-group, or 'all'. - key=None, # Optional 'key' to be used in keyed-text message result. - debug_=False): + endpoint: str = None, # Name of endpoint, test-group, or 'all'. [R] + key: str = None, # Optional 'key' to be used in keyed-text message result. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_script_results(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endpoint is not None: data["endpoint"] = endpoint @@ -12519,9 +11479,10 @@ class LFJsonPost(LFCliBase): data["key"] = key if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_script_results", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_script_results", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12531,16 +11492,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_spans ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_spans(self, - resource=None, # Resource number, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - span_number=None, # Span-Number of the span, or 'all'. - debug_=False): + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + span_number: str = None, # Span-Number of the span, or 'all'. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_spans(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -12550,9 +11511,10 @@ class LFJsonPost(LFCliBase): data["span_number"] = span_number if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_spans", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_spans", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12562,16 +11524,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_text_blob ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_text_blob(self, - brief=None, # Set to 'brief' for a brief listing of all text blobs. - name=None, # Text Blob Name or 'ALL'. - p_type=None, # Text Blob type or 'ALL'. - debug_=False): + brief: str = None, # Set to 'brief' for a brief listing of all text blobs. + name: str = None, # Text Blob Name or 'ALL'. [R] + p_type: str = None, # Text Blob type or 'ALL'. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_text_blob(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if brief is not None: data["brief"] = brief @@ -12581,9 +11543,10 @@ class LFJsonPost(LFCliBase): data["type"] = p_type if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_text_blob", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_text_blob", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12593,22 +11556,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_tm ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_tm(self, - test_mgr=None, # Can be name of test manager, or 'all'. - debug_=False): + test_mgr: str = None, # Can be name of test manager, or 'all'. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_tm(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if test_mgr is not None: data["test_mgr"] = test_mgr if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_tm", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_tm", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12618,22 +11582,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_traffic_profile ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_traffic_profile(self, - name=None, # Profile Name or 'ALL'. - debug_=False): + name: str = None, # Profile Name or 'ALL'. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_traffic_profile(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_traffic_profile", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_traffic_profile", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12643,16 +11608,17 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_venue ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_venue(self, - resource=None, # Resource number, or 'ALL' - shelf=None, # Shelf number. - venu_id=None, # Number to uniquely identify this venue on this resource, or 'ALL' - debug_=False): + resource: int = None, # Resource number, or 'ALL' [W] + shelf: int = 1, # Shelf number. [R][D:1] + venu_id: str = None, # Number to uniquely identify this venue on this resource, or 'ALL' + # [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_venue(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -12662,9 +11628,10 @@ class LFJsonPost(LFCliBase): data["venu_id"] = venu_id if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_venue", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_venue", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12674,16 +11641,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_vr ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_vr(self, - resource=None, # Resource number, or 'all'. - router=None, # Name of the Virtual Router, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - debug_=False): + resource: int = None, # Resource number, or 'all'. [W] + router: str = None, # Name of the Virtual Router, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_vr(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -12693,9 +11660,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_vr", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_vr", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12705,16 +11673,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_vrcx ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_vrcx(self, - cx_name=None, # Name of the Virtual Router Connection, or 'all'. - resource=None, # Resource number, or 'all'. - shelf=None, # Name/id of the shelf, or 'all'. - debug_=False): + cx_name: str = None, # Name of the Virtual Router Connection, or 'all'. [W] + resource: int = None, # Resource number, or 'all'. [W] + shelf: int = 1, # Name/id of the shelf, or 'all'. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_vrcx(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if cx_name is not None: data["cx_name"] = cx_name @@ -12724,9 +11692,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_vrcx", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_vrcx", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12736,15 +11705,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#show_wanpaths ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_show_wanpaths(self, - endpoint=None, # Name of endpoint, or 'all'. - wanpath=None, # Name of wanpath, or 'all'. - debug_=False): + endpoint: str = None, # Name of endpoint, or 'all'. [W] + wanpath: str = None, # Name of wanpath, or 'all'. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_show_wanpaths(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endpoint is not None: data["endpoint"] = endpoint @@ -12752,9 +11721,10 @@ class LFJsonPost(LFCliBase): data["wanpath"] = wanpath if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/show_wanpaths", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/show_wanpaths", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12764,18 +11734,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#shutdown ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_shutdown(self, - chdir=None, # Directory to cd to before dying. Only useful when using gprof to debug, - # or 'NA' to ignore. - really=None, # Must be 'YES' for command to really work. - serverctl=None, # Enter 'YES' to do a ./serverctl.bash restart to restart all LANforge - # processes. - debug_=False): + chdir: str = None, # Directory to cd to before dying. Only useful when using gprof to + # debug, or 'NA' to ignore. + really: str = None, # Must be 'YES' for command to really work. + serverctl: str = None, # Enter 'YES' to do a ./serverctl.bash restart to restart all + # LANforge processes. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_shutdown(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if chdir is not None: data["chdir"] = chdir @@ -12785,9 +11755,10 @@ class LFJsonPost(LFCliBase): data["serverctl"] = serverctl if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/shutdown", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/shutdown", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12797,15 +11768,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#shutdown_os ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_shutdown_os(self, - resource=None, # Resource number, or ALL. - shelf=None, # Shelf number, or ALL. - debug_=False): + resource: int = None, # Resource number, or ALL. [W] + shelf: int = 1, # Shelf number, or ALL. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_shutdown_os(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -12813,9 +11784,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/shutdown_os", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/shutdown_os", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12825,15 +11797,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#shutdown_resource ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_shutdown_resource(self, - resource=None, # Resource number, or ALL. - shelf=None, # Shelf number, or ALL. - debug_=False): + resource: int = None, # Resource number, or ALL. [W] + shelf: int = 1, # Shelf number, or ALL. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_shutdown_resource(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -12841,9 +11813,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/shutdown_resource", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/shutdown_resource", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12876,22 +11849,22 @@ class LFJsonPost(LFCliBase): return (cls[member].value for member in cls.__members__ if member == name) def post_sniff_port(self, - display=None, # The DISPLAY option, for example: 192.168.1.5:0.0. Will guess if left - # blank. - duration=None, # Duration for doing a capture (in seconds). Default is 5 minutes for - # dumpcap/tshark, and forever for wireshark - flags=None, # Flags that control how the sniffing is done. - outfile=None, # Optional file location for saving a capture. - port=None, # The port we are trying to run the packet sniffer on. - resource=None, # Resource number. - shelf=None, # Shelf number. - debug_=False): + display: str = None, # The DISPLAY option, for example: 192.168.1.5:0.0. Will guess if + # left blank. + duration: str = None, # Duration for doing a capture (in seconds). Default is 5 minutes + # for dumpcap/tshark, and forever for wireshark + flags: str = None, # Flags that control how the sniffing is done. + outfile: str = None, # Optional file location for saving a capture. + port: str = None, # The port we are trying to run the packet sniffer on. [R] + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_sniff_port(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if display is not None: data["display"] = display @@ -12909,9 +11882,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/sniff_port", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/sniff_port", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12921,22 +11895,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#start_endp ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_start_endp(self, - endp_name=None, # Name of the cross-connect, or 'all'. - debug_=False): + endp_name: str = None, # Name of the cross-connect, or 'all'. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_start_endp(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endp_name is not None: data["endp_name"] = endp_name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/start_endp", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/start_endp", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12946,22 +11921,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#start_group ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_start_group(self, - name=None, # The name of the test group. - debug_=False): + name: str = None, # The name of the test group. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_start_group(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/start_group", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/start_group", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -12971,16 +11947,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#start_ppp_link ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_start_ppp_link(self, - resource=None, # Resource number that holds this PppLink. - shelf=None, # Name/id of the shelf. - unit_num=None, # Unit-Number for the PppLink to be started. - debug_=False): + resource: int = None, # Resource number that holds this PppLink. [W] + shelf: int = 1, # Name/id of the shelf. [R][D:1] + unit_num: str = None, # Unit-Number for the PppLink to be started. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_start_ppp_link(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -12990,9 +11966,10 @@ class LFJsonPost(LFCliBase): data["unit_num"] = unit_num if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/start_ppp_link", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/start_ppp_link", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -13002,22 +11979,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#stop_endp ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_stop_endp(self, - endp_name=None, # Name of the endpoint, or 'all'. - debug_=False): + endp_name: str = None, # Name of the endpoint, or 'all'. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_stop_endp(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if endp_name is not None: data["endp_name"] = endp_name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/stop_endp", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/stop_endp", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -13027,22 +12005,23 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#stop_group ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_stop_group(self, - name=None, # The name of the test group, or 'all' - debug_=False): + name: str = None, # The name of the test group, or 'all' [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_stop_group(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if name is not None: data["name"] = name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/stop_group", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/stop_group", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -13052,16 +12031,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#stop_ppp_link ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_stop_ppp_link(self, - resource=None, # Resource number that holds this PppLink. - shelf=None, # Name/id of the shelf. - unit_num=None, # Unit-Number for the PppLink to be stopped. - debug_=False): + resource: int = None, # Resource number that holds this PppLink. [W] + shelf: int = 1, # Name/id of the shelf. [R][D:1] + unit_num: str = None, # Unit-Number for the PppLink to be stopped. [W] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_stop_ppp_link(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -13071,9 +12050,10 @@ class LFJsonPost(LFCliBase): data["unit_num"] = unit_num if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/stop_ppp_link", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/stop_ppp_link", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -13083,19 +12063,19 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#tail ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_tail(self, - cmd=None, # Command: start, stop, results - key=None, # File-name that we should be tailing. - message=None, # The contents to display (for results only) Unescaped - # Value - resource=None, # Resource that holds the file. - shelf=None, # Shelf that holds the resource that holds the file. - debug_=False): + cmd: str = None, # Command: start, stop, results + key: str = None, # File-name that we should be tailing. + message: str = None, # The contents to display (for results only) Unescaped Value + resource: int = None, # Resource that holds the file. [W] + shelf: int = 1, # Shelf that holds the resource that holds the file. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_tail(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if cmd is not None: data["cmd"] = cmd @@ -13109,9 +12089,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/tail", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/tail", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -13121,15 +12102,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#tm_register ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_tm_register(self, - client_name=None, # Name of client to be registered. (dflt is current client) - test_mgr=None, # Name of test manager (can be all.) - debug_=False): + client_name: str = None, # Name of client to be registered. (dflt is current client) [W] + test_mgr: str = None, # Name of test manager (can be all.) [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_tm_register(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if client_name is not None: data["client_name"] = client_name @@ -13137,9 +12118,10 @@ class LFJsonPost(LFCliBase): data["test_mgr"] = test_mgr if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/tm_register", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/tm_register", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -13149,15 +12131,16 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#tm_unregister ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_tm_unregister(self, - client_name=None, # Name of client to be un-registered. (dflt is current client) - test_mgr=None, # Name of test manager (can be all.) - debug_=False): + client_name: str = None, # Name of client to be un-registered. (dflt is current client) + # [W] + test_mgr: str = None, # Name of test manager (can be all.) [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_tm_unregister(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if client_name is not None: data["client_name"] = client_name @@ -13165,9 +12148,10 @@ class LFJsonPost(LFCliBase): data["test_mgr"] = test_mgr if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/tm_unregister", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/tm_unregister", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -13177,17 +12161,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#version ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_version(self, - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_version(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} - response = self.json_post("/cli-json/version", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/version", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -13197,17 +12182,18 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#who ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_who(self, - debug_=False): + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_who(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} - response = self.json_post("/cli-json/who", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/who", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -13217,19 +12203,19 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#wifi_cli_cmd ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_wifi_cli_cmd(self, - port=None, # Name of the WiFi station or AP interface to which this command - # will be directed. - resource=None, # Resource number. - shelf=None, # Shelf number. - wpa_cli_cmd=None, # Command to pass to wpa_cli or hostap_cli. This must be - # single-quoted. - debug_=False): + port: str = None, # Name of the WiFi station or AP interface to which this command + # will be directed. [R] + resource: int = None, # Resource number. [W] + shelf: int = 1, # Shelf number. [R][D:1] + wpa_cli_cmd: str = None, # Command to pass to wpa_cli or hostap_cli. This must be + # single-quoted. [R] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_wifi_cli_cmd(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if port is not None: data["port"] = port @@ -13241,9 +12227,10 @@ class LFJsonPost(LFCliBase): data["wpa_cli_cmd"] = wpa_cli_cmd if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/wifi_cli_cmd", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/wifi_cli_cmd", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -13253,17 +12240,17 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#wifi_event ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_wifi_event(self, - device=None, # Interface or PHY in most cases. - event=None, # What happened. - msg=None, # Entire event in human readable form. - status=None, # Status on what happened. - debug_=False): + device: str = None, # Interface or PHY in most cases. [R] + event: str = None, # What happened. [R] + msg: str = None, # Entire event in human readable form. + status: str = None, # Status on what happened. + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_wifi_event(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if device is not None: data["device"] = device @@ -13275,9 +12262,10 @@ class LFJsonPost(LFCliBase): data["status"] = status if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/wifi_event", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/wifi_event", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -13287,15 +12275,15 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#wiser_reset ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_wiser_reset(self, - resource=None, # Resource number, or ALL. - shelf=None, # Shelf number, or ALL. - debug_=False): + resource: int = None, # Resource number, or ALL. [W] + shelf: int = 1, # Shelf number, or ALL. [R][D:1] + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_wiser_reset(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if resource is not None: data["resource"] = resource @@ -13303,9 +12291,10 @@ class LFJsonPost(LFCliBase): data["shelf"] = shelf if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/wiser_reset", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/wiser_reset", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # @@ -13315,21 +12304,3426 @@ class LFJsonPost(LFCliBase): https://www.candelatech.com/lfcli_ug.php#write ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" def post_write(self, - db_name=None, # The name the backup shall be saved as (blank means dflt) - debug_=False): + db_name: str = None, # The name the backup shall be saved as (blank means dflt) + debug=False): """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Example Usage: result = post_write(param=value ...) pprint.pprint( result ) ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" - debug_ |= self.debug + debug |= self.debug_on data = {} if db_name is not None: data["db_name"] = db_name if len(data) < 1: raise ValueError(__name__+": no parameters to submit") - response = self.json_post("/cli-json/write", - data, - debug_=debug_) + response = self.json_post(url="/cli-json/write", + post_data=data, + die_on_error=self.die_on_error, + debug=debug) return response # + + +class LFJsonQuery(JsonQuery): + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + LFJsonQuery inherits from JsonQuery. + Queries are used for GET requests. + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + def __init__(self, + session_obj: object = None, + debug: bool = False, + exit_on_error: bool = False): + super().__init__(session_obj=session_obj, + debug=debug, + exit_on_error=exit_on_error) + + # Auto generated methods follow: + + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /alerts/ + /alerts/$event_id + /alerts/before/$event_id + /alerts/between/$start_event_id/$end_event_id + /alerts/last/$event_count + /alerts/since/$event_id + + When requesting specific column names, they need to be URL encoded: + eid, entity+id, event, event+description, id, name, priority, time-stamp, + type + Example URL: /alerts?fields=eid,entity+id + + Example py-json call (it knows the URL): + record = LFJsonGet.get_alerts(eid_list=['1.234', '1.344'], + requested_col_names=['entity id'], + debug=True) + + The record returned will have these members: + { + 'eid': # Time at which this event was created.This uses the clock on the source + # machine. + 'entity id': # Entity IdentifierExact format depends on the + # type.(shelf.resource.port.endpoint.extra) + 'event': # Event Type + 'event description': # Text description for this event. + 'id': # Unique ID for this event. + 'name': # Name of the entity associated with this event. + 'priority': # Event priority. + 'time-stamp': # Time at which this event was created.This uses the clock on the source + # machine. + 'type': # Entity type. + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_alerts(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/alerts" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="alert", + plural_key="alerts") + # + """ + Below are 7 methods defined by LFClient URL Responders + """ + + def alerts_since(self, + event_id: int = None, + debug : bool = False, + wait_sec : float = None, + request_timeout_sec : float = None, + max_timeout_sec : float = None, + errors_warnings : list = None): + """ + Select alerts since an alert ID + :param event_id: earliest to start at + """ + response = self.json_get(url="/alerts/alerts_since/{event_id}".format(event_id=event_id), + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=request_timeout_sec, + max_timeout_sec=max_timeout_sec, + errors_warnings=errors_warnings) + if not response: + return None + return self.extract_values(response=response, + singular_key="event", + plural_key="events") + # + + def alerts_last_events(self, + event_count: int = None, + debug : bool = False, + wait_sec : float = None, + request_timeout_sec : float = None, + max_timeout_sec : float = None, + errors_warnings : list = None): + """ + Select last event_count alerts + :param event_count: number since end to select + """ + response = self.json_get(url="/alerts/last/{event_count}".format(event_count=event_count), + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=request_timeout_sec, + max_timeout_sec=max_timeout_sec, + errors_warnings=errors_warnings) + if not response: + return None + return self.extract_values(response=response, + singular_key="event", + plural_key="events") + # + + def alerts_before(self, + event_id: int = None, + debug : bool = False, + wait_sec : float = None, + request_timeout_sec : float = None, + max_timeout_sec : float = None, + errors_warnings : list = None): + """ + Select first alerts before alert_id + :param event_id: id to stop selecting at + """ + response = self.json_get(url="/alerts/before/{event_id}".format(event_id=event_id), + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=request_timeout_sec, + max_timeout_sec=max_timeout_sec, + errors_warnings=errors_warnings) + if not response: + return None + return self.extract_values(response=response, + singular_key="event", + plural_key="events") + # + + def events_between(self, + start_event_id: int = None, + end_event_id: int = None, + debug : bool = False, + wait_sec : float = None, + request_timeout_sec : float = None, + max_timeout_sec : float = None, + errors_warnings : list = None): + """ + Select events between start and end IDs, inclusive + :param start_event_id: start selection at this id + :param end_event_id: end selection at this id + """ + response = self.json_get(url="/events/between/{start_event_id}/{end_event_id}".format(start_event_id=start_event_id, end_event_id=end_event_id), + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=request_timeout_sec, + max_timeout_sec=max_timeout_sec, + errors_warnings=errors_warnings) + if not response: + return None + return self.extract_values(response=response, + singular_key="event", + plural_key="events") + # + + def events_get_event(self, + event_id: int = None, + debug : bool = False, + wait_sec : float = None, + request_timeout_sec : float = None, + max_timeout_sec : float = None, + errors_warnings : list = None): + """ + Query an event by id + :param event_id: id to select + """ + response = self.json_get(url="/events/{event_id}".format(event_id=event_id), + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=request_timeout_sec, + max_timeout_sec=max_timeout_sec, + errors_warnings=errors_warnings) + if not response: + return None + return self.extract_values(response=response, + singular_key="event", + plural_key="events") + # + + def events_last_events(self, + event_count: int = None, + debug : bool = False, + wait_sec : float = None, + request_timeout_sec : float = None, + max_timeout_sec : float = None, + errors_warnings : list = None): + """ + Select last event_count events + :param event_count: number since end to select + """ + response = self.json_get(url="/events/last/{event_count}".format(event_count=event_count), + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=request_timeout_sec, + max_timeout_sec=max_timeout_sec, + errors_warnings=errors_warnings) + if not response: + return None + return self.extract_values(response=response, + singular_key="event", + plural_key="events") + # + + def events_since(self, + event_id: int = None, + debug : bool = False, + wait_sec : float = None, + request_timeout_sec : float = None, + max_timeout_sec : float = None, + errors_warnings : list = None): + """ + Select events since an id + :param event_id: event id to start at + """ + response = self.json_get(url="/events/since/{event_id}".format(event_id=event_id), + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=request_timeout_sec, + max_timeout_sec=max_timeout_sec, + errors_warnings=errors_warnings) + if not response: + return None + return self.extract_values(response=response, + singular_key="event", + plural_key="events") + # + + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /attenuator/ + /attenuator/$shelf_id + /attenuator/$shelf_id/$resource_id + /attenuator/$shelf_id/$resource_id/$port_id + /attenuators/ + /attenuators/$shelf_id + /attenuators/$shelf_id/$resource_id + /attenuators/$shelf_id/$resource_id/$port_id + + When requesting specific column names, they need to be URL encoded: + entity+id, module+1, module+2, module+3, module+4, module+5, module+6, module+7, + module+8, name, script, state, temperature + Example URL: /attenuator?fields=entity+id,module+1 + + Example py-json call (it knows the URL): + record = LFJsonGet.get_attenuator(eid_list=['1.234', '1.344'], + requested_col_names=['entity id'], + debug=True) + + The record returned will have these members: + { + 'entity id': # Entity ID + 'module 1': # Reported attenuator dB settings. + 'module 2': # Reported attenuator dB settings. + 'module 3': # Reported attenuator dB settings. + 'module 4': # Reported attenuator dB settings. + 'module 5': # Reported attenuator dB settings. + 'module 6': # Reported attenuator dB settings. + 'module 7': # Reported attenuator dB settings. + 'module 8': # Reported attenuator dB settings. + 'name': # Attenuator module identifier (shelf . resource . serial-num). + 'script': # Attenuator script state. + 'state': # Attenuator state. + 'temperature': # Temperature in degres Farenheight reported in Attenuator unit. + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_attenuator(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/attenuator" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="attenuator", + plural_key="attenuators") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /chamber/ + /chamber/$chamber_name + + When requesting specific column names, they need to be URL encoded: + chamber, chamber+connections, chamber+resources, chamber+type, duts, entity+id, + flags, hide, isolation, marked, open, reported+rotation+%28deg%29, reported+rpm, + reported+tilt+%28deg%29, resource, rotation+%28deg%29, rpm, smas, tilt+%28deg%29, turntable, + turntable+type, virtual + Example URL: /chamber?fields=chamber,chamber+connections + + Example py-json call (it knows the URL): + record = LFJsonGet.get_chamber(eid_list=['1.234', '1.344'], + requested_col_names=['entity id'], + debug=True) + + The record returned will have these members: + { + 'chamber': # - + 'chamber connections': # - + 'chamber resources': # - + 'chamber type': # - + 'duts': # - + 'entity id': # - + 'flags': # - + 'hide': # - + 'isolation': # - + 'marked': # - + 'open': # - + 'reported rotation (deg)': # - + 'reported rpm ': # - + 'reported tilt (deg)': # - + 'resource': # - + 'rotation (deg)': # - + 'rpm': # - + 'smas': # - + 'tilt (deg)': # - + 'turntable': # - + 'turntable type': # - + 'virtual': # - + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_chamber(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/chamber" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="chamber", + plural_key="chambers") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /control/$command + + + Example py-json call (it knows the URL): + record = LFJsonGet.get_control(eid_list=['1.234', '1.344'], + debug=True) + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_control(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/control" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="", + plural_key="") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /cx/ + /cx/$cx_id + + When requesting specific column names, they need to be URL encoded: + avg+rtt, bps+rx+a, bps+rx+b, drop+pkts+a, drop+pkts+b, eid, endpoints+%28a%C2%A0%E2%86%94%C2%A0b%29, + entity+id, name, pkt+rx+a, pkt+rx+b, rpt+timer, rx+drop+%25+a, rx+drop+%25+b, + state, type + Example URL: /cx?fields=avg+rtt,bps+rx+a + + Example py-json call (it knows the URL): + record = LFJsonGet.get_cx(eid_list=['1.234', '1.344'], + requested_col_names=['entity id'], + debug=True) + + The record returned will have these members: + { + 'avg rtt': # Average Round-Trip-Time (latency) for this connection (ms). + 'bps rx a': # Endpoint A's real receive rate (bps). + 'bps rx b': # Endpoint B's real receive rate (bps). + 'drop pkts a': # The number of packets Endpoint B sent minus the number Endpoint A + # received.This number is not 100% correct as long as packets are in + # flight.After a Quiesce of the test, the number should be perfectly + # accurate. + 'drop pkts b': # The number of packets Endpoint A sent minus the number Endpoint B + # received.This number is not 100% correct as long as packets are in + # flight.After a Quiesce of the test, the number should be perfectly + # accurate. + 'eid': # Cross Connect's Name. + 'endpoints (a ↔ b)': # Endpoints that make up this Cross Connect. + 'entity id': # Cross Connect's Name. + 'name': # Cross Connect's Name. + 'pkt rx a': # Endpoint A's Packets Recieved. + 'pkt rx b': # Endpoint B's Packets Recieved. + 'rpt timer': # Cross Connect's Report Timer (milliseconds).This is how often the GUI + # will ask for updates from the LANforge processes.If the GUI is sluggish, + # increasing the report timers may help. + 'rx drop % a': # Endpoint A percentage packet loss.Calculated using the number of PDUs + # Endpoint B sent minus the number Endpoint A received.This number is not + # 100% correct as long as packets are in flight.After a Quiesce of the + # test, the number should be perfectly accurate. + 'rx drop % b': # Endpoint B percentage packet loss.Calculated using the number of PDUs + # Endpoint A sent minus the number Endpoint B received.This number is not + # 100% correct as long as packets are in flight.After a Quiesce of the + # test, the number should be perfectly accurate. + 'state': # Current State of the connection.UninitializedHas not yet been + # started/stopped.InitializingBeing set up.StartingStarting the + # test.RunningTest is actively running.StoppedTest has been + # stopped.QuiesceTest will gracefully stop soon.HW-BYPASSTest is in + # hardware-bypass mode (WanLinks only)FTM_WAITTest wants to run, but is + # phantom, probably due to non-existent interface or resource.WAITINGWill + # restart as soon as resources are available.PHANTOMTest is stopped, and + # is phantom, probably due to non-existent interface or resource. + 'type': # Cross-Connect type. + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_cx(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/cx" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="", + plural_key="") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /dut/ + /dut/$name + + When requesting specific column names, they need to be URL encoded: + api+version, bssid-1, bssid-2, bssid-3, bssid-4, bssid-5, bssid-6, bssid-7, + bssid-8, dut, eap-id, entity+id, hw+info, image+file, lan, mgt+ip, model+number, + notes, num+ant+radio+1, num+ant+radio+2, num+ant+radio+3, password-1, password-2, + password-3, password-4, password-5, password-6, password-7, password-8, serial+number, + serial+port, ssid-1, ssid-2, ssid-3, ssid-4, ssid-5, ssid-6, ssid-7, ssid-8, + sw+info, wan + Example URL: /dut?fields=api+version,bssid-1 + + Example py-json call (it knows the URL): + record = LFJsonGet.get_dut(eid_list=['1.234', '1.344'], + requested_col_names=['entity id'], + debug=True) + + The record returned will have these members: + { + 'api version': # API Version + 'bssid-1': # WiFi BSSID for DUT. + 'bssid-2': # WiFi BSSID for DUT. + 'bssid-3': # WiFi BSSID for DUT. + 'bssid-4': # WiFi BSSID for DUT. + 'bssid-5': # WiFi BSSID for DUT. + 'bssid-6': # WiFi BSSID for DUT. + 'bssid-7': # WiFi BSSID for DUT. + 'bssid-8': # WiFi BSSID for DUT. + 'dut': # Devices Under Test + 'eap-id': # EAP Identifier, only used when one of the EAP options are selected. + 'entity id': # Entity ID + 'hw info': # DUT Hardware Info + 'image file': # Image file name. Relative paths assume directory /home/lanforge. Fully + # qualified pathnames begin with a slash (eg + # /usr/lib/share/icons/icon.png).File format should be PNG, JPG or BMP. + 'lan': # IP/Mask for LAN port (192.168.2.1/24). + 'mgt ip': # DUT Management IP address. + 'model number': # DUT model number or product name + 'notes': # Notes + 'num ant radio 1': # Antenna count for DUT radio(s). + 'num ant radio 2': # Antenna count for DUT radio(s). + 'num ant radio 3': # Antenna count for DUT radio(s). + 'password-1': # WiFi Password needed to connect to DUT. + 'password-2': # WiFi Password needed to connect to DUT. + 'password-3': # WiFi Password needed to connect to DUT. + 'password-4': # WiFi Password needed to connect to DUT. + 'password-5': # WiFi Password needed to connect to DUT. + 'password-6': # WiFi Password needed to connect to DUT. + 'password-7': # WiFi Password needed to connect to DUT. + 'password-8': # WiFi Password needed to connect to DUT. + 'serial number': # DUT Identifier (serial-number, or similar) + 'serial port': # Resource and name of LANforge serial port that connects to this DUT. + # (1.1.ttyS0). Does not need to belong to lan_port or wan_port resource. + 'ssid-1': # WiFi SSID advertised by DUT. + 'ssid-2': # WiFi SSID advertised by DUT. + 'ssid-3': # WiFi SSID advertised by DUT. + 'ssid-4': # WiFi SSID advertised by DUT. + 'ssid-5': # WiFi SSID advertised by DUT. + 'ssid-6': # WiFi SSID advertised by DUT. + 'ssid-7': # WiFi SSID advertised by DUT. + 'ssid-8': # WiFi SSID advertised by DUT. + 'sw info': # DUT Software Info + 'wan': # IP/Mask for WAN port (192.168.3.2/24). + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_dut(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/dut" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="dut", + plural_key="duts") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /endp/ + /endp/$endp_id + + When requesting specific column names, they need to be URL encoded: + 1st+rx, a%2Fb, bursty, crc+fail, cwnd, cx+active, cx+estab, cx+estab%2Fs, cx+to, + delay, destination+addr, dropped, dup+pkts, eid, elapsed, entity+id, jitter, + max+pdu, max+rate, min+pdu, min+rate, mng, name, ooo+pkts, pattern, pdu%2Fs+rx, + pdu%2Fs+tx, pps+rx+ll, pps+tx+ll, rcv+buf, replays, run, rx+ber, rx+bytes, + rx+drop+%25, rx+dup+%25, rx+ooo+%25, rx+pdus, rx+pkts+ll, rx+rate, rx+rate+%281%C2%A0min%29, + rx+rate+%28last%29, rx+rate+ll, rx+wrong+dev, script, send+buf, source+addr, + tcp+mss, tcp+rtx, tx+bytes, tx+pdus, tx+pkts+ll, tx+rate, tx+rate+%281%C2%A0min%29, + tx+rate+%28last%29, tx+rate+ll # hidden columns: + drop-count-5m, latency-5m, rt-latency-5m, rx-silence-5m + Example URL: /endp?fields=1st+rx,a%2Fb + + Example py-json call (it knows the URL): + record = LFJsonGet.get_endp(eid_list=['1.234', '1.344'], + requested_col_names=['entity id'], + debug=True) + + The record returned will have these members: + { + '1st rx': # Miliseconds between starting the endpoint and receiving the first + # packet.Note that LANforge UDP connections (not including multicast) will + # wait 20msbefore sending first frame to make sure receiver has adequate + # time to start. + 'a/b': # Display side (A or B) for the endpoint. + 'bursty': # Is the transmit rate bursty or not? + 'crc fail': # Total packets received with a bad payload CRC. + 'cwnd': # Sender's TCP Current Window Size. In units of Maximum Segment Size. + 'cx active': # Total number of active connections for this endpoint. + 'cx estab': # Total times the connection between the endpoints has been established. + 'cx estab/s': # Connections established per second, averaged over the last 30 seconds. + 'cx to': # Number of TCP connection attemtps timed out by LANforge. + 'delay': # Average latency in milliseconds for packets received by this endpoint. + 'destination addr': # Destination Address (MAC, ip/port, VoIP destination). + 'dropped': # Total dropped packets, as identified by gaps in packet sequence numbers. + 'dup pkts': # Total duplicate packets received. Only an estimate, but never less than + # this value. + 'eid': # Entity ID + 'elapsed': # Amount of time (seconds) this endpoint has been running (or ran.) + 'entity id': # Entity ID + 'jitter': # Exponential decaying average jitter calculated per RFC3393(old_jitter * + # 15/16 + new_jitter * 1/16) + 'max pdu': # The maximum write size.For Ethernet protocols, this is the entire + # Ethernet frame. For UDP, it is the UDP payload size, and for TCP, it + # just means the maximum amount of data that is written per socket + # write.In all cases, the packets on the wire will not exceed theport's + # MTU + Ethernet-Header-Size (typically 1514 for Ethernet) + 'max rate': # Maximum desired transmit rate, in bits per second (bps). + 'min pdu': # The minimum write size.For Ethernet protocols, this is the entire + # Ethernet frame. For UDP, it is the UDP payload size, and for TCP, it + # just means the maximum amount of data that is written per socket + # write.In all cases, the packets on the wire will not exceed theport's + # MTU + Ethernet-Header-Size (typically 1514 for Ethernet) + 'min rate': # Minimum desired transmit rate, in bits per second (bps). + 'mng': # Is the Endpoint managed or not? + 'name': # Endpoint's Name. + 'ooo pkts': # Total out of order packets received. Only an estimate, but never less + # than this value. + 'pattern': # Pattern of bytes this endpoint transmits. + 'pdu/s rx': # Received PDU per second.This counts the protocol reads, such as UDP + # PDUs. + 'pdu/s tx': # Transmitted PDU per second.This counts the protocol writes, such as UDP + # PDUs. + 'pps rx ll': # Estimated total received packets per second (on the wire).For TCP, this + # is an estimate.UDP and Ethernet protocols should be quite accurate on + # normal networks. + 'pps tx ll': # Estimated total transmitted packets per second (on the wire).For TCP, + # this is an estimate.UDP and Ethernet protocols should be quite accurate + # on normal networks. + 'rcv buf': # Configured/Actual values for receiving buffer size (bytes). + 'replays': # Total number of files replayed. + 'run': # Is the Endpoint is Running or not. + 'rx ber': # Received bit-errors. These are only calculated in the LANforge payload + # portion starting 28 bytes into the UDP or TCP payload. In addition, the + # bit-errors are only checked when LANforge CRCis enabled and detected to + # be invalid. If the 28-byte header is corrupted, LANforge will not + # detectit, and may also give false positives for other packet errors. + # Bit-Errors are only calculated forcertain payload patterns: Increasing, + # Decreasing, Zeros, Ones, and the PRBS patterns. + 'rx bytes': # Total received bytes count. + 'rx drop %': # Percentage of packets that should have been received by Endpoint, but + # were not, as calculated by the Cross-Connect. + 'rx dup %': # Percentage of duplicate packets, as detected by sequence numbers. + 'rx ooo %': # Percentage of packets received out of order, as detected by sequence + # numbers. + 'rx pdus': # Total received PDU count.This counts the protocol reads, such as UDP + # PDUs (aka goodput). + 'rx pkts ll': # Estimated total received packet count (on the wire).For TCP, this is an + # estimate.UDP and Ethernet protocols should be quite accurate on normal + # networks. + 'rx rate': # Real receive rate (bps) for this run.This includes only the protocol + # payload (goodput). + 'rx rate (1 min)': # Real receive rate (bps) over the last minute.This includes only the + # protocol payload (goodput). + 'rx rate (last)': # Real receive rate (bps) over the last report interval.This includes only + # the protocol payload (goodput). + 'rx rate ll': # Estimated low-level receive rate (bps) over the last minute.This + # includes any Ethernet, IP, TCP, UDP or similar headers. + 'rx wrong dev': # Total packets received on the wrong device (port). + 'script': # Endpoint script state. + 'send buf': # Configured/Actual values for sending buffer size (bytes). + 'source addr': # + 'tcp mss': # Sender's TCP-MSS (max segment size) setting.This cooresponds to the + # TCP_MAXSEGS socket option,and TCP-MSS plus 54 is the maximum packet size + # on the wirefor Ethernet frames.This is a good option to efficiently + # limit TCP packet size. + 'tcp rtx': # Total packets retransmitted by the TCP stack for this connection.These + # were likely dropped or corrupted in transit. + 'tx bytes': # Total transmitted bytes count. + 'tx pdus': # Total transmitted PDU count.This counts the protocol writes, such as UDP + # PDUs (aka goodput). + 'tx pkts ll': # Estimated total transmitted packet count (on the wire).For TCP, this is + # an estimate.UDP and Ethernet protocols should be quite accurate on + # normal networks. + 'tx rate': # Real transmit rate (bps) for this run.This includes only the protocol + # payload (goodput). + 'tx rate (1 min)': # Real transmit rate (bps) over the last minute.This includes only the + # protocol payload (goodput). + 'tx rate (last)': # Real transmit rate (bps) over the last report interval.This includes + # only the protocol payload (goodput). + 'tx rate ll': # Estimated low-level transmit rate (bps) over the last minute.This + # includes any Ethernet, IP, TCP, UDP or similar headers. + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_endp(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/endp" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="endpoint", + plural_key="endpoint") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /endsession + + + Example py-json call (it knows the URL): + record = LFJsonGet.get_endsession(eid_list=['1.234', '1.344'], + debug=True) + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_endsession(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/endsession" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="", + plural_key="") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /events/ + /events/$event_id + /events/before/$event_id + /events/between/$start_event_id/$end_event_id + /events/last/$event_count + /events/since/$event_id + + When requesting specific column names, they need to be URL encoded: + eid, entity+id, event, event+description, id, name, priority, time-stamp, + type + Example URL: /events?fields=eid,entity+id + + Example py-json call (it knows the URL): + record = LFJsonGet.get_events(eid_list=['1.234', '1.344'], + requested_col_names=['entity id'], + debug=True) + + The record returned will have these members: + { + 'eid': # Time at which this event was created.This uses the clock on the source + # machine. + 'entity id': # Entity IdentifierExact format depends on the + # type.(shelf.resource.port.endpoint.extra) + 'event': # Event Type + 'event description': # Text description for this event. + 'id': # Unique ID for this event. + 'name': # Name of the entity associated with this event. + 'priority': # Event priority. + 'time-stamp': # Time at which this event was created.This uses the clock on the source + # machine. + 'type': # Entity type. + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_events(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/events" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="alert", + plural_key="alerts") + # + """ + Below are 7 methods defined by LFClient URL Responders + """ + + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /fileio/ + /fileio/$endp_id + + When requesting specific column names, they need to be URL encoded: + buf-rd, buf-wr, bytes-rd, bytes-wr, crc+fail, eid, entity+id, files+%23, files-read, + files-wr, io+fail, max-file-sz, max-rd-bps, max-rw-sz, max-wr-bps, min-file-sz, + min-rd-bps, min-rw-sz, min-wr-bps, name, read-bps, rpt+timer, rx-bps-20s, + status, tx-bps-20s, type, write-bps + Example URL: /fileio?fields=buf-rd,buf-wr + + Example py-json call (it knows the URL): + record = LFJsonGet.get_fileio(eid_list=['1.234', '1.344'], + requested_col_names=['entity id'], + debug=True) + + The record returned will have these members: + { + 'buf-rd': # Buffer reads. When doing CRC, it takes two reads per 'packet', because + # we first read the header, then the payload. Non-CRC reads ignore the + # header. + 'buf-wr': # Buffer writes. + 'bytes-rd': # Bytes read. + 'bytes-wr': # Bytes written. + 'crc fail': # 32-bit CRC Errors detected upon READ. + 'eid': # Entity ID + 'entity id': # Entity ID + 'files #': # Number of files to write. + 'files-read': # Files read. + 'files-wr': # Files written. + 'io fail': # Amount of time in miliseconds this test has been experiencing IO + # failures. + 'max-file-sz': # Maximum configured file size (bytes). + 'max-rd-bps': # Maximum configured read rate (bps). + 'max-rw-sz': # Maximum configured size for each call to read(2) or write(2) (bytes). + 'max-wr-bps': # Maximum configured write rate (bps). + 'min-file-sz': # Minimum configured file size (bytes). + 'min-rd-bps': # Minimum configured read rate (bps). + 'min-rw-sz': # Minimum configured size for each call to read(2) or write(2) (bytes). + 'min-wr-bps': # Minimum configured write rate (bps). + 'name': # File Endpoint's Name. + 'read-bps': # File read rate for this endpoint over the duration of the test. + 'rpt timer': # Report Timer (milliseconds).This is how often the GUI will ask for + # updates from the LANforge processes.If the GUI is sluggish, increasing + # the report timers may help. + 'rx-bps-20s': # File read rate for this endpoint over the last 20 seconds. + 'status': # Current State of the connection.UninitializedHas not yet been + # started/stopped.InitializingBeing set up.StartingStarting the + # test.RunningTest is actively running.StoppedTest has been + # stopped.QuiesceTest will gracefully stop soon.HW-BYPASSTest is in + # hardware-bypass mode (WanLinks only)FTM_WAITTest wants to run, but is + # phantom, probably due to non-existent interface or resource.WAITINGWill + # restart as soon as resources are available.PHANTOMTest is stopped, and + # is phantom, probably due to non-existent interface or resource. + 'tx-bps-20s': # File write rate for this endpoint over the last 20 seconds. + 'type': # The specific type of this File Endpoint. + 'write-bps': # File write rate for this endpoint over the duration of the test. + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_fileio(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/fileio" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="endpoint", + plural_key="endpoint") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /generic/ + /generic/$endp_id + + When requesting specific column names, they need to be URL encoded: + bps+rx, bps+tx, command, dropped, eid, elapsed, entity+id, last+results, + name, pdu%2Fs+rx, pdu%2Fs+tx, rpt+timer, rpt%23, rx+bytes, rx+pkts, status, tx+bytes, + tx+pkts, type + Example URL: /generic?fields=bps+rx,bps+tx + + Example py-json call (it knows the URL): + record = LFJsonGet.get_generic(eid_list=['1.234', '1.344'], + requested_col_names=['entity id'], + debug=True) + + The record returned will have these members: + { + 'bps rx': # Receive rate reported by this endpoint. + 'bps tx': # Transmit rate reported by this endpoint. + 'command': # The command that this endpoint executes. + 'dropped': # Dropped PDUs reported by this endpoint. + 'eid': # Entity ID + 'elapsed': # Amount of time (seconds) this endpoint has been running (or ran.) + 'entity id': # Entity ID + 'last results': # Latest output from the Generic Endpoint. + 'name': # Endpoint's Name. + 'pdu/s rx': # Received packets-per-second reported by this endpoint. + 'pdu/s tx': # Transmitted packets-per-second reported by this endpoint. + 'rpt timer': # Report Timer (milliseconds).This is how often the GUI will ask for + # updates from the LANforge processes.If the GUI is sluggish, increasing + # the report timers may help. + 'rpt#': # The N_th report that we have received. (Some cmds will produce only one + # report, others will produce continuous reports.) + 'rx bytes': # Received bytes reported by this endpoint. + 'rx pkts': # Received PDUs reported by this endpoint. + 'status': # Current State of the connection.UninitializedHas not yet been + # started/stopped.InitializingBeing set up.StartingStarting the + # test.RunningTest is actively running.StoppedTest has been + # stopped.QuiesceTest will gracefully stop soon.HW-BYPASSTest is in + # hardware-bypass mode (WanLinks only)FTM_WAITTest wants to run, but is + # phantom, probably due to non-existent interface or resource.WAITINGWill + # restart as soon as resources are available.PHANTOMTest is stopped, and + # is phantom, probably due to non-existent interface or resource. + 'tx bytes': # Transmitted bytes reported by this endpoint. + 'tx pkts': # Transmitted PDUs reported by this endpoint. + 'type': # The specific type of this Generic Endpoint. + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_generic(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/generic" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="endpoint", + plural_key="endpoints") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /gui-cli/ + + + Example py-json call (it knows the URL): + record = LFJsonGet.get_gui_cli(eid_list=['1.234', '1.344'], + debug=True) + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_gui_cli(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/gui-cli" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="", + plural_key="") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /layer4/ + /layer4/$endp_id + + When requesting specific column names, they need to be URL encoded: + %21conn, acc.+denied, bad-proto, bad-url, bytes-rd, bytes-wr, dns-avg, dns-max, + dns-min, eid, elapsed, entity+id, fb-avg, fb-max, fb-min, ftp-host, ftp-port, + ftp-stor, http-p, http-r, http-t, login-denied, name, nf+%284xx%29, other-err, + read, redir, rpt+timer, rslv-h, rslv-p, rx+rate, rx+rate+%281%C2%A0min%29, status, + timeout, total-err, total-urls, tx+rate, tx+rate+%281%C2%A0min%29, type, uc-avg, + uc-max, uc-min, urls%2Fs, write # hidden columns: + rpt-time + Example URL: /layer4?fields=%21conn,acc.+denied + + Example py-json call (it knows the URL): + record = LFJsonGet.get_layer4(eid_list=['1.234', '1.344'], + requested_col_names=['entity id'], + debug=True) + + The record returned will have these members: + { + '!conn': # Could not establish connection. + 'acc. denied': # Access Access Denied Error.This could be password, user-name, + # file-permissions or other error. + 'bad-proto': # Bad protocol. + 'bad-url': # Bad URL format. + 'bytes-rd': # Bytes read. + 'bytes-wr': # Bytes written. + 'dns-avg': # Average time in milliseconds to complete resolving the DNS lookupfor the + # last 100 requests. + 'dns-max': # Maximum time in milliseconds to complete resolving the DNS lookupfor + # requests made in the last 30 seconds. + 'dns-min': # Minimum time in milliseconds to complete resolving the DNS lookupfor + # requests made in the last 30 seconds. + 'eid': # EID + 'elapsed': # Amount of time (seconds) this endpoint has been running (or ran.) + 'entity id': # Entity ID + 'fb-avg': # Average time in milliseconds for receiving the first byte of the URLfor + # the last 100 requests. + 'fb-max': # Maximum time in milliseconds for receiving the first byte of the URLfor + # requests made in the last 30 seconds. + 'fb-min': # Minimum time in milliseconds for receiving the first byte of the URLfor + # requests made in the last 30 seconds. + 'ftp-host': # FTP HOST Error + 'ftp-port': # FTP PORT Error. + 'ftp-stor': # FTP STOR Error. + 'http-p': # HTTP Post error. + 'http-r': # HTTP RANGE error. + 'http-t': # HTTP PORT Error. + 'login-denied': # Login attempt was denied.Probable cause is user-name or password errors. + 'name': # Endpoint's Name. + 'nf (4xx)': # File not found.For HTTP, an HTTP 4XX error was returned. This is only + # counted when the endpoint has 'Enable 4XX' selected.Includes 403 + # permission denied and 404 not found errors.For other protocols, it + # should be returned any time a file is not found. + 'other-err': # Error not otherwise specified. The actual error code may be found + # inl4helper logs. Contact support if you see these errors:we would like + # to account for all possible errors. + 'read': # Error attempting to read file or URL. + 'redir': # Noticed redirect loop! + 'rpt timer': # Cross Connect's Report Timer (milliseconds).This is how often the GUI + # will ask for updates from the LANforge processes.If the GUI is sluggish, + # increasing the report timers may help. + 'rslv-h': # Couldn't resolve host. + 'rslv-p': # Couldn't resolve Proxy. + 'rx rate': # Payload receive rate (bps). + 'rx rate (1 min)': # Payload receive rate over the last minute (bps). + 'status': # Current State of the connection.UninitializedHas not yet been + # started/stopped.InitializingBeing set up.StartingStarting the + # test.RunningTest is actively running.StoppedTest has been + # stopped.QuiesceTest will gracefully stop soon.HW-BYPASSTest is in + # hardware-bypass mode (WanLinks only)FTM_WAITTest wants to run, but is + # phantom, probably due to non-existent interface or resource.WAITINGWill + # restart as soon as resources are available.PHANTOMTest is stopped, and + # is phantom, probably due to non-existent interface or resource. + 'timeout': # Operation timed out. + 'total-err': # Total Errors. + 'total-urls': # URLs processed. + 'tx rate': # Payload transmit rate (bps). + 'tx rate (1 min)': # Payload transmit rate over the last minute (bps). + 'type': # The specific type of this Layer 4-7 Endpoint. + 'uc-avg': # Average time in milliseconds to complete processing of the URLfor the + # last 100 requests. + 'uc-max': # Maximum time in milliseconds to complete processing of the URLfor + # requests made in the last 30 seconds. + 'uc-min': # Minimum time in milliseconds to complete processing of the URLfor + # requests made in the last 30 seconds. + 'urls/s': # URLs processed per second over the last minute. + 'write': # Error attempting to write file or URL. + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_layer4(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/layer4" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="endpoint", + plural_key="endpoint") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /newsession + + + Example py-json call (it knows the URL): + record = LFJsonGet.get_newsession(eid_list=['1.234', '1.344'], + debug=True) + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_newsession(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/newsession" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="", + plural_key="") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /port/ + /port/$shelf_id + /port/$shelf_id/$resource_id + /port/$shelf_id/$resource_id/$port_id + /portprobe/ + /portprobe/$shelf_id/$resource_id/$port_id + /ports/ + /ports/$shelf_id + /ports/$shelf_id/$resource_id + /ports/$shelf_id/$resource_id/$port_id + + When requesting specific column names, they need to be URL encoded: + 4way+time+%28us%29, activity, alias, anqp+time+%28us%29, ap, beacon, bps+rx, bps+rx+ll, + bps+tx, bps+tx+ll, bytes+rx+ll, bytes+tx+ll, channel, collisions, connections, + crypt, cx+ago, cx+time+%28us%29, device, dhcp+%28ms%29, down, entity+id, gateway+ip, + ip, ipv6+address, ipv6+gateway, key%2Fphrase, login-fail, login-ok, logout-fail, + logout-ok, mac, mask, misc, mode, mtu, no+cx+%28us%29, noise, parent+dev, phantom, + port, port+type, pps+rx, pps+tx, qlen, reset, retry+failed, rx+bytes, rx+crc, + rx+drop, rx+errors, rx+fifo, rx+frame, rx+length, rx+miss, rx+over, rx+pkts, + rx-rate, sec, signal, ssid, status, time-stamp, tx+abort, tx+bytes, tx+crr, + tx+errors, tx+fifo, tx+hb, tx+pkts, tx+wind, tx-failed+%25, tx-rate, wifi+retries, + # hidden columns: + beacon_rx_signal, port_cur_flags_h, port_cur_flags_l, port_supported_flags_h, + port_supported_flags_l, resource, rx_multicast, tx_dropped + Example URL: /port?fields=4way+time+%28us%29,activity + + Example py-json call (it knows the URL): + record = LFJsonGet.get_port(eid_list=['1.234', '1.344'], + requested_col_names=['entity id'], + debug=True) + + The record returned will have these members: + { + '4way time (us)': # TIme (in micro-seconds) it took to complete the last WiFi 4-way + # authentication. + 'activity': # Percent of the channel that is utilized over the last minute.This + # includes locally generated traffic as well as anyother systems active on + # this channel.This is a per-radio value. + 'alias': # User-specified alias for this Port. + 'anqp time (us)': # Time (in micro-seconds) it took to complete the last WiFi ANQP + # request/response session. + 'ap': # BSSID of AP for connected stations. + 'beacon': # Number of Wireless beacons from Cell or AP that have been missed. + 'bps rx': # Average bits per second received for the last 30 seconds. + 'bps rx ll': # Bits per second received, including low-level framing (Ethernet Only). + 'bps tx': # Average bits per second transmitted for the last 30 seconds. + 'bps tx ll': # Bits per second transmitted, including low-level framing (Ethernet + # Only). + 'bytes rx ll': # Bytes received, including low-level framing (Ethernet Only). + 'bytes tx ll': # Bytes transmitted, including low-level framing (Ethernet Only). + 'channel': # Channel at the device is currently on, if known. + 'collisions': # Total number of collisions reported by this Interface.For WiFi devices, + # this is number of re-transmit attempts. + 'connections': # Number of wireless connections completed. + 'crypt': # Number of Wireless packets dropped due to inability to decrypt. + 'cx ago': # How long ago was the last WiFi connection attempt started?This relates + # only to the network interface, not any higher level protocol traffic + # upon it. + 'cx time (us)': # Time (in micro-seconds) it took to complete the last WiFi connection to + # the AP. + 'device': # Ethernet device name, as seen by the kernel. + 'dhcp (ms)': # Time (in miliseconds) it took to acquire DHCP lease,or to time out while + # trying to acquire lease. + 'down': # The interface is configured DOWN. It must be configured UP to be in + # active use. + 'entity id': # Entity ID + 'gateway ip': # Default Router/Gateway IP for the Interface. + 'ip': # IP Address of the Interface. + 'ipv6 address': # IPv6 Address for this interface. If global-scope address exists, it + # will be displayed,otherwise link-local will be displayed. + 'ipv6 gateway': # IPv6 default gateway. + 'key/phrase': # WEP Key or WPA Phrase (if enabled). + 'login-fail': # The 'ifup-post' script reported failure. This is usually used for WiFi + # portallogins, but may be customized by the user for other needs. + 'login-ok': # The 'ifup-post' script reported OK. This is usually used for WiFi + # portallogins, but may be customized by the user for other needs. + 'logout-fail': # The 'ifup-post --logout' script reported failure. This is usually used + # for WiFi portallogouts, but may be customized by the user for other + # needs. + 'logout-ok': # The 'ifup-post --logout' script reported OK. This is usually used for + # WiFi portallogouts, but may be customized by the user for other needs. + 'mac': # Ethernet MAC address of the Interface. + 'mask': # IP Mask of the Interface. + 'misc': # Number of Wireless packets dropped on receive due to unspecified + # reasons. + 'mode': # Wireless radio mode (802.11a/b/g). + 'mtu': # MTU (Maximum Transmit Unit) size, in bytes. + 'no cx (us)': # How long was the WiFi disconnect duration for the last disconnection? + 'noise': # Wireless noise level. + 'parent dev': # Parent device or port of this port. Blank if this device is not a child + # of another device or port. + 'phantom': # Is the port PHANTOM (no hardware found) or not. + 'port': # Entity ID + 'port type': # Ports can be Ethernet, Radio, vAP, vSTA, Redirect, or Bridges + 'pps rx': # Average packets per second received for the last 30 seconds. + 'pps tx': # Average packets per second transmitted for the last 30 seconds. + 'qlen': # "Transmit Queue Length for this Interface. + 'reset': # Current Reset-State. + 'retry failed': # Number of Wireless packets that the interface failed to send due to + # excessive retries. + 'rx bytes': # Total number of bytes received by this Interface. + 'rx crc': # Total number of packets dropped because of a bad CRC/FCS. + 'rx drop': # Total number of dropped packets on recieve. Usually means driver/kernel + # is being over-worked. + 'rx errors': # Total number of all types of Receive Errors. + 'rx fifo': # Total number of packets dropped because driver/kernel queues are full. + 'rx frame': # Total number of packets dropped because of framing errors at the + # physical layer. + 'rx length': # Total number of packets dropped because their length was invalid. + 'rx miss': # Total number of packets dropped because of a missed interrupt. + 'rx over': # Total number of packets dropped because of framing errors at the + # physical layer. + 'rx pkts': # Total number of packets received by this Interface. + 'rx-rate': # Reported network device RX link speed. + 'sec': # Number of secondary IP addresses configured or detected. + 'signal': # Wireless signal strength (RSSI). + 'ssid': # WiFi SSID identifier.Use [BLANK] for empty SSID, which means use any + # available SSID when associating. + 'status': # Wireless link status. + 'time-stamp': # Time-Stamp + 'tx abort': # Total packets dropped on transmit because of driver abort. + 'tx bytes': # Total number of bytes sent by this Interface. + 'tx crr': # Total packets dropped on transmit because of carrier error. + 'tx errors': # Total number of all types of Transmit Errors. + 'tx fifo': # Total packets dropped on transmit because outgoing queue was full. + 'tx hb': # Total packets dropped on transmit because of transceiver heartbeat + # errors. + 'tx pkts': # Total number of packets sent by this Interface. + 'tx wind': # Total number dropped on transmit because of Out-of-Window collision. + 'tx-failed %': # Percentage of transmitted Wireless packets that were not ACKed.They + # might have succeeded on retry. + 'tx-rate': # Reported network device TX link speed. + 'wifi retries': # Number of Wireless packets that the wifi radio retried.One packet may be + # tried multiple times and each try would be counted in this stat.Not all + # radios can properly report this statistic. + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_port(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/port" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="interface", + plural_key="interfaces") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /probe/ + /probe/$shelf_id/$resource_id/$port_id + + When requesting specific column names, they need to be URL encoded: + entity+id, probe+results + Example URL: /probe?fields=entity+id,probe+results + + Example py-json call (it knows the URL): + record = LFJsonGet.get_probe(eid_list=['1.234', '1.344'], + requested_col_names=['probe results'], + debug=True) + + The record returned will have these members: + { + 'entity id': # Entity ID + 'probe results': # Probe the low level information about the port. + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_probe(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/probe" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="probe-results", + plural_key="probe-results") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /quit + + + Example py-json call (it knows the URL): + record = LFJsonGet.get_quit(eid_list=['1.234', '1.344'], + debug=True) + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_quit(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/quit" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="", + plural_key="") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /radiostatus/ + /radiostatus/$eid + /radiostatus/$shelf_id/$resource_id/$port_id + + When requesting specific column names, they need to be URL encoded: + _links, antenna, ap, capabilities, channel, country, driver, entity+id, firmware+version, + frag, frequency, max_sta, max_vap, max_vifs, monitors_down, monitors_up, + phantom, port, resource, rts, stations_down, stations_up, tx-power, vaps_down, + vaps_up, verbose+debug + Example URL: /radiostatus?fields=_links,antenna + + Example py-json call (it knows the URL): + record = LFJsonGet.get_radiostatus(eid_list=['1.234', '1.344'], + requested_col_names=['firmware version'], + debug=True) + + The record returned will have these members: + { + '_links': # - + 'antenna': # - + 'ap': # - + 'capabilities': # - + 'channel': # - + 'country': # - + 'driver': # - + 'entity id': # - + 'firmware version': # - + 'frag': # - + 'frequency': # - + 'max_sta': # - + 'max_vap': # - + 'max_vifs': # - + 'monitors_down': # - + 'monitors_up': # - + 'phantom': # - + 'port': # - + 'resource': # - + 'rts': # - + 'stations_down': # - + 'stations_up': # - + 'tx-power': # - + 'vaps_down': # - + 'vaps_up': # - + 'verbose debug': # - + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_radiostatus(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/radiostatus" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="radio", + plural_key="radios") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /resource/ + /resource/$shelf_id + /resource/$shelf_id/$resource_id + + When requesting specific column names, they need to be URL encoded: + bps-rx-3s, bps-tx-3s, cli-port, cpu, ctrl-ip, ctrl-port, eid, entity+id, + free+mem, free+swap, gps, hostname, hw+version, load, max+if-up, max+staged, + mem, phantom, ports, rx+bytes, shelf, sta+up, sw+version, swap, tx+bytes, + # hidden columns: + timestamp + Example URL: /resource?fields=bps-rx-3s,bps-tx-3s + + Example py-json call (it knows the URL): + record = LFJsonGet.get_resource(eid_list=['1.234', '1.344'], + requested_col_names=['entity id'], + debug=True) + + The record returned will have these members: + { + 'bps-rx-3s': # Rate in bits-per-second that the manager issending management data to + # the resource, averaged over the last 3 seconds.This is TCP payload data, + # and does not count the IP and Ethernet overhead. + 'bps-tx-3s': # Rate in bits-per-second that the manager isreceiving management data + # from the resource, averaged over the last 3 seconds.This is TCP payload + # data, and does not count the IP and Ethernet overhead. + 'cli-port': # Text (telnet) interface IP Port. + 'cpu': # CPU information for the machine. + 'ctrl-ip': # IP Address of the Control Interface. + 'ctrl-port': # Binary interface IP Port. + 'eid': # Resource EID (Shelf.Resource). + 'entity id': # Entity ID + 'free mem': # Free Memory (Kbytes) in the machine. If this is too low, performance + # will be degraded. + 'free swap': # Free Swap (Kbytes) in the machine. If this is too low, performance will + # be degraded. + 'gps': # GPS Info for this machine, if GPS is attached. + 'hostname': # The name for this resource, as reported by the resource. + 'hw version': # Hardware version on the machine. + 'load': # Unix process load.. + 'max if-up': # Max number of interface-config scripts try to run at once. + 'max staged': # Max number of interfaces the system will try to bringup at once. + 'mem': # Total memory (Kbytes) on the machine. + 'phantom': # Is the resource PHANTOM (undiscovered) or not. + 'ports': # All real and phantom ports on this machine. + 'rx bytes': # Total management TCP payload bytes received from the manager process by + # this resource. + 'shelf': # Number of shelf that this resource belongs to. + 'sta up': # Max number of stations to bring up per radio per 0.25s tick. + 'sw version': # LANforge Software version running on the machine. + 'swap': # Total swap space (Kbytes) on the machine. + 'tx bytes': # Total management TCP payload bytes sent from this resource to the + # manager process. + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_resource(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/resource" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="resource", + plural_key="resources") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /scan-results/ + /scan-results/$shelf_id/$resource_id/$port_id + /scan-results/$shelf_id/$resource_id/$port_id/$bssid + /scan/ + /scan/$shelf_id/$resource_id/$port_id + /scan/$shelf_id/$resource_id/$port_id/$bssid + /scanresults/ + /scanresults/$shelf_id/$resource_id/$port_id + /scanresults/$shelf_id/$resource_id/$port_id/$bssid + + + Example py-json call (it knows the URL): + record = LFJsonGet.get_scan(eid_list=['1.234', '1.344'], + debug=True) + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_scan(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/scan" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="scan-results", + plural_key="scan-results") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /stations/ + /stations/$mac + + When requesting specific column names, they need to be URL encoded: + ap, auth-for, capabilities, entity+id, idle, roam-duration, rx+bytes, rx+pkts, + rx+rate, signal, station+bssid, tx+bytes, tx+pkts, tx+rate, tx+retries, tx-failed, + + Example URL: /stations?fields=ap,auth-for + + Example py-json call (it knows the URL): + record = LFJsonGet.get_stations(eid_list=['1.234', '1.344'], + requested_col_names=['entity id'], + debug=True) + + The record returned will have these members: + { + 'ap': # The Port that owns this station. + 'auth-for': # Duration in seconds this station has been authenticated. + 'capabilities': # Station's negotiated capabilities. + 'entity id': # Entity ID + 'idle': # Miliseconds since this station last received a frame from the peer. + 'roam-duration': # The difference between the authenticate-time on the new APand the last + # frame received on old AP, in milliseconds.It is not always possible to + # compute this accurately,especially if traffic is not flowing during the + # roam. + 'rx bytes': # RX Byte counter for this station. + 'rx pkts': # RX Packets counter for this station. + 'rx rate': # Station last received encoding rate. + 'signal': # Station signal quality. + 'station bssid': # Station's MAC address (BSSID). + 'tx bytes': # TX Byte counter for this station. + 'tx pkts': # TX Packets counter for this station. + 'tx rate': # Station transmit encoding rate. + 'tx retries': # TX Retries counter for this station.This counts retries at the driver + # level.Retries made by the WiFi hardware and/or firmware is not counted. + 'tx-failed': # TX Failed counter for this station.This counts TX failures at the driver + # level.The hardware and/or firmware may have made several failed attempts + # that are not included in this counter. + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_stations(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/stations" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="station", + plural_key="stations") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /status-msg/ + /status-msg/$session + /status-msg/$session/$id + /status-msg/$session/$id/ws-msg,... + /status-msg/$session/all + /status-msg/$session/this + /status-msg/sessions + + + Example py-json call (it knows the URL): + record = LFJsonGet.get_status_msg(eid_list=['1.234', '1.344'], + debug=True) + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_status_msg(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/status-msg" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="sessions/messages", + plural_key="sessions/messages") + # + """ + Below are 3 methods defined by LFClient URL Responders + """ + + def status_msg_new_session(self, + session : str = None, + debug : bool = False, + wait_sec : float = None, + request_timeout_sec : float = None, + max_timeout_sec : float = None, + errors_warnings : list = None): + """ + Add a status message + :param [R]session: session ID [R] + """ + response = self.json_put(url="/status-msg/{session}".format(session=session), + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=request_timeout_sec, + max_timeout_sec=max_timeout_sec, + errors_warnings=errors_warnings) + if not response: + return None + return response + + def status_msg_delete_session(self, + session : str = None, + debug : bool = False, + wait_sec : float = None, + request_timeout_sec : float = None, + max_timeout_sec : float = None, + errors_warnings : list = None): + """ + Delete a status-msg session + :param session: id to delete + """ + response = self.json_delete(url="/status-msg/{session}".format(session=session), + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=request_timeout_sec, + max_timeout_sec=max_timeout_sec, + errors_warnings=errors_warnings) + if not response: + return None + return response + + def status_msg_delete_message(self, + session : str = None, + key : str = None, + debug : bool = False, + wait_sec : float = None, + request_timeout_sec : float = None, + max_timeout_sec : float = None, + errors_warnings : list = None): + """ + Delete a status message + :param session: session ID + :param key: item ID + """ + response = self.json_delete(url="/status-msg/{session}/{key}".format(session=session, key=key), + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=request_timeout_sec, + max_timeout_sec=max_timeout_sec, + errors_warnings=errors_warnings) + if not response: + return None + return response + + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /test-group/ + /test-group/$id + /test-groups/ + /test-groups/$id + + When requesting specific column names, they need to be URL encoded: + cross+connects, entity+id, name, run, script + Example URL: /test-group?fields=cross+connects,entity+id + + Example py-json call (it knows the URL): + record = LFJsonGet.get_test_group(eid_list=['1.234', '1.344'], + requested_col_names=['entity id'], + debug=True) + + The record returned will have these members: + { + 'cross connects': # List of Test Manager's Cross-Connects. + 'entity id': # Entity ID + 'name': # Test Group's Name. + 'run': # Is Test Group running or not. + 'script': # Endpoint script state. + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_test_group(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/test-group" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="groups", + plural_key="groups") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /text/ + /text/$group + /text/$group/$class + /text/$group/$class/$key + + When requesting specific column names, they need to be URL encoded: + eid, name, text, type + Example URL: /text?fields=eid,name + + Example py-json call (it knows the URL): + record = LFJsonGet.get_text(eid_list=['1.234', '1.344'], + requested_col_names=['text'], + debug=True) + + The record returned will have these members: + { + 'eid': # - + 'name': # - + 'text': # - + 'type': # - + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_text(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/text" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="record", + plural_key="records") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /voip-endp/ + /voip-endp/$endp_id + /voip-ep/ + /voip-ep/$endp_id + /voip/ + /voip/$cx_id + /voip_endp/ + /voip_endp/$endp_id + /voip_ep/ + /voip_ep/$endp_id + + When requesting specific column names, they need to be URL encoded: + bps+rx+a, bps+rx+b, delay+a+%E2%86%90+b, delay+a+%E2%86%92+b, eid, endpoints+%28a%C2%A0%E2%86%94%C2%A0b%29, + entity+id, jitter+a+%E2%86%90+b, jitter+a+%E2%86%92+b, name, pkt+tx+a%C2%A0%E2%86%90%C2%A0b, + pkt+tx+a%C2%A0%E2%86%92%C2%A0b, rpt+timer, rx+drop+%25+a, rx+drop+%25+b, state, + type + Example URL: /voip?fields=bps+rx+a,bps+rx+b + + Example py-json call (it knows the URL): + record = LFJsonGet.get_voip(eid_list=['1.234', '1.344'], + requested_col_names=['entity id'], + debug=True) + + The record returned will have these members: + { + 'bps rx a': # Endpoint B's real transmit rate (bps).Measured at the CX Type layer. + 'bps rx b': # Endpoint A's real transmit rate (bps).Measured at the CX Type layer. + 'delay a ← b': # Average Latency in milliseconds for traffic from Endpoint B to Endpoint + # A + 'delay a → b': # Average Latency in milliseconds for traffic from Endpoint A to Endpoint + # B + 'eid': # Entity ID + 'endpoints (a ↔ b)': # Endpoints that make up this Cross Connect. + 'entity id': # Entity ID + 'jitter a ← b': # Average Jitter in milliseconds for traffic from Endpoint B to Endpoint A + 'jitter a → b': # Average Jitter in milliseconds for traffic from Endpoint A to Endpoint B + 'name': # Cross Connect's Name. + 'pkt tx a ← b': # Endpoint B's Packets Transmitted. + 'pkt tx a → b': # Endpoint A's Packets Transmitted. + 'rpt timer': # Cross Connect's Report Timer (milliseconds).This is how often the GUI + # will ask for updates from the LANforge processes.If the GUI is sluggish, + # increasing the report timers may help. + 'rx drop % a': # Endpoint A percentage packet loss.Calculated using the number of PDUs + # Endpoint B sent minus the number Endpoint A received.This number is not + # 100% correct as long as packets are in flight.After a Quiesce of the + # test, the number should be perfectly accurate. + 'rx drop % b': # Endpoint B percentage packet loss.Calculated using the number of PDUs + # Endpoint A sent minus the number Endpoint B received.This number is not + # 100% correct as long as packets are in flight.After a Quiesce of the + # test, the number should be perfectly accurate. + 'state': # Current State of the connection.UninitializedHas not yet been + # started/stopped.InitializingBeing set up.StartingStarting the + # test.RunningTest is actively running.StoppedTest has been + # stopped.QuiesceTest will gracefully stop soon.HW-BYPASSTest is in + # hardware-bypass mode (WanLinks only)FTM_WAITTest wants to run, but is + # phantom, probably due to non-existent interface or resource.WAITINGWill + # restart as soon as resources are available.PHANTOMTest is stopped, and + # is phantom, probably due to non-existent interface or resource. + 'type': # Cross-Connect type. + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_voip(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/voip" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="connection", + plural_key="connections") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /voip-endp/ + /voip-endp/$endp_id + + When requesting specific column names, they need to be URL encoded: + calls+answered, calls+attempted, calls+completed, calls+failed, cf+404, cf+408, + cf+busy, cf+canceled, delay, destination+addr, dropped, dup+pkts, eid, elapsed, + entity+id, jb+cur, jb+over, jb+silence, jb+under, jitter, mng, name, ooo+pkts, + pesq, pesq+bklg, pesq%23, reg+state, rst, rtp+rtt, run, rx+bytes, rx+pkts, + source+addr, state, tx+bytes, tx+pkts, vad+pkts + Example URL: /voip-endp?fields=calls+answered,calls+attempted + + Example py-json call (it knows the URL): + record = LFJsonGet.get_voip_endp(eid_list=['1.234', '1.344'], + requested_col_names=['entity id'], + debug=True) + + The record returned will have these members: + { + 'calls answered': # Number of calls that where the remote answered + 'calls attempted': # Number of calls that have been attempted + 'calls completed': # Number of calls that have been successfully completed + 'calls failed': # Number of calls that did not succeed for any reason. + 'cf 404': # Number of calls failed for '404': callee not found. + 'cf 408': # Number of calls failed for '408': callee did not answer. + 'cf busy': # Number of calls failed because callee is busy. + 'cf canceled': # Number of calls failed because they were canceled. + 'delay': # Average latency in milliseconds for packets received by this endpoint. + 'destination addr': # Destination Address (MAC, ip/port, VoIP destination). + 'dropped': # Total dropped packets, as identified by gaps in RTP sequence numbers + # (pre jitter buffer). + 'dup pkts': # Total duplicate packets, as identified by RTP sequence numbers (pre + # jitter buffer). + 'eid': # Entity ID + 'elapsed': # Amount of time (seconds) this endpoint has been running (or ran.) + 'entity id': # Entity ID + 'jb cur': # Current number of packets in the jitter buffer waiting to be played / + # Jitter Buffer Size. + 'jb over': # Total times the jitter buffer was given more packets than it could hold. + 'jb silence': # Silence is played when there is no valid voice packet, due to drop, or + # reorder/jitter/latency out of range of the jitter buffer. + 'jb under': # Total times the reader asked for a packet to play but the jitter buffer + # was empty. + 'jitter': # Average interpacket variation, calculated per RFC 1889 A.8. + 'mng': # Is the Endpoint managed or not? + 'name': # Endpoint's Name. + 'ooo pkts': # Total out-of-order packets, as identified by RTP sequence numbers (pre + # jitter buffer). + 'pesq': # PESQ Report score for the PESQ report number (PESQ#). + 'pesq bklg': # PESQ server call processing backlog. + 'pesq#': # The pesq-report-number to which the PESQ value cooresponds. + 'reg state': # Current State of the Endpoint. + 'rst': # How many times has the endpoint been restarted due to abnormal + # termination. + 'rtp rtt': # Round trip latency as reported by RTCP + 'run': # Is the Endpoint is Running or not. + 'rx bytes': # Total received bytes count. + 'rx pkts': # Total received packet count. + 'source addr': # Source Address (MAC, ip/port, VoIP source). + 'state': # Phone registration state + 'tx bytes': # Total transmitted bytes count. + 'tx pkts': # Total transmitted packet count. + 'vad pkts': # Total VAD (Silence Suppression) packets suppressed before transmit. + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_voip_endp(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/voip-endp" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="endpoint", + plural_key="endpoints") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /vr-cx/ + /vr-cx/$shelf_id/$resource_id/$port_id + /vr/ + /vr/$shelf_id/$resource_id + /vrcx/ + /vrcx/$shelf_id/$resource_id/$port_id + + When requesting specific column names, they need to be URL encoded: + active+ipv6+router, bgp+4byte+as, bgp+damping, bgp+peers, cluster+id, collision+domain+id, + confederation+id, damping+half+life, damping+max+suppress, damping+reuse, + damping+suppress, entity+id, height, ipv6+radv, is+bgp+reflector, local+as, + multicast+routing, name, netsmith-state, notes, pad, ripv2, router+connections, + router+id, router+id, use+confederation, use+existing+cfg, use+ospf, use+rip+dft+route, + using+bgp, using+olsr, width, x, xorp+sha, y + Example URL: /vr?fields=active+ipv6+router,bgp+4byte+as + + Example py-json call (it knows the URL): + record = LFJsonGet.get_vr(eid_list=['1.234', '1.344'], + requested_col_names=['netsmith-state'], + debug=True) + + The record returned will have these members: + { + 'active ipv6 router': # - + 'bgp 4byte as': # - + 'bgp damping': # lc_key > lc_col_name- + 'bgp peers': # - + 'cluster id': # - + 'collision domain id': # - + 'confederation id': # - + 'damping half life': # - + 'damping max suppress': # - + 'damping reuse': # - + 'damping suppress': # - + 'entity id': # Entity ID + 'height': # - + 'ipv6 radv': # - + 'is bgp reflector': # - + 'local as': # - + 'multicast routing': # - + 'name': # Name + 'netsmith-state': # - + 'notes': # - + 'pad': # - + 'ripv2': # - + 'router connections': # - + 'router id': # - + 'router id': # - + 'use confederation ': # - + 'use existing cfg': # - + 'use ospf': # - + 'use rip dft route': # - + 'using bgp': # - + 'using olsr': # - + 'width': # - + 'x': # - + 'xorp sha': # - + 'y': # - + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_vr(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/vr" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="virtual-routers", + plural_key="virtual-routers") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /vrcx/ + /vrcx/$shelf_id/$resource_id/$port_id + + When requesting specific column names, they need to be URL encoded: + entity+id, height, interface+cost, local-a, local-b, netsmith-state, remote-a, + remote-b, resource, rip+metric, vrrp+id, vrrp+interval, vrrp+ip, vrrp+ip-prefix, + vrrp+priority, wan+link, width, x, y + Example URL: /vrcx?fields=entity+id,height + + Example py-json call (it knows the URL): + record = LFJsonGet.get_vrcx(eid_list=['1.234', '1.344'], + requested_col_names=['netsmith-state'], + debug=True) + + The record returned will have these members: + { + 'entity id': # - + 'height': # - + 'interface cost': # - + 'local-a': # - + 'local-b': # - + 'netsmith-state': # - + 'remote-a': # - + 'remote-b': # - + 'resource': # - + 'rip metric': # - + 'vrrp id': # - + 'vrrp interval': # - + 'vrrp ip': # - + 'vrrp ip-prefix': # - + 'vrrp priority': # - + 'wan link': # - + 'width': # - + 'x': # - + 'y': # - + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_vrcx(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/vrcx" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="router-connections", + plural_key="router-connections") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /wl-endp/ + /wl-endp/$wl_ep_id + /wl-ep/ + /wl-ep/$wl_ep_id + /wl/ + /wl/$wl_id + /wl_endp/ + /wl_endp/$wl_ep_id + /wl_ep/ + /wl_ep/$wl_ep_id + /wlendp/$wl_ep_id + + When requesting specific column names, they need to be URL encoded: + bps+rx+a, bps+rx+b, eid, endpoints+%28a%C2%A0%E2%86%94%C2%A0b%29, entity+id, k-m, + name, pkt+tx+a%C2%A0%E2%86%90%C2%A0b, pkt+tx+a%C2%A0%E2%86%92%C2%A0b, rpt+timer, + state + Example URL: /wl?fields=bps+rx+a,bps+rx+b + + Example py-json call (it knows the URL): + record = LFJsonGet.get_wl(eid_list=['1.234', '1.344'], + requested_col_names=['entity id'], + debug=True) + + The record returned will have these members: + { + 'bps rx a': # Endpoint B's Max transmit rate (bps). + 'bps rx b': # Endpoint A's Max transmit rate (bps). + 'eid': # Entity ID + 'endpoints (a ↔ b)': # Endpoints that make up this WanLink. + 'entity id': # Entity ID + 'k-m': # Whether the WanLink is Kernel-Mode or not. + 'name': # WanLink's Name. + 'pkt tx a ← b': # Packets received on endpoint B and transmitted out endpoint A. + 'pkt tx a → b': # Packets received on endpoint A and transmitted out endpoint B. + 'rpt timer': # Cross Connect's Report Timer (milliseconds).This is how often the GUI + # will ask for updates from the LANforge processes.If the GUI is sluggish, + # increasing the report timers may help. + 'state': # Current State of the connection.UninitializedHas not yet been + # started/stopped.InitializingBeing set up.StartingStarting the + # test.RunningTest is actively running.StoppedTest has been + # stopped.QuiesceTest will gracefully stop soon.HW-BYPASSTest is in + # hardware-bypass mode (WanLinks only)FTM_WAITTest wants to run, but is + # phantom, probably due to non-existent interface or resource.WAITINGWill + # restart as soon as resources are available.PHANTOMTest is stopped, and + # is phantom, probably due to non-existent interface or resource. + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_wl(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/wl" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="", + plural_key="") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /wl-endp/ + /wl-endp/$wl_ep_id + + When requesting specific column names, they need to be URL encoded: + buffer, corrupt+1, corrupt+2, corrupt+3, corrupt+4, corrupt+5, corrupt+6, + delay, dropfreq+%25, dropped, dup+pkts, dupfreq+%25, eid, elapsed, extrabuf, + failed-late, jitfreq+%25, max+rate, maxjitter, maxlate, name, ooo+pkts, qdisc, + reordfrq+%25, run, rx+bytes, rx+pkts, script, serdelay, tx+bytes, tx+drop+%25, + tx+pkts, tx+rate, tx-failed, wps + Example URL: /wl-endp?fields=buffer,corrupt+1 + + Example py-json call (it knows the URL): + record = LFJsonGet.get_wl_endp(eid_list=['1.234', '1.344'], + requested_col_names=['eid'], + debug=True) + + The record returned will have these members: + { + 'buffer': # Maximum size of receive buffer, in bytes.This is the sum of the amount + # needed for the transit buffers (delay * bandwidth)plus the WanLink + # "Backlog Buffer:" queue size which handles bursts. + 'corrupt 1': # Counters for how many times this corruption has been applied. + 'corrupt 2': # Counters for how many times this corruption has been applied. + 'corrupt 3': # Counters for how many times this corruption has been applied. + 'corrupt 4': # Counters for how many times this corruption has been applied. + 'corrupt 5': # Counters for how many times this corruption has been applied. + 'corrupt 6': # Counters for how many times this corruption has been applied. + 'delay': # Base induced latency on received packets, in microseconds. + 'dropfreq %': # Frequency out of 1,000,000 to drop a received packet.Select a preset + # value or enter your own. + 'dropped': # Total dropped packets on receive.This does not include the tx-failed + # counters. + 'dup pkts': # Total duplicate packets generated. + 'dupfreq %': # Frequency out of 1,000,000 to duplicate a received packet.Select a + # preset value or enter your own. + 'eid': # Entity ID + 'elapsed': # Amount of time (seconds) this endpoint has been running (or ran.) + 'extrabuf': # Size of "Backlog Buffer:" setting in WanLink configuration in bytes. + 'failed-late': # Total amount of received packets that could not be transmitted out the + # peer becausethe emulator was overloaded and could not transmit within + # the specified 'lateness' + 'jitfreq %': # Frequency out of 1,000,000 that packets should have jitter applied to + # them.Select a preset value or enter your own. + 'max rate': # Max transmit rate (bps) for this Endpoint. + 'maxjitter': # Maximum additional delay, in microseconds. See Jitter-Frequency as + # well. + 'maxlate': # The maximum lateness in milliseconds allowed before packets will be + # dropped on transmit.If lateness is configured to be automatic, this + # variable will change based onconfigured bandwidth and backlog buffer, + # but will not go below 10ms. + 'name': # Endpoint's Name. + 'ooo pkts': # Total out of order packets generated. + 'qdisc': # Queueing discipline (FIFO, WRR, etc). + 'reordfrq %': # Frequency out of 1,000,000 to re-order a received packet.Select a preset + # value or enter your own. + 'run': # Is the Endpoint is Running or not. + 'rx bytes': # Total received bytes count. + 'rx pkts': # Total received packet count. + 'script': # Endpoint script state. + 'serdelay': # Additional serialization delay for a 1514 byte packet at the configured + # speed (microseconds). + 'tx bytes': # Total transmitted bytes count. + 'tx drop %': # Packet drop percentage over the last 1 minute. + 'tx pkts': # Packets received on the peer interface and transmitted out this + # endpoint's interface. + 'tx rate': # The average speed over the last 30 seconds at which we are + # transmittingout the peer interface.This can be thought of as the actual + # transfer rate for packets entering the interfaceassociated with this + # Endpoint. + 'tx-failed': # Total amount of received packets that could not be transmitted out the + # peer.This includes any tx-failed-late packets. + 'wps': # Enable/Disable showing of WanPaths for individual endpoints. + } + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_wl_endp(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/wl-endp" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="endpoint", + plural_key="endpoint") + # + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Notes for type requests + + If you need to call the URL directly, + request one of these URLs: + /ws-msg/ + /ws-msg/$sessionid + + + Example py-json call (it knows the URL): + record = LFJsonGet.get_ws_msg(eid_list=['1.234', '1.344'], + debug=True) + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + def get_ws_msg(self, + eid_list: list = None, + requested_col_names: list = None, + wait_sec: float = 0.01, + timeout_sec: float = 5.0, + errors_warnings: list = None, + debug: bool = False): + """ + :param eid_list: list of entity IDs to query for + :param requested_col_names: list of column names to return + :param wait_sec: duration to wait between retries if no response or response is HTTP 404 + :param timeout_sec: duration in which to keep querying before returning + :param errors_warnings: optional list to extend with errors and warnings from response + :param debug: print diagnostic info if true + :return: dictionary of results + """ + debug |= self.debug_on + url = "/ws-msg" + if (eid_list is None) or (len(eid_list) < 1): + raise ValueError("no entity id in request") + trimmed_fields = [] + if isinstance(requested_col_names, str): + if not requested_col_names.strip(): + raise ValueError("column name cannot be blank") + trimmed_fields.append(requested_col_names.strip()) + if isinstance(requested_col_names, list): + for field in requested_col_names: + if not field.strip(): + raise ValueError("column names cannot be blank") + field = field.strip() + if field.find(" ") > -1: + raise ValueError("field should be URL encoded: [%s]" % field) + trimmed_fields.append(field) + url += self.create_port_eid_url(eid_list=eid_list) + + if len(trimmed_fields) > 0: + url += "?fields=%s" % (",".join(trimmed_fields)) + + response = self.json_get(url=url, + debug=debug, + wait_sec=wait_sec, + request_timeout_sec=timeout_sec, + max_timeout_sec=timeout_sec, + errors_warnings=errors_warnings) + if response is None: + return None + return self.extract_values(response=response, + singular_key="", + plural_key="") + # + + +class LFSession(BaseSession): + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + This subclass of BaseSession knows about LFJsonQuery and LFJsonCommand + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + def __init__(self, lfclient_url: str = 'http://localhost:8080', + debug: bool = False, + proxy_map: dict = None, + connection_timeout_sec: float = None, + stream_errors: bool = True, + stream_warnings: bool = False, + require_session: bool = False, + exit_on_error: bool = False): + """ + :param debug: turn on diagnostic information + :param proxy_map: a dict with addresses of proxies to route requests through. + E.G.: { 'http':'http://192.168.1.253:3128', 'https':'https://192.168.1.253:443' } + :param connection_timeout_sec: timeout in second to wait for a connect to the LANforge client (GUI) + This timeout does should not apply to long running client requests, there are individual + timeouts for those conditions, such as max_timeout_sec. + :param stream_errors: print HTTP JSON API errors to system out and logging stream + :param stream_warnings: print HTTP JSON API warnings to system out and logging stream + :param require_session: exit(1) if unable to establish a session_id + :param exit_on_error: on requests failing HTTP requests on besides error 404, + exit(1). This does not include failing to establish a session_id + """ + super().__init__(lfclient_url=lfclient_url, + debug=debug, + proxy_map=proxy_map, + connection_timeout_sec=connection_timeout_sec, + stream_errors=stream_errors, + stream_warnings=stream_warnings, + exit_on_error=exit_on_error) + self.command_instance = LFJsonCommand(session_obj=self, debug=debug, exit_on_error=exit_on_error) + self.query_instance = LFJsonQuery(session_obj=self, debug=debug, exit_on_error=exit_on_error) + self.session_connection_check = \ + self.command_instance.start_session(debug=debug, + die_without_session_id_=require_session) + if self.session_connection_check: + self.session_id = self.command_instance.session_id + self.query_instance.session_id = self.session_id + else: + self.logger.error('LFSession failed to establish session_id') + if require_session and ((not self.command_instance.session_id) or (not self.session_id)): + self.logger.error('LFSession failed to setup session_id correctly') + + def get_command(self) -> LFJsonCommand: + """ + Remember to override this method with your session subclass, it should return LFJsonCommand + :return: registered instance of JsonCommand + """ + if self.command_instance: + return self.command_instance + self.command_instance = LFJsonCommand(session_obj=self) + return self.command_instance + + def get_query(self) -> LFJsonQuery: + """ + Remember to override this method with your session subclass, it should return LFJsonQuery + :return: registered instance of JsonQuery + """ + if self.query_instance: + return self.query_instance + self.query_instance = LFJsonQuery(session_obj=self, debug=self.debug_on) + return self.query_instance diff --git a/lanforge_client/logg.py b/lanforge_client/logg.py new file mode 100644 index 00000000..d05341d9 --- /dev/null +++ b/lanforge_client/logg.py @@ -0,0 +1,259 @@ +import sys + +if sys.version_info[0] != 3: + print("This script requires Python 3") + exit() + +import logging +from logging import Logger +import time +import datetime +import inspect +# import traceback +# from typing import Optional +from pprint import pprint # pformat +from .strutil import nott # iss + +class Logg: + """ + This method presently defines various log "levels" but does not yet express + ability to log "areas" or "keywords". + + TODO: + - LOG BUFFER a list that only holds last 100 lines logged to it. This is useful + for emitting when an exception happens in a loop and you are not interested + in the first 10e6 log entries + + - KEYWORD LOGGING: pair a --debug_kw=keyword,keyword set on the command line to only + recieve log output from log statements matching those keywords + + - CLASS/METHOD/FUNCTION logging: --debug_fn=class.method,module.func set on the command + line that activates logging in the method or function listed. See inspection techniques + listed near this SO question https://stackoverflow.com/a/5104943/11014343 + + - BITWISE LOG LEVELS: --log_level=DEBUG|FILEIO|JSON|HTTP a maskable combination of enum_bitmask + names that combine to a value that can trigger logging. + + These reserved words may not be used as tags: + debug, debugging, debug_log, digest, file, gui, http, json, log, method, tag + + Protocol logging levels: + * always: X-Errors( stops script on halt_on_errors) + * timeouts: can be configured as halt level errors + - digest (POST set_port / GET /ports ) + - url (POST /cli-json/set_port / GET /port/1/2/3/?fields) + - json (POST /cli-json/set_port { a:b } ; GET /port/1/2/3?fields {results interfaces[]} + - http that plus X-Warnings and ALL headers + - gui Xtra debugging messages generated by LANforgeGUI + + + Please also consider how log messages can be formatted: + https://stackoverflow.com/a/20112491/11014343: + logging.basicConfig(format="[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s") + """ + DEFAULT_LEVEL = logging.WARNING + DefaultLogger = logging.getLogger(__name__) + method_name_list: list = [] # list[str] + tag_list: list = [] # list[str] + reserved_tags: list = [ # list[str] + "debug", + "debugging", + "debug_log", + "digest", + "file", + "gui", + "http", + "json", + "log", + "method", + "tag" + ] + + def __init__(self, + log_level: int = DEFAULT_LEVEL, + name: str = None, + filename: str = None, + debug: bool = False): + """----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + Base class that can be used to send logging messages elsewhere. extend this + in order to send log messages from this framework elsewhere. + ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----""" + + self.level = log_level + self.logger: Logger + + # self.start_time = datetime.now() # py 3.9 maybe? + self.start_time = datetime.datetime.now() # py 3.9 maybe? + self.start_time_str = time.strftime("%Y%m%d-%I:%M%:%S") + if name: + self.name = name + if "@" in name: + self.name = name.replace('@', self.start_time_str) + else: + self.name = "started-" + self.start_time_str + + self.logger = Logger(name, level=log_level) + if filename: + logging.basicConfig(filename=filename, filemode="a") + if debug: + self.logg(level=logging.WARNING, + msg="Logger {name} begun to {filename}".format(name=name, + filename=filename)) + + @classmethod + def logg(cls, + level: int = logging.WARNING, + tag: str = None, + msg: str = None) -> None: + """ + Use this *class method* to send logs to the DefaultLogger instance created when this class was created + :param level: + :param msg: + :return: + """ + if nott(msg): + return + if level == logging.CRITICAL: + cls.DefaultLogger.critical(msg) + return + if level == logging.ERROR: + cls.DefaultLogger.error(msg) + return + if level == logging.WARNING: + cls.DefaultLogger.warning(msg) + return + if level == logging.INFO: + cls.DefaultLogger.info(msg) + return + if level == logging.DEBUG: + cls.DefaultLogger.debug(msg) + return + + def by_level(self, + level: int = logging.WARNING, + msg: str = None): + """ + Use this *instance* version of the method for logging when you have a specific logger + customized for a purpose. Otherwise please use Logg.logg(). + :param level: python logging priority + :param msg: text to send to logging channel + :return: None + """ + if nott(msg): + return + + if level == logging.CRITICAL: + self.logger.critical(msg) + return + + if level == logging.ERROR: + self.logger.error(msg) + return + + if level == logging.WARNING: + self.logger.warning(msg) + return + + if level == logging.INFO: + self.logger.info(msg) + return + + if level == logging.DEBUG: + self.logger.debug(msg) + return + print("UNKNOWN: " + msg) + + def error(self, message: str = None): + if not message: + return + self.logg(level=logging.ERROR, msg=message) + + def warning(self, message: str = None): + if not message: + return + self.logg(level=logging.WARNING, msg=message) + + def info(self, message: str = None): + if not message: + return + self.logg(level=logging.INFO, msg=message) + + def debug(self, message: str = None): + if not message: + return + self.logg(level=logging.DEBUG, msg=message) + + @classmethod + def register_method_name(cls, methodname: str = None) -> None: + """ + Use this method to register names of functions you want to allow logging from + :param methodname: + :return: + """ + if not methodname: + return + cls.method_name_list.append(methodname) + if methodname not in cls.tag_list: + cls.tag_list.append(methodname) + + @classmethod + def register_tag(cls, tag: str = None) -> None: + """ + Use this method to register keywords you want to allow logging from. + There are a list of reserved tags which will not be accepted. + :return: + """ + if not tag: + return + if tag in cls.tag_list: + return + if tag in cls.reserved_tags: + cls.logg(level=logging.ERROR, + msg=f"tag [{tag}] is reserved, ignoring") + # note: add directly to tag_list to append a reserved tag + cls.tag_list.append(tag) + + @classmethod + def by_method(cls, msg: str = None) -> None: + """ + should only log if we're in the method_list + reminder: https://stackoverflow.com/a/13514318/11014343 + import inspect + import types + from typing import cast + this_fn_name = cat(types.FrameType, inspect.currentframe()).f_code.co_name + :return: None + """ + try: + caller = inspect.currentframe().f_back.f_code.co_name + + if caller in cls.method_name_list: + cls.logg(level=cls.DEFAULT_LEVEL, msg=f"[{caller}] {msg}") + + except Exception as e: + pprint(e) + pass + + @classmethod + def by_tag(cls, tag: str = None, msg: str = None) -> None: + """ + should only log if we're in the method_list + reminder: https://stackoverflow.com/a/13514318/11014343 + import inspect + import types + from typing import cast + this_fn_name = cat(types.FrameType, inspect.currentframe()).f_code.co_name + :return: + """ + if (not cls.tag_list) or (tag not in cls.tag_list): + return + + cls.logg(level=cls.DEFAULT_LEVEL, msg=f"[{tag}] {msg}") + + def enable(self, reserved_tag: str = None) -> None: + if (not reserved_tag) or (reserved_tag not in self.reserved_tags): + return + if reserved_tag in self.tag_list: + return + self.tag_list.append(reserved_tag) + diff --git a/lanforge_client/strutil.py b/lanforge_client/strutil.py new file mode 100644 index 00000000..0a9dac1b --- /dev/null +++ b/lanforge_client/strutil.py @@ -0,0 +1,20 @@ +def iss(text: str) -> bool: + """ + + :param text: string to test + :return: true if text is at lease one non-whitespace character + """ + if text is None: + return False + if (len(text) == 0) or (text.strip() == ""): + return False + return True + + +def nott(text: str) -> bool: + """ + + :param text: + :return: opposite of is + """ + return not iss(text=text) diff --git a/pipupgrade.sh b/pipupgrade.sh new file mode 100755 index 00000000..24a729eb --- /dev/null +++ b/pipupgrade.sh @@ -0,0 +1,2 @@ +#!/bin/bash +pip3 install --user -r requirements.txt --upgrade diff --git a/py-dashboard/GhostRequest.py b/py-dashboard/GhostRequest.py index ce0dc586..56a2be1e 100644 --- a/py-dashboard/GhostRequest.py +++ b/py-dashboard/GhostRequest.py @@ -29,8 +29,8 @@ RecordInflux = InfluxRequest.RecordInflux class CSVReader: - def read_csv(self, - file, + @staticmethod + def read_csv(file, sep='\t'): df = open(file).read().split('\n') rows = list() @@ -39,8 +39,8 @@ class CSVReader: rows.append(x.split(sep)) return rows - def get_column(self, - df, + @staticmethod + def get_column(df, value): index = df[0].index(value) values = [] @@ -48,7 +48,8 @@ class CSVReader: values.append(row[index]) return values - def get_columns(self, df, targets): + @staticmethod + def get_columns(df, targets): target_index = [] for item in targets: target_index.append(df[0].index(item)) @@ -60,7 +61,8 @@ class CSVReader: results.append(row_data) return results - def to_html(self, df): + @staticmethod + def to_html(df): html = '' html = html + ('' '' @@ -78,7 +80,8 @@ class CSVReader: '
') return html - def filter_df(self, df, column, expression, target): + @staticmethod + def filter_df(df, column, expression, target): target_index = df[0].index(column) counter = 0 targets = [0] @@ -98,7 +101,8 @@ class CSVReader: counter += 1 return list(map(df.__getitem__, targets)) - def concat(self, dfs): + @staticmethod + def concat(dfs): return list(itertools.chain.from_iterable(dfs)) @@ -204,7 +208,6 @@ class GhostRequest: def custom_post(self, folder, - authors, title='custom'): self.upload_images(folder) head = '''This is a custom post created via a script''' @@ -215,11 +218,9 @@ class GhostRequest: text=head) def kpi_to_ghost(self, - authors, folders, parent_folder=None, title=None, - server_pull=None, ghost_host=None, port=22, user_push=None, @@ -227,13 +228,12 @@ class GhostRequest: customer=None, testbed=None, test_run=None, - target_folders=list(), + target_folders=None, grafana_token=None, grafana_host=None, grafana_port=3000, grafana_datasource='InfluxDB', grafana_bucket=None): - global dut_hw, dut_sw, dut_model, dut_serial now = datetime.now() @@ -440,7 +440,7 @@ class GhostRequest: # create Grafana Dashboard target_files = [] for folder in target_folders: - target_file=folder.split('/')[-1] + '/kpi.csv' + target_file = folder.split('/')[-1] + '/kpi.csv' try: open(target_file) target_files.append(target_file) @@ -502,7 +502,8 @@ class GhostRequest: Influx Host: %s
Influx Port: %s
Influx Organization: %s
- Influx Bucket: %s
''' % (influx_error, self.influx_host, self.influx_port, self.influx_org, self.influx_bucket) + Influx Bucket: %s
''' % ( + influx_error, self.influx_host, self.influx_port, self.influx_org, self.influx_bucket) raw_test_tags = list() test_tag_table = '' @@ -524,8 +525,8 @@ class GhostRequest: else: column_name = column dut_table_columns += ( - '%s%s' % ( - column_name, duts[column]) + '%s%s' % + (column_name, duts[column]) ) dut_table = '= 1): + if self.requested_url.find('#') >= 1: self.requested_url = self.requested_url.replace('#', '%23') - if (self.requested_url.find(' ') >= 1): + if self.requested_url.find(' ') >= 1: self.requested_url = self.requested_url.replace(' ', '+') - if self.debug: - print("new LFRequest[%s]" % self.requested_url ) + self.logger.debug("new LFRequest[%s]" % self.requested_url) # request first url on stack def formPost(self, show_error=True, debug=False, die_on_error_=False): @@ -94,7 +95,7 @@ class LFRequest: def form_post(self, show_error=True, debug=False, die_on_error_=False): if self.die_on_error: die_on_error_ = True - if (debug == False) and (self.debug == True): + if not debug and self.debug: debug = True responses = [] urlenc_data = "" @@ -104,20 +105,17 @@ class LFRequest: opener = request.build_opener(request.ProxyHandler(self.proxies)) request.install_opener(opener) - - if (debug): - print("formPost: url: "+self.requested_url) - if ((self.post_data != None) and (self.post_data is not self.No_Data)): + self.logger.debug("formPost: url: " + self.requested_url) + if (self.post_data is not None) and (self.post_data is not self.No_Data): urlenc_data = urllib.parse.urlencode(self.post_data).encode("utf-8") - if (debug): - print("formPost: data looks like:" + str(urlenc_data)) - print("formPost: url: "+self.requested_url) + self.logger.debug("formPost: data looks like:" + str(urlenc_data)) + self.logger.debug("formPost: url: " + self.requested_url) myrequest = request.Request(url=self.requested_url, - data=urlenc_data, - headers=self.default_headers) + data=urlenc_data, + headers=self.default_headers) else: myrequest = request.Request(url=self.requested_url, headers=self.default_headers) - print("No data for this formPost?") + self.logger.error("No data for this formPost?") myrequest.headers['Content-type'] = 'application/x-www-form-urlencoded' @@ -143,15 +141,16 @@ class LFRequest: error_list_=self.error_list, debug_=debug) - if (die_on_error_ == True) or (self.die_on_error == True): + if die_on_error_ or self.die_on_error: exit(1) return None def jsonPost(self, show_error=True, debug=False, die_on_error_=False, response_json_list_=None): - return self.json_post(show_error=show_error, debug=debug, die_on_error_=die_on_error_, response_json_list_=response_json_list_) + return self.json_post(show_error=show_error, debug=debug, die_on_error_=die_on_error_, + response_json_list_=response_json_list_) def json_post(self, show_error=True, debug=False, die_on_error_=False, response_json_list_=None, method_='POST'): - if (debug == False) and (self.debug == True): + if not debug and self.debug: debug = True if self.die_on_error: die_on_error_ = True @@ -160,14 +159,14 @@ class LFRequest: opener = urllib.request.build_opener(request.ProxyHandler(self.proxies)) urllib.request.install_opener(opener) - if ((self.post_data != None) and (self.post_data is not self.No_Data)): + if (self.post_data is not None) and (self.post_data is not self.No_Data): myrequest = request.Request(url=self.requested_url, - method=method_, - data=json.dumps(self.post_data).encode("utf-8"), - headers=self.default_headers) + method=method_, + data=json.dumps(self.post_data).encode("utf-8"), + headers=self.default_headers) else: myrequest = request.Request(url=self.requested_url, headers=self.default_headers) - print("No data for this jsonPost?") + self.logger.error("No data for this jsonPost?") myrequest.headers['Content-type'] = 'application/json' @@ -176,23 +175,24 @@ class LFRequest: try: resp = urllib.request.urlopen(myrequest) resp_data = resp.read().decode('utf-8') - if (debug and die_on_error_): - print("----- LFRequest::json_post:128 debug: --------------------------------------------") - print("URL: %s :%d "% (self.requested_url, resp.status)) + if debug and die_on_error_: + self.logger.debug("----- LFRequest::json_post:128 debug: --------------------------------------------") + self.logger.debug("URL: <%s> status: %d " % (self.requested_url, resp.status)) if resp.status != 200: - LFUtils.debug_printer.pprint(resp.getheaders()) - print("----- resp_data:128 -------------------------------------------------") - print(resp_data) - print("-------------------------------------------------") + self.logger.debug(pformat(resp.getheaders())) + self.logger.debug("----- resp_data:128 -------------------------------------------------") + self.logger.debug(resp_data) + self.logger.debug("-------------------------------------------------") responses.append(resp) if response_json_list_ is not None: if type(response_json_list_) is not list: raise ValueError("reponse_json_list_ needs to be type list") j = json.loads(resp_data) if debug: - print("----- LFRequest::json_post:140 debug: --------------------------------------------") - LFUtils.debug_printer.pprint(j) - print("-------------------------------------------------") + self.logger.debug( + "----- LFRequest::json_post:140 debug: --------------------------------------------") + self.logger.debug(pformat(j)) + self.logger.debug("-------------------------------------------------") response_json_list_.append(j) return responses[0] @@ -210,39 +210,33 @@ class LFRequest: error_=uerror, debug_=debug) - if die_on_error_ == True: + if die_on_error_: exit(1) return None def json_put(self, show_error=True, debug=False, die_on_error_=False, response_json_list_=None): - return self.json_post(show_error=show_error, - debug=debug, - die_on_error_=die_on_error_, - response_json_list_=response_json_list_, - method_='PUT') + return self.json_post(show_error=show_error, + debug=debug, + die_on_error_=die_on_error_, + response_json_list_=response_json_list_, + method_='PUT') def json_delete(self, show_error=True, debug=False, die_on_error_=False, response_json_list_=None): - return self.get_as_json(debug_=debug, - die_on_error_=die_on_error_, - method_='DELETE') + return self.get_as_json(method_='DELETE') - def get(self, debug=False, die_on_error_=False, method_='GET'): - if self.debug == True: - debug = True - if self.die_on_error == True: - die_on_error_ = True - if debug: - print("LFUtils.get: url: "+self.requested_url) + def get(self, method_='GET'): + if self.debug: + self.logger.debug("LFUtils.get: url: " + self.requested_url) # https://stackoverflow.com/a/59635684/11014343 if (self.proxies is not None) and (len(self.proxies) > 0): opener = request.build_opener(request.ProxyHandler(self.proxies)) - #opener = urllib.request.build_opener(myrequest.ProxyHandler(self.proxies)) + # opener = urllib.request.build_opener(myrequest.ProxyHandler(self.proxies)) request.install_opener(opener) myrequest = request.Request(url=self.requested_url, - headers=self.default_headers, - method=method_) + headers=self.default_headers, + method=method_) myresponses = [] try: myresponses.append(request.urlopen(myrequest)) @@ -254,7 +248,7 @@ class LFRequest: responses_=myresponses, error_=error, error_list_=self.error_list, - debug_=debug) + debug_=self.debug) except urllib.error.URLError as uerror: print_diagnostics(url_=self.requested_url, @@ -262,26 +256,24 @@ class LFRequest: responses_=myresponses, error_=uerror, error_list_=self.error_list, - debug_=debug) + debug_=self.debug) - if die_on_error_ == True: + if self.die_on_error: exit(1) return None - def getAsJson(self, die_on_error_=False, debug_=False): - return self.get_as_json(die_on_error_=die_on_error_, debug_=debug_) + def getAsJson(self): + return self.get_as_json() - def get_as_json(self, die_on_error_=False, debug_=False, method_='GET'): - responses = [] - j = self.get(debug=debug_, die_on_error_=die_on_error_, method_=method_) - responses.append(j) + def get_as_json(self, method_='GET'): + responses = list() + responses.append(self.get(method_=method_)) if len(responses) < 1: - if debug_ and self.has_errors(): + if self.debug and self.has_errors(): self.print_errors() return None - if responses[0] == None: - if debug_: - print("No response from "+self.requested_url) + if responses[0] is None: + self.logger.debug("No response from " + self.requested_url) return None json_data = json.loads(responses[0].read().decode('utf-8')) return json_data @@ -298,14 +290,15 @@ class LFRequest: self.post_data = data def has_errors(self): - return (True, False)[len(self.error_list)>0] + return (True, False)[len(self.error_list) > 0] def print_errors(self): if not self.has_errors: - print("---------- no errors ----------") + self.logger.debug("---------- no errors ----------") return for err in self.error_list: - print("error: %s" % err) + self.logger.error("error: %s" % err) + def plain_get(url_=None, debug_=False, die_on_error_=False, proxies_=None): """ @@ -340,25 +333,25 @@ def plain_get(url_=None, debug_=False, die_on_error_=False, proxies_=None): error_=uerror, debug_=debug_) - if die_on_error_ == True: + if die_on_error_: exit(1) return None def print_diagnostics(url_=None, request_=None, responses_=None, error_=None, error_list_=None, debug_=False): - if debug_: - print("LFRequest::print_diagnostics: error_.__class__: %s"%error_.__class__) - LFUtils.debug_printer.pprint(error_) + logger = logging.getLogger(__name__) + # logger.error("LFRequest::print_diagnostics: error_.__class__: %s"%error_.__class__) + # logger.error(pformat(error_)) if url_ is None: - print("WARNING LFRequest::print_diagnostics: url_ is None") + logger.warning("WARNING LFRequest::print_diagnostics: url_ is None") if request_ is None: - print("WARNING LFRequest::print_diagnostics: request_ is None") + logger.warning("WARNING LFRequest::print_diagnostics: request_ is None") if error_ is None: - print("WARNING LFRequest::print_diagnostics: error_ is None") + logger.warning("WARNING LFRequest::print_diagnostics: error_ is None") method = 'NA' - if (hasattr(request_, 'method')): + if hasattr(request_, 'method'): method = request_.method err_code = 0 err_reason = 'NA' @@ -376,52 +369,52 @@ def print_diagnostics(url_=None, request_=None, responses_=None, error_=None, er if err_code == 404: xerrors.append("[%s HTTP %s] <%s> : %s" % (method, err_code, err_full_url, err_reason)) else: - if (len(err_headers) > 0): + if len(err_headers) > 0: for headername in sorted(err_headers.keys()): if headername.startswith("X-Error-"): xerrors.append("%s: %s" % (headername, err_headers.get(headername))) if len(xerrors) > 0: - print(" = = LANforge Error Messages = =") + logger.error(" = = LANforge Error Messages = =") + logger.error(" = = URL: %s" % err_full_url) for xerr in xerrors: - print(xerr) + logger.error(xerr) if (error_list_ is not None) and isinstance(error_list_, list): error_list_.append(xerr) - print(" = = = = = = = = = = = = = = = =") + logger.error(" = = = = = = = = = = = = = = = =") - if (error_.__class__ is urllib.error.HTTPError): - if debug_: - print("----- LFRequest: HTTPError: --------------------------------------------") - print("%s <%s> HTTP %s: %s" % (method, err_full_url, err_code, err_reason)) + if error_.__class__ is urllib.error.HTTPError: + logger.debug("----- LFRequest: HTTPError: --------------------------------------------") + logger.debug("%s <%s> HTTP %s: %s" % (method, err_full_url, err_code, err_reason)) if err_code == 404: if (error_list_ is not None) and isinstance(error_list_, list): error_list_.append("[%s HTTP %s] <%s> : %s" % (method, err_code, err_full_url, err_reason)) else: - if debug_: - print(" Content-type:[%s] Accept[%s]" % (request_.get_header('Content-type'), request_.get_header('Accept'))) + logger.debug( + " Content-type:[%s] Accept[%s]" % (request_.get_header('Content-type'), request_.get_header('Accept'))) if hasattr(request_, "data") and (request_.data is not None): - print(" Data:") - LFUtils.debug_printer.pprint(request_.data) + logger.debug(" Data:") + logger.debug(debug_printer.pformat(request_.data)) elif debug_: - print(" ") + logger.debug(" ") - if debug_ and (len(err_headers) > 0): + if len(err_headers) > 0: # the HTTPError is of type HTTPMessage a subclass of email.message - print(" Response Headers: ") + logger.debug(" Response Headers: ") for headername in sorted(err_headers.keys()): - print(" %s: %s" % (headername, err_headers.get(headername))) + logger.debug(" %s: %s" % (headername, err_headers.get(headername))) if len(responses_) > 0: - print("----- Response: --------------------------------------------------------") - LFUtils.debug_printer.pprint(responses_[0].reason) - if debug_: - print("------------------------------------------------------------------------") + logger.debug("----- Response: --------------------------------------------------------") + logger.debug(debug_printer.pformat(responses_[0].reason)) + + logger.debug("------------------------------------------------------------------------") return - if (error_.__class__ is urllib.error.URLError): - print("----- LFRequest: URLError: ---------------------------------------------") - print("%s <%s> HTTP %s: %s" % (method, err_full_url, err_code, err_reason)) - print("------------------------------------------------------------------------") + if error_.__class__ is urllib.error.URLError: + logger.error("----- LFRequest: URLError: ---------------------------------------------") + logger.error("%s <%s> HTTP %s: %s" % (method, err_full_url, err_code, err_reason)) + logger.error("------------------------------------------------------------------------") # ~LFRequest diff --git a/py-json/LANforge/LFUtils.py b/py-json/LANforge/LFUtils.py index e5d7bb35..75d4d7f5 100644 --- a/py-json/LANforge/LFUtils.py +++ b/py-json/LANforge/LFUtils.py @@ -12,15 +12,16 @@ from time import sleep from random import seed, randint import re import ipaddress +import logging if sys.version_info[0] != 3: print("This script requires Python 3") exit() - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../../"))) LFRequest = importlib.import_module("py-json.LANforge.LFRequest") +Logg = importlib.import_module("lanforge_client.logg") # .Logg debug_printer = pprint.PrettyPrinter(indent=2) @@ -30,7 +31,8 @@ ADD_STA_FLAGS_DOWN_WPA2 = 68719477760 REPORT_TIMER_MS_FAST = 1500 REPORT_TIMER_MS_SLOW = 3000 -#Used for Speed + +# Used for Speed def parse_size_bps(size_val): if isinstance(size_val, str): size_val.upper() @@ -52,7 +54,8 @@ def parse_size_bps(size_val): else: return size_val -#Used for Size of file + +# Used for Size of file def parse_size(size_val): if isinstance(size_val, str): size_val.upper() @@ -80,22 +83,14 @@ class PortEID: port_id = 0 port_name = "" - def __init__(self, p_resource=1, p_port_id=0, p_port_name=""): - resource = p_resource - port_id = p_port_id - port_name = p_port_name - def __init__(self, json_response): - if json_response == None: + if json_response is None: raise Exception("No json input") json_s = json_response - if json_response['interface'] != None: + if json_response['interface'] is not None: json_s = json_response['interface'] debug_printer(json_s) - resource = json_s['resource'] - port_id = json_s['id'] - port_name = json_s['name'] # end class PortEID @@ -103,6 +98,7 @@ class PortEID: def staNewDownStaRequest(sta_name, resource_id=1, radio="wiphy0", ssid="", passphrase="", debug_on=False): return sta_new_down_sta_request(sta_name, resource_id, radio, ssid, passphrase, debug_on) + def sta_new_down_sta_request(sta_name, resource_id=1, radio="wiphy0", ssid="", passphrase="", debug_on=False): """ For use with add_sta. If you don't want to generate mac addresses via patterns (xx:xx:xx:xx:81:*) @@ -132,6 +128,7 @@ def sta_new_down_sta_request(sta_name, resource_id=1, radio="wiphy0", ssid="", p def portSetDhcpDownRequest(resource_id, port_name, debug_on=False): return port_set_dhcp_down_request(resource_id, port_name, debug_on) + def port_set_dhcp_down_request(resource_id, port_name, debug_on=False): """ See http://localhost:8080/help/set_port @@ -156,6 +153,7 @@ def port_set_dhcp_down_request(resource_id, port_name, debug_on=False): def portDhcpUpRequest(resource_id, port_name, debug_on=False): return port_dhcp_up_request(resource_id, port_name, debug_on) + def port_dhcp_up_request(resource_id, port_name, debug_on=False): """ See http://localhost:8080/help/set_port @@ -181,6 +179,7 @@ def port_dhcp_up_request(resource_id, port_name, debug_on=False): def portUpRequest(resource_id, port_name, debug_on=False): return port_up_request(resource_id, port_name, debug_on) + def port_up_request(resource_id, port_name, debug_on=False): """ See http://localhost:8080/help/set_port @@ -201,9 +200,11 @@ def port_up_request(resource_id, port_name, debug_on=False): debug_printer.pprint(data) return data + def portDownRequest(resource_id, port_name, debug_on=False): return port_down_request(resource_id, port_name, debug_on) + def port_down_request(resource_id, port_name, debug_on=False): """ Does not change the use_dhcp flag @@ -212,7 +213,7 @@ def port_down_request(resource_id, port_name, debug_on=False): :param port_name: :return: """ - + data = { "shelf": 1, "resource": resource_id, @@ -226,6 +227,7 @@ def port_down_request(resource_id, port_name, debug_on=False): debug_printer.pprint(data) return data + def port_reset_request(resource_id, port_name, debug_on=False): """ Does not change the use_dhcp flag @@ -234,7 +236,7 @@ def port_reset_request(resource_id, port_name, debug_on=False): :param port_name: :return: """ - + data = { "shelf": 1, "resource": resource_id, @@ -249,6 +251,7 @@ def port_reset_request(resource_id, port_name, debug_on=False): def generateMac(parent_mac, random_octet, debug=False): return generate_mac(parent_mac=parent_mac, random_octet=random_octet, debug=debug) + def generate_mac(parent_mac, random_octet, debug=False): if debug: print("************ random_octet: %s **************" % (random_octet)) @@ -272,7 +275,8 @@ def portNameSeries(prefix_="sta", start_id_=0, end_id_=1, padding_number_=10000, :param padding_number_: :return: """ - return port_name_series(prefix=prefix_, start_id=start_id_, end_id=end_id_, padding_number=padding_number_, radio=radio) + return port_name_series(prefix=prefix_, start_id=start_id_, end_id=end_id_, padding_number=padding_number_, + radio=radio) def port_name_series(prefix="sta", start_id=0, end_id=1, padding_number=10000, radio=None): @@ -291,7 +295,7 @@ def port_name_series(prefix="sta", start_id=0, end_id=1, padding_number=10000, r eid = None if radio is not None: eid = name_to_eid(radio) - + name_list = [] for i in range((padding_number + start_id), (padding_number + end_id + 1)): sta_name = "%s%s" % (prefix, str(i)[1:]) @@ -312,9 +316,11 @@ def gen_ip_series(ip_addr, netmask, num_ips=None): chosen_ips.append(ip_list[i]) return chosen_ips + def generateRandomHex(): return generate_random_hex() + # generate random hex if you need it for mac addresses def generate_random_hex(): # generate a few random numbers and convert them into hex: @@ -370,6 +376,7 @@ def port_list_to_alias_map(json_list, debug_=False): return reverse_map + def list_to_alias_map(json_list=None, from_element=None, debug_=False): reverse_map = {} if (json_list is None) or (len(json_list) < 1): @@ -419,9 +426,9 @@ def find_port_eids(resource_id=1, base_url="http://localhost:8080", port_names=( port_url = "/port/1" for port_name in port_names: uri = "%s/%s/%s" % (port_url, resource_id, port_name) - lf_r = LFRequest.LFRequest(base_url, uri) + lf_r = LFRequest.LFRequest(base_url, uri, debug_=debug) try: - response = lf_r.getAsJson(debug) + response = lf_r.getAsJson() if response is None: continue port_eids.append(PortEID(response)) @@ -443,9 +450,9 @@ def wait_until_ports_admin_down(resource_id=1, base_url="http://localhost:8080", up_stations = [] for port_name in port_list: uri = "%s/%s/%s?fields=device,down" % (port_url, resource_id, port_name) - lf_r = LFRequest.LFRequest(base_url, uri) - json_response = lf_r.getAsJson(debug_=False) - if json_response == None: + lf_r = LFRequest.LFRequest(base_url, uri, debug_=debug_) + json_response = lf_r.getAsJson() + if json_response is None: if debug_: print("port %s disappeared" % port_name) continue @@ -460,6 +467,7 @@ def wait_until_ports_admin_down(resource_id=1, base_url="http://localhost:8080", def waitUntilPortsAdminUp(resource_id=1, base_url="http://localhost:8080", port_list=()): return wait_until_ports_admin_up(resource_id=resource_id, base_url=base_url, port_list=port_list) + def wait_until_ports_admin_up(resource_id=1, base_url="http://localhost:8080", port_list=(), debug_=False): print("Waiting until ports appear admin-up...") down_stations = port_list.copy() @@ -470,9 +478,9 @@ def wait_until_ports_admin_up(resource_id=1, base_url="http://localhost:8080", p down_stations = [] for port_name in port_list: uri = "%s/%s/%s?fields=device,down" % (port_url, resource_id, port_name) - lf_r = LFRequest.LFRequest(base_url, uri) - json_response = lf_r.getAsJson(debug_=False) - if json_response == None: + lf_r = LFRequest.LFRequest(base_url, uri, debug_=debug_) + json_response = lf_r.getAsJson() + if json_response is None: if debug_: print("port %s appeared" % port_name) continue @@ -483,9 +491,11 @@ def wait_until_ports_admin_up(resource_id=1, base_url="http://localhost:8080", p sleep(1) return None + def waitUntilPortsDisappear(base_url="http://localhost:8080", port_list=(), debug=False): wait_until_ports_disappear(base_url, port_list, debug) + def wait_until_ports_disappear(base_url="http://localhost:8080", port_list=(), debug=False): if (port_list is None) or (len(port_list) < 1): if debug: @@ -499,8 +509,8 @@ def wait_until_ports_disappear(base_url="http://localhost:8080", port_list=(), d else: found_stations = [port_list] - temp_names_by_resource = {1:[]} - temp_query_by_resource = {1:""} + temp_names_by_resource = {1: []} + temp_query_by_resource = {1: ""} for port_eid in port_list: eid = name_to_eid(port_eid) # shelf = eid[0] @@ -511,7 +521,8 @@ def wait_until_ports_disappear(base_url="http://localhost:8080", port_list=(), d temp_names_by_resource[resource_id] = [] port_name = eid[2] temp_names_by_resource[resource_id].append(port_name) - temp_query_by_resource[resource_id] = "%s/%s/%s?fields=alias" % (url, resource_id, ",".join(temp_names_by_resource[resource_id])) + temp_query_by_resource[resource_id] = "%s/%s/%s?fields=alias" % ( + url, resource_id, ",".join(temp_names_by_resource[resource_id])) if debug: pprint.pprint(("temp_query_by_resource", temp_query_by_resource)) while len(found_stations) > 0: @@ -523,8 +534,8 @@ def wait_until_ports_disappear(base_url="http://localhost:8080", port_list=(), d ("check_url", check_url), ]) lf_r = LFRequest.LFRequest(base_url, check_url, debug_=debug) - json_response = lf_r.get_as_json(debug_=debug, die_on_error_=False) - if (json_response == None): + json_response = lf_r.get_as_json() + if json_response is None: print("LFUtils::wait_until_ports_disappear:: Request returned None: [{}]".format(base_url + check_url)) else: if debug: @@ -540,7 +551,7 @@ def wait_until_ports_disappear(base_url="http://localhost:8080", port_list=(), d if len(found_stations) > 0: if debug: pprint.pprint(("wait_until_ports_disappear found_stations:", found_stations)) - sleep(1) # safety + sleep(1) # safety return @@ -554,37 +565,39 @@ def waitUntilPortsAppear(base_url="http://localhost:8080", port_list=(), debug=F """ return wait_until_ports_appear(base_url, port_list, debug=debug) -def name_to_eid(input, non_port=False): + +def name_to_eid(eid_input, non_port=False): rv = [1, 1, "", ""] info = [] - if (input is None) or (input == ""): - raise ValueError("name_to_eid wants eid like 1.1.sta0 but given[%s]" % input) - if type(input) is not str: - raise ValueError("name_to_eid wants string formatted like '1.2.name', not a tuple or list or [%s]" % type(input)) + if (eid_input is None) or (eid_input == ""): + raise ValueError("name_to_eid wants eid like 1.1.sta0 but given[%s]" % eid_input) + if type(eid_input) is not str: + raise ValueError( + "name_to_eid wants string formatted like '1.2.name', not a tuple or list or [%s]" % type(eid_input)) - info = input.split('.') + info = eid_input.split('.') if len(info) == 1: - rv[2] = info[0] # just port name + rv[2] = info[0] # just port name return rv - if (len(info) == 2) and info[0].isnumeric() and not info[1].isnumeric(): # resource.port-name + if (len(info) == 2) and info[0].isnumeric() and not info[1].isnumeric(): # resource.port-name rv[1] = int(info[0]) rv[2] = info[1] return rv - elif (len(info) == 2) and not info[0].isnumeric(): # port-name.qvlan - rv[2] = info[0]+"."+info[1] + elif (len(info) == 2) and not info[0].isnumeric(): # port-name.qvlan + rv[2] = info[0] + "." + info[1] return rv - if (len(info) == 3) and info[0].isnumeric() and info[1].isnumeric(): # shelf.resource.port-name + if (len(info) == 3) and info[0].isnumeric() and info[1].isnumeric(): # shelf.resource.port-name rv[0] = int(info[0]) rv[1] = int(info[1]) rv[2] = info[2] return rv - elif (len(info) == 3) and info[0].isnumeric() and not info[1].isnumeric(): # resource.port-name.qvlan + elif (len(info) == 3) and info[0].isnumeric() and not info[1].isnumeric(): # resource.port-name.qvlan rv[1] = int(info[0]) - rv[2] = info[1]+"."+info[2] + rv[2] = info[1] + "." + info[2] return rv if non_port: @@ -595,14 +608,15 @@ def name_to_eid(input, non_port=False): if (len(info) >= 4): rv[3] = int(info[3]) return rv - - if len(info) == 4: # shelf.resource.port-name.qvlan + + if len(info) == 4: # shelf.resource.port-name.qvlan rv[0] = int(info[0]) rv[1] = int(info[1]) - rv[2] = info[2]+"."+info[3] + rv[2] = info[2] + "." + info[3] return rv + def wait_until_ports_appear(base_url="http://localhost:8080", port_list=(), debug=False): """ Use this method to pause until the LANforge system has caught up and implemented the @@ -633,21 +647,22 @@ def wait_until_ports_appear(base_url="http://localhost:8080", port_list=(), debu port_name = eid[2] # print("waiting for sta sta "+port_eid) uri = "%s/%s/%s" % (port_url, resource_id, port_name) - lf_r = LFRequest.LFRequest(base_url, uri) - json_response = lf_r.getAsJson(debug_=False) - if (json_response != None): + lf_r = LFRequest.LFRequest(base_url, uri, debug_=debug) + json_response = lf_r.getAsJson() + if json_response is not None: found_stations.append(port_name) else: - lf_r = LFRequest.LFRequest(base_url, ncshow_url) + lf_r = LFRequest.LFRequest(base_url, ncshow_url, debug_=debug) lf_r.addPostData({"shelf": shelf, "resource": resource_id, "port": port_name, "probe_flags": 5}) lf_r.jsonPost() - if (len(found_stations) < len(port_list)): + if len(found_stations) < len(port_list): sleep(2) if debug: print("These stations appeared: " + ", ".join(found_stations)) return + def wait_until_endps(base_url="http://localhost:8080", endp_list=(), debug=False): """ @@ -672,14 +687,14 @@ def wait_until_endps(base_url="http://localhost:8080", endp_list=(), debug=False shelf = eid[0] resource_id = eid[1] port_name = eid[2] - + uri = "%s/%s/%s" % (port_url, resource_id, port_name) - lf_r = LFRequest.LFRequest(base_url, uri) - json_response = lf_r.getAsJson(debug_=False) - if (json_response != None): + lf_r = LFRequest.LFRequest(base_url, uri, debug_=debug) + json_response = lf_r.getAsJson() + if json_response is not None: found_stations.append(port_name) else: - lf_r = LFRequest.LFRequest(base_url, ncshow_url) + lf_r = LFRequest.LFRequest(base_url, ncshow_url, debug_=debug) lf_r.addPostData({"shelf": shelf, "resource": resource_id, "port": port_name, "flags": 1}) lf_r.formPost() if (len(found_stations) < len(endp_list)): @@ -698,7 +713,7 @@ def remove_port(resource, port_name, baseurl="http://localhost:8080/", debug=Fal if debug: print("Removing port %d.%s" % (resource, port_name)) url = "/cli-json/rm_vlan" - lf_r = LFRequest.LFRequest(baseurl, url) + lf_r = LFRequest.LFRequest(baseurl, url, debug_=debug) lf_r.addPostData({ "shelf": 1, "resource": resource, @@ -720,7 +735,7 @@ def remove_cx(baseurl, cx_names, debug=False): "test_mgr": "all", "cx_name": name } - lf_r = LFRequest.LFRequest(baseurl, url) + lf_r = LFRequest.LFRequest(baseurl, url, debug_=debug) lf_r.addPostData(data) lf_r.jsonPost(debug) @@ -733,7 +748,7 @@ def remove_endps(baseurl, endp_names, debug=False): if debug: print("Removing endp %s" % ", ".join(endp_names)) url = "/cli-json/rm_endp" - lf_r = LFRequest.LFRequest(baseurl, url) + lf_r = LFRequest.LFRequest(baseurl, url, debug_=debug) for name in endp_names: data = { "endp_name": name @@ -791,11 +806,11 @@ def expand_endp_histogram(distribution_payload=None): raise ValueError("Unexpected histogram format.") multiplier = int(distribution_payload["histo_category_width"]) formatted_dict = { - #"00000 <= x <= 00001" : "0" + # "00000 <= x <= 00001" : "0" } for bucket_index in range(len(distribution_payload["histogram"]) - 1): - pow1 = (2**bucket_index) * multiplier - pow2 = (2**(bucket_index+1)) * multiplier + pow1 = (2 ** bucket_index) * multiplier + pow2 = (2 ** (bucket_index + 1)) * multiplier if bucket_index == 0: category_name = "00000 <= x <= {:-05.0f}".format(pow2) else: diff --git a/py-json/LANforge/lfcli_base.py b/py-json/LANforge/lfcli_base.py index dc5c8b69..934d9ffa 100644 --- a/py-json/LANforge/lfcli_base.py +++ b/py-json/LANforge/lfcli_base.py @@ -10,23 +10,32 @@ import random import string import datetime import argparse +import re +import logging if sys.version_info[0] != 3: print("This script requires Python 3") exit() - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../../"))) -LFUtils = importlib.import_module("py-json.LANforge.LFUtils") +debug_printer = pprint.PrettyPrinter(indent=2) LFRequest = importlib.import_module("py-json.LANforge.LFRequest") +LFUtils = importlib.import_module("py-json.LANforge.LFUtils") +Logg = importlib.import_module("lanforge_client.logg") + +if os.environ.get("LF_USE_AUTOGEN") == 1: + lanforge_api = importlib.import_module("lanforge_client.lanforge_api") + LFSession = lanforge_api.LFSession class LFCliBase: + SHOULD_RUN = 0 # indicates normal operation + SHOULD_QUIT = 1 # indicates to quit loops, close files, send SIGQUIT to threads and return + SHOULD_HALT = 2 # indicates to quit loops, send SIGABRT to threads and exit - SHOULD_RUN = 0 # indicates normal operation - SHOULD_QUIT = 1 # indicates to quit loops, close files, send SIGQUIT to threads and return - SHOULD_HALT = 2 # indicates to quit loops, send SIGABRT to threads and exit + # - LOGGING - + _logger = logging.getLogger(__name__) # do not use `super(LFCLiBase,self).__init__(self, host, port, _debug) # that is py2 era syntax and will force self into the host variable, making you @@ -37,7 +46,9 @@ class LFCliBase: _exit_on_fail=False, _local_realm=None, _proxy_str=None, - _capture_signal_list=[]): + _capture_signal_list=None): + if _capture_signal_list is None: + _capture_signal_list = [] self.fail_pref = "FAILED: " self.pass_pref = "PASSED: " self.lfclient_host = _lfjson_host @@ -48,7 +59,7 @@ class LFCliBase: self.proxy = {} self.adjust_proxy(_proxy_str) - if (_local_realm is not None): + if _local_realm: self.local_realm = _local_realm # if (_debug): @@ -69,7 +80,7 @@ class LFCliBase: if len(_capture_signal_list) > 0: for zignal in _capture_signal_list: - self.captured_signal(zignal, self.my_captured_signal) + self.captured_signal(zignal) # def _finish(self): @@ -136,7 +147,8 @@ class LFCliBase: print("sending signal %s to thread %s" % (signum, name)) # do a thing - def my_captured_signal(self, signum): + @staticmethod + def my_captured_signal(signum): """ Override me to process signals, otherwise superclass signal handler is called. You may use _finish() or _halt() to indicate finishing soon or halting immediately. @@ -164,6 +176,42 @@ class LFCliBase: def clear_test_results(self): self.test_results.clear() + # - LOGGING - we want to remove old logging code + def log_register_method_name(self, method_name=None): + if not method_name: + return + if os.environ.get("LF_USE_AUTOGEN") == 1: + Logg.register_method_name(method_name=method_name) + else: + if method_name not in self._method_name_list: + self._method_name_list.append(method_name) + if method_name not in self._tag_list: + self._tag_list.append(method_name) + + def log_register_tag(self, tag=None): + if not tag: + return + if os.environ.get("LF_USE_AUTOGEN") == 1: + Logg.register_tag(tag=tag) + else: + if tag not in self._tag_list: + self._tag_list.append(tag) + self._logger.register_method_name(tag=tag) + + def log_enable(self, reserved_tag=None): + if os.environ.get("LF_USE_AUTOGEN") == 1: + Logg.enable(reserved_tag=reserved_tag) + else: + self.log_register_tag(reserved_tag) + + @staticmethod + def log_set_filename(filename=None): + if not filename: + return + logging.basicConfig(filename=filename) + + # - END LOGGING - + def json_post(self, _req_url, _data, debug_=False, suppress_related_commands_=None, response_json_list_=None): """ send json to the LANforge client @@ -191,7 +239,7 @@ class LFCliBase: del _data['suppress_postexec_cli'] if 'suppress_postexec_method' in _data: del _data['suppress_postexec_method'] - elif suppress_related_commands_ == False: + elif not suppress_related_commands_: _data['suppress_preexec_cli'] = False _data['suppress_preexec_method'] = False _data['suppress_postexec_cli'] = False @@ -204,11 +252,11 @@ class LFCliBase: lf_r.addPostData(_data) if debug_: - LFUtils.debug_printer.pprint(_data) + debug_printer.pprint(_data) json_response = lf_r.json_post(show_error=debug_, - debug=debug_, - response_json_list_=response_json_list_, - die_on_error_=self.exit_on_error) + debug=debug_, + response_json_list_=response_json_list_, + die_on_error_=self.exit_on_error) if debug_ and (response_json_list_ is not None): pprint.pprint(response_json_list_) except Exception as x: @@ -242,7 +290,7 @@ class LFCliBase: die_on_error_=self.exit_on_error) lf_r.addPostData(_data) if debug_: - LFUtils.debug_printer.pprint(_data) + debug_printer.pprint(_data) json_response = lf_r.json_put(show_error=self.debug, debug=debug_, response_json_list_=response_json_list_, @@ -259,23 +307,22 @@ class LFCliBase: exit(1) return json_response - def json_get(self, _req_url, debug_=False): - debug_ |= self.debug + def json_get(self, _req_url, debug_=None): # if debug_: # print("json_get: "+_req_url) # print("json_get: proxies:") # pprint.pprint(self.proxy) + if debug_ is None: + debug_ = self.debug json_response = None - # print("----- GET ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ") try: lf_r = LFRequest.LFRequest(url=self.lfclient_url, uri=_req_url, proxies_=self.proxy, debug_=debug_, die_on_error_=self.exit_on_error) - json_response = lf_r.get_as_json(debug_=debug_, die_on_error_=False) - #debug_printer.pprint(json_response) - if (json_response is None): + json_response = lf_r.get_as_json() + if json_response is None: if debug_: if hasattr(lf_r, 'print_errors'): lf_r.print_errors() @@ -296,7 +343,7 @@ class LFCliBase: def json_delete(self, _req_url, debug_=False): debug_ |= self.debug if debug_: - print("DELETE: "+_req_url) + print("DELETE: " + _req_url) json_response = None try: # print("----- DELETE ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ") @@ -307,7 +354,7 @@ class LFCliBase: die_on_error_=self.exit_on_error) json_response = lf_r.json_delete(debug=debug_, die_on_error_=False) print(json_response) - #debug_printer.pprint(json_response) + # debug_printer.pprint(json_response) if (json_response is None) and debug_: print("LFCliBase.json_delete: no entity/response, probabily status 404") return None @@ -352,7 +399,8 @@ class LFCliBase: return reverse_map - def error(self, exception): + @staticmethod + def error(exception): # print("lfcli_base error: %s" % exception) pprint.pprint(exception) traceback.print_exception(Exception, exception, exception.__traceback__, chain=True) @@ -372,11 +420,11 @@ class LFCliBase: print("Could not connect to LANforge GUI") sys.exit(1) - #return ALL messages in list form + # return ALL messages in list form def get_result_list(self): return self.test_results - #return ALL fail messages in list form + # return ALL fail messages in list form def get_failed_result_list(self): fail_list = [] for result in self.test_results: @@ -384,7 +432,7 @@ class LFCliBase: fail_list.append(result) return fail_list - #return ALL pass messages in list form + # return ALL pass messages in list form def get_passed_result_list(self): pass_list = [] for result in self.test_results: @@ -403,7 +451,7 @@ class LFCliBase: def get_all_message(self): return "\n".join(self.test_results) - #determines if overall test passes via comparing passes vs. fails + # determines if overall test passes via comparing passes vs. fails def passes(self): pass_counter = 0 fail_counter = 0 @@ -416,11 +464,11 @@ class LFCliBase: return True return False - #EXIT script with a fail + # EXIT script with a fail def exit_fail(self, message="%d out of %d tests failed. Exiting script with script failure."): - total_len=len(self.get_result_list()) - fail_len=len(self.get_failed_result_list()) - print(message %(fail_len,total_len)) + total_len = len(self.get_result_list()) + fail_len = len(self.get_failed_result_list()) + print(message % (fail_len, total_len)) sys.exit(1) # use this inside the class to log a failure result and print it if wished @@ -431,17 +479,17 @@ class LFCliBase: if self.exit_on_fail: sys.exit(1) - #EXIT script with a success - def exit_success(self,message="%d out of %d tests passed successfully. Exiting script with script success."): - num_total=len(self.get_result_list()) - num_passing=len(self.get_passed_result_list()) - print(message %(num_passing,num_total)) + # EXIT script with a success + def exit_success(self, message="%d out of %d tests passed successfully. Exiting script with script success."): + num_total = len(self.get_result_list()) + num_passing = len(self.get_passed_result_list()) + print(message % (num_passing, num_total)) sys.exit(0) - def success(self,message="%d out of %d tests passed successfully."): - num_total=len(self.get_result_list()) - num_passing=len(self.get_passed_result_list()) - print(message %(num_passing,num_total)) + def success(self, message="%d out of %d tests passed successfully."): + num_total = len(self.get_result_list()) + num_passing = len(self.get_passed_result_list()) + print(message % (num_passing, num_total)) # use this inside the class to log a pass result and print if wished. def _pass(self, message, print_=False): @@ -465,27 +513,35 @@ class LFCliBase: # print("lfclibase::self.proxy: ") # pprint.pprint(self.proxy) - - def logg2(self, level="debug", mesg=None): + @staticmethod + def logg2(level="debug", mesg=None): if (mesg is None) or (mesg == ""): return print("[{level}]: {msg}".format(level=level, msg=mesg)) - def logg(self, - level=None, - mesg=None, - filename=None, - scriptname=None): + @staticmethod + def logg(level=None, + mesg=None, + filename=None, + scriptname=None): + """ + This method is used by vr_profile2, lf_create_bcast, and shadowed by base_profile.py + :param level: + :param mesg: + :param filename: + :param scriptname: + :return: + """ if (mesg is None) or (mesg == "") or (level is None): return - userhome=os.path.expanduser('~') - session = str(datetime.datetime.now().strftime("%Y-%m-%d-%H-h-%M-m-%S-s")).replace(':','-') - if filename == None: - try: + userhome = os.path.expanduser('~') + session = str(datetime.datetime.now().strftime("%Y-%m-%d-%H-h-%M-m-%S-s")).replace(':', '-') + if filename is None: + if not os.path.isdir("%s/report-data/%s" % (userhome, session)): + if not os.path.isdir('%s/report-data' % userhome): + os.mkdir('%s/report-data' % userhome) os.mkdir("%s/report-data/%s" % (userhome, session)) - except: - pass - filename = ("%s/report-data/%s/%s.log" % (userhome,session,scriptname)) + filename = ("%s/report-data/%s/%s.log" % (userhome, session, scriptname)) import logging logging.basicConfig(filename=filename, level=logging.DEBUG) if level == "debug": @@ -496,7 +552,7 @@ class LFCliBase: logging.warning(mesg) elif level == "error": logging.error(mesg) - + @staticmethod def parse_time(time_string): if isinstance(time_string, str): @@ -547,10 +603,20 @@ class LFCliBase: parser = argparse.ArgumentParser() optional = parser.add_argument_group('optional arguments') required = parser.add_argument_group('required arguments') - optional.add_argument('--mgr', help='hostname for where LANforge GUI is running', default='localhost') - optional.add_argument('--mgr_port', help='port LANforge GUI HTTP service is running on', default=8080) - optional.add_argument('--debug', '-d', help='Enable debugging', default=False, action="store_true") - optional.add_argument('--proxy', nargs='?', default=None, # action=ProxyAction, + optional.add_argument('--mgr', + default='localhost', + help='hostname for where LANforge GUI is running') + optional.add_argument('--mgr_port', + default=8080, + help='port LANforge GUI HTTP service is running on') + optional.add_argument('--debug', + '-d', + default=False, + action="store_true", + help='Enable debugging') + optional.add_argument('--proxy', + nargs='?', + default=None, # action=ProxyAction, help='Connection proxy like http://proxy.localnet:80 or https://user:pass@proxy.localnet:3128') return parser @@ -574,36 +640,74 @@ class LFCliBase: optional = parser.add_argument_group('optional arguments') required = parser.add_argument_group('required arguments') - #Optional Args - optional.add_argument('--mgr', help='hostname for where LANforge GUI is running', default='localhost') - optional.add_argument('--mgr_port', help='port LANforge GUI HTTP service is running on', default=8080) - optional.add_argument('-u', '--upstream_port', - help='non-station port that generates traffic: ., e.g: 1.eth1', - default='1.eth1') - optional.add_argument('--num_stations', help='Number of stations to create', default=0) - optional.add_argument('--test_id', help='Test ID (intended to use for ws events)', default="webconsole") - optional.add_argument('--debug', help='Enable debugging', default=False, action="store_true") - optional.add_argument('--proxy', nargs='?', default=None, - help='Connection proxy like http://proxy.localnet:80 or https://user:pass@proxy.localnet:3128') + # Optional Args + optional.add_argument('--mgr', + default='localhost', + help='hostname for where LANforge GUI is running') + optional.add_argument('--mgr_port', + default=8080, + help='port LANforge GUI HTTP service is running on') + optional.add_argument('-u', + '--upstream_port', + default='1.eth1', + help='non-station port that generates traffic: ., e.g: 1.eth1') + optional.add_argument('--num_stations', + type=int, + default=0, + help='Number of stations to create') + optional.add_argument('--test_id', + default="webconsole", + help='Test ID (intended to use for ws events)') + optional.add_argument('-d', + '--debug', + action="store_true", + help='Enable debugging') + optional.add_argument('--proxy', + nargs='?', + default=None, + help="Connection proxy like http://proxy.localnet:80 \n" + + " or https://user:pass@proxy.localnet:3128") + optional.add_argument('--debugging', + nargs="+", + action="append", + help="Indicate what areas you would like express debug output:\n" + + " - digest - print terse indications of lanforge_api calls\n" + + " - json - print url and json data\n" + + " - http - print HTTP headers\n" + + " - gui - ask the GUI for extra debugging in responses\n" + + " - method:method_name - enable by_method() debugging (if present)\n" + + " - tag:tagname - enable matching by_tag() debug output\n" + ) + optional.add_argument('--debug_log', + default=None, + help="Specify a file to send debug output to") if more_optional is not None: - for x in more_optional: - if 'default' in x.keys(): - optional.add_argument(x['name'], help=x['help'], default=x['default']) - else: - optional.add_argument(x['name'], help=x['help']) + for argument in more_optional: + if 'default' in argument.keys(): + optional.add_argument(argument['name'], help=argument['help'], default=argument['default']) + else: + optional.add_argument(argument['name'], help=argument['help']) - #Required Args - required.add_argument('--radio', help='radio EID, e.g: 1.wiphy2') - required.add_argument('--security', help='WiFi Security protocol: < open | wep | wpa | wpa2 | wpa3 >', default="open") - required.add_argument('--ssid', help='WiFi SSID for script objects to associate to') - required.add_argument('--passwd', '--password' ,'--key', help='WiFi passphrase/password/key', default="[BLANK]") + # Required Args + required.add_argument('--radio', + help='radio EID, e.g: 1.wiphy2') + required.add_argument('--security', + default="open", + help='WiFi Security protocol: < open | wep | wpa | wpa2 | wpa3 >') + required.add_argument('--ssid', + help='WiFi SSID for script objects to associate to') + required.add_argument('--passwd', + '--password', + '--key', + default="[BLANK]", + help='WiFi passphrase/password/key') if more_required is not None: - for x in more_required: - if 'default' in x.keys(): - required.add_argument(x['name'], help=x['help'], default=x['default']) + for argument in more_required: + if 'default' in argument.keys(): + required.add_argument(argument['name'], help=argument['help'], default=argument['default']) else: - required.add_argument(x['name'], help=x['help']) + required.add_argument(argument['name'], help=argument['help']) return parser @@ -622,24 +726,29 @@ class LFCliBase: } self.json_post("/cli-json/add_event", data, debug_=debug_) - def read_file(self, filename): + @staticmethod + def read_file(filename): filename = open(filename, 'r') return [line.split(',') for line in filename.readlines()] - #Function creates random characters made of letters - def random_chars(self, size, chars=None): + # Function creates random characters made of letters + @staticmethod + def random_chars(size, chars=None): if chars is None: chars = string.ascii_letters return ''.join(random.choice(chars) for x in range(size)) - def get_milliseconds(self, timestamp): - return (timestamp - datetime.datetime(1970,1,1)).total_seconds()*1000 + @staticmethod + def get_milliseconds(timestamp): + return (timestamp - datetime.datetime(1970, 1, 1)).total_seconds() * 1000 - def get_seconds(self, timestamp): - return (timestamp - datetime.datetime(1970,1,1)).total_seconds() + @staticmethod + def get_seconds(timestamp): + return (timestamp - datetime.datetime(1970, 1, 1)).total_seconds() - def replace_special_char(self, str): - return str.replace('+', ' ').replace('_', ' ').strip(' ') + @staticmethod + def replace_special_char(special_str): + return special_str.replace('+', ' ').replace('_', ' ').strip(' ') Help_Mode = """Station WiFi modes: use the number value below: auto : 0, @@ -656,4 +765,4 @@ class LFCliBase: bgnAC : 11, abgnAX : 12, bgnAX : 13 -""" +""" diff --git a/py-json/LANforge/pandas_extensions.py b/py-json/LANforge/pandas_extensions.py index 935daa4b..3214d2da 100644 --- a/py-json/LANforge/pandas_extensions.py +++ b/py-json/LANforge/pandas_extensions.py @@ -81,7 +81,7 @@ class pandas_extensions: print(for_loop_df1.at[0, col]) print(for_loop_df2.at[0, col]) if type(for_loop_df1.at[0, col]) == str and type(for_loop_df2.at[0, col]) == str: - if (' ' in for_loop_df1.at[0, col]) == True: + if (' ' in for_loop_df1.at[0, col]): # do subtraction new_value = float(for_loop_df1.at[0, col].split(" ")[0]) - float( for_loop_df2.at[0, col].split(" ")[0]) diff --git a/py-json/LANforge/set_port.py b/py-json/LANforge/set_port.py index f6fa7f3b..ad45f354 100644 --- a/py-json/LANforge/set_port.py +++ b/py-json/LANforge/set_port.py @@ -6,17 +6,16 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit() - -sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../../"))) -lf_json_autogen = importlib.import_module("py-json.LANforge.lf_json_autogen") -LFJsonPost = lf_json_autogen.LFJsonPost +sys.path.append(os.path.join(os.path.abspath(__file__ + "../../"))) if os.environ.get("LF_USE_AUTOGEN") == 1: - set_port_current_flags = LFJsonPost.SetPortCurrentFlags.__members__ - set_port_cmd_flags = LFJsonPost.SetPortCmdFlags.__members__ - set_port_interest_flags = LFJsonPost.SetPortInterest.__members__ + lanforge_api = importlib.import_module("lanforge_client.lanforge_api") + LFJsonCommand = lanforge_api.LFJsonCommand + set_port_current_flags = LFJsonCommand.SetPortCurrentFlags.__members__ + set_port_cmd_flags = LFJsonCommand.SetPortCmdFlags.__members__ + set_port_interest_flags = LFJsonCommand.SetPortInterest.__members__ else: set_port_current_flags = { diff --git a/py-json/create_wanlink.py b/py-json/create_wanlink.py index fab6c0bb..83322b48 100755 --- a/py-json/create_wanlink.py +++ b/py-json/create_wanlink.py @@ -2,6 +2,12 @@ # Create and modify WAN Links Using LANforge JSON AP : http://www.candelatech.com/cookbook.php?vol=cli&book=JSON:+Managing+WANlinks+using+JSON+and+Python # Written by Candela Technologies Inc. # Updated by: Erin Grimes + +""" +sample command: +./test_wanlink.py --name my_wanlink4 --latency_A 20 --latency_B 69 --rate 1000 --jitter_A 53 --jitter_B 73 --jitter_freq 6 --drop_A 12 --drop_B 11 +""" + import sys import urllib import importlib @@ -13,19 +19,23 @@ import os from time import sleep from urllib import error import pprint +import argparse sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) LFRequest = importlib.import_module("py-json.LANforge.LFRequest") LFUtils = importlib.import_module("py-json.LANforge.LFUtils") +lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") +LFCliBase = lfcli_base.LFCliBase j_printer = pprint.PrettyPrinter(indent=2) # todo: this needs to change resource_id = 1 -def main(base_url, args={}): +def main(args): + base_url = 'http://'+args['host']+':8080' print(base_url) json_post = "" json_response = "" @@ -36,7 +46,7 @@ def main(base_url, args={}): print(lf_r.get_as_json()) # remove old wanlinks - if (num_wanlinks > 0): + if num_wanlinks > 0: lf_r = LFRequest.LFRequest(base_url+"/cli-json/rm_cx") lf_r.addPostData({ 'test_mgr': 'all', @@ -49,10 +59,10 @@ def main(base_url, args={}): json_response = lf_r.getAsJson() LFUtils.debug_printer.pprint(json_response) for key, value in json_response.items(): - if (isinstance(value, dict) and "_links" in value): + if isinstance(value, dict) and "_links" in value: num_wanlinks = 1 except urllib.error.HTTPError as error: - print("Error code "+error.code) + print("Error code %s" % error.code) lf_r = LFRequest.LFRequest(base_url+"/cli-json/rm_endp") lf_r.addPostData({ @@ -129,18 +139,18 @@ def main(base_url, args={}): # start wanlink once we see it seen = 0 - while (seen < 1): + while seen < 1: sleep(1) lf_r = LFRequest.LFRequest(base_url+"/wl/"+args['name']+"?fields=name,state,_links") try: json_response = lf_r.getAsJson() - if (json_response is None): + if json_response is None: continue LFUtils.debug_printer.pprint(json_response) for key, value in json_response.items(): - if (isinstance(value, dict)): - if ("_links" in value): - if (value["name"] == args['name']): + if isinstance(value, dict): + if "_links" in value: + if value["name"] == args['name']: seen = 1 else: pass @@ -152,71 +162,71 @@ def main(base_url, args={}): # print("value not a dict") except urllib.error.HTTPError as error: - print("Error code "+error.code) + print("Error code %s " % error.code) continue - print("starting wanlink:") - # print("the latency is {laten}".format(laten=latency)) - lf_r = LFRequest.LFRequest(base_url+"/cli-json/set_cx_state") - lf_r.addPostData({ - 'test_mgr': 'all', - 'cx_name': args['name'], - 'cx_state': 'RUNNING' - }) - lf_r.jsonPost() + # print("starting wanlink:") + # # print("the latency is {laten}".format(laten=latency)) + # lf_r = LFRequest.LFRequest(base_url+"/cli-json/set_cx_state") + # lf_r.addPostData({ + # 'test_mgr': 'all', + # 'cx_name': args['name'], + # 'cx_state': 'RUNNING' + # }) + # lf_r.jsonPost() running = 0 - while (running < 1): + while running < 1: sleep(1) lf_r = LFRequest.LFRequest(base_url+"/wl/"+args['name']+"?fields=name,state,_links") try: json_response = lf_r.getAsJson() - if (json_response is None): + if json_response is None: continue for key, value in json_response.items(): - if (isinstance(value, dict)): - if ("_links" in value): - if (value["name"] == args['name']): - if (value["state"].startswith("Run")): + if isinstance(value, dict): + if "_links" in value: + if value["name"] == args['name']: + if value["state"].startswith("Run"): LFUtils.debug_printer.pprint(json_response) running = 1 except urllib.error.HTTPError as error: - print("Error code "+error.code) + print("Error code %s" % error.code) continue print("Wanlink is running") - # stop wanlink - lf_r = LFRequest.LFRequest(base_url+"/cli-json/set_cx_state") - lf_r.addPostData({ - 'test_mgr': 'all', - 'cx_name': args['name'], - 'cx_state': 'STOPPED' - }) - lf_r.jsonPost() - running = 1 - while (running > 0): - sleep(1) - lf_r = LFRequest.LFRequest(base_url+"/wl/"+args['name']+"?fields=name,eid,state,_links") - LFUtils.debug_printer.pprint(json_response) - try: - json_response = lf_r.getAsJson() - if (json_response is None): - continue - for key, value in json_response.items(): - if (isinstance(value, dict)): - if ("_links" in value): - if (value["name"] == args['name']): - if (value["state"].startswith("Stop")): - LFUtils.debug_printer.pprint(json_response) - running = 0 + # # stop wanlink + # lf_r = LFRequest.LFRequest(base_url+"/cli-json/set_cx_state") + # lf_r.addPostData({ + # 'test_mgr': 'all', + # 'cx_name': args['name'], + # 'cx_state': 'STOPPED' + # }) + # lf_r.jsonPost() + # running = 1 + # while (running > 0): + # sleep(1) + # lf_r = LFRequest.LFRequest(base_url+"/wl/"+args['name']+"?fields=name,eid,state,_links") + # LFUtils.debug_printer.pprint(json_response) + # try: + # json_response = lf_r.getAsJson() + # if (json_response is None): + # continue + # for key, value in json_response.items(): + # if (isinstance(value, dict)): + # if ("_links" in value): + # if (value["name"] == args['name']): + # if (value["state"].startswith("Stop")): + # LFUtils.debug_printer.pprint(json_response) + # running = 0 - except urllib.error.HTTPError as error: - print("Error code "+error.code) - continue + # except urllib.error.HTTPError as error: + # print("Error code "+error.code) + # continue - print("Wanlink is stopped.") + # print("Wanlink is stopped.") # print("Wanlink info:") # lf_r = LFRequest.LFRequest(base_url+"/wl/wl_eg1") @@ -235,4 +245,67 @@ def main(base_url, args={}): if __name__ == '__main__': - main() + parser = LFCliBase.create_basic_argparse( + prog='create_wanlink.py', + formatter_class=argparse.RawTextHelpFormatter) + for group in parser._action_groups: + if group.title == "required arguments": + required_args = group + break + + optional_args = None + for group in parser._action_groups: + if group.title == "optional arguments": + optional_args = group + break + if optional_args is not None: + optional_args.add_argument('--host', help='The resource IP address', default="localhost") + optional_args.add_argument('--port_A', help='Endpoint A', default="eth1") + optional_args.add_argument('--port_B', help='Endpoint B', default="eth2") + optional_args.add_argument('--name', help='The name of the wanlink', default="wl_eg1") + optional_args.add_argument('--rate', help='The maximum rate of transfer at both endpoints (bits/s)', default=1000000) + optional_args.add_argument('--rate_A', help='The max rate of transfer at endpoint A (bits/s)', default=None) + optional_args.add_argument('--rate_B', help='The maximum rate of transfer (bits/s)', default=None) + optional_args.add_argument('--latency', help='The delay of both ports', default=20) + optional_args.add_argument('--latency_A', help='The delay of port A', default=None) + optional_args.add_argument('--latency_B', help='The delay of port B', default=None) + optional_args.add_argument('--jitter', help='The max jitter of both ports (ms)', default=None) + optional_args.add_argument('--jitter_A', help='The max jitter of port A (ms)', default=None) + optional_args.add_argument('--jitter_B', help='The max jitter of port B (ms)', default=None) + optional_args.add_argument('--jitter_freq', help='The jitter frequency of both ports (%%)', default=None) + optional_args.add_argument('--jitter_freq_A', help='The jitter frequency of port A (%%)', default=None) + optional_args.add_argument('--jitter_freq_B', help='The jitter frequency of port B (%%)', default=None) + optional_args.add_argument('--drop', help='The drop frequency of both ports (%%)', default=None) + optional_args.add_argument('--drop_A', help='The drop frequency of port A (%%)', default=None) + optional_args.add_argument('--drop_B', help='The drop frequency of port B (%%)', default=None) + # todo: packet loss A and B + # todo: jitter A and B + for group in parser._action_groups: + if group.title == "optional arguments": + optional_args = group + break + parseargs = parser.parse_args() + args = { + "host": parseargs.mgr, + "port": parseargs.mgr_port, + "name": parseargs.name, + "port_A": parseargs.port_A, + "port_B": parseargs.port_B, + "latency": parseargs.latency, + "latency_A": (parseargs.latency_A if parseargs.latency_A is not None else parseargs.latency), + "latency_B": (parseargs.latency_B if parseargs.latency_B is not None else parseargs.latency), + "rate": parseargs.rate, + "rate_A": (parseargs.rate_A if parseargs.rate_A is not None else parseargs.rate), + "rate_B": (parseargs.rate_B if parseargs.rate_B is not None else parseargs.rate), + "jitter": parseargs.jitter, + "jitter_A": (parseargs.jitter_A if parseargs.jitter_A is not None else parseargs.jitter), + "jitter_B": (parseargs.jitter_B if parseargs.jitter_B is not None else parseargs.jitter), + "jitter_freq": parseargs.jitter, + "jitter_freq_A": (parseargs.jitter_freq_A if parseargs.jitter_freq_A is not None else parseargs.jitter_freq), + "jitter_freq_B": (parseargs.jitter_freq_B if parseargs.jitter_freq_B is not None else parseargs.jitter_freq), + "drop": parseargs.drop, + "drop_A": (parseargs.drop_A if parseargs.drop_A is not None else parseargs.drop), + "drop_B": (parseargs.drop_B if parseargs.drop_B is not None else parseargs.drop), + } + + main(args) diff --git a/py-json/cv_dut_profile.py b/py-json/cv_dut_profile.py index d10f97ad..1013a3ce 100644 --- a/py-json/cv_dut_profile.py +++ b/py-json/cv_dut_profile.py @@ -40,9 +40,12 @@ class cv_dut(LFCliBase): self.lan_port = "[BLANK]" self.api_id = "0" self.flags_mask = "NA" - if desired_dut_flags is not None: + if desired_dut_flags: self.dut_flags = desired_dut_flags self.dut_flags_mask = desired_dut_flags_mask + if self.dut_flags: + self.flags = self.add_named_flags(self.dut_flags, add_dut_flags) + self.flags_mask = self.add_named_flags(self.dut_flags_mask, add_dut_flags) def add_named_flags(self, desired_list, command_ref): if desired_list is None: @@ -80,11 +83,6 @@ class cv_dut(LFCliBase): top_left_x="NA", top_left_y="NA", ): - try: - self.flags = self.add_named_flags(self.dut_flags, add_dut_flags) - self.flags_mask = self.add_named_flags(self.dut_flags_mask, add_dut_flags) - except: - pass response_json = [] req_url = "/cli-json/add_dut" data = { @@ -129,13 +127,13 @@ class cv_dut(LFCliBase): ssid_flags=0, ssid_flags_mask=0xFFFFFFFF): req_url = "/cli-json/add_dut_ssid" - print("name:" + dut_name, - "ssid_idx:" + ssid_idx, - "ssid:" + ssid, - "passwd:" + passwd, - "bssid:" + bssid, - "ssid_flags:" + str(ssid_flags), - "ssid_flags_mask:" + str(ssid_flags_mask)) + print("name: %s" % dut_name, + "ssid_idx: %s" % ssid_idx, + "ssid: %s" % ssid, + "passwd: %s" % passwd, + "bssid: %s" % bssid, + "ssid_flags: %s" % ssid_flags, + "ssid_flags_mask: %s" % ssid_flags_mask) self.json_post(req_url, { "name": dut_name, diff --git a/py-json/cv_test_manager.py b/py-json/cv_test_manager.py index 92532caf..41e45497 100644 --- a/py-json/cv_test_manager.py +++ b/py-json/cv_test_manager.py @@ -9,7 +9,6 @@ import importlib import time import json from pprint import pprint -import argparse if sys.version_info[0] != 3: print("This script requires Python 3") @@ -56,9 +55,9 @@ def cv_add_base_parser(parser): parser.add_argument("-c", "--config_name", type=str, default="cv_dflt_cfg", help="Config file name") - parser.add_argument("-r", "--pull_report", default=False, action='store_true', + parser.add_argument("-r", "--pull_report", action='store_true', help="pull reports from lanforge (by default: False)") - parser.add_argument("--load_old_cfg", default=False, action='store_true', + parser.add_argument("--load_old_cfg", action='store_true', help="Should we first load defaults from previous run of the capacity test? Default is False") parser.add_argument("--enable", action='append', nargs=1, default=[], @@ -86,7 +85,7 @@ class cv_test(Realm): def __init__(self, lfclient_host="localhost", lfclient_port=8080, - lf_report_dir="" + lf_report_dir=None ): super().__init__(lfclient_host=lfclient_host, lfclient_port=lfclient_port) @@ -105,7 +104,7 @@ class cv_test(Realm): print("adding- " + text + " " + "to test config") - rsp = self.json_post(req_url, data) + self.json_post(req_url, data) # time.sleep(1) # Tell LANforge GUI Chamber View to launch a test @@ -138,24 +137,6 @@ class cv_test(Realm): cmd = "cv click '%s' Cancel" % instance self.run_cv_cmd(cmd) - # Send chamber view commands to the LANforge GUI - def run_cv_cmd(self, command): - response_json = [] - req_url = "/gui-json/cmd" - data = { - "cmd": command - } - debug_par = "" - rsp = self.json_post("/gui-json/cmd%s" % debug_par, data, debug_=False, response_json_list_=response_json) - try: - if response_json[0]["LAST"]["warnings"].startswith("Unknown"): - print("Unknown command?\n"); - pprint(response_json) - except: - # Ignore un-handled structs at this point, let calling code deal with it. - pass - return response_json - # For auto save report def auto_save_report(self, instance): cmd = "cv click %s 'Auto Save Report'" % instance @@ -165,16 +146,6 @@ class cv_test(Realm): def get_report_location(self, instance): cmd = "cv get %s 'Report Location:'" % instance location = self.run_cv_cmd(cmd) - var = 1 - while var != 0: - try: - data = json.dumps(location[0]["LAST"]["response"]) - var = 0 - except Exception as e: - var += 1 - time.sleep(2) - if var > 5: - break return location # To get if test is running or not @@ -216,7 +187,7 @@ class cv_test(Realm): if self.get_exists(instance): print("Waiting %i/60 for test instance: %s to be deleted." % (tries, instance)) tries += 1 - if (tries > 60): + if tries > 60: break time.sleep(1) else: @@ -226,9 +197,9 @@ class cv_test(Realm): tries = 0 while True: if not self.get_cv_is_built(): - print("Waiting %i/60 for Chamber-View to be built." % (tries)) + print("Waiting %i/60 for Chamber-View to be built." % tries) tries += 1 - if (tries > 60): + if tries > 60: break time.sleep(1) else: @@ -258,17 +229,18 @@ class cv_test(Realm): "type": "Plugin-Settings", "name": str(blob_test_name + config_name), # config name } - rsp = self.json_post(req_url, data) + self.json_post(req_url, data) - def rm_cv_text_blob(self, type="Network-Connectivity", name=None): + def rm_cv_text_blob(self, cv_type="Network-Connectivity", name=None): req_url = "/cli-json/rm_text_blob" data = { - "type": type, + "type": cv_type, "name": name, # config name } - rsp = self.json_post(req_url, data) + self.json_post(req_url, data) - def apply_cfg_options(self, cfg_options, enables, disables, raw_lines, raw_lines_file): + @staticmethod + def apply_cfg_options(cfg_options, enables, disables, raw_lines, raw_lines_file): # Read in calibration data and whatever else. if raw_lines_file != "": @@ -315,7 +287,7 @@ class cv_test(Realm): # cv_cmds: Array of raw chamber-view commands, such as "cv click 'button-name'" # These (and the sets) are applied after the test is created and before it is started. def create_and_run_test(self, load_old_cfg, test_name, instance_name, config_name, sets, - pull_report, lf_host, lf_user, lf_password, cv_cmds, local_lf_report_dir="", ssh_port=22, + pull_report, lf_host, lf_user, lf_password, cv_cmds, local_lf_report_dir=None, ssh_port=22, graph_groups_file=None): load_old = "false" if load_old_cfg: @@ -327,7 +299,7 @@ class cv_test(Realm): if response[0]["LAST"]["response"] == "OK": break else: - print("Could not create test, try: %i/60:\n" % (start_try)) + print("Could not create test, try: %i/60:\n" % start_try) pprint(response) start_try += 1 if start_try > 60: @@ -349,7 +321,7 @@ class cv_test(Realm): response = self.start_test(instance_name) if response[0]["LAST"]["response"].__contains__("Could not find instance:"): - print("ERROR: start_test failed: ", response[0]["LAST"]["response"], "\n"); + print("ERROR: start_test failed: ", response[0]["LAST"]["response"], "\n") # pprint(response) exit(1) @@ -357,16 +329,12 @@ class cv_test(Realm): while True: cmd = "cv get_and_close_dialog" dialog = self.run_cv_cmd(cmd) - try: - if dialog[0]["LAST"]["response"] != "NO-DIALOG": - print("Popup Dialog:\n") - print(dialog[0]["LAST"]["response"]) - except Exception as e: - print(e) + if dialog[0]["LAST"]["response"] != "NO-DIALOG": + print("Popup Dialog:\n") + print(dialog[0]["LAST"]["response"]) check = self.get_report_location(instance_name) location = json.dumps(check[0]["LAST"]["response"]) - if location != '\"Report Location:::\"': print(location) location = location.replace('\"Report Location:::', '') @@ -385,25 +353,25 @@ class cv_test(Realm): self.lf_report_dir = location if pull_report: try: - print(lf_host) + print("Pulling report to directory: %s from %s@%s/%s" % + (local_lf_report_dir, lf_user, lf_host, location)) report.pull_reports(hostname=lf_host, username=lf_user, password=lf_password, port=ssh_port, report_dir=local_lf_report_dir, report_location=location) except Exception as e: - print("SCP failed, user %s, password %s, dest %s", (lf_user, lf_password, lf_host)) + print("SCP failed, user %s, password %s, dest %s" % (lf_user, lf_password, lf_host)) raise e # Exception("Could not find Reports") break + else: + print('Not reporting to kpi file') # Of if test stopped for some reason and could not generate report. - try: - if not self.get_is_running(instance_name): - print("Detected test is not running.") - not_running += 1 - if not_running > 5: - break - except Exception as e: - print(e) - + if not self.get_is_running(instance_name): + print("Detected test is not running.") + not_running += 1 + if not_running > 5: + break + time.sleep(1) self.report_name = self.get_report_location(instance_name) # Ensure test is closed and cleaned up @@ -411,20 +379,17 @@ class cv_test(Realm): # Clean up any remaining popups. while True: - dialog = self.run_cv_cmd(cmd); + dialog = self.run_cv_cmd(cmd) if dialog[0]["LAST"]["response"] != "NO-DIALOG": print("Popup Dialog:\n") print(dialog[0]["LAST"]["response"]) else: break - def a(self): - pass - # Takes cmd-line args struct or something that looks like it. # See csv_to_influx.py::influx_add_parser_args for options, or --help. def check_influx_kpi(self, args): - if self.lf_report_dir == "": + if self.lf_report_dir is None: # Nothing to report on. print("Not submitting to influx, no report-dir.\n") return @@ -446,12 +411,12 @@ class cv_test(Realm): # lf_wifi_capacity_test.py may be run / initiated by a remote system against a lanforge # the local_lf_report_dir is where data is stored, if there is no local_lf_report_dir then the test is run directly on lanforge - if self.local_lf_report_dir == "": - csv_path = "%s/kpi.csv" % (self.lf_report_dir) + if self.lf_report_dir: + csv_path = "%s/kpi.csv" % self.lf_report_dir else: - kpi_location = self.local_lf_report_dir + "/" + os.path.basename(self.lf_report_dir) - # the local_lf_report_dir is the parent directory, need to get the directory name - csv_path = "%s/kpi.csv" % (kpi_location) + kpi_location = self.lf_report_dir + "/" + os.path.basename(self.lf_report_dir) + # the lf_report_dir is the parent directory, need to get the directory name + csv_path = "%s/kpi.csv" % kpi_location print("Attempt to submit kpi: ", csv_path) print("Posting to influx...\n") @@ -483,7 +448,7 @@ class cv_test(Realm): "text": text_blob } - rsp = self.json_post(req_url, data) + self.json_post(req_url, data) def pass_raw_lines_to_cv(self, scenario_name="Automation", @@ -494,7 +459,7 @@ class cv_test(Realm): "name": scenario_name, "text": Rawline } - rsp = self.json_post(req_url, data) + self.json_post(req_url, data) # This is for chamber view buttons @@ -520,18 +485,17 @@ class cv_test(Realm): def run_cv_cmd(self, command): # Send chamber view commands response_json = [] req_url = "/gui-json/cmd" - data = { - "cmd": command - } - rsp = self.json_post(req_url, data, debug_=False, response_json_list_=response_json) + data = {"cmd": command} + self.json_post(req_url, data, debug_=False, response_json_list_=response_json) return response_json - def get_response_string(self, response): + @staticmethod + def get_response_string(response): return response[0]["LAST"]["response"] def get_popup_info_and_close(self): cmd = "cv get_and_close_dialog" - dialog = self.run_cv_cmd(cmd); + dialog = self.run_cv_cmd(cmd) if dialog[0]["LAST"]["response"] != "NO-DIALOG": print("Popup Dialog:\n") print(dialog[0]["LAST"]["response"]) diff --git a/py-json/cv_test_reports.py b/py-json/cv_test_reports.py index 325bb9d9..83285410 100644 --- a/py-json/cv_test_reports.py +++ b/py-json/cv_test_reports.py @@ -1,9 +1,11 @@ import paramiko from scp import SCPClient + class lanforge_reports: - def pull_reports(self, hostname="localhost", port=22, username="lanforge", password="lanforge", + @staticmethod + def pull_reports(hostname="localhost", port=22, username="lanforge", password="lanforge", report_location="/home/lanforge/html-reports/", report_dir="../../../reports/"): ssh = paramiko.SSHClient() @@ -14,4 +16,3 @@ class lanforge_reports: with SCPClient(ssh.get_transport()) as scp: scp.get(remote_path=report_location, local_path=report_dir, recursive=True) scp.close() - diff --git a/py-json/dataplane_test_profile.py b/py-json/dataplane_test_profile.py index 77004472..0ec6f35a 100644 --- a/py-json/dataplane_test_profile.py +++ b/py-json/dataplane_test_profile.py @@ -39,7 +39,7 @@ class DataPlaneTest(ChamberViewBase): def main(): - obj = DataPlaneTest(lfclient_host="localhost", lfclient_port=8080, debug_=True) + DataPlaneTest(lfclient_host="localhost", lfclient_port=8080, debug_=True) if __name__ == '__main__': diff --git a/py-json/base_profile.py b/py-json/deprecated/base_profile.py similarity index 79% rename from py-json/base_profile.py rename to py-json/deprecated/base_profile.py index c73fed0d..0209a290 100644 --- a/py-json/base_profile.py +++ b/py-json/deprecated/base_profile.py @@ -2,7 +2,8 @@ import datetime import random import string -from pprint import pprint +from pprint import pformat + class BaseProfile: def __init__(self, local_realm, debug=False): @@ -11,9 +12,8 @@ class BaseProfile: self.debug = debug or local_realm.debug self.profiles = [] - def json_get(self, _req_url, debug_=False): - return self.parent_realm.json_get(_req_url, debug_=False) + return self.parent_realm.json_get(_req_url, debug_=debug_) def json_post(self, req_url=None, data=None, debug_=False, suppress_related_commands_=None): return self.parent_realm.json_post(_req_url=req_url, @@ -34,52 +34,56 @@ class BaseProfile: return self.parent_realm.rm_cx(cx_name) def rm_endp(self, ename, debug_=False, suppress_related_commands_=True): - self.parent_realm.rm_endp(ename, debug_=False, suppress_related_commands_=True) + self.parent_realm.rm_endp(ename, debug_=debug_, suppress_related_commands_=suppress_related_commands_) def name_to_eid(self, eid): return self.parent_realm.name_to_eid(eid) def set_endp_tos(self, ename, _tos, debug_=False, suppress_related_commands_=True): - return self.parent_realm.set_endp_tos(ename, _tos, debug_=False, suppress_related_commands_=True) + return self.parent_realm.set_endp_tos(ename, _tos, debug_=debug_, suppress_related_commands_=suppress_related_commands_) def wait_until_endps_appear(self, these_endp, debug=False): - return self.parent_realm.wait_until_endps_appear(these_endp, debug=False) + return self.parent_realm.wait_until_endps_appear(these_endp, debug=debug) def wait_until_cxs_appear(self, these_cx, debug=False): - return self.parent_realm.wait_until_cxs_appear(these_cx, debug=False) + return self.parent_realm.wait_until_cxs_appear(these_cx, debug=debug) def logg(self, message=None, audit_list=None): if audit_list is None: self.parent_realm.logg(message) for item in audit_list: - if (item is None): + if item is None: continue - message += ("\n" + pprint.pformat(item, indent=4)) + message += ("\n" + pformat(item, indent=4)) self.parent_realm.logg(message) - def replace_special_char(self, str): - return str.replace('+', ' ').replace('_', ' ').strip(' ') + @staticmethod + def replace_special_char(original): + return original.replace('+', ' ').replace('_', ' ').strip(' ') # @deprecate me - def get_milliseconds(self, timestamp): - return (timestamp - datetime.datetime(1970,1,1)).total_seconds()*1000 + @staticmethod + def get_milliseconds(timestamp): + return (timestamp - datetime.datetime(1970, 1, 1)).total_seconds() * 1000 # @deprecate me - def get_seconds(self, timestamp): - return (timestamp - datetime.datetime(1970,1,1)).total_seconds() + @staticmethod + def get_seconds(timestamp): + return (timestamp - datetime.datetime(1970, 1, 1)).total_seconds() - def read_file(self, filename): + @staticmethod + def read_file(filename): filename = open(filename, 'r') return [line.split(',') for line in filename.readlines()] - #Function to create random characters made of letters - def random_chars(self, size, chars=None): + # Function to create random characters made of letters + @staticmethod + def random_chars(size, chars=None): if chars is None: chars = string.ascii_letters - return ''.join(random.choice(chars) for x in range(size)) + return ''.join(random.choice(chars) for _ in range(size)) - - #--------------- create file path / find file path code - to be put into functions + # --------------- create file path / find file path code - to be put into functions # #Find file path to save data/csv to: # if args.report_file is None: # new_file_path = str(datetime.datetime.now().strftime("%Y-%m-%d-%H-h-%M-m-%S-s")).replace(':', @@ -100,7 +104,7 @@ class BaseProfile: # print('Not supporting this report format or cannot find report format provided. Defaulting to csv data file output type, naming it data.csv.') # report_f = str(path) + '/data.csv' # output = 'csv' - + # else: # report_f = args.report_file # if args.output_format is None: @@ -118,5 +122,3 @@ class BaseProfile: # exit(1) # else: # compared_rept=args.compared_report - - diff --git a/py-json/l3_cxprofile2.py b/py-json/deprecated/l3_cxprofile2.py similarity index 99% rename from py-json/l3_cxprofile2.py rename to py-json/deprecated/l3_cxprofile2.py index 1bbc3e08..de5398d9 100644 --- a/py-json/l3_cxprofile2.py +++ b/py-json/deprecated/l3_cxprofile2.py @@ -611,9 +611,9 @@ class L3CXProfile2(BaseProfile): raise ValueError("L3CXProfile::monitor wants duration_sec > 1 second") if (duration_sec <= monitor_interval_ms): raise ValueError("L3CXProfile::monitor wants duration_sec > monitor_interval") - if report_file == None: + if report_file is None: raise ValueError("Monitor requires an output file to be defined") - if created_cx == None: + if created_cx is None: raise ValueError("Monitor needs a list of Layer 3 connections") if (monitor_interval_ms is None) or (monitor_interval_ms < 1): raise ValueError("L3CXProfile::monitor wants monitor_interval >= 1 second") diff --git a/py-json/vr_profile2.py b/py-json/deprecated/vr_profile2.py similarity index 99% rename from py-json/vr_profile2.py rename to py-json/deprecated/vr_profile2.py index 7e994ddf..b2870e81 100644 --- a/py-json/vr_profile2.py +++ b/py-json/deprecated/vr_profile2.py @@ -74,7 +74,7 @@ class VRProfile(BaseProfile): def vr_eid_to_url(self, eid_str=None, debug=False): debug |= self.debug - if (eid_str is None) or ("" == eid_str) or (eid_str.index(".") < 1): + if (eid_str is None) or (eid_str == "") or (eid_str.index(".") < 1): raise ValueError("vr_eid_to_url cannot read eid[%s]" % eid_str) hunks = eid_str.split(".") if len(hunks) > 3: @@ -111,7 +111,7 @@ class VRProfile(BaseProfile): resource=1, debug=False): debug |= self.debug - if (resource is None) or (resource == 0) or ("" == resource): + if (resource is None) or (resource == 0) or (resource == ""): raise ValueError("resource needs to be a number greater than 1") router_map = self.router_list(resource=resource, debug=debug) @@ -334,9 +334,9 @@ class VRProfile(BaseProfile): :return: True if area is inside listed virtual router(s) """ debug |= self.debug - if (resource is None) or (resource == 0) or ("" == resource): + if (resource is None) or (resource == 0) or (resource == ""): raise ValueError("resource needs to be a number greater than 1") - if (vrcx_rect is None) or type(vrcx_rect ) or ("" == resource): + if (vrcx_rect is None) or type(vrcx_rect) or (resource == ""): raise ValueError("resource needs to be a number greater than 1") router_list = self.router_list(resource=resource, debug=debug) #router_list = self.json_get("/vr/1/%s/%s?fields=eid,x,y,height,width") diff --git a/py-json/dut_profile.py b/py-json/dut_profile.py index 141ff953..aa1a9f28 100644 --- a/py-json/dut_profile.py +++ b/py-json/dut_profile.py @@ -50,10 +50,10 @@ class DUTProfile(LFCliBase): self.append = [] def set_param(self, name, value): - if (name in self.__dict__): + if name in self.__dict__: self.__dict__[name] = value - def create(self, name=None, param_=None, flags=None, flags_mask=None, notes=None): + def create(self, name=None, flags=None, flags_mask=None): data = {} if (name is not None) and (name != ""): data["name"] = name @@ -63,7 +63,7 @@ class DUTProfile(LFCliBase): raise ValueError("cannot create/update DUT record lacking a name") for param in add_dut.dut_params: - if (param.name in self.__dict__): + if param.name in self.__dict__: if (self.__dict__[param.name] is not None) \ and (self.__dict__[param.name] != "NA"): data[param.name] = self.__dict__[param.name] @@ -97,7 +97,6 @@ class DUTProfile(LFCliBase): "dut": self.name, "text": "[BLANK]" }, self.debug) - notebytes = None for line in self.notes: notebytes = base64.b64encode(line.encode('ascii')) if self.debug: @@ -110,7 +109,6 @@ class DUTProfile(LFCliBase): "text-64": notebytes.decode('ascii') }, self.debug) if (self.append is not None) and (len(self.append) > 0): - notebytes = None for line in self.append: notebytes = base64.b64encode(line.encode('ascii')) if self.debug: diff --git a/py-json/fio_endp_profile.py b/py-json/fio_endp_profile.py index a3497923..5eed7b7d 100644 --- a/py-json/fio_endp_profile.py +++ b/py-json/fio_endp_profile.py @@ -121,7 +121,9 @@ class FIOEndpProfile(LFCliBase): self.json_post(req_url, data) # pprint(data) - def create(self, ports=[], connections_per_port=1, sleep_time=.5, debug_=False, suppress_related_commands_=None): + def create(self, ports=None, connections_per_port=1, sleep_time=.5, debug_=False, suppress_related_commands_=None): + if ports is None: + ports = [] cx_post_data = [] for port_name in ports: for num_connection in range(connections_per_port): @@ -173,8 +175,6 @@ class FIOEndpProfile(LFCliBase): self.local_realm.json_post("/cli-json/nc_show_endpoints", {"endpoint": "all"}) for port_name in ports: for num_connection in range(connections_per_port): - shelf = self.local_realm.name_to_eid(port_name)[0] - resource = self.local_realm.name_to_eid(port_name)[1] name = self.local_realm.name_to_eid(port_name)[2] endp_data = { diff --git a/py-json/gen_cxprofile.py b/py-json/gen_cxprofile.py index f2d870c5..0612c577 100644 --- a/py-json/gen_cxprofile.py +++ b/py-json/gen_cxprofile.py @@ -9,7 +9,6 @@ import time import datetime import json - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") @@ -49,7 +48,7 @@ class GenCXProfile(LFCliBase): if self.cmd == "": raise ValueError("Please ensure cmd has been set correctly") elif self.type == "speedtest": - self.cmd = "vrf_exec.bash %s speedtest-cli --json --share" % (sta_name) + self.cmd = "vrf_exec.bash %s speedtest-cli --json --share" % sta_name elif self.type == "iperf3" and self.dest is not None: self.cmd = "iperf3 --forceflush --format k --precision 4 -c %s -t 60 --tos 0 -b 1K --bind_dev %s -i 1 " \ "--pidfile /tmp/lf_helper_iperf3_%s.pid" % (self.dest, sta_name, gen_name) @@ -132,7 +131,7 @@ class GenCXProfile(LFCliBase): if self.cmd == "": raise ValueError("Please ensure cmd has been set correctly") elif self.type == "speedtest": - self.cmd = "vrf_exec.bash %s speedtest-cli --json --share" % (sta_name) + self.cmd = "vrf_exec.bash %s speedtest-cli --json --share" % sta_name elif self.type == "iperf3" and self.dest is not None: self.cmd = "iperf3 --forceflush --format k --precision 4 -c %s -t 60 --tos 0 -b 1K --bind_dev %s -i 1 " \ "--pidfile /tmp/lf_helper_iperf3_test.pid" % (self.dest, sta_name) @@ -176,7 +175,7 @@ class GenCXProfile(LFCliBase): resource = port_info[1] shelf = port_info[0] name = port_info[2] - except: + except ValueError: raise ValueError("Unexpected name for port_name %s" % port_name) # this naming convention follows what you see when you use @@ -278,7 +277,9 @@ class GenCXProfile(LFCliBase): }) time.sleep(sleep_time) - def create(self, ports=[], sleep_time=.5, debug_=False, suppress_related_commands_=None): + def create(self, ports=None, sleep_time=.5, debug_=False, suppress_related_commands_=None): + if ports is None: + ports = [] if self.debug: debug_ = True post_data = [] @@ -396,12 +397,11 @@ class GenCXProfile(LFCliBase): gen_results = self.json_get("generic/list?fields=name,last+results", debug_=self.debug) if gen_results['endpoints'] is not None: pprint(gen_results['endpoints']) - #for name in gen_results['endpoints']: - # pprint(name.items) - #for k,v in name.items(): + # for name in gen_results['endpoints']: + # pprint(name.items) + # for k,v in name.items(): exit(1) - def choose_speedtest_command(self): gen_results = self.json_get("generic/list?fields=name,last+results", debug_=self.debug) if gen_results['endpoints'] is not None: @@ -412,13 +412,13 @@ class GenCXProfile(LFCliBase): if last_results['download'] is None and last_results['upload'] is None and last_results['ping'] is None: return False, v['name'] elif last_results['download'] >= self.speedtest_min_dl and \ - last_results['upload'] >= self.speedtest_min_up and \ - last_results['ping'] <= self.speedtest_max_ping: + last_results['upload'] >= self.speedtest_min_up and \ + last_results['ping'] <= self.speedtest_max_ping: return True, v['name'] def choose_generic_command(self): gen_results = self.json_get("generic/list?fields=name,last+results", debug_=self.debug) - if (gen_results['endpoints'] is not None): + if gen_results['endpoints'] is not None: for name in gen_results['endpoints']: for k, v in name.items(): if v['name'] in self.created_endp and not v['name'].endswith('1'): @@ -444,10 +444,10 @@ class GenCXProfile(LFCliBase): debug=False): try: duration_sec = self.parse_time(duration_sec).seconds - except: + except ValueError: if (duration_sec is None) or (duration_sec <= 1): raise ValueError("GenCXProfile::monitor wants duration_sec > 1 second") - if (duration_sec <= monitor_interval_ms): + if duration_sec <= monitor_interval_ms: raise ValueError("GenCXProfile::monitor wants duration_sec > monitor_interval") if report_file is None: raise ValueError("Monitor requires an output file to be defined") @@ -602,7 +602,9 @@ class GenCXProfile(LFCliBase): exit(1) # append compared df to created one if output_format.lower() != 'csv': - pandas_extensions.df_to_file(dataframe=pd.read_csv(report_file), output_f=output_format, save_path=report_file) + pandas_extensions.df_to_file(dataframe=pd.read_csv(report_file), output_f=output_format, + save_path=report_file) else: if output_format.lower() != 'csv': - pandas_extensions.df_to_file(dataframe=pd.read_csv(report_file), output_f=output_format, save_path=report_file) + pandas_extensions.df_to_file(dataframe=pd.read_csv(report_file), output_f=output_format, + save_path=report_file) diff --git a/py-json/http_profile.py b/py-json/http_profile.py index 9acd05d5..098d681f 100644 --- a/py-json/http_profile.py +++ b/py-json/http_profile.py @@ -4,7 +4,6 @@ import os import importlib import time - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) port_utils = importlib.import_module("py-json.port_utils") @@ -26,7 +25,8 @@ class HTTPProfile(LFCliBase): self.direction = "dl" self.dest = "/dev/null" self.port_util = PortUtils(self.local_realm) - self.max_speed = 0 #infinity + self.max_speed = 0 # infinity + self.quiesce_after = 0 # infinity def check_errors(self, debug=False): fields_list = ["!conn", "acc.+denied", "bad-proto", "bad-url", "other-err", "total-err", "rslv-p", "rslv-h", @@ -91,7 +91,9 @@ class HTTPProfile(LFCliBase): self.json_post(req_url, data) # pprint(data) - def map_sta_ips(self, sta_list=[]): + def map_sta_ips(self, sta_list=None): + if sta_list is None: + sta_list = [] for sta_eid in sta_list: eid = self.local_realm.name_to_eid(sta_eid) sta_list = self.json_get("/port/%s/%s/%s?fields=alias,ip" % @@ -99,8 +101,11 @@ class HTTPProfile(LFCliBase): if sta_list['interface'] is not None: self.ip_map[sta_list['interface']['alias']] = sta_list['interface']['ip'] - def create(self, ports=[], sleep_time=.5, debug_=False, suppress_related_commands_=None, http=False, ftp=False, - https=False, user=None, passwd=None, source=None, ftp_ip=None, upload_name=None, http_ip=None, https_ip=None): + def create(self, ports=None, sleep_time=.5, debug_=False, suppress_related_commands_=None, http=False, ftp=False, + https=False, user=None, passwd=None, source=None, ftp_ip=None, upload_name=None, http_ip=None, + https_ip=None): + if ports is None: + ports = [] cx_post_data = [] self.map_sta_ips(ports) print("Create CXs...") @@ -121,7 +126,7 @@ class HTTPProfile(LFCliBase): resource = self.local_realm.name_to_eid(port_name)[1] name = self.local_realm.name_to_eid(port_name)[2] - if upload_name != None: + if upload_name is not None: name = upload_name if http: @@ -143,7 +148,7 @@ class HTTPProfile(LFCliBase): self.port_util.set_ftp(port_name=name, resource=resource, on=True) if user is not None and passwd is not None and source is not None: if ftp_ip is not None: - ip_addr=ftp_ip + ip_addr = ftp_ip url = "%s ftp://%s:%s@%s%s %s" % (self.direction, user, passwd, ip_addr, source, self.dest) print("###### url:{}".format(url)) else: @@ -154,7 +159,7 @@ class HTTPProfile(LFCliBase): if (url is None) or (url == ""): raise ValueError("HTTPProfile::create: url unset") - if upload_name ==None: + if upload_name is None: endp_data = { "alias": name + "_l4", "shelf": shelf, @@ -164,7 +169,9 @@ class HTTPProfile(LFCliBase): "timeout": 10, "url_rate": self.requests_per_ten, "url": url, - "proxy_auth_type": 0x200 + "proxy_auth_type": 0x200, + "quiesce_after": self.quiesce_after, + "max_speed": self.max_speed } else: endp_data = { @@ -179,7 +186,8 @@ class HTTPProfile(LFCliBase): "ssl_cert_fname": "ca-bundle.crt", "proxy_port": 0, "max_speed": self.max_speed, - "proxy_auth_type": 0x200 + "proxy_auth_type": 0x200, + "quiesce_after": self.quiesce_after } url = "cli-json/add_l4_endp" self.local_realm.json_post(url, endp_data, debug_=debug_, diff --git a/py-json/l3_cxprofile.py b/py-json/l3_cxprofile.py index 524820fb..cb8937b7 100644 --- a/py-json/l3_cxprofile.py +++ b/py-json/l3_cxprofile.py @@ -2,18 +2,18 @@ import sys import os import importlib -from pprint import pprint -import csv +import pprint import pandas as pd import time import datetime - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") LFCliBase = lfcli_base.LFCliBase pandas_extensions = importlib.import_module("py-json.LANforge.pandas_extensions") +port_probe = importlib.import_module("py-json.port_probe") +ProbePort = port_probe.ProbePort class L3CXProfile(LFCliBase): @@ -21,8 +21,8 @@ class L3CXProfile(LFCliBase): lfclient_host, lfclient_port, local_realm, - side_a_min_bps=None, - side_b_min_bps=None, + side_a_min_bps=256000, + side_b_min_bps=256000, side_a_max_bps=0, side_b_max_bps=0, side_a_min_pdu=-1, @@ -76,10 +76,10 @@ class L3CXProfile(LFCliBase): return self.created_cx.keys() def get_cx_report(self): - self.data = {} + data = dict() for cx_name in self.get_cx_names(): - self.data[cx_name] = self.json_get("/cx/" + cx_name).get(cx_name) - return self.data + data[cx_name] = self.json_get("/cx/" + cx_name).get(cx_name) + return data def __get_rx_values(self): cx_list = self.json_get("endp?fields=name,rx+bytes") @@ -95,7 +95,8 @@ class L3CXProfile(LFCliBase): cx_rx_map[item] = value_rx return cx_rx_map - def __compare_vals(self, old_list, new_list): + @staticmethod + def __compare_vals(old_list, new_list): passes = 0 expected_passes = 0 if len(old_list) == len(new_list): @@ -121,7 +122,6 @@ class L3CXProfile(LFCliBase): layer3_cols=None, port_mgr_cols=None, created_cx=None, - monitor=True, report_file=None, systeminfopath=None, output_format=None, @@ -129,24 +129,23 @@ class L3CXProfile(LFCliBase): arguments=None, compared_report=None, debug=False): - try: + if duration_sec: duration_sec = self.parse_time(duration_sec).seconds - except: - if (duration_sec is None) or (duration_sec <= 1): - raise ValueError("L3CXProfile::monitor wants duration_sec > 1 second") - if (duration_sec <= monitor_interval_ms): - raise ValueError("L3CXProfile::monitor wants duration_sec > monitor_interval") - if report_file == None: + else: + raise ValueError("L3CXProfile::monitor wants duration_sec > 1 second") + if duration_sec <= monitor_interval_ms: + raise ValueError("L3CXProfile::monitor wants duration_sec > monitor_interval") + if report_file is None: raise ValueError("Monitor requires an output file to be defined") - if systeminfopath == None: + if systeminfopath is None: raise ValueError("Monitor requires a system info path to be defined") - if created_cx == None: + if created_cx is None: raise ValueError("Monitor needs a list of Layer 3 connections") if (monitor_interval_ms is None) or (monitor_interval_ms < 1): raise ValueError("L3CXProfile::monitor wants monitor_interval >= 1 second") if layer3_cols is None: raise ValueError("L3CXProfile::monitor wants a list of column names to monitor") - if output_format is not None: + if output_format: if output_format.lower() != report_file.split('.')[-1]: raise ValueError('Filename %s has an extension that does not match output format %s .' % ( report_file, output_format)) @@ -163,13 +162,16 @@ class L3CXProfile(LFCliBase): layer3_fields = ",".join(layer3_cols) default_cols = ['Timestamp', 'Timestamp milliseconds epoch', 'Timestamp seconds epoch', 'Duration elapsed'] default_cols.extend(layer3_cols) - if port_mgr_cols is not None: + # append alias to port_mgr_cols if not present needed later + if port_mgr_cols: + if 'alias' not in port_mgr_cols: + port_mgr_cols.append('alias') + + if port_mgr_cols: default_cols.extend(port_mgr_cols) header_row = default_cols - # csvwriter.writerow([systeminfo['VersionInfo']['BuildVersion'], script_name, str(arguments)]) - - if port_mgr_cols is not None: + if port_mgr_cols: port_mgr_cols = [self.replace_special_char(x) for x in port_mgr_cols] port_mgr_cols_labelled = [] for col_name in port_mgr_cols: @@ -193,59 +195,25 @@ class L3CXProfile(LFCliBase): expected_passes = 0 old_cx_rx_values = self.__get_rx_values() - # instantiate csv file here, add specified column headers - csvfile = open(str(report_file), 'w') - csvwriter = csv.writer(csvfile, delimiter=",") - csvwriter.writerow(header_row) - # wait 10 seconds to get proper port data time.sleep(10) # for x in range(0,int(round(iterations,0))): initial_starttime = datetime.datetime.now() + timestamp_data = list() while datetime.datetime.now() < end_time: t = datetime.datetime.now() timestamp = t.strftime("%m/%d/%Y %I:%M:%S") t_to_millisec_epoch = int(self.get_milliseconds(t)) t_to_sec_epoch = int(self.get_seconds(t)) time_elapsed = int(self.get_seconds(t)) - int(self.get_seconds(initial_starttime)) - basecolumns = [timestamp, t_to_millisec_epoch, t_to_sec_epoch, time_elapsed] - layer_3_response = self.json_get("/endp/%s?fields=%s" % (created_cx, layer3_fields)) - if port_mgr_cols is not None: - port_mgr_response = self.json_get("/port/1/1/%s?fields=%s" % (sta_list, port_mgr_fields)) - # get info from port manager with list of values from cx_a_side_list - if "endpoint" not in layer_3_response or layer_3_response is None: - print(layer_3_response) - raise ValueError("Cannot find columns requested to be searched. Exiting script, please retry.") - if debug: - print("Json layer_3_response from LANforge... " + str(layer_3_response)) - if port_mgr_cols is not None: - if "interfaces" not in port_mgr_response or port_mgr_response is None: - print(port_mgr_response) - raise ValueError("Cannot find columns requested to be searched. Exiting script, please retry.") - if debug: - print("Json port_mgr_response from LANforge... " + str(port_mgr_response)) + stations = [station.split('.')[-1] for station in sta_list] + stations = ','.join(stations) - for endpoint in layer_3_response["endpoint"]: # each endpoint is a dictionary - endp_values = list(endpoint.values())[0] - temp_list = basecolumns - for columnname in header_row[len(basecolumns):]: - temp_list.append(endp_values[columnname]) - if port_mgr_cols is not None: - for sta_name in sta_list_edit: - if sta_name in current_sta: - for interface in port_mgr_response["interfaces"]: - if sta_name in list(interface.keys())[0]: - merge = temp_endp_values.copy() - # rename keys (separate port mgr 'rx bytes' from layer3 'rx bytes') - port_mgr_values_dict = list(interface.values())[0] - renamed_port_cols = {} - for key in port_mgr_values_dict.keys(): - renamed_port_cols['port mgr - ' + key] = port_mgr_values_dict[key] - merge.update(renamed_port_cols) - for name in port_mgr_cols: - temp_list.append(merge[name]) - csvwriter.writerow(temp_list) + if port_mgr_cols: + port_mgr_response = self.json_get("/port/1/1/%s?fields=%s" % (stations, port_mgr_fields)) + + layer_3_response = self.json_get("/endp/%s?fields=%s" % (created_cx, layer3_fields)) new_cx_rx_values = self.__get_rx_values() if debug: @@ -258,38 +226,130 @@ class L3CXProfile(LFCliBase): passes += 1 else: self.fail("FAIL: Not all stations increased traffic") - self.exit_fail() - try: - cx_data = self.json_get("/cx/all") - cx_data.pop("handler") - cx_data.pop("uri") - for i in self.created_cx.keys(): - endp_a_data = self.json_get("/endp/"+ cx_data[i]['endpoints'][0]) - endp_b_data = self.json_get("/endp/" + cx_data[i]['endpoints'][1]) - print("cx name:", i, "\n", - " bps tx a :", endp_a_data['endpoint']['tx rate'], " --> ", - " bps rx b : ", endp_b_data['endpoint']['rx rate'], - " rx drop % b : ", cx_data[i]['rx drop % b'], "\n" - " tx bytes a : ", endp_a_data['endpoint']['tx bytes'], " --> " - " rx bytes b", endp_b_data['endpoint']['rx bytes'], "\n" - " tx bytes b : ", endp_b_data['endpoint']['tx bytes'], " --> " - " rx bytes a", endp_a_data['endpoint']['rx bytes'], "\n" - " bps tx b :", endp_b_data['endpoint']['tx rate'], " --> " - " bps rx a : ", endp_a_data['endpoint']['rx rate'], - " rx drop % a :", cx_data[i]['rx drop % a'], "\n" - " pkt rx a :", cx_data[i]['pkt rx a'], " pkt rx b : ", cx_data[i]['pkt rx b'], - ) - print("\n\n\n") - except Exception as e: - print(e) + result = dict() # create dataframe from layer 3 results + if type(layer_3_response) is dict: + for dictionary in layer_3_response['endpoint']: + # if debug: + print('layer_3_data: %s' % dictionary) + result.update(dictionary) + else: + pass + layer3 = pd.DataFrame(result.values()) + layer3.columns = ['l3-' + x for x in layer3.columns] + + if port_mgr_cols: # create dataframe from port mgr results + result = dict() + if type(port_mgr_response) is dict: + print("port_mgr_response {pmr}".format(pmr=port_mgr_response)) + if 'interfaces' in port_mgr_response: + for dictionary in port_mgr_response['interfaces']: + if debug: + print('port mgr data: %s' % dictionary) + result.update(dictionary) + + elif 'interface' in port_mgr_response: + dict_update = {port_mgr_response['interface']['alias']: port_mgr_response['interface']} + if debug: + print(dict_update) + result.update(dict_update) + if debug: + print(result) + else: + print('interfaces and interface not in port_mgr_response') + exit(1) + portdata_df = pd.DataFrame(result.values()) + print("portdata_df {pd}".format(pd=portdata_df)) + portdata_df.columns = ['port-' + x for x in portdata_df.columns] + portdata_df['alias'] = portdata_df['port-alias'] + + layer3_alias = list() # Add alias to layer 3 dataframe + for cross_connect in layer3['l3-name']: + for port in portdata_df['port-alias']: + if port in cross_connect: + layer3_alias.append(port) + if len(layer3_alias) == layer3.shape[0]: + layer3['alias'] = layer3_alias + else: + raise ValueError("The Stations or Connection on LANforge did not match expected, \ + Check if LANForge initial state correct or delete/cleanup corrects") + + timestamp_df = pd.merge(layer3, portdata_df, on='alias') + else: + timestamp_df = layer3 + probe_port_df_list = list() + for station in sta_list: + probe_port = ProbePort(lfhost=self.lfclient_host, + lfport=self.lfclient_port, + eid_str=station, + debug=self.debug) + probe_results = dict() + probe_port.refreshProbe() + probe_results['Signal Avg Combined'] = probe_port.getSignalAvgCombined() + probe_results['Signal Avg per Chain'] = probe_port.getSignalAvgPerChain() + probe_results['Signal Combined'] = probe_port.getSignalCombined() + probe_results['Signal per Chain'] = probe_port.getSignalPerChain() + if 'Beacon Av Signal' in probe_results.keys(): + probe_results['Beacon Avg Signal'] = probe_port.getBeaconSignalAvg() + else: + probe_results['Beacon Avg Signal'] = "0" + # probe_results['HE status'] = probe_port.he + probe_results['TX Bitrate'] = probe_port.tx_bitrate + probe_results['TX Mbps'] = probe_port.tx_mbit + probe_results['TX MCS ACTUAL'] = probe_port.tx_mcs + if probe_port.tx_mcs: + probe_results['TX MCS'] = int(probe_port.tx_mcs) % 8 + else: + probe_results['TX MCS'] = probe_port.tx_mcs + probe_results['TX NSS'] = probe_port.tx_nss + probe_results['TX MHz'] = probe_port.tx_mhz + if probe_port.tx_gi: + probe_results['TX GI ns'] = (probe_port.tx_gi * 10**9) + else: + probe_results['TX GI ns'] = probe_port.tx_gi + probe_results['TX Mbps Calc'] = probe_port.tx_mbit_calc + probe_results['TX GI'] = probe_port.tx_gi + probe_results['TX Mbps short GI'] = probe_port.tx_data_rate_gi_short_Mbps + probe_results['TX Mbps long GI'] = probe_port.tx_data_rate_gi_long_Mbps + probe_results['RX Bitrate'] = probe_port.rx_bitrate + probe_results['RX Mbps'] = probe_port.rx_mbit + probe_results['RX MCS ACTUAL'] = probe_port.rx_mcs + if probe_port.rx_mcs: + probe_results['RX MCS'] = int(probe_port.rx_mcs) % 8 + else: + probe_results['RX MCS'] = probe_port.rx_mcs + probe_results['RX NSS'] = probe_port.rx_nss + probe_results['RX MHz'] = probe_port.rx_mhz + if probe_port.rx_gi: + probe_results['RX GI ns'] = (probe_port.rx_gi * 10**9) + else: + probe_results['RX GI ns'] = probe_port.rx_gi + probe_results['RX Mbps Calc'] = probe_port.rx_mbit_calc + probe_results['RX GI'] = probe_port.rx_gi + probe_results['RX Mbps short GI'] = probe_port.rx_data_rate_gi_short_Mbps + probe_results['RX Mbps long GI'] = probe_port.rx_data_rate_gi_long_Mbps + + probe_df_initial = pd.DataFrame(probe_results.values()).transpose() + probe_df_initial.columns = probe_results.keys() + probe_df_initial.columns = ['probe ' + x for x in probe_df_initial.columns] + probe_df_initial['alias'] = station.split('.')[-1] + probe_port_df_list.append(probe_df_initial) + probe_port_df = pd.concat(probe_port_df_list) + timestamp_df = pd.merge(timestamp_df, probe_port_df, on='alias') + timestamp_df['Timestamp'] = timestamp + timestamp_df['Timestamp milliseconds epoch'] = t_to_millisec_epoch + timestamp_df['Timestamp seconds epoch'] = t_to_sec_epoch + timestamp_df['Duration elapsed'] = time_elapsed + timestamp_data.append(timestamp_df) time.sleep(monitor_interval_ms) - csvfile.close() + df = pd.concat(timestamp_data) + df = df.drop('alias', axis=1) + df.to_csv(str(report_file), index=False) # comparison to last report / report inputted - if compared_report is not None: - compared_df = pandas_extensions.compare_two_df(dataframe_one=pandas_extensions.file_to_df(report_file), - dataframe_two=pandas_extensions.file_to_df(compared_report)) + if compared_report: + pandas_extensions.compare_two_df(dataframe_one=pandas_extensions.file_to_df(report_file), + dataframe_two=pandas_extensions.file_to_df(compared_report)) exit(1) # append compared df to created one if output_format.lower() != 'csv': @@ -310,7 +370,7 @@ class L3CXProfile(LFCliBase): print("Starting CXs...") for cx_name in self.created_cx.keys(): if self.debug: - print("cx-name: %s" % (cx_name)) + print("cx-name: %s" % cx_name) self.json_post("/cli-json/set_cx_state", { "test_mgr": "default_tm", "cx_name": cx_name, @@ -336,13 +396,13 @@ class L3CXProfile(LFCliBase): if len(self.created_cx) != 0: for cx_name in self.created_cx.keys(): if self.debug: - print("Cleaning cx: %s" % (cx_name)) + print("Cleaning cx: %s" % cx_name) self.local_realm.rm_cx(cx_name) for side in range(len(self.created_cx[cx_name])): ename = self.created_cx[cx_name][side] if self.debug: - print("Cleaning endpoint: %s" % (ename)) + print("Cleaning endpoint: %s" % ename) self.local_realm.rm_endp(self.created_cx[cx_name][side]) self.clean_cx_lists() @@ -382,8 +442,6 @@ class L3CXProfile(LFCliBase): side_a_info = self.local_realm.name_to_eid(port_name, debug=debug_) side_a_shelf = side_a_info[0] side_a_resource = side_a_info[1] - if port_name.find('.') < 0: - port_name = "%d.%s" % (side_a_info[1], port_name) cx_name = "%s%s-%i" % (self.name_prefix, side_a_info[2], len(self.created_cx)) @@ -456,7 +514,7 @@ class L3CXProfile(LFCliBase): self.local_realm.json_post(url, data, debug_=debug_, suppress_related_commands_=suppress_related_commands) - if tos != None: + if tos: self.local_realm.set_endp_tos(endp_a_name, tos) self.local_realm.set_endp_tos(endp_b_name, tos) @@ -485,7 +543,6 @@ class L3CXProfile(LFCliBase): side_b_info = self.local_realm.name_to_eid(port_name, debug=debug_) side_b_shelf = side_b_info[0] side_b_resource = side_b_info[1] - side_b_name = side_b_info[2] cx_name = "%s%s-%i" % (self.name_prefix, port_name, len(self.created_cx)) endp_a_name = cx_name + "-A" diff --git a/py-json/l4_cxprofile.py b/py-json/l4_cxprofile.py index 25138e72..d562d3c6 100644 --- a/py-json/l4_cxprofile.py +++ b/py-json/l4_cxprofile.py @@ -8,7 +8,6 @@ import time import datetime import ast - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") @@ -74,7 +73,8 @@ class L4CXProfile(LFCliBase): print(".", end='') print("") - def compare_vals(self, old_list, new_list): + @staticmethod + def compare_vals(old_list, new_list): passes = 0 expected_passes = 0 if len(old_list) == len(new_list): @@ -139,10 +139,16 @@ class L4CXProfile(LFCliBase): self.json_post(req_url, data) # pprint(data) - def create(self, ports=[], sleep_time=.5, debug_=False, suppress_related_commands_=None): + def create(self, ports=None, sleep_time=.5, debug_=False, suppress_related_commands_=None): + if ports is None: + ports = [] cx_post_data = [] for port_name in ports: - print("port_name: {} len: {} self.local_realm.name_to_eid(port_name): {}".format(port_name, len(self.local_realm.name_to_eid(port_name)), self.local_realm.name_to_eid(port_name))) + print("port_name: {} len: {} self.local_realm.name_to_eid(port_name): {}".format(port_name, + len(self.local_realm.name_to_eid( + port_name)), + self.local_realm.name_to_eid( + port_name))) shelf = self.local_realm.name_to_eid(port_name)[0] resource = self.local_realm.name_to_eid(port_name)[1] name = self.local_realm.name_to_eid(port_name)[2] @@ -189,16 +195,16 @@ class L4CXProfile(LFCliBase): arguments=None, iterations=0, debug=False): - try: + if duration_sec: duration_sec = LFCliBase.parse_time(duration_sec).seconds - except: + else: if (duration_sec is None) or (duration_sec <= 1): raise ValueError("L4CXProfile::monitor wants duration_sec > 1 second") - if (duration_sec <= monitor_interval): - raise ValueError("L4CXProfile::monitor wants duration_sec > monitor_interval") - if report_file == None: + if duration_sec <= monitor_interval: + raise ValueError("L4CXProfile::monitor wants duration_sec > monitor_interval") + if report_file is None: raise ValueError("Monitor requires an output file to be defined") - if created_cx == None: + if created_cx is None: raise ValueError("Monitor needs a list of Layer 4 connections") if (monitor_interval is None) or (monitor_interval < 1): raise ValueError("L4CXProfile::monitor wants monitor_interval >= 1 second") @@ -211,20 +217,20 @@ class L4CXProfile(LFCliBase): # Step 1 - Assign column names if col_names is not None and len(col_names) > 0: - header_row=col_names + header_row = col_names else: - header_row=list((list(self.json_get("/layer4/all")['endpoint'][0].values())[0].keys())) + header_row = list((list(self.json_get("/layer4/all")['endpoint'][0].values())[0].keys())) if debug: print(header_row) # Step 2 - Monitor columns start_time = datetime.datetime.now() end_time = start_time + datetime.timedelta(seconds=duration_sec) - sleep_interval = round(duration_sec // 5) + sleep_interval = round(duration_sec // 5) if debug: print("Sleep_interval is %s ", sleep_interval) - print("Start time is %s " , start_time) - print("End time is %s " ,end_time) + print("Start time is %s ", start_time) + print("End time is %s ", end_time) value_map = dict() passes = 0 expected_passes = 0 @@ -232,7 +238,7 @@ class L4CXProfile(LFCliBase): if self.test_type != 'urls': old_rx_values = self.get_bytes() - for test in range(1+iterations): + for test in range(1 + iterations): while datetime.datetime.now() < end_time: if col_names is None: response = self.json_get("/layer4/all") @@ -276,10 +282,10 @@ class L4CXProfile(LFCliBase): print(value_map) - #[further] post-processing data, after test completion + # [further] post-processing data, after test completion full_test_data_list = [] for test_timestamp, data in value_map.items(): - #reduce the endpoint data to single dictionary of dictionaries + # reduce the endpoint data to single dictionary of dictionaries for datum in data["endpoint"]: for endpoint_data in datum.values(): if debug: @@ -287,19 +293,19 @@ class L4CXProfile(LFCliBase): endpoint_data["Timestamp"] = test_timestamp full_test_data_list.append(endpoint_data) - header_row.append("Timestamp") header_row.append('Timestamp milliseconds') df = pd.DataFrame(full_test_data_list) df["Timestamp milliseconds"] = [self.get_milliseconds(x) for x in df["Timestamp"]] - #round entire column - df["Timestamp milliseconds"]=df["Timestamp milliseconds"].astype(int) - df["Timestamp"]=df["Timestamp"].apply(lambda x:x.strftime("%m/%d/%Y %I:%M:%S")) - df=df[["Timestamp","Timestamp milliseconds", *header_row[:-2]]] - #compare previous data to current data + # round entire column + df["Timestamp milliseconds"] = df["Timestamp milliseconds"].astype(int) + df["Timestamp"] = df["Timestamp"].apply(lambda x: x.strftime("%m/%d/%Y %I:%M:%S")) + df = df[["Timestamp", "Timestamp milliseconds", *header_row[:-2]]] + # compare previous data to current data - systeminfo = ast.literal_eval(requests.get('http://'+str(self.lfclient_host)+':'+str(self.lfclient_port)).text) + systeminfo = ast.literal_eval( + requests.get('http://' + str(self.lfclient_host) + ':' + str(self.lfclient_port)).text) if output_format == 'hdf': df.to_hdf(report_file, 'table', append=True) @@ -312,7 +318,7 @@ class L4CXProfile(LFCliBase): df.to_excel(report_file, index=False) if output_format == 'df': return df - supported_formats = ['csv', 'json', 'stata', 'pickle','html'] + supported_formats = ['csv', 'json', 'stata', 'pickle', 'html'] for x in supported_formats: if output_format.lower() == x or report_file.split('.')[-1] == x: - exec('df.to_' + x + '("'+report_file+'")') + exec('df.to_' + x + '("' + report_file + '")') diff --git a/py-json/lf_cv_base.py b/py-json/lf_cv_base.py index 4016c03c..ab916a2c 100644 --- a/py-json/lf_cv_base.py +++ b/py-json/lf_cv_base.py @@ -27,15 +27,15 @@ class ChamberViewBase(LFCliBase): def remove_text_blobs(self): pass - def add_text_blobs(self, type="", name="", data="", debug=False): - data = {'type': type, + def add_text_blobs(self, text_type="", name="", data="", debug=False): + data = {'type': text_type, 'name': name, "text": data } self.json_post("/cli-json/add_text_blob/", data, debug_=debug) - def get_text_blob(self, type="", name="", debug=False): - data = {'type': type, + def get_text_blob(self, text_type="", name="", debug=False): + data = {'type': text_type, 'name': name, } return self.json_post("/cli-json/show_text_blob/", data, debug_=debug) diff --git a/py-json/lfdata.py b/py-json/lfdata.py index b0e154ad..f6889703 100644 --- a/py-json/lfdata.py +++ b/py-json/lfdata.py @@ -4,16 +4,16 @@ import datetime # LFData class actions: # - Methods to collect data/store data (use from monitor instance) - used by Profile class. - # - file open/save - # - save row (rolling) - to CSV (standard) - # - headers - # - file to data-storage-type conversion and vice versa (e.g. dataframe (or datatable) to file type and vice versa) - # - other common util methods related to immediate data storage - # - include compression method - # - monitoring truncates every 5 mins and sends to report? --- need clarification. truncate file and rewrite to same file? - # - large data collection use NFS share to NAS. +# - file open/save +# - save row (rolling) - to CSV (standard) +# - headers +# - file to data-storage-type conversion and vice versa (e.g. dataframe (or datatable) to file type and vice versa) +# - other common util methods related to immediate data storage +# - include compression method +# - monitoring truncates every 5 mins and sends to report? --- need clarification. truncate file and rewrite to same file? +# - large data collection use NFS share to NAS. # Websocket class actions: - #reading data from websockets +# reading data from websockets class LFDataCollection: def __init__(self, local_realm, debug=False): @@ -22,70 +22,71 @@ class LFDataCollection: self.debug = debug or local_realm.debug def json_get(self, _req_url, debug_=False): - return self.parent_realm.json_get(_req_url, debug_=False) - - def check_json_validity(self, keyword=None, json_response=None): + return self.parent_realm.json_get(_req_url, debug_=debug_) + + @staticmethod + def check_json_validity(keyword=None, json_response=None): if json_response is None: - raise ValueError("Cannot find columns requested to be searched in port manager. Exiting script, please retry.") + raise ValueError( + "Cannot find columns requested to be searched in port manager. Exiting script, please retry.") if keyword is not None and keyword not in json_response: - raise ValueError("Cannot find proper information from json. Please check your json request. Exiting script, please retry.") + raise ValueError( + "Cannot find proper information from json. Please check your json request. Exiting script, please retry.") + @staticmethod + def get_milliseconds(timestamp): + return (timestamp - datetime.datetime(1970, 1, 1)).total_seconds() * 1000 - def get_milliseconds(self, - timestamp): - return (timestamp - datetime.datetime(1970,1,1)).total_seconds()*1000 - def get_seconds(self, - timestamp): - return (timestamp - datetime.datetime(1970,1,1)).total_seconds() + @staticmethod + def get_seconds(timestamp): + return (timestamp - datetime.datetime(1970, 1, 1)).total_seconds() + # only for ipv4_variable_time at the moment + def monitor_interval(self, header_row_=None, + start_time_=None, sta_list_=None, + created_cx_=None, layer3_fields_=None, + port_mgr_fields_=None): - #only for ipv4_variable_time at the moment - def monitor_interval(self, header_row_= None, - start_time_= None, sta_list_= None, - created_cx_= None, layer3_fields_= None, - port_mgr_fields_= None): + # time calculations for while loop and writing to csv + t = datetime.datetime.now() + timestamp = t.strftime("%m/%d/%Y %I:%M:%S") + t_to_millisec_epoch = int(self.get_milliseconds(t)) + time_elapsed = int(self.get_seconds(t)) - int(self.get_seconds(start_time_)) - #time calculations for while loop and writing to csv - t = datetime.datetime.now() - timestamp= t.strftime("%m/%d/%Y %I:%M:%S") - t_to_millisec_epoch= int(self.get_milliseconds(t)) - time_elapsed=int(self.get_seconds(t))-int(self.get_seconds(start_time_)) - - #get responses from json - layer_3_response = self.json_get("/endp/%s?fields=%s" % (created_cx_, layer3_fields_),debug_=self.debug) + # get responses from json + layer_3_response = self.json_get("/endp/%s?fields=%s" % (created_cx_, layer3_fields_), debug_=self.debug) + if port_mgr_fields_ is not None: + port_mgr_response = self.json_get("/port/1/1/%s?fields=%s" % (sta_list_, port_mgr_fields_), + debug_=self.debug) + + # check json response validity + self.check_json_validity(keyword="endpoint", json_response=layer_3_response) + self.check_json_validity(keyword="interfaces", json_response=port_mgr_response) + + # dict manipulation + temp_list = [] + for endpoint in layer_3_response["endpoint"]: + if self.debug: + print("Current endpoint values list... ") + print(list(endpoint.values())[0]) + temp_endp_values = list(endpoint.values())[0] # dict + temp_list.extend([timestamp, t_to_millisec_epoch, time_elapsed]) + current_sta = temp_endp_values['name'] + merge = {} if port_mgr_fields_ is not None: - port_mgr_response=self.json_get("/port/1/1/%s?fields=%s" % (sta_list_, port_mgr_fields_), debug_=self.debug) - - #check json response validity - self.check_json_validity(keyword="endpoint",json_response=layer_3_response) - self.check_json_validity(keyword="interfaces",json_response=port_mgr_response) - - #dict manipulation - temp_list=[] - for endpoint in layer_3_response["endpoint"]: - if self.debug: - print("Current endpoint values list... ") - print(list(endpoint.values())[0]) - temp_endp_values=list(endpoint.values())[0] #dict - temp_list.extend([timestamp,t_to_millisec_epoch,time_elapsed]) - current_sta = temp_endp_values['name'] - merge={} - if port_mgr_fields_ is not None: - for sta_name in sta_list_: - if sta_name in current_sta: - for interface in port_mgr_response["interfaces"]: - if sta_name in list(interface.keys())[0]: - merge=temp_endp_values.copy() - - port_mgr_values_dict =list(interface.values())[0] - renamed_port_cols={} - for key in port_mgr_values_dict.keys(): - renamed_port_cols['port mgr - ' +key]=port_mgr_values_dict[key] - merge.update(renamed_port_cols) - for name in header_row_[3:-3]: - temp_list.append(merge[name]) - return temp_list + for sta_name in sta_list_: + if sta_name in current_sta: + for interface in port_mgr_response["interfaces"]: + if sta_name in list(interface.keys())[0]: + merge = temp_endp_values.copy() + port_mgr_values_dict = list(interface.values())[0] + renamed_port_cols = {} + for key in port_mgr_values_dict.keys(): + renamed_port_cols['port mgr - ' + key] = port_mgr_values_dict[key] + merge.update(renamed_port_cols) + for name in header_row_[3:-3]: + temp_list.append(merge[name]) + return temp_list -#class WebSocket(): - \ No newline at end of file +# class WebSocket(): diff --git a/py-json/mac_vlan_profile.py b/py-json/mac_vlan_profile.py index 87636973..1382cc27 100644 --- a/py-json/mac_vlan_profile.py +++ b/py-json/mac_vlan_profile.py @@ -101,17 +101,17 @@ class MACVLANProfile(LFCliBase): pprint(set_port.set_port_current_flags) pprint(set_port.set_port_interest_flags) return - if (param_name in set_port.set_port_cmd_flags): + if param_name in set_port.set_port_cmd_flags: if (value == 1) and (param_name not in self.desired_set_port_cmd_flags): self.desired_set_port_cmd_flags.append(param_name) elif value == 0: self.desired_set_port_cmd_flags.remove(param_name) - elif (param_name in set_port.set_port_current_flags): + elif param_name in set_port.set_port_current_flags: if (value == 1) and (param_name not in self.desired_set_port_current_flags): self.desired_set_port_current_flags.append(param_name) elif value == 0: self.desired_set_port_current_flags.remove(param_name) - elif (param_name in set_port.set_port_interest_flags): + elif param_name in set_port.set_port_interest_flags: if (value == 1) and (param_name not in self.desired_set_port_interest_flags): self.desired_set_port_interest_flags.append(param_name) elif value == 0: diff --git a/py-json/multicast_profile.py b/py-json/multicast_profile.py index faf43ad4..a7125703 100644 --- a/py-json/multicast_profile.py +++ b/py-json/multicast_profile.py @@ -2,9 +2,8 @@ import sys import os import importlib -from pprint import pprint +import pprint - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") @@ -36,7 +35,7 @@ class MULTICASTProfile(LFCliBase): # Clean out our local lists, this by itself does NOT remove anything from LANforge manager. # but, if you are trying to modify existing connections, then clearing these arrays and # re-calling 'create' will do the trick. - created_mc = {} + self.created_mc = {} def get_mc_names(self): return self.created_mc.keys() @@ -52,7 +51,7 @@ class MULTICASTProfile(LFCliBase): debug_ = True for endp_name in self.get_mc_names(): - print("Starting mcast endpoint: %s" % (endp_name)) + print("Starting mcast endpoint: %s" % endp_name) json_data = { "endp_name": endp_name } @@ -78,15 +77,15 @@ class MULTICASTProfile(LFCliBase): def cleanup_prefix(self): self.local_realm.cleanup_cxe_prefix(self.name_prefix) - def cleanup(self, suppress_related_commands=None, debug_ = False): + def cleanup(self, suppress_related_commands=None, debug_=False): if self.debug: debug_ = True for endp_name in self.get_mc_names(): self.local_realm.rm_endp(endp_name, debug_=debug_, suppress_related_commands_=suppress_related_commands) - def create_mc_tx(self, endp_type, side_tx, mcast_group="224.9.9.9", mcast_dest_port=9999, - suppress_related_commands=None, debug_=False): + def create_mc_tx(self, endp_type, side_tx, mcast_group="224.9.9.9", mcast_dest_port=9999, + suppress_related_commands=None, debug_=False): if self.debug: debug_ = True @@ -96,8 +95,6 @@ class MULTICASTProfile(LFCliBase): side_tx_port = side_tx_info[2] side_tx_name = "%smtx-%s-%i" % (self.name_prefix, side_tx_port, len(self.created_mc)) - json_data = [] - # add_endp mcast-xmit-sta 1 1 side_tx mc_udp -1 NO 4000000 0 NO 1472 0 INCREASING NO 32 0 0 json_data = { 'alias': side_tx_name, @@ -138,8 +135,8 @@ class MULTICASTProfile(LFCliBase): these_endp = [side_tx_name] self.local_realm.wait_until_endps_appear(these_endp, debug=debug_) - def create_mc_rx(self, endp_type, side_rx, mcast_group="224.9.9.9", mcast_dest_port=9999, - suppress_related_commands=None, debug_=False): + def create_mc_rx(self, endp_type, side_rx, mcast_group="224.9.9.9", mcast_dest_port=9999, + suppress_related_commands=None, debug_=False): if self.debug: debug_ = True diff --git a/py-json/old-examples/create_sta.py b/py-json/old-examples/create_sta.py index 0cc40273..e45d911a 100755 --- a/py-json/old-examples/create_sta.py +++ b/py-json/old-examples/create_sta.py @@ -203,7 +203,7 @@ def main(): url = base_url+"/port/1/%s/list?fields=alias" % (resource_id) lf_r = LFRequest.LFRequest(url) json_response = lf_r.getAsJson() - if json_response == None: + if json_response is None: raise Exception("no reponse to: "+url) port_map = LFUtils.portListToAliasMap(json_response) #LFUtils.debug_printer.pprint(port_map) diff --git a/py-json/old-examples/wct-example.py b/py-json/old-examples/wct-example.py index 0d1e1410..94f9cb97 100755 --- a/py-json/old-examples/wct-example.py +++ b/py-json/old-examples/wct-example.py @@ -136,7 +136,7 @@ def main(): # Now lets do some cli-socket scripting gui_telnet = pexpect.spawn('telnet %s %s'%(host, clisock)) - if (gui_telnet == None): + if gui_telnet is None: print ("Unable to telnet to %s:%s"%(host,clisock)); exit(1) diff --git a/py-json/port_probe.py b/py-json/port_probe.py new file mode 100644 index 00000000..378a85cc --- /dev/null +++ b/py-json/port_probe.py @@ -0,0 +1,708 @@ +#!/usr/bin/env python3 +import importlib +from time import sleep +# import pandas as pd +import sys +import os +from pprint import pprint + +sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) + +lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") +LFCliBase = lfcli_base.LFCliBase + + +# Probe data can change frequently. It is recommended to update + +class ProbePort(LFCliBase): + def __init__(self, + lfhost=None, + lfport='8080', + debug=False, + eid_str=None): + super().__init__(_lfjson_host=lfhost, + _lfjson_port=lfport, + _debug=debug) + hunks = eid_str.split(".") + self.eid_str = eid_str + self.probepath = "/probe/1/%s/%s" % (hunks[-2], hunks[-1]) + self.response = None + self.signals = None + self.ofdma = False + + self.tx_bitrate = None + self.tx_mcs = None + self.tx_nss = None + self.tx_mbit = None + self.tx_mhz = None + self.tx_gi = None + self.tx_duration = None + self.tx_mbit_calc = None + self.tx_data_rate_gi_short_Mbps = None + self.tx_data_rate_gi_long_Mbps = None + + self.rx_bitrate = None + self.rx_mcs = None + self.rx_nss = None + self.rx_mbit = None + self.rx_mhz = None + self.rx_gi = None + self.rx_duration = None + self.rx_mbit_calc = None + self.rx_data_rate_gi_short_Mbps = None + self.rx_data_rate_gi_long_Mbps = None + + self.data_rate = None + # folder = os.path.dirname(__file__) + + def refreshProbe(self): + self.json_post(self.probepath, {}) + sleep(0.2) + response = self.json_get(self.probepath) + self.response = response + if self.debug: + print("probepath (eid): {probepath}".format(probepath=self.probepath)) + pprint("Probe response: {response}".format(response=self.response)) + text = self.response['probe-results'][0][self.eid_str]['probe results'].split('\n') + signals = [x.strip('\t').split('\t') for x in text if 'signal' in x] + keys = [x[0].strip(' ').strip(':') for x in signals] + values = [x[1].strip('dBm').strip(' ') for x in signals] + # if self.debug: + print("signals keys: {keys}".format(keys=keys)) + print("signals values: {values}".format(values=values)) + self.signals = dict(zip(keys, values)) + + tx_bitrate = [x for x in text if 'tx bitrate' in x][0].replace('\t', ' ') + # if 'HE' in tx_bitrate: + # print("HE not supported ") + print("tx_bitrate {tx_bitrate}".format(tx_bitrate=tx_bitrate)) + self.tx_bitrate = tx_bitrate.split(':')[-1].strip(' ') + if 'MHz' in tx_bitrate: + self.tx_mhz = [x.strip('\t') for x in text if 'tx bitrate' in x][0].split('MHz')[0].rsplit(' ')[-1].strip( + ' ') + print("tx_mhz {tx_mhz}".format(tx_mhz=self.tx_mhz)) + else: + self.tx_mhz = 20 + print("HT: tx_mhz {tx_mhz}".format(tx_mhz=self.tx_mhz)) + tx_mcs = [x.strip('\t') for x in text if 'tx bitrate' in x][0].split(':')[1].strip('\t') + if 'MCS' in tx_mcs: + self.tx_mcs = int(tx_mcs.split('MCS')[1].strip(' ').split(' ')[0]) + print("self.tx_mcs {tx_mcs}".format(tx_mcs=self.tx_mcs)) + if 'NSS' in text: + self.tx_nss = [x.strip('\t') for x in text if 'tx bitrate' in x][0].split('NSS')[1].strip(' ') + else: + # nss is not present need to derive from MCS for HT + if 0 <= self.tx_mcs <= 7: + self.tx_nss = 1 + elif 8 <= self.tx_mcs <= 15: + self.tx_nss = 2 + elif 16 <= self.tx_mcs <= 23: + self.tx_nss = 3 + elif 24 <= self.tx_mcs <= 31: + self.tx_nss = 4 + print("tx_nss {tx_nss}".format(tx_nss=self.tx_nss)) + self.tx_mbit = float(self.tx_bitrate.split(' ')[0]) + print("tx_mbit {tx_mbit}".format(tx_mbit=self.tx_mbit)) + if 'HE' in tx_bitrate: + self.calculated_data_rate_tx_HE() + elif 'VHT' in tx_bitrate: + self.calculated_data_rate_tx_VHT() + else: + self.calculated_data_rate_tx_HT() + else: + print("No tx MCS value:{tx_bitrate}".format(tx_bitrate=tx_bitrate)) + + rx_bitrate = [x for x in text if 'rx bitrate' in x][0].replace('\t', ' ') + print("rx_bitrate {rx_bitrate}".format(rx_bitrate=rx_bitrate)) + self.rx_bitrate = rx_bitrate.split(':')[-1].strip(' ') + print("self.rx_bitrate {rx_bitrate}".format(rx_bitrate=self.rx_bitrate)) + # rx will received : 6Mbps encoding is legacy frame + # for 24g - MHz is 20 + # try: + if 'MHz' in rx_bitrate: + self.rx_mhz = [x.strip('\t') for x in text if 'rx bitrate' in x][0].split('MHz')[0].rsplit(' ')[ + -1].strip(' ') + print("rx_mhz {rx_mhz}".format(rx_mhz=self.rx_mhz)) + else: + self.rx_mhz = 20 + + rx_mcs = [x.strip('\t') for x in text if 'rx bitrate' in x][0].split(':')[1].strip('\t') + # MCS is not in the 6.0MBit/s frame + if 'MCS' in rx_mcs: + self.rx_mcs = int(rx_mcs.split('MCS')[1].strip(' ').split(' ')[0]) + print("self.rx_mcs {rx_mcs}".format(rx_mcs=self.rx_mcs)) + if 'NSS' in text: + self.rx_nss = [x.strip('\t') for x in text if 'rx bitrate' in x][0].split('NSS')[1].strip(' ') + else: + # nss is not present need to derive from MCS for HT + if 0 <= self.rx_mcs <= 7: + self.rx_nss = 1 + elif 8 <= self.rx_mcs <= 15: + self.rx_nss = 2 + elif 16 <= self.rx_mcs <= 23: + self.rx_nss = 3 + elif 24 <= self.rx_mcs <= 31: + self.rx_nss = 4 + + self.rx_mbit = self.rx_bitrate.split(' ')[0] + print("rx_nss {rx_nss}".format(rx_nss=self.rx_nss)) + self.rx_mbit = float(self.rx_bitrate.split(' ')[0]) + print("rx_mbit {rx_mbit}".format(rx_mbit=self.rx_mbit)) + if 'HE' in rx_bitrate: + self.calculated_data_rate_rx_HE() + elif 'VHT' in rx_bitrate: + self.calculated_data_rate_rx_VHT() + else: + self.calculated_data_rate_rx_HT() + else: + print("No rx MCS value:{rx_bitrate}".format(rx_bitrate=rx_bitrate)) + + def getSignalAvgCombined(self): + return self.signals['signal avg'].split(' ')[0] + + def getSignalAvgPerChain(self): + return ' '.join(self.signals['signal avg'].split(' ')[1:]) + + def getSignalCombined(self): + return self.signals['signal'].split(' ')[0] + + def getSignalPerChain(self): + return ' '.join(self.signals['signal'].split(' ')[1:]) + + def getBeaconSignalAvg(self): + return ' '.join(self.signals['beacon signal avg']).replace(' ', '') + + def calculated_data_rate_tx_HT(self): + print("calculated_data_rate_tx_HT") + # TODO compare with standard for 40 MHz if values change + N_sd = 0 # Number of Data Subcarriers based on modulation and bandwith + N_bpscs = 0 # Number of coded bits per Subcarrier(Determined by the modulation, MCS) + R = 0 # coding , (Determined by the modulation, MCS ) + N_ss = 0 # Number of Spatial Streams + T_dft = 3.2 * 10 ** -6 # Constant for HT + T_gi_short = .4 * 10 ** -6 # Guard index. + T_gi_long = .8 * 10 ** -6 # Guard index. + bw = 20 + # Note the T_gi is not exactly know so need to calculate bothh with .4 and .8 + # the nubmer of Data Subcarriers is based on modulation and bandwith + bw = int(self.tx_mhz) + print("Mhz {Mhz}".format(Mhz=self.tx_mhz)) + if bw == 20: + N_sd = 52 + elif bw == 40: + N_sd = 108 + elif bw == 80: + N_sd = 234 + elif bw == 160: + N_sd = 468 + else: + print("For HT if cannot be read bw is assumed to be 20") + N_sd = 52 + self.tx_mhz = 20 + + # NSS + N_ss = self.tx_nss + # MCS (Modulation Coding Scheme) determines the constands + # MCS 0 == Modulation BPSK R = 1/2 , N_bpscs = 1, + # Only for HT configuration + if self.tx_mcs == 0 or self.tx_mcs == 8 or self.tx_mcs == 16 or self.tx_mcs == 24: + R = 1 / 2 + N_bpscs = 1 + # MCS 1 == Modulation QPSK R = 1/2 , N_bpscs = 2 + elif self.tx_mcs == 1 or self.tx_mcs == 9 or self.tx_mcs == 17 or self.tx_mcs == 25: + R = 1 / 2 + N_bpscs = 2 + # MCS 2 == Modulation QPSK R = 3/4 , N_bpscs = 2 + elif self.tx_mcs == 2 or self.tx_mcs == 10 or self.tx_mcs == 18 or self.tx_mcs == 26: + R = 3 / 4 + N_bpscs = 2 + # MCS 3 == Modulation 16-QAM R = 1/2 , N_bpscs = 4 + elif self.tx_mcs == 3 or self.tx_mcs == 11 or self.tx_mcs == 19 or self.tx_mcs == 27: + R = 1 / 2 + N_bpscs = 4 + # MCS 4 == Modulation 16-QAM R = 3/4 , N_bpscs = 4 + elif self.tx_mcs == 4 or self.tx_mcs == 12 or self.tx_mcs == 20 or self.tx_mcs == 28: + R = 3 / 4 + N_bpscs = 4 + # MCS 5 == Modulation 64-QAM R = 2/3 , N_bpscs = 6 + elif self.tx_mcs == 5 or self.tx_mcs == 13 or self.tx_mcs == 21 or self.tx_mcs == 29: + R = 2 / 3 + N_bpscs = 6 + # MCS 6 == Modulation 64-QAM R = 3/4 , N_bpscs = 6 + elif self.tx_mcs == 6 or self.tx_mcs == 14 or self.tx_mcs == 22 or self.tx_mcs == 30: + R = 3 / 4 + N_bpscs = 6 + # MCS 7 == Modulation 64-QAM R = 5/6 , N_bpscs = 6 + elif self.tx_mcs == 7 or self.tx_mcs == 15 or self.tx_mcs == 23 or self.tx_mcs == 31: + R = 5 / 6 + N_bpscs = 6 + + print( + "tx: mcs {mcs} N_sd {N_sd} N_bpscs {N_bpscs} R {R} N_ss {N_ss} T_dft {T_dft} T_gi_short {T_gi_short}".format( + mcs=self.tx_mcs, N_sd=N_sd, N_bpscs=N_bpscs, R=R, N_ss=N_ss, T_dft=T_dft, T_gi_short=T_gi_short)) + + self.tx_data_rate_gi_short_Mbps = ((N_sd * N_bpscs * R * float(N_ss)) / (T_dft + T_gi_short)) / 1000000 + print("tx_data_rate gi_short {data_rate} Mbit/s".format(data_rate=self.tx_data_rate_gi_short_Mbps)) + + print( + "tx: mcs {mcs} N_sd {N_sd} N_bpscs {N_bpscs} R {R} N_ss {N_ss} T_dft {T_dft} T_gi_long {T_gi_long}".format( + mcs=self.tx_mcs, N_sd=N_sd, N_bpscs=N_bpscs, R=R, N_ss=N_ss, T_dft=T_dft, T_gi_long=T_gi_long)) + + self.tx_data_rate_gi_long_Mbps = ((N_sd * N_bpscs * R * float(N_ss)) / (T_dft + T_gi_long)) / 1000000 + print("data_rate gi_long {data_rate} Mbps".format(data_rate=self.tx_data_rate_gi_long_Mbps)) + + if abs(self.tx_mbit - self.tx_data_rate_gi_short_Mbps) <= abs(self.tx_mbit - self.tx_data_rate_gi_long_Mbps): + self.tx_mbit_calc = self.tx_data_rate_gi_short_Mbps + self.tx_gi = T_gi_short + else: + self.tx_mbit_calc = self.tx_data_rate_gi_long_Mbps + self.tx_gi = T_gi_long + + def calculated_data_rate_rx_HT(self): + print("calculated_data_rate_rx_HT") + N_sd = 0 # Number of Data Subcarriers based on modulation and bandwith + N_bpscs = 0 # Number of coded bits per Subcarrier(Determined by the modulation, MCS) + R = 0 # coding , (Determined by the modulation, MCS ) + N_ss = 0 # Number of Spatial Streams + T_dft = 3.2 * 10 ** -6 # Constant for HT + T_gi_short = .4 * 10 ** -6 # Guard index. + T_gi_long = .8 * 10 ** -6 # Guard index. + bw = 20 + # Note the T_gi is not exactly know so need to calculate bothh with .4 and .8 + # the nubmer of Data Subcarriers is based on modulation and bandwith + + bw = int(self.rx_mhz) + print("Mhz {Mhz}".format(Mhz=self.rx_mhz)) + if bw == 20: + N_sd = 52 + elif bw == 40: + N_sd = 108 + elif bw == 80: + N_sd = 234 + elif bw == 160: + N_sd = 468 + else: + print("For HT if cannot be read bw is assumed to be 20") + N_sd = 52 + self.rx_mhz = 20 + # NSS + N_ss = self.rx_nss + # MCS (Modulation Coding Scheme) determines the constands + # MCS 0 == Modulation BPSK R = 1/2 , N_bpscs = 1, + # Only for HT configuration + if self.rx_mcs == 0 or self.rx_mcs == 8 or self.rx_mcs == 16 or self.rx_mcs == 24: + R = 1 / 2 + N_bpscs = 1 + # MCS 1 == Modulation QPSK R = 1/2 , N_bpscs = 2 + elif self.rx_mcs == 1 or self.rx_mcs == 9 or self.rx_mcs == 17 or self.rx_mcs == 25: + R = 1 / 2 + N_bpscs = 2 + # MCS 2 == Modulation QPSK R = 3/4 , N_bpscs = 2 + elif self.rx_mcs == 2 or self.rx_mcs == 10 or self.rx_mcs == 18 or self.rx_mcs == 26: + R = 3 / 4 + N_bpscs = 2 + # MCS 3 == Modulation 16-QAM R = 1/2 , N_bpscs = 4 + elif self.rx_mcs == 3 or self.rx_mcs == 11 or self.rx_mcs == 19 or self.rx_mcs == 27: + R = 1 / 2 + N_bpscs = 4 + # MCS 4 == Modulation 16-QAM R = 3/4 , N_bpscs = 4 + elif self.rx_mcs == 4 or self.rx_mcs == 12 or self.rx_mcs == 20 or self.rx_mcs == 28: + R = 3 / 4 + N_bpscs = 4 + # MCS 5 == Modulation 64-QAM R = 2/3 , N_bpscs = 6 + elif self.rx_mcs == 5 or self.rx_mcs == 13 or self.rx_mcs == 21 or self.rx_mcs == 29: + R = 2 / 3 + N_bpscs = 6 + # MCS 6 == Modulation 64-QAM R = 3/4 , N_bpscs = 6 + elif self.rx_mcs == 6 or self.rx_mcs == 14 or self.rx_mcs == 22 or self.rx_mcs == 30: + R = 3 / 4 + N_bpscs = 6 + # MCS 7 == Modulation 64-QAM R = 5/6 , N_bpscs = 6 + elif self.rx_mcs == 7 or self.rx_mcs == 15 or self.rx_mcs == 23 or self.rx_mcs == 31: + R = 5 / 6 + N_bpscs = 6 + print( + "mcs {mcs} N_sd {N_sd} N_bpscs {N_bpscs} R {R} N_ss {N_ss} T_dft {T_dft} T_gi_short {T_gi_short}".format( + mcs=self.rx_mcs, N_sd=N_sd, N_bpscs=N_bpscs, R=R, N_ss=N_ss, T_dft=T_dft, T_gi_short=T_gi_short)) + self.rx_data_rate_gi_short_Mbps = ((N_sd * N_bpscs * R * float(N_ss)) / (T_dft + T_gi_short)) / 1000000 + print("rx_data_rate gi_short {data_rate} Mbit/s".format(data_rate=self.rx_data_rate_gi_short_Mbps)) + print( + "mcs {mcs} N_sd {N_sd} N_bpscs {N_bpscs} R {R} N_ss {N_ss} T_dft {T_dft} T_gi_long {T_gi_long}".format( + mcs=self.rx_mcs, N_sd=N_sd, N_bpscs=N_bpscs, R=R, N_ss=N_ss, T_dft=T_dft, T_gi_long=T_gi_long)) + self.rx_data_rate_gi_long_Mbps = ((N_sd * N_bpscs * R * float(N_ss)) / (T_dft + T_gi_long)) / 1000000 + print("rx_data_rate gi_long {data_rate} Mbps".format(data_rate=self.rx_data_rate_gi_long_Mbps)) + if abs(self.rx_mbit - self.rx_data_rate_gi_short_Mbps) <= abs( + self.rx_mbit - self.rx_data_rate_gi_long_Mbps): + self.rx_mbit_calc = self.rx_data_rate_gi_short_Mbps + self.rx_gi = T_gi_short + else: + self.rx_mbit_calc = self.rx_data_rate_gi_long_Mbps + self.rx_gi = T_gi_long + + def calculated_data_rate_tx_VHT(self): + print("calculated_data_rate_tx_VHT") + # TODO compare with standard for 40 MHz if values change + N_sd = 0 # Number of Data Subcarriers based on modulation and bandwith + N_bpscs = 0 # Number of coded bits per Subcarrier(Determined by the modulation, MCS) + R = 0 # coding , (Determined by the modulation, MCS ) + N_ss = 0 # Number of Spatial Streams + T_dft = 3.2 * 10 ** -6 # Constant for HT + T_gi_short = .4 * 10 ** -6 # Guard index. + T_gi_long = .8 * 10 ** -6 # Guard index. + bw = 20 + # Note the T_gi is not exactly know so need to calculate bothh with .4 and .8 + # the nubmer of Data Subcarriers is based on modulation and bandwith + bw = int(self.tx_mhz) + + print("Mhz {Mhz}".format(Mhz=self.tx_mhz)) + if bw == 20: + N_sd = 52 + elif bw == 40: + N_sd = 108 + elif bw == 80: + N_sd = 234 + elif bw == 160: + N_sd = 468 + else: + print("For HT if cannot be read bw is assumed to be 20") + N_sd = 52 + self.tx_mhz = 20 + + # NSS + N_ss = self.tx_nss + # MCS (Modulation Coding Scheme) determines the constands + # MCS 0 == Modulation BPSK R = 1/2 , N_bpscs = 1, + # Only for HT configuration + if self.tx_mcs == 0: + R = 1 / 2 + N_bpscs = 1 + # MCS 1 == Modulation QPSK R = 1/2 , N_bpscs = 2 + elif self.tx_mcs == 1: + R = 1 / 2 + N_bpscs = 2 + # MCS 2 == Modulation QPSK R = 3/4 , N_bpscs = 2 + elif self.tx_mcs == 2: + R = 3 / 4 + N_bpscs = 2 + # MCS 3 == Modulation 16-QAM R = 1/2 , N_bpscs = 4 + elif self.tx_mcs == 3: + R = 1 / 2 + N_bpscs = 4 + # MCS 4 == Modulation 16-QAM R = 3/4 , N_bpscs = 4 + elif self.tx_mcs == 4: + R = 3 / 4 + N_bpscs = 4 + # MCS 5 == Modulation 64-QAM R = 2/3 , N_bpscs = 6 + elif self.tx_mcs == 5: + R = 2 / 3 + N_bpscs = 6 + # MCS 6 == Modulation 64-QAM R = 3/4 , N_bpscs = 6 + elif self.tx_mcs == 6: + R = 3 / 4 + N_bpscs = 6 + # MCS 7 == Modulation 64-QAM R = 5/6 , N_bpscs = 6 + elif self.tx_mcs == 7: + R = 5 / 6 + N_bpscs = 6 + # MCS 8 == Modulation 256-QAM R = 3/4 , N_bpscs = 8 + elif self.tx_mcs == 8: + R = 3 / 4 + N_bpscs = 8 + # MCS 9 == Modulation 256-QAM R = 5/6 , N_bpscs = 8 + elif self.tx_mcs == 9: + R = 5 / 6 + N_bpscs = 8 + + print( + "tx: mcs {mcs} N_sd {N_sd} N_bpscs {N_bpscs} R {R} N_ss {N_ss} T_dft {T_dft} T_gi_short {T_gi_short}".format( + mcs=self.tx_mcs, N_sd=N_sd, N_bpscs=N_bpscs, R=R, N_ss=N_ss, T_dft=T_dft, T_gi_short=T_gi_short)) + + self.tx_data_rate_gi_short_Mbps = ((N_sd * N_bpscs * R * float(N_ss)) / (T_dft + T_gi_short)) / 1000000 + print("tx_data_rate gi_short {data_rate} Mbit/s".format(data_rate=self.tx_data_rate_gi_short_Mbps)) + + print( + "tx: mcs {mcs} N_sd {N_sd} N_bpscs {N_bpscs} R {R} N_ss {N_ss} T_dft {T_dft} T_gi_long {T_gi_long}".format( + mcs=self.tx_mcs, N_sd=N_sd, N_bpscs=N_bpscs, R=R, N_ss=N_ss, T_dft=T_dft, T_gi_long=T_gi_long)) + + self.tx_data_rate_gi_long_Mbps = ((N_sd * N_bpscs * R * float(N_ss)) / (T_dft + T_gi_long)) / 1000000 + print("data_rate gi_long {data_rate} Mbps".format(data_rate=self.tx_data_rate_gi_long_Mbps)) + + if abs(self.tx_mbit - self.tx_data_rate_gi_short_Mbps) <= abs(self.tx_mbit - self.tx_data_rate_gi_long_Mbps): + self.tx_mbit_calc = self.tx_data_rate_gi_short_Mbps + self.tx_gi = T_gi_short + else: + self.tx_mbit_calc = self.tx_data_rate_gi_long_Mbps + self.tx_gi = T_gi_long + + def calculated_data_rate_rx_VHT(self): + print("calculated_data_rate_rx_VHT") + N_sd = 0 # Number of Data Subcarriers based on modulation and bandwith + N_bpscs = 0 # Number of coded bits per Subcarrier(Determined by the modulation, MCS) + R = 0 # coding , (Determined by the modulation, MCS ) + N_ss = 0 # Number of Spatial Streams + T_dft = 3.2 * 10 ** -6 # Constant for HT + T_gi_short = .4 * 10 ** -6 # Guard index. + T_gi_long = .8 * 10 ** -6 # Guard index. + # Note the T_gi is not exactly know so need to calculate bothh with .4 and .8 + # the nubmer of Data Subcarriers is based on modulation and bandwith + bw = int(self.rx_mhz) + print("Mhz {Mhz}".format(Mhz=self.rx_mhz)) + if bw == 20: + N_sd = 52 + elif bw == 40: + N_sd = 108 + elif bw == 80: + N_sd = 234 + elif bw == 160: + N_sd = 468 + else: + print("For HT if cannot be read bw is assumed to be 20") + N_sd = 52 + self.rx_mhz = 20 + # NSS + N_ss = self.rx_nss + # MCS (Modulation Coding Scheme) determines the constands + # MCS 0 == Modulation BPSK R = 1/2 , N_bpscs = 1, + # Only for HT configuration + if self.rx_mcs == 0: + R = 1 / 2 + N_bpscs = 1 + # MCS 1 == Modulation QPSK R = 1/2 , N_bpscs = 2 + elif self.rx_mcs == 1: + R = 1 / 2 + N_bpscs = 2 + # MCS 2 == Modulation QPSK R = 3/4 , N_bpscs = 2 + elif self.rx_mcs == 2: + R = 3 / 4 + N_bpscs = 2 + # MCS 3 == Modulation 16-QAM R = 1/2 , N_bpscs = 4 + elif self.rx_mcs == 3: + R = 1 / 2 + N_bpscs = 4 + # MCS 4 == Modulation 16-QAM R = 3/4 , N_bpscs = 4 + elif self.rx_mcs == 4: + R = 3 / 4 + N_bpscs = 4 + # MCS 5 == Modulation 64-QAM R = 2/3 , N_bpscs = 6 + elif self.rx_mcs == 5: + R = 2 / 3 + N_bpscs = 6 + # MCS 6 == Modulation 64-QAM R = 3/4 , N_bpscs = 6 + elif self.rx_mcs == 6: + R = 3 / 4 + N_bpscs = 6 + # MCS 7 == Modulation 64-QAM R = 5/6 , N_bpscs = 6 + elif self.rx_mcs == 7: + R = 5 / 6 + N_bpscs = 6 + # MCS 8 == Modulation 256-QAM R = 3/4 , N_bpscs = 8 + elif self.rx_mcs == 8: + R = 3 / 4 + N_bpscs = 8 + # MCS 9 == Modulation 256-QAM R = 5/6 , N_bpscs = 8 + elif self.rx_mcs == 9: + R = 5 / 6 + N_bpscs = 8 + print( + "mcs {mcs} N_sd {N_sd} N_bpscs {N_bpscs} R {R} N_ss {N_ss} T_dft {T_dft} T_gi_short {T_gi_short}".format( + mcs=self.rx_mcs, N_sd=N_sd, N_bpscs=N_bpscs, R=R, N_ss=N_ss, T_dft=T_dft, T_gi_short=T_gi_short)) + self.rx_data_rate_gi_short_Mbps = ((N_sd * N_bpscs * R * float(N_ss)) / (T_dft + T_gi_short)) / 1000000 + print("rx_data_rate gi_short {data_rate} Mbit/s".format(data_rate=self.rx_data_rate_gi_short_Mbps)) + print( + "mcs {mcs} N_sd {N_sd} N_bpscs {N_bpscs} R {R} N_ss {N_ss} T_dft {T_dft} T_gi_long {T_gi_long}".format( + mcs=self.rx_mcs, N_sd=N_sd, N_bpscs=N_bpscs, R=R, N_ss=N_ss, T_dft=T_dft, T_gi_long=T_gi_long)) + self.rx_data_rate_gi_long_Mbps = ((N_sd * N_bpscs * R * float(N_ss)) / (T_dft + T_gi_long)) / 1000000 + print("rx_data_rate gi_long {data_rate} Mbps".format(data_rate=self.rx_data_rate_gi_long_Mbps)) + if abs(self.rx_mbit - self.rx_data_rate_gi_short_Mbps) <= abs( + self.rx_mbit - self.rx_data_rate_gi_long_Mbps): + self.rx_mbit_calc = self.rx_data_rate_gi_short_Mbps + self.rx_gi = T_gi_short + else: + self.rx_mbit_calc = self.rx_data_rate_gi_long_Mbps + self.rx_gi = T_gi_long + ########################################## + # + # HE no OFDMA - changes the calculations + # + ########################################### + + def calculated_data_rate_tx_HE(self): + print("calculated_data_rate_tx_HE") + # TODO compare with standard for 40 MHz if values change + N_sd = 0 # Number of Data Subcarriers based on modulation and bandwith + N_bpscs = 0 # Number of coded bits per Subcarrier(Determined by the modulation, MCS) + R = 0 # coding , (Determined by the modulation, MCS ) + N_ss = 0 # Number of Spatial Streams + T_dft = 3.2 * 10 ** -6 # Constant for HT + T_gi_short = .4 * 10 ** -6 # Guard index. + T_gi_long = .8 * 10 ** -6 # Guard index. + bw = 20 + # Note the T_gi is not exactly know so need to calculate bothh with .4 and .8 + # the nubmer of Data Subcarriers is based on modulation and bandwith + bw = int(self.tx_mhz) + print("Mhz {Mhz}".format(Mhz=self.tx_mhz)) + if bw == 20: + N_sd = 52 + elif bw == 40: + N_sd = 108 + elif bw == 80: + N_sd = 234 + elif bw == 160: + N_sd = 468 + else: + print("For HT if cannot be read bw is assumed to be 20") + N_sd = 52 + self.tx_mhz = 20 + + # NSS + N_ss = self.tx_nss + # MCS (Modulation Coding Scheme) determines the constands + # MCS 0 == Modulation BPSK R = 1/2 , N_bpscs = 1, + # Only for HT configuration + if self.tx_mcs == 0: + R = 1 / 2 + N_bpscs = 1 + # MCS 1 == Modulation QPSK R = 1/2 , N_bpscs = 2 + elif self.tx_mcs == 1: + R = 1 / 2 + N_bpscs = 2 + # MCS 2 == Modulation QPSK R = 3/4 , N_bpscs = 2 + elif self.tx_mcs == 2: + R = 3 / 4 + N_bpscs = 2 + # MCS 3 == Modulation 16-QAM R = 1/2 , N_bpscs = 4 + elif self.tx_mcs == 3: + R = 1 / 2 + N_bpscs = 4 + # MCS 4 == Modulation 16-QAM R = 3/4 , N_bpscs = 4 + elif self.tx_mcs == 4: + R = 3 / 4 + N_bpscs = 4 + # MCS 5 == Modulation 64-QAM R = 2/3 , N_bpscs = 6 + elif self.tx_mcs == 5: + R = 2 / 3 + N_bpscs = 6 + # MCS 6 == Modulation 64-QAM R = 3/4 , N_bpscs = 6 + elif self.tx_mcs == 6: + R = 3 / 4 + N_bpscs = 6 + # MCS 7 == Modulation 64-QAM R = 5/6 , N_bpscs = 6 + elif self.tx_mcs == 7: + R = 5 / 6 + N_bpscs = 6 + # MCS 8 == Modulation 256-QAM R = 3/4 , N_bpscs = 8 + elif self.tx_mcs == 8: + R = 3 / 4 + N_bpscs = 8 + # MCS 9 == Modulation 256-QAM R = 5/6 , N_bpscs = 8 + elif self.tx_mcs == 9: + R = 5 / 6 + N_bpscs = 8 + + print( + "tx: mcs {mcs} N_sd {N_sd} N_bpscs {N_bpscs} R {R} N_ss {N_ss} T_dft {T_dft} T_gi_short {T_gi_short}".format( + mcs=self.tx_mcs, N_sd=N_sd, N_bpscs=N_bpscs, R=R, N_ss=N_ss, T_dft=T_dft, T_gi_short=T_gi_short)) + + self.tx_data_rate_gi_short_Mbps = ((N_sd * N_bpscs * R * float(N_ss)) / (T_dft + T_gi_short)) / 1000000 + print("tx_data_rate gi_short {data_rate} Mbit/s".format(data_rate=self.tx_data_rate_gi_short_Mbps)) + + print( + "tx: mcs {mcs} N_sd {N_sd} N_bpscs {N_bpscs} R {R} N_ss {N_ss} T_dft {T_dft} T_gi_long {T_gi_long}".format( + mcs=self.tx_mcs, N_sd=N_sd, N_bpscs=N_bpscs, R=R, N_ss=N_ss, T_dft=T_dft, T_gi_long=T_gi_long)) + + self.tx_data_rate_gi_long_Mbps = ((N_sd * N_bpscs * R * float(N_ss)) / (T_dft + T_gi_long)) / 1000000 + print("data_rate gi_long {data_rate} Mbps".format(data_rate=self.tx_data_rate_gi_long_Mbps)) + + if abs(self.tx_mbit - self.tx_data_rate_gi_short_Mbps) <= abs(self.tx_mbit - self.tx_data_rate_gi_long_Mbps): + self.tx_mbit_calc = self.tx_data_rate_gi_short_Mbps + self.tx_gi = T_gi_short + else: + self.tx_mbit_calc = self.tx_data_rate_gi_long_Mbps + self.tx_gi = T_gi_long + + def calculated_data_rate_rx_HE(self): + print("calculated_data_rate_rx_HE") + N_sd = 0 # Number of Data Subcarriers based on modulation and bandwith + N_bpscs = 0 # Number of coded bits per Subcarrier(Determined by the modulation, MCS) + R = 0 # coding , (Determined by the modulation, MCS ) + N_ss = 0 # Number of Spatial Streams + T_dft = 3.2 * 10 ** -6 # Constant for HT + T_gi_short = .4 * 10 ** -6 # Guard index. + T_gi_long = .8 * 10 ** -6 # Guard index. + # Note the T_gi is not exactly know so need to calculate bothh with .4 and .8 + # the nubmer of Data Subcarriers is based on modulation and bandwith + bw = int(self.rx_mhz) + print("Mhz {Mhz}".format(Mhz=self.rx_mhz)) + if bw == 20: + N_sd = 52 + elif bw == 40: + N_sd = 108 + elif bw == 80: + N_sd = 234 + elif bw == 160: + N_sd = 468 + else: + print("For HT if cannot be read bw is assumed to be 20") + N_sd = 52 + self.rx_mhz = 20 + # NSS + N_ss = self.rx_nss + # MCS (Modulation Coding Scheme) determines the constands + # MCS 0 == Modulation BPSK R = 1/2 , N_bpscs = 1, + # Only for HT configuration + if self.rx_mcs == 0: + R = 1 / 2 + N_bpscs = 1 + # MCS 1 == Modulation QPSK R = 1/2 , N_bpscs = 2 + elif self.rx_mcs == 1: + R = 1 / 2 + N_bpscs = 2 + # MCS 2 == Modulation QPSK R = 3/4 , N_bpscs = 2 + elif self.rx_mcs == 2: + R = 3 / 4 + N_bpscs = 2 + # MCS 3 == Modulation 16-QAM R = 1/2 , N_bpscs = 4 + elif self.rx_mcs == 3: + R = 1 / 2 + N_bpscs = 4 + # MCS 4 == Modulation 16-QAM R = 3/4 , N_bpscs = 4 + elif self.rx_mcs == 4: + R = 3 / 4 + N_bpscs = 4 + # MCS 5 == Modulation 64-QAM R = 2/3 , N_bpscs = 6 + elif self.rx_mcs == 5: + R = 2 / 3 + N_bpscs = 6 + # MCS 6 == Modulation 64-QAM R = 3/4 , N_bpscs = 6 + elif self.rx_mcs == 6: + R = 3 / 4 + N_bpscs = 6 + # MCS 7 == Modulation 64-QAM R = 5/6 , N_bpscs = 6 + elif self.rx_mcs == 7: + R = 5 / 6 + N_bpscs = 6 + # MCS 8 == Modulation 256-QAM R = 3/4 , N_bpscs = 8 + elif self.rx_mcs == 8: + R = 3 / 4 + N_bpscs = 8 + # MCS 9 == Modulation 256-QAM R = 5/6 , N_bpscs = 8 + elif self.rx_mcs == 9: + R = 5 / 6 + N_bpscs = 8 + print( + "mcs {mcs} N_sd {N_sd} N_bpscs {N_bpscs} R {R} N_ss {N_ss} T_dft {T_dft} T_gi_short {T_gi_short}".format( + mcs=self.rx_mcs, N_sd=N_sd, N_bpscs=N_bpscs, R=R, N_ss=N_ss, T_dft=T_dft, T_gi_short=T_gi_short)) + self.rx_data_rate_gi_short_Mbps = ((N_sd * N_bpscs * R * float(N_ss)) / (T_dft + T_gi_short)) / 1000000 + print("rx_data_rate gi_short {data_rate} Mbit/s".format(data_rate=self.rx_data_rate_gi_short_Mbps)) + print( + "mcs {mcs} N_sd {N_sd} N_bpscs {N_bpscs} R {R} N_ss {N_ss} T_dft {T_dft} T_gi_long {T_gi_long}".format( + mcs=self.rx_mcs, N_sd=N_sd, N_bpscs=N_bpscs, R=R, N_ss=N_ss, T_dft=T_dft, T_gi_long=T_gi_long)) + self.rx_data_rate_gi_long_Mbps = ((N_sd * N_bpscs * R * float(N_ss)) / (T_dft + T_gi_long)) / 1000000 + print("rx_data_rate gi_long {data_rate} Mbps".format(data_rate=self.rx_data_rate_gi_long_Mbps)) + if abs(self.rx_mbit - self.rx_data_rate_gi_short_Mbps) <= abs( + self.rx_mbit - self.rx_data_rate_gi_long_Mbps): + self.rx_mbit_calc = self.rx_data_rate_gi_short_Mbps + self.rx_gi = T_gi_short + else: + self.rx_mbit_calc = self.rx_data_rate_gi_long_Mbps + self.rx_gi = T_gi_long \ No newline at end of file diff --git a/py-json/port_utils.py b/py-json/port_utils.py index 7e4d49a2..1b274c2f 100644 --- a/py-json/port_utils.py +++ b/py-json/port_utils.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -class PortUtils(): +class PortUtils: def __init__(self, local_realm): self.local_realm = local_realm diff --git a/py-json/qvlan_profile.py b/py-json/qvlan_profile.py index e2b8bbe6..f1a22033 100644 --- a/py-json/qvlan_profile.py +++ b/py-json/qvlan_profile.py @@ -5,13 +5,13 @@ import importlib from pprint import pprint import time - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") LFCliBase = lfcli_base.LFCliBase LFRequest = importlib.import_module("py-json.LANforge.LFRequest") LFUtils = importlib.import_module("py-json.LANforge.LFUtils") +set_port = importlib.import_module("py-json.LANforge.set_port") class QVLANProfile(LFCliBase): @@ -19,7 +19,6 @@ class QVLANProfile(LFCliBase): local_realm, qvlan_parent="eth1", num_qvlans=1, - admin_down=False, dhcp=False, debug_=False): super().__init__(lfclient_host, lfclient_port, debug_) @@ -98,17 +97,17 @@ class QVLANProfile(LFCliBase): pprint(set_port.set_port_current_flags) pprint(set_port.set_port_interest_flags) return - if (param_name in set_port.set_port_cmd_flags): + if param_name in set_port.set_port_cmd_flags: if (value == 1) and (param_name not in self.desired_set_port_cmd_flags): self.desired_set_port_cmd_flags.append(param_name) elif value == 0: self.desired_set_port_cmd_flags.remove(param_name) - elif (param_name in set_port.set_port_current_flags): + elif param_name in set_port.set_port_current_flags: if (value == 1) and (param_name not in self.desired_set_port_current_flags): self.desired_set_port_current_flags.append(param_name) elif value == 0: self.desired_set_port_current_flags.remove(param_name) - elif (param_name in set_port.set_port_interest_flags): + elif param_name in set_port.set_port_interest_flags: if (value == 1) and (param_name not in self.desired_set_port_interest_flags): self.desired_set_port_interest_flags.append(param_name) elif value == 0: @@ -116,11 +115,11 @@ class QVLANProfile(LFCliBase): else: raise ValueError("Unknown param name: " + param_name) - def create(self, admin_down=False, debug=False, sleep_time=1): + def create(self, sleep_time=1): print("Creating qvlans...") req_url = "/cli-json/add_vlan" - if not self.dhcp and self.first_ip_addr is not None and self.netmask is not None and self.gateway is not None: + if not self.dhcp and self.first_ip_addr and self.netmask and self.gateway: self.desired_set_port_interest_flags.append("ip_address") self.desired_set_port_interest_flags.append("ip_Mask") self.desired_set_port_interest_flags.append("ip_gateway") @@ -143,11 +142,10 @@ class QVLANProfile(LFCliBase): "shelf": self.shelf, "resource": self.resource, "port": self.local_realm.name_to_eid(self.qvlan_parent)[2], - "vid": i+1 + "vid": i + 1 } self.created_qvlans.append("%s.%s.%s#%d" % (self.shelf, self.resource, - self.qvlan_parent, int( - self.desired_qvlans[i][self.desired_qvlans[i].index('#') + 1:]))) + self.qvlan_parent, int(self.desired_qvlans[i][self.desired_qvlans[i].index('#') + 1:]))) self.local_realm.json_post(req_url, data) time.sleep(sleep_time) diff --git a/py-json/realm.py b/py-json/realm.py index e19f01be..cc697e89 100755 --- a/py-json/realm.py +++ b/py-json/realm.py @@ -16,7 +16,7 @@ from pprint import pprint # ---- ---- ---- ---- LANforge Base Imports ---- ---- ---- ---- - + sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) LANforge = importlib.import_module("py-json.LANforge") @@ -28,8 +28,6 @@ LFCliBase = lfcli_base.LFCliBase l3_cxprofile = importlib.import_module("py-json.l3_cxprofile") L3CXProfile = l3_cxprofile.L3CXProfile -l3_cxprofile2 = importlib.import_module("py-json.l3_cxprofile2") -L3CXProfile2 = l3_cxprofile2.L3CXProfile2 l4_cxprofile = importlib.import_module("py-json.l4_cxprofile") L4CXProfile = l4_cxprofile.L4CXProfile lf_attenmod = importlib.import_module("py-json.lf_attenmod") @@ -96,7 +94,7 @@ class Realm(LFCliBase): _exit_on_error=False, _exit_on_fail=False, _proxy_str=None, - _capture_signal_list=[]): + _capture_signal_list=None): super().__init__(_lfjson_host=lfclient_host, _lfjson_port=lfclient_port, _debug=debug_, @@ -105,6 +103,8 @@ class Realm(LFCliBase): _proxy_str=_proxy_str, _capture_signal_list=_capture_signal_list) + if _capture_signal_list is None: + _capture_signal_list = [] self.debug = debug_ # if debug_: # print("Realm _proxy_str: %s" % _proxy_str) @@ -112,7 +112,6 @@ class Realm(LFCliBase): self.check_connect() self.chan_to_freq = {} self.freq_to_chan = {} - freq = 0 chan = 1 for freq in range(2412, 2472, 5): self.freq_to_chan[freq] = chan @@ -223,35 +222,38 @@ class Realm(LFCliBase): port_list=sta_list, debug=debug_) - def rm_port(self, port_eid, check_exists=True, debug_=False): + def rm_port(self, port_eid, check_exists=True, debug_=None): if port_eid is None: raise ValueError("realm.rm_port: want a port eid like 1.1.eth1") - debug_ |= self.debug + if debug_ is None: + debug_ = self.debug req_url = "/cli-json/rm_vlan" eid = self.name_to_eid(port_eid) if check_exists: - if not self.port_exists(port_eid): + if not self.port_exists(port_eid, debug=debug_): return False data = { "shelf": eid[0], "resource": eid[1], "port": eid[2] - } - rsp = self.json_post(req_url, data, debug_=debug_) + } + self.json_post(req_url, data, debug_=debug_) return True - def port_exists(self, port_eid): + def port_exists(self, port_eid, debug=None): + if debug is None: + debug = self.debug eid = self.name_to_eid(port_eid) - current_stations = self.json_get("/port/%s/%s/%s?fields=alias" % (eid[0], eid[1], eid[2])) - if not current_stations is None: + current_stations = self.json_get("/port/%s/%s/%s?fields=alias" % (eid[0], eid[1], eid[2]), + debug_=debug) + if current_stations: return True return False def admin_up(self, port_eid): # print("186 admin_up port_eid: "+port_eid) eid = self.name_to_eid(port_eid) - shelf = eid[0] resource = eid[1] port = eid[2] request = LFUtils.port_up_request(resource_id=resource, port_name=port) @@ -261,7 +263,6 @@ class Realm(LFCliBase): def admin_down(self, port_eid): eid = self.name_to_eid(port_eid) - shelf = eid[0] resource = eid[1] port = eid[2] request = LFUtils.port_down_request(resource_id=resource, port_name=port) @@ -269,7 +270,6 @@ class Realm(LFCliBase): def reset_port(self, port_eid): eid = self.name_to_eid(port_eid) - shelf = eid[0] resource = eid[1] port = eid[2] request = LFUtils.port_reset_request(resource_id=resource, port_name=port) @@ -317,13 +317,13 @@ class Realm(LFCliBase): def cleanup_cxe_prefix(self, prefix): cx_list = self.cx_list() - if cx_list is not None: + if cx_list: for cx_name in cx_list: if cx_name.startswith(prefix): self.rm_cx(cx_name) endp_list = self.json_get("/endp/list") - if endp_list is not None: + if endp_list: if 'endpoint' in endp_list: endp_list = list(endp_list['endpoint']) for idx in range(len(endp_list)): @@ -351,12 +351,11 @@ class Realm(LFCliBase): if debug_: dbg_param = "?__debug=1" - while (last_response != "YES"): - response = self.json_post("/gui-json/cmd%s" % dbg_param, data, debug_=debug_, - response_json_list_=response_json) + while last_response != "YES": + self.json_post("/gui-json/cmd%s" % dbg_param, data, debug_=debug_, response_json_list_=response_json) # LFUtils.debug_printer.pprint(response_json) last_response = response_json[0]["LAST"]["response"] - if (last_response != "YES"): + if last_response != "YES": last_response = None response_json = [] time.sleep(1) @@ -397,22 +396,23 @@ class Realm(LFCliBase): found_endps = {} if debug: print("Waiting on endpoint endp_list {}".format(endp_list)) - if (endp_list is not None) and ("items" not in endp_list): + if endp_list and ("items" not in endp_list): try: endp_list = list(endp_list['endpoint']) for idx in range(len(endp_list)): name = list(endp_list[idx])[0] found_endps[name] = name except: - print("non-fatal exception endp_list = list(endp_list['endpoint'] did not exist, will wait some more") + print( + "non-fatal exception endp_list = list(endp_list['endpoint'] did not exist, will wait some more") for req in these_endp: - if not req in found_endps: + if req not in found_endps: if debug: - print("Waiting on endpoint: %s" % (req)) + print("Waiting on endpoint: %s" % req) wait_more = True count += 1 - if (count > 100): + if count > 100: break return not wait_more @@ -429,23 +429,25 @@ class Realm(LFCliBase): found_cxs = {} cx_list = self.cx_list() not_cx = ['warnings', 'errors', 'handler', 'uri', 'items'] - if cx_list is not None: + if cx_list: for cx_name in cx_list: if cx_name in not_cx: continue found_cxs[cx_name] = cx_name for req in these_cx: - if not req in found_cxs: + if req not in found_cxs: if debug: - print("Waiting on CX: %s" % (req)) + print("Waiting on CX: %s" % req) wait_more = True count += 1 - if (count > 100): + if count > 100: break return not wait_more + # def wait_until_database_loaded(self): + # Returns map of all stations with port+type == WIFI-STATION # Key is the EID, value is the map of key/values for the port values. def station_map(self): @@ -457,7 +459,7 @@ class Realm(LFCliBase): sta_map = {} temp_map = LFUtils.portListToAliasMap(response) for k, v in temp_map.items(): - if (v['port type'] == "WIFI-STA"): + if v['port type'] == "WIFI-STA": sta_map[k] = v temp_map.clear() del temp_map @@ -482,7 +484,6 @@ class Realm(LFCliBase): # Returns list of all ports def port_list(self): - sta_list = [] response = super().json_get("/port/list?fields=all") if (response is None) or ("interfaces" not in response): print("port_list: incomplete response:") @@ -515,14 +516,14 @@ class Realm(LFCliBase): "shelf": eid_toks[0], "resource": eid_toks[1], "serno": eid_toks[2], - "atten_idx":eid_toks[3], - "val":atten_ddb, - } + "atten_idx": eid_toks[3], + "val": atten_ddb, + } self.json_post(req_url, data) # removes port by eid/eidpn def remove_vlan_by_eid(self, eid): - if (eid is None) or ("" == eid): + if (eid is None) or (eid == ""): raise ValueError("removeVlanByEid wants eid like 1.1.sta0 but given[%s]" % eid) hunks = self.name_to_eid(eid) # print("- - - - - - - - - - - - - - - - -") @@ -556,7 +557,7 @@ class Realm(LFCliBase): if debug_: print("- prelim - - - - - - - - - - - - - - - - - - -") pprint(record) - if (record["port type"] == "WIFI-STA"): + if record["port type"] == "WIFI-STA": prelim_map[name] = record except Exception as x: @@ -606,7 +607,7 @@ class Realm(LFCliBase): def name_to_eid(self, eid, debug=False, non_port=False): if debug: - self.logg(level="debug", mesg="name_to_eid: "+str(eid)) + self.logg(level="debug", mesg="name_to_eid: " + str(eid)) if (type(eid) is list) or (type(eid) is tuple): return eid return LFUtils.name_to_eid(eid, non_port=non_port) @@ -645,7 +646,7 @@ class Realm(LFCliBase): for sta_eid in station_list: if debug: - print("checking sta-eid: %s" % (sta_eid)) + print("checking sta-eid: %s" % sta_eid) eid = self.name_to_eid(sta_eid) response = super().json_get("/port/%s/%s/%s?fields=alias,ip,port+type,ipv6+address" % @@ -663,7 +664,7 @@ class Realm(LFCliBase): if v['ip'] in waiting_states: wait_more = True if debug: - print("Waiting for port %s to get IPv4 Address." % (sta_eid)) + print("Waiting for port %s to get IPv4 Address." % sta_eid) else: if sta_eid not in stas_with_ips: stas_with_ips[sta_eid] = {'ipv4': v['ip']} @@ -682,7 +683,7 @@ class Realm(LFCliBase): else: wait_more = True if debug: - print("Waiting for port %s to get IPv6 Address." % (sta_eid)) + print("Waiting for port %s to get IPv6 Address." % sta_eid) if wait_more: time.sleep(1) @@ -698,7 +699,7 @@ class Realm(LFCliBase): raise ValueError("check for num curr ips expects non-empty list of ports") for sta_eid in station_list: if debug: - print("checking sta-eid: %s" % (sta_eid)) + print("checking sta-eid: %s" % sta_eid) eid = self.name_to_eid(sta_eid) response = super().json_get("/port/%s/%s/%s?fields=alias,ip,port+type,ipv6+address" % (eid[0], eid[1], eid[2])) @@ -711,9 +712,9 @@ class Realm(LFCliBase): break if ipv4: v = response['interface'] - if (v['ip'] in waiting_states): + if v['ip'] in waiting_states: if debug: - print("Waiting for port %s to get IPv4 Address." % (sta_eid)) + print("Waiting for port %s to get IPv4 Address." % sta_eid) else: if debug: print("Found IP: %s on port: %s" % (v['ip'], sta_eid)) @@ -723,9 +724,9 @@ class Realm(LFCliBase): num_sta_with_ips += 1 if ipv6: v = response['interface'] - if (v['ip'] in waiting_states): + if v['ip'] in waiting_states: if debug: - print("Waiting for port %s to get IPv6 Address." % (sta_eid)) + print("Waiting for port %s to get IPv6 Address." % sta_eid) else: if debug: @@ -736,11 +737,12 @@ class Realm(LFCliBase): num_sta_with_ips += 1 return num_sta_with_ips - def duration_time_to_seconds(self, time_string): + @staticmethod + def duration_time_to_seconds(time_string): if isinstance(time_string, str): pattern = re.compile("^(\d+)([dhms]$)") td = pattern.match(time_string) - if td is not None: + if td: dur_time = int(td.group(1)) dur_measure = str(td.group(2)) if dur_measure == "d": @@ -757,11 +759,10 @@ class Realm(LFCliBase): raise ValueError("time_string must be of type str. Type %s provided" % type(time_string)) return duration_sec - def remove_all_stations(self, resource): port_list = self.station_list() sta_list = [] - if sta_list is not None: + if port_list: print("Removing all stations") for item in list(port_list): if "sta" in list(item)[0]: @@ -780,7 +781,7 @@ class Realm(LFCliBase): endp_list = self.json_get("/endp/list") if "items" in endp_list or "empty" in endp_list: return - if endp_list is not None or endp_list: + if endp_list: print("Removing all endps") endp_list = list(endp_list['endpoint']) for endp_name in range(len(endp_list)): @@ -796,10 +797,10 @@ class Realm(LFCliBase): # remove endpoints # nc show endpoints # nc show cross connects - try: + if self.cx_list(): cx_list = list(self.cx_list()) not_cx = ['warnings', 'errors', 'handler', 'uri', 'items', 'empty'] - if cx_list is not None: + if cx_list: print("Removing all cxs") for cx_name in cx_list: if cx_name in not_cx: @@ -810,7 +811,7 @@ class Realm(LFCliBase): "cx_name": cx_name } self.json_post(req_url, data) - except: + else: print("no cxs to remove") if remove_all_endpoints: @@ -820,186 +821,93 @@ class Realm(LFCliBase): "endpoint": "all" } self.json_post(req_url, data) - req_url = "cli-json/show_cx" - data = { - "test_mgr": "all", - "cross_connect": "all" - } def parse_link(self, link): link = self.lfclient_url + link info = () - def new_station_profile(self, ver = 1): - if ver == 1: - station_prof = StationProfile(self.lfclient_url, local_realm=self, debug_=self.debug, up=False) - #elif ver == 2: - # import station_profile2 - # station_prof = station_profile2.StationProfile2(self.lfclient_url, local_realm=self, debug_=self.debug, up=False) - return station_prof + def new_station_profile(self): + return StationProfile(self.lfclient_url, local_realm=self, debug_=self.debug, up=False) - def new_multicast_profile(self, ver = 1): - if ver == 1: - multi_prof = MULTICASTProfile(self.lfclient_host, self.lfclient_port, - local_realm=self, debug_=self.debug, report_timer_=3000) - #elif ver == 2: - # import multicast_profile2 - # multi_prof = multicast_profile2.MULTICASTProfile2(self.lfclient_host, self.lfclient_port, - # local_realm=self, debug_=self.debug, report_timer_=3000) - return multi_prof + def new_multicast_profile(self): + return MULTICASTProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug, report_timer_=3000) - def new_wifi_monitor_profile(self, resource_=1, debug_=False, up_=False, ver = 1): - if ver == 1: - wifi_mon_prof = WifiMonitor(self.lfclient_url, - local_realm=self, - resource_=resource_, - up=up_, - debug_=(self.debug or debug_)) - #elif ver == 2: - # import wifi_monitor_profile2 - # wifi_mon_prof = wifi_monitor_profile2.WifiMonitor2(self.lfclient_url, - # local_realm=self, - # resource_=resource_, - # up=up_, - # debug_=(self.debug or debug_)) - return wifi_mon_prof + def new_wifi_monitor_profile(self, resource_=1, debug_=False, up_=False): + return WifiMonitor(self.lfclient_url, + local_realm=self, + resource_=resource_, + up=up_, + debug_=(self.debug or debug_)) - def new_l3_cx_profile(self, ver=1): - if ver == 1: - cx_prof = L3CXProfile(self.lfclient_host, - self.lfclient_port, - local_realm=self, - debug_=self.debug, - report_timer_=3000) - elif ver == 2: - cx_prof = L3CXProfile2(self.lfclient_host, - self.lfclient_port, - local_realm=self, - debug_=self.debug, - report_timer_=3000) - return cx_prof + def new_l3_cx_profile(self): + return L3CXProfile(self.lfclient_host, + self.lfclient_port, + local_realm=self, + debug_=self.debug, + report_timer_=3000) - def new_l4_cx_profile(self, ver=1): - if ver == 1: - cx_prof = L4CXProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - #elif ver == 2: - # import l4_cxprofile2 - # cx_prof = l4_cxprofile2.L4CXProfile2(self.lfclient_host, - # self.lfclient_port, - # local_realm=self, - # debug_=self.debug, - # report_timer_=3000) - return cx_prof - def new_attenuator_profile(self, ver=1): - if ver == 1: - atten_prof = ATTENUATORProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - return atten_prof - def new_generic_endp_profile(self, ver=1): - if ver == 1 : - endp_prof = GenCXProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - #elif ver == 2: - # import gen_cxprofile2 - # endp_prof = gen_cxprofile2.GenCXProfile(self.lfclient_host, - # self.lfclient_port, - # local_realm=self, - # debug_=self.debug, - # report_timer_=3000) - return endp_prof + def new_l4_cx_profile(self): + return L4CXProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - def new_generic_cx_profile(self, ver=1): + def new_attenuator_profile(self): + return ATTENUATORProfile(self.lfclient_host, self.lfclient_port, debug_=self.debug) + + def new_generic_endp_profile(self): + return GenCXProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) + + def new_generic_cx_profile(self): """ @deprecated :return: new GenCXProfile """ - if ver == 1: - cx_prof = GenCXProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - #elif ver == 2: - # import gen_cxprofile2 - # cx_prof = gen_cxprofile2.GenCXProfile(self.lfclient_host, - # self.lfclient_port, - # local_realm=self, - # debug_=self.debug, - # report_timer_=3000) - return cx_prof + return GenCXProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - def new_vap_profile(self, ver=1): - if ver == 1: - vap_prof = VAPProfile(lfclient_host=self.lfclient_host, lfclient_port=self.lfclient_port, local_realm=self, - debug_=self.debug) - # elif ver == 2: - # import vap_profile2 - # vap_prof = vap_profile2.VAPProfile2(lfclient_host=self.lfclient_host, lfclient_port=self.lfclient_port, local_realm=self, - # debug_=self.debug) - return vap_prof + def new_vap_profile(self): + return VAPProfile(lfclient_host=self.lfclient_host, lfclient_port=self.lfclient_port, local_realm=self, + debug_=self.debug) - def new_vr_profile(self, ver=2): - if ver == 2: - from vr_profile2 import VRProfile - vap_prof = VRProfile(local_realm=self, - debug=self.debug) - return vap_prof + # def new_vr_profile(self): + # return VRProfile(local_realm=self, + # debug=self.debug) - def new_http_profile(self, ver = 1): - if ver == 1: - http_prof = HTTPProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - # elif ver == 2: - # import http_profile2 - # http_prof = http_profile2.HTTPProfile2(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - return http_prof + def new_http_profile(self): + return HTTPProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - def new_fio_endp_profile(self, ver = 1): - if ver == 1: - cx_prof = FIOEndpProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - # elif ver == 2: - # import fio_endp_profile2 - # cx_prof = fio_endp_profile2.FIOEndpProfile2(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - return cx_prof + def new_fio_endp_profile(self): + return FIOEndpProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - def new_dut_profile(self, ver = 1): - if ver == 1: - dut_profile = DUTProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - # elif ver == 2: - # import dut_profile2 - # dut_profile = dut_profile2.DUTProfile2(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - return dut_profile + def new_dut_profile(self): + return DUTProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - def new_mvlan_profile(self, ver = 1): - if ver == 1: - mac_vlan_profile = MACVLANProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - # elif ver == 2: - # import mac_vlan_profile2 - # mac_vlan_profile = mac_vlan_profile2.MACVLANProfile2(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - return mac_vlan_profile + def new_mvlan_profile(self): + return MACVLANProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) def new_qvlan_profile(self): return QVLANProfile(self.host, self.port, local_realm=self, debug_=self.debug) - def new_test_group_profile(self, ver = 1): - if ver == 1: - test_group_profile = TestGroupProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - # elif ver == 2: - # import test_group_profile2 - # test_group_profile = test_group_profile2.TestGroupProfile2(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) - return test_group_profile + def new_test_group_profile(self): + return TestGroupProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) def new_lf_data_collection(self): return LFDataCollection(local_realm=self) -class PacketFilter(): - def get_filter_wlan_assoc_packets(self, ap_mac, sta_mac): - filter = "-T fields -e wlan.fc.type_subtype -e wlan.addr -e wlan.fc.pwrmgt " \ - "-Y \"(wlan.addr==%s or wlan.addr==%s) and wlan.fc.type_subtype<=3\" " % (ap_mac, sta_mac) - return filter +class PacketFilter: - def get_filter_wlan_null_packets(self, ap_mac, sta_mac): - filter = "-T fields -e wlan.fc.type_subtype -e wlan.addr -e wlan.fc.pwrmgt " \ - "-Y \"(wlan.addr==%s or wlan.addr==%s) and wlan.fc.type_subtype==44\" " % (ap_mac, sta_mac) - return filter + @staticmethod + def get_filter_wlan_assoc_packets(ap_mac, sta_mac): + return "-T fields -e wlan.fc.type_subtype -e wlan.addr -e wlan.fc.pwrmgt " \ + "-Y \"(wlan.addr==%s or wlan.addr==%s) and wlan.fc.type_subtype<=3\" " % (ap_mac, sta_mac) - def run_filter(self, pcap_file, filter): + @staticmethod + def get_filter_wlan_null_packets(ap_mac, sta_mac): + return "-T fields -e wlan.fc.type_subtype -e wlan.addr -e wlan.fc.pwrmgt " \ + "-Y \"(wlan.addr==%s or wlan.addr==%s) and wlan.fc.type_subtype==44\" " % (ap_mac, sta_mac) + + @staticmethod + def run_filter(pcap_file, file_filter): filename = "/tmp/tshark_dump.txt" - cmd = "tshark -r %s %s > %s" % (pcap_file, filter, filename) + cmd = "tshark -r %s %s > %s" % (pcap_file, file_filter, filename) # print("CMD: ", cmd) os.system(cmd) lines = [] diff --git a/py-json/show_ports.py b/py-json/show_ports.py index 05fae06a..24413072 100644 --- a/py-json/show_ports.py +++ b/py-json/show_ports.py @@ -12,25 +12,24 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit() - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) LFRequest = importlib.import_module("py-json.LANforge.LFRequest") def main(): - url = "http://localhost:8080/port/1/1/list" - timeout = 5 # seconds + url = "http://localhost:8080/port/1/1/list" + + lf_r = LFRequest.LFRequest(url) + json_response = lf_r.getAsJson(True) + j_printer = pprint.PrettyPrinter(indent=2) + j_printer.pprint(json_response) + + # for record in json_response['interfaces']: + # j_printer.pprint(record) - lf_r = LFRequest.LFRequest(url) - json_response = lf_r.getAsJson(True) - j_printer = pprint.PrettyPrinter(indent=2) - j_printer.pprint(json_response) - - #for record in json_response['interfaces']: - #j_printer.pprint(record) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if __name__ == "__main__": - main() + main() # diff --git a/py-json/station_profile.py b/py-json/station_profile.py index 673ec0ea..239eae2f 100644 --- a/py-json/station_profile.py +++ b/py-json/station_profile.py @@ -300,17 +300,17 @@ class StationProfile: pprint(set_port.set_port_current_flags) pprint(set_port.set_port_interest_flags) return - if (param_name in set_port.set_port_cmd_flags): + if param_name in set_port.set_port_cmd_flags: if (value == 1) and (param_name not in self.desired_set_port_cmd_flags): self.desired_set_port_cmd_flags.append(param_name) elif value == 0: self.desired_set_port_cmd_flags.remove(param_name) - elif (param_name in set_port.set_port_current_flags): + elif param_name in set_port.set_port_current_flags: if (value == 1) and (param_name not in self.desired_set_port_current_flags): self.desired_set_port_current_flags.append(param_name) elif value == 0: self.desired_set_port_current_flags.remove(param_name) - elif (param_name in set_port.set_port_interest_flags): + elif param_name in set_port.set_port_interest_flags: if (value == 1) and (param_name not in self.desired_set_port_interest_flags): self.desired_set_port_interest_flags.append(param_name) elif value == 0: @@ -359,7 +359,7 @@ class StationProfile: def cleanup(self, desired_stations=None, delay=0.03, debug_=False): print("Cleaning up stations") - if (desired_stations is None): + if desired_stations is None: desired_stations = self.station_names if len(desired_stations) < 1: @@ -371,7 +371,9 @@ class StationProfile: self.local_realm.rm_port(port_eid, check_exists=True, debug_=debug_) time.sleep(delay) # And now see if they are gone - LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=desired_stations) + LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, + port_list=desired_stations, + debug=debug_) # Checks for errors in initialization values and creates specified number of stations using init parameters def create(self, radio, @@ -440,7 +442,6 @@ class StationProfile: set_port_r = LFRequest.LFRequest(self.lfclient_url + "/cli-json/set_port", debug_=debug) wifi_extra_r = LFRequest.LFRequest(self.lfclient_url + "/cli-json/set_wifi_extra", debug_=debug) wifi_txo_r = LFRequest.LFRequest(self.lfclient_url + "/cli-json/set_wifi_txo", debug_=debug) - my_sta_names = [] # add radio here if (num_stations > 0) and (len(sta_names_) < 1): # print("CREATING MORE STA NAMES == == == == == == == == == == == == == == == == == == == == == == == ==") @@ -449,7 +450,7 @@ class StationProfile: else: my_sta_names = sta_names_ - if (len(my_sta_names) >= 15) or (suppress_related_commands_ == True): + if (len(my_sta_names) >= 15) or suppress_related_commands_: self.add_sta_data["suppress_preexec_cli"] = "yes" self.add_sta_data["suppress_preexec_method"] = 1 self.set_port_data["suppress_preexec_cli"] = "yes" @@ -503,13 +504,13 @@ class StationProfile: continue # print("- 3264 - ## %s ## add_sta_r.jsonPost - - - - - - - - - - - - - - - - - - "%eidn) - json_response = add_sta_r.jsonPost(debug=self.debug) + add_sta_r.jsonPost(debug=self.debug) finished_sta.append(eidn) # print("- ~3264 - %s - add_sta_r.jsonPost - - - - - - - - - - - - - - - - - - "%eidn) time.sleep(0.01) set_port_r.addPostData(self.set_port_data) # print("- 3270 -- %s -- set_port_r.jsonPost - - - - - - - - - - - - - - - - - - "%eidn) - json_response = set_port_r.jsonPost(debug) + set_port_r.jsonPost(debug) # print("- ~3270 - %s - set_port_r.jsonPost - - - - - - - - - - - - - - - - - - "%eidn) time.sleep(0.01) @@ -519,10 +520,10 @@ class StationProfile: self.wifi_txo_data["port"] = name if self.wifi_extra_data_modified: wifi_extra_r.addPostData(self.wifi_extra_data) - json_response = wifi_extra_r.jsonPost(debug) + wifi_extra_r.jsonPost(debug) if self.wifi_txo_data_modified: wifi_txo_r.addPostData(self.wifi_txo_data) - json_response = wifi_txo_r.jsonPost(debug) + wifi_txo_r.jsonPost(debug) # append created stations to self.station_names self.station_names.append("%s.%s.%s" % (radio_shelf, radio_resource, name)) @@ -534,7 +535,7 @@ class StationProfile: # and set ports up if dry_run: return - if (self.up): + if self.up: self.admin_up() # for sta_name in self.station_names: @@ -551,8 +552,15 @@ class StationProfile: self.add_sta_data["flags"] = self.add_named_flags(self.desired_add_sta_flags, add_sta.add_sta_flags) self.add_sta_data["flags_mask"] = self.add_named_flags(self.desired_add_sta_flags_mask, add_sta.add_sta_flags) + + station_eid = self.local_realm.name_to_eid(station) + station_shelf = station_eid[0] + station_resource = station_eid[1] + station_port = station_eid[2] self.add_sta_data["radio"] = radio - self.add_sta_data["sta_name"] = station + self.add_sta_data["shelf"] = station_shelf + self.add_sta_data["resource"] = station_resource + self.add_sta_data["sta_name"] = station_port self.add_sta_data["ssid"] = 'NA' self.add_sta_data["key"] = 'NA' self.add_sta_data['mac'] = 'NA' @@ -565,4 +573,4 @@ class StationProfile: print(self.lfclient_url + "/cli_json/add_sta") print(self.add_sta_data) add_sta_r.addPostData(self.add_sta_data) - json_response = add_sta_r.jsonPost(self.debug) + add_sta_r.jsonPost(self.debug) diff --git a/py-json/test_base.py b/py-json/test_base.py index aa349e66..7bf68ddc 100644 --- a/py-json/test_base.py +++ b/py-json/test_base.py @@ -27,8 +27,8 @@ class TestBase: def build(self): # - create station profile # - create 2 criteria [ex: not down, continually_receiving] object (for ex) - # - station_profile.add_criteria([not_down, continually_receiving, etc_3]) - # design - inversion of control + # - station_profile.add_criteria([not_down, continually_receiving, etc_3]) + # design - inversion of control if self.profiles: for profile in self.profiles: @@ -38,31 +38,30 @@ class TestBase: if self.profiles: for profile in self.profiles: profile.check_passes() - - def run_duration(self, monitor_enabled= False): - #here check if monitor is enabled or not, then run loop accordingly + + def run_duration(self, monitor_enabled=False): + # here check if monitor is enabled or not, then run loop accordingly self.check_for_halt() if self.profiles: if monitor_enabled: for profile in self.profiles: - profile.monitor_record() #check for halt in monitor record? + profile.monitor_record() # check for halt in monitor record? for profile in self.profiles: profile.grade() if self.exit_on_fail: if self.fails(): self.exit_fail() self.check_for_quit() - - def report(self, enabled= False): - #here check if monitor is enabled or not, then run loop accordingly with lfreporting + + def report(self, enabled=False): + # here check if monitor is enabled or not, then run loop accordingly with lfreporting pass def begin(self): self.pre_clean_up() self.build() - self.start() + self.start() self.run_duration() - self.stop() + self.stop() self.report() - self.clean_up() - + self.clean_up() diff --git a/py-json/test_utility.py b/py-json/test_utility.py index edc6462a..d1cd52a1 100644 --- a/py-json/test_utility.py +++ b/py-json/test_utility.py @@ -14,7 +14,6 @@ import threading import re import json - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") @@ -28,13 +27,14 @@ updates_path = webconsole_dir + "/web_json/updates.js" class ClientVisualization(LFCliBase, threading.Thread): - def __init__(self, lfclient_host="localhost", lfclient_port=8080, num_clients= 64, max_data= 120, thread_id=None, _debug_on=False, _exit_on_error=False, _exit_on_fail=False): + def __init__(self, lfclient_host="localhost", lfclient_port=8080, num_clients=64, max_data=120, thread_id=None, + _debug_on=False, _exit_on_error=False, _exit_on_fail=False): super().__init__(lfclient_host, lfclient_port, _debug=_debug_on, _exit_on_fail=_exit_on_fail) threading.Thread.__init__(self) self.num_clients = num_clients self.max_data = max_data self._stop_event = threading.Event() - self.client_data = {"down":[], "phantom":[], "ip":[], "scanning":[]} + self.client_data = {"down": [], "phantom": [], "ip": [], "scanning": []} def stop(self): self._stop_event.set() @@ -56,15 +56,15 @@ class ClientVisualization(LFCliBase, threading.Thread): for j in i: print(i[j]['port type']) if i[j]['port type'] == "WIFI-STA" and i[j]['parent dev'] == "wiphy1" and i[j]['alias'] != 'wlan1': - #print(j) - if i[j]['down'] == False and i[j]['phantom'] == False and i[j]['ip'] == '0.0.0.0': + # print(j) + if i[j]['down'] is False and i[j]['phantom'] is False and i[j]['ip'] == '0.0.0.0': self.scanning += 1 - elif i[j]['down'] == False and i[j]['phantom'] == True: + elif i[j]['down'] is False and i[j]['phantom'] is True: self.phantom += 1 - elif i[j]['down'] == True and i[j]['phantom'] == True: + elif i[j]['down'] is True and i[j]['phantom'] is True: self.phantom += 1 self.client_data['phantom'].append(self.phantom) - elif i[j]['down'] == True and i[j]['phantom'] == False: + elif i[j]['down'] is True and i[j]['phantom'] is False: self.down += 1 elif i[j]['ip'] != "0.0.0.0": self.ip += 1 @@ -75,7 +75,6 @@ class ClientVisualization(LFCliBase, threading.Thread): self.client_data['down'].append(self.down) self.client_data['ip'].append(self.ip) - for i in self.client_data: if len(self.client_data[i]) >= self.max_data: self.client_data[i].pop(0) @@ -84,20 +83,21 @@ class ClientVisualization(LFCliBase, threading.Thread): break -class CreateHTML(): - def __init__(self, path="", test_name="", time_snap="", dut_ssid="", test_conf_data={}, objective="", test_results={}, chart_data={}, chart_params={}): +class CreateHTML: + def __init__(self, path="", test_name="", time_snap="", dut_ssid="", test_conf_data={}, objective="", + test_results={}, chart_data={}, chart_params={}): self.head = """ - """+test_name+""" + """ + test_name + """

-

"""+test_name+"""

-

"""+time_snap+"""

+

""" + test_name + """

+

""" + time_snap + """


@@ -119,16 +119,16 @@ class CreateHTML():
- """ for i in test_conf_data: self.test_conf = self.test_conf + """ - - """ @@ -141,13 +141,13 @@ class CreateHTML(): self.objective = """

Objective

- """+objective+""" + """ + objective + """


""" if str(test_results['summary']).__contains__("PASS"): - self.summary_results =""" + self.summary_results = """
SSID """+dut_ssid+""" + """ + dut_ssid + """
"""+str(i)+""" + """ + str(i) + """ """+test_conf_data[i]+""" + """ + test_conf_data[i] + """
@@ -180,23 +180,20 @@ class CreateHTML():

""" - chart_d =[] - chart_label =[] + chart_d = [] + chart_label = [] for i in chart_data: chart_label.append(i) chart_d.append(chart_data[i]) - - - self.detail_result = """
Detailed Results
""" for index in test_results['detail']['keys']: - self.detail_result = self.detail_result+"" - self.detail_result = self.detail_result +"" + self.detail_result = self.detail_result + "" + self.detail_result = self.detail_result + "" for data in test_results['detail']['data']: self.detail_result = self.detail_result + "" @@ -205,12 +202,14 @@ class CreateHTML(): for i in data: print(data[i]) if str(data[i]).__contains__("PASS"): - self.detail_result = self.detail_result + "" + self.detail_result = self.detail_result + "" elif str(data[i]).__contains__("FAIL"): - self.detail_result = self.detail_result + "" + self.detail_result = self.detail_result + "" else: self.detail_result = self.detail_result + "" - self.detail_result = self.detail_result +"" + self.detail_result = self.detail_result + "" self.chart_data = chart_data chart_values = [] @@ -231,26 +230,24 @@ class CreateHTML(): self.chart = """""" - self.end = """
"+index+"
" + index + "
" + str(data[i]) + "" + str( + data[i]) + "" + str(data[i]) + "" + str( + data[i]) + "" + str(data[i]) + "
""" - self.report = self.head + self.test_conf + self.objective + self.summary_results + self.chart +self.detail_result + self.end + self.report = self.head + self.test_conf + self.objective + self.summary_results + self.chart + self.detail_result + self.end - -class RuntimeUpdates(): +class RuntimeUpdates: def __init__(self, session_id, init_data): self.session_id = session_id self.init_data = init_data f = open(updates_path, 'r+') data = f.read() f.close() - obj = data[data.find('{'): data.rfind('}') + 1] - obj = re.sub('[\']', '"', obj) - data = json.loads(obj) + self.obj = data[data.find('{'): data.rfind('}') + 1] + self.obj = re.sub('[\']', '"', self.obj) + data = json.loads(self.obj) print(data) data["web_updates"].append({"ID": self.session_id, "data": self.init_data}) print(data) @@ -264,9 +261,9 @@ class RuntimeUpdates(): f = open(updates_path, 'r+') data = f.read() f.close() - obj = data[data.find('{'): data.rfind('}') + 1] - obj = re.sub('[\']', '"', obj) - data = json.loads(obj) + data_obj = data[data.find('{'): data.rfind('}') + 1] + data_obj = re.sub('[\']', '"', data_obj) + data = json.loads(data_obj) for update in data["web_updates"]: if update["ID"] == self.session_id: @@ -306,22 +303,14 @@ class StatusSession(LFCliBase): Method to read all the messages for a particular session """ keys = [] - for i in self.json_get("/status-msg/"+self.session_id)['messages']: + for i in self.json_get("/status-msg/" + self.session_id)['messages']: keys.append(i['key']) - json_uri = "/status-msg/"+self.session_id + "/" + json_uri = "/status-msg/" + self.session_id + "/" for i in keys: json_uri = json_uri + i + "," return self.json_get(json_uri)['messages'] - - - - - - if __name__ == "__main__": obj = StatusMsg(lfclient_host="localhost", lfclient_port=8090, session_id="01_18_21_20_04_20") print(obj.read()) - - diff --git a/py-json/vap_profile.py b/py-json/vap_profile.py index cace9bb3..173610f2 100644 --- a/py-json/vap_profile.py +++ b/py-json/vap_profile.py @@ -5,7 +5,6 @@ import importlib from pprint import pprint import time - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") @@ -97,7 +96,7 @@ class VAPProfile(LFCliBase): req_json = LFUtils.portUpRequest(resource, None, debug_on=self.debug) req_json["port"] = self.vap_name set_port_r.addPostData(req_json) - json_response = set_port_r.jsonPost(self.debug) + set_port_r.jsonPost(self.debug) time.sleep(0.03) def admin_down(self, resource): @@ -105,7 +104,7 @@ class VAPProfile(LFCliBase): req_json = LFUtils.port_down_request(resource, None, debug_on=self.debug) req_json["port"] = self.vap_name set_port_r.addPostData(req_json) - json_response = set_port_r.jsonPost(self.debug) + set_port_r.jsonPost(self.debug) time.sleep(0.03) def use_security(self, security_type, ssid=None, passwd=None): @@ -141,7 +140,7 @@ class VAPProfile(LFCliBase): print("Command name name [%s] not defined in %s" % (command_name, self.COMMANDS)) return if command_name == "add_vap": - if (param_name not in add_vap.add_vap_flags): + if param_name not in add_vap.add_vap_flags: print("Parameter name [%s] not defined in add_vap.py" % param_name) if self.debug: pprint(add_vap.add_vap_flags) @@ -255,7 +254,6 @@ class VAPProfile(LFCliBase): raise ValueError("No radio %s.%s found" % (resource, radio)) eid = "1.%s.%s" % (resource, radio) - frequency = 0 country = 0 if eid in jr: country = jr[eid]["country"] @@ -312,18 +310,18 @@ class VAPProfile(LFCliBase): pprint(add_vap_r) print("- ~1502 - - - - - - - - - - - - - - - - - - - ") - json_response = add_vap_r.jsonPost(debug) + add_vap_r.jsonPost(debug) # time.sleep(0.03) time.sleep(2) set_port_r.addPostData(self.set_port_data) - json_response = set_port_r.jsonPost(debug) + set_port_r.jsonPost(debug) time.sleep(0.03) self.wifi_extra_data["resource"] = resource self.wifi_extra_data["port"] = self.vap_name if self.wifi_extra_data_modified: wifi_extra_r.addPostData(self.wifi_extra_data) - json_response = wifi_extra_r.jsonPost(debug) + wifi_extra_r.jsonPost(debug) port_list = self.local_realm.json_get("port/1/1/list") if port_list is not None: @@ -335,7 +333,7 @@ class VAPProfile(LFCliBase): time.sleep(5) # create bridge - if bridge : + if bridge: print("creating bridge") data = { "shelf": 1, @@ -354,19 +352,16 @@ class VAPProfile(LFCliBase): } self.local_realm.json_post("cli-json/set_port", bridge_set_port) - if (self.up): + if self.up: self.admin_up(resource) def cleanup(self, resource, delay=0.03): print("Cleaning up VAPs") desired_ports = ["1.%s.%s" % (resource, self.vap_name), "1.%s.br0" % resource] - del_count = len(desired_ports) - # First, request remove on the list. for port_eid in desired_ports: self.local_realm.rm_port(port_eid, check_exists=True) # And now see if they are gone LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=desired_ports) - diff --git a/py-json/wifi_monitor_profile.py b/py-json/wifi_monitor_profile.py index ac001b8f..7089c8b0 100644 --- a/py-json/wifi_monitor_profile.py +++ b/py-json/wifi_monitor_profile.py @@ -46,7 +46,7 @@ class WifiMonitor: raise ValueError("No radio %s.%s found" % (resource_, radio_)) eid = "1.%s.%s" % (resource_, radio_) - #frequency = 0 + # frequency = 0 country = 0 if eid in jr: country = jr[eid]["country"] @@ -73,7 +73,7 @@ class WifiMonitor: }) def set_flag(self, param_name, value): - if (param_name not in add_monitor.flags): + if param_name not in add_monitor.flags: raise ValueError("Flag '%s' does not exist for add_monitor, consult add_monitor.py" % param_name) if (value == 1) and (param_name not in self.flag_names): self.flag_names.append(param_name) @@ -97,13 +97,13 @@ class WifiMonitor: if (existing_ports is None) or ("interfaces" not in existing_ports) or ("interface" not in existing_ports): print("No monitor names found to delete") return - if ("interfaces" in existing_ports): + if "interfaces" in existing_ports: for eid, info in existing_ports["interfaces"].items(): LFUtils.removePort(resource=resource_, port_name=info["alias"], baseurl=self.lfclient_url, debug=self.debug) - if ("interface" in existing_ports): + if "interface" in existing_ports: for eid, info in existing_ports["interface"].items(): LFUtils.removePort(resource=resource_, port_name=info["alias"], @@ -132,4 +132,3 @@ class WifiMonitor: "duration": duration_sec } self.local_realm.json_post("/cli-json/sniff_port", _data=data) - diff --git a/py-json/wlan_theoretical_sta.py b/py-json/wlan_theoretical_sta.py index 261c23c2..84f03521 100755 --- a/py-json/wlan_theoretical_sta.py +++ b/py-json/wlan_theoretical_sta.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -''' +""" Candela Technologies Inc. Info : Standard Script for WLAN Capaity Calculator @@ -13,7 +13,7 @@ This Script has three classes : 3. ac11_calculator : It will take all the user input of 802.11ac station,calculate Intermediate values and Theoretical values. All classes have different functions: input_parameter() that calculates intermediate values and generate theroretical data -''' +""" import argparse import json @@ -22,8 +22,7 @@ import json # Class to take all user input (802.11a/b/g Standard) - -class abg11_calculator(): +class abg11_calculator: def __init__(self, Traffic_Type, PHY_Bit_Rate, Encryption, QoS, MAC_Frame_802_11, Basic_Rate_Set, Preamble, slot_name, Codec_Type, RTS_CTS_Handshake, CTS_to_self): @@ -39,19 +38,16 @@ class abg11_calculator(): self.RTS_CTS_Handshake = RTS_CTS_Handshake self.CTS_to_self = CTS_to_self - - - # This function is for calculate intermediate values and Theoretical values @staticmethod def create_argparse(prog=None, formatter_class=None, epilog=None, description=None): if (prog is not None) or (formatter_class is not None) or (epilog is not None) or (description is not None): ap = argparse.ArgumentParser(prog=prog, - formatter_class=formatter_class, - allow_abbrev=True, - epilog=epilog, - description=description) + formatter_class=formatter_class, + allow_abbrev=True, + epilog=epilog, + description=description) else: ap = argparse.ArgumentParser() @@ -329,7 +325,7 @@ class abg11_calculator(): # CWmin_str (leave alone for default) - if (PHY_Bit_Rate_int == 1 or PHY_Bit_Rate_int == 2 or PHY_Bit_Rate_int == 5 or PHY_Bit_Rate_int == 11): + if PHY_Bit_Rate_int == 1 or PHY_Bit_Rate_int == 2 or PHY_Bit_Rate_int == 5 or PHY_Bit_Rate_int == 11: CWmin_str = 31 else: if ( @@ -376,7 +372,7 @@ class abg11_calculator(): # PHY Bit Rate of Control Frames - if (PHY_Bit_Rate_int == 1 or PHY_Bit_Rate_int == 2 or PHY_Bit_Rate_int == 5 or PHY_Bit_Rate_int == 11): + if PHY_Bit_Rate_int == 1 or PHY_Bit_Rate_int == 2 or PHY_Bit_Rate_int == 5 or PHY_Bit_Rate_int == 11: data = 1 else: data = 6 @@ -406,7 +402,7 @@ class abg11_calculator(): Preamble_1 = float(192) if (PHY_Bit == 1) or (PHY_Bit == 2) or (PHY_Bit == 5.5) or (PHY_Bit == 11): - Ttxframe = (14 * 8) / PHY_Bit + (Preamble_1) + Ttxframe = (14 * 8) / PHY_Bit + Preamble_1 Ttxframe_new = format(Ttxframe, '.2f') else: @@ -415,7 +411,7 @@ class abg11_calculator(): # RTS/CTS Handshake Overhead - if (PHY_Bit_Rate_int == 1 or PHY_Bit_Rate_int == 2 or PHY_Bit_Rate_int == 5 or PHY_Bit_Rate_int == 11): + if PHY_Bit_Rate_int == 1 or PHY_Bit_Rate_int == 2 or PHY_Bit_Rate_int == 5 or PHY_Bit_Rate_int == 11: SIFS_value = float(10) else: SIFS_value = float(16) @@ -425,7 +421,7 @@ class abg11_calculator(): elif "Yes" in self.RTS_CTS_Handshake: if (PHY_Bit == 1) or (PHY_Bit == 2) or (PHY_Bit == 5.5) or (PHY_Bit == 11): - RTS_CTS_Handshake = ((20 + 14) * 8) / PHY_Bit + (Preamble_1) + RTS_CTS_Handshake = ((20 + 14) * 8) / PHY_Bit + Preamble_1 else: RTS_CTS_Handshake = int(((20 + 14) * 8 + 22 + PHY_Bit * 4 - 1) / (PHY_Bit * 4)) * 4 + 2 * 20 @@ -441,26 +437,26 @@ class abg11_calculator(): CTS_to_self_Handshake = 0 else: if (PHY_Bit == 1) or (PHY_Bit == 2) or (PHY_Bit == 5.5) or (PHY_Bit == 11): - CTS_to_self_Handshake = (14 * 8) / PHY_Bit + (Preamble_1) + SIFS_value + CTS_to_self_Handshake = (14 * 8) / PHY_Bit + Preamble_1 + SIFS_value else: CTS_to_self_Handshake = int( (14 * 8 + 22 + PHY_Bit * 4 - 1) / (PHY_Bit * 4)) * 4 + 20 + SIFS_value # DIFS calulation - if (PHY_Bit_Rate_int == 1 or PHY_Bit_Rate_int == 2 or PHY_Bit_Rate_int == 5 or PHY_Bit_Rate_int == 11): + if PHY_Bit_Rate_int == 1 or PHY_Bit_Rate_int == 2 or PHY_Bit_Rate_int == 5 or PHY_Bit_Rate_int == 11: DIFS_value = 50 - elif ("Short" in self.slot_name): + elif "Short" in self.slot_name: DIFS_value = 34 else: DIFS_value = 50 # MeanBackoff calculation - if (PHY_Bit_Rate_int == 1 or PHY_Bit_Rate_int == 2 or PHY_Bit_Rate_int == 5 or PHY_Bit_Rate_int == 11): + if PHY_Bit_Rate_int == 1 or PHY_Bit_Rate_int == 2 or PHY_Bit_Rate_int == 5 or PHY_Bit_Rate_int == 11: c4 = (CWmin_str * 20 / 2) MeanBackoff_value = float(c4) - elif ("Short" in self.slot_name): + elif "Short" in self.slot_name: d2 = (CWmin_str * 9 / 2) MeanBackoff_value = float(d2) else: @@ -474,7 +470,7 @@ class abg11_calculator(): Nbits_value = (MAC_MPDU_Size * 8) # Tmac, time for MAC frame and Tplcp, time for MAC PLCP - if (PHY_Bit_Rate_int == 1 or PHY_Bit_Rate_int == 2 or PHY_Bit_Rate_int == 5 or PHY_Bit_Rate_int == 11): + if PHY_Bit_Rate_int == 1 or PHY_Bit_Rate_int == 2 or PHY_Bit_Rate_int == 5 or PHY_Bit_Rate_int == 11: Tmac_value = Nbits_value / yellow_cell if "Short" in self.Preamble: Tplcp = float(96) @@ -597,8 +593,6 @@ class abg11_calculator(): IP_Throughput_C6_new = "N/A" IP_Throughput_C7_new = "N/A" - - Voice_Call = Max_Frame_Rate_C1 / Codec_Frame_rate Voice_Call_value = round(Voice_Call) @@ -620,18 +614,18 @@ class abg11_calculator(): self.Estimated_MOS_Score = "N/A" self.Maximum_Bidirectional_Voice_Calls = "N/A" else: - if (Voice_Call_value <= 1): + if Voice_Call_value <= 1: Maximum_Bidirectional_Voice_Calls1 = self.Max_Frame_Rate_C1_round / Codec_Frame_rate - elif (Voice_Call_value <= 2): + elif Voice_Call_value <= 2: Maximum_Bidirectional_Voice_Calls1 = Max_Frame_Rate_C2_round / Codec_Frame_rate - elif (Voice_Call_value <= 5): + elif Voice_Call_value <= 5: Maximum_Bidirectional_Voice_Calls1 = Max_Frame_Rate_C3_round / Codec_Frame_rate - elif (Voice_Call_value <= 10): + elif Voice_Call_value <= 10: Maximum_Bidirectional_Voice_Calls1 = Max_Frame_Rate_C4_round / Codec_Frame_rate - elif (Voice_Call_value <= 20): + elif Voice_Call_value <= 20: Maximum_Bidirectional_Voice_Calls1 = Max_Frame_Rate_C5_round / Codec_Frame_rate - elif (Voice_Call_value <= 50): + elif Voice_Call_value <= 50: Maximum_Bidirectional_Voice_Calls1 = Max_Frame_Rate_C6_round / Codec_Frame_rate else: Maximum_Bidirectional_Voice_Calls1 = Max_Frame_Rate_C7_round / Codec_Frame_rate @@ -644,18 +638,17 @@ class abg11_calculator(): else: Estimated_MOS_Score_1 = 1 + 0.035 * self.Maximum_Theoretical_R_value + self.Maximum_Theoretical_R_value * ( - self.Maximum_Theoretical_R_value - 60) * ( + self.Maximum_Theoretical_R_value - 60) * ( 100 - self.Maximum_Theoretical_R_value) * 7 * 0.000001 self.Estimated_MOS_Score = round(Estimated_MOS_Score_1, 2) - - def get_result(self): print("\n" + "******************Station : 11abgCalculator*****************************" + "\n") print("Theoretical Maximum Offered Load" + "\n") print("1 Client:") - All_theoretical_output = {'Packet Interval(usec)': self.Client_1_new, 'Max Frame Rate(fps)': self.Max_Frame_Rate_C1_round, + All_theoretical_output = {'Packet Interval(usec)': self.Client_1_new, + 'Max Frame Rate(fps)': self.Max_Frame_Rate_C1_round, 'Max. Offered Load (802.11)(Mb/s)': self.Max_Offered_Load_C1_new, 'Offered Load Per 802.11 Client(Mb/s)': self.Offered_Load_Per_Client1_new, 'Offered Load (802.3 Side)(Mb/s)': self.Offered_Load_C1_new, @@ -677,9 +670,10 @@ class n11_calculator(abg11_calculator): def __init__(self, Traffic_Type, Data_Voice_MCS, Channel_Bandwidth, Guard_Interval_value, Highest_Basic_str, Encryption, QoS, IP_Packets_MSDU_str, MAC_Frames_per_A_MPDU_str, BSS_Basic_Rate, MAC_MPDU_Size_Data_Traffic, - Codec_Type, PLCP, CWmin, RTS_CTS_Handshake, CTS_to_self,PHY_Bit_Rate=None,MAC_Frame_802_11=None,Basic_Rate_Set=None,Preamble=None,slot_name=None): + Codec_Type, PLCP, CWmin, RTS_CTS_Handshake, CTS_to_self, PHY_Bit_Rate=None, MAC_Frame_802_11=None, + Basic_Rate_Set=None, Preamble=None, slot_name=None): super().__init__(Traffic_Type, PHY_Bit_Rate, Encryption, QoS, MAC_Frame_802_11, Basic_Rate_Set, Preamble, - slot_name, Codec_Type, RTS_CTS_Handshake, CTS_to_self) + slot_name, Codec_Type, RTS_CTS_Handshake, CTS_to_self) self.Data_Voice_MCS = Data_Voice_MCS self.Channel_Bandwidth = Channel_Bandwidth self.Guard_Interval_value = Guard_Interval_value @@ -691,7 +685,6 @@ class n11_calculator(abg11_calculator): self.PLCP = PLCP self.CWmin = CWmin - # This function is for calculate intermediate values and Theoretical values def calculate(self): @@ -875,7 +868,7 @@ class n11_calculator(abg11_calculator): MAC_MPDU_Size = int(self.MAC_MPDU_Size_Data_Traffic) else: - if ((IP_Packets_MSDU == 0)): + if IP_Packets_MSDU == 0: MAC_MPDU_Size = (Codec_IP_Packet_Size + 28 + QoS_Hdr + Encrypt_Hdr + 8) else: @@ -890,7 +883,7 @@ class n11_calculator(abg11_calculator): else: - MSDU_1 = (MAC_MPDU_Size - 28 - QoS_Hdr - Encrypt_Hdr - (IP_Packets_MSDU) * (14 + 3)) + MSDU_1 = (MAC_MPDU_Size - 28 - QoS_Hdr - Encrypt_Hdr - IP_Packets_MSDU * (14 + 3)) MSDU_final = MSDU_1 / IP_Packets_MSDU if MSDU_final < 0: @@ -1076,7 +1069,7 @@ class n11_calculator(abg11_calculator): # g22 A-MPDU Pad - if ((MAC_Frames_per_A_MPDU == 0)): + if MAC_Frames_per_A_MPDU == 0: MPDU_Pad = int(0) else: @@ -1087,7 +1080,7 @@ class n11_calculator(abg11_calculator): # c26 Nbits, Bits per MAC PPDU MAC_Frames_per_A_MPDU_loc = MAC_Frames_per_A_MPDU + 1 - if (MAC_Frames_per_A_MPDU == 0): + if MAC_Frames_per_A_MPDU == 0: Nbits_Bits_per_MAC_PPDU = MAC_MPDU_Size * 8 else: @@ -1100,7 +1093,7 @@ class n11_calculator(abg11_calculator): Guard_Interval_1 = 1 elif "800" in self.Guard_Interval_value: Guard_Interval_1 = 0 - calculation = (((Data_Voice_MCS_int > 7 and PLCP_Configuration_int == 2) or PLCP_Configuration_int == 1)) + calculation = ((Data_Voice_MCS_int > 7 and PLCP_Configuration_int == 2) or PLCP_Configuration_int == 1) if (Guard_Interval_1 == 1) and calculation: Tsymbol_Data_Symbol_Period = 3.60 @@ -1132,7 +1125,7 @@ class n11_calculator(abg11_calculator): (22 + 32 * 8 + PHY_Bit_Rate_of_Control_Frames * 4 - 1) / (PHY_Bit_Rate_of_Control_Frames * 4)) * 4 + 20 # g20 Use BlockAck - if (MAC_Frames_per_A_MPDU == 0): + if MAC_Frames_per_A_MPDU == 0: Use_BlockAck = False else: @@ -1228,14 +1221,14 @@ class n11_calculator(abg11_calculator): Client_14_new = format(Max_PPDU_Rate_7, '.2f') # c44 Max_MAC_MPDU_Rate_1 - if (MAC_Frames_per_A_MPDU > 0): - Max_MAC_MPDU_Rate_1 = (MAC_Frames_per_A_MPDU) * Max_PPDU_Rate_1 - Max_MAC_MPDU_Rate_2 = (MAC_Frames_per_A_MPDU) * Max_PPDU_Rate_2 - Max_MAC_MPDU_Rate_3 = (MAC_Frames_per_A_MPDU) * Max_PPDU_Rate_3 - Max_MAC_MPDU_Rate_4 = (MAC_Frames_per_A_MPDU) * Max_PPDU_Rate_4 - Max_MAC_MPDU_Rate_5 = (MAC_Frames_per_A_MPDU) * Max_PPDU_Rate_5 - Max_MAC_MPDU_Rate_6 = (MAC_Frames_per_A_MPDU) * Max_PPDU_Rate_6 - Max_MAC_MPDU_Rate_7 = (MAC_Frames_per_A_MPDU) * Max_PPDU_Rate_7 + if MAC_Frames_per_A_MPDU > 0: + Max_MAC_MPDU_Rate_1 = MAC_Frames_per_A_MPDU * Max_PPDU_Rate_1 + Max_MAC_MPDU_Rate_2 = MAC_Frames_per_A_MPDU * Max_PPDU_Rate_2 + Max_MAC_MPDU_Rate_3 = MAC_Frames_per_A_MPDU * Max_PPDU_Rate_3 + Max_MAC_MPDU_Rate_4 = MAC_Frames_per_A_MPDU * Max_PPDU_Rate_4 + Max_MAC_MPDU_Rate_5 = MAC_Frames_per_A_MPDU * Max_PPDU_Rate_5 + Max_MAC_MPDU_Rate_6 = MAC_Frames_per_A_MPDU * Max_PPDU_Rate_6 + Max_MAC_MPDU_Rate_7 = MAC_Frames_per_A_MPDU * Max_PPDU_Rate_7 else: Max_MAC_MPDU_Rate_1 = Max_PPDU_Rate_1 Max_MAC_MPDU_Rate_2 = Max_PPDU_Rate_2 @@ -1255,14 +1248,14 @@ class n11_calculator(abg11_calculator): # Max MAC MSDU Rate - if (IP_Packets_MSDU > 0): - Max_MAC_MSDU_Rate_1 = (IP_Packets_MSDU) * Max_MAC_MPDU_Rate_1 - Max_MAC_MSDU_Rate_2 = (IP_Packets_MSDU) * Max_MAC_MPDU_Rate_2 - Max_MAC_MSDU_Rate_3 = (IP_Packets_MSDU) * Max_MAC_MPDU_Rate_3 - Max_MAC_MSDU_Rate_4 = (IP_Packets_MSDU) * Max_MAC_MPDU_Rate_4 - Max_MAC_MSDU_Rate_5 = (IP_Packets_MSDU) * Max_MAC_MPDU_Rate_5 - Max_MAC_MSDU_Rate_6 = (IP_Packets_MSDU) * Max_MAC_MPDU_Rate_6 - Max_MAC_MSDU_Rate_7 = (IP_Packets_MSDU) * Max_MAC_MPDU_Rate_7 + if IP_Packets_MSDU > 0: + Max_MAC_MSDU_Rate_1 = IP_Packets_MSDU * Max_MAC_MPDU_Rate_1 + Max_MAC_MSDU_Rate_2 = IP_Packets_MSDU * Max_MAC_MPDU_Rate_2 + Max_MAC_MSDU_Rate_3 = IP_Packets_MSDU * Max_MAC_MPDU_Rate_3 + Max_MAC_MSDU_Rate_4 = IP_Packets_MSDU * Max_MAC_MPDU_Rate_4 + Max_MAC_MSDU_Rate_5 = IP_Packets_MSDU * Max_MAC_MPDU_Rate_5 + Max_MAC_MSDU_Rate_6 = IP_Packets_MSDU * Max_MAC_MPDU_Rate_6 + Max_MAC_MSDU_Rate_7 = IP_Packets_MSDU * Max_MAC_MPDU_Rate_7 else: Max_MAC_MSDU_Rate_1 = Max_MAC_MPDU_Rate_1 @@ -1458,15 +1451,13 @@ class n11_calculator(abg11_calculator): else: self.Maximum_Bidirectional_Voice_Calls = round(Maximum_Bidirectional, 2) - - def get_result(self): print("\n" + "******************Station : 11nCalculator*****************************" + "\n") print("Theoretical Maximum Offered Load" + "\n") print("1 Client:") All_theoretical_output = {'MAC PPDU Interval(usec)': self.Client_1_new, - 'Max PPDU Rate(fps)': self.Client_8_new, + 'Max PPDU Rate(fps)': self.Client_8_new, 'Max MAC MPDU Rate': self.Client_15_new, 'Max MAC MSDU Rate': self.Client_22_new, 'Max. 802.11 MAC Frame Data Rate(Mb/s)': self.Client_29_new, @@ -1488,20 +1479,18 @@ class n11_calculator(abg11_calculator): class ac11_calculator(n11_calculator): - - def __init__(self, Traffic_Type, Data_Voice_MCS, spatial, Channel_Bandwidth, Guard_Interval_value, - Highest_Basic_str, Encryption, QoS,IP_Packets_MSDU_str, MAC_Frames_per_A_MPDU_str, BSS_Basic_Rate, MAC_MPDU_Size_Data_Traffic, - Codec_Type, CWmin, RTS_CTS,PLCP = None,RTS_CTS_Handshake=None,CTS_to_self=None): + Highest_Basic_str, Encryption, QoS, IP_Packets_MSDU_str, MAC_Frames_per_A_MPDU_str, BSS_Basic_Rate, + MAC_MPDU_Size_Data_Traffic, + Codec_Type, CWmin, RTS_CTS, PLCP=None, RTS_CTS_Handshake=None, CTS_to_self=None): super().__init__(Traffic_Type, Data_Voice_MCS, Channel_Bandwidth, Guard_Interval_value, Highest_Basic_str, - Encryption, QoS, - IP_Packets_MSDU_str, MAC_Frames_per_A_MPDU_str, BSS_Basic_Rate, MAC_MPDU_Size_Data_Traffic, - Codec_Type, PLCP, CWmin, RTS_CTS_Handshake, CTS_to_self) + Encryption, QoS, + IP_Packets_MSDU_str, MAC_Frames_per_A_MPDU_str, BSS_Basic_Rate, MAC_MPDU_Size_Data_Traffic, + Codec_Type, PLCP, CWmin, RTS_CTS_Handshake, CTS_to_self) self.spatial = spatial self.RTS_CTS = RTS_CTS - # This function is for calculate intermediate values and Theoretical values def calculate(self): @@ -1695,7 +1684,7 @@ class ac11_calculator(n11_calculator): MAC_MPDU_Size = int(self.MAC_MPDU_Size_Data_Traffic) else: - if (IP_Packets_MSDU == 0): + if IP_Packets_MSDU == 0: MAC_MPDU_Size = (Codec_IP_Packet_Size + 28 + QoS_Hdr + Encrypt_Hdr + 8) else: @@ -1711,8 +1700,8 @@ class ac11_calculator(n11_calculator): else: - MSDU_1 = (MAC_MPDU_Size - 28 - QoS_Hdr - Encrypt_Hdr - (IP_Packets_MSDU) * (14 + 3)) - MSDU_final = (int(MSDU_1 / (IP_Packets_MSDU))) + MSDU_1 = (MAC_MPDU_Size - 28 - QoS_Hdr - Encrypt_Hdr - IP_Packets_MSDU * (14 + 3)) + MSDU_final = (int(MSDU_1 / IP_Packets_MSDU)) if MSDU_final < 0: MSDU = MSDU_final - 1 else: @@ -1775,7 +1764,7 @@ class ac11_calculator(n11_calculator): elif "800" in self.Guard_Interval_value: Guard_Interval_1 = 0 - calculation = (((Data_Voice_MCS_int > 7 and plcp == 2) or plcp == 1)) + calculation = ((Data_Voice_MCS_int > 7 and plcp == 2) or plcp == 1) if (Guard_Interval_1 == 1) and calculation: Tsymbol_Data_Symbol_Period = 3.60 @@ -1839,7 +1828,7 @@ class ac11_calculator(n11_calculator): # Nbits, Bits per MAC PPDU # A-MPDU Pad - if ((MAC_Frames_per_A_MPDU == 0)): + if MAC_Frames_per_A_MPDU == 0: MPDU_Pad = int(0) else: @@ -1848,7 +1837,7 @@ class ac11_calculator(n11_calculator): MPDU_Pad = int((y % 4)) MAC_Frames_per_A_MPDU_loc = MAC_Frames_per_A_MPDU + 1 - if (MAC_Frames_per_A_MPDU == 0): + if MAC_Frames_per_A_MPDU == 0: Nbits_Bits_per_MAC_PPDU = MAC_MPDU_Size * 8 else: @@ -1925,7 +1914,7 @@ class ac11_calculator(n11_calculator): # c37 Ack Response Overhead # g20 Use BlockAck - if (MAC_Frames_per_A_MPDU == 0): + if MAC_Frames_per_A_MPDU == 0: Use_BlockAck = False else: Use_BlockAck = True @@ -1987,14 +1976,14 @@ class ac11_calculator(n11_calculator): # c44 Max_MAC_MPDU_Rate_1 - if (MAC_Frames_per_A_MPDU > 0): - Max_MAC_MPDU_Rate_1 = (MAC_Frames_per_A_MPDU) * Max_PPDU_Rate_1 - Max_MAC_MPDU_Rate_2 = (MAC_Frames_per_A_MPDU) * Max_PPDU_Rate_2 - Max_MAC_MPDU_Rate_3 = (MAC_Frames_per_A_MPDU) * Max_PPDU_Rate_3 - Max_MAC_MPDU_Rate_4 = (MAC_Frames_per_A_MPDU) * Max_PPDU_Rate_4 - Max_MAC_MPDU_Rate_5 = (MAC_Frames_per_A_MPDU) * Max_PPDU_Rate_5 - Max_MAC_MPDU_Rate_6 = (MAC_Frames_per_A_MPDU) * Max_PPDU_Rate_6 - Max_MAC_MPDU_Rate_7 = (MAC_Frames_per_A_MPDU) * Max_PPDU_Rate_7 + if MAC_Frames_per_A_MPDU > 0: + Max_MAC_MPDU_Rate_1 = MAC_Frames_per_A_MPDU * Max_PPDU_Rate_1 + Max_MAC_MPDU_Rate_2 = MAC_Frames_per_A_MPDU * Max_PPDU_Rate_2 + Max_MAC_MPDU_Rate_3 = MAC_Frames_per_A_MPDU * Max_PPDU_Rate_3 + Max_MAC_MPDU_Rate_4 = MAC_Frames_per_A_MPDU * Max_PPDU_Rate_4 + Max_MAC_MPDU_Rate_5 = MAC_Frames_per_A_MPDU * Max_PPDU_Rate_5 + Max_MAC_MPDU_Rate_6 = MAC_Frames_per_A_MPDU * Max_PPDU_Rate_6 + Max_MAC_MPDU_Rate_7 = MAC_Frames_per_A_MPDU * Max_PPDU_Rate_7 else: Max_MAC_MPDU_Rate_1 = Max_PPDU_Rate_1 Max_MAC_MPDU_Rate_2 = Max_PPDU_Rate_2 @@ -2014,14 +2003,14 @@ class ac11_calculator(n11_calculator): # Max MAC MSDU Rate - if (IP_Packets_MSDU > 0): - Max_MAC_MSDU_Rate_1 = (IP_Packets_MSDU) * Max_MAC_MPDU_Rate_1 - Max_MAC_MSDU_Rate_2 = (IP_Packets_MSDU) * Max_MAC_MPDU_Rate_2 - Max_MAC_MSDU_Rate_3 = (IP_Packets_MSDU) * Max_MAC_MPDU_Rate_3 - Max_MAC_MSDU_Rate_4 = (IP_Packets_MSDU) * Max_MAC_MPDU_Rate_4 - Max_MAC_MSDU_Rate_5 = (IP_Packets_MSDU) * Max_MAC_MPDU_Rate_5 - Max_MAC_MSDU_Rate_6 = (IP_Packets_MSDU) * Max_MAC_MPDU_Rate_6 - Max_MAC_MSDU_Rate_7 = (IP_Packets_MSDU) * Max_MAC_MPDU_Rate_7 + if IP_Packets_MSDU > 0: + Max_MAC_MSDU_Rate_1 = IP_Packets_MSDU * Max_MAC_MPDU_Rate_1 + Max_MAC_MSDU_Rate_2 = IP_Packets_MSDU * Max_MAC_MPDU_Rate_2 + Max_MAC_MSDU_Rate_3 = IP_Packets_MSDU * Max_MAC_MPDU_Rate_3 + Max_MAC_MSDU_Rate_4 = IP_Packets_MSDU * Max_MAC_MPDU_Rate_4 + Max_MAC_MSDU_Rate_5 = IP_Packets_MSDU * Max_MAC_MPDU_Rate_5 + Max_MAC_MSDU_Rate_6 = IP_Packets_MSDU * Max_MAC_MPDU_Rate_6 + Max_MAC_MSDU_Rate_7 = IP_Packets_MSDU * Max_MAC_MPDU_Rate_7 else: Max_MAC_MSDU_Rate_1 = Max_MAC_MPDU_Rate_1 @@ -2162,8 +2151,10 @@ class ac11_calculator(n11_calculator): if self.Maximum_Theoretical_R_value > 100: self.Estimated_MOS_Score = 4.5 else: - Estimated_MOS_Score_1 = (1 + 0.035 * self.Maximum_Theoretical_R_value + self.Maximum_Theoretical_R_value * ( - self.Maximum_Theoretical_R_value - 60) * (100 - self.Maximum_Theoretical_R_value) * 7 * 0.000001) + Estimated_MOS_Score_1 = ( + 1 + 0.035 * self.Maximum_Theoretical_R_value + self.Maximum_Theoretical_R_value * ( + self.Maximum_Theoretical_R_value - 60) * ( + 100 - self.Maximum_Theoretical_R_value) * 7 * 0.000001) self.Estimated_MOS_Score = format(Estimated_MOS_Score_1, '.2f') # Voice_Call_Range @@ -2207,7 +2198,6 @@ class ac11_calculator(n11_calculator): else: self.Maximum_Bidirectional_Voice_Calls = round(Maximum_Bidirectional, 2) - def get_result(self): print("\n" + "******************Station : 11ac Calculator*****************************" + "\n") @@ -2228,4 +2218,4 @@ class ac11_calculator(n11_calculator): All_theoretical_voice = {'Maximum Theoretical R-value': self.Maximum_Theoretical_R_value, 'Estimated MOS Score': self.Estimated_MOS_Score, 'Maximum Bidirectional Voice Calls(calls)': self.Maximum_Bidirectional_Voice_Calls} - print(json.dumps(All_theoretical_voice, indent=4)) \ No newline at end of file + print(json.dumps(All_theoretical_voice, indent=4)) diff --git a/py-json/ws-sta-monitor.py b/py-json/ws-sta-monitor.py index c957be29..daf870b3 100755 --- a/py-json/ws-sta-monitor.py +++ b/py-json/ws-sta-monitor.py @@ -18,6 +18,7 @@ import traceback from time import sleep import websocket import re + try: import thread except ImportError: @@ -27,25 +28,23 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit() - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) LFUtils = importlib.import_module("py-json.LANforge.LFUtils") - -cre={ - "phy": re.compile(r'^(1\.\d+):\s+(\S+)\s+\(phy', re.I), - "ifname": re.compile(r'(1\.\d+):\s+IFNAME=(\S+)\s+', re.I), - "port": re.compile(r'Port (\S+)', re.I), - "connected": re.compile(r'.*?CTRL-EVENT-CONNECTED - Connection to ([a-f0-9:]+) complete', re.I), - "associated": re.compile(r'^.*?Associated with ([a-f0-9:]+)$', re.I), - "auth": re.compile(r'.*: auth ([a-f0-9:]+) -> ([a-f0-9:]+) status: 0: Successful', re.I), - "authenticated": re.compile(r'.*?Authenticated with ([a-f0-9:]+)', re.I), - "associating": re.compile(r'.*?Trying to associate with ([a-f0-9:]+)', re.I), - "authenticating": re.compile(r'.*?[>]SME: Trying to authenticate with ([a-f0-9:]+)', re.I), +cre = { + "phy": re.compile(r'^(1\.\d+):\s+(\S+)\s+\(phy', re.I), + "ifname": re.compile(r'(1\.\d+):\s+IFNAME=(\S+)\s+', re.I), + "port": re.compile(r'Port (\S+)', re.I), + "connected": re.compile(r'.*?CTRL-EVENT-CONNECTED - Connection to ([a-f0-9:]+) complete', re.I), + "associated": re.compile(r'^.*?Associated with ([a-f0-9:]+)$', re.I), + "auth": re.compile(r'.*: auth ([a-f0-9:]+) -> ([a-f0-9:]+) status: 0: Successful', re.I), + "authenticated": re.compile(r'.*?Authenticated with ([a-f0-9:]+)', re.I), + "associating": re.compile(r'.*?Trying to associate with ([a-f0-9:]+)', re.I), + "authenticating": re.compile(r'.*?[>]SME: Trying to authenticate with ([a-f0-9:]+)', re.I), } -ignore=[ +ignore = [ ": scan finished", ": scan started", ": scan aborted: ", @@ -68,13 +67,14 @@ ignore=[ ] rebank = { - "ifname" : re.compile("IFNAME=(\S+)") + "ifname": re.compile("IFNAME=(\S+)") } websock = None host = "localhost" base_url = None port = 8081 + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def usage(): print("""Example: __file__ --host 192.168.1.101 --port 8081\n""") @@ -94,7 +94,7 @@ def main(): base_url = "unset" try: args = parser.parse_args() - if (args.host is None): + if args.host is None: host = "localhost" elif (type(args) is tuple) or (type(args) is list): host = args.host[0] @@ -104,7 +104,7 @@ def main(): base_url = "ws://%s:%s" % (host, port) except Exception as e: - print("Exception: "+e) + print("Exception: " + e) logging.exception(e) usage() exit(2) @@ -125,79 +125,74 @@ def sock_filter(wsock, text): resource = None for test in ignore: - if (test in text): - if (debug): - print (" ignoring ",text) - return; + if test in text: + if debug: + print(" ignoring ", text) + return try: message = json.loads(text) - except Exception as ex: - print ("Json Exception: ", repr(ex)) - traceback.print_exc() - - try: # big generic filter for wifi-message or details keys try: - if ("details" in message.keys()): + if "details" in message.keys(): for test in ignore: - if (test in message["details"]): - return; + if test in message["details"]: + return except KeyError: print("Message lacks key 'details'") try: - if ("wifi-event" in message.keys()): + if "wifi-event" in message.keys(): for test in ignore: # print (" is ",test, " in ", message["wifi-event"]) - if (test in message["wifi-event"]): - return; + if test in message["wifi-event"]: + return except KeyError: print("Message lacks key 'wifi-event'") - if (("time" in message.keys()) and ("timestamp" in message.keys())): + if ("time" in message.keys()) and ("timestamp" in message.keys()): return - if ("name" in message.keys()): + if "name" in message.keys(): station_name = message["name"] - if ("resource" in message.keys()): + if "resource" in message.keys(): resource = "1.", message["resource"] - if ("event_type" in message.keys()): + if "event_type" in message.keys(): match_result = cre["port"].match(message["details"]) - if (match_result is not None): + if match_result is not None: station_name = match_result.group(1) - if (message["is_alert"]): + if message["is_alert"]: print("alert: ", message["details"]) # LFUtils.debug_printer.pprint(message) return else: # LFUtils.debug_printer.pprint(message) - if (" IP change from " in message["details"]): - if (" to 0.0.0.0" in messsage["details"]): + if " IP change from " in message["details"]: + if " to 0.0.0.0" in message["details"]: print("e: %s.%s lost IP address", [resource, station_name]) else: print("e: %s.%s gained IP address", [resource, station_name]) - if ("Link DOWN" in message["details"]): + if "Link DOWN" in message["details"]: return # duplicates alert print("event: ", message["details"]) return - if ("wifi-event" in message.keys()): - if ("CTRL-EVENT-CONNECTED" in message["wifi-event"]): + if "wifi-event" in message.keys(): + if "CTRL-EVENT-CONNECTED" in message["wifi-event"]: # redunant return if (("CTRL-EVENT-CONNECTED - Connection to " in message["wifi-event"]) and ( " complete" in message["wifi-event"])): - return; - if ((": assoc " in message["wifi-event"]) and ("status: 0: Successful" in message["wifi-event"])): return - if ((station_name is None) or (resource is None)): + if (": assoc " in message["wifi-event"]) and ("status: 0: Successful" in message["wifi-event"]): + return + if (station_name is None) or (resource is None): try: match_result = cre["phy"].match(message["wifi-event"]) - if (match_result is not None): + if match_result is not None: # LFUtils.debug_printer.pprint(match_result) # LFUtils.debug_printer.pprint(match_result.groups()) resource = match_result.group(1) @@ -206,7 +201,7 @@ def sock_filter(wsock, text): match_result = cre["ifname"].match(message["wifi-event"]) # LFUtils.debug_printer.pprint(match_result) # LFUtils.debug_printer.pprint(match_result.groups()) - if (match_result is not None): + if match_result is not None: resource = match_result.group(1) station_name = match_result.group(2) else: @@ -221,9 +216,9 @@ def sock_filter(wsock, text): sleep(1) # print ("Determined station name: as %s.%s"%(resource, station_name)) - if ((": auth ") and ("status: 0: Successful" in message["wifi-event"])): + if ": auth " and ("status: 0: Successful" in message["wifi-event"]): match_result = cre["auth"].match(message["wifi-event"]) - if (match_result and match_result.groups()): + if match_result and match_result.groups(): bssid = match_result.group(1) print("station %s.%s auth with %s" % (resource, station_name, bssid)) return @@ -231,9 +226,9 @@ def sock_filter(wsock, text): print("station %s.%s auth with ??" % (resource, station_name)) LFUtils.debug_printer.pprint(match_result) - if ("Associated with " in message["wifi-event"]): + if "Associated with " in message["wifi-event"]: match_result = cre["associated"].match(message["wifi-event"]) - if (match_result and match_result.groups()): + if match_result and match_result.groups(): bssid = match_result.group(1) print("station %s.%s assocated with %s" % (resource, station_name, bssid)) return @@ -241,9 +236,9 @@ def sock_filter(wsock, text): print("station %s.%s assocated with ??" % (resource, station_name)) LFUtils.debug_printer.pprint(match_result) - if (" - Connection to " in message["wifi-event"]): + if " - Connection to " in message["wifi-event"]: match_result = cre["connected"].match(message["wifi-event"]) - if (match_result and match_result.groups()): + if match_result and match_result.groups(): bssid = match_result.group(1) print("station %s.%s connected to %s" % (resource, station_name, bssid)) return @@ -251,14 +246,14 @@ def sock_filter(wsock, text): print("station %s.%s connected to ??" % (resource, station_name)) LFUtils.debug_printer.pprint(match_result) - if ("disconnected" in message["wifi-event"]): + if "disconnected" in message["wifi-event"]: print("Station %s.%s down" % (resource, station_name)) return - if ("Trying to associate with " in message["wifi-event"]): + if "Trying to associate with " in message["wifi-event"]: match_result = cre["associating"].match(message["wifi-event"]) - if (match_result and match_result.groups()): + if match_result and match_result.groups(): bssid = match_result.group(1) print("station %s.%s associating with %s" % (resource, station_name, bssid)) return @@ -266,10 +261,10 @@ def sock_filter(wsock, text): print("station %s.%s associating with ??" % (resource, station_name)) LFUtils.debug_printer.pprint(match_result) - if ("Trying to authenticate" in message["wifi-event"]): + if "Trying to authenticate" in message["wifi-event"]: match_result = cre["authenticating"].match(message["wifi-event"]) - if (match_result and match_result.groups()): + if match_result and match_result.groups(): bssid = match_result.group(1) print("station %s.%s authenticating with %s" % (resource, station_name, bssid)) return @@ -277,10 +272,10 @@ def sock_filter(wsock, text): print("station %s.%s authenticating with ??" % (resource, station_name)) LFUtils.debug_printer.pprint(match_result) - if ("Authenticated" in message["wifi-event"]): + if "Authenticated" in message["wifi-event"]: match_result = cre["authenticed"].match(message["wifi-event"]) LFUtils.debug_printer.pprint(match_result) - if (match_result and match_result.groups()): + if match_result and match_result.groups(): bssid = match_result.group(1) print("station %s.%s authenticated with %s" % (resource, station_name, bssid)) else: @@ -291,6 +286,10 @@ def sock_filter(wsock, text): print("\nUnhandled: ") LFUtils.debug_printer.pprint(message) + except Exception as ex: + traceback.print_exc() + raise ("Json Exception: ", repr(ex)) + except KeyError as kerr: print("# ----- Bad Key: ----- ----- ----- ----- ----- ----- ----- ----- ----- -----") print("input: ", text) @@ -317,6 +316,7 @@ def sock_filter(wsock, text): sleep(1) return + # ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- def m_error(wsock, err): print("# ----- Error: ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----\n") @@ -355,7 +355,6 @@ def start_websocket(uri, websock): if __name__ == '__main__': main() - #### #### #### diff --git a/py-json/ws_generic_monitor.py b/py-json/ws_generic_monitor.py index 174e9403..c8fff5c8 100644 --- a/py-json/ws_generic_monitor.py +++ b/py-json/ws_generic_monitor.py @@ -13,13 +13,11 @@ WS_Listener has three arguments in general : lfclient_host, _scriptname, _callba """ -class WS_Listener(): + +class WS_Listener: def __init__(self, lfclient_host="localhost", _scriptname=None, _callback=None): import websocket self.scriptname = _scriptname websocket.enableTrace(True) - self.ws = websocket.WebSocketApp("ws://"+lfclient_host+":8081", on_message=_callback) + self.ws = websocket.WebSocketApp("ws://" + lfclient_host + ":8081", on_message=_callback) self.ws.run_forever() - - - diff --git a/py-scripts/artifacts/report.css b/py-scripts/artifacts/report.css index 542ba429..517d9190 100644 --- a/py-scripts/artifacts/report.css +++ b/py-scripts/artifacts/report.css @@ -368,8 +368,8 @@ td.scriptdetails span.copybtn { } td.scriptdetails:hover span.copybtn { display: inline-block; - padding: 5px; - font-size: 12px; + padding: 2px; + font-size:10px; float: left; color: #050; background: white; diff --git a/py-scripts/asus_ap.py b/py-scripts/asus_ap.py new file mode 100644 index 00000000..b4f7f14a --- /dev/null +++ b/py-scripts/asus_ap.py @@ -0,0 +1,179 @@ +#!/usr/bin/python3 + +''' +NAME: +asus_ap.py + +PURPOSE: +Generic AP library that will work for the ASUS ap's + +EXAMPLE: + +./asus_ap.py --ap_port '/dev/ttyUSB0' --ap_baud '115200' --ap_cmd "wl -i wl1 bs_data" + +./asus_ap.py --ap_port '/dev/ttyUSB0' --ap_baud '115200' --ap_cmd "wl -i wl1 bs_data" --ap_file 'ap_file.txt' + + + +NOTES: + + + +''' + +import sys +if sys.version_info[0] != 3: + print("This script requires Python3") + exit() + +import argparse +import pexpect +import serial +from pexpect_serial import SerialSpawn + + +# see https://stackoverflow.com/a/13306095/11014343 +class FileAdapter(object): + def __init__(self, logger): + self.logger = logger + def write(self, data): + # NOTE: data can be a partial line, multiple lines + data = data.strip() # ignore leading/trailing whitespace + if data: # non-blank + self.logger.info(data) + def flush(self): + pass # leave it to logging to flush properly + + +class lf_ap(): + def __init__(self, + _ap_test_mode = False, + _ap_2G_interface = "wl0", + _ap_5G_interface = "wl1", + _ap_6G_interface = "wl2", + _ap_scheme = 'serial', + _ap_serial_port = '/dev/ttyUSB0', + _ap_ssh_port = "22", + _ap_telnet_port = "23", + _ap_serial_baud = '115200', + _ap_report_dir = "", + _ap_log_file = ""): + self.ap_test_mode = _ap_test_mode + self.ap_2G_interface = _ap_2G_interface + self.ap_5G_interface = _ap_5G_interface + self.ap_6G_interface = _ap_6G_interface + self.ap_scheme = _ap_scheme + self.ap_serial_port = _ap_serial_port + self.ap_telnet_port = _ap_ssh_port + self.ap_telnet = _ap_telnet_port + self.ap_serial_baud = _ap_serial_baud + self.ap_report_dir = _ap_report_dir + self.ap_log_file = _ap_log_file + + def ap_action(self): + + print("ap_cmd: {}".format(self.ap_cmd)) + try: + ser = serial.Serial(self.ap_port, int(self.ap_baud), timeout=5) + ss = SerialSpawn(ser) + ss.sendline(str(self.ap_cmd)) + ss.expect([pexpect.TIMEOUT], timeout=2) # do not detete line, waits for output + ap_results = ss.before.decode('utf-8','ignore') + print("ap_results {}".format(ap_results)) + except: + ap_results = "exception on accessing {} Command: {}\r\n".format(self.ap_port,self.ap_cmd) + print("{}".format(ap_results)) + + if(self.ap_file != None): + ap_file = open(str(self.ap_file),"a") + ap_file.write(ap_results) + ap_file.close() + print("ap file written {}".format(str(self.ap_file))) + + # ASUS + def ap_clear_stats(self,band): + pass + + # ASUS bs_data + def ap_ul_data(self,band): + pass + + # ASUS rx_report + def ap_dl_data(self,band): + pass + + # ASUS chanel info (channel utilization) + def ap_chanim(self,band): + pass + + def ap_ul_stats(self,band): + pass + + def ap_dl_stats(self,band): + pass + + def ap_store_dl_scheduler_stats(self,band): + if band is "6G": + pass + + def ap_store_ul_scheduler_stats(self,band): + pass + + + def ap_ofdma_stats(self,band): + pass + +def main(): + + parser = argparse.ArgumentParser( + prog='lf_ap.py', + #formatter_class=argparse.RawDescriptionHelpFormatter, + formatter_class=argparse.RawTextHelpFormatter, + epilog='''\ + Useful Information: + 1. Useful Information goes here + ''', + + description='''\ +lf_ap.py: +-------------------- +Summary : +---------- +This file is used for verification + +Commands: (wl2 == 6GHz wl1 == 5GHz , wl0 == 24ghz) + +read ap data:: 'wl -i wl1 bs_data' +reset scheduler's counters:: 'wl -i wl1 dump_clear' +UL scheduler statistics:: 'wl -i wl1 dump umsched' +DL scheduler statistics:: 'wl -i wl1 dump msched' + +Generic command layout: +----------------------- + + ''') + parser.add_argument('--ap_test_mode', help='--ap_mode ',default=True) + parser.add_argument('--ap_port', help='--ap_port \'/dev/ttyUSB0\'',default='/dev/ttyUSB0') + parser.add_argument('--ap_baud', help='--ap_baud \'115200\'',default='115200') + parser.add_argument('--ap_cmd', help='--ap_cmd \'wl -i wl1 bs_data\'',default='wl -i wl1 bs_data') + parser.add_argument('--ap_file', help='--ap_file \'ap_file.txt\'') + + args = parser.parse_args() + + __ap_port = args.ap_port + __ap_baud = args.ap_baud + __ap_cmd = args.ap_cmd + __ap_file = args.ap_file + + ap_dut = lf_ap( + _ap_port = __ap_port, + _ap_baud = __ap_baud, + _ap_cmd = __ap_cmd , + _ap_file = __ap_file) + + ap_dut.ap_action() + +if __name__ == '__main__': + main() + + diff --git a/py-scripts/check_argparse.py b/py-scripts/check_argparse.py index 1702e5c0..cdd65ce7 100644 --- a/py-scripts/check_argparse.py +++ b/py-scripts/check_argparse.py @@ -5,13 +5,6 @@ import pandas as pd import argparse -def get_tag(x, tag): - try: - return x[tag] - except: - return False - - def main(): parser = argparse.ArgumentParser( prog="check_argparse.py", @@ -29,7 +22,7 @@ def main(): text = open(os.path.join(args.path, file)).read() results_file = dict() results_file['argparse'] = 'argparse.' in text - if results_file['argparse'] is True: + if results_file['argparse']: results_file['create_basic'] = 'create_basic_argparse' in text results_file['create_bare'] = 'create_bare_argparse' in text results_file['prog'] = 'prog=' in text @@ -48,7 +41,9 @@ def main(): 'description', 'epilog', 'usage']: - df[tag] = [get_tag(x, tag) for x in df['results']] + for result in df['results']: + if tag in result: + df[tag] = df['results'][tag] df['details'] = df['description'] + df['epilog'] + df['usage'] df.to_csv(args.output + '.csv', index=False) diff --git a/py-scripts/create_bond.py b/py-scripts/create_bond.py index b094622e..2e9b75f8 100755 --- a/py-scripts/create_bond.py +++ b/py-scripts/create_bond.py @@ -19,7 +19,7 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - + sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") @@ -58,7 +58,8 @@ class CreateBond(LFCliBase): "resource": self.resource, "port": "bond0000", "current_flags": 0x80000000, - "interest": 0x4000 # (0x2 + 0x4000 + 0x800000) # current, dhcp, down + # (0x2 + 0x4000 + 0x800000) # current, dhcp, down + "interest": 0x4000 } self.json_post("cli-json/set_port", bond_set_port) diff --git a/py-scripts/create_bridge.py b/py-scripts/create_bridge.py index c830e646..5dd6661b 100755 --- a/py-scripts/create_bridge.py +++ b/py-scripts/create_bridge.py @@ -13,7 +13,6 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") @@ -24,7 +23,7 @@ Realm = realm.Realm class CreateBridge(Realm): - def __init__(self,sta_list,resource,target_device,radio, + def __init__(self, sta_list, resource, target_device, radio, _ssid=None, _security=None, _password=None, @@ -54,7 +53,6 @@ class CreateBridge(Realm): pprint.pprint(self.sta_list) print("---- ~bridge List ----- ----- ----- ----- ----- ----- \n") - def build(self): # Build bridges @@ -71,13 +69,12 @@ class CreateBridge(Realm): "resource": self.resource, "port": "br0", "current_flags": 0x80000000, - "interest": 0x4000 # (0x2 + 0x4000 + 0x800000) # current, dhcp, down + # (0x2 + 0x4000 + 0x800000) # current, dhcp, down + "interest": 0x4000 } self.json_post("cli-json/set_port", bridge_set_port) - - def main(): parser = LFCliBase.create_basic_argparse( prog='create_bridge.py', @@ -101,17 +98,19 @@ Command example: --debug ''') required = parser.add_argument_group('required arguments') - required.add_argument('--target_device', help='Where the bridges should be connecting', required=True) - #required.add_argument('--security', help='WiFi Security protocol: < open | wep | wpa | wpa2 | wpa3 >', required=True) + required.add_argument( + '--target_device', help='Where the bridges should be connecting', required=True) + # required.add_argument('--security', help='WiFi Security protocol: < open | wep | wpa | wpa2 | wpa3 >', required=True) optional = parser.add_argument_group('optional arguments') - optional.add_argument('--num_bridges', help='Number of bridges to Create', required=False) + optional.add_argument( + '--num_bridges', help='Number of bridges to Create', required=False) args = parser.parse_args() - #if args.debug: + # if args.debug: # pprint.pprint(args) # time.sleep(5) - if (args.radio is None): - raise ValueError("--radio required") + if args.radio is None: + raise ValueError("--radio required") num_bridge = 2 if (args.num_bridges is not None) and (int(args.num_bridges) > 0): @@ -119,25 +118,26 @@ Command example: num_bridge = num_bridges_converted bridge_list = LFUtils.port_name_series(prefix="bridge", - start_id=0, - end_id=num_bridge-1, - padding_number=10000, - radio=args.radio) + start_id=0, + end_id=num_bridge - 1, + padding_number=10000, + radio=args.radio) create_bridge = CreateBridge(_host=args.mgr, - _port=args.mgr_port, - _ssid=args.ssid, - _password=args.passwd, - _security=args.security, - _bridge_list=bridge_list, - radio=args.radio, - _debug_on=args.debug, - sta_list=bridge_list, - resource=1, - target_device=args.target_device) + _port=args.mgr_port, + _ssid=args.ssid, + _password=args.passwd, + _security=args.security, + _bridge_list=bridge_list, + radio=args.radio, + _debug_on=args.debug, + sta_list=bridge_list, + resource=1, + target_device=args.target_device) create_bridge.build() print('Created %s bridges' % num_bridge) + if __name__ == "__main__": main() diff --git a/py-scripts/create_chamberview.py b/py-scripts/create_chamberview.py index c8b4f2af..1dfff7b6 100755 --- a/py-scripts/create_chamberview.py +++ b/py-scripts/create_chamberview.py @@ -41,7 +41,6 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) cv_test_manager = importlib.import_module("py-json.cv_test_manager") @@ -52,28 +51,31 @@ class CreateChamberview(cv): def __init__(self, lfmgr="localhost", port="8080", - ): + ): super().__init__( - lfclient_host=lfmgr, - lfclient_port=port, + lfclient_host=lfmgr, + lfclient_port=port, ) self.lfmgr = lfmgr self.port = port - def clean_cv_scenario(self,type="Network-Connectivity",scenario_name=None): - self.rm_cv_text_blob(type,scenario_name) + def clean_cv_scenario( + self, + cv_type="Network-Connectivity", + scenario_name=None): + self.rm_cv_text_blob(cv_type, scenario_name) def setup(self, - create_scenario="", - line="", - raw_line=[]): + create_scenario="", + line="", + raw_line=None): if raw_line: print("creating %s scenario" % create_scenario) for create_lines in raw_line: - self.pass_raw_lines_to_cv(create_scenario,create_lines[0]) + self.pass_raw_lines_to_cv(create_scenario, create_lines[0]) - #check for lines + # check for lines if line: scenario_name = create_scenario line = line @@ -88,85 +90,80 @@ class CreateChamberview(cv): Freq = "-1" VLAN = "" - for i in range(len(line)): - if " " in line[i][0]: - line[i][0] = (re.split(' ', line[i][0])) - elif "," in line[i][0]: - line[i][0] = (re.split(',', line[i][0])) - elif ", " in line[i][0]: - line[i][0] = (re.split(',', line[i][0])) - elif " ," in line[i][0]: - line[i][0] = (re.split(',', line[i][0])) + for item in line: + if " " in item[0]: + item[0] = (re.split(' ', item[0])) + elif "," in item[0]: + item[0] = (re.split(',', item[0])) else: print("Wrong arguments entered !") exit(1) print("creating %s scenario" % scenario_name) - for j in range(len(line[i][0])): - line[i][0][j] = line[i][0][j].split("=") - for k in range(len(line[i][0][j])): - name = line[i][0][j][k] - if str(name) == "Resource" or str(name) == "Res" or str(name) == "R": - Resource = line[i][0][j][k + 1] - elif str(name) == "Profile" or str(name) == "Prof" or str(name) == "P": - Profile = line[i][0][j][k + 1] - elif str(name) == "Amount" or str(name) == "Sta" or str(name) == "A": - Amount = line[i][0][j][k + 1] - elif str(name) == "Uses-1" or str(name) == "U1" or str(name) == "U-1": - Uses1 = line[i][0][j][k + 1] - elif str(name) == "Uses-2" or str(name) == "U2" or str(name) == "U-2": - Uses2 = line[i][0][j][k + 1] - elif str(name) == "Freq" or str(name) == "Freq" or str(name) == "F": - Freq = line[i][0][j][k + 1] - elif str(name) == "DUT" or str(name) == "dut" or str(name) == "D": - DUT = line[i][0][j][k + 1] - elif str(name) == "DUT_Radio" or str(name) == "dr" or str(name) == "DR": - DUT_Radio = line[i][0][j][k + 1] - elif str(name) == "Traffic" or str(name) == "Traf" or str(name) == "T": - Traffic = line[i][0][j][k + 1] - elif str(name) == "VLAN" or str(name) == "Vlan" or str(name) == "V": - VLAN = line[i][0][j][k + 1] - else: - continue + for sub_item in item[0]: + sub_item = sub_item.split("=") + if sub_item[0] == "Resource" or str( + sub_item[0]) == "Res" or sub_item[0] == "R": + Resource = sub_item[1] + elif sub_item[0] == "Profile" or sub_item[0] == "Prof" or sub_item[0] == "P": + Profile = sub_item[1] + elif sub_item[0] == "Amount" or sub_item[0] == "Sta" or sub_item[0] == "A": + Amount = sub_item[1] + elif sub_item[0] == "Uses-1" or sub_item[0] == "U1" or sub_item[0] == "U-1": + Uses1 = sub_item[1] + elif sub_item[0] == "Uses-2" or sub_item[0] == "U2" or sub_item[0] == "U-2": + Uses2 = sub_item[1] + elif sub_item[0] == "Freq" or sub_item[0] == "Freq" or sub_item[0] == "F": + Freq = sub_item[1] + elif sub_item[0] == "DUT" or sub_item[0] == "dut" or sub_item[0] == "D": + DUT = sub_item[1] + elif sub_item[0] == "DUT_Radio" or sub_item[0] == "dr" or sub_item[0] == "DR": + DUT_Radio = sub_item[1] + elif sub_item[0] == "Traffic" or sub_item[0] == "Traf" or sub_item[0] == "T": + Traffic = sub_item[1] + elif sub_item[0] == "VLAN" or sub_item[0] == "Vlan" or sub_item[0] == "V": + VLAN = sub_item[1] + else: + continue self.add_text_blob_line(scenario_name, - Resource, - Profile, - Amount, - DUT, - DUT_Radio, - Uses1, - Uses2, - Traffic, - Freq, - VLAN - ); # To manage scenario + Resource, + Profile, + Amount, + DUT, + DUT_Radio, + Uses1, + Uses2, + Traffic, + Freq, + VLAN + ) # To manage scenario if not line and not raw_line: raise Exception("scenario creation failed") return True - def build(self,scenario_name): + def build(self, scenario_name): self.sync_cv() # chamberview sync time.sleep(2) self.apply_cv_scenario(scenario_name) # Apply scenario - self.show_text_blob(None, None, False) # Show changes on GUI + self.show_text_blob(None, None, False) # Show changes on GUI self.apply_cv_scenario(scenario_name) # Apply scenario self.build_cv_scenario() # build scenario tries = 0 - while (True): + while True: self.get_popup_info_and_close() if not self.get_cv_is_built(): # It can take a while to build a large scenario, so wait-time # is currently max of 5 minutes. - print("Waiting %i/300 for Chamber-View to be built." % (tries)) + print("Waiting %i/300 for Chamber-View to be built." % tries) tries += 1 - if (tries > 300): + if tries > 300: break time.sleep(1) else: break - print("completed building %s scenario" %scenario_name) + print("completed building %s scenario" % scenario_name) def main(): @@ -177,36 +174,53 @@ def main(): For Two line scenario use --line twice as shown in example, for multi line scenario use --line argument to create multiple lines \n - create_chamberview.py -m "localhost" -o "8080" -cs "scenario_name" - --line "Resource=1.1 Profile=STA-AC Amount=1 Uses-1=wiphy0 Uses-2=AUTO Freq=-1 - DUT=Test DUT_Radio=Radio-1 Traffic=http VLAN=" - --line "Resource=1.1 Profile=upstream Amount=1 Uses-1=eth1 Uses-2=AUTO Freq=-1 + create_chamberview.py -m "localhost" -o "8080" -cs "scenario_name" + --line "Resource=1.1 Profile=STA-AC Amount=1 Uses-1=wiphy0 Uses-2=AUTO Freq=-1 DUT=Test DUT_Radio=Radio-1 Traffic=http VLAN=" - ******************************** OR ******************************** + --line "Resource=1.1 Profile=upstream Amount=1 Uses-1=eth1 Uses-2=AUTO Freq=-1 + DUT=Test DUT_Radio=Radio-1 Traffic=http VLAN=" + ******************************** OR ******************************** create_chamberview.py -m "localhost" -o "8080" -cs "scenario_name" --raw_line "profile_link 1.1 STA-AC 10 'DUT: temp Radio-1' tcp-dl-6m-vi wiphy0,AUTO -1" --raw_line "profile_link 1.1 upstream 1 'DUT: temp Radio-1' tcp-dl-6m-vi eth1,AUTO -1" - + """) - parser.add_argument("-m", "--lfmgr", type=str, - help="address of the LANforge GUI machine (localhost is default)") - parser.add_argument("-o", "--port", type=int, default=8080, - help="IP Port the LANforge GUI is listening on (8080 is default)") - parser.add_argument("-cs", "--create_scenario", "--create_lf_scenario", type=str, - help="name of scenario to be created") + parser.add_argument( + "-m", + "--lfmgr", + type=str, + help="address of the LANforge GUI machine (localhost is default)") + parser.add_argument( + "-o", + "--port", + type=int, + default=8080, + help="IP Port the LANforge GUI is listening on (8080 is default)") + parser.add_argument( + "-cs", + "--create_scenario", + "--create_lf_scenario", + type=str, + help="name of scenario to be created") parser.add_argument("-l", "--line", action='append', nargs='+', help="line number", default=[]) parser.add_argument("-rl", "--raw_line", action='append', nargs=1, help="raw lines", default=[]) - parser.add_argument("-ds", "--delete_scenario", default=False, action='store_true', - help="delete scenario (by default: False)") + parser.add_argument( + "-ds", + "--delete_scenario", + default=False, + action='store_true', + help="delete scenario (by default: False)") args = parser.parse_args() Create_Chamberview = CreateChamberview(lfmgr=args.lfmgr, port=args.port, ) if args.delete_scenario: - Create_Chamberview.clean_cv_scenario(type="Network-Connectivity", scenario_name=args.create_scenario) + Create_Chamberview.clean_cv_scenario( + cv_type="Network-Connectivity", + scenario_name=args.create_scenario) Create_Chamberview.setup(create_scenario=args.create_scenario, line=args.line, diff --git a/py-scripts/create_chamberview_dut.py b/py-scripts/create_chamberview_dut.py index b21c75a8..9951ec45 100755 --- a/py-scripts/create_chamberview_dut.py +++ b/py-scripts/create_chamberview_dut.py @@ -54,7 +54,6 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) # from cv_dut_profile import cv_dut as dut @@ -70,7 +69,7 @@ class DUT(dut): lfmgr="localhost", port="8080", dut_name="DUT", - ssid=[], + ssid=None, sw_version="NA", hw_version="NA", serial_num="NA", @@ -87,12 +86,13 @@ class DUT(dut): desired_dut_flags=dut_flags, desired_dut_flags_mask=dut_flags ) + if ssid is None: + ssid = [] self.cv_dut_name = dut_name self.cv_test = cvtest(lfmgr, port) self.dut_name = dut_name self.ssid = ssid - def setup(self): self.create_dut() @@ -115,16 +115,14 @@ class DUT(dut): d[item[0].lower()] = item[1] self.ssid[j] = d self.ssid[j]['flag'] = [] - self.ssid[j].keys - flag=0x0 + flag = 0x0 if 'security' in self.ssid[j].keys(): - self.ssid[j]['security'] = self.ssid[j]['security'].split('|') + self.ssid[j]['security'] = self.ssid[j]['security'].split( + '|') for security in self.ssid[j]['security']: - try: + if security.lower() in flags: flag |= flags[security.lower()] - except: - pass self.ssid[j]['flag'] = flag if 'bssid' not in self.ssid[j].keys(): @@ -148,34 +146,55 @@ def main(): prog='create_chamberview_dut.py', formatter_class=argparse.RawTextHelpFormatter, description=""" - ./create_chamberview_dut -m "localhost" -o "8080" -d "dut_name" - --ssid "ssid_idx=0 ssid=NET1 security=WPA|WEP|11r|EAP-PEAP bssid=78:d2:94:bf:16:41" + ./create_chamberview_dut -m "localhost" -o "8080" -d "dut_name" + --ssid "ssid_idx=0 ssid=NET1 security=WPA|WEP|11r|EAP-PEAP bssid=78:d2:94:bf:16:41" --ssid "ssid_idx=1 ssid=NET1 security=WPA password=test bssid=78:d2:94:bf:16:40" """) - parser.add_argument("-m", "--lfmgr", type=str, default="localhost", - help="address of the LANforge GUI machine (localhost is default)") - parser.add_argument("-o", "--port", type=str, default="8080", - help="IP Port the LANforge GUI is listening on (8080 is default)") + parser.add_argument( + "-m", + "--lfmgr", + type=str, + default="localhost", + help="address of the LANforge GUI machine (localhost is default)") + parser.add_argument( + "-o", + "--port", + type=str, + default="8080", + help="IP Port the LANforge GUI is listening on (8080 is default)") parser.add_argument("-d", "--dut_name", type=str, default="DUT", help="set dut name") parser.add_argument("-s", "--ssid", action='append', nargs=1, help="SSID", default=[]) - parser.add_argument("--sw_version", default="NA", help="DUT Software version.") - parser.add_argument("--hw_version", default="NA", help="DUT Hardware version.") - parser.add_argument("--serial_num", default="NA", help="DUT Serial number.") + parser.add_argument( + "--sw_version", + default="NA", + help="DUT Software version.") + parser.add_argument( + "--hw_version", + default="NA", + help="DUT Hardware version.") + parser.add_argument( + "--serial_num", + default="NA", + help="DUT Serial number.") parser.add_argument("--model_num", default="NA", help="DUT Model Number.") - parser.add_argument('--dut_flag', help='station flags to add', default=None, action='append') + parser.add_argument( + '--dut_flag', + help='station flags to add', + default=None, + action='append') args = parser.parse_args() new_dut = DUT(lfmgr=args.lfmgr, port=args.port, dut_name=args.dut_name, ssid=args.ssid, - sw_version = args.sw_version, - hw_version = args.hw_version, - serial_num = args.serial_num, - model_num = args.model_num, + sw_version=args.sw_version, + hw_version=args.hw_version, + serial_num=args.serial_num, + model_num=args.model_num, dut_flags=args.dut_flag ) diff --git a/py-scripts/create_l3.py b/py-scripts/create_l3.py index 68457ce1..b2a44c6e 100755 --- a/py-scripts/create_l3.py +++ b/py-scripts/create_l3.py @@ -16,7 +16,6 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) LANforge = importlib.import_module("py-json.LANforge") @@ -46,10 +45,12 @@ class CreateL3(Realm): self.endp_a = endp_a self.mode = mode self.name_prefix = name_prefix - self.station_profile = self.new_station_profile() + # self.station_profile = self.new_station_profile() + # self.station_profile.lfclient_url = self.lfclient_url + # self.station_list= LFUtils.portNameSeries(prefix_="sta", start_id_=0, + # end_id_=2, padding_number_=10000, radio='wiphy0') #Make radio a user + # defined variable from terminal. self.cx_profile = self.new_l3_cx_profile() - self.station_profile.lfclient_url = self.lfclient_url - self.station_list= LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=2, padding_number_=10000, radio='wiphy0') #Make radio a user defined variable from terminal. self.cx_profile.host = self.host self.cx_profile.port = self.port self.cx_profile.name_prefix = self.name_prefix @@ -66,47 +67,16 @@ class CreateL3(Realm): side_a=self.endp_a, side_b=self.endp_b, sleep_time=0) + # self.cx_profile.start_cx() self._pass("PASS: Cross-connect build finished") -def main(): - parser = LFCliBase.create_basic_argparse( - prog='create_l3.py', - formatter_class=argparse.RawTextHelpFormatter, - epilog='''\ - Generate traffic between ports - ''', - description='''\ - ''') +def main(args): - required_args = None - for group in parser._action_groups: - if group.title == "required arguments": - required_args = group - break - if required_args is not None: - required_args.add_argument('--min_rate_a', help='--min_rate_a bps rate minimum for side_a', default=56000) - required_args.add_argument('--min_rate_b', help='--min_rate_b bps rate minimum for side_b', default=56000) - required_args.add_argument('--endp_a', help='--endp_a station list', default=["eth1"], action="append") - required_args.add_argument('--endp_b', help='--upstream port', default="eth2") + num_sta = 0 + # if (args.num_stations is not None) and (int(args.num_stations) > 0): + # num_sta = int(args.num_stations) - optional_args = None - for group in parser._action_groups: - if group.title == "optional arguments": - optional_args = group - break; - if optional_args is not None: - optional_args.add_argument('--mode', help='Used to force mode of stations', default=0) - optional_args.add_argument('--ap', help='Used to force a connection to a particular AP') - optional_args.add_argument('--number_template', help='Start the station numbering with a particular number. Default is 0000', default=0000) - args = parser.parse_args() - - num_sta = 2 - if (args.num_stations is not None) and (int(args.num_stations) > 0): - num_sta = int(args.num_stations) - - # station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=int(args.number_template), end_id_=num_sta+int(args.number_template) - 1, padding_number_=10000, - # radio=args.radio) ip_var_test = CreateL3(host=args.mgr, port=args.mgr_port, name_prefix="VT", @@ -117,13 +87,53 @@ def main(): mode=args.mode, _debug_on=args.debug) - ip_var_test.pre_cleanup() + # ip_var_test.pre_cleanup() ip_var_test.build() if not ip_var_test.passes(): print(ip_var_test.get_fail_message()) ip_var_test.exit_fail() - print('Created %s stations and connections' % num_sta) + print(f'Created {num_sta} stations and connections') if __name__ == "__main__": - main() + parser = LFCliBase.create_basic_argparse( + prog='create_l3.py', + formatter_class=argparse.RawTextHelpFormatter, + epilog='''\ + Generate traffic between ports + ''', + description='''\ + ''') + parser.add_argument( + '--min_rate_a', + help='--min_rate_a bps rate minimum for side_a', + default=56000) + parser.add_argument( + '--min_rate_b', + help='--min_rate_b bps rate minimum for side_b', + default=56000) + parser.add_argument( + '--endp_a', + help='--endp_a station list', + default=[], + action="append", + required=True) + parser.add_argument( + '--endp_b', + help='--upstream port', + default="eth2", + required=True) + parser.add_argument( + '--mode', + help='Used to force mode of stations', + default=0) + parser.add_argument( + '--ap', + help='Used to force a connection to a particular AP') + parser.add_argument( + '--number_template', + help='Start the station numbering with a particular number. Default is 0000', + default=0000) + args = parser.parse_args() + + main(args) diff --git a/py-scripts/create_l3_stations.py b/py-scripts/create_l3_stations.py index 65521043..df5ea5ff 100755 --- a/py-scripts/create_l3_stations.py +++ b/py-scripts/create_l3_stations.py @@ -5,6 +5,8 @@ Example script: './create_l3_stations.py --radio wiphy0 --ssid lanforge --password password --security wpa2' + './create_l3_stations.py --station_list sta00,sta01 --radio wiphy0 --ssid lanforge --password password --security wpa2' + './create_l3_stations.py --station_list sta00 sta01 --radio wiphy0 --ssid lanforge --password password --security wpa2' """ import sys @@ -24,15 +26,28 @@ from realm import Realm class CreateL3(Realm): - def __init__(self, - ssid, security, password, sta_list, name_prefix, upstream, radio, - host="localhost", port=8080, mode=0, ap=None, - side_a_min_rate=56, side_a_max_rate=0, - side_b_min_rate=56, side_b_max_rate=0, - number_template="00000", use_ht160=False, - _debug_on=False, - _exit_on_error=False, - _exit_on_fail=False): + def __init__( + self, + ssid, + security, + password, + sta_list, + name_prefix, + upstream, + radio, + host="localhost", + port=8080, + mode=0, + ap=None, + side_a_min_rate=56, + side_a_max_rate=0, + side_b_min_rate=56, + side_b_max_rate=0, + number_template="00000", + use_ht160=False, + _debug_on=False, + _exit_on_error=False, + _exit_on_fail=False): super().__init__(host, port) self.upstream = upstream self.host = host @@ -61,7 +76,9 @@ class CreateL3(Realm): self.station_profile.mode = mode if self.ap is not None: self.station_profile.set_command_param("add_sta", "ap", self.ap) - # self.station_list= LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=2, padding_number_=10000, radio='wiphy0') #Make radio a user defined variable from terminal. + # self.station_list= LFUtils.portNameSeries(prefix_="sta", start_id_=0, + # end_id_=2, padding_number_=10000, radio='wiphy0') #Make radio a user + # defined variable from terminal. self.cx_profile.host = self.host self.cx_profile.port = self.port @@ -74,7 +91,7 @@ class CreateL3(Realm): def pre_cleanup(self): self.cx_profile.cleanup_prefix() for sta in self.sta_list: - self.rm_port(sta, check_exists=True) + self.rm_port(sta, check_exists=True, debug_=False) def build(self): @@ -83,8 +100,10 @@ class CreateL3(Realm): self.password) self.station_profile.set_number_template(self.number_template) print("Creating stations") - self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) - self.station_profile.set_command_param("set_port", "report_timer", 1500) + self.station_profile.set_command_flag( + "add_sta", "create_admin_down", 1) + self.station_profile.set_command_param( + "set_port", "report_timer", 1500) self.station_profile.set_command_flag("set_port", "rpt_timer", 1) self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, @@ -108,7 +127,7 @@ def main(): create_l3_stations.py: -------------------- Generic command layout: - + python3 ./create_l3_stations.py --upstream_port eth1 --radio wiphy0 @@ -136,39 +155,92 @@ def main(): --ap "00:0e:8e:78:e1:76" --number_template 0000 --debug + + python3 ./create_l3_stations.py + --upstream_port eth1 + --radio wiphy0 + --station_list sta00,sta01 + --security {open|wep|wpa|wpa2|wpa3} \\ + --mode 1 + {"auto" : "0", + "a" : "1", + "b" : "2", + "g" : "3", + "abg" : "4", + "abgn" : "5", + "bgn" : "6", + "bg" : "7", + "abgnAC" : "8", + "anAC" : "9", + "an" : "10", + "bgnAC" : "11", + "abgnAX" : "12", + "bgnAX" : "13", + --ssid netgear + --password admin123 + --a_min 1000 + --b_min 1000 + --ap "00:0e:8e:78:e1:76" + --number_template 0000 + --debug ''') required_args = None for group in parser._action_groups: if group.title == "required arguments": required_args = group - break; + break if required_args is not None: - required_args.add_argument('--a_min', help='--a_min bps rate minimum for side_a', default=256000) - required_args.add_argument('--b_min', help='--b_min bps rate minimum for side_b', default=256000) + required_args.add_argument( + '--a_min', + help='--a_min bps rate minimum for side_a', + default=256000) + required_args.add_argument( + '--b_min', + help='--b_min bps rate minimum for side_b', + default=256000) optional_args = None for group in parser._action_groups: if group.title == "optional arguments": optional_args = group - break; - if optional_args is not None: - optional_args.add_argument('--mode', help='Used to force mode of stations') - optional_args.add_argument('--ap', help='Used to force a connection to a particular AP') - optional_args.add_argument('--number_template', help='Start the station numbering with a particular number. Default is 0000', default=0000) - optional_args.add_argument('--station_list', help='Optional: User defined station names', action='append',default=None) + break + if optional_args: + optional_args.add_argument( + '--mode', help='Used to force mode of stations') + optional_args.add_argument( + '--ap', help='Used to force a connection to a particular AP') + optional_args.add_argument( + '--number_template', + help='Start the station numbering with a particular number. Default is 0000', + default=0000) + optional_args.add_argument( + '--station_list', + help='Optional: User defined station names, can be a comma or space separated list', + nargs='+', + default=None) + optional_args.add_argument( + '--no_cleanup', + help="Optional: Don't cleanup existing stations", + action='store_true') args = parser.parse_args() num_sta = 2 if (args.num_stations is not None) and (int(args.num_stations) > 0): num_sta = int(args.num_stations) - if args.station_list is None: - station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=int(args.number_template), end_id_=num_sta+int(args.number_template) - 1, padding_number_=10000, - radio=args.radio) + if not args.station_list: + station_list = LFUtils.portNameSeries( + prefix_="sta", start_id_=int( + args.number_template), end_id_=num_sta + int( + args.number_template) - 1, padding_number_=10000, radio=args.radio) else: - station_list = args.station_list - + if ',' in args.station_list[0]: + station_list = args.station_list[0].split(',') + elif ' ' in args.station_list[0]: + station_list = args.station_list[0].split() + else: + station_list = args.station_list ip_var_test = CreateL3(host=args.mgr, port=args.mgr_port, number_template=str(args.number_template), @@ -186,7 +258,8 @@ def main(): ap=args.ap, _debug_on=args.debug) - ip_var_test.pre_cleanup() + if not args.no_cleanup: + ip_var_test.pre_cleanup() ip_var_test.build() if not ip_var_test.passes(): print(ip_var_test.get_fail_message()) diff --git a/py-scripts/create_l4.py b/py-scripts/create_l4.py index 12662b49..e8b6c1d8 100755 --- a/py-scripts/create_l4.py +++ b/py-scripts/create_l4.py @@ -13,7 +13,6 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") @@ -25,15 +24,28 @@ TestGroupProfile = realm.TestGroupProfile class CreateL4(Realm): - def __init__(self, - ssid, security, password, sta_list, name_prefix, upstream, radio, - host="localhost", port=8080, mode = 0, ap=None, - side_a_min_rate=56, side_a_max_rate=0, - side_b_min_rate=56, side_b_max_rate=0, - number_template="00000", use_ht160=False, - _debug_on=False, - _exit_on_error=False, - _exit_on_fail=False): + def __init__( + self, + ssid, + security, + password, + sta_list, + name_prefix, + upstream, + radio, + host="localhost", + port=8080, + mode=0, + ap=None, + side_a_min_rate=56, + side_a_max_rate=0, + side_b_min_rate=56, + side_b_max_rate=0, + number_template="00000", + use_ht160=False, + _debug_on=False, + _exit_on_error=False, + _exit_on_fail=False): super().__init__(host, port) self.upstream = upstream self.host = host @@ -43,8 +55,8 @@ class CreateL4(Realm): self.security = security self.password = password self.radio = radio - self.mode= mode - self.ap=ap + self.mode = mode + self.ap = ap self.number_template = number_template self.debug = _debug_on self.name_prefix = name_prefix @@ -61,9 +73,10 @@ class CreateL4(Realm): self.station_profile.mode = 9 self.station_profile.mode = mode if self.ap is not None: - self.station_profile.set_command_param("add_sta", "ap",self.ap) - #self.station_list= LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=2, padding_number_=10000, radio='wiphy0') #Make radio a user defined variable from terminal. - + self.station_profile.set_command_param("add_sta", "ap", self.ap) + # self.station_list= LFUtils.portNameSeries(prefix_="sta", start_id_=0, + # end_id_=2, padding_number_=10000, radio='wiphy0') #Make radio a user + # defined variable from terminal. self.cx_profile.host = self.host self.cx_profile.port = self.port @@ -76,22 +89,34 @@ class CreateL4(Realm): def cleanup(self): self.cx_profile.cleanup() self.station_profile.cleanup() - LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, - port_list=self.station_profile.station_names, - debug=self.debug) + LFUtils.wait_until_ports_disappear( + base_url=self.lfclient_url, + port_list=self.station_profile.station_names, + debug=self.debug) def build(self): # Build stations - self.station_profile.use_security(self.security, self.ssid, self.password) + self.station_profile.use_security( + self.security, self.ssid, self.password) self.station_profile.set_number_template(self.number_template) print("Creating stations") - self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) - self.station_profile.set_command_param("set_port", "report_timer", 1500) + self.station_profile.set_command_flag( + "add_sta", "create_admin_down", 1) + self.station_profile.set_command_param( + "set_port", "report_timer", 1500) self.station_profile.set_command_flag("set_port", "rpt_timer", 1) - self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug) + self.station_profile.create( + radio=self.radio, + sta_names_=self.sta_list, + debug=self.debug) self._pass("PASS: Station build finished") - self.cx_profile.create(ports=self.station_profile.station_names, sleep_time=.5, debug_=self.debug, suppress_related_commands_=True) + self.cx_profile.create( + ports=self.station_profile.station_names, + sleep_time=.5, + debug_=self.debug, + suppress_related_commands_=True) + def main(): parser = LFCliBase.create_basic_argparse( @@ -134,46 +159,61 @@ python3 ./layer4.py --debug ''') - required_args=None + required_args = None for group in parser._action_groups: if group.title == "required arguments": - required_args=group - break; + required_args = group + break if required_args is not None: - required_args.add_argument('--a_min', help='--a_min bps rate minimum for side_a', default=256000) - required_args.add_argument('--b_min', help='--b_min bps rate minimum for side_b', default=256000) + required_args.add_argument( + '--a_min', + help='--a_min bps rate minimum for side_a', + default=256000) + required_args.add_argument( + '--b_min', + help='--b_min bps rate minimum for side_b', + default=256000) - optional_args=None + optional_args = None for group in parser._action_groups: if group.title == "optional arguments": - optional_args=group - break; + optional_args = group + break if optional_args is not None: - optional_args.add_argument('--mode',help='Used to force mode of stations', default=0) - optional_args.add_argument('--ap',help='Used to force a connection to a particular AP') + optional_args.add_argument( + '--mode', + help='Used to force mode of stations', + default=0) + optional_args.add_argument( + '--ap', help='Used to force a connection to a particular AP') args = parser.parse_args() num_sta = 2 if (args.num_stations is not None) and (int(args.num_stations) > 0): num_sta = int(args.num_stations) - station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=num_sta-1, padding_number_=10000, radio=args.radio) + station_list = LFUtils.portNameSeries( + prefix_="sta", + start_id_=0, + end_id_=num_sta - 1, + padding_number_=10000, + radio=args.radio) ip_var_test = CreateL4(host=args.mgr, - port=args.mgr_port, - number_template="0000", - sta_list=station_list, - name_prefix="VT", - upstream=args.upstream_port, - ssid=args.ssid, - password=args.passwd, - radio=args.radio, - security=args.security, - use_ht160=False, - side_a_min_rate=args.a_min, - side_b_min_rate=args.b_min, - mode=args.mode, - ap=args.ap, - _debug_on=args.debug) + port=args.mgr_port, + number_template="0000", + sta_list=station_list, + name_prefix="VT", + upstream=args.upstream_port, + ssid=args.ssid, + password=args.passwd, + radio=args.radio, + security=args.security, + use_ht160=False, + side_a_min_rate=args.a_min, + side_b_min_rate=args.b_min, + mode=args.mode, + ap=args.ap, + _debug_on=args.debug) ip_var_test.cleanup() ip_var_test.build() diff --git a/py-scripts/create_macvlan.py b/py-scripts/create_macvlan.py index 5694f006..7123b23e 100755 --- a/py-scripts/create_macvlan.py +++ b/py-scripts/create_macvlan.py @@ -8,7 +8,6 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") @@ -29,7 +28,7 @@ class CreateMacVlan(Realm): netmask=None, gateway=None, dhcp=True, - port_list=[], + port_list=None, ip_list=None, connections_per_port=1, _debug_on=False, @@ -51,7 +50,6 @@ class CreateMacVlan(Realm): self.mvlan_profile = self.new_mvlan_profile() - self.mvlan_profile.num_macvlans = int(num_ports) self.mvlan_profile.desired_macvlans = self.port_list self.mvlan_profile.macvlan_parent = self.macvlan_parent @@ -65,10 +63,14 @@ class CreateMacVlan(Realm): def build(self): # Build stations print("Creating MACVLANs") - self.mvlan_profile.create(admin_down=False, sleep_time=.5, debug=self.debug) + self.mvlan_profile.create( + admin_down=False, + sleep_time=.5, + debug=self.debug) self._pass("PASS: MACVLAN build finished") self.created_ports += self.mvlan_profile.created_macvlans + def main(): parser = LFCliBase.create_bare_argparse( prog='create_macvlan.py', @@ -80,7 +82,7 @@ def main(): create_macvlan.py: -------------------- Generic command layout: -./create_macvlan.py --macvlan_parent --num_ports +./create_macvlan.py --macvlan_parent --num_ports --first_mvlan_ip --netmask --gateway ./create_macvlan.py --macvlan_parent eth2 --num_ports 3 --first_mvlan_ip 192.168.92.13 @@ -97,25 +99,58 @@ Generic command layout: --use_ports eth1#0=10.40.3.103,eth1#1,eth1#2 --connections_per_port 2 --netmask 255.255.240.0 --gateway 10.40.0.1 + You can only add MAC-VLANs to Ethernet, Bonding, Redir, and 802.1Q VLAN devices. + ''') - parser.add_argument('--num_stations', help='Number of stations to create', default=0) + parser.add_argument( + '--num_stations', + help='Number of stations to create', + default=0) parser.add_argument('--radio', help='radio EID, e.g: 1.wiphy2') - parser.add_argument('-u', '--upstream_port', - help='non-station port that generates traffic: ., e.g: 1.eth1', - default='1.eth1') - parser.add_argument('--macvlan_parent', help='specifies parent port for macvlan creation', default=None) - parser.add_argument('--first_port', help='specifies name of first port to be used', default=None) - parser.add_argument('--num_ports', help='number of ports to create', default=1) - parser.add_argument('--connections_per_port', help='specifies number of connections to be used per port', default=1, - type=int) - parser.add_argument('--use_ports', help='list of comma separated ports to use with ips, \'=\' separates name and ip' - '{ port_name1=ip_addr1,port_name1=ip_addr2 }. ' - 'Ports without ips will be left alone', default=None) - parser.add_argument('--first_mvlan_ip', help='specifies first static ip address to be used or dhcp', default=None) - parser.add_argument('--netmask', help='specifies netmask to be used with static ip addresses', default=None) - parser.add_argument('--gateway', help='specifies default gateway to be used with static addressing', default=None) - parser.add_argument('--cxs', help='list of cxs to add/remove depending on use of --add_to_group or --del_from_group' - , default=None) + parser.add_argument( + '-u', + '--upstream_port', + help='non-station port that generates traffic: ., e.g: 1.eth1', + default='1.eth1') + parser.add_argument( + '--macvlan_parent', + help='specifies parent port for macvlan creation', + required=True) + parser.add_argument( + '--first_port', + help='specifies name of first port to be used', + default=None) + parser.add_argument( + '--num_ports', + help='number of ports to create', + default=1) + parser.add_argument( + '--connections_per_port', + help='specifies number of connections to be used per port', + default=1, + type=int) + parser.add_argument( + '--use_ports', + help='list of comma separated ports to use with ips, \'=\' separates name and ip' + '{ port_name1=ip_addr1,port_name1=ip_addr2 }. ' + 'Ports without ips will be left alone', + default=None) + parser.add_argument( + '--first_mvlan_ip', + help='specifies first static ip address to be used or dhcp', + default=None) + parser.add_argument( + '--netmask', + help='specifies netmask to be used with static ip addresses', + default=None) + parser.add_argument( + '--gateway', + help='specifies default gateway to be used with static addressing', + default=None) + parser.add_argument( + '--cxs', + help='list of cxs to add/remove depending on use of --add_to_group or --del_from_group', + default=None) args = parser.parse_args() port_list = [] @@ -125,27 +160,38 @@ Generic command layout: if (args.num_ports is not None) and (int(args.num_ports) > 0): start_num = int(args.first_port[3:]) num_ports = int(args.num_ports) - port_list = LFUtils.port_name_series(prefix="sta", start_id=start_num, end_id=start_num + num_ports - 1, - padding_number=10000, - radio=args.radio) + port_list = LFUtils.port_name_series( + prefix="sta", + start_id=start_num, + end_id=start_num + num_ports - 1, + padding_number=10000, + radio=args.radio) else: - if (args.num_ports is not None) and args.macvlan_parent is not None and (int(args.num_ports) > 0) \ - and args.macvlan_parent in args.first_port: - start_num = int(args.first_port[args.first_port.index('#') + 1:]) + if (args.num_ports is not None) and args.macvlan_parent is not None and ( + int(args.num_ports) > 0) and args.macvlan_parent in args.first_port: + start_num = int( + args.first_port[args.first_port.index('#') + 1:]) num_ports = int(args.num_ports) - port_list = LFUtils.port_name_series(prefix=args.macvlan_parent + "#", start_id=start_num, - end_id=start_num + num_ports - 1, padding_number=100000, - radio=args.radio) + port_list = LFUtils.port_name_series( + prefix=args.macvlan_parent + "#", + start_id=start_num, + end_id=start_num + num_ports - 1, + padding_number=100000, + radio=args.radio) else: - raise ValueError("Invalid values for num_ports [%s], macvlan_parent [%s], and/or first_port [%s].\n" - "first_port must contain parent port and num_ports must be greater than 0" - % (args.num_ports, args.macvlan_parent, args.first_port)) + raise ValueError( + "Invalid values for num_ports [%s], macvlan_parent [%s], and/or first_port [%s].\n" + "first_port must contain parent port and num_ports must be greater than 0" % + (args.num_ports, args.macvlan_parent, args.first_port)) else: if args.use_ports is None: num_ports = int(args.num_ports) - port_list = LFUtils.port_name_series(prefix=args.macvlan_parent + "#", start_id=0, - end_id=num_ports - 1, padding_number=100000, - radio=args.radio) + port_list = LFUtils.port_name_series( + prefix=args.macvlan_parent + "#", + start_id=0, + end_id=num_ports - 1, + padding_number=100000, + radio=args.radio) else: temp_list = args.use_ports.split(',') for port in temp_list: @@ -156,7 +202,8 @@ Generic command layout: ip_list.append(0) if len(port_list) != len(ip_list): - raise ValueError(temp_list, " ports must have matching ip addresses!") + raise ValueError( + temp_list, " ports must have matching ip addresses!") if args.first_mvlan_ip is not None: if args.first_mvlan_ip.lower() == "dhcp": diff --git a/py-scripts/create_qvlan.py b/py-scripts/create_qvlan.py index aa6ac8a1..510281ce 100755 --- a/py-scripts/create_qvlan.py +++ b/py-scripts/create_qvlan.py @@ -8,7 +8,7 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - + sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") @@ -29,11 +29,15 @@ class CreateQVlan(Realm): netmask=None, first_qvlan_ip=None, gateway=None, - port_list=[], - ip_list=[], + port_list=None, + ip_list=None, exit_on_error=False, debug=False): super().__init__(host, port) + if port_list is None: + port_list = [] + if ip_list is None: + ip_list = [] self.host = host self.port = port self.qvlan_parent = qvlan_parent @@ -54,7 +58,8 @@ class CreateQVlan(Realm): def build(self): print("Creating QVLAN stations") - self.qvlan_profile.create(admin_down=False, sleep_time=.5, debug=self.debug) + self.qvlan_profile.create( + sleep_time=.5) def main(): @@ -68,21 +73,50 @@ def main(): --------------------- Generic command ''') parser.add_argument('--radio', help='radio EID, e.g: 1.wiphy2') - parser.add_argument('--qvlan_parent', help='specifies parent port for qvlan creation', default=None) - parser.add_argument('--first_port', help='specifies name of first port to be used', default=None) - parser.add_argument('--num_ports', help='number of ports to create', default=1) - parser.add_argument('--first_qvlan_ip', help='specifies first static ip address to be used or dhcp', default=None) - parser.add_argument('--netmask', help='specifies netmask to be used with static ip addresses', default=None) - parser.add_argument('--gateway', help='specifies default gateway to be used with static addressing', default=None) - parser.add_argument('--use_ports', - help='list of comma separated ports to use with ips, \'=\' separates name and ip { port_name1=ip_addr1,port_name1=ip_addr2 }. Ports without ips will be left alone', - default=None) + parser.add_argument( + '--qvlan_parent', + help='specifies parent port for qvlan creation', + default=None, + required=True) + parser.add_argument( + '--first_port', + help='specifies name of first port to be used', + default=None) + parser.add_argument( + '--num_ports', + type=int, + help='number of ports to create', + default=1) + parser.add_argument( + '--first_qvlan_ip', + help='specifies first static ip address to be used or dhcp', + default=None) + parser.add_argument( + '--netmask', + help='specifies netmask to be used with static ip addresses', + default=None) + parser.add_argument( + '--gateway', + help='specifies default gateway to be used with static addressing', + default=None) + parser.add_argument( + '--use_ports', + help='list of comma separated ports to use with ips, \'=\' separates name and ip { port_name1=ip_addr1,port_name1=ip_addr2 }. Ports without ips will be left alone', + default=None) tg_group = parser.add_mutually_exclusive_group() - tg_group.add_argument('--add_to_group', help='name of test group to add cxs to', default=None) - parser.add_argument('--cxs', help='list of cxs to add/remove depending on use of --add_to_group or --del_from_group' - , default=None) - parser.add_argument('--use_qvlans', help='will create qvlans', action='store_true', default=False) - + tg_group.add_argument( + '--add_to_group', + help='name of test group to add cxs to', + default=None) + parser.add_argument( + '--cxs', + help='list of cxs to add/remove depending on use of --add_to_group or --del_from_group', + default=None) + parser.add_argument( + '--use_qvlans', + help='will create qvlans', + action='store_true', + default=False) args = parser.parse_args() @@ -100,34 +134,44 @@ def main(): update_group_args['cxs'] = args.cxs port_list = [] ip_list = [] - if args.first_port is not None and args.use_ports is not None: + if args.first_port and args.use_ports: if args.first_port.startswith("sta"): - if (args.num_ports is not None) and (int(args.num_ports) > 0): + if args.num_ports and args.num_ports > 0: start_num = int(args.first_port[3:]) - num_ports = int(args.num_ports) - port_list = LFUtils.port_name_series(prefix="sta", start_id=start_num, end_id=start_num + num_ports - 1, - padding_number=10000, - radio=args.radio) + port_list = LFUtils.port_name_series( + prefix="sta", + start_id=start_num, + end_id=start_num + args.num_ports - 1, + padding_number=10000, + radio=args.radio) print(1) else: - if (args.num_ports is not None) and args.qvlan_parent is not None and (int(args.num_ports) > 0) \ - and args.qvlan_parent in args.first_port: - start_num = int(args.first_port[args.first_port.index('#') + 1:]) - num_ports = int(args.num_ports) - port_list = LFUtils.port_name_series(prefix=args.qvlan_parent + "#", start_id=start_num, - end_id=start_num + num_ports - 1, padding_number=10000, - radio=args.radio) + if args.num_ports and args.qvlan_parent and (args.num_ports > 0) and args.qvlan_parent in args.first_port: + start_num = int( + args.first_port[args.first_port.index('#') + 1:]) + port_list = LFUtils.port_name_series( + prefix=str( + args.qvlan_parent) + "#", + start_id=start_num, + end_id=start_num + args.num_ports - 1, + padding_number=10000, + radio=args.radio) print(2) else: - raise ValueError("Invalid values for num_ports [%s], qvlan_parent [%s], and/or first_port [%s].\n" - "first_port must contain parent port and num_ports must be greater than 0" - % (args.num_ports, args.qvlan_parent, args.first_port)) + raise ValueError( + "Invalid values for num_ports [%s], qvlan_parent [%s], and/or first_port [%s].\n" + "first_port must contain parent port and num_ports must be greater than 0" % + (args.num_ports, args.qvlan_parent, args.first_port)) else: - if args.use_ports is None: + if not args.use_ports: num_ports = int(args.num_ports) - port_list = LFUtils.port_name_series(prefix=args.qvlan_parent + "#", start_id=1, - end_id=num_ports, padding_number=10000, - radio=args.radio) + port_list = LFUtils.port_name_series( + prefix=str( + args.qvlan_parent) + "#", + start_id=1, + end_id=num_ports, + padding_number=10000, + radio=args.radio) print(3) else: temp_list = args.use_ports.split(',') @@ -139,7 +183,8 @@ def main(): ip_list.append(0) if len(port_list) != len(ip_list): - raise ValueError(temp_list, " ports must have matching ip addresses!") + raise ValueError( + temp_list, " ports must have matching ip addresses!") print(port_list) print(ip_list) @@ -155,7 +200,8 @@ def main(): ip_list=ip_list, debug=args.debug) create_qvlan.build() - print('Created %s QVLAN stations' % num_ports) + print('Created %s QVLAN stations' % args.num_ports) + if __name__ == "__main__": main() diff --git a/py-scripts/create_station.py b/py-scripts/create_station.py index 55b1da06..78feaa9b 100755 --- a/py-scripts/create_station.py +++ b/py-scripts/create_station.py @@ -12,7 +12,7 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - + sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") @@ -74,23 +74,31 @@ class CreateStation(Realm): def build(self): # Build stations - self.station_profile.use_security(self.security, self.ssid, self.password) + self.station_profile.use_security( + self.security, self.ssid, self.password) self.station_profile.set_number_template(self.number_template) print("Creating stations") - self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) - self.station_profile.set_command_param("set_port", "report_timer", 1500) + self.station_profile.set_command_flag( + "add_sta", "create_admin_down", 1) + self.station_profile.set_command_param( + "set_port", "report_timer", 1500) self.station_profile.set_command_flag("set_port", "rpt_timer", 1) if self.set_txo_data is not None: - self.station_profile.set_wifi_txo(txo_ena=self.set_txo_data["txo_enable"], - tx_power=self.set_txo_data["txpower"], - pream=self.set_txo_data["pream"], - mcs=self.set_txo_data["mcs"], - nss=self.set_txo_data["nss"], - bw=self.set_txo_data["bw"], - retries=self.set_txo_data["retries"], - sgi=self.set_txo_data["sgi"], ) - self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug) + self.station_profile.set_wifi_txo( + txo_ena=self.set_txo_data["txo_enable"], + tx_power=self.set_txo_data["txpower"], + pream=self.set_txo_data["pream"], + mcs=self.set_txo_data["mcs"], + nss=self.set_txo_data["nss"], + bw=self.set_txo_data["bw"], + retries=self.set_txo_data["retries"], + sgi=self.set_txo_data["sgi"], + ) + self.station_profile.create( + radio=self.radio, + sta_names_=self.sta_list, + debug=self.debug) if self.up: self.station_profile.admin_up() @@ -98,7 +106,7 @@ class CreateStation(Realm): def main(): - parser = LFCliBase.create_basic_argparse( # see create_basic_argparse in ../py-json/LANforge/lfcli_base.py + parser = LFCliBase.create_basic_argparse( # see create_basic_argparse in ../py-json/LANforge/lfcli_base.py prog='create_station.py', formatter_class=argparse.RawTextHelpFormatter, epilog='''\ @@ -119,21 +127,32 @@ def main(): --debug ''') required = parser.add_argument_group('required arguments') - required.add_argument('--start_id', help='--start_id default 0', default=0) + required.add_argument( + '--start_id', + help='--start_id default 0', + default=0) optional = parser.add_argument_group('Optional arguments') - optional.add_argument('--mode', help='Mode for your station (as a number)',default=0) - optional.add_argument('--station_flag', help='station flags to add', required=False, default=None, action='append') + optional.add_argument( + '--mode', + help='Mode for your station (as a number)', + default=0) + optional.add_argument( + '--station_flag', + help='station flags to add', + required=False, + default=None, + action='append') args = parser.parse_args() # if args.debug: # pprint.pprint(args) # time.sleep(5) - if (args.radio is None): + if args.radio is None: raise ValueError("--radio required") start_id = 0 - if (args.start_id != 0): + if args.start_id != 0: start_id = int(args.start_id) num_sta = 2 @@ -148,16 +167,6 @@ def main(): radio=args.radio) print("station_list {}".format(station_list)) - set_txo_data={ - "txo_enable": 1, - "txpower": 255, - "pream": 0, - "mcs": 0, - "nss": 0, - "bw": 3, - "retries": 1, - "sgi": 0 - } create_station = CreateStation(_host=args.mgr, _port=args.mgr_port, @@ -175,5 +184,6 @@ def main(): create_station.build() print('Created %s stations' % num_sta) + if __name__ == "__main__": main() diff --git a/py-scripts/create_station_from_df.py b/py-scripts/create_station_from_df.py index 29189dbd..04741ecf 100755 --- a/py-scripts/create_station_from_df.py +++ b/py-scripts/create_station_from_df.py @@ -13,7 +13,6 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") @@ -62,7 +61,6 @@ class CreateStation(Realm): pprint.pprint(self.sta_list) print("---- ~Station List ----- ----- ----- ----- ----- ----- \n") - def build(self): # Build stations self.station_profile.use_security(self.security, self.ssid, self.password) @@ -80,8 +78,6 @@ class CreateStation(Realm): def main(): - required=[] - required.append({'name':'--df','help':'Which file you want to build stations off of?'}) parser = LFCliBase.create_basic_argparse( prog='create_station_from_df.py', formatter_class=argparse.RawTextHelpFormatter, @@ -99,29 +95,29 @@ def main(): --ssid netgear --passwd BLANK --debug - ''', - more_required=required) - + ''') + required = parser.add_argument_group('required arguments') + required.add_argument('df', help='Which file do you want to build stations off of?', required=True) args = parser.parse_args() - df=pd.read_csv(args.df) - unique=df[['radio','ssid','passwd','security']].drop_duplicates().reset_index(drop=True) + df = pd.read_csv(args.df) + unique = df[['radio', 'ssid', 'passwd', 'security']].drop_duplicates().reset_index(drop=True) for item in unique.index: - uniquedf=unique.iloc[item] - df1=df.merge(pd.DataFrame(uniquedf).transpose(),on=['radio','ssid','passwd','security']) - try: - radio=uniquedf['radio'] - except: - radio=args.radio - station_list=df1['station'] - try: - ssid=uniquedf['ssid'] - passwd=uniquedf['passwd'] - security=uniquedf['security'] - except: - ssid=args.ssid - passwd=args.passwd - security=args.security + uniquedf = unique.iloc[item] + df1 = df.merge(pd.DataFrame(uniquedf).transpose(), on=['radio', 'ssid', 'passwd', 'security']) + if uniquedf['radio']: + radio = uniquedf['radio'] + else: + radio = args.radio + station_list = df1['station'] + if uniquedf['ssid']: + ssid = uniquedf['ssid'] + passwd = uniquedf['passwd'] + security = uniquedf['security'] + else: + ssid = args.ssid + passwd = args.passwd + security = args.security create_station = CreateStation(_host=args.mgr, _port=args.mgr_port, _ssid=ssid, @@ -135,5 +131,6 @@ def main(): create_station.build() print('Created %s stations' % len(unique.index)) + if __name__ == "__main__": main() diff --git a/py-scripts/create_vap.py b/py-scripts/create_vap.py index d627998b..3425449e 100755 --- a/py-scripts/create_vap.py +++ b/py-scripts/create_vap.py @@ -12,7 +12,7 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - + sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") @@ -55,7 +55,10 @@ class CreateVAP(Realm): self.vap_list = _vap_list self.resource = _resource if _vap_flags is None: - self.vap_flags = ["wpa2_enable", "80211u_enable", "create_admin_down"] + self.vap_flags = [ + "wpa2_enable", + "80211u_enable", + "create_admin_down"] else: self.vap_flags = _vap_flags self.mode = _mode @@ -74,8 +77,10 @@ class CreateVAP(Realm): self.vap_profile.ssid_pass = self.password self.vap_profile.dhcp = self.dhcp self.vap_profile.mode = self.mode - self.vap_profile.desired_add_vap_flags = self.vap_flags + ["wpa2_enable", "80211u_enable", "create_admin_down"] - self.vap_profile.desired_add_vap_flags_mask = self.vap_flags + ["wpa2_enable", "80211u_enable", "create_admin_down"] + self.vap_profile.desired_add_vap_flags = self.vap_flags + \ + ["wpa2_enable", "80211u_enable", "create_admin_down"] + self.vap_profile.desired_add_vap_flags_mask = self.vap_flags + \ + ["wpa2_enable", "80211u_enable", "create_admin_down"] if self.debug: print("----- VAP List ----- ----- ----- ----- ----- ----- \n") pprint.pprint(self.vap_list) @@ -83,19 +88,19 @@ class CreateVAP(Realm): def build(self): # Build VAPs - self.vap_profile.use_security(self.security, self.ssid, passwd=self.password) + self.vap_profile.use_security( + self.security, self.ssid, passwd=self.password) print("Creating VAPs") - self.vap_profile.create(resource = self.resource, - radio = self.radio, - channel = self.channel, - country=self.country_code, - up_ = True, - debug = False, + self.vap_profile.create(resource=self.resource, + radio=self.radio, + channel=self.channel, + up_=True, + debug=False, use_ht40=True, use_ht80=True, use_ht160=False, - suppress_related_commands_ = True, + suppress_related_commands_=True, use_radius=False, hs20_enable=False, bridge=self.bridge) @@ -125,57 +130,73 @@ Command example: ''') optional = parser.add_argument_group('optional arguments') - optional.add_argument('--num_vaps', help='Number of VAPs to Create', required=False, default=1) - optional.add_argument('--vap_flag', help='VAP flags to add', required=False, default=None, action='append') - optional.add_argument('--bridge', help='Create a bridge connecting the VAP to a port', required=False, default=False) - optional.add_argument('--mac', help='Custom mac address', default="xx:xx:xx:xx:*:xx") + optional.add_argument( + '--num_vaps', + help='Number of VAPs to Create', + required=False, + default=1) + optional.add_argument( + '--vap_flag', + help='VAP flags to add', + required=False, + default=None, + action='append') + optional.add_argument( + '--bridge', + help='Create a bridge connecting the VAP to a port', + required=False, + default=False) + optional.add_argument( + '--mac', + help='Custom mac address', + default="xx:xx:xx:xx:*:xx") optional.add_argument('--mode', default='AUTO') optional.add_argument('--channel', default=36) optional.add_argument('--country_code', default=0) optional.add_argument('--nss', default=False) optional.add_argument('--resource', default=1) optional.add_argument('--start_id', default=0) - optional.add_argument('--vap_name',default=None) + optional.add_argument('--vap_name', default=None) args = parser.parse_args() - #if args.debug: + # if args.debug: # pprint.pprint(args) # time.sleep(5) - if (args.radio is None): - raise ValueError("--radio required") + if args.radio is None: + raise ValueError("--radio required") num_vap = int(args.num_vaps) vap_list = LFUtils.port_name_series(prefix="vap", - start_id=int(args.start_id), - end_id=num_vap-1, - padding_number=10000, - radio=args.radio) - #print(args.passwd) - #print(args.ssid) + start_id=int(args.start_id), + end_id=num_vap - 1, + padding_number=10000, + radio=args.radio) + # print(args.passwd) + # print(args.ssid) if args.vap_name is None: for vap in vap_list: create_vap = CreateVAP(_host=args.mgr, - _port=args.mgr_port, - _ssid=args.ssid, - _password=args.passwd, - _security=args.security, + _port=args.mgr_port, + _ssid=args.ssid, + _password=args.passwd, + _security=args.security, _mode=args.mode, - _vap_list=vap, + _vap_list=vap, _resource=args.resource, _vap_flags=args.vap_flag, - _radio=args.radio, + _radio=args.radio, _channel=args.channel, _country_code=args.country_code, _nss=args.nss, - _proxy_str=args.proxy, + _proxy_str=args.proxy, _bridge=args.bridge, - _debug_on=args.debug) + _debug_on=args.debug) print('Creating VAP') create_vap.build() else: - vap_name = "vap"+args.vap_name + vap_name = "vap" + args.vap_name create_vap = CreateVAP(_host=args.mgr, _port=args.mgr_port, _ssid=args.ssid, @@ -196,5 +217,6 @@ Command example: create_vap.build() + if __name__ == "__main__": main() diff --git a/py-scripts/create_vr.py b/py-scripts/create_vr.py index 3d9f2320..9e111eb6 100755 --- a/py-scripts/create_vr.py +++ b/py-scripts/create_vr.py @@ -12,7 +12,7 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - + sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") @@ -50,7 +50,8 @@ class CreateVR(Realm): self.vr_profile = self.new_vr_profile() def clean(self): - if (self.vr_name is None) or (self.vr_profile.vr_eid is None) and (self.vr_profile.vr_eid) == "": + if (self.vr_name is None) or (self.vr_profile.vr_eid is None) and ( + self.vr_profile.vr_eid) == "": print("No vr_eid to clean") return self.rm_port("1.1.rd90a", debug_=self.debug) @@ -59,13 +60,13 @@ class CreateVR(Realm): debug_=self.debug) if (self.vr_profile.vr_eid is not None) \ - and (self.vr_profile.vr_eid[1] is not None) \ - and (self.vr_profile.vr_eid[2] is not None): + and (self.vr_profile.vr_eid[1] is not None) \ + and (self.vr_profile.vr_eid[2] is not None): self.vr_profile.cleanup(debug=self.debug) if (self.vr_name is not None) \ - and (self.vr_name[1] is not None) \ - and (self.vr_name[2] is not None): + and (self.vr_name[1] is not None) \ + and (self.vr_name[2] is not None): data = { "shelf": 1, "resource": self.vr_name[1], @@ -84,9 +85,9 @@ class CreateVR(Realm): "cx_name": "all" }, debug_=self.debug) - def build(self): - self.vr_profile.apply_netsmith(self.vr_name[1], delay=5, debug=self.debug) + self.vr_profile.apply_netsmith( + self.vr_name[1], delay=5, debug=self.debug) self.json_post("/cli-json/add_rdd", { "shelf": 1, "resource": self.vr_name[1], @@ -101,10 +102,17 @@ class CreateVR(Realm): "peer_ifname": "rd90a", "report_timer": "3000" }) - self.wait_until_ports_appear(sta_list=["1.1.rd90a", "1.1.rd90b"], debug_=self.debug) - self.vr_profile.vrcx_list(resource=self.vr_name[1], do_sync=True) # do_sync + self.wait_until_ports_appear( + sta_list=[ + "1.1.rd90a", + "1.1.rd90b"], + debug_=self.debug) + self.vr_profile.vrcx_list( + resource=self.vr_name[1], + do_sync=True) # do_sync self.vr_profile.create(vr_name=self.vr_name, debug=self.debug) - self.vr_profile.sync_netsmith(resource=self.vr_name[1], debug=self.debug) + self.vr_profile.sync_netsmith( + resource=self.vr_name[1], debug=self.debug) self._pass("created router") def start(self): @@ -113,25 +121,39 @@ class CreateVR(Realm): :return: void """ # move rd90a into router - self.vr_profile.refresh_netsmith(resource=self.vr_name[1], debug=self.debug) + self.vr_profile.refresh_netsmith( + resource=self.vr_name[1], debug=self.debug) if self.debug: pprint(("vr_eid", self.vr_name)) - self.vr_profile.wait_until_vrcx_appear(resource=self.vr_name[1], name_list=["rd90a", "rd90b"]) - self.vr_profile.add_vrcx(vr_eid=self.vr_name, connection_name_list="rd90a", debug=True) + self.vr_profile.wait_until_vrcx_appear( + resource=self.vr_name[1], name_list=[ + "rd90a", "rd90b"]) + self.vr_profile.add_vrcx( + vr_eid=self.vr_name, + connection_name_list="rd90a", + debug=True) - self.vr_profile.refresh_netsmith(resource=self.vr_name[1], debug=self.debug) + self.vr_profile.refresh_netsmith( + resource=self.vr_name[1], debug=self.debug) # test to make sure that vrcx is inside vr we expect self.vr_profile.vrcx_list(resource=self.vr_name[1], do_sync=True) - vr_list = self.vr_profile.router_list(resource=self.vr_name[1], do_refresh=True) - router = self.vr_profile.find_cached_router(resource=self.vr_name[1], router_name=self.vr_name[2]) + vr_list = self.vr_profile.router_list( + resource=self.vr_name[1], do_refresh=True) + router = self.vr_profile.find_cached_router( + resource=self.vr_name[1], router_name=self.vr_name[2]) pprint(("cached router 120: ", router)) router_eid = LFUtils.name_to_eid(router["eid"]) pprint(("router eid 122: ", router_eid)) - full_router = self.json_get("/vr/1/%s/%s/%s" %(router_eid[0], router_eid[1], self.vr_name[2]), debug_=True) + full_router = self.json_get( + "/vr/1/%s/%s/%s" % + (router_eid[0], + router_eid[1], + self.vr_name[2]), + debug_=True) pprint(("full router: ", full_router)) time.sleep(5) if router is None: - self._fail("Unable to find router after vrcx move "+self.vr_name) + self._fail("Unable to find router after vrcx move " + self.vr_name) self.exit_fail() def stop(self): @@ -146,8 +168,8 @@ def main(): -------------------- Command example: {f} --vr_name 1.vr0 --ports 1.br0,1.rdd0a --services 1.br0=dhcp,nat --services 1.vr0=radvd -{f} --vr_name 2.vr0 --ports 2.br0,2.vap2 --services - +{f} --vr_name 2.vr0 --ports 2.br0,2.vap2 --services + --debug """.format(f=__file__)) required = parser.add_argument_group('required arguments') @@ -156,8 +178,11 @@ Command example: optional = parser.add_argument_group('optional arguments') - optional.add_argument('--ports', default=None, required=False, - help='Comma separated list of ports to add to virtual router') + optional.add_argument( + '--ports', + default=None, + required=False, + help='Comma separated list of ports to add to virtual router') optional.add_argument('--services', default=None, required=False, help='Add router services to a port, "br0=nat,dhcp"') @@ -175,10 +200,11 @@ Command example: create_vr.build() create_vr.start() create_vr.monitor() - #create_vr.stop() - #create_vr.clean() + # create_vr.stop() + # create_vr.clean() print('Created Virtual Router') + if __name__ == "__main__": main() diff --git a/py-scripts/create_wanlink.py b/py-scripts/create_wanlink.py deleted file mode 100755 index 40c20e3e..00000000 --- a/py-scripts/create_wanlink.py +++ /dev/null @@ -1,314 +0,0 @@ -#!/usr/bin/python3 -""" - - Create and modify WAN Links Using LANforge JSON AP : http://www.candelatech.com/cookbook.php?vol=cli&book=JSON:+Managing+WANlinks+using+JSON+and+Python - Written by Candela Technologies Inc. - Updated by: Erin Grimes - -""" -import sys - -if sys.version_info[0] != 3: - print("This script requires Python 3") - exit(1) - - - - -from time import sleep -import urllib -import pprint - -sys.path.append("../py-json") -from LANforge import LFRequest -from LANforge import LFUtils -from LANforge.lfcli_base import LFCliBase - -j_printer = pprint.PrettyPrinter(indent=2) -# todo: this needs to change -resource_id = 1 - - -def main(): - parser = LFCliBase.create_basic_argparse() - args = parser.parse_args() - base_url = 'http://%s:%s' % (args.mgr, args.mgr_port) - print(base_url) - json_post = "" - json_response = "" - num_wanlinks = -1 - - # force a refresh on the ports and wanlinks - lf_r = LFRequest.LFRequest(base_url+"/cli-json/nc_show_ports", debug_=True) - lf_r.addPostData({ - "shelf": 1, - "resource": 1, - "port": "all", - }) - json_response = lf_r.jsonPost(debug=True) - - lf_r = LFRequest.LFRequest(base_url+"/cli-json/nc_show_endpoints", debug_=True) - lf_r.addPostData({ - "endpoint": "all" - }) - json_response = lf_r.jsonPost(debug=True) - - sleep(1) - - # see if there are old wanlinks to remove - lf_r = LFRequest.LFRequest(base_url+"/wl_ep/list", debug_=True) - json_reponse = lf_r.get_as_json() - - endpA = args['name']+"-A" - endpB = args['name']+"-B" - - # count the number of wanlink endpoints - if "endpoint" in json_response: - endpoint_map = LFUtils.list_to_alias_map(json_list=json_reponse, from_element="endpoint") - if endpA in endpoint_map: - num_wanlinks += 1 - if endpB in endpoint_map: - num_wanlinks += 1 - - # remove old wanlinks - if (num_wanlinks > 0): - print("Removing old wanlinks...") - lf_r = LFRequest.LFRequest(base_url+"/cli-json/rm_cx", debug_=True) - lf_r.addPostData({ - 'test_mgr': 'all', - 'cx_name': args['name'] - }) - lf_r.jsonPost() - - lf_r = LFRequest.LFRequest(base_url+"/cli-json/rm_endp", debug_=True) - lf_r.addPostData({ - 'endp_name': endpA - }) - lf_r.jsonPost() - - lf_r = LFRequest.LFRequest(base_url+"/cli-json/rm_endp", debug_=True) - lf_r.addPostData({ - 'endp_name': endpB - }) - lf_r.jsonPost() - sleep(1) - - # check to see if we have ports - lf_r = LFRequest.LFRequest(base_url+"/ports/1/1/list", debug_=True) - port_response = lf_r.getAsJson() - - if "interfaces" not in port_response: - print("No interfaces in port_response!") - pprint.pprint(port_response) - exit(1) - - if "interfaces" in port_response: - port_map = LFUtils.list_to_alias_map(json_list=port_response, from_element="interfaces") - ports_created = 0 - if args["port_A"] not in port_map: - lf_r = LFRequest.LFRequest(base_url+"/cli-json/add_rdd", debug_=True) - lf_r.addPostData({ - "shelf": 1, - "resource": 1, - "port": args["port_A"], - "peer_ifname": args["port_A"]+"b", - }) - json_reponse = lf_r.jsonPost(debug=True) - if not json_response: - print("could not create port "+args["port_A"]) - exit(1) - sleep(0.1) - ports_created += 1 - if args["port_B"] not in port_map: - lf_r.addPostData({ - "shelf": 1, - "resource": 1, - "port": args["port_B"], - "peer_ifname": args["port_B"]+"b", - }) - json_reponse = lf_r.jsonPost(debug=True) - if not json_response: - print("could not create port " + args["port_B"]) - exit(1) - ports_created += 1 - sleep(0.1) - if ports_created > 0: - LFUtils.wait_until_ports_appear(base_url=base_url, - port_list=(args["port_A"], args["port_B"]), - debug=True) - print("Created {} ports".format(ports_created)) - - # create wanlink endpoint A - print("Adding WL Endpoints...", end='') - lf_r = LFRequest.LFRequest(base_url+"/cli-json/add_wl_endp", debug_=True) - lf_r.addPostData({ - 'alias': endpA, - 'shelf': 1, - 'resource': '1', - 'port': args['port_A'], - 'latency': args['latency_A'], - 'max_rate': args['rate_A'], - }) - json_response = lf_r.jsonPost(debug=True) - if not json_response: - print("Unable to create "+endpA) - else: - print("A, ", end='') - # create wanlink endpoint B - lf_r = LFRequest.LFRequest(base_url+"/cli-json/add_wl_endp", debug_=True) - lf_r.addPostData({ - 'alias': endpB, - 'shelf': 1, - 'resource': '1', - 'port': args['port_B'], - 'latency': args['latency_B'], - 'max_rate': args['rate_B'], - }) - json_response = lf_r.jsonPost() - if not json_response: - print("Unable to create "+endpB) - else: - print("B") - sleep(1) - - # create cx - lf_r = LFRequest.LFRequest(base_url+"/cli-json/add_cx", debug_=True) - lf_r.addPostData({ - 'alias': args['name'], - 'test_mgr': 'default_tm', - 'tx_endp': endpA, - 'rx_endp': endpB - }) - lf_r.jsonPost(debug=True) - sleep(0.5) - - # modify wanlink endpoint A - lf_r = LFRequest.LFRequest(base_url+"/cli-json/set_wanlink_info", debug_=True) - lf_r.addPostData({ - 'name': endpA, - 'max_jitter': args['jitter_A'], - 'jitter_freq': args['jitter_freq_A'], - 'drop_freq': args['drop_A'] - }) - lf_r.jsonPost(debug=True) - - # modify wanlink endpoint B - lf_r = LFRequest.LFRequest(base_url+"/cli-json/set_wanlink_info", debug_=True) - lf_r.addPostData({ - 'name': endpB, - 'max_jitter': args['jitter_B'], - 'jitter_freq': args['jitter_freq_B'], - 'drop_freq': args['drop_B'] - }) - lf_r.jsonPost() - - # start wanlink once we see it - seen = 0 - print("Looking for {} and {}: ".format(endpA, endpB), end='') - while (seen < 2): - sleep(1) - lf_r = LFRequest.LFRequest(base_url+"/wl_ep/list?fields=name,eid") - try: - json_response = lf_r.getAsJson() - if json_response is None: - print(".", end="") - continue - LFUtils.debug_printer.pprint(json_response) - if "endpoint" not in json_response: - print("-", end="") - continue - - endpoint_map = LFUtils.list_to_alias_map(json_list=json_response["endpoint"], - from_element="endpoint") - if endpA in endpoint_map: - seen += 1 - print("+", end="") - if endpB in endpoint_map: - seen += 1 - print("+", end="") - - except urllib.error.HTTPError as error: - print("Error code {}".format(error.code)) - continue - print("") - print("Starting wanlink:") - # print("the latency is {laten}".format(laten=latency)) - lf_r = LFRequest.LFRequest(base_url+"/cli-json/set_cx_state") - lf_r.addPostData({ - 'test_mgr': 'all', - 'cx_name': args['name'], - 'cx_state': 'RUNNING' - }) - lf_r.jsonPost() - - running = 0 - while (running < 1): - sleep(1) - lf_r = LFRequest.LFRequest(base_url+"/wl/"+args['name']+"?fields=name,state,_links") - try: - json_response = lf_r.getAsJson() - if (json_response is None): - continue - for key, value in json_response.items(): - if (isinstance(value, dict)): - if ("_links" in value): - if (value["name"] == args['name']): - if (value["state"].startswith("Run")): - LFUtils.debug_printer.pprint(json_response) - running = 1 - - except urllib.error.HTTPError as error: - print("Error code {}".format(error.code)) - continue - - print("Wanlink is running") - - # stop wanlink - lf_r = LFRequest.LFRequest(base_url+"/cli-json/set_cx_state") - lf_r.addPostData({ - 'test_mgr': 'all', - 'cx_name': args['name'], - 'cx_state': 'STOPPED' - }) - lf_r.jsonPost() - running = 1 - while (running > 0): - sleep(1) - lf_r = LFRequest.LFRequest(base_url+"/wl/"+args['name']+"?fields=name,eid,state,_links") - LFUtils.debug_printer.pprint(json_response) - try: - json_response = lf_r.getAsJson() - if (json_response is None): - continue - for key, value in json_response.items(): - if (isinstance(value, dict)): - if ("_links" in value): - if (value["name"] == args['name']): - if (value["state"].startswith("Stop")): - LFUtils.debug_printer.pprint(json_response) - running = 0 - - except urllib.error.HTTPError as error: - print("Error code {}".format(error.code)) - continue - - print("Wanlink is stopped.") - - # print("Wanlink info:") - # lf_r = LFRequest.LFRequest(base_url+"/wl/wl_eg1") - # json_response = lf_r.getAsJson() - # LFUtils.debug_printer.pprint(json_response) - - # lf_r = LFRequest.LFRequest(base_url+"/wl_ep/wl_eg1-A") - # json_response = lf_r.getAsJson() - # LFUtils.debug_printer.pprint(json_response) - - # lf_r = LFRequest.LFRequest(base_url+"/wl_ep/wl_eg1-B") - # json_response = lf_r.getAsJson() - # LFUtils.debug_printer.pprint(json_response) - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -if __name__ == '__main__': - main() diff --git a/py-scripts/csv_convert.py b/py-scripts/csv_convert.py index a0ac5255..fc184756 100755 --- a/py-scripts/csv_convert.py +++ b/py-scripts/csv_convert.py @@ -23,14 +23,12 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) -class CSVParcer(): - def __init__(self,csv_infile=None,csv_outfile=None): +class CSVParcer: + def __init__(self, csv_infile=None, csv_outfile=None): - idx = 0 i_atten = -1 i_rotation = -1 i_rxbps = -1 @@ -46,34 +44,33 @@ class CSVParcer(): x = line.split(",") cni = 0 for cn in x: - if (cn == "Attenuation [dB]"): + if cn == "Attenuation [dB]": i_atten = cni - if (cn == "Position [Deg]"): + if cn == "Position [Deg]": i_rotation = cni - if (cn == "Throughput [Mbps]"): + if cn == "Throughput [Mbps]": i_rxbps = cni - if (cn == "Beacon RSSI [dBm]"): + if cn == "Beacon RSSI [dBm]": i_beacon_rssi = cni - if (cn == "Data RSSI [dBm]"): + if cn == "Data RSSI [dBm]": i_data_rssi = cni cni += 1 # Write out out header for the new file. - fpo.write("Test Run,Position [Deg],Attenuation 1 [dB],Pal Stats Endpoint 1 Control Rssi [dBm],Pal Stats Endpoint 1 Data Rssi [dBm]\n") + fpo.write( + "Test Run,Position [Deg],Attenuation 1 [dB],Pal Stats Endpoint 1 Control Rssi [dBm],Pal Stats Endpoint 1 Data Rssi [dBm]\n") # Read rest of the input lines, processing one at a time. Covert the columns as # needed, and write out new data to the output file. line = fp.readline() - bottom_half="Step Index,Position [Deg],Attenuation [dB],Traffic Pair 1 Throughput [Mbps]\n" + bottom_half = "Step Index,Position [Deg],Attenuation [dB],Traffic Pair 1 Throughput [Mbps]\n" - test_run="1" + test_run = "1" step_i = 0 while line: x = line.split(",") - #print(x) - #print([test_run, x[i_rotation], x[i_atten], x[i_beacon_rssi], x[i_data_rssi]]) fpo.write("%s,%s,%s,%s,%s" % (test_run, x[i_rotation], x[i_atten], x[i_beacon_rssi], x[i_data_rssi])) bottom_half += ("%s,%s,%s,%s\n" % (step_i, x[i_rotation], x[i_atten], x[i_rxbps])) line = fp.readline() @@ -83,37 +80,36 @@ class CSVParcer(): fpo.write("\n\n# RvRvO Data\n\n") fpo.write(bottom_half) -def main(): - #debug_on = False +def main(): parser = argparse.ArgumentParser( prog='csv_convert.py', formatter_class=argparse.RawTextHelpFormatter, epilog='''\ Useful Information: ''', - + description=''' csv_convert.py: converts the candela brief csv into the data for specific customer, ''') - # for testing parser.add_argument('-i','--infile', help="input file of csv data", default='text-csv-0-candela.csv') - parser.add_argument('-i','--infile', help="input file of csv data", required=True) - parser.add_argument('-o','--outfile', help="output file in .csv format", default='outfile.csv') - + parser.add_argument('-i', '--infile', help="input file of csv data", required=True) + parser.add_argument('-o', '--outfile', help="output file in .csv format", default='outfile.csv') args = parser.parse_args() csv_outfile_name = None + csv_infile_name = None if args.infile: csv_infile_name = args.infile if args.outfile: csv_outfile_name = args.outfile - print("infile: %s outfile: %s"%(csv_infile_name, csv_outfile_name)) + print("infile: %s outfile: %s" % (csv_infile_name, csv_outfile_name)) CSVParcer(csv_infile_name, csv_outfile_name) + if __name__ == "__main__": main() diff --git a/py-scripts/cv_examples/ap_auto_example.bash b/py-scripts/cv_examples/ap_auto_example.bash new file mode 100644 index 00000000..e69de29b diff --git a/py-scripts/cv_manager.py b/py-scripts/cv_manager.py index 57bf23cd..5476c375 100755 --- a/py-scripts/cv_manager.py +++ b/py-scripts/cv_manager.py @@ -8,7 +8,6 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) cv_test_manager = importlib.import_module("py-json.cv_test_manager") @@ -29,6 +28,7 @@ class CVManager(cv_test): self.apply_cv_scenario(self.scenario) self.build_cv_scenario() + def main(): parser = argparse.ArgumentParser( prog='cv_manager.py', @@ -45,5 +45,6 @@ def main(): lfclient_host=args.mgr) manager.apply_and_build_scenario() -if __name__ =="__main__": + +if __name__ == "__main__": main() diff --git a/py-scripts/cv_to_grafana.py b/py-scripts/cv_to_grafana.py index 8be615e3..b05be51d 100755 --- a/py-scripts/cv_to_grafana.py +++ b/py-scripts/cv_to_grafana.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -''' +""" This script loads and builds a Chamber View Scenario, runs WiFi Capacity Test, runs Dataplane Test, and posts the results to Influx. There are optional arguments which will create a Grafana dashboard which will import the data posted to @@ -59,7 +59,7 @@ AP Auto test has the following argument: DUT syntax is somewhat tricky: DUT-name SSID BSID (bssid-idx), example: linksys-8450 Default-SSID-5gl c4:41:1e:f5:3f:25 (2) * radio2: Specify 2.4Ghz radio. May be specified multiple times. * radio5: Specify 5Ghz radio. May be specified multiple times. -''' +""" import sys import os import importlib @@ -70,20 +70,24 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lf_wifi_capacity_test = importlib.import_module("py-scripts.lf_wifi_capacity_test") WiFiCapacityTest = lf_wifi_capacity_test.WiFiCapacityTest -cv_test_manager = importlib.import_module("py-scripts.cv_test_manager") +cv_test_manager = importlib.import_module("py-json.cv_test_manager") create_chamberview = importlib.import_module("py-scripts.create_chamberview") CreateChamberview = create_chamberview.CreateChamberview -DUT = create_chamberview.DUT +create_chamberview_dut = importlib.import_module("py-scripts.create_chamberview_dut") +DUT = create_chamberview_dut.DUT lf_dataplane_test = importlib.import_module("py-scripts.lf_dataplane_test") DataplaneTest = lf_dataplane_test.DataplaneTest grafana_profile = importlib.import_module("py-scripts.grafana_profile") UseGrafana = grafana_profile.UseGrafana lf_ap_auto_test = importlib.import_module("py-scripts.lf_ap_auto_test") +ApAutoTest = lf_ap_auto_test.ApAutoTest + +cv_add_base_parser = cv_test_manager.cv_add_base_parser +cv_base_adjust_parser = cv_add_base_parser.cv_base_adjust_parser def main(): @@ -169,7 +173,7 @@ def main(): parser.add_argument('--grafana_port', help='Grafana port if different from 3000', default=3000) parser.add_argument('--grafana_host', help='Grafana host', default='localhost') - #Flags for AP-Auto Test config + # Flags for AP-Auto Test config parser.add_argument("--max_stations_2", type=int, default=-1, help="Specify maximum 2.4Ghz stations") @@ -187,14 +191,15 @@ def main(): parser.add_argument("--radio5", action='append', nargs=1, default=[], help="Specify 5Ghz radio. May be specified multiple times.") - #Flags for Grafana + # Flags for Grafana parser.add_argument('--dashboard_title', help='Titles of dashboards', default=None, action='append') parser.add_argument('--scripts', help='Scripts to graph in Grafana', default=None, action='append') parser.add_argument('--title', help='title of your Grafana Dashboard', default=None) parser.add_argument('--testbed', help='Which testbed you want to query', default=None) - parser.add_argument('--graph_groups_file', help='File which determines how you want to filter your graphs on your dashboard', - default=None) + parser.add_argument('--graph_groups_file', + help='File which determines how you want to filter your graphs on your dashboard', + default=None) parser.add_argument('--kpi', help='KPI file(s) which you want to graph form', action='append', default=None) parser.add_argument('--datasource', help='Name of Influx database if different from InfluxDB', default='InfluxDB') parser.add_argument('--from_date', help='Date you want to start your Grafana dashboard from', default='now-1y') diff --git a/py-scripts/example_security_connection.py b/py-scripts/example_security_connection.py index 54fe1463..1fc8a90c 100755 --- a/py-scripts/example_security_connection.py +++ b/py-scripts/example_security_connection.py @@ -8,7 +8,7 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - + sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") @@ -19,7 +19,7 @@ Realm = realm.Realm class IPv4Test(LFCliBase): - def __init__(self, ssid, security, password, sta_list=None, ap=None, mode = 0, number_template="00000", host="localhost", port=8080,radio = "wiphy0",_debug_on=False, + def __init__(self, ssid, security, password, sta_list=None, ap=None, mode=0, number_template="00000", host="localhost", port=8080, radio="wiphy0", _debug_on=False, _exit_on_error=False, _exit_on_fail=False): super().__init__(host, port, _debug=_debug_on, _exit_on_fail=_exit_on_fail) @@ -35,43 +35,49 @@ class IPv4Test(LFCliBase): self.timeout = 120 self.number_template = number_template self.debug = _debug_on - self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port) + self.local_realm = realm.Realm( + lfclient_host=self.host, lfclient_port=self.port) self.station_profile = self.local_realm.new_station_profile() self.station_profile.lfclient_url = self.lfclient_url self.station_profile.ssid = self.ssid self.station_profile.ssid_pass = self.password - self.station_profile.mode =self.mode + self.station_profile.mode = self.mode self.station_profile.security = self.security self.station_profile.number_template_ = self.number_template self.station_profile.mode = mode if self.ap is not None: - self.station_profile.set_command_param("add_sta", "ap",self.ap) + self.station_profile.set_command_param("add_sta", "ap", self.ap) def build(self): # Build stations #print("We've gotten into the build stations function") - self.station_profile.use_security(self.security, self.ssid, self.password) + self.station_profile.use_security( + self.security, self.ssid, self.password) self.station_profile.set_number_template(self.number_template) print("Creating stations") - self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) - self.station_profile.set_command_param("set_port", "report_timer", 1500) + self.station_profile.set_command_flag( + "add_sta", "create_admin_down", 1) + self.station_profile.set_command_param( + "set_port", "report_timer", 1500) self.station_profile.set_command_flag("set_port", "rpt_timer", 1) - self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug) + self.station_profile.create( + radio=self.radio, sta_names_=self.sta_list, debug=self.debug) self.station_profile.admin_up() if self.local_realm.wait_for_ip(station_list=self.sta_list, debug=self.debug, timeout_sec=30): self._pass("Station build finished") self.exit_success() else: - self._fail("Stations not able to acquire IP. Please check network input.") + self._fail( + "Stations not able to acquire IP. Please check network input.") self.exit_fail() - def cleanup(self, sta_list): self.station_profile.cleanup(sta_list) LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=sta_list, debug=self.debug) + def main(): parser = LFCliBase.create_basic_argparse( @@ -97,18 +103,19 @@ def main(): --passwd admin123-wpa3 --debug ''') - required=None + required = None for agroup in parser._action_groups: if agroup.title == "required arguments": required = agroup - #if required is not None: + # if required is not None: optional = None for agroup in parser._action_groups: if agroup.title == "optional arguments": optional = agroup if optional is not None: - optional.add_argument('--mode',help=LFCliBase.Help_Mode) - optional.add_argument('--ap',help='Add BSSID of access point to connect to') + optional.add_argument('--mode', help=LFCliBase.Help_Mode) + optional.add_argument( + '--ap', help='Add BSSID of access point to connect to') args = parser.parse_args() num_sta = 2 @@ -117,18 +124,19 @@ def main(): num_sta = num_stations_converted station_list = LFUtils.portNameSeries(prefix_="sta", - start_id_=0, - end_id_=num_sta-1, - padding_number_=10000, - radio=args.radio) - ip_test = IPv4Test(host=args.mgr, port=args.mgr_port, - ssid=args.ssid, password=args.passwd, - radio=args.radio, mode= args.mode, - security=args.security, sta_list=station_list, - ap=args.ap) + start_id_=0, + end_id_=num_sta-1, + padding_number_=10000, + radio=args.radio) + ip_test = IPv4Test(host=args.mgr, port=args.mgr_port, + ssid=args.ssid, password=args.passwd, + radio=args.radio, mode=args.mode, + security=args.security, sta_list=station_list, + ap=args.ap) ip_test.cleanup(station_list) ip_test.timeout = 60 ip_test.build() + if __name__ == "__main__": main() diff --git a/py-scripts/influx.py b/py-scripts/influx_utils.py similarity index 100% rename from py-scripts/influx.py rename to py-scripts/influx_utils.py diff --git a/py-scripts/lf_ap_auto_test.py b/py-scripts/lf_ap_auto_test.py index 2b21d55e..410f5bac 100755 --- a/py-scripts/lf_ap_auto_test.py +++ b/py-scripts/lf_ap_auto_test.py @@ -172,13 +172,13 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) cv_test_manager = importlib.import_module("py-json.cv_test_manager") cvtest = cv_test_manager.cv_test cv_add_base_parser = cv_test_manager.cv_add_base_parser cv_base_adjust_parser = cv_test_manager.cv_base_adjust_parser +LFUtils = importlib.import_module("py-json.LANforge.LFUtils") class ApAutoTest(cvtest): @@ -188,10 +188,11 @@ class ApAutoTest(cvtest): lf_user="lanforge", lf_password="lanforge", ssh_port=22, - local_lf_report_dir="", + local_lf_report_dir=None, + lf_report_dir=None, instance_name="ap_auto_instance", config_name="ap_auto_config", - upstream="1.1.eth1", + upstream=None, pull_report=False, dut5_0="NA", dut2_0="NA", @@ -199,21 +200,33 @@ class ApAutoTest(cvtest): max_stations_2=100, max_stations_5=100, max_stations_dual=200, - radio2=[], - radio5=[], - enables=[], - disables=[], - raw_lines=[], + radio2=None, + radio5=None, + enables=None, + disables=None, + raw_lines=None, raw_lines_file="", - sets=[], + sets=None, graph_groups=None ): super().__init__(lfclient_host=lf_host, lfclient_port=lf_port) + if radio2 is None: + radio2 = [] + if radio5 is None: + radio5 = [] + if enables is None: + enables = [] + if disables is None: + disables = [] + if raw_lines is None: + raw_lines = [] + if sets is None: + sets = [] self.lf_host = lf_host self.lf_port = lf_port self.lf_user = lf_user - self.lf_password =lf_password + self.lf_password = lf_password self.instance_name = instance_name self.config_name = config_name self.upstream = upstream @@ -234,19 +247,19 @@ class ApAutoTest(cvtest): self.sets = sets self.ssh_port = ssh_port self.graph_groups = graph_groups + self.lf_report_dir = lf_report_dir self.local_lf_report_dir = local_lf_report_dir def setup(self): # Nothing to do at this time. return - def run(self): self.sync_cv() time.sleep(2) self.sync_cv() - blob_test = "%s-"%(self.test_name) + blob_test = "%s-" % self.test_name self.rm_text_blob(self.config_name, blob_test) # To delete old config with same name self.show_text_blob(None, None, False) @@ -256,19 +269,19 @@ class ApAutoTest(cvtest): ridx = 0 for r in self.radio2: - cfg_options.append("radio2-%i: %s"%(ridx, r[0])) + cfg_options.append("radio2-%i: %s" % (ridx, r[0])) ridx += 1 ridx = 0 for r in self.radio5: - cfg_options.append("radio5-%i: %s"%(ridx, r[0])) + cfg_options.append("radio5-%i: %s" % (ridx, r[0])) ridx += 1 self.apply_cfg_options(cfg_options, self.enables, self.disables, self.raw_lines, self.raw_lines_file) # Command line args take precedence. - if self.upstream != "": - cfg_options.append("upstream_port: " + self.upstream) + if self.upstream: + cfg_options.append("upstream-port: %s" % self.upstream) if self.dut5_0 != "": cfg_options.append("dut5-0: " + self.dut5_0) if self.dut2_0 != "": @@ -294,7 +307,6 @@ class ApAutoTest(cvtest): def main(): - parser = argparse.ArgumentParser( prog="lf_ap_auto_test.py", formatter_class=argparse.RawTextHelpFormatter, @@ -302,28 +314,28 @@ def main(): Open this file in an editor and read the top notes for more details. Example: - ./lf_ap_auto_test.py --mgr localhost --port 8080 --lf_user lanforge --lf_password lanforge \ - --instance_name ap-auto-instance --config_name test_con --upstream 1.1.eth2 \ - --dut5_0 'linksys-8450 Default-SSID-5gl c4:41:1e:f5:3f:25 (2)' \ - --dut2_0 'linksys-8450 Default-SSID-2g c4:41:1e:f5:3f:24 (1)' \ - --max_stations_2 100 --max_stations_5 100 --max_stations_dual 200 \ - --radio2 1.1.wiphy0 --radio2 1.1.wiphy2 \ - --radio5 1.1.wiphy1 --radio5 1.1.wiphy3 --radio5 1.1.wiphy4 \ - --radio5 1.1.wiphy5 --radio5 1.1.wiphy6 --radio5 1.1.wiphy7 \ - --set 'Basic Client Connectivity' 1 --set 'Multi Band Performance' 1 \ - --set 'Skip 2.4Ghz Tests' 1 --set 'Skip 5Ghz Tests' 1 \ - --set 'Throughput vs Pkt Size' 0 --set 'Capacity' 0 --set 'Stability' 0 --set 'Band-Steering' 0 \ - --set 'Multi-Station Throughput vs Pkt Size' 0 --set 'Long-Term' 0 \ - --test_rig Testbed-01 --test_tag ATH10K --pull_report \ - --influx_host c7-graphana --influx_port 8086 --influx_org Candela \ - --influx_token=-u_Wd-L8o992701QF0c5UmqEp7w7Z7YOMaWLxOMgmHfATJGnQbbmYyNxHBR9PgD6taM_tcxqJl6U8DjU1xINFQ== \ - --influx_bucket ben \ + ./lf_ap_auto_test.py --mgr localhost --port 8080 --lf_user lanforge --lf_password lanforge \\ + --instance_name ap-auto-instance --config_name test_con --upstream 1.1.eth2 \\ + --dut5_0 'linksys-8450 Default-SSID-5gl c4:41:1e:f5:3f:25 (2)' \\ + --dut2_0 'linksys-8450 Default-SSID-2g c4:41:1e:f5:3f:24 (1)' \\ + --max_stations_2 100 --max_stations_5 100 --max_stations_dual 200 \\ + --radio2 1.1.wiphy0 --radio2 1.1.wiphy2 \\ + --radio5 1.1.wiphy1 --radio5 1.1.wiphy3 --radio5 1.1.wiphy4 \\ + --radio5 1.1.wiphy5 --radio5 1.1.wiphy6 --radio5 1.1.wiphy7 \\ + --set 'Basic Client Connectivity' 1 --set 'Multi Band Performance' 1 \\ + --set 'Skip 2.4Ghz Tests' 1 --set 'Skip 5Ghz Tests' 1 \\ + --set 'Throughput vs Pkt Size' 0 --set 'Capacity' 0 --set 'Stability' 0 --set 'Band-Steering' 0 \\ + --set 'Multi-Station Throughput vs Pkt Size' 0 --set 'Long-Term' 0 \\ + --test_rig Testbed-01 --test_tag ATH10K --pull_report \\ + --influx_host c7-graphana --influx_port 8086 --influx_org Candela \\ + --influx_token=-u_Wd-L8o992701QF0c5UmqEp7w7Z7YOMaWLxOMgmHfATJGnQbbmYyNxHBR9PgD6taM_tcxqJl6U8DjU1xINFQ== \\ + --influx_bucket ben \\ --influx_tag testbed Ferndale-01 """ - ) + ) cv_add_base_parser(parser) # see cv_test_manager.py - parser.add_argument("-u", "--upstream", type=str, default="", + parser.add_argument("-u", "--upstream", type=str, default=None, help="Upstream port for wifi capacity test ex. 1.1.eth1") parser.add_argument("--max_stations_2", type=int, default=-1, @@ -341,39 +353,46 @@ def main(): help="Specify 2.4Ghz radio. May be specified multiple times.") parser.add_argument("--radio5", action='append', nargs=1, default=[], help="Specify 5Ghz radio. May be specified multiple times.") - parser.add_argument("--local_lf_report_dir", help="--local_lf_report_dir default '' put where dataplane script run from",default="") + parser.add_argument("--local_lf_report_dir", + help="--local_lf_report_dir default '' put where dataplane script run from", + default="") + parser.add_argument("--lf_report_dir", + help="--lf_report_dir default '' put where dataplane script run from", + default="") args = parser.parse_args() cv_base_adjust_parser(args) - CV_Test = ApAutoTest(lf_host = args.mgr, - lf_port = args.port, - lf_user = args.lf_user, - lf_password = args.lf_password, - instance_name = args.instance_name, - config_name = args.config_name, - upstream = args.upstream, - pull_report = args.pull_report, - local_lf_report_dir = args.local_lf_report_dir, - dut5_0 = args.dut5_0, - dut2_0 = args.dut2_0, - load_old_cfg = args.load_old_cfg, - max_stations_2 = args.max_stations_2, - max_stations_5 = args.max_stations_5, - max_stations_dual = args.max_stations_dual, - radio2 = args.radio2, - radio5 = args.radio5, - enables = args.enable, - disables = args.disable, - raw_lines = args.raw_line, - raw_lines_file = args.raw_lines_file, - sets = args.set + CV_Test = ApAutoTest(lf_host=args.mgr, + lf_port=args.port, + lf_user=args.lf_user, + lf_password=args.lf_password, + instance_name=args.instance_name, + config_name=args.config_name, + upstream=args.upstream, + pull_report=args.pull_report, + local_lf_report_dir=args.local_lf_report_dir, + lf_report_dir=args.lf_report_dir, + dut5_0=args.dut5_0, + dut2_0=args.dut2_0, + load_old_cfg=args.load_old_cfg, + max_stations_2=args.max_stations_2, + max_stations_5=args.max_stations_5, + max_stations_dual=args.max_stations_dual, + radio2=args.radio2, + radio5=args.radio5, + enables=args.enable, + disables=args.disable, + raw_lines=args.raw_line, + raw_lines_file=args.raw_lines_file, + sets=args.set ) CV_Test.setup() CV_Test.run() CV_Test.check_influx_kpi(args) + if __name__ == "__main__": main() diff --git a/py-scripts/lf_csv.py b/py-scripts/lf_csv.py old mode 100644 new mode 100755 index 01a90ad3..747b1017 --- a/py-scripts/lf_csv.py +++ b/py-scripts/lf_csv.py @@ -42,39 +42,9 @@ class lf_csv: print(csv_df) csv_df.to_csv(self.filename, index=False, encoding='utf-8', na_rep='NA', float_format='%.2f') -# this layout may need to change -''' -kpi.csv : specific file that is used for the database, dashboard and blog post -A blank entry is a valid entry in some cases. - - Date: date of run - test-rig : testbed that the tests are run on for example ct_us_001 - test-tag : test specific information to differenciate the test, LANforge radios used, security modes (wpa2 , open) - dut-hw-version : hardware version of the device under test - dut-sw-version : software version of the device under test - dut-model-num : model number / name of the device under test - test-priority : test-priority is arbitrary number, choosing under 95 means it goes down at bottom of blog report, and higher priority goes at top. - test-id : script or test name , AP Auto, wifi capacity, data plane, dfs - short-description : short description of the test - pass/fail : set blank for performance tests - numeric-score : this is the value for the y-axis (x-axis is a timestamp), numeric value of what was measured - test-details : what was measured in the numeric-score, e.g. bits per second, bytes per second, upload speed, minimum cx time (ms) - Units : units used for the numeric-scort - Graph-Group - For the dashboard the graph / panel to put the resutls in . Currently the dashboard is Grafana - -''' -class lf_kpi_csv: - def __init__(self, - _kpi_headers = ['Date','test-rig','test-tag','dut-hw-version','dut-sw-version','dut-model-num', - 'test-priority','test-id','short-description','pass/fail','numberic-score' - 'test details','Units','Graph-Group','Subtest-Pass','Subtest-Fail'], - _kpi_file='kpi.csv' #Currently this is the only file name accepted - ): - self.kpi_headers = _kpi_headers - self.kpi_rows = "" - self.kpi_filename = _kpi_file - - -if __name__ == "__main__": +def main(): test = lf_csv() test.generate_csv() + +if __name__ == "__main__": + main() diff --git a/py-scripts/lf_dataplane_test.py b/py-scripts/lf_dataplane_test.py index 88431acc..2362a8c3 100755 --- a/py-scripts/lf_dataplane_test.py +++ b/py-scripts/lf_dataplane_test.py @@ -9,7 +9,7 @@ Note: To Run this script gui should be opened with This script is used to automate running Dataplane tests. You may need to view a Dataplane test configured through the GUI to understand the options and how best to input data. - + ./lf_dataplane_test.py --mgr localhost --port 8080 --lf_user lanforge --lf_password lanforge \ --instance_name dataplane-instance --config_name test_con --upstream 1.1.eth2 \ --dut linksys-8450 --duration 15s --station 1.1.sta01500 \ @@ -39,7 +39,7 @@ port_sorting: 0 kpi_id: Dataplane Pkt-Size notes0: ec5211 in bridge mode, wpa2 auth. bg: 0xE0ECF8 -test_rig: +test_rig: show_scan: 1 auto_helper: 0 skip_2: 0 @@ -87,7 +87,7 @@ show_1m: 1 pause_iter: 0 outer_loop_atten: 0 show_realtime: 1 -operator: +operator: mconn: 1 mpkt: 1000 tos: 0 @@ -105,7 +105,6 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) cv_test_manager = importlib.import_module("py-json.cv_test_manager") @@ -132,17 +131,24 @@ class DataplaneTest(cv_test): duration="15s", station="1.1.sta01500", dut="NA", - enables=[], - disables=[], - raw_lines=[], + enables=None, + disables=None, + raw_lines=None, raw_lines_file="", - sets=[], + sets=None, graph_groups=None, - report_dir="", test_rig="" ): super().__init__(lfclient_host=lf_host, lfclient_port=lf_port) + if enables is None: + enables = [] + if disables is None: + disables = [] + if raw_lines is None: + raw_lines = [] + if sets is None: + sets = [] self.lf_host = lf_host self.lf_port = lf_port self.lf_user = lf_user @@ -164,7 +170,6 @@ class DataplaneTest(cv_test): self.raw_lines_file = raw_lines_file self.sets = sets self.graph_groups = graph_groups - self.report_dir = report_dir self.ssh_port = ssh_port self.local_lf_report_dir = local_lf_report_dir self.test_rig = test_rig @@ -180,14 +185,16 @@ class DataplaneTest(cv_test): blob_test = "dataplane-test-latest-" - self.rm_text_blob(self.config_name, blob_test) # To delete old config with same name + # To delete old config with same name + self.rm_text_blob(self.config_name, blob_test) self.show_text_blob(None, None, False) # Test related settings cfg_options = [] ### HERE### - self.apply_cfg_options(cfg_options, self.enables, self.disables, self.raw_lines, self.raw_lines_file) + self.apply_cfg_options(cfg_options, self.enables, + self.disables, self.raw_lines, self.raw_lines_file) # cmd line args take precedence and so come last in the cfg array. if self.upstream != "": @@ -215,7 +222,8 @@ class DataplaneTest(cv_test): self.pull_report, self.lf_host, self.lf_user, self.lf_password, cv_cmds, ssh_port=self.ssh_port, local_lf_report_dir=self.local_lf_report_dir, graph_groups_file=self.graph_groups) - self.rm_text_blob(self.config_name, blob_test) # To delete old config with same name + # To delete old config with same name + self.rm_text_blob(self.config_name, blob_test) def main(): @@ -226,7 +234,7 @@ def main(): IMPORTANT: Start lanforge with socket 3990 : ./lfclient.bash -cli-socket 3990 lfclient.bash is located in the LANforgeGUI_X.X.X directory - + On local or remote system: ./lfclient.bash -cli-socket 3990 -s LF_MGR On local system the -s LF_MGR will be local_host if not provided @@ -246,7 +254,7 @@ def main(): --influx_bucket ben \ --influx_tag testbed Ferndale-01 - + Example 2: ./lf_dataplane_test.py --json .json @@ -254,46 +262,47 @@ def main(): Sample .json between using eth1 and eth2 { - "mgr":"192.168.0.101", - "port":"8080", - "lf_user":"lanforge", - "lf_password":"lanforge", - "instance_name":"dataplane-instance", - "config_name":"test_con", - "upstream":"1.1.eth1", - "dut":"asus_5g", - "duration":"15s", - "station":"1.1.eth2", - "download_speed":"85%", - "upload_speed":"0", - "raw_line": ["pkts: Custom;60;MTU", "cust_pkt_sz: 88 1200", "directions: DUT Transmit", "traffic_types: UDP", "bandw_options: 20", "spatial_streams: 1"] + "mgr":"192.168.0.101", + "port":"8080", + "lf_user":"lanforge", + "lf_password":"lanforge", + "instance_name":"dataplane-instance", + "config_name":"test_con", + "upstream":"1.1.eth1", + "dut":"asus_5g", + "duration":"15s", + "station":"1.1.eth2", + "download_speed":"85%", + "upload_speed":"0", + "raw_line": ["pkts: Custom;60;MTU", "cust_pkt_sz: 88 1200", "directions: DUT Transmit", "traffic_types: UDP", "bandw_options: 20", "spatial_streams: 1"] } - + Sample .json between using eth1 and station 1.1.sta0002 { - "mgr":"192.168.0.101", - "port":"8080", - "lf_user":"lanforge", - "lf_password":"lanforge", - "instance_name":"dataplane-instance", - "config_name":"test_con", - "upstream":"1.1.eth1", - "dut":"asus_5g", - "duration":"15s", - "station":"1.1.sta0002", - "download_speed":"85%", - "upload_speed":"0", - "raw_line": ["pkts: Custom;60;MTU", "cust_pkt_sz: 88 1200", "directions: DUT Transmit", "traffic_types: UDP", "bandw_options: 20", "spatial_streams: 1"] - } + "mgr":"192.168.0.101", + "port":"8080", + "lf_user":"lanforge", + "lf_password":"lanforge", + "instance_name":"dataplane-instance", + "config_name":"test_con", + "upstream":"1.1.eth1", + "dut":"asus_5g", + "duration":"15s", + "station":"1.1.sta0002", + "download_speed":"85%", + "upload_speed":"0", + "raw_line": ["pkts: Custom;60;MTU", "cust_pkt_sz: 88 1200", "directions: DUT Transmit", "traffic_types: UDP", "bandw_options: 20", "spatial_streams: 1"] +} """ - ) + ) cv_add_base_parser(parser) # see cv_test_manager.py - parser.add_argument('--json', help="--json json input file", default="") - parser.add_argument('--influx_json', help="--influx_json influx config json input file", - default="") + parser.add_argument( + '--json', help="--json json input file", default="") + parser.add_argument( + '--influx_json', help="--influx_json influx config json input file", default="") parser.add_argument("-u", "--upstream", type=str, default="", help="Upstream port for wifi capacity test ex. 1.1.eth2") parser.add_argument("--station", type=str, default="", @@ -307,8 +316,8 @@ def main(): help="Specify requested upload speed. Percentage of theoretical is also supported. Default: 0") parser.add_argument("--duration", default="", help="Specify duration of each traffic run") - parser.add_argument("--graph_groups", help="File to save graph_groups to", default=None) - parser.add_argument("--report_dir", default="") + parser.add_argument( + "--graph_groups", help="File to save graph_groups to", default=None) parser.add_argument("--local_lf_report_dir", help="--local_lf_report_dir default '' put where dataplane script run from", default="") @@ -316,12 +325,12 @@ def main(): args = parser.parse_args() # use json config file - if args.json != "": - try: + if args.json: + if os.path.exists(args.json): with open(args.json, 'r') as json_config: json_data = json.load(json_config) - except: - print("Error reading {}".format(args.json)) + else: + return FileNotFoundError("Error reading {}".format(args.json)) # json configuation takes presidence to command line if "mgr" in json_data: args.mgr = json_data["mgr"] @@ -356,12 +365,12 @@ def main(): args.raw_line = json_data_tmp # use influx json config file - if args.influx_json != "": - try: - with open(args.influx_json, 'r') as influx_json_config: - influx_json_data = json.load(influx_json_config) - except: - print("Error reading {}".format(args.influx_json)) + if args.influx_json: + if os.path.exists(args.influx_json): + with open(args.influx_json, 'r') as json_config: + influx_json_data = json.load(json_config) + else: + return FileNotFoundError("Error reading {}".format(args.influx_json)) # json configuation takes presidence to command line # influx DB configuration if "influx_host" in influx_json_data: diff --git a/py-scripts/lf_dfs_test.py b/py-scripts/lf_dfs_test.py index 5ed0ff59..35289eb7 100755 --- a/py-scripts/lf_dfs_test.py +++ b/py-scripts/lf_dfs_test.py @@ -10,15 +10,14 @@ import re import csv import random import logging +import argparse if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) -import argparse LFUtils = importlib.import_module("py-json.LANforge.LFUtils") realm = importlib.import_module("py-json.realm") Realm = realm.Realm @@ -28,15 +27,18 @@ Realm = realm.Realm FORMAT = '%(asctime)s %(name)s %(levelname)s: %(message)s' + # see https://stackoverflow.com/a/13306095/11014343 class FileAdapter(object): def __init__(self, logger): self.logger = logger + def write(self, data): # NOTE: data can be a partial line, multiple lines - data = data.strip() # ignore leading/trailing whitespace - if data: # non-blank - self.logger.info(data) + data = data.strip() # ignore leading/trailing whitespace + if data: # non-blank + self.logger.info(data) + def flush(self): pass # leave it to logging to flush properly @@ -46,27 +48,27 @@ class FileAdapter(object): # Scaling and Performance to be self contained and not impact other tests ################################################################################ -class CreateCtlr(): +class CreateCtlr: def __init__(self, - _scheme, - _port, - _series, - _ctlr, - _prompt, - _user, - _passwd, - _ap, - _band, - _chan_5ghz, - _chan_24ghz, - _chan_width, - _ap_mode, - _tx_power, - _client_density, - _cap_ctl_out): + _scheme, + _port, + _series, + _ctlr, + _prompt, + _user, + _passwd, + _ap, + _band, + _chan_5ghz, + _chan_24ghz, + _chan_width, + _ap_mode, + _tx_power, + _client_density, + _cap_ctl_out): self.scheme = _scheme - self.port = _port + self.port = _port self.series = _series self.ctlr = _ctlr self.prompt = _prompt @@ -81,45 +83,54 @@ class CreateCtlr(): self.tx_power = _tx_power self.cap_ctl_out = _cap_ctl_out self.client_density = 0 + self.wlan = None + self.wlanID = None + self.wlanSSID = None - def verify_controller(self,client_density): + def verify_controller(self, client_density): self.client_density = client_density try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,"summary")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, "summary")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series,"--action", "summary"], capture_output=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--action", "summary"], capture_output=True) pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}" - .format(process_error.returncode, process_error.output)) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) time.sleep(1) exit(1) - + # Find our station count searchap = False for line in pss.splitlines(): - if (line.startswith("---------")): + if line.startswith("---------"): searchap = True continue - #TODO need to test with 9800 series to chelck the values - if (searchap): - pat = "%s\s+\S+\s+\S+\s+\S+\s+\S+.* \S+\s+\S+\s+(\S+)\s+\["%(self.ap) - #logg.info("AP line: %s"%(line)) + # TODO need to test with 9800 series to chelck the values + if searchap: + pat = "%s\s+\S+\s+\S+\s+\S+\s+\S+.* \S+\s+\S+\s+(\S+)\s+\[" % self.ap + # logg.info("AP line: %s"%(line)) m = re.search(pat, line) - if (m != None): + if m: sta_count = m.group(1) - logg.info("AP line: %s"%(line)) - logg.info("sta-count: %s"%(sta_count)) - if (int(sta_count) != int(self.client_density)): - logg.info("WARNING: Controller reported %s stations, should be %s"%(sta_count, self.client_density)) + logg.info("AP line: %s" % line) + logg.info("sta-count: %s" % sta_count) + if int(sta_count) != int(self.client_density): + logg.info( + "WARNING: Controller reported %s stations, should be %s" % (sta_count, self.client_density)) - #show summary (to get AP) (3400/9800) - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 --action summary --series 9800 --log stdout + # show summary (to get AP) (3400/9800) + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 --action summary --series 9800 --log stdout def controller_show_summary(self): pss = "" try: @@ -134,589 +145,697 @@ class CreateCtlr(): series: {} \ band: {} \ action: {}".format( - self.scheme, - self.ctlr, - self.port, - self.prompt, - self.user, - self.passwd, - self.ap, - self.series, - self.band, - "summary")) + self.scheme, + self.ctlr, + self.port, + self.prompt, + self.user, + self.passwd, + self.ap, + self.series, + self.band, + "summary")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", - "--scheme", self.scheme, - "--prompt", self.prompt, - "--port", self.port, - "-d", self.ctlr, - "-u", self.user, - "-p", self.passwd, - "-a", self.ap, - "--series", self.series, - "--band", self.band, - "--action", "summary"], - capture_output=self.cap_ctl_out, + ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", + "--scheme", self.scheme, + "--prompt", self.prompt, + "--port", self.port, + "-d", self.ctlr, + "-u", self.user, + "-p", self.passwd, + "-a", self.ap, + "--series", self.series, + "--band", self.band, + "--action", "summary"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}" - .format(process_error.returncode, process_error.output)) - time.sleep(1) - exit(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) + exit(1) return pss - #show ap dot11 5ghz summary (band defaults to 5ghz) --band a - #show ap dot11 24ghz summary use --band b for 2.4 ghz - #action advanced (3400/9800) - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 --action advanced --series 9800 --log stdout + # show ap dot11 5ghz summary (band defaults to 5ghz) --band a + # show ap dot11 24ghz summary use --band b for 2.4 ghz + # action advanced (3400/9800) + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 --action advanced --series 9800 --log stdout def controller_show_ap_summary(self): pss = "" try: logg.info("\ - scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,"advanced")) + scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, "advanced")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "advanced"], - capture_output=True, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "advanced"], + capture_output=True, check=True) pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) return pss - #show wlan summary + # show wlan summary def controller_show_wlan_summary(self): try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,"show wlan summary")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, "show wlan summary")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "show_wlan_summary"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "show_wlan_summary"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - #disable AP - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action disable --series 9800 + # disable AP + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action disable --series 9800 def controller_disable_ap(self): try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,"disable")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, "disable")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", - self.ctlr, "-u",self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "disable"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", + self.ctlr, "-u", self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "disable"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - - #disable wlan - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action disable_wlan --series 9800 + # disable wlan + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action disable_wlan --series 9800 def controller_disable_wlan(self): try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} wlan: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,self.wlan,"disable_wlan")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} wlan: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, self.wlan, "disable_wlan")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band,"--wlan", self.wlan, "--action", "disable_wlan"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--wlan", self.wlan, "--action", + "disable_wlan"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - - #disable network 5ghz - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action disable_network_5ghz --series 9800 + # disable network 5ghz + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action disable_network_5ghz --series 9800 def controller_disable_network_5ghz(self): if self.series == "9800": try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,"disable_network_5ghz")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, "disable_network_5ghz")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "disable_network_5ghz"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "disable_network_5ghz"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) else: try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"cmd","config 802.11a disable network")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "cmd", "config 802.11a disable network")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "cmd", "--value", "config 802.11a disable network"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "cmd", "--value", + "config 802.11a disable network"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - - #disable network 24ghz - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action disable_network_24ghz --series 9800 + # disable network 24ghz + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action disable_network_24ghz --series 9800 def controller_disable_network_24ghz(self): if self.series == "9800": try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,"disable_network_24ghz")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, "disable_network_24ghz")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "disable_network_24ghz"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "disable_network_24ghz"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) else: try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"cmd","config 802.11b disable network")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "cmd", "config 802.11b disable network")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "cmd", "--value", "config 802.11b disable network"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "cmd", "--value", + "config 802.11b disable network"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - - - #set manual mode - Series 9800 must be set to manual mode - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action manual --series 9800 + # set manual mode - Series 9800 must be set to manual mode + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action manual --series 9800 # ap name dot11 5ghz radio role manual client-serving def controller_role_manual(self): if self.series == "9800": try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,"manual")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, "manual")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "manual"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "manual"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) else: - logg.info("Check the controller scheme used attemping 9800 series on 3504 controller: {}".format(self.scheme)) + logg.info( + "Check the controller scheme used attemping 9800 series on 3504 controller: {}".format(self.scheme)) - #set manual mode - Series 9800 must be set to auto mode - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action auto --series 9800 + # set manual mode - Series 9800 must be set to auto mode + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action auto --series 9800 # ap name dot11 5ghz radio role manual client-serving def controller_role_auto(self): if self.series == "9800": try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,"auto")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, "auto")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "auto"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "auto"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) else: - logg.info("Check the controller scheme used attemping 9800 series on 3504 controller: {}".format(self.scheme)) + logg.info( + "Check the controller scheme used attemping 9800 series on 3504 controller: {}".format(self.scheme)) - #test parameters summary (txPower 1-8) - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action txPower --value 5 --series 9800 + # test parameters summary (txPower 1-8) + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action txPower --value 5 --series 9800 def controller_set_tx_power(self): try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"txPower", self.tx_power )) # TODO fix txPower to tx_power in wifi_ctl_9800_3504.py - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, - "--action", "txPower","--value", self.tx_power], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "txPower", self.tx_power)) # TODO fix txPower to tx_power in wifi_ctl_9800_3504.py + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, + "--action", "txPower", "--value", self.tx_power], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - #set channel [36, 64, 100] - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action channel --value 36 --series 9800 + # set channel [36, 64, 100] + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action channel --value 36 --series 9800 # 9800 : ap name dot11 [5ghz | 24ghz] channel # 3504 : (controller Controller) >config 802.11a channel ap APA453.0E7B.CF9C 52 def controller_set_channel(self): try: - if (self.band == "a"): + if self.band == "a": controller_channel = self.chan_5ghz else: controller_channel = self.chan_24ghz - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"channel", controller_channel )) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, - "--action", "channel","--value", controller_channel], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "channel", controller_channel)) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, + "--action", "channel", "--value", controller_channel], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) def controller_set_bandwidth_20(self): controller_chan_width_20 = "20" try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"channel", controller_chan_width_20 )) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, - "--action", "channel","--value", controller_chan_width_20], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "channel", controller_chan_width_20)) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, + "--action", "channel", "--value", controller_chan_width_20], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) - + except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - - #set bandwidth [20 40 80 160] - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action bandwidth --value 40 --series 9800 + # set bandwidth [20 40 80 160] + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action bandwidth --value 40 --series 9800 def controller_set_bandwidth(self): try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"channel", self.chan_width )) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, - "--action", "channel","--value", self.chan_width], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "channel", self.chan_width)) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, + "--action", "channel", "--value", self.chan_width], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) - + except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - - #create wlan - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action create_wlan --wlan "open-wlan" --wlanID 1 --series 9800 + # create wlan + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action create_wlan --wlan "open-wlan" --wlanID 1 --series 9800 def controller_create_wlan(self): if self.series == "9800": try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} wlan {} wlanID {} wlanSSID {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"create_wlan", self.wlan, self.wlanID, self.wlanSSID )) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, - "--action", "create_wlan","--wlan", self.wlan, "--wlanID", self.wlanID, "--wlanSSID", self.wlanSSID], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} wlan {} wlanID {} wlanSSID {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "create_wlan", self.wlan, self.wlanID, self.wlanSSID)) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, + "--action", "create_wlan", "--wlan", self.wlan, "--wlanID", self.wlanID, "--wlanSSID", + self.wlanSSID], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) - + except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) else: - logg.info("Check the controller_scheme used attemping 9800 series on 3504 controller: {}".format(self.scheme)) + logg.info( + "Check the controller_scheme used attemping 9800 series on 3504 controller: {}".format(self.scheme)) - #create wireless tag policy --9800 series needs to have wireless tag policy set - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action wireless_tag_policy --series 9800 + # create wireless tag policy --9800 series needs to have wireless tag policy set + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action wireless_tag_policy --series 9800 def controller_set_wireless_tag_policy(self): if self.series == "9800": try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"wireless_tag_policy" )) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, - "--action", "wireless_tag_policy"], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "wireless_tag_policy")) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, + "--action", "wireless_tag_policy"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) else: - logg.info("Check the controller_scheme used attemping 9800 series on 3504 controller: {}".format(self.scheme)) + logg.info( + "Check the controller_scheme used attemping 9800 series on 3504 controller: {}".format(self.scheme)) - - #enable wlan - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action enable_wlan --series 9800 + # enable wlan + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action enable_wlan --series 9800 def controller_enable_wlan(self): try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} wlan: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band, self.wlan,"enable_wlan")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--wlan", self.wlan, - "--action", "enable_wlan"], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} wlan: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, self.wlan, "enable_wlan")) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--wlan", self.wlan, + "--action", "enable_wlan"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) - + except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - - #enable 5ghz - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action enable_network_5ghz --series 9800 + # enable 5ghz + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action enable_network_5ghz --series 9800 def controller_enable_network_5ghz(self): if self.series == "9800": try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"enable_network_5ghz")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, - "--action", "enable_network_5ghz"], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "enable_network_5ghz")) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, + "--action", "enable_network_5ghz"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) - + except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) else: try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"cmd","config 802.11a enable network")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "cmd", "config 802.11a enable network")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "cmd", "--value", "config 802.11a enable network"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "cmd", "--value", + "config 802.11a enable network"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - - - #enable 24ghz - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action enable_network_24ghz --series 9800 + # enable 24ghz + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action enable_network_24ghz --series 9800 def controller_enable_network_24ghz(self): if self.series == "9800": try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"enable_network_24ghz")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, - "--action", "enable_network_24ghz"], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "enable_network_24ghz")) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, + "--action", "enable_network_24ghz"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) else: try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"cmd","config 802.11b enable network")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "cmd", "config 802.11b enable network")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "cmd", "--value", "config 802.11b enable network"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "cmd", "--value", + "config 802.11b enable network"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - - - #enable (band a) - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action enable --series 9800 + # enable (band a) + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action enable --series 9800 def controller_enable_ap(self): try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"enable")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, - "--action", "enable"], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "enable")) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, + "--action", "enable"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - - #advanced (showes summary) - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action advanced --series 9800 + # advanced (showes summary) + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action advanced --series 9800 def controller_show_ap_channel(self): - advanced = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--action", "ap_channel"], capture_output=True) + advanced = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", + self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--action", "ap_channel"], capture_output=True) pss = advanced.stdout.decode('utf-8', 'ignore') logg.info(pss) if self.series == "9800": - if (self.band == "a"): + if self.band == "a": controller_channel = self.chan_5ghz else: controller_channel = self.chan_24ghz @@ -726,45 +845,53 @@ class CreateCtlr(): logg.info("line {}".format(line)) element_list = line.lstrip().split() logg.info("element_list {}".format(element_list)) - if (line.lstrip().startswith(search_str)): + if line.lstrip().startswith(search_str): logg.info("line {}".format(line)) element_list = line.lstrip().split() logg.info("element_list {}".format(element_list)) # AP Name (0) mac (1) slot (2) Admin State [enable/disable] (3) Oper State [Up/Down] (4) Width (5) Txpwr (6,7) channel (8) mode (9) - logg.info("ap: {} slof {} channel {} chan_width {}".format(element_list[0],element_list[2],element_list[8],element_list[5])) - if (str(controller_channel) in str(element_list[8])) and (str(self.chan_width) in str(element_list[5])): - logg.info("ap {} configuration successful: channel {} in expected {} chan_width {} in expected {}" - .format(element_list[0],controller_channel,element_list[8],self.chan_width,element_list[5])) + logg.info("ap: {} slof {} channel {} chan_width {}".format(element_list[0], element_list[2], + element_list[8], element_list[5])) + if (str(controller_channel) in str(element_list[8])) and ( + str(self.chan_width) in str(element_list[5])): + logg.info( + "ap {} configuration successful: channel {} in expected {} chan_width {} in expected {}".format( + element_list[0], controller_channel, element_list[8], self.chan_width, + element_list[5])) else: logg.info("WARNING ap {} configuration: channel {} in expected {} chan_width {} in expected {}" - .format(element_list[0],controller_channel,element_list[8],self.chan_width,element_list[5])) + .format(element_list[0], controller_channel, element_list[8], self.chan_width, + element_list[5])) break else: logg.info("checking for 802.11{}".format(self.band)) - if (self.band == "a"): + if self.band == "a": controller_channel = self.chan_5ghz else: controller_channel = self.chan_24ghz for line in pss.splitlines(): - #logg.info("line {}".format(line)) + # logg.info("line {}".format(line)) search_str = "802.11{}".format(self.band) - if (line.lstrip().startswith(search_str)): + if line.lstrip().startswith(search_str): logg.info("line {}".format(line)) element_list = line.lstrip().split() logg.info("element_list {}".format(element_list)) - logg.info("ap: {} channel {} chan_width {}".format(self.ap,element_list[4],element_list[5])) - if (str(controller_channel) in str(element_list[4])) and (str(self.chan_width) in str(element_list[5])): + logg.info("ap: {} channel {} chan_width {}".format(self.ap, element_list[4], element_list[5])) + if (str(controller_channel) in str(element_list[4])) and ( + str(self.chan_width) in str(element_list[5])): logg.info("ap configuration successful: channel {} in expected {} chan_width {} in expected {}" - .format(controller_channel,element_list[4],self.chan_width,element_list[5])) + .format(controller_channel, element_list[4], self.chan_width, element_list[5])) else: logg.info("AP WARNING: channel {} expected {} chan_width {} expected {}" - .format(element_list[4],controller_channel,element_list[5],self.chan_width)) + .format(element_list[4], controller_channel, element_list[5], self.chan_width)) break - - logg.info("configure ap {} channel {} chan_width {}".format(self.ap,self.channel,self.chan_width)) + + logg.info("configure ap {} channel {} chan_width {}".format(self.ap, self.channel, self.chan_width)) # Verify channel and channel width. -########################################## + + +########################################## # End of controller controller class ########################################## @@ -773,68 +900,66 @@ class CreateCtlr(): ########################################## class L3VariableTime(Realm): - def __init__(self, - args, - _dfs, - _dfs_time, - _radar_duration, - _scheme, - _port, - _series, - _ctlr, - _prompt, - _user, - _passwd, - _ap, - _ap_slot, - _band, - _chan_5ghz, - _chan_24ghz, - _chan_width, - _ap_mode, - _tx_power, - _client_density, - _cap_ctl_out, - _ap_dict, - endp_type, - tos, - side_b, - radio_name_list, - number_of_stations_per_radio_list, - ssid_list, - ssid_password_list, - ssid_security_list, - wifimode_list, - station_lists, - name_prefix, - debug_on, - outfile, - results, - test_keys, - test_config, - reset_port_enable_list, - reset_port_time_min_list, - reset_port_time_max_list, - csv_started=False, - side_a_min_bps=560000, - side_a_max_bps=0, - side_a_min_pdu=1518, - side_a_max_pdu=0, - side_b_min_bps=560000, - side_b_max_bps=0, - side_b_min_pdu=1518, - side_b_max_pdu=0, - number_template="00", - test_duration="256s", - polling_interval="60s", - lfclient_host="localhost", - lfclient_port=8080, - debug=False, - wait_timeout=120, - _exit_on_error=False, - _exit_on_fail=False, - _proxy_str=None, - _capture_signal_list=[]): + def __init__(self, + args, + _dfs, + _dfs_time, + _radar_duration, + _scheme, + _port, + _series, + _ctlr, + _prompt, + _user, + _passwd, + _ap, + _ap_slot, + _band, + _chan_5ghz, + _chan_24ghz, + _chan_width, + _ap_mode, + _tx_power, + _client_density, + _cap_ctl_out, + _ap_dict, + endp_type, + tos, + side_b, + radio_name_list, + number_of_stations_per_radio_list, + ssid_list, + ssid_password_list, + ssid_security_list, + wifimode_list, + station_lists, + name_prefix, + debug_on, + outfile, + results, + test_keys, + test_config, + reset_port_enable_list, + reset_port_time_min_list, + reset_port_time_max_list, + csv_started=False, + side_a_min_bps=560000, + side_a_min_pdu=1518, + side_a_max_pdu=0, + side_b_min_bps=560000, + side_b_min_pdu=1518, + side_b_max_pdu=0, + number_template="00", + test_duration="256s", + polling_interval="60s", + lfclient_host="localhost", + lfclient_port=8080, + debug=False, + wait_timeout=120, + _exit_on_error=False, + _exit_on_fail=False, + _proxy_str=None, + _capture_signal_list=None): super().__init__(lfclient_host=lfclient_host, lfclient_port=lfclient_port, debug_=debug, @@ -842,22 +967,25 @@ class L3VariableTime(Realm): _exit_on_fail=_exit_on_fail, _proxy_str=_proxy_str, _capture_signal_list=_capture_signal_list) + if _capture_signal_list is None: + _capture_signal_list = [] + self.total_stas = 0 self.dfs = _dfs self.dfs_time = _dfs_time self.radar_duration = _radar_duration self.radar_duration_seconds = self.duration_time_to_seconds(_radar_duration) self.dfs_time_seconds = self.duration_time_to_seconds(_dfs_time) self.scheme = _scheme - self.port = _port + self.port = _port self.series = _series - self.ctlr = _ctlr + self.ctlr = _ctlr self.prompt = _prompt - self.user = _user + self.user = _user self.passwd = _passwd - self.ap = _ap + self.ap = _ap self.ap_slot = _ap_slot - self.band = _band - self.chan_5ghz = _chan_5ghz + self.band = _band + self.chan_5ghz = _chan_5ghz self.chan_24ghz = _chan_24ghz self.chan_width = _chan_width self.ap_mode = _ap_mode @@ -870,7 +998,7 @@ class L3VariableTime(Realm): self.side_b = side_b self.ssid_list = ssid_list self.ssid_password_list = ssid_password_list - self.station_lists = station_lists + self.station_lists = station_lists self.ssid_security_list = ssid_security_list self.wifimode_list = wifimode_list self.reset_port_enable_list = reset_port_enable_list @@ -880,8 +1008,8 @@ class L3VariableTime(Realm): self.name_prefix = name_prefix self.test_duration = test_duration self.radio_name_list = radio_name_list - self.number_of_stations_per_radio_list = number_of_stations_per_radio_list - #self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port, debug_=debug_on) + self.number_of_stations_per_radio_list = number_of_stations_per_radio_list + # self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port, debug_=debug_on) self.polling_interval_seconds = self.duration_time_to_seconds(polling_interval) self.cx_profile = self.new_l3_cx_profile() self.multicast_profile = self.new_multicast_profile() @@ -892,13 +1020,13 @@ class L3VariableTime(Realm): self.results = results self.csv_started = csv_started self.epoch_time = int(time.time()) - self.dfs_epoch_start = 0 + self.dfs_epoch_start = 0 self.dfs_epoch_detect = 0 - #[*07/07/2020 23:37:48.1460] changed to DFS channel 52, running CAC for 60 seconds. + # [*07/07/2020 23:37:48.1460] changed to DFS channel 52, running CAC for 60 seconds. self.CAC_TIMER = "" - #[*07/07/2020 23:38:48.7240] CAC_EXPIRY_EVT: CAC finished on DFS channel 52 + # [*07/07/2020 23:38:48.7240] CAC_EXPIRY_EVT: CAC finished on DFS channel 52 self.CAC_EXPIRY_EVT = "" - #[*07/07/2020 23:44:27.8060] DOT11_DRV[1]: set_dfs Channel set to 36/20, CSA count 10 + # [*07/07/2020 23:44:27.8060] DOT11_DRV[1]: set_dfs Channel set to 36/20, CSA count 10 self.CSA_COUNT = "" self.BLACK_LIST = "" self.debug = debug_on @@ -906,36 +1034,39 @@ class L3VariableTime(Realm): self.test_keys = test_keys self.test_config = test_config - self.test_config_dict = dict(map(lambda x: x.split('=='), str(self.test_config).replace('[','').replace(']','').replace("'","").split())) - + self.test_config_dict = dict(map(lambda x: x.split('=='), + str(self.test_config).replace('[', '').replace(']', '').replace("'", + "").split())) # Full spread-sheet data if self.outfile is not None: - self.csv_file = open(self.outfile, "a+") + self.csv_file = open(self.outfile, "a+") self.csv_writer = csv.writer(self.csv_file, delimiter=",") - + if self.results is not None: - self.csv_results = open(self.results, "a+") + self.csv_results = open(self.results, "a+") self.csv_results_writer = csv.writer(self.csv_results, delimiter=",") - for (radio_, ssid_, ssid_password_, ssid_security_, wifimode_,\ - reset_port_enable_, reset_port_time_min_, reset_port_time_max_) \ - in zip(radio_name_list, ssid_list, ssid_password_list, ssid_security_list, wifimode_list,\ - reset_port_enable_list, reset_port_time_min_list, reset_port_time_max_list): + for (radio_, ssid_, ssid_password_, ssid_security_, wifimode_, + reset_port_enable_, reset_port_time_min_, reset_port_time_max_) \ + in zip(radio_name_list, ssid_list, ssid_password_list, ssid_security_list, wifimode_list, + reset_port_enable_list, reset_port_time_min_list, reset_port_time_max_list): self.station_profile = self.new_station_profile() self.station_profile.lfclient_url = self.lfclient_url self.station_profile.ssid = ssid_ self.station_profile.ssid_pass = ssid_password_ self.station_profile.security = ssid_security_ - self.station_profile.mode = wifimode_ + self.station_profile.mode = wifimode_ self.station_profile.number_template = self.number_template - self.station_profile.mode = wifimode_ - self.station_profile.set_reset_extra(reset_port_enable=reset_port_enable_,\ - test_duration=self.duration_time_to_seconds(self.test_duration),\ - reset_port_min_time=self.duration_time_to_seconds(reset_port_time_min_),\ - reset_port_max_time=self.duration_time_to_seconds(reset_port_time_max_)) + self.station_profile.mode = wifimode_ + self.station_profile.set_reset_extra(reset_port_enable=reset_port_enable_, + test_duration=self.duration_time_to_seconds(self.test_duration), + reset_port_min_time=self.duration_time_to_seconds( + reset_port_time_min_), + reset_port_max_time=self.duration_time_to_seconds( + reset_port_time_max_)) self.station_profiles.append(self.station_profile) - + self.multicast_profile.host = self.lfclient_host self.cx_profile.host = self.lfclient_host self.cx_profile.port = self.lfclient_port @@ -974,46 +1105,48 @@ class L3VariableTime(Realm): def time_stamp(self): return time.strftime('%Y-%m-%d %H %M %S', time.localtime(self.epoch_time)) - def __record_rx_dropped_percent(self,rx_drop_percent): + def __record_rx_dropped_percent(self, rx_drop_percent): csv_rx_drop_percent_data = [] print("test_keys {}".format(self.test_keys)) print("self.test_config_dict {}".format(self.test_config_dict)) for key in self.test_keys: csv_rx_drop_percent_data.append(self.test_config_dict[key]) - csv_rx_drop_percent_data.extend([self.epoch_time, self.time_stamp(),'rx_drop_percent']) + csv_rx_drop_percent_data.extend([self.epoch_time, self.time_stamp(), 'rx_drop_percent']) # remove multi cast since downstream only if selected - for key in [key for key in rx_drop_percent if "mtx" in key]: del rx_drop_percent[key] + for key in [key for key in rx_drop_percent if "mtx" in key]: + del rx_drop_percent[key] if "upstream" in self.test_config_dict.values(): - for key in [key for key in rx_drop_percent if "-A" in key]: del rx_drop_percent[key] + for key in [key for key in rx_drop_percent if "-A" in key]: + del rx_drop_percent[key] elif "downstream" in self.test_config_dict.values(): - for key in [key for key in rx_drop_percent if "-B" in key]: del rx_drop_percent[key] + for key in [key for key in rx_drop_percent if "-B" in key]: + del rx_drop_percent[key] - - filtered_values = [v for _, v in rx_drop_percent.items() if v !=0] + filtered_values = [v for _, v in rx_drop_percent.items() if v != 0] average_rx_drop_percent = sum(filtered_values) / len(filtered_values) if len(filtered_values) != 0 else 0 - csv_performance_rx_drop_percent_values=sorted(rx_drop_percent.items(), key=lambda x: (x[1],x[0]), reverse=False) - csv_performance_rx_drop_percent_values=self.csv_validate_list(csv_performance_rx_drop_percent_values,5) + csv_performance_rx_drop_percent_values = sorted(rx_drop_percent.items(), key=lambda x: (x[1], x[0]), + reverse=False) + csv_performance_rx_drop_percent_values = self.csv_validate_list(csv_performance_rx_drop_percent_values, 5) for i in range(5): - csv_rx_drop_percent_data.append(str(csv_performance_rx_drop_percent_values[i]).replace(',',';')) - for i in range(-1,-6,-1): - csv_rx_drop_percent_data.append(str(csv_performance_rx_drop_percent_values[i]).replace(',',';')) + csv_rx_drop_percent_data.append(str(csv_performance_rx_drop_percent_values[i]).replace(',', ';')) + for i in range(-1, -6, -1): + csv_rx_drop_percent_data.append(str(csv_performance_rx_drop_percent_values[i]).replace(',', ';')) csv_rx_drop_percent_data.append(average_rx_drop_percent) for item, value in rx_drop_percent.items(): - #logg.info(item, "rx drop percent: ", rx_drop_percent[item]) + # logg.info(item, "rx drop percent: ", rx_drop_percent[item]) csv_rx_drop_percent_data.append(rx_drop_percent[item]) - self.csv_add_row(csv_rx_drop_percent_data,self.csv_writer,self.csv_file) - self.csv_add_row(csv_rx_drop_percent_data,self.csv_results_writer,self.csv_results) + self.csv_add_row(csv_rx_drop_percent_data, self.csv_writer, self.csv_file) + self.csv_add_row(csv_rx_drop_percent_data, self.csv_results_writer, self.csv_results) def __compare_vals(self, old_list, new_list): passes = 0 expected_passes = 0 - csv_performance_values = [] csv_rx_headers = [] csv_rx_row_data = [] csv_result_row_data = [] @@ -1021,27 +1154,30 @@ class L3VariableTime(Realm): csv_rx_delta_dict = {} test_id = "" - #for key in self.test_keys: + # for key in self.test_keys: # csv_rx_row_data.append(self.test_config_dict[key]) # csv_rx_delta_row_data.append(self.test_config_dict[key]) + for key in [key for key in old_list if "mtx" in key]: + del old_list[key] + for key in [key for key in new_list if "mtx" in key]: + del new_list[key] - for key in [key for key in old_list if "mtx" in key]: del old_list[key] - for key in [key for key in new_list if "mtx" in key]: del new_list[key] - - filtered_values = [v for _, v in new_list.items() if v !=0] - average_rx= sum(filtered_values) / len(filtered_values) if len(filtered_values) != 0 else 0 + filtered_values = [v for _, v in new_list.items() if v != 0] + average_rx = sum(filtered_values) / len(filtered_values) if len(filtered_values) != 0 else 0 # only evaluate upstream or downstream new_evaluate_list = new_list.copy() - print("new_evaluate_list before",new_evaluate_list) + print("new_evaluate_list before", new_evaluate_list) if "upstream" in self.test_config_dict.values(): - for key in [key for key in new_evaluate_list if "-A" in key]: del new_evaluate_list[key] + for key in [key for key in new_evaluate_list if "-A" in key]: + del new_evaluate_list[key] print("upstream in dictionary values") - elif "downstream" in self.test_config_dict.values(): - for key in [key for key in new_evaluate_list if "-B" in key]: del new_evaluate_list[key] + elif "downstream" in self.test_config_dict.values(): + for key in [key for key in new_evaluate_list if "-B" in key]: + del new_evaluate_list[key] print("downstream in dictionary values") - #follow code left in for now, provides the best 5 worst 5 + # follow code left in for now, provides the best 5 worst 5 '''print("new_evaluate_list after",new_evaluate_list) csv_performance_values=sorted(new_evaluate_list.items(), key=lambda x: (x[1],x[0]), reverse=False) csv_performance_values=self.csv_validate_list(csv_performance_values,5) @@ -1054,26 +1190,28 @@ class L3VariableTime(Realm): old_evaluate_list = old_list.copy() if "upstream" in self.test_config_dict.values(): - for key in [key for key in old_evaluate_list if "-A" in key]: del old_evaluate_list[key] + for key in [key for key in old_evaluate_list if "-A" in key]: + del old_evaluate_list[key] print("upstream in dictionary values") - elif "downstream" in self.test_config_dict.values(): - for key in [key for key in old_evaluate_list if "-B" in key]: del old_evaluate_list[key] + elif "downstream" in self.test_config_dict.values(): + for key in [key for key in old_evaluate_list if "-B" in key]: + del old_evaluate_list[key] print("downstream in dictionary values") if len(old_evaluate_list) == len(new_evaluate_list): for item, value in old_evaluate_list.items(): - expected_passes +=1 + expected_passes += 1 print("ITEM: {} VALUE: {}".format(item, value)) if new_evaluate_list[item] > old_evaluate_list[item]: passes += 1 - #if self.debug: logg.info(item, new_evaluate_list[item], old_evaluate_list[item], " Difference: ", new_evaluate_list[item] - old_evaluate_list[item]) - print(item, new_evaluate_list[item], old_evaluate_list[item], " Difference: ", new_evaluate_list[item] - old_evaluate_list[item]) + # if self.debug: logg.info(item, new_evaluate_list[item], old_evaluate_list[item], " Difference: ", new_evaluate_list[item] - old_evaluate_list[item]) + print(item, new_evaluate_list[item], old_evaluate_list[item], " Difference: ", + new_evaluate_list[item] - old_evaluate_list[item]) else: print("Failed to increase rx data: ", item, new_evaluate_list[item], old_evaluate_list[item]) if not self.csv_started: csv_rx_headers.append(item) - csv_rx_delta_dict.update({item:(new_evaluate_list[item] - old_evaluate_list[item])}) - + csv_rx_delta_dict.update({item: (new_evaluate_list[item] - old_evaluate_list[item])}) if not self.csv_started: csv_header = self.csv_generate_column_headers() @@ -1081,7 +1219,7 @@ class L3VariableTime(Realm): logg.info(csv_header) self.csv_add_column_headers(csv_header) csv_results = self.csv_generate_column_results_headers() - #csv_results += csv_rx_headers + # csv_results += csv_rx_headers self.csv_add_column_headers_results(csv_results) print("###################################") print(csv_results) @@ -1090,24 +1228,23 @@ class L3VariableTime(Realm): self.csv_started = True # need to generate list first to determine worst and best - filtered_values = [v for _, v in csv_rx_delta_dict.items() if v !=0] - #average_rx_delta= sum(filtered_values) / len(filtered_values) if len(filtered_values) != 0 else 0 + filtered_values = [v for _, v in csv_rx_delta_dict.items() if v != 0] + # average_rx_delta= sum(filtered_values) / len(filtered_values) if len(filtered_values) != 0 else 0 for key in self.test_keys: csv_rx_row_data.append(self.test_config_dict[key]) csv_result_row_data.append(self.test_config_dict[key]) csv_rx_delta_row_data.append(self.test_config_dict[key]) - - max_tp_mbps = sum(filtered_values) + + max_tp_mbps = sum(filtered_values) csv_rx_row_data.append(max_tp_mbps) csv_result_row_data.append(max_tp_mbps) - #To do needs to be read or passed in based on test type - expected_tp_mbps = max_tp_mbps + # To do needs to be read or passed in based on test type + expected_tp_mbps = max_tp_mbps csv_rx_row_data.append(expected_tp_mbps) csv_result_row_data.append(expected_tp_mbps) - - #Generate TestID + # Generate TestID for key in self.test_keys: test_id = test_id + "_" + self.test_config_dict[key] @@ -1125,11 +1262,11 @@ class L3VariableTime(Realm): csv_rx_row_data.append("fail") csv_result_row_data.append("fail")''' - csv_rx_row_data.extend([self.epoch_time, self.time_stamp(),'rx_delta']) + csv_rx_row_data.extend([self.epoch_time, self.time_stamp(), 'rx_delta']) csv_result_row_data.extend([self.epoch_time, self.time_stamp()]) print("csv_rx_row_data {}".format(csv_rx_row_data)) - #TODO: may want to pass in the information that needs to be in the csv file into the class + # TODO: may want to pass in the information that needs to be in the csv file into the class ''' csv_rx_row_data.extend([self.epoch_time, self.time_stamp(),'rx']) csv_rx_delta_row_data.extend([self.epoch_time, self.time_stamp(),'rx_delta']) @@ -1142,61 +1279,71 @@ class L3VariableTime(Realm): csv_rx_delta_row_data.append(str(csv_performance_delta_values[i]).replace(',',';')) csv_rx_delta_row_data.append(average_rx_delta)''' - + for item, value in old_evaluate_list.items(): - expected_passes +=1 + expected_passes += 1 if new_evaluate_list[item] > old_evaluate_list[item]: passes += 1 - #if self.debug: logg.info(item, new_evaluate_list[item], old_evaluate_list[item], " Difference: ", new_evaluate_list[item] - old_evaluate_list[item]) - print(item, new_evaluate_list[item], old_evaluate_list[item], " Difference: ", new_evaluate_list[item] - old_evaluate_list[item]) + # if self.debug: logg.info(item, new_evaluate_list[item], old_evaluate_list[item], " Difference: ", new_evaluate_list[item] - old_evaluate_list[item]) + print(item, new_evaluate_list[item], old_evaluate_list[item], " Difference: ", + new_evaluate_list[item] - old_evaluate_list[item]) else: print("Failed to increase rx data: ", item, new_evaluate_list[item], old_evaluate_list[item]) if not self.csv_started: csv_rx_headers.append(item) # note need to have all upstream and downstream in the csv table thus new_list and old_list - #csv_rx_row_data.append(new_list[item]) + # csv_rx_row_data.append(new_list[item]) # provide delta csv_rx_row_data.append(new_list[item] - old_list[item]) - self.csv_add_row(csv_rx_row_data,self.csv_writer,self.csv_file) - #self.csv_add_row(csv_rx_row_data,self.csv_results_writer,self.csv_results) + self.csv_add_row(csv_rx_row_data, self.csv_writer, self.csv_file) + # self.csv_add_row(csv_rx_row_data,self.csv_results_writer,self.csv_results) - #self.csv_add_row(csv_rx_delta_row_data,self.csv_writer,self.csv_file) + # self.csv_add_row(csv_rx_delta_row_data,self.csv_writer,self.csv_file) if passes == expected_passes: return True, max_tp_mbps, csv_result_row_data else: return False, max_tp_mbps, csv_result_row_data else: - print("Old-list length: %i new: %i does not match in compare-vals."%(len(old_list), len(new_list))) - print("old-list:",old_list) - print("new-list:",new_list) - return False, None, None # check to see if this is valid + print("Old-list length: %i new: %i does not match in compare-vals." % (len(old_list), len(new_list))) + print("old-list:", old_list) + print("new-list:", new_list) + return False, None, None # check to see if this is valid def reset_port_check(self): for station_profile in self.station_profiles: if station_profile.reset_port_extra_data['reset_port_enable']: - if station_profile.reset_port_extra_data['reset_port_timer_started'] == False: - logg.info("reset_port_time_min: {}".format(station_profile.reset_port_extra_data['reset_port_time_min'])) - logg.info("reset_port_time_max: {}".format(station_profile.reset_port_extra_data['reset_port_time_max'])) + if not station_profile.reset_port_extra_data['reset_port_timer_started']: + logg.info( + "reset_port_time_min: {}".format(station_profile.reset_port_extra_data['reset_port_time_min'])) + logg.info( + "reset_port_time_max: {}".format(station_profile.reset_port_extra_data['reset_port_time_max'])) station_profile.reset_port_extra_data['seconds_till_reset'] = \ - random.randint(station_profile.reset_port_extra_data['reset_port_time_min'],\ - station_profile.reset_port_extra_data['reset_port_time_max']) + random.randint(station_profile.reset_port_extra_data['reset_port_time_min'], + station_profile.reset_port_extra_data['reset_port_time_max']) station_profile.reset_port_extra_data['reset_port_timer_started'] = True - logg.info("on radio {} seconds_till_reset {}".format(station_profile.add_sta_data['radio'],station_profile.reset_port_extra_data['seconds_till_reset'])) + logg.info("on radio {} seconds_till_reset {}".format(station_profile.add_sta_data['radio'], + station_profile.reset_port_extra_data[ + 'seconds_till_reset'])) else: - station_profile.reset_port_extra_data['seconds_till_reset'] = station_profile.reset_port_extra_data['seconds_till_reset'] - 1 - if self.debug: logg.info("radio: {} countdown seconds_till_reset {}".format(station_profile.add_sta_data['radio'] ,station_profile.reset_port_extra_data['seconds_till_reset'])) - if ((station_profile.reset_port_extra_data['seconds_till_reset'] <= 0)): + station_profile.reset_port_extra_data['seconds_till_reset'] = station_profile.reset_port_extra_data[ + 'seconds_till_reset'] - 1 + if self.debug: + logg.info( + "radio: {} countdown seconds_till_reset {}".format(station_profile.add_sta_data['radio'], + station_profile.reset_port_extra_data[ + 'seconds_till_reset'])) + if station_profile.reset_port_extra_data['seconds_till_reset'] <= 0: station_profile.reset_port_extra_data['reset_port_timer_started'] = False - port_to_reset = random.randint(0,len(station_profile.station_names)-1) - logg.info("reset on radio {} station: {}".format(station_profile.add_sta_data['radio'],station_profile.station_names[port_to_reset])) + port_to_reset = random.randint(0, len(station_profile.station_names) - 1) + logg.info("reset on radio {} station: {}".format(station_profile.add_sta_data['radio'], + station_profile.station_names[port_to_reset])) self.reset_port(station_profile.station_names[port_to_reset]) def pre_cleanup(self): self.cx_profile.cleanup_prefix() self.multicast_profile.cleanup_prefix() - self.total_stas = 0 for station_list in self.station_lists: for sta in station_list: self.rm_port(sta, check_exists=True) @@ -1204,12 +1351,12 @@ class L3VariableTime(Realm): # Make sure they are gone count = 0 - while (count < 10): + while count < 10: more = False for station_list in self.station_lists: for sta in station_list: rv = self.rm_port(sta, check_exists=True) - if (rv): + if rv: more = True if not more: break @@ -1223,34 +1370,36 @@ class L3VariableTime(Realm): station_profile.set_number_template(station_profile.number_template) logg.info("Creating stations") - station_profile.create(radio=self.radio_name_list[index], sta_names_=self.station_lists[index], debug=self.debug, sleep_time=0) + station_profile.create(radio=self.radio_name_list[index], sta_names_=self.station_lists[index], + debug=self.debug, sleep_time=0) index += 1 # 12/4/2020 put back in multi cast - #for etype in self.endp_types: + # for etype in self.endp_types: # if etype == "mc_udp" or etype == "mc_udp6": # logg.info("Creating Multicast connections for endpoint type: %s"%(etype)) # self.multicast_profile.create_mc_tx(etype, self.side_b, etype) # self.multicast_profile.create_mc_rx(etype, side_rx=station_profile.station_names) - + for _tos in self.tos: - logg.info("Creating connections for endpoint type: {} TOS: {} stations_names {}".format(self.endp_type, _tos, station_profile.station_names)) - self.cx_profile.create(endp_type=self.endp_type, side_a=station_profile.station_names, side_b=self.side_b, sleep_time=0, tos=_tos) - self._pass("PASS: Stations build finished") - + logg.info( + "Creating connections for endpoint type: {} TOS: {} stations_names {}".format(self.endp_type, _tos, + station_profile.station_names)) + self.cx_profile.create(endp_type=self.endp_type, side_a=station_profile.station_names, + side_b=self.side_b, sleep_time=0, tos=_tos) + self._pass("PASS: Stations build finished") + def station_bringup(self): client_density = 0 logg.info("Bringing up stations") - self.admin_up(self.side_b) + self.admin_up(self.side_b) for station_profile in self.station_profiles: for sta in station_profile.station_names: - logg.info("Bringing up station %s"%(sta)) + logg.info("Bringing up station %s" % sta) self.admin_up(sta) client_density += 1 - - temp_stations_list = [] - temp_stations_list.append(self.side_b) + temp_stations_list = [self.side_b] for station_profile in self.station_profiles: temp_stations_list.extend(station_profile.station_names.copy()) # need algorithm for setting time default @@ -1258,8 +1407,8 @@ class L3VariableTime(Realm): logg.info("ip's acquired") else: logg.info("print failed to get IP's") - exit(1) # why continue - + exit(1) # why continue + return client_density def read_channel(self): @@ -1268,52 +1417,55 @@ class L3VariableTime(Realm): pss = "" try: logg.info("\ - scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,"advanced")) + scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, "advanced")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "advanced"], - capture_output=True, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "advanced"], + capture_output=True, check=True) pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) logg.info("controller_show_ap_summary::: pss {}".format(pss)) if self.series == "9800": searchap = False - cc_mac = "" cc_ch = "" - cc_bw = "" - cc_power = "" - cc_dbm = "" for line in pss.splitlines(): - if (line.startswith("---------")): + if line.startswith("---------"): searchap = True continue # if the pattern changes save the output of the advanced command and re parse https://regex101.com - if (searchap): - pat = "%s\s+(\S+)\s+(%s)\s+\S+\s+\S+\s+(\S+)\s+(\S+)\s+(\S+)\s+dBm\)+\s+(\S+)+\s"%(self.ap,self.ap_slot) + if searchap: + pat = "%s\s+(\S+)\s+(%s)\s+\S+\s+\S+\s+(\S+)\s+(\S+)\s+(\S+)\s+dBm\)+\s+(\S+)+\s" % ( + self.ap, self.ap_slot) m = re.search(pat, line) - if (m != None): - if(m.group(2) == self.ap_slot): + if m: + if m.group(2) == self.ap_slot: cc_mac = m.group(1) cc_slot = m.group(2) - cc_ch = m.group(6); # (132,136,140,144) + cc_ch = m.group(6) # (132,136,140,144) cc_power = m.group(4) - cc_power = cc_power.replace("/", " of ") # spread-sheets turn 1/8 into a date + cc_power = cc_power.replace("/", " of ") # spread-sheets turn 1/8 into a date cc_dbm = m.group(5) - cc_dbm = cc_dbm.replace("(","") + cc_dbm = cc_dbm.replace("(", "") cc_ch_count = cc_ch.count(",") + 1 cc_bw = m.group(3) - logg.info("group 1: {} 2: {} 3: {} 4: {} 5: {} 6: {}".format(m.group(1),m.group(2),m.group(3),m.group(4),m.group(5),m.group(6))) + logg.info( + "group 1: {} 2: {} 3: {} 4: {} 5: {} 6: {}".format(m.group(1), m.group(2), m.group(3), + m.group(4), m.group(5), m.group(6))) logg.info("9800 test_parameters cc_mac: read : {}".format(cc_mac)) logg.info("9800 test_parameters cc_slot: read : {}".format(cc_slot)) logg.info("9800 test_parameters cc_count: read : {}".format(cc_ch_count)) @@ -1324,29 +1476,24 @@ class L3VariableTime(Realm): break else: searchap = False - cc_mac = "" cc_ch = "" - cc_bw = "" - cc_power = "" - cc_dbm = "" - ch_count = "" for line in pss.splitlines(): - if (line.startswith("---------")): + if line.startswith("---------"): searchap = True continue - - if (searchap): - pat = "%s\s+(\S+)\s+\S+\s+\S+\s+\S+\s+(\S+)\s+(\S+)\s+\(\s*(\S+)\s+dBm"%(self.ap) + + if searchap: + pat = "%s\s+(\S+)\s+\S+\s+\S+\s+\S+\s+(\S+)\s+(\S+)\s+\(\s*(\S+)\s+dBm" % self.ap m = re.search(pat, line) - if (m != None): + if m: cc_mac = m.group(1) - cc_ch = m.group(2); # (132,136,140,144) + cc_ch = m.group(2) # (132,136,140,144) cc_power = m.group(3) - cc_power = cc_power.replace("/", " of ", 1) # spread-sheets turn 1/8 into a date + cc_power = cc_power.replace("/", " of ", 1) # spread-sheets turn 1/8 into a date cc_dbm = m.group(4) ch_count = cc_ch.count(",") cc_bw = 20 * (ch_count + 1) - + logg.info("3504 test_parameters cc_mac: read : {}".format(cc_mac)) logg.info("3504 test_parameters cc_count: read : {}".format(ch_count)) logg.info("3504 test_parameters cc_bw: read : {}".format(cc_bw)) @@ -1354,7 +1501,7 @@ class L3VariableTime(Realm): logg.info("3504 test_parameters cc_dbm: read : {}".format(cc_dbm)) logg.info("3504 test_parameters cc_ch: read : {}".format(cc_ch)) - return cc_ch + return cc_ch def read_auto_rf(self): @@ -1362,34 +1509,39 @@ class L3VariableTime(Realm): pss = "" try: logg.info("\ - scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,"advanced")) + scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, "advanced")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "auto_rf"], - capture_output=True, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "auto_rf"], + capture_output=True, check=True) pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) blacklist_time = "" for line in pss.splitlines(): - pat = 'Channel\s+%s\S+\s+(\S+)\s+\S+\s+remaining'%(self.chan_5ghz) + pat = 'Channel\s+%s\S+\s+(\S+)\s+\S+\s+remaining' % self.chan_5ghz m = re.search(pat, line) - if ( m != None ): + if m: blacklist_time = m.group(1) - logg.info("dfs_channel: {} blacklist_time: {}".format(self.chan_5ghz,blacklist_time)) + logg.info("dfs_channel: {} blacklist_time: {}".format(self.chan_5ghz, blacklist_time)) return blacklist_time - def dfs_waveforms(self,waveform): + @staticmethod + def dfs_waveforms(waveform): # 1, 2, 3, 4, 5, 11, 12, 13, 14, 15, 16 # "FCCO" , "FCC1" , "FCC2" , "FCC3", "FCC4", "FCC5", "ETSI1", "ETSI2", "ETSI3", "ETSI4", "ETSI5", "ETSI6" if waveform == "FCCO": @@ -1443,10 +1595,11 @@ class L3VariableTime(Realm): return width, interval, count - def dfs_get_frequency(self,channel): + @staticmethod + def dfs_get_frequency(channel): # possibly have a dictionary - if channel == "36": + if channel == "36": frequency = "5180000" elif channel == "38": frequency = "5190000" @@ -1511,22 +1664,19 @@ class L3VariableTime(Realm): logg.info("Invalid Channel") exit(1) return frequency - - def dfs_send_radar(self,channel): + def dfs_send_radar(self, channel): # Hard coded to FCC0 - need to support others width_ = "1" interval_ = "1428" count_ = "18" - frequency_ = "5260000" # channel 52 - #sweep_time_ = "1000" sweep_time_ = "0" if_gain_ = "40" bb_gain_ = "20" gain_ = "0" frequency_ = self.dfs_get_frequency(channel) - if frequency_ == None: + if frequency_ is None: logg.info("frequency_ is : {}".format(frequency_)) exit(1) @@ -1537,7 +1687,7 @@ class L3VariableTime(Realm): time.sleep(0.4) # for testing bash - i = child.expect([r'\$',pexpect.TIMEOUT],timeout=2) + i = child.expect([r'\$', pexpect.TIMEOUT], timeout=2) if i == 0: logg.info("i: {} received bash prompt for hackrf command".format(i)) if i == 1: @@ -1574,65 +1724,89 @@ class L3VariableTime(Realm): ################################# # With timeouts ################################# - command_hackRF = "sudo python lf_hackrf.py --pulse_width {} --pulse_interval {} --pulse_count {} --sweep_time {} --freq {} --if_gain {} --bb_gain {} --gain {}".format(width_,interval_,count_,sweep_time_,frequency_,if_gain_,bb_gain_,gain_) + command_hackRF = "sudo python lf_hackrf.py --pulse_width {} --pulse_interval {} --pulse_count {} --sweep_time {} --freq {} --if_gain {} --bb_gain {} --gain {}".format( + width_, interval_, count_, sweep_time_, frequency_, if_gain_, bb_gain_, gain_) logg.info("hackrf command {}".format(command_hackRF)) child.sendline(command_hackRF) time.sleep(0.4) - i = child.expect(['lanforge:',pexpect.TIMEOUT], timeout=2) + i = child.expect(['lanforge:', pexpect.TIMEOUT], timeout=2) if i == 0: - logg.info("lanforge prompt received i: {} before {} after {}".format(i,child.before.decode('utf-8', 'ignore'),child.after.decode('utf-8', 'ignore'))) + logg.info( + "lanforge prompt received i: {} before {} after {}".format(i, child.before.decode('utf-8', 'ignore'), + child.after.decode('utf-8', 'ignore'))) child.sendline('lanforge') time.sleep(0.4) self.dfs_epoch_start = int(time.time()) - j = child.expect(['>>>',pexpect.TIMEOUT], timeout=5) + j = child.expect(['>>>', pexpect.TIMEOUT], timeout=5) if j == 0: - logg.info(">>> prompt received i: {} j: {} before {} after {}".format(i,j,child.before.decode('utf-8', 'ignore'),child.after.decode('utf-8', 'ignore'))) + logg.info(">>> prompt received i: {} j: {} before {} after {}".format(i, j, child.before.decode('utf-8', + 'ignore'), + child.after.decode('utf-8', + 'ignore'))) logg.info("Let the radar run for {}".format(self.radar_duration_seconds)) time.sleep(self.radar_duration_seconds) - child.sendline('s') # stop + child.sendline('s') # stop time.sleep(0.4) - k = child.expect(['>>>',pexpect.TIMEOUT], timeout=2) + k = child.expect(['>>>', pexpect.TIMEOUT], timeout=2) if k == 0: - logg.info(">>> prompt received i: {} j: {} k: {} before {} after {}".format(i,j,k,child.before.decode('utf-8', 'ignore'),child.after.decode('utf-8', 'ignore'))) + logg.info(">>> prompt received i: {} j: {} k: {} before {} after {}".format(i, j, k, + child.before.decode( + 'utf-8', 'ignore'), + child.after.decode( + 'utf-8', 'ignore'))) logg.info("send q - for quit") child.sendline('q') time.sleep(1) if k == 1: - logg.info("TIMEOUT hackrf >>> prompt i: {} j: {} k: {} before {} after {}".format(i,j,k,child.before.decode('utf-8', 'ignore'),child.after)) + logg.info("TIMEOUT hackrf >>> prompt i: {} j: {} k: {} before {} after {}".format(i, j, k, + child.before.decode( + 'utf-8', + 'ignore'), + child.after)) if j == 1: - logg.info("TIMEOUT hackrf >>> prompt i: {} j: {} before {} after {}".format(i,j,child.before.decode('utf-8', 'ignore'),child.after)) + logg.info("TIMEOUT hackrf >>> prompt i: {} j: {} before {} after {}".format(i, j, + child.before.decode('utf-8', + 'ignore'), + child.after)) if i == 1: - logg.info("TIMEOUT lanforge password prompt i: {} before {} after {}".format(i,child.before.decode('utf-8', 'ignore'),child.after)) - + logg.info("TIMEOUT lanforge password prompt i: {} before {} after {}".format(i, child.before.decode('utf-8', + 'ignore'), + child.after)) + time.sleep(2) def ap_cac_verify(self): - if(bool(self.ap_dict)): + if bool(self.ap_dict): pss = "" # will need to verify that timer has timed out on AP - need in results logg.info("DFS channel 5ghz {} done waiting CAC time, 2.4 ghz: {}".format(self.chan_5ghz, self.chan_24ghz)) - logg.info("##################################################################") + logg.info("##################################################################") logg.info("# READ changed to DFS channel {}, running CAC for 60 seconds.".format(self.chan_5ghz)) - logg.info("# READ AP CAC_EXPIRY_EVT: CAC finished on DFS channel ") + logg.info("# READ AP CAC_EXPIRY_EVT: CAC finished on DFS channel ") logg.info("##################################################################") logg.info("ap_dict {}".format(self.ap_dict)) - logg.info("Read AP action: {} ap_scheme: {} ap_ip: {} ap_port: {} ap_user: {} ap_pw: {} ap_tty: {} ap_baud: {}".format("show_log",self.ap_dict['ap_scheme'],self.ap_dict['ap_ip'],self.ap_dict["ap_port"], - self.ap_dict['ap_user'],self.ap_dict['ap_pw'],self.ap_dict['ap_tty'],self.ap_dict['ap_baud'])) + logg.info( + "Read AP action: {} ap_scheme: {} ap_ip: {} ap_port: {} ap_user: {} ap_pw: {} ap_tty: {} ap_baud: {}".format( + "show_log", self.ap_dict['ap_scheme'], self.ap_dict['ap_ip'], self.ap_dict["ap_port"], + self.ap_dict['ap_user'], self.ap_dict['ap_pw'], self.ap_dict['ap_tty'], self.ap_dict['ap_baud'])) try: logg.info("ap_ctl.py: read for CAC timer and CAC_EXPIRY_EVT") # TODO remove position dependence if in tree - ap_info= subprocess.run(["./../ap_ctl.py", "--scheme", self.ap_dict['ap_scheme'], "--prompt", self.ap_dict['ap_prompt'],"--dest", self.ap_dict['ap_ip'], "--port", self.ap_dict["ap_port"], - "--user", self.ap_dict['ap_user'], "--passwd", self.ap_dict['ap_pw'],"--tty", self.ap_dict['ap_tty'],"--baud", self.ap_dict['ap_baud'],"--action", "show_log"],capture_output=True, check=True) - try: + ap_info = subprocess.run( + ["./../ap_ctl.py", "--scheme", self.ap_dict['ap_scheme'], "--prompt", self.ap_dict['ap_prompt'], + "--dest", self.ap_dict['ap_ip'], "--port", self.ap_dict["ap_port"], + "--user", self.ap_dict['ap_user'], "--passwd", self.ap_dict['ap_pw'], "--tty", + self.ap_dict['ap_tty'], "--baud", self.ap_dict['ap_baud'], "--action", "show_log"], + capture_output=True, check=True) + if ap_info: pss = ap_info.stdout.decode('utf-8', 'ignore') - except: - logg.info("ap_info was of type NoneType will set pss empty") - + except subprocess.CalledProcessError as process_error: - logg.info("###################################################") - logg.info("# CHECK IF AP HAS CONNECTION ALREADY ACTIVE") - logg.info("###################################################") - logg.info("# Unable to commicate to AP error code: {} output {}".format(process_error.returncode, process_error.output)) + logg.info("###################################################") + logg.info("# CHECK IF AP HAS CONNECTION ALREADY ACTIVE") + logg.info("###################################################") + logg.info("# Unable to commicate to AP error code: {} output {}".format(process_error.returncode, + process_error.output)) logg.info("###################################################") logg.info(pss) # fine CAC_TIMER @@ -1640,10 +1814,10 @@ class L3VariableTime(Realm): logg.info("ap: CAC_EXPIRY_EVT {}".format(line)) pat = 'changed to DFS channel\s+(\S+),\s+\S+\s+\S+\s+\S+\s+(\S+)' m = re.search(pat, line) - if (m != None): + if m: dfs_channel = m.group(1) cac_time = m.group(2) - logg.info("dfs_channel: {} cac_time: {}".format(dfs_channel,cac_time)) + logg.info("dfs_channel: {} cac_time: {}".format(dfs_channel, cac_time)) logg.info("dfs_cac line: {}".format(line)) self.CAC_TIMER = line break @@ -1653,7 +1827,7 @@ class L3VariableTime(Realm): logg.info("ap: CAC_EXPIRY_EVT {}".format(line)) pat = 'CAC_EXPIRY_EVT:\s+\S+\s+\S+\s+\S+\s\S+\s\S+\s(\S+)' m = re.search(pat, line) - if (m != None): + if m: dfs_channel = m.group(1) logg.info("dfs_channel: {}".format(dfs_channel)) logg.info("dfs_channel line: {}".format(line)) @@ -1661,14 +1835,9 @@ class L3VariableTime(Realm): else: logg.info("ap_dict not set") - def start(self, print_pass=False, print_fail=False): + def start(self, print_pass=False, print_fail=False): best_max_tp_mbps = 0 best_csv_rx_row_data = " " - max_tp_mbps = 0 - csv_rx_row_data = " " - Result = False - - # verify the AP CAC timer and experation self.ap_cac_verify() @@ -1680,13 +1849,14 @@ class L3VariableTime(Realm): logg.info("# INITIAL CHANNEL: {}".format(initial_channel)) logg.info("###########################################") - if (initial_channel != self.chan_5ghz): + if initial_channel != self.chan_5ghz: logg.info("##################################################################") - logg.info("# DFS LOCKOUT? COMMAND LINE CHANNEL: {} NOT EQUAL INITIAL CONTROLLER CHANNEL: {}".format(self.chan_5ghz,initial_channel)) + logg.info("# DFS LOCKOUT? COMMAND LINE CHANNEL: {} NOT EQUAL INITIAL CONTROLLER CHANNEL: {}".format( + self.chan_5ghz, initial_channel)) logg.info("##################################################################") time.sleep(30) - + logg.info("Starting multicast traffic (if any configured)") self.multicast_profile.start_mc(debug_=self.debug) self.multicast_profile.refresh_mc(debug_=self.debug) @@ -1700,7 +1870,7 @@ class L3VariableTime(Realm): end_time = self.parse_time(self.test_duration) + cur_time - logg.info("Monitoring throughput for duration: %s"%(self.test_duration)) + logg.info("Monitoring throughput for duration: %s" % self.test_duration) passes = 0 expected_passes = 0 @@ -1715,8 +1885,8 @@ class L3VariableTime(Realm): while cur_time < interval_time: cur_time = datetime.datetime.now() self.reset_port_check() - if((cur_time > dfs_time) and dfs_radar_sent == False): - if(self.dfs): + if cur_time > dfs_time and not dfs_radar_sent: + if self.dfs: self.dfs_send_radar(initial_channel) dfs_radar_sent = True else: @@ -1725,7 +1895,7 @@ class L3VariableTime(Realm): logg.info("################################################################") time.sleep(1) - + self.epoch_time = int(time.time()) new_rx_values, rx_drop_percent = self.__get_rx_values() @@ -1752,39 +1922,39 @@ class L3VariableTime(Realm): self._fail("FAIL: Not all stations increased traffic", print_fail) old_rx_values = new_rx_values - #percentage dropped not needed for scaling and performance , needed for longevity - #self.__record_rx_dropped_percent(rx_drop_percent) + # percentage dropped not needed for scaling and performance , needed for longevity + # self.__record_rx_dropped_percent(rx_drop_percent) cur_time = datetime.datetime.now() - final_channel = self.read_channel() logg.info("###########################################") logg.info("# FINAL CHANNEL : {}".format(final_channel)) logg.info("###########################################") - dfs_channel_bw20_values = [52, 56, 60, 64, 68, 96, 100, 104, 108, 112, 116, 120, 124 ,128, 132, 136, 140, 144] + dfs_channel_bw20_values = [52, 56, 60, 64, 68, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144] pass_fail = "pass" if int(final_channel) in dfs_channel_bw20_values: logg.info("FAIL: The DFS channel did not change or initial channel was not DFS") pass_fail = "fail" - if (initial_channel != self.chan_5ghz): - logg.info("FAIL: channel set on command line: {} not configured in controller: {} is there a DFS lockout condition".format(self.chan_5ghz,initial_channel)) + if initial_channel != self.chan_5ghz: + logg.info( + "FAIL: channel set on command line: {} not configured in controller: {} is there a DFS lockout condition".format( + self.chan_5ghz, initial_channel)) pass_fail = "fail" blacklist_time = self.read_auto_rf() - best_csv_rx_row_data.append(initial_channel) best_csv_rx_row_data.append(final_channel) best_csv_rx_row_data.append(pass_fail) best_csv_rx_row_data.append(self.CAC_TIMER) best_csv_rx_row_data.append(self.CAC_EXPIRY_EVT) best_csv_rx_row_data.append(blacklist_time) - self.csv_add_row(best_csv_rx_row_data,self.csv_results_writer,self.csv_results) + self.csv_add_row(best_csv_rx_row_data, self.csv_results_writer, self.csv_results) # TO DO check to see if the data is still being transmitted if passes == expected_passes: @@ -1802,12 +1972,10 @@ class L3VariableTime(Realm): self.multicast_profile.cleanup() for station_profile in self.station_profiles: station_profile.cleanup() - - + def csv_generate_column_headers(self): - csv_rx_headers = self.test_keys.copy() - csv_rx_headers.extend - csv_rx_headers.extend(['max_tp_mbps','expected_tp','test_id','epoch_time','time','monitor','pass_fail']) + csv_rx_headers = self.test_keys.copy() + csv_rx_headers.extend(['max_tp_mbps', 'expected_tp', 'test_id', 'epoch_time', 'time', 'monitor', 'pass_fail']) '''for i in range(1,6): csv_rx_headers.append("least_rx_data {}".format(i)) for i in range(1,6): @@ -1816,9 +1984,10 @@ class L3VariableTime(Realm): return csv_rx_headers def csv_generate_column_results_headers(self): - csv_rx_headers = self.test_keys.copy() - csv_rx_headers.extend - csv_rx_headers.extend(['max_tp_mbps','expected_tp','test_id','epoch_time','time','initial_channel','final_channel','pass_fail','cac_timer','cac_expiry_evt','blacklist_time_sec_remaining']) + csv_rx_headers = self.test_keys.copy() + csv_rx_headers.extend( + ['max_tp_mbps', 'expected_tp', 'test_id', 'epoch_time', 'time', 'initial_channel', 'final_channel', + 'pass_fail', 'cac_timer', 'cac_expiry_evt', 'blacklist_time_sec_remaining']) '''for i in range(1,6): csv_rx_headers.append("least_rx_data {}".format(i)) for i in range(1,6): @@ -1826,27 +1995,29 @@ class L3VariableTime(Realm): csv_rx_headers.append("average_rx_data")''' return csv_rx_headers - - def csv_add_column_headers(self,headers): + def csv_add_column_headers(self, headers): if self.csv_file is not None: self.csv_writer.writerow(headers) self.csv_file.flush() - def csv_add_column_headers_results(self,headers): + def csv_add_column_headers_results(self, headers): if self.csv_results is not None: self.csv_results_writer.writerow(headers) - self.csv_results.flush() + self.csv_results.flush() - def csv_validate_list(self, csv_list, length): + @staticmethod + def csv_validate_list(csv_list, length): if len(csv_list) < length: - csv_list = csv_list + [('no data','no data')] * (length - len(csv_list)) + csv_list = csv_list + [('no data', 'no data')] * (length - len(csv_list)) return csv_list - def csv_add_row(self,row,writer,csv_file): # can make two calls eventually + @staticmethod + def csv_add_row(row, writer, csv_file): # can make two calls eventually if csv_file is not None: writer.writerow(row) csv_file.flush() + ######################################### # # AP helper functions @@ -1856,13 +2027,15 @@ class L3VariableTime(Realm): def valid_endp_types(_endp_type): etypes = _endp_type.split() for endp_type in etypes: - valid_endp_type=['lf_udp','lf_udp6','lf_tcp','lf_tcp6','mc_udp','mc_udp6'] + valid_endp_type = ['lf_udp', 'lf_udp6', 'lf_tcp', 'lf_tcp6', 'mc_udp', 'mc_udp6'] if not (str(endp_type) in valid_endp_type): - logg.info('invalid endp_type: %s. Valid types lf_udp, lf_udp6, lf_tcp, lf_tcp6, mc_udp, mc_udp6' % endp_type) + logg.info( + 'invalid endp_type: %s. Valid types lf_udp, lf_udp6, lf_tcp, lf_tcp6, mc_udp, mc_udp6' % endp_type) exit(1) return _endp_type -########################################## + +########################################## # Traffic Generation End ########################################## @@ -1871,17 +2044,15 @@ def main(): global logg lfjson_host = "localhost" lfjson_port = 8080 - endp_types = "lf_udp" - debug_on = False parser = argparse.ArgumentParser( prog='lf_dfs_test.py', - #formatter_class=argparse.RawDescriptionHelpFormatter, + # formatter_class=argparse.RawDescriptionHelpFormatter, formatter_class=argparse.RawTextHelpFormatter, epilog='''\ Scaling and Performance ''', - + description='''\ lf_dfs_test.py: -------------------- @@ -2095,104 +2266,140 @@ Sample script 2/11/2021 # reorder to follow looping - parser.add_argument('-cca' ,'--controller_ap', help='--controller_ap List of APs to test default: Axel',default="APA453.0E7B.CF9C") - parser.add_argument('-ccf' ,'--controller_band', help='--controller_band default a',default="a") + parser.add_argument('-cca', '--controller_ap', help='--controller_ap List of APs to test default: Axel', + default="APA453.0E7B.CF9C") + parser.add_argument('-ccf', '--controller_band', help='--controller_band default a', default="a") # controller wanted 11ax , 11ac, 11n, 11gb - parser.add_argument('-cwm' ,'--controller_wifimode', help='List of of wifi mode to test <11ax 11ac 11n 11gb> default: an',default="an", - choices=[ "auto", "a", "b", "g", "abg", "abgn", "bgn", "bg", "abgnAC", "anAC", "an", "bgnAC", "abgnAX", "bgnAX", "anAX"]) + parser.add_argument('-cwm', '--controller_wifimode', + help='List of of wifi mode to test <11ax 11ac 11n 11gb> default: an', default="an", + choices=["auto", "a", "b", "g", "abg", "abgn", "bgn", "bg", "abgnAC", "anAC", "an", "bgnAC", + "abgnAX", "bgnAX", "anAX"]) - parser.add_argument('-cc5','--controller_chan_5ghz', help='--controller_chan_5ghz <36 40 ...> default 36',default="36") - parser.add_argument('-cc2','--controller_chan_24ghz', help='--controller_chan_24ghz <1 2 ...> default 1',default="1") - parser.add_argument('-ccw','--controller_chan_width', help='--controller_chan_width <20 40 80 160> default: 20',default="20") - parser.add_argument('-cam','--controller_ap_mode', help='--controller_ap_mode default local',default="local") - parser.add_argument('-cps','--controller_packet_size', help='--controller_packet_size List of packet sizes <88 512 1370 1518> default 1518 ',default="1518" ) - parser.add_argument('-ctd','--controller_directions', help='--controller_directions default: upstream downstream ',default="upstream downstream" ) - parser.add_argument('-ccd','--controller_client_density', help='--controller_client_density List of client densities <1 10 20 50 100 200> default 1 ', - default="1" ) - #TODO set str for ones that are str - parser.add_argument('-cde','--controller_data_encryption', help='--controller_data_encryption \"enable disable\"',default="disable" ) - parser.add_argument('-cs' ,'--controller_series', help='--controller_series <9800 | 3504>',default="3504",choices=["9800","3504"]) - parser.add_argument('-ccp','--controller_prompt', type=str,help="controller prompt default WLC",default="WLC") - parser.add_argument('-cas','--controller_ap_slot', type=str,help="AP slot, default 1",default="1") + parser.add_argument('-cc5', '--controller_chan_5ghz', help='--controller_chan_5ghz <36 40 ...> default 36', + default="36") + parser.add_argument('-cc2', '--controller_chan_24ghz', help='--controller_chan_24ghz <1 2 ...> default 1', + default="1") + parser.add_argument('-ccw', '--controller_chan_width', help='--controller_chan_width <20 40 80 160> default: 20', + default="20") + parser.add_argument('-cam', '--controller_ap_mode', help='--controller_ap_mode default local', + default="local") + parser.add_argument('-cps', '--controller_packet_size', + help='--controller_packet_size List of packet sizes <88 512 1370 1518> default 1518 ', + default="1518") + parser.add_argument('-ctd', '--controller_directions', + help='--controller_directions default: upstream downstream ', + default="upstream downstream") + parser.add_argument('-ccd', '--controller_client_density', + help='--controller_client_density List of client densities <1 10 20 50 100 200> default 1 ', + default="1") + # TODO set str for ones that are str + parser.add_argument('-cde', '--controller_data_encryption', help='--controller_data_encryption \"enable disable\"', + default="disable") + parser.add_argument('-cs', '--controller_series', help='--controller_series <9800 | 3504>', default="3504", + choices=["9800", "3504"]) + parser.add_argument('-ccp', '--controller_prompt', type=str, help="controller prompt default WLC", default="WLC") + parser.add_argument('-cas', '--controller_ap_slot', type=str, help="AP slot, default 1", default="1") - parser.add_argument('-cc' ,'--controller_ip', help='--controller_ip default 192.168.100.178',default="192.168.100.178") - parser.add_argument('-cp' ,'--controller_port', help='--controller_port ssh default 22',default="22") - parser.add_argument('-cu' ,'--controller_user', help='--controller_user ',default="admin") - parser.add_argument('-cpw','--controller_passwd', help='--controller_passwd ',default="controller123") - parser.add_argument('-ccs','--controller_scheme', help='--controller_scheme (serial|telnet|ssh): connect via serial, ssh or telnet',default="ssh",choices=["serial","telnet","ssh"]) - parser.add_argument('-cw' ,'--controller_wlan', help='--controller_wlan ',required=True) - parser.add_argument('-cwi','--controller_wlanID', help='--controller_wlanID ',required=True) - parser.add_argument('-cws' ,'--controller_wlanSSID', help='--controller_wlanSSID ',required=True) + parser.add_argument('-cc', '--controller_ip', + help='--controller_ip default 192.168.100.178', + default="192.168.100.178") + parser.add_argument('-cp', '--controller_port', + help='--controller_port ssh default 22', default="22") + parser.add_argument('-cu', '--controller_user', help='--controller_user ', + default="admin") + parser.add_argument('-cpw', '--controller_passwd', help='--controller_passwd ', + default="controller123") + parser.add_argument('-ccs', '--controller_scheme', + help='--controller_scheme (serial|telnet|ssh): connect via serial, ssh or telnet', + default="ssh", choices=["serial", "telnet", "ssh"]) + parser.add_argument('-cw', '--controller_wlan', help='--controller_wlan ', required=True) + parser.add_argument('-cwi', '--controller_wlanID', help='--controller_wlanID ', required=True) + parser.add_argument('-cws', '--controller_wlanSSID', help='--controller_wlanSSID ', required=True) - parser.add_argument('-ctp','--controller_tx_power', help='--controller_tx_power <1 | 2 | 3 | 4 | 5 | 6 | 7 | 8> 1 is highest power default NA NA means no change',default="NA" - ,choices=["1","2","3","4","5","6","7","8","NA"]) - parser.add_argument('-dfs','--controller_dfs', help='--controller_dfs, switch to enable dfs testing', action='store_true') - parser.add_argument('-dft','--controller_dfs_time', help='--controller_dfs_time, time to wait prior to sending radar signal default 30s', default='30s') - parser.add_argument('-hrd','--radar_duration', help='--radar_duration, hack rf radar duration default 5s', default='5s') - parser.add_argument('-cco','--cap_ctl_out', help='--cap_ctl_out , switch the controller controller output will be captured', action='store_true') - + parser.add_argument('-ctp', '--controller_tx_power', + help='--controller_tx_power <1 | 2 | 3 | 4 | 5 | 6 | 7 | 8> 1 is highest power default NA NA means no change', + default="NA", choices=["1", "2", "3", "4", "5", "6", "7", "8", "NA"]) + parser.add_argument('-dfs', '--controller_dfs', help='--controller_dfs, switch to enable dfs testing', + action='store_true') + parser.add_argument('-dft', '--controller_dfs_time', + help='--controller_dfs_time, time to wait prior to sending radar signal default 30s', + default='30s') + parser.add_argument('-hrd', '--radar_duration', help='--radar_duration, hack rf radar duration default 5s', + default='5s') + parser.add_argument('-cco', '--cap_ctl_out', + help='--cap_ctl_out , switch the controller controller output will be captured', + action='store_true') - parser.add_argument('-apr','--amount_ports_to_reset', help='--amount_ports_to_reset \" \" ', default=None) - parser.add_argument('-prs','--port_reset_seconds', help='--ports_reset_seconds \" \" ', default="10 30") + parser.add_argument('-apr', '--amount_ports_to_reset', + help='--amount_ports_to_reset \" \" ', default=None) + parser.add_argument('-prs', '--port_reset_seconds', help='--ports_reset_seconds \" \" ', + default="10 30") - parser.add_argument('-lm','--mgr', help='--mgr ',default='localhost') - parser.add_argument('-d','--test_duration', help='--test_duration example --time 5d (5 days) default: 2m options: number followed by d, h, m or s',default='2m') - parser.add_argument('-pi','--polling_interval', help="--polling_interval ", default='30s') - parser.add_argument('--tos', help='--tos: Support different ToS settings: BK | BE | VI | VO | numeric',default="BE") - parser.add_argument('-db','--debug', help='--debug: Enable debugging',action='store_true') - parser.add_argument('-t', '--endp_type', help='--endp_type example --endp_type \"lf_udp lf_tcp mc_udp\" Default: lf_tcp, options: lf_udp, lf_udp6, lf_tcp, lf_tcp6, mc_udp, mc_udp6', + parser.add_argument('-lm', '--mgr', help='--mgr ', default='localhost') + parser.add_argument('-d', '--test_duration', + help='--test_duration example --time 5d (5 days) default: 2m options: number followed by d, h, m or s', + default='2m') + parser.add_argument('-pi', '--polling_interval', help="--polling_interval ", default='30s') + parser.add_argument('--tos', help='--tos: Support different ToS settings: BK | BE | VI | VO | numeric', + default="BE") + parser.add_argument('-db', '--debug', help='--debug: Enable debugging', action='store_true') + parser.add_argument('-t', '--endp_type', + help='--endp_type example --endp_type \"lf_udp lf_tcp mc_udp\" Default: lf_tcp, options: lf_udp, lf_udp6, lf_tcp, lf_tcp6, mc_udp, mc_udp6', default='lf_tcp', type=valid_endp_types) - parser.add_argument('-u', '--upstream_port', help='--upstream_port example: --upstream_port eth1',default='eth1') - parser.add_argument('-o','--csv_outfile', help="--csv_outfile ", default='dfs') - parser.add_argument("-l", "--log", action='store_true', help="create logfile for messages, default stdout") - parser.add_argument('-c','--csv_output', help="Generate csv output", default=True) + parser.add_argument('-u', '--upstream_port', + help='--upstream_port example: --upstream_port eth1', + default='eth1') + parser.add_argument('-o', '--csv_outfile', help="--csv_outfile ", default='dfs') + parser.add_argument("-l", "--log", action='store_true', help="create logfile for messages, default stdout") + parser.add_argument('-c', '--csv_output', help="Generate csv output", default=True) - #to do add wifimode - parser.add_argument('-r','--radio', action='append', nargs=1, help='--radio \ - \"radio== ssid== ssid_pw== security== wifimode==\" '\ - , required=False) - parser.add_argument('-amr','--side_a_min_bps', help='--side_a_min_bps, station min tx bits per second default 9600', default=9600) - parser.add_argument('-amp','--side_a_min_pdu', help='--side_a_min_pdu , station ipdu size default 1518', default=1518) - parser.add_argument('-bmr','--side_b_min_bps', help='--side_b_min_bps , upstream min tx rate default 256000', default=9600) - parser.add_argument('-bmp','--side_b_min_pdu', help='--side_b_min_pdu , upstream pdu size default 1518', default=1518) + # to do add wifimode + parser.add_argument('-r', '--radio', action='append', nargs=1, help='--radio \ + \"radio== ssid== ssid_pw== security== wifimode==\" ', + required=False) + parser.add_argument('-amr', '--side_a_min_bps', + help='--side_a_min_bps, station min tx bits per second default 9600', default=9600) + parser.add_argument('-amp', '--side_a_min_pdu', help='--side_a_min_pdu , station ipdu size default 1518', + default=1518) + parser.add_argument('-bmr', '--side_b_min_bps', help='--side_b_min_bps , upstream min tx rate default 256000', + default=9600) + parser.add_argument('-bmp', '--side_b_min_pdu', help='--side_b_min_pdu , upstream pdu size default 1518', + default=1518) # AP parameters - parser.add_argument('-api','--ap_info', action='append', nargs=1, type=str, \ - help='(enter 0 if does not apply) --ap_info \"ap_scheme== ap_prompt== ap_ip== ap_port== ap_user== ap_pw== ap_tty==\" ') - #--ap_info "ap_scheme==serial ap_prompt==APA53.0E7B.CF9C ap_ip==0 ap_port==0 ap_user==admin ap_pw==Admin123 ap_tty==/dev/ttyUSB2" + parser.add_argument('-api', '--ap_info', action='append', nargs=1, type=str, + help='(enter 0 if does not apply) --ap_info \"ap_scheme== ap_prompt== ap_ip== ap_port== ap_user== ap_pw== ap_tty==\" ') + # --ap_info "ap_scheme==serial ap_prompt==APA53.0E7B.CF9C ap_ip==0 ap_port==0 ap_user==admin ap_pw==Admin123 ap_tty==/dev/ttyUSB2" '''./lf_dfs_test.py -cc 192.168.100.112 -cu admin -cpw controller123 -cca APA453.0E7B.CF9C -ccf "a" -cwm "auto" -cc5 "36" \ -ccw "20" -ccd "1" -cs "3504" --endp_type 'lf_udp' --upstream_port eth2 --controller_wlan "test_candela" --controller_wlanID 1 \ --controller_wlanSSID "test_candela" --controller_directions "upstream" --controller_prompt "(controller Controller)" \ --radio "radio==1.wiphy0 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto" \ - --ap_info "ap_scheme==serial ap_prompt--APA53.0E7B.EF9C ap_ip==0 ap_port==0 ap_baud==9600 ap_user==admin ap_pw==Admin123 ap_tty==/dev/ttyUSB2" ''' - + --ap_info "ap_scheme==serial ap_prompt--APA53.0E7B.EF9C ap_ip==0 ap_port==0 ap_baud==9600 ap_user==admin ap_pw==Admin123 ap_tty==/dev/ttyUSB2" ''' # Parameters that allow for testing - parser.add_argument('-noc','--no_controller', help='--no_controller no configuration of the controller', action='store_true') - parser.add_argument('-nos','--no_stations', help='--no_stations , no stations', action='store_true') - parser.add_argument('-wto','--wait_timeout', help='--wait_timeout , time to wait for stations to get IP ', default="120") + parser.add_argument('-noc', '--no_controller', help='--no_controller no configuration of the controller', + action='store_true') + parser.add_argument('-nos', '--no_stations', help='--no_stations , no stations', action='store_true') + parser.add_argument('-wto', '--wait_timeout', help='--wait_timeout , time to wait for stations to get IP ', + default="120") args = parser.parse_args() controller_args = args - #logg.info("args: {}".format(args)) debug_on = args.debug ################################################################## # Gather Test Data ################################################################# - + if args.test_duration: test_duration = args.test_duration if args.polling_interval: polling_interval = args.polling_interval - if args.endp_type: - endp_types = args.endp_type - if args.mgr: lfjson_host = args.mgr @@ -2202,21 +2409,21 @@ Sample script 2/11/2021 if args.radio: radios = args.radio - if args.csv_outfile != None: + if args.csv_outfile: current_time = time.strftime("%m_%d_%Y_%H_%M_%S", time.localtime()) - csv_outfile = "{}_{}.csv".format(args.csv_outfile,current_time) - csv_results = "results_{}_{}.csv".format(args.csv_outfile,current_time) + csv_outfile = "{}_{}.csv".format(args.csv_outfile, current_time) + csv_results = "results_{}_{}.csv".format(args.csv_outfile, current_time) print("csv output file : {}".format(csv_outfile)) - + if args.log: - outfile_log = "{}_{}_output_log.log".format(args.outfile,current_time) + outfile_log = "{}_{}_output_log.log".format(args.outfile, current_time) print("output file log: {}".format(outfile_log)) else: outfile_log = "stdout" - print("output file log: {}".format(outfile_log)) + print("output file log: {}".format(outfile_log)) if args.wait_timeout: - wait_timeout = int(args.wait_timeout) + wait_timeout = int(args.wait_timeout) if args.controller_scheme: __scheme = args.controller_scheme @@ -2231,7 +2438,7 @@ Sample script 2/11/2021 __prompt = args.controller_prompt if args.controller_series: - __series = args.controller_series + __series = args.controller_series if args.controller_user: __user = args.controller_user @@ -2243,7 +2450,7 @@ Sample script 2/11/2021 __cap_ctl_out = args.cap_ctl_out else: __cap_ctl_out = False - + if args.controller_ap_slot: __ap_slot = args.controller_ap_slot @@ -2263,27 +2470,26 @@ Sample script 2/11/2021 ap_info = args.ap_info for _ap_info in ap_info: print("ap_info {}".format(_ap_info)) - ap_keys = ['ap_scheme','ap_prompt','ap_ip','ap_port','ap_user','ap_pw', 'ap_tty', 'ap_baud'] - ap_dict = dict(map(lambda x: x.split('=='), str(_ap_info).replace('[','').replace(']','').replace("'","").split())) + ap_keys = ['ap_scheme', 'ap_prompt', 'ap_ip', 'ap_port', 'ap_user', 'ap_pw', 'ap_tty', 'ap_baud'] + ap_dict = dict( + map(lambda x: x.split('=='), str(_ap_info).replace('[', '').replace(']', '').replace("'", "").split())) for key in ap_keys: if key not in ap_dict: - print("missing ap config, for the {}, all these need to be set {} ".format(key,ap_keys)) + print("missing ap config, for the {}, all these need to be set {} ".format(key, ap_keys)) exit(1) print("ap_dict: {}".format(ap_dict)) - console_handler = logging.StreamHandler() formatter = logging.Formatter(FORMAT) logg = logging.getLogger(__name__) logg.setLevel(logging.DEBUG) - file_handler = None - if (args.log): + if args.log: file_handler = logging.FileHandler(outfile_log, "w") file_handler.setLevel(logging.DEBUG) file_handler.setFormatter(formatter) logg.addHandler(file_handler) - logg.addHandler(logging.StreamHandler(sys.stdout)) # allows to logging to file and stderr + logg.addHandler(logging.StreamHandler(sys.stdout)) # allows to logging to file and stderr # if loggin.basicConfig is called this will result in duplicating log entries # logging.basicConfig(format=FORMAT, handlers=[file_handler]) else: @@ -2291,7 +2497,7 @@ Sample script 2/11/2021 logging.basicConfig(format=FORMAT, handlers=[console_handler]) MAX_NUMBER_OF_STATIONS = 200 - + radio_name_list = [] number_of_stations_per_radio_list = [] ssid_list = [] @@ -2299,58 +2505,56 @@ Sample script 2/11/2021 ssid_security_list = [] wifimode_list = [] - #optional radio configuration + # optional radio configuration reset_port_enable_list = [] reset_port_time_min_list = [] reset_port_time_max_list = [] wifi_mode_dict = { - "auto" : "0", - "a" : "1", - "b" : "2", - "g" : "3", - "abg" : "4", - "abgn" : "5", - "bgn" : "6", - "bg" : "7", - "abgnAC" : "8", - "anAC" : "9", - "an" : "10", - "bgnAC" : "11", - "abgnAX" : "12", - "bgnAX" : "13", - "anAX" : "14" - } + "auto": "0", + "a": "1", + "b": "2", + "g": "3", + "abg": "4", + "abgn": "5", + "bgn": "6", + "bg": "7", + "abgnAC": "8", + "anAC": "9", + "an": "10", + "bgnAC": "11", + "abgnAX": "12", + "bgnAX": "13", + "anAX": "14" + } - dfs_channel_bw20_values = [52, 56, 60, 64, 68, 96, 100, 104, 108, 112, 116, 120, 124 ,128, 132, 136, 140, 144] + dfs_channel_bw20_values = [52, 56, 60, 64, 68, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144] - - - - controller_aps = args.controller_ap.split() - controller_bands = args.controller_band.split() - controller_wifimodes = args.controller_wifimode.split() + controller_aps = args.controller_ap.split() + controller_bands = args.controller_band.split() + controller_wifimodes = args.controller_wifimode.split() for mode in controller_wifimodes: if mode in wifi_mode_dict.keys(): pass else: - logg.info("wifimode [{}] not recognised. Please use: auto, a, b, g, abg, abgn, bgn, bg, abgnAC, anAC, an, bgnAC, abgnAX, bgnAX, anAX".format(mode)) + logg.info( + "wifimode [{}] not recognised. Please use: auto, a, b, g, abg, abgn, bgn, bg, abgnAC, anAC, an, bgnAC, abgnAX, bgnAX, anAX".format( + mode)) exit(1) - controller_tx_powers = "3".split() - controller_chan_5ghzs = args.controller_chan_5ghz.split() - controller_chan_24ghzs = args.controller_chan_24ghz.split() - controller_chan_widths = args.controller_chan_width.split() - controller_ap_modes = args.controller_ap_mode.split() - controller_client_densities = args.controller_client_density.split() - controller_packet_types = args.endp_type.split() - controller_directions = args.controller_directions.split() - #controller_directions = "upstream".split() - controller_packet_sizes = args.controller_packet_size.split() - controller_data_encryptions = args.controller_data_encryption.split() - controller_side_a_min_bps = args.side_a_min_bps - controller_side_b_min_bps = args.side_b_min_bps + controller_tx_powers = "3".split() + controller_chan_5ghzs = args.controller_chan_5ghz.split() + controller_chan_24ghzs = args.controller_chan_24ghz.split() + controller_chan_widths = args.controller_chan_width.split() + controller_ap_modes = args.controller_ap_mode.split() + controller_client_densities = args.controller_client_density.split() + controller_packet_types = args.endp_type.split() + controller_directions = args.controller_directions.split() + # controller_directions = "upstream".split() + controller_packet_sizes = args.controller_packet_size.split() + controller_data_encryptions = args.controller_data_encryption.split() + controller_side_a_min_bps = args.side_a_min_bps + controller_side_b_min_bps = args.side_b_min_bps - logg.info(controller_aps) logg.info(controller_bands) logg.info(controller_wifimodes) @@ -2368,18 +2572,17 @@ Sample script 2/11/2021 else: logg.info("AP NO login information") + __ap_set = None + __band_set = None + __chan_width_set = None + __ap_mode_set = None + __tx_power_set = None + __chan_5ghz_set = None + __chan_24ghz_set = None + __csv_started = False - __ap_set = None - __band_set = None - __chan_width_set = None - __ap_mode_set = None - __tx_power_set = None - __chan_5ghz_set = None - __chan_24ghz_set = None - __csv_started = False - - __dfs_channel = None - __cac_timer_time = 0 + __dfs_channel = None + __cac_timer_time = 0 __dfs_chan_switch_to = None for controller_ap in controller_aps: @@ -2387,79 +2590,95 @@ Sample script 2/11/2021 for controller_wifimode in controller_wifimodes: # check for valid frequency and wifi_mode combination put here to simplify logic since all radios do not support all modes # "an anAX anAC abgn bg" - if((controller_band == "a" and controller_wifimode == "bg") or (controller_band == "b" and controller_wifimode == "anAC")): + if ((controller_band == "a" and controller_wifimode == "bg") or ( + controller_band == "b" and controller_wifimode == "anAC")): logg.info("#######################################################################") - logg.info("# Skipping combination controller_band {} controller_wifimode {}".format(controller_band,controller_wifimode)) + logg.info("# Skipping combination controller_band {} controller_wifimode {}".format(controller_band, + controller_wifimode)) logg.info("#######################################################################") - pass # invalid combination continue + pass # invalid combination continue else: # TODO the following - #[(x, y, z) for x in [1,2,3] for y in [4,5,6] for z in [7,8,9] if x != z]: + # [(x, y, z) for x in [1,2,3] for y in [4,5,6] for z in [7,8,9] if x != z]: for controller_tx_power in controller_tx_powers: for controller_chan_5ghz in controller_chan_5ghzs: for controller_chan_24ghz in controller_chan_24ghzs: - for controller_chan_width in controller_chan_widths: #bandwidth + for controller_chan_width in controller_chan_widths: # bandwidth for controller_data_encryption in controller_data_encryptions: for controller_ap_mode in controller_ap_modes: for controller_client_density in controller_client_densities: for controller_packet_type in controller_packet_types: for controller_direction in controller_directions: for controller_packet_size in controller_packet_sizes: - logg.info("#####################################################") - logg.info("# TEST RUNNING , TEST RUNNING ######################") - logg.info("#####################################################") + logg.info( + "#####################################################") + logg.info( + "# TEST RUNNING , TEST RUNNING ######################") + logg.info( + "#####################################################") test_config = "AP=={} Band=={} chan_5ghz=={} chan_24ghz=={} wifi_mode=={} BW=={} encryption=={} ap_mode=={} clients=={} packet_type=={} direction=={} packet_size=={}".format( - controller_ap,controller_band,controller_chan_5ghz,controller_chan_24ghz,controller_wifimode,controller_chan_width,controller_data_encryption,controller_ap_mode,controller_client_density, - controller_packet_type,controller_direction,controller_packet_size) - test_keys = ['AP','Band','wifi_mode','chan_5ghz','chan_24ghz','BW','encryption','ap_mode','clients','packet_type','direction','packet_size'] - logg.info("# controller run settings: {}".format(test_config)) - if(args.no_controller): - logg.info("################################################") + controller_ap, controller_band, controller_chan_5ghz, + controller_chan_24ghz, controller_wifimode, + controller_chan_width, controller_data_encryption, + controller_ap_mode, controller_client_density, + controller_packet_type, controller_direction, + controller_packet_size) + test_keys = ['AP', 'Band', 'wifi_mode', 'chan_5ghz', + 'chan_24ghz', 'BW', 'encryption', 'ap_mode', + 'clients', 'packet_type', 'direction', + 'packet_size'] + logg.info( + "# controller run settings: {}".format(test_config)) + if args.no_controller: + logg.info( + "################################################") logg.info("# NO CONTROLLER SET , TEST MODE") - logg.info("################################################") + logg.info( + "################################################") else: - if( controller_ap != __ap_set or - controller_band != __band_set or - controller_chan_width != __chan_width_set or - controller_ap_mode != __ap_mode_set or - controller_tx_power != __tx_power_set or - controller_chan_5ghz != __chan_5ghz_set or - controller_chan_24ghz != __chan_24ghz_set - ): - logg.info("###############################################") + if (controller_ap != __ap_set or + controller_band != __band_set or + controller_chan_width != __chan_width_set or + controller_ap_mode != __ap_mode_set or + controller_tx_power != __tx_power_set or + controller_chan_5ghz != __chan_5ghz_set or + controller_chan_24ghz != __chan_24ghz_set): + logg.info( + "###############################################") logg.info("# NEW CONTROLLER CONFIG") - logg.info("###############################################") - __ap_set = controller_ap - __band_set = controller_band - __chan_width_set = controller_chan_width - __ap_mode_set = controller_ap_mode - __tx_power_set = controller_tx_power - __chan_5ghz_set = controller_chan_5ghz - __chan_24ghz_set = controller_chan_24ghz - __client_density = controller_client_density + logg.info( + "###############################################") + __ap_set = controller_ap + __band_set = controller_band + __chan_width_set = controller_chan_width + __ap_mode_set = controller_ap_mode + __tx_power_set = controller_tx_power + __chan_5ghz_set = controller_chan_5ghz + __chan_24ghz_set = controller_chan_24ghz + __client_density = controller_client_density controller = CreateCtlr( - _scheme=__scheme, - _port=__port, - _series=__series, - _ctlr=__ctlr, - _prompt=__prompt, - _user=__user, - _passwd=__passwd, - _ap=__ap_set, - _band=__band_set, - _chan_5ghz=__chan_5ghz_set, - _chan_24ghz=__chan_24ghz_set, - _chan_width=__chan_width_set, - _ap_mode=__ap_mode_set, - _tx_power=__tx_power_set, - _client_density=__client_density, - _cap_ctl_out=__cap_ctl_out - ) - #Disable AP + _scheme=__scheme, + _port=__port, + _series=__series, + _ctlr=__ctlr, + _prompt=__prompt, + _user=__user, + _passwd=__passwd, + _ap=__ap_set, + _band=__band_set, + _chan_5ghz=__chan_5ghz_set, + _chan_24ghz=__chan_24ghz_set, + _chan_width=__chan_width_set, + _ap_mode=__ap_mode_set, + _tx_power=__tx_power_set, + _client_density=__client_density, + _cap_ctl_out=__cap_ctl_out + ) + # Disable AP # # Controller Configuration # - #if controller_args.controller_series == "9800": + # if controller_args.controller_series == "9800": # controller_controller_no_loggin_console() pss = controller.controller_show_ap_summary() logg.info("pss {}".format(pss)) @@ -2480,54 +2699,96 @@ Sample script 2/11/2021 controller.controller_create_wlan() controller.controller_set_wireless_tag_policy() controller.controller_enable_wlan() - if controller_band == "a": + if controller_band == "a": controller.controller_enable_network_5ghz() - else: + else: controller.controller_enable_network_24ghz() # clear logs on AP /dev/ttyUSB2 - candelatech - if(bool(ap_dict)): + if bool(ap_dict): logg.info("ap_dict {}".format(ap_dict)) - logg.info("Read AP action: {} ap_scheme: {} ap_ip: {} ap_port: {} ap_user: {} ap_pw: {} ap_tty: {} ap_baud: {}".format("show_log",ap_dict['ap_scheme'],ap_dict['ap_ip'],ap_dict["ap_port"], - ap_dict['ap_user'],ap_dict['ap_pw'],ap_dict['ap_tty'],ap_dict['ap_baud'])) + logg.info( + "Read AP action: {} ap_scheme: {} ap_ip: {} ap_port: {} ap_user: {} ap_pw: {} ap_tty: {} ap_baud: {}".format( + "show_log", ap_dict['ap_scheme'], + ap_dict['ap_ip'], ap_dict["ap_port"], + ap_dict['ap_user'], ap_dict['ap_pw'], + ap_dict['ap_tty'], ap_dict['ap_baud'])) # clear log (AP) try: logg.info("ap_ctl.py: clear log") # TODO remove position dependence if in tree - ap_info= subprocess.run(["./../ap_ctl.py", "--scheme", ap_dict['ap_scheme'], "--prompt", ap_dict['ap_prompt'],"--dest", ap_dict['ap_ip'], "--port", ap_dict["ap_port"], - "--user", ap_dict['ap_user'], "--passwd", ap_dict['ap_pw'],"--tty", ap_dict['ap_tty'],"--baud", ap_dict['ap_baud'],"--action", "clear_log"],capture_output=True, check=True)#stdout=subprocess.PIPE) - try: - pss = ap_info.stdout.decode('utf-8', 'ignore') - except: - logg.info("ap_info was of type NoneType will set pss empty") + ap_info = subprocess.run( + ["./../ap_ctl.py", "--scheme", + ap_dict['ap_scheme'], "--prompt", + ap_dict['ap_prompt'], "--dest", + ap_dict['ap_ip'], "--port", + ap_dict["ap_port"], + "--user", ap_dict['ap_user'], + "--passwd", ap_dict['ap_pw'], "--tty", + ap_dict['ap_tty'], "--baud", + ap_dict['ap_baud'], "--action", + "clear_log"], capture_output=True, + check=True) # stdout=subprocess.PIPE) + if ap_info: + pss = ap_info.stdout.decode('utf-8', + 'ignore') + else: pss = "empty" except subprocess.CalledProcessError as process_error: - logg.info("####################################################################################################") - logg.info("# CHECK IF AP HAS CONNECTION ALREADY ACTIVE") - logg.info("####################################################################################################") - logg.info("####################################################################################################") - logg.info("# Unable to commicate to AP error code: {} output {}".format(process_error.returncode, process_error.output)) - logg.info("####################################################################################################") + logg.info( + "####################################################################################################") + logg.info( + "# CHECK IF AP HAS CONNECTION ALREADY ACTIVE") + logg.info( + "####################################################################################################") + logg.info( + "####################################################################################################") + logg.info( + "# Unable to commicate to AP error code: {} output {}".format( + process_error.returncode, + process_error.output)) + logg.info( + "####################################################################################################") logg.info(pss) # show log (AP) try: logg.info("ap_ctl.py: show log") # TODO remove position dependence if in tree - ap_info= subprocess.run(["./../ap_ctl.py", "--scheme", ap_dict['ap_scheme'], "--prompt", ap_dict['ap_prompt'],"--dest", ap_dict['ap_ip'], "--port", ap_dict["ap_port"], - "--user", ap_dict['ap_user'], "--passwd", ap_dict['ap_pw'],"--tty", ap_dict['ap_tty'],"--baud", ap_dict['ap_baud'],"--action", "show_log"],capture_output=True, check=True) #stdout=subprocess.PIPE - try: - pss = ap_info.stdout.decode('utf-8', 'ignore') - except: - logg.info("ap_info was of type NoneType will set pss empty") + ap_info = subprocess.run( + ["./../ap_ctl.py", "--scheme", + ap_dict['ap_scheme'], "--prompt", + ap_dict['ap_prompt'], "--dest", + ap_dict['ap_ip'], "--port", + ap_dict["ap_port"], + "--user", ap_dict['ap_user'], + "--passwd", ap_dict['ap_pw'], "--tty", + ap_dict['ap_tty'], "--baud", + ap_dict['ap_baud'], "--action", + "show_log"], capture_output=True, + check=True) # stdout=subprocess.PIPE + if ap_info: + pss = ap_info.stdout.decode('utf-8', + 'ignore') + else: + logg.info( + "ap_info was of type NoneType will set pss empty") pss = "empty" except subprocess.CalledProcessError as process_error: - logg.info("####################################################################################################") - logg.info("# CHECK IF AP HAS CONNECTION ALREADY ACTIVE") - logg.info("####################################################################################################") - logg.info("####################################################################################################") - logg.info("# Unable to commicate to AP error code: {} output {}".format(process_error.returncode, process_error.output)) - logg.info("####################################################################################################") + logg.info( + "####################################################################################################") + logg.info( + "# CHECK IF AP HAS CONNECTION ALREADY ACTIVE") + logg.info( + "####################################################################################################") + logg.info( + "####################################################################################################") + logg.info( + "# Unable to commicate to AP error code: {} output {}".format( + process_error.returncode, + process_error.output)) + logg.info( + "####################################################################################################") logg.info(pss) controller.controller_enable_ap() @@ -2535,48 +2796,87 @@ Sample script 2/11/2021 time.sleep(10) # When the AP moves to another DFS channel, the wait time is 60 second # the CAC (Channel Avaiability Check Time) - if (int(__chan_5ghz_set) in dfs_channel_bw20_values): - logg.info("DFS 5ghz channel {} being set wait CAC time 60, 2.4 ghz: {} : ".format(__chan_5ghz_set, __chan_24ghz_set)) + if ( + int(__chan_5ghz_set) in dfs_channel_bw20_values): + logg.info( + "DFS 5ghz channel {} being set wait CAC time 60, 2.4 ghz: {} : ".format( + __chan_5ghz_set, __chan_24ghz_set)) # read AP to verify CAC timer set # will need to use time to verify CAC from AP - need in results - cac_sleeptime = "65" # 65 - logg.info("CAC start sleeptime: {}".format(cac_sleeptime)) + cac_sleeptime = "65" # 65 + logg.info("CAC start sleeptime: {}".format( + cac_sleeptime)) time.sleep(int(cac_sleeptime)) - logg.info("CAC done sleeptime: {}".format(cac_sleeptime)) - if(bool(ap_dict)): + logg.info("CAC done sleeptime: {}".format( + cac_sleeptime)) + if bool(ap_dict): # will need to verify that timer has timed out on AP - need in results - logg.info("DFS channel 5ghz {} done waiting CAC time, 2.4 ghz: {}".format(__chan_5ghz_set, __chan_24ghz_set)) - logg.info("####################################################################################################") - logg.info("# READ changed to DFS channel {}, running CAC for 60 seconds.".format(__chan_5ghz_set)) - logg.info("# READ AP CAC_EXPIRY_EVT: CAC finished on DFS channel ") - logg.info("####################################################################################################") + logg.info( + "DFS channel 5ghz {} done waiting CAC time, 2.4 ghz: {}".format( + __chan_5ghz_set, __chan_24ghz_set)) + logg.info( + "####################################################################################################") + logg.info( + "# READ changed to DFS channel {}, running CAC for 60 seconds.".format( + __chan_5ghz_set)) + logg.info( + "# READ AP CAC_EXPIRY_EVT: CAC finished on DFS channel ") + logg.info( + "####################################################################################################") logg.info("ap_dict {}".format(ap_dict)) - logg.info("Read AP action: {} ap_scheme: {} ap_ip: {} ap_port: {} ap_user: {} ap_pw: {} ap_tty: {} ap_baud: {}".format("show_log",ap_dict['ap_scheme'],ap_dict['ap_ip'],ap_dict["ap_port"], - ap_dict['ap_user'],ap_dict['ap_pw'],ap_dict['ap_tty'],ap_dict['ap_baud'],)) + logg.info( + "Read AP action: {} ap_scheme: {} ap_ip: {} ap_port: {} ap_user: {} ap_pw: {} ap_tty: {} ap_baud: {}".format( + "show_log", ap_dict['ap_scheme'], + ap_dict['ap_ip'], + ap_dict["ap_port"], + ap_dict['ap_user'], + ap_dict['ap_pw'], ap_dict['ap_tty'], + ap_dict['ap_baud'], )) try: - logg.info("ap_ctl.py: read for CAC timer and CAC_EXPIRY_EVT") + logg.info( + "ap_ctl.py: read for CAC timer and CAC_EXPIRY_EVT") # TODO remove position dependence if in tree - #ap_info= subprocess.run(["./../ap_ctl.py", "--scheme", ap_dict['ap_scheme'], "--prompt", ap_dict['ap_prompt'],"--dest", ap_dict['ap_ip'], "--port", ap_dict["ap_port"], + # ap_info= subprocess.run(["./../ap_ctl.py", "--scheme", ap_dict['ap_scheme'], "--prompt", ap_dict['ap_prompt'],"--dest", ap_dict['ap_ip'], "--port", ap_dict["ap_port"], # "--user", ap_dict['ap_user'], "--passwd", ap_dict['ap_pw'],"--tty", ap_dict['ap_tty'],"--baud", ap_dict['ap_baud'],"--action", "cac_expiry_evt"],capture_output=True, check=True) - ap_info= subprocess.run(["./../ap_ctl.py", "--scheme", ap_dict['ap_scheme'], "--prompt", ap_dict['ap_prompt'],"--dest", ap_dict['ap_ip'], "--port", ap_dict["ap_port"], - "--user", ap_dict['ap_user'], "--passwd", ap_dict['ap_pw'],"--tty", ap_dict['ap_tty'],"--baud", ap_dict['ap_baud'],"--action", "show_log"],capture_output=True, check=True) + ap_info = subprocess.run( + ["./../ap_ctl.py", "--scheme", + ap_dict['ap_scheme'], "--prompt", + ap_dict['ap_prompt'], "--dest", + ap_dict['ap_ip'], "--port", + ap_dict["ap_port"], + "--user", ap_dict['ap_user'], + "--passwd", ap_dict['ap_pw'], + "--tty", ap_dict['ap_tty'], + "--baud", ap_dict['ap_baud'], + "--action", "show_log"], + capture_output=True, check=True) - try: - pss = ap_info.stdout.decode('utf-8', 'ignore') - except: - logg.info("ap_info was of type NoneType will set pss empty") + if ap_info: + pss = ap_info.stdout.decode('utf-8', + 'ignore') + else: + logg.info( + "ap_info was of type NoneType will set pss empty") pss = "empty" except subprocess.CalledProcessError as process_error: - logg.info("####################################################################################################") - logg.info("# CHECK IF AP HAS CONNECTION ALREADY ACTIVE") - logg.info("####################################################################################################") + logg.info( + "####################################################################################################") + logg.info( + "# CHECK IF AP HAS CONNECTION ALREADY ACTIVE") + logg.info( + "####################################################################################################") - logg.info("####################################################################################################") - logg.info("# Unable to commicate to AP error code: {} output {}".format(process_error.returncode, process_error.output)) - logg.info("####################################################################################################") + logg.info( + "####################################################################################################") + logg.info( + "# Unable to commicate to AP error code: {} output {}".format( + process_error.returncode, + process_error.output)) + logg.info( + "####################################################################################################") logg.info(pss) # find the DFS Channel @@ -2584,102 +2884,150 @@ Sample script 2/11/2021 logg.info("ap: {}".format(line)) pat = 'CAC_EXPIRY_EVT:\s+\S+\s+\S+\s+\S+\s\S+\s\S+\s(\S+)' m = re.search(pat, line) - if (m != None): + if m: __dfs_channel = m.group(1) - logg.info("__dfs_channel: {}".format(__dfs_channel)) - logg.info("__dfs_channel line: {}".format(line)) + logg.info( + "__dfs_channel: {}".format( + __dfs_channel)) + logg.info( + "__dfs_channel line: {}".format( + line)) break else: - logg.info("Non-DFS 5ghz channel {} being set sleep 30, 2.4 ghz: {} ".format(__chan_5ghz_set, __chan_24ghz_set)) + logg.info( + "Non-DFS 5ghz channel {} being set sleep 30, 2.4 ghz: {} ".format( + __chan_5ghz_set, __chan_24ghz_set)) time.sleep(30) ########################################## # end of controller controller code ########################################## - + else: - logg.info("###############################################") + logg.info( + "###############################################") logg.info("# NO CHANGE TO CONTROLLER CONFIG") - logg.info("###############################################") - logg.info("controller_ap: {} controller_band: {} controller_chan_width: {} controller_ap_mode: {} controller_tx_power: {} controller_chan_5ghz: {} controller_chan_24ghz: {}" - .format(controller_ap,controller_band, controller_chan_width, controller_ap_mode, controller_tx_power, controller_chan_5ghz, controller_chan_24ghz)) - logg.info("__ap_set: {} __band_set: {} __chan_width_set: {} __ap_mode_set: {} __tx_power_set: {} __chan_5ghz_set: {} __chan_24ghz_set: {}" - .format(__ap_set,__band_set, __chan_width_set, __ap_mode_set, __tx_power_set, __chan_5ghz_set, __chan_24ghz_set)) - logg.info("controller_wifi_mode {}".format(controller_wifimode)) + logg.info( + "###############################################") + logg.info( + "controller_ap: {} controller_band: {} controller_chan_width: {} controller_ap_mode: {} controller_tx_power: {} controller_chan_5ghz: {} controller_chan_24ghz: {}".format( + controller_ap, controller_band, + controller_chan_width, + controller_ap_mode, + controller_tx_power, + controller_chan_5ghz, + controller_chan_24ghz)) + logg.info( + "__ap_set: {} __band_set: {} __chan_width_set: {} __ap_mode_set: {} __tx_power_set: {} __chan_5ghz_set: {} __chan_24ghz_set: {}".format( + __ap_set, __band_set, + __chan_width_set, + __ap_mode_set, __tx_power_set, + __chan_5ghz_set, __chan_24ghz_set)) + logg.info("controller_wifi_mode {}".format( + controller_wifimode)) pss = controller.controller_show_ap_summary() - logg.info("controller_show_ap_summary::: pss {}".format(pss)) + logg.info( + "controller_show_ap_summary::: pss {}".format(pss)) if args.controller_series == "9800": searchap = False - cc_mac = "" cc_ch = "" - cc_bw = "" - cc_power = "" - cc_dbm = "" for line in pss.splitlines(): - if (line.startswith("---------")): + if line.startswith("---------"): searchap = True continue # if the pattern changes save the output of the advanced command and re parse https://regex101.com - if (searchap): - pat = "%s\s+(\S+)\s+(%s)\s+\S+\s+\S+\s+(\S+)\s+(\S+)\s+(\S+)\s+dBm\)+\s+(\S+)+\s"%(__ap_set,__ap_slot) + if searchap: + pat = "%s\s+(\S+)\s+(%s)\s+\S+\s+\S+\s+(\S+)\s+(\S+)\s+(\S+)\s+dBm\)+\s+(\S+)+\s" % ( + __ap_set, __ap_slot) m = re.search(pat, line) - if (m != None): - if(m.group(2) == __ap_slot): + if m: + if m.group(2) == __ap_slot: cc_mac = m.group(1) cc_slot = m.group(2) - cc_ch = m.group(6); # (132,136,140,144) + cc_ch = m.group( + 6) # (132,136,140,144) cc_power = m.group(4) - cc_power = cc_power.replace("/", " of ") # spread-sheets turn 1/8 into a date + cc_power = cc_power.replace("/", + " of ") # spread-sheets turn 1/8 into a date cc_dbm = m.group(5) - cc_dbm = cc_dbm.replace("(","") - + cc_dbm = cc_dbm.replace("(", "") + cc_ch_count = cc_ch.count(",") + 1 cc_bw = m.group(3) - logg.info("group 1: {} 2: {} 3: {} 4: {} 5: {} 6: {}".format(m.group(1),m.group(2),m.group(3),m.group(4),m.group(5),m.group(6))) - - logg.info("9800 test_parameters cc_mac: read : {}".format(cc_mac)) - logg.info("9800 test_parameters cc_slot: read : {}".format(cc_slot)) - logg.info("9800 test_parameters cc_count: read : {}".format(cc_ch_count)) - logg.info("9800 test_parameters cc_bw: read : {}".format(cc_bw)) - logg.info("9800 test_parameters cc_power: read : {}".format(cc_power)) - logg.info("9800 test_parameters cc_dbm: read : {}".format(cc_dbm)) - logg.info("9800 test_parameters cc_ch: read : {}".format(cc_ch)) + logg.info( + "group 1: {} 2: {} 3: {} 4: {} 5: {} 6: {}".format( + m.group(1), m.group(2), + m.group(3), m.group(4), + m.group(5), m.group(6))) + + logg.info( + "9800 test_parameters cc_mac: read : {}".format( + cc_mac)) + logg.info( + "9800 test_parameters cc_slot: read : {}".format( + cc_slot)) + logg.info( + "9800 test_parameters cc_count: read : {}".format( + cc_ch_count)) + logg.info( + "9800 test_parameters cc_bw: read : {}".format( + cc_bw)) + logg.info( + "9800 test_parameters cc_power: read : {}".format( + cc_power)) + logg.info( + "9800 test_parameters cc_dbm: read : {}".format( + cc_dbm)) + logg.info( + "9800 test_parameters cc_ch: read : {}".format( + cc_ch)) break else: searchap = False - cc_mac = "" cc_ch = "" - cc_bw = "" - cc_power = "" - cc_dbm = "" - ch_count = "" for line in pss.splitlines(): - if (line.startswith("---------")): + if line.startswith("---------"): searchap = True continue - - if (searchap): - pat = "%s\s+(\S+)\s+\S+\s+\S+\s+\S+\s+(\S+)\s+(\S+)\s+\(\s*(\S+)\s+dBm"%(__ap_set) + + if searchap: + pat = "%s\s+(\S+)\s+\S+\s+\S+\s+\S+\s+(\S+)\s+(\S+)\s+\(\s*(\S+)\s+dBm" % ( + __ap_set) m = re.search(pat, line) - if (m != None): + if m: cc_mac = m.group(1) - cc_ch = m.group(2); # (132,136,140,144) + cc_ch = m.group(2) # (132,136,140,144) cc_power = m.group(3) - cc_power = cc_power.replace("/", " of ", 1) # spread-sheets turn 1/8 into a date + cc_power = cc_power.replace("/", " of ", + 1) # spread-sheets turn 1/8 into a date cc_dbm = m.group(4) - + ch_count = cc_ch.count(",") cc_bw = 20 * (ch_count + 1) - - logg.info("3504 test_parameters cc_mac: read : {}".format(cc_mac)) - logg.info("3504 test_parameters cc_count: read : {}".format(ch_count)) - logg.info("3504 test_parameters cc_bw: read : {}".format(cc_bw)) - logg.info("3504 test_parameters cc_power: read : {}".format(cc_power)) - logg.info("3504 test_parameters cc_dbm: read : {}".format(cc_dbm)) - logg.info("3504 test_parameters cc_ch: read : {}".format(cc_ch)) + + logg.info( + "3504 test_parameters cc_mac: read : {}".format( + cc_mac)) + logg.info( + "3504 test_parameters cc_count: read : {}".format( + ch_count)) + logg.info( + "3504 test_parameters cc_bw: read : {}".format( + cc_bw)) + logg.info( + "3504 test_parameters cc_power: read : {}".format( + cc_power)) + logg.info( + "3504 test_parameters cc_dbm: read : {}".format( + cc_dbm)) + logg.info( + "3504 test_parameters cc_ch: read : {}".format( + cc_ch)) break - if(cc_ch != controller_chan_5ghz): - logg.info("configured channel {} not equal controller channel {}".format(controller_chan_5ghz,cc_ch)) + if cc_ch != controller_chan_5ghz: + logg.info( + "configured channel {} not equal controller channel {}".format( + controller_chan_5ghz, cc_ch)) ###################################################### # end of controller controller code no change to controller ###################################################### @@ -2687,131 +3035,154 @@ Sample script 2/11/2021 radios = args.radio logg.info("radios {}".format(radios)) for radio_ in radios: - radio_keys = ['radio','stations','ssid','ssid_pw','security','wifimode'] - radio_info_dict = dict(map(lambda x: x.split('=='), str(radio_).replace('[','').replace(']','').replace("'","").split())) + radio_keys = ['radio', 'stations', 'ssid', + 'ssid_pw', 'security', 'wifimode'] + radio_info_dict = dict(map(lambda x: x.split('=='), + str(radio_).replace('[', + '').replace( + ']', '').replace("'", + "").split())) logg.info("radio_dict {}".format(radio_info_dict)) for key in radio_keys: if key not in radio_info_dict: - logg.info("missing config, for the {}, all of the following need to be present {} ".format(key,radio_keys)) + logg.info( + "missing config, for the {}, all of the following need to be present {} ".format( + key, radio_keys)) exit(1) radio_name_list.append(radio_info_dict['radio']) ssid_list.append(radio_info_dict['ssid']) - ssid_password_list.append(radio_info_dict['ssid_pw']) - ssid_security_list.append(radio_info_dict['security']) + ssid_password_list.append( + radio_info_dict['ssid_pw']) + ssid_security_list.append( + radio_info_dict['security']) if args.radio: - number_of_stations_per_radio_list.append(radio_info_dict['stations']) - wifimode_list.append(int(wifi_mode_dict[radio_info_dict['wifimode']])) - else: - number_of_stations_per_radio_list.append(radio_info_dict['stations']) - wifimode_list.append(int(wifi_mode_dict[radio_info_dict['wifimode']])) + number_of_stations_per_radio_list.append( + radio_info_dict['stations']) + wifimode_list.append(int(wifi_mode_dict[ + radio_info_dict[ + 'wifimode']])) + else: + number_of_stations_per_radio_list.append( + radio_info_dict['stations']) + wifimode_list.append(int(wifi_mode_dict[ + radio_info_dict[ + 'wifimode']])) optional_radio_reset_keys = ['reset_port_enable'] radio_reset_found = True for key in optional_radio_reset_keys: if key not in radio_info_dict: - #logg.info("port reset test not enabled") + # logg.info("port reset test not enabled") radio_reset_found = False break - + if radio_reset_found: reset_port_enable_list.append(True) - reset_port_time_min_list.append(radio_info_dict['reset_port_time_min']) - reset_port_time_max_list.append(radio_info_dict['reset_port_time_max']) + reset_port_time_min_list.append( + radio_info_dict['reset_port_time_min']) + reset_port_time_max_list.append( + radio_info_dict['reset_port_time_max']) else: reset_port_enable_list.append(False) reset_port_time_min_list.append('0s') reset_port_time_max_list.append('0s') # no stations for testing reconfiguration of the controller - - if(args.no_stations): + if args.no_stations: logg.info("##################################") logg.info("# NO STATIONS") logg.info("##################################") else: index = 0 station_lists = [] - for (radio_name_, number_of_stations_per_radio_) in zip(radio_name_list,number_of_stations_per_radio_list): - number_of_stations = int(number_of_stations_per_radio_) + for (radio_name_, number_of_stations_per_radio_) in zip( + radio_name_list, + number_of_stations_per_radio_list): + number_of_stations = int( + number_of_stations_per_radio_) if number_of_stations > MAX_NUMBER_OF_STATIONS: - logg.info("number of stations per radio exceeded max of : {}".format(MAX_NUMBER_OF_STATIONS)) + logg.info( + "number of stations per radio exceeded max of : {}".format( + MAX_NUMBER_OF_STATIONS)) quit(1) - station_list = LFUtils.portNameSeries(prefix_="sta", start_id_= 1 + index*1000, end_id_= number_of_stations + index*1000, - padding_number_=10000, radio=radio_name_) + station_list = LFUtils.portNameSeries(prefix_="sta", + start_id_=1 + index * 1000, + end_id_=number_of_stations + index * 1000, + padding_number_=10000, + radio=radio_name_) station_lists.append(station_list) index += 1 # Run Traffic Upstream (STA to AP) - if(controller_direction == "upstream"): - side_a_min_bps = controller_side_a_min_bps - side_b_min_bps = 0 - # Run Traffic Downstream (AP to STA) + if controller_direction == "upstream": + side_a_min_bps = controller_side_a_min_bps + side_b_min_bps = 0 + # Run Traffic Downstream (AP to STA) else: - side_a_min_bps = 0 - side_b_min_bps = controller_side_b_min_bps - # current default is to have a values + side_a_min_bps = 0 + side_b_min_bps = controller_side_b_min_bps + # current default is to have a values ip_var_test = L3VariableTime( - args=args, - _dfs=__dfs, - _dfs_time=__dfs_time, - _radar_duration=__radar_duration, - _scheme=__scheme, - _port=__port, - _series=__series, - _ctlr=__ctlr, - _prompt=__prompt, - _user=__user, - _passwd=__passwd, - _ap=__ap_set, - _ap_slot=__ap_slot, - _band=__band_set, - _chan_5ghz=__chan_5ghz_set, - _chan_24ghz=__chan_24ghz_set, - _chan_width=__chan_width_set, - _ap_mode=__ap_mode_set, - _tx_power=__tx_power_set, - _client_density=__client_density, - _cap_ctl_out=__cap_ctl_out, - _ap_dict = ap_dict, - endp_type=controller_packet_type, - tos=args.tos, - side_b=side_b, - radio_name_list=radio_name_list, - number_of_stations_per_radio_list=number_of_stations_per_radio_list, - ssid_list=ssid_list, - ssid_password_list=ssid_password_list, - ssid_security_list=ssid_security_list, - wifimode_list=wifimode_list, - station_lists= station_lists, - name_prefix="LT-", - debug_on=debug_on, - wait_timeout=wait_timeout, - outfile=csv_outfile, - results=csv_results, - test_keys=test_keys, - test_config=test_config, - reset_port_enable_list=reset_port_enable_list, - reset_port_time_min_list=reset_port_time_min_list, - reset_port_time_max_list=reset_port_time_max_list, - csv_started=__csv_started, - side_a_min_bps =side_a_min_bps, - side_a_max_bps =0, - side_a_min_pdu =controller_packet_size, - side_a_max_pdu =0, - side_b_min_bps =side_b_min_bps, - side_b_max_bps =0, - side_b_min_pdu =controller_packet_size, - side_b_max_pdu = 0, - number_template="00", - test_duration=test_duration, - polling_interval= polling_interval, - lfclient_host=lfjson_host, - lfclient_port=lfjson_port) + args=args, + _dfs=__dfs, + _dfs_time=__dfs_time, + _radar_duration=__radar_duration, + _scheme=__scheme, + _port=__port, + _series=__series, + _ctlr=__ctlr, + _prompt=__prompt, + _user=__user, + _passwd=__passwd, + _ap=__ap_set, + _ap_slot=__ap_slot, + _band=__band_set, + _chan_5ghz=__chan_5ghz_set, + _chan_24ghz=__chan_24ghz_set, + _chan_width=__chan_width_set, + _ap_mode=__ap_mode_set, + _tx_power=__tx_power_set, + _client_density=__client_density, + _cap_ctl_out=__cap_ctl_out, + _ap_dict=ap_dict, + endp_type=controller_packet_type, + tos=args.tos, + side_b=side_b, + radio_name_list=radio_name_list, + number_of_stations_per_radio_list=number_of_stations_per_radio_list, + ssid_list=ssid_list, + ssid_password_list=ssid_password_list, + ssid_security_list=ssid_security_list, + wifimode_list=wifimode_list, + station_lists=station_lists, + name_prefix="LT-", + debug_on=debug_on, + wait_timeout=wait_timeout, + outfile=csv_outfile, + results=args.csv_results, + test_keys=test_keys, + test_config=test_config, + reset_port_enable_list=reset_port_enable_list, + reset_port_time_min_list=reset_port_time_min_list, + reset_port_time_max_list=reset_port_time_max_list, + csv_started=__csv_started, + side_a_min_bps=side_a_min_bps, + side_a_min_pdu=controller_packet_size, + side_a_max_pdu=0, + side_b_min_bps=side_b_min_bps, + side_b_min_pdu=controller_packet_size, + side_b_max_pdu=0, + number_template="00", + test_duration=args.test_duration, + polling_interval=args.polling_interval, + lfclient_host=lfjson_host, + lfclient_port=lfjson_port) __csv_started = True ip_var_test.pre_cleanup() ip_var_test.build() if not ip_var_test.passes(): logg.info("build step failed.") logg.info(ip_var_test.get_fail_message()) - exit(1) - client_density = ip_var_test.station_bringup() - #controller.verify_controller(client_density) + exit(1) + ip_var_test.station_bringup() + # controller.verify_controller(client_density) ip_var_test.start(False, False) ip_var_test.stop() if not ip_var_test.passes(): @@ -2825,16 +3196,16 @@ Sample script 2/11/2021 ssid_security_list = [] wifimode_list = [] ip_var_test.cleanup() - if ( args.no_stations): + if args.no_stations: pass else: ip_var_test.passes() logg.info("Test Complete") + if __name__ == "__main__": main() - ''' SAMPLE Command 2/15/2021 ./lf_dfs_test.py -cc 192.168.100.112 -cu admin -cpw Controller123 -cca APA453.0E7B.CF9C -ccf "a" -cwm "auto" -cc5 "52 56 60 64 68 96 100 104 108 112 116 120 124 128 132 136 140 144" -ccw "20" -ccd "1" -cs "3504" --endp_type 'lf_udp' --upstream_port eth2 --controller_wlan "test_candela" --controller_wlanID 1 --controller_wlanSSID "test_candela" --controller_directions "upstream" --controller_prompt "(controller Controller)" --radio "radio==1.wiphy0 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto" @@ -2842,4 +3213,3 @@ SAMPLE Command 2/15/2021 SAMPLE Command with AP (need root if using serial) sudo ./lf_dfs_test.py -cc 192.168.100.112 -cu admin -cpw Controller123 -cca APA453.0E7B.CF9C -ccf "a" -cwm "auto" -cc5 "56" -ccw "20" -ccd "1" -cs "3504" --endp_type 'lf_udp' --upstream_port eth2 --controller_wlan "test_candela" --controller_wlanID 1 --controller_wlanSSID "test_candela" --controller_directions "upstream" --controller_prompt "(controller Controller)" --radio "radio==1.wiphy0 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto" --ap_info "ap_scheme==serial ap_prompt==APA453.0E7B.CF9C ap_ip==0 ap_port==0 ap_user==admin ap_pw==Admin123 ap_tty==/dev/ttyUSB2 ap_baud==9600" --controller_dfs ''' - diff --git a/py-scripts/lf_dut_sta_vap_test.py b/py-scripts/lf_dut_sta_vap_test.py index 3b56a9a1..9ebbb771 100755 --- a/py-scripts/lf_dut_sta_vap_test.py +++ b/py-scripts/lf_dut_sta_vap_test.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -''' +""" This Script has two classes : 1. LoadScenario : It will load the existing saved scenario to the Lanforge (Here used for Loading Bridged VAP) 2. CreateSTA_CX : It will create stations and L3 Cross connects and start them @@ -7,11 +7,11 @@ In this example, Another Lanforge is used as DUT It also have a function : GenerateReport that generates the report in xlsx format as well as it plots the Graph of throughput over time with temperature It also have Plot function that generates a html page that contains the plot - - - Prerequisite + + + Prerequisite Start the Lanforge Manager both Sides - + Installation pip install paramiko pip install bokeh @@ -21,13 +21,12 @@ .\Lexus_Final.py --lf_host 192.168.200.15 --dut_host 192.168.200.18 --dut_radio wiphy1 --lf_radio wiphy1 --num_sta 1 --sta_id 1 --lf_ssid lanforge_ap --dut_ssid lexusap --security open --dut_upstream eth2 --lf_upstream eth1 --protocol lf_udp --min_bps 1000 --max_bps 10000 --time 1 This Script is intended to automate the testing of DUT that has stations as well as AP. To automate the simultaenous testing and check the DUT Temperature -''' +""" import sys import os import importlib import argparse import time -import logging import paramiko as pm from paramiko.ssh_exception import NoValidConnectionsError as exception import xlsxwriter @@ -39,7 +38,6 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) LFUtils = importlib.import_module("py-json.LANforge.LFUtils") @@ -53,58 +51,60 @@ Realm = realm.Realm class Login_DUT: def __init__(self, threadID, name, HOST): - self.threadID = threadID - self.name = name - self.host=HOST - self.USERNAME = "lanforge" - self.PASSWORD = "lanforge" - self.CLIENT= pm.SSHClient() - self.LF1= self.Connect() - self.data_core1=[] - self.data_core2=[] - if self.CLIENT == 0: - exit() - print("Connected to " +HOST+" DUT to Measure the Core Temperature") + self.threadID = threadID + self.name = name + self.host = HOST + self.USERNAME = "lanforge" + self.PASSWORD = "lanforge" + self.CLIENT = pm.SSHClient() + self.LF1 = self.Connect() + self.data_core1 = [] + self.data_core2 = [] + if self.CLIENT == 0: + exit() + print("Connected to " + HOST + " DUT to Measure the Core Temperature") + def run(self): - stdin, stdout, stderr= self.CLIENT.exec_command("sensors") + stdin, stdout, stderr = self.CLIENT.exec_command("sensors") out_lines = stdout.readlines() err_lines = stderr.readlines() - print(out_lines[len(out_lines)-3], out_lines[len(out_lines)-2]) - self.data_core1.append(out_lines[len(out_lines)-3]) - self.data_core2.append(out_lines[len(out_lines)-2]) - + print(out_lines[len(out_lines) - 3], out_lines[len(out_lines) - 2]) + self.data_core1.append(out_lines[len(out_lines) - 3]) + self.data_core2.append(out_lines[len(out_lines) - 2]) def Connect(self): self.CLIENT.load_system_host_keys() self.CLIENT.set_missing_host_key_policy(pm.AutoAddPolicy()) try: - self.CLIENT.connect(self.host, username=self.USERNAME, password=self.PASSWORD,timeout=10) - return None + self.CLIENT.connect(self.host, username=self.USERNAME, password=self.PASSWORD, timeout=10) + return None except exception as error: - self.CLIENT = 0; + self.CLIENT = 0 return None # Class to Load a Scenario that has been Created in Chamber View saved under DB/[Database_Name] class LoadScenario(LFCliBase): - def __init__(self, host, port, db_name, security_debug_on=False, _exit_on_error=False,_exit_on_fail=False): + def __init__(self, host, port, db_name, security_debug_on=False, _exit_on_error=False, _exit_on_fail=False): super().__init__(host, port, _debug=security_debug_on, _exit_on_fail=_exit_on_fail) self.host = host self.port = port - self.json_post("/cli-json/load", { "name": db_name, "action": 'overwrite' }) - print(host+ " : Scenario Loaded...") + self.json_post("/cli-json/load", {"name": db_name, "action": 'overwrite'}) + print(host + " : Scenario Loaded...") time.sleep(2) + # Class to create stations and run L3 Cross connects and run them for given time. It also stores the endpoint names for measuring throughput class CreateSTA_CX(LFCliBase): - - def __init__(self, host, port, radio, num_sta, sta_id, ssid, security, password, upstream, protocol, min_bps, max_bps, security_debug_on=True, _exit_on_error=True, _exit_on_fail=True): + + def __init__(self, host, port, radio, num_sta, sta_id, ssid, security, password, upstream, protocol, min_bps, + max_bps, security_debug_on=True, _exit_on_error=True, _exit_on_fail=True): super().__init__(host, port, _debug=security_debug_on, _exit_on_fail=_exit_on_fail) - + self.host = host self.port = port self.radio = radio - + self.num_sta = num_sta self.sta_id = sta_id @@ -116,25 +116,25 @@ class CreateSTA_CX(LFCliBase): self.upstream = upstream self.protocol = protocol - self.min_bps =min_bps - self.max_bps =max_bps + self.min_bps = min_bps + self.max_bps = max_bps - #Creating a Realm Object + # Creating a Realm Object self.local_realm = Realm(lfclient_host=host, lfclient_port=port) - #Creating Profile Objects + # Creating Profile Objects self.station_profile = self.local_realm.new_station_profile() self.cx_profile = self.local_realm.new_l3_cx_profile() - #Setting CX Name - self.cx_profile.name_prefix_="Connection" + # Setting CX Name + self.cx_profile.name_prefix_ = "Connection" self.cx_names = [] self.sta_list = [] - self.endp=[] - for i in range(sta_id,sta_id+num_sta): + self.endp = [] + for i in range(sta_id, sta_id + num_sta): self.sta_list.append("sta00") - - #portDhcpUpRequest + + # portDhcpUpRequest ''' upstream_dhcp = LFRequest.LFRequest("http://"+str(host)+":"+str(port)+"/"+"/cli-form/set_port") upstream_dhcp.addPostData( LFUtils.portSetDhcpDownRequest(1, upstream)) @@ -147,42 +147,42 @@ class CreateSTA_CX(LFCliBase): def build(self): - #Creating Stations of Given Profile Settings + # Creating Stations of Given Profile Settings self.station_profile.use_security(self.security, self.ssid, passwd=self.password) self.station_profile.create(self.radio, num_stations=self.num_sta, sta_names_=self.sta_list) self.station_profile.admin_up() - #Wait for a while + # Wait for a while time.sleep(15) - - #Setting up the Parameters for CX + + # Setting up the Parameters for CX self.cx_profile.side_a_min_bps = self.min_bps self.cx_profile.side_b_min_bps = self.min_bps self.cx_profile.side_a_max_bps = self.max_bps self.cx_profile.side_b_max_bps = self.max_bps - + self.cx_profile.side_a_min_pdu = 'Auto' self.cx_profile.side_b_min_pdu = 'Auto' self.cx_profile.report_timer = 1000 - self.cx_profile.side_a_min_pkt='Same' - self.cx_profile.side_a_max_pkt='Same' - - #Create Connections of Given Parameters - self.cx_profile.create(self.protocol, side_a="1.1."+self.upstream, side_b=list(self.local_realm.find_ports_like("sta0+"))) + self.cx_profile.side_a_min_pkt = 'Same' + self.cx_profile.side_a_max_pkt = 'Same' + + # Create Connections of Given Parameters + self.cx_profile.create(self.protocol, side_a="1.1." + self.upstream, + side_b=list(self.local_realm.find_ports_like("sta0+"))) time.sleep(15) - + # Getting all the Endpoint Names for measuring Throughput Later for i in self.cx_profile.get_cx_names(): - self.cx_names.append(i) + self.cx_names.append(i) for j in self.cx_names: - x=self.local_realm.json_get("/cx/"+j) + x = self.local_realm.json_get("/cx/" + j) self.endp.append(x.get(j).get('endpoints')[1]) - #print(self.endp) + # print(self.endp) return 0 - def start(self): - #self.station_profile.admin_up() - + # self.station_profile.admin_up() + self.cx_profile.start_cx() time.sleep(5) return 0 @@ -197,75 +197,71 @@ class CreateSTA_CX(LFCliBase): def cleanup(self): # Removing Connections self.local_realm.cleanup_cxe_prefix(self.cx_profile.name_prefix) - + vap = self.local_realm.find_ports_like("vap+") bridges = self.local_realm.find_ports_like("br+") station_map = self.local_realm.find_ports_like("sta+") - #Removing Bridges - for eid,record in bridges.items(): + # Removing Bridges + for eid, record in bridges.items(): self.local_realm.remove_vlan_by_eid(eid) time.sleep(0.03) - #Removing VAP - for eid,record in vap.items(): + # Removing VAP + for eid, record in vap.items(): self.local_realm.remove_vlan_by_eid(eid) time.sleep(0.03) - - #Removing stations - for eid,record in station_map.items(): + + # Removing stations + for eid, record in station_map.items(): self.local_realm.remove_vlan_by_eid(eid) time.sleep(0.03) del_sta_names = [] try: - for eid,value in station_map.items(): + for eid, value in station_map.items(): tname = eid[eid.rfind('.'):] del_sta_names.append(tname) except Exception as x: self.local_realm.error(x) - try: - LFUtils.waitUntilPortsDisappear(base_url=self.local_realm.lfclient_url, port_list=del_sta_names, debug=True) - print("Ports Successfully Cleaned up") - return 0 - except: - print("Ports Successfully Cleaned up") + LFUtils.waitUntilPortsDisappear(base_url=self.local_realm.lfclient_url, port_list=del_sta_names, debug=True) + print("Ports Successfully Cleaned up") time.sleep(5) return 0 # Generates XLSX Report -def GenerateReport(throughput_sta, throughput_vap, core1_temp, core2_temp, duration,name): +def GenerateReport(throughput_sta, throughput_vap, core1_temp, core2_temp, duration, name): workbook = xlsxwriter.Workbook(name) worksheet = workbook.add_worksheet() worksheet.write('A1', 'THROUGHPUT OVER TIME STA CX ') worksheet.write('B1', 'THROUGHPUT OVER TIME VAP ') worksheet.write('C1', 'CORE 0 TEMP') worksheet.write('D1', 'CORE 1 TEMP') - core1=[] - core2=[] - sta_throu=[] - vap_throu=[] - j=2 + core1 = [] + core2 = [] + sta_throu = [] + vap_throu = [] + j = 2 for i in throughput_sta: - sta_throu.append(i/1000000) - worksheet.write('A'+str(j), str(i/1000000)+" Mbps") - j=j+1 - j=2 + sta_throu.append(i / 1000000) + worksheet.write('A' + str(j), str(i / 1000000) + " Mbps") + j = j + 1 + j = 2 for i in throughput_vap: - vap_throu.append(i/1000000) - worksheet.write('B'+str(j), str(i/1000000)+" Mbps") - j=j+1 - j=2 + vap_throu.append(i / 1000000) + worksheet.write('B' + str(j), str(i / 1000000) + " Mbps") + j = j + 1 + j = 2 for i in core1_temp: core1.append(int(str(i).split(':')[1].split('(')[0].split('.')[0].split('+')[1])) - worksheet.write('C'+str(j),str(i).split(':')[1].split('(')[0] ) - j=j+1 - j=2 + worksheet.write('C' + str(j), str(i).split(':')[1].split('(')[0]) + j = j + 1 + j = 2 for i in core2_temp: core2.append(int(str(i).split(':')[1].split('(')[0].split('.')[0].split('+')[1])) - worksheet.write('D'+str(j), str(i).split(':')[1].split('(')[0]) - j=j+1 + worksheet.write('D' + str(j), str(i).split(':')[1].split('(')[0]) + j = j + 1 - Time =[] - for i in range(0,int(duration)*5): + Time = [] + for i in range(0, int(duration) * 5): Time.append(i) plot(sta_throu, vap_throu, core1, core2, Time) workbook.close() @@ -273,169 +269,94 @@ def GenerateReport(throughput_sta, throughput_vap, core1_temp, core2_temp, durat # Plotting Function for Parameters def plot(throughput_sta, throughput_vap, core1_temp, core2_temp, Time): - - s1 = figure() s1.title.text = "WIFI Throughput vs Temperature Plot" s1.xaxis.axis_label = "Time in Seconds" s1.yaxis.axis_label = "Throughput in Mbps" - s1.line( Time, throughput_sta, color='black') - #s1.circle(Time, throughput_sta, color='red') + s1.line(Time, throughput_sta, color='black') + # s1.circle(Time, throughput_sta, color='red') + + s1.line(Time, throughput_vap, color='blue') + # s1.circle(Time, throughput_vap, color='blue') - s1.line( Time, throughput_vap, color='blue') - #s1.circle(Time, throughput_vap, color='blue') - s1.extra_y_ranges = {"Temperature": Range1d(start=0, end=150)} s1.add_layout(LinearAxis(y_range_name="Temperature", axis_label="Temperature in Degree Celsius"), 'right') - + s1.line(Time, core1_temp, y_range_name='Temperature', color='red') - #s1.circle(Time, core1_temp, y_range_name='Temperature', color='red') + # s1.circle(Time, core1_temp, y_range_name='Temperature', color='red') s1.line(Time, core2_temp, y_range_name='Temperature', color='green') - #s1.circle(Time, core2_temp, y_range_name='Temperature', color='blue') + # s1.circle(Time, core2_temp, y_range_name='Temperature', color='blue') show(s1) - + # Creates the Instance for LFCliBase class VAP_Measure(LFCliBase): def __init__(self, lfclient_host, lfclient_port): super().__init__(lfclient_host, lfclient_port) - # main method def main(): - parser = argparse.ArgumentParser( prog='lf_dut_sta_vap_test.py', formatter_class=argparse.RawTextHelpFormatter, description="Test Scenario of DUT Temperature measurement along with simultaneous throughput on VAP as well as stations") - - parser.add_argument("-m", "--manager", type=str, help="Enter the address of Lanforge Manager (By default localhost)") - parser.add_argument("-sc", "--scenario", type=str, help="Enter the Name of the Scenario you want to load (by Default DFLT)") + + parser.add_argument("-m", "--manager", type=str, + help="Enter the address of Lanforge Manager (By default localhost)", default="localhost") + parser.add_argument("-sc", "--scenario", type=str, + help="Enter the Name of the Scenario you want to load (by Default DFLT)") parser.add_argument("-r", "--radio", type=str, help="Enter the radio on which you want to create a station/s on ") - parser.add_argument("-n", "--num_sta", type=int, help="Enter the Number of Stations You want to create") - parser.add_argument("-i", "--sta_id", type=int, help="Enter Station id [for sta001, enter 1]") - parser.add_argument("-ss", "--ssid", type=str, help="Enter the ssid, with which you want to associate your stations (Enter the SSID of DUT AP)") - parser.add_argument("-up", "--upstream", type=str, help="Enter the upstream ethernet port") - parser.add_argument("-sec", "--security", type=str, help="Enter the security type [open, wep, wpa, wpa2]") - parser.add_argument("-p", "--password", type=str, help="Enter the password if security is not open") - parser.add_argument("-pr", "--protocol", type=str, help="Enter the protocol on which you want to run your connections [lf_udp, lf_tcp]") - parser.add_argument("-mn", "--min_mbps", type=str, help="Enter the Minimum Rate") - parser.add_argument("-mx", "--max_mbps", type=str, help="Enter the Maximum Rate") - parser.add_argument("-t", "--duration", type=int, help="Enter the Time for which you want to run test (In Minutes)") - parser.add_argument("-o", "--report_name", type=str, help="Enter the Name of the Output file ('Report.xlsx')") - args = None - - try: - args = parser.parse_args() - # Lanforge Manager IP Address - if (args.manager is None): - manager = "localhost" - if (args.manager is not None): - manager = args.manager - - # Scenario Name - if (args.scenario is not None): - scenario = args.scenario - # Radio Name - if (args.radio is not None): - radio = args.radio - - # Number of Stations - if (args.num_sta is None): - num_sta = 0 - if (args.num_sta is not None): - num_sta = args.num_sta - - # Station ID - if (args.sta_id is None): - sta_id = '0' - if (args.sta_id is not None): - sta_id = args.sta_id - - # SSID - if (args.ssid is not None): - ssid = args.ssid - if (args.ssid is not None): - ssid = args.ssid + parser.add_argument("-n", "--num_sta", type=int, help="Enter the Number of Stations You want to create", default=0) + parser.add_argument("-i", "--sta_id", type=int, help="Enter Station id [for sta001, enter 1]", default=0) + parser.add_argument("-ss", "--ssid", type=str, + help="Enter the ssid, with which you want to associate your stations (Enter the SSID of DUT AP)") + parser.add_argument("-up", "--upstream", type=str, help="Enter the upstream ethernet port", default='br0000') + parser.add_argument("-sec", "--security", type=str, help="Enter the security type [open, wep, wpa, wpa2]", + default='open') + parser.add_argument("-p", "--password", type=str, help="Enter the password if security is not open", + default='[Blank]') + parser.add_argument("-pr", "--protocol", type=str, + help="Enter the protocol on which you want to run your connections [lf_udp, lf_tcp]", + default='lf_udp') + parser.add_argument("-mn", "--min_mbps", type=int, help="Enter the Minimum Rate", default=1000) + parser.add_argument("-mx", "--max_mbps", type=int, help="Enter the Maximum Rate") + parser.add_argument("-t", "--duration", type=int, help="Enter the Time for which you want to run test (In Minutes)", + default=15) + parser.add_argument("-o", "--report_name", type=str, help="Enter the Name of the Output file ('Report.xlsx')", + default='report.xlsx') - # Security (Open by Default) - if (args.security is None): - security = 'open' - if (args.security is not None): - security = args.security + args = parser.parse_args() - # Password (if Security is not Open) - if (args.password is not None): - password = args.password - if (args.password == 'open'): - password = "[Blank]" - if (args.password is None): - password = "[Blank]" - - # Upstream Port (By default br0000) - if (args.upstream is None): - upstream = 'br0000' - if (args.upstream is not None): - upstream = args.upstream - - # Protocol (By Default lf_udp) - if (args.protocol is not None): - protocol = args.protocol - if (args.protocol is None): - protocol = 'lf_udp' - - #Min BPS - if (args.min_mbps is not None): - min_bps = int(args.min_mbps)*1000000 - if (args.min_mbps is None): - min_bps = int(1000)*1000000 - if (args.max_mbps is None ): - max_bps = int(1000)*1000000 + min_bps = args.min_mbps * 1000000 - if (args.min_mbps is not None): - min_bps = int(args.min_mbps)*1000000 - if (args.max_mbps is not None and args.max_mbps != "same"): - max_bps = int(args.max_mbps)*1000000 - if (args.max_mbps is not None and args.max_mbps == "same"): - max_bps = args.min_mbps - if (args.duration is not None): - duration = (args.duration * 60)/5 - if (args.report_name is not None): - report_name = args.report_name - if (args.duration is None): - duration = (1 * 60)/5 - if (args.report_name is None): - report_name = "report.xlsx" - except Exception as e: - logging.exception(e) - - exit(2) - + if args.max_mbps and args.max_mbps != "same": + max_bps = int(args.max_mbps) * 1000000 + if args.max_mbps and args.max_mbps == "same": + max_bps = args.min_mbps - # Start DUT - - #Loading the Scenario on Lanforge_1 (Here Considered as DUT) [Created VAP With SSID 'lexusap' on wiphy0 with eth1 as backhaul] + # Loading the Scenario on Lanforge_1 (Here Considered as DUT) [Created VAP With SSID 'lexusap' on wiphy0 with eth1 as backhaul] Scenario_1 = LoadScenario("192.168.200.18", 8080, "Lexus_DUT") - - dut_traffic_profile = CreateSTA_CX("192.168.200.18", 8080, "wiphy1", 1, 0, 'lanforge_ap', 'open', password, 'br0000', 'lf_udp', min_bps, max_bps) + + dut_traffic_profile = CreateSTA_CX("192.168.200.18", 8080, "wiphy1", 1, 0, 'lanforge_ap', 'open', args.password, + 'br0000', 'lf_udp', min_bps, max_bps) dut_traffic_profile.build() print("DUT All Set... Lets setup Lanforge") - - #Loading the Scenario on Lanforge_2 (Here Considered as LANFORGE Test) [Created VAP With SSID 'lanforge_ap' on wiphy0 with eth2 as backhaul] - + # Loading the Scenario on Lanforge_2 (Here Considered as LANFORGE Test) [Created VAP With SSID 'lanforge_ap' on wiphy0 with eth2 as backhaul] + DB_Lanforge_2 = "LANforge_TEST" - Scenario_2 = LoadScenario(manager, 8080, scenario) - + Scenario_2 = LoadScenario(args.manager, 8080, args.scenario) - lf_traffic_profile = CreateSTA_CX(manager, 8080, radio, num_sta, sta_id, ssid, security, password, upstream, protocol, min_bps, max_bps) + lf_traffic_profile = CreateSTA_CX(args.manager, 8080, args.radio, args.num_sta, args.sta_id, args.ssid, + args.security, args.password, args.upstream, args.protocol, min_bps, + max_bps) lf_traffic_profile.build() print("Lanforge System is All set... Lets start and Measure") @@ -448,21 +369,21 @@ def main(): print("Collecting Throughput Values...") # Object to Measure Throughput at VAP Side - vap_measure_obj = VAP_Measure(manager, 8080) + vap_measure_obj = VAP_Measure(args.manager, 8080) # dut_temp_obj = Login_DUT(1, "Thread-1", "192.168.200.18") - #List for Storing the Total Throughput - throughput_sta =[] - throughput_vap =[] - + # List for Storing the Total Throughput + throughput_sta = [] + throughput_vap = [] + # This loop will get the Data from All the endpoints and sum up to give total Throughput over time - for i in range(0,int(duration)): - temp=0 + for i in range(0, int(args.duration)): + temp = 0 for j in lf_traffic_profile.endp: - y=lf_traffic_profile.local_realm.json_get("/endp/"+j).get('endpoint').get('rx rate') - temp=temp+y + y = lf_traffic_profile.local_realm.json_get("/endp/" + j).get('endpoint').get('rx rate') + temp = temp + y throughput_sta.append(temp) throughput_vap.append(vap_measure_obj.json_get("/port/1/1/vap0000/").get('interface').get('bps rx')) dut_temp_obj.run() @@ -472,10 +393,9 @@ def main(): print(throughput_sta) dut_traffic_profile.cleanup() lf_traffic_profile.cleanup() - GenerateReport(throughput_sta, throughput_vap, dut_temp_obj.data_core1, dut_temp_obj.data_core2, duration, report_name) - + GenerateReport(throughput_sta, throughput_vap, dut_temp_obj.data_core1, dut_temp_obj.data_core2, args.duration, + args.report_name) + - if __name__ == '__main__': main() - diff --git a/py-scripts/lf_ftp.py b/py-scripts/lf_ftp.py index e097b527..4de260eb 100755 --- a/py-scripts/lf_ftp.py +++ b/py-scripts/lf_ftp.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 """ lf_ftp.py will verify that N clients connected on specified band and can simultaneously download/upload some amount of file from FTP server and measuring the time taken by client to download/upload the file. - cli- python3 lf_ftp.py --mgr localhost --mgr_port 8080 --upstream_port eth1 --ssid FTP --security open --passwd BLANK --ap_name WAC505 --ap_ip 192.168.213.90 --bands Both --directions Download --twog_radio wiphy1 --fiveg_radio wiphy0 --file_size 2MB --num_stations 40 --Both_duration 1 --traffic_duration 2 --ssh_port 22_ + cli- ./lf_ftp.py --ssid --passwd --file_sizes 2MB --fiveg_duration 4 --mgr 192.168.1.101 --traffic_duration 2 --security wpa2 --bands 5G --fiveg_radio wiphy1 --directions Download Upload Copyright 2021 Candela Technologies Inc License: Free to distribute and modify. LANforge systems must be licensed. """ @@ -11,12 +12,13 @@ from datetime import datetime import time import os import matplotlib.patches as mpatches +import pandas as pd if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - + sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) LFUtils = importlib.import_module("py-json.LANforge.LFUtils") @@ -26,13 +28,14 @@ realm = importlib.import_module("py-json.realm") Realm = realm.Realm lf_report = importlib.import_module("py-scripts.lf_report") lf_graph = importlib.import_module("py-scripts.lf_graph") +lf_kpi_csv = importlib.import_module("py-scripts.lf_kpi_csv") class FtpTest(LFCliBase): def __init__(self, lfclient_host="localhost", lfclient_port=8080, sta_prefix="sta", start_id=0, num_sta=None, dut_ssid=None, dut_security=None, dut_passwd=None, file_size=None, band=None, twog_radio=None, fiveg_radio=None, upstream="eth1", _debug_on=False, _exit_on_error=False, _exit_on_fail=False, - direction=None, duration=None, traffic_duration=None, ssh_port=None): + direction=None, duration=None, traffic_duration=None, ssh_port=None, kpi_csv=None): super().__init__(lfclient_host, lfclient_port, _debug=_debug_on, _exit_on_fail=_exit_on_fail) print("Test is about to start") self.host = lfclient_host @@ -47,6 +50,7 @@ class FtpTest(LFCliBase): self.password = dut_passwd self.requests_per_ten = 1 self.band = band + self.kpi_csv = kpi_csv self.file_size = file_size self.direction = direction self.twog_radio = twog_radio @@ -301,7 +305,7 @@ class FtpTest(LFCliBase): for i in range(self.num_sta): list_of_time.append(0) #running layer 4 traffic upto user given time - while str(datetime.datetime.now() - time1) <= self.traffic_duration: + while str(datetime.now() - time1) <= self.traffic_duration: if list_of_time.count(0) == 0: break @@ -309,11 +313,11 @@ class FtpTest(LFCliBase): # run script upto given time if counter == 0: - if str(datetime.datetime.now() - time1) >= self.duration: + if str(datetime.now() - time1) >= self.duration: counter = counter + 1 break else: - if str(datetime.datetime.now() - time1) >= self.traffic_duration: + if str(datetime.now() - time1) >= self.traffic_duration: break for i in range(self.num_sta): @@ -321,9 +325,9 @@ class FtpTest(LFCliBase): # reading uc-avg data in json format uc_avg = self.json_get("layer4/list?fields=uc-avg") - if data['endpoint'][i][data2[i]]['bytes-rd'] <= self.file_size_bytes: + if int(data['endpoint'][i][data2[i]]['bytes-rd']) <= self.file_size_bytes: data = self.json_get("layer4/list?fields=bytes-rd") - if data['endpoint'][i][data2[i]]['bytes-rd'] >= self.file_size_bytes: + if int(data['endpoint'][i][data2[i]]['bytes-rd']) >= self.file_size_bytes: list1.append(i) if list1.count(i) == 1: list2.append(i) @@ -614,7 +618,7 @@ class FtpTest(LFCliBase): def bar_graph(self, x_axis, image_name, dataset, color, labels, x_axis_name, y_axis_name,handles, ncol, box, fontsize): '''This Method will plot bar graph''' - graph = lf_bar_graph(_data_set=dataset, + graph = lf_graph.lf_bar_graph(_data_set=dataset, _xaxis_name=x_axis_name, _yaxis_name=y_axis_name, _xaxis_categories=x_axis, @@ -660,7 +664,7 @@ class FtpTest(LFCliBase): def generate_report(self, ftp_data, date,test_setup_info, input_setup_info): '''Method for generate the report''' - self.report = lf_report(_results_dir_name="ftp_test", _output_html="ftp_test.html", _output_pdf="ftp_test.pdf") + self.report = lf_report.lf_report(_results_dir_name="ftp_test", _output_html="ftp_test.html", _output_pdf="ftp_test.pdf") self.report.set_title("FTP Test") self.report.set_date(date) self.report.build_banner() @@ -703,7 +707,14 @@ def main(): parser = argparse.ArgumentParser( prog='lf_ftp.py', formatter_class=argparse.RawTextHelpFormatter, - description="FTP Test Script") + description='''\ +--------------------------- +FTP Test Script - lf_ftp.py +--------------------------- +CLI Example: +./lf_ftp.py --ssid --passwd --file_sizes 2MB --fiveg_duration 4 --mgr 192.168.1.101 --traffic_duration 2 --security wpa2 --bands 5G --fiveg_radio wiphy1 --directions Download Upload +--------------------------- + ''') parser.add_argument('--mgr', help='hostname for where LANforge GUI is running', default='localhost') parser.add_argument('--mgr_port', help='port LANforge GUI HTTP service is running on', default=8080) parser.add_argument('--upstream_port', help='non-station port that generates traffic: eg: eth1', default='eth1') @@ -716,7 +727,7 @@ def main(): parser.add_argument('--fiveg_radio', type=str, help='specify radio for 5G client', default='wiphy0') parser.add_argument('--twog_duration', nargs="+", help='Pass and Fail duration for 2.4G band in minutes') parser.add_argument('--fiveg_duration', nargs="+", help='Pass and Fail duration for 5G band in minutes') - parser.add_argument('--Both_duration', nargs="+", help='Pass and Fail duration for Both band in minutes') + parser.add_argument('--both_duration', nargs="+", help='Pass and Fail duration for Both band in minutes') parser.add_argument('--traffic_duration', type=int, help='duration for layer 4 traffic running') parser.add_argument('--ssh_port', type=int, help="specify the shh port eg 22", default=22) @@ -732,10 +743,10 @@ def main(): args = parser.parse_args() # 1st time stamp for test duration - time_stamp1 = datetime.datetime.now() + time_stamp1 = datetime.now() # use for creating ftp_test dictionary - iteraration_num = 0 + interation_num = 0 # empty dictionary for whole test data ftp_data = {} @@ -759,12 +770,12 @@ def main(): index = list(args.file_sizes).index(size) duration = args.fiveg_duration[index] else: - if len(args.file_sizes) is not len(args.Both_duration): + if len(args.file_sizes) is not len(args.both_duration): raise Exception("Give proper Pass or Fail duration for 5G band") for size in args.file_sizes: if size == file_size: index = list(args.file_sizes).index(size) - duration = args.Both_duration[index] + duration = args.both_duration[index] if duration.isdigit(): duration = int(duration) else: @@ -794,7 +805,7 @@ def main(): ssh_port=args.ssh_port ) - iteraration_num = iteraration_num + 1 + interation_num = interation_num + 1 obj.file_create() obj.set_values() obj.precleanup() @@ -804,7 +815,7 @@ def main(): exit(1) # First time stamp - time1 = datetime.datetime.now() + time1 = datetime.now() obj.start(False, False) @@ -815,19 +826,19 @@ def main(): pass_fail = obj.pass_fail_check(time_list) # dictionary of whole data - ftp_data[iteraration_num] = obj.ftp_test_data(time_list, pass_fail, args.bands, args.file_sizes, + ftp_data[interation_num] = obj.ftp_test_data(time_list, pass_fail, args.bands, args.file_sizes, args.directions, args.num_stations) obj.stop() obj.postcleanup() # 2nd time stamp for test duration - time_stamp2 = datetime.datetime.now() + time_stamp2 = datetime.now() # total time for test duration test_duration = str(time_stamp2 - time_stamp1)[:-7] - date = str(datetime.datetime.now()).split(",")[0].replace(" ", "-").split(".")[0] + date = str(datetime.now()).split(",")[0].replace(" ", "-").split(".")[0] #print(ftp_data) diff --git a/py-scripts/lf_graph.py b/py-scripts/lf_graph.py index 9704c305..58a2d194 100755 --- a/py-scripts/lf_graph.py +++ b/py-scripts/lf_graph.py @@ -24,39 +24,42 @@ import matplotlib.pyplot as plt import numpy as np import pdfkit from matplotlib.colors import ListedColormap +import argparse - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lf_csv = importlib.import_module("py-scripts.lf_csv") lf_csv = lf_csv.lf_csv -# internal candela references included during intial phases, to be deleted at future date +# internal candela references included during intial phases, to be deleted +# at future date # graph reporting classes -class lf_bar_graph(): - def __init__(self, _data_set=[[30.4, 55.3, 69.2, 37.1], [45.1, 67.2, 34.3, 22.4], [22.5, 45.6, 12.7, 34.8]], + + +class lf_bar_graph: + def __init__(self, _data_set=None, _xaxis_name="x-axis", _yaxis_name="y-axis", - _xaxis_categories=[1, 2, 3, 4], - _xaxis_label=["a", "b", "c", "d"], + _xaxis_categories=None, + _xaxis_label=None, _graph_title="", _title_size=16, _graph_image_name="image_name", - _label=["bi-downlink", "bi-uplink", 'uplink'], + _label=None, _color=None, _bar_width=0.25, _color_edge='grey', _font_weight='bold', - _color_name=['lightcoral', 'darkgrey', 'r', 'g', 'b', 'y'], + _color_name=None, _figsize=(10, 5), _show_bar_value=False, _xaxis_step=1, - _xticks_font = None, - _xaxis_value_location = 0, + _xticks_font=None, + _xaxis_value_location=0, _text_font=None, _text_rotation=None, - _grp_title = "", + _grp_title="", _legend_handles=None, _legend_loc="best", _legend_box=None, @@ -65,6 +68,16 @@ class lf_bar_graph(): _dpi=96, _enable_csv=False): + if _data_set is None: + _data_set = [[30.4, 55.3, 69.2, 37.1], [45.1, 67.2, 34.3, 22.4], [22.5, 45.6, 12.7, 34.8]] + if _xaxis_categories is None: + _xaxis_categories = [1, 2, 3, 4] + if _xaxis_label is None: + _xaxis_label = ["a", "b", "c", "d"] + if _label is None: + _label = ["bi-downlink", "bi-uplink", 'uplink'] + if _color_name is None: + _color_name = ['lightcoral', 'darkgrey', 'r', 'g', 'b', 'y'] self.data_set = _data_set self.xaxis_name = _xaxis_name self.yaxis_name = _yaxis_name @@ -99,20 +112,20 @@ class lf_bar_graph(): if self.color is None: i = 0 self.color = [] - for col in self.data_set: + for _ in self.data_set: self.color.append(self.color_name[i]) i = i + 1 - fig = plt.subplots(figsize=self.figsize) + plt.subplots(figsize=self.figsize) i = 0 - def show_value(rects): - for rect in rects: + def show_value(rectangles): + for rect in rectangles: h = rect.get_height() plt.text(rect.get_x() + rect.get_width() / 2., h, h, ha='center', va='bottom', rotation=self.text_rotation, fontsize=self.text_font) - for data in self.data_set: + for _ in self.data_set: if i > 0: br = br1 br2 = [x + self.bar_width for x in br] @@ -132,14 +145,22 @@ class lf_bar_graph(): plt.xlabel(self.xaxis_name, fontweight='bold', fontsize=15) plt.ylabel(self.yaxis_name, fontweight='bold', fontsize=15) if self.xaxis_categories[0] == 0: - plt.xticks(np.arange(0, len(self.xaxis_categories), step=self.xaxis_step),fontsize = self.xticks_font) + plt.xticks(np.arange(0, + len(self.xaxis_categories), + step=self.xaxis_step), + fontsize=self.xticks_font) else: plt.xticks([i + self._xaxis_value_location for i in np.arange(0, len(self.data_set[0]), step=self.xaxis_step)], - self.xaxis_categories, fontsize=self.xticks_font) - plt.legend(handles=self.legend_handles, loc=self.legend_loc, bbox_to_anchor=self.legend_box, ncol=self.legend_ncol, fontsize=self.legend_fontsize) + self.xaxis_categories, fontsize=self.xticks_font) + plt.legend( + handles=self.legend_handles, + loc=self.legend_loc, + bbox_to_anchor=self.legend_box, + ncol=self.legend_ncol, + fontsize=self.legend_fontsize) plt.suptitle(self.title, fontsize=self.title_size) plt.title(self.grp_title) - fig = plt.gcf() + plt.gcf() plt.savefig("%s.png" % self.graph_image_name, dpi=96) plt.close() print("{}.png".format(self.graph_image_name)) @@ -155,25 +176,32 @@ class lf_bar_graph(): self.lf_csv.filename = f"{self.graph_image_name}.csv" self.lf_csv.generate_csv() else: - raise ValueError("Length and x-axis values and y-axis values should be same.") + raise ValueError( + "Length and x-axis values and y-axis values should be same.") else: print("No Dataset Found") print("{}.csv".format(self.graph_image_name)) return "%s.png" % self.graph_image_name -class lf_scatter_graph(): +class lf_scatter_graph: def __init__(self, - _x_data_set=["sta0 ", "sta1", "sta2", "sta3"], - _y_data_set=[[30, 55, 69, 37]], + _x_data_set=None, + _y_data_set=None, _values=None, _xaxis_name="x-axis", _yaxis_name="y-axis", - _label=["num1", "num2"], + _label=None, _graph_image_name="image_name1", - _color=["r", "y"], + _color=None, _figsize=(9, 4), _enable_csv=True): + if _x_data_set is None: + _x_data_set = ["sta0 ", "sta1", "sta2", "sta3"] + if _y_data_set is None: + _y_data_set = [[30, 55, 69, 37]] + if _label is None: + _label = ["num1", "num2"] self.x_data_set = _x_data_set self.y_data_set = _y_data_set self.xaxis_name = _xaxis_name @@ -188,20 +216,38 @@ class lf_scatter_graph(): def build_scatter_graph(self): if self.color is None: - self.color = ["orchid", "lime", "aquamarine", "royalblue", "darkgray", "maroon"] - fig = plt.subplots(figsize=self.figsize) + self.color = [ + "orchid", + "lime", + "aquamarine", + "royalblue", + "darkgray", + "maroon"] + plt.subplots(figsize=self.figsize) if self.values is None: - plt.scatter(self.x_data_set, self.y_data_set[0], color=self.color[0], label=self.label[0]) + plt.scatter( + self.x_data_set, + self.y_data_set[0], + color=self.color[0], + label=self.label[0]) if len(self.y_data_set) > 1: for i in range(1, len(self.y_data_set)): - plt.scatter(self.x_data_set, self.y_data_set[i], color=self.color[i], label=self.label[i]) + plt.scatter( + self.x_data_set, + self.y_data_set[i], + color=self.color[i], + label=self.label[i]) plt.xlabel(self.xaxis_name, fontweight='bold', fontsize=15) plt.ylabel(self.yaxis_name, fontweight='bold', fontsize=15) plt.gcf().autofmt_xdate() plt.legend() else: colours = ListedColormap(self.color) - scatter = plt.scatter(self.x_data_set, self.y_data_set, c=self.values, cmap=colours) + scatter = plt.scatter( + self.x_data_set, + self.y_data_set, + c=self.values, + cmap=colours) plt.xlabel(self.xaxis_name, fontweight='bold', fontsize=15) plt.ylabel(self.yaxis_name, fontweight='bold', fontsize=15) plt.gcf().autofmt_xdate() @@ -218,16 +264,20 @@ class lf_scatter_graph(): return "%s.png" % self.graph_image_name -class lf_stacked_graph(): +class lf_stacked_graph: def __init__(self, - _data_set=[[1, 2, 3, 4], [1, 1, 1, 1], [1, 1, 1, 1]], + _data_set=None, _xaxis_name="Stations", _yaxis_name="Numbers", - _label=['Success', 'Fail'], + _label=None, _graph_image_name="image_name2", - _color=["b", "g"], + _color=None, _figsize=(9, 4), _enable_csv=True): + if _data_set is None: + _data_set = [[1, 2, 3, 4], [1, 1, 1, 1], [1, 1, 1, 1]] + if _label is None: + _label = ['Success', 'Fail'] self.data_set = _data_set # [x_axis,y1_axis,y2_axis] self.xaxis_name = _xaxis_name self.yaxis_name = _yaxis_name @@ -239,11 +289,21 @@ class lf_stacked_graph(): self.lf_csv = lf_csv() def build_stacked_graph(self): - fig = plt.subplots(figsize=self.figsize) + plt.subplots(figsize=self.figsize) if self.color is None: - self.color = ["darkred", "tomato", "springgreen", "skyblue", "indigo", "plum"] + self.color = [ + "darkred", + "tomato", + "springgreen", + "skyblue", + "indigo", + "plum"] plt.bar(self.data_set[0], self.data_set[1], color=self.color[0]) - plt.bar(self.data_set[0], self.data_set[2], bottom=self.data_set[1], color=self.color[1]) + plt.bar( + self.data_set[0], + self.data_set[2], + bottom=self.data_set[1], + color=self.color[1]) if len(self.data_set) > 3: for i in range(3, len(self.data_set)): plt.bar(self.data_set[0], self.data_set[i], @@ -251,7 +311,7 @@ class lf_stacked_graph(): plt.xlabel(self.xaxis_name) plt.ylabel(self.yaxis_name) plt.legend(self.label) - plt.savefig("%s.png" % (self.graph_image_name), dpi=96) + plt.savefig("%s.png" % self.graph_image_name, dpi=96) plt.close() print("{}.png".format(self.graph_image_name)) if self.enable_csv: @@ -259,23 +319,31 @@ class lf_stacked_graph(): self.lf_csv.rows = self.data_set self.lf_csv.filename = f"{self.graph_image_name}.csv" self.lf_csv.generate_csv() - return "%s.png" % (self.graph_image_name) + return "%s.png" % self.graph_image_name -class lf_horizontal_stacked_graph(): +class lf_horizontal_stacked_graph: def __init__(self, _seg=2, _yaxis_set=('A', 'B'), - _xaxis_set1=[12, 0, 0, 16, 15], - _xaxis_set2=[23, 34, 23, 0], + _xaxis_set1=None, + _xaxis_set2=None, _unit="%", _xaxis_name="Stations", - _label=['Success', 'Fail'], + _label=None, _graph_image_name="image_name3", - _color=["success", "Fail"], + _color=None, _figsize=(9, 4), _disable_xaxis=False, _enable_csv=True): + if _xaxis_set1 is None: + _xaxis_set1 = [12, 0, 0, 16, 15] + if _xaxis_set2 is None: + _xaxis_set2 = [23, 34, 23, 0] + if _label is None: + _label = ['Success', 'Fail'] + if _color is None: + _color = ["success", "Fail"] self.unit = _unit self.seg = _seg self.xaxis_set1 = _xaxis_set1 @@ -303,8 +371,19 @@ class lf_horizontal_stacked_graph(): ind = np.arange(n) + .15 width = 0.3 - rects1 = plt.barh(ind, values1, width, color=self.color[0], label=self.label[0]) - rects2 = plt.barh(ind, values2, width, left=sumzip(values1), color=self.color[1], label=self.label[1]) + plt.barh( + ind, + values1, + width, + color=self.color[0], + label=self.label[0]) + plt.barh( + ind, + values2, + width, + left=sumzip(values1), + color=self.color[1], + label=self.label[1]) extra_space = 0.15 ax.set_yticks(ind + width - extra_space) @@ -326,7 +405,12 @@ class lf_horizontal_stacked_graph(): ax.spines['top'].set_visible(False) ax.legend(loc='upper right') if self.disable_xaxis: - plt.tick_params(axis='x', which='both', bottom=False, top=False, labelbottom=False) # disable x-axis + plt.tick_params( + axis='x', + which='both', + bottom=False, + top=False, + labelbottom=False) # disable x-axis plt.savefig("%s.png" % self.graph_image_name, dpi=96) plt.close() print("{}.png".format(self.graph_image_name)) @@ -338,21 +422,21 @@ class lf_horizontal_stacked_graph(): return "%s.png" % self.graph_image_name -class lf_line_graph(): - def __init__(self,_data_set=[[30.4, 55.3, 69.2, 37.1], [45.1, 67.2, 34.3, 22.4], [22.5, 45.6, 12.7, 34.8]], +class lf_line_graph: + def __init__(self, _data_set=None, _xaxis_name="x-axis", _yaxis_name="y-axis", - _xaxis_categories=[1, 2, 3, 4, 5], - _xaxis_label=["a", "b", "c", "d", "e"], + _xaxis_categories=None, + _xaxis_label=None, _graph_title="", _title_size=16, _graph_image_name="image_name", - _label=["bi-downlink", "bi-uplink", 'uplink'], + _label=None, _font_weight='bold', - _color=['forestgreen', 'c', 'r', 'g', 'b', 'p'], + _color=None, _figsize=(10, 5), - _xaxis_step = 5, - _xticks_font = None, + _xaxis_step=5, + _xticks_font=None, _text_font=None, _legend_handles=None, _legend_loc="best", @@ -362,6 +446,16 @@ class lf_line_graph(): _marker=None, _dpi=96, _enable_csv=False): + if _data_set is None: + _data_set = [[30.4, 55.3, 69.2, 37.1], [45.1, 67.2, 34.3, 22.4], [22.5, 45.6, 12.7, 34.8]] + if _xaxis_categories is None: + _xaxis_categories = [1, 2, 3, 4, 5] + if _xaxis_label is None: + _xaxis_label = ["a", "b", "c", "d", "e"] + if _label is None: + _label = ["bi-downlink", "bi-uplink", 'uplink'] + if _color is None: + _color = ['forestgreen', 'c', 'r', 'g', 'b', 'p'] self.data_set = _data_set self.xaxis_name = _xaxis_name self.yaxis_name = _yaxis_name @@ -387,17 +481,27 @@ class lf_line_graph(): self.legend_fontsize = _legend_fontsize def build_line_graph(self): - fig = plt.subplots(figsize=self.figsize) + plt.subplots(figsize=self.figsize) i = 0 for data in self.data_set: - plt.plot(self.xaxis_categories, data, color=self.color[i], label=self.label[i], marker = self.marker) + plt.plot( + self.xaxis_categories, + data, + color=self.color[i], + label=self.label[i], + marker=self.marker) i += 1 plt.xlabel(self.xaxis_name, fontweight='bold', fontsize=15) plt.ylabel(self.yaxis_name, fontweight='bold', fontsize=15) - plt.legend(handles=self.legend_handles, loc=self.legend_loc, bbox_to_anchor=self.legend_box, ncol=self.legend_ncol, fontsize=self.legend_fontsize) + plt.legend( + handles=self.legend_handles, + loc=self.legend_loc, + bbox_to_anchor=self.legend_box, + ncol=self.legend_ncol, + fontsize=self.legend_fontsize) plt.suptitle(self.grp_title, fontsize=self.title_size) - fig = plt.gcf() + plt.gcf() plt.savefig("%s.png" % self.graph_image_name, dpi=96) plt.close() print("{}.png".format(self.graph_image_name)) @@ -412,8 +516,46 @@ class lf_line_graph(): print("{}.csv".format(self.graph_image_name)) return "%s.png" % self.graph_image_name -# Unit Test -if __name__ == "__main__": + +def main(): + # arguments + parser = argparse.ArgumentParser( + prog='lf_graph.py', + formatter_class=argparse.RawTextHelpFormatter, + epilog='''\ + lf_graph.py : unit test in lf_graph.py for exersizing the lf_graph.py library + ''', + description='''\ +----------------- +NAME: lf_graph.py + +PURPOSE: +Common Library for generating graphs for LANforge output + +SETUP: +/lanforge/html-reports directory needs to be present or output generated in local file + +EXAMPLE: +see: /py-scritps/lf_report_test.py for example + +COPYWRITE + Copyright 2021 Candela Technologies Inc + License: Free to distribute and modify. LANforge systems must be licensed. + +INCLUDE_IN_README +--------------------- + ''') + parser.add_argument( + '--mgr', + '--lfmgr', + dest='lfmgr', + help='sample argument: where LANforge GUI is running', + default='localhost') + # the args parser is not really used , this is so the report is not generated when testing + # the imports with --help + args = parser.parse_args() + print("LANforge manager {lfmgr}".format(lfmgr=args.lfmgr)) + output_html_1 = "graph_1.html" output_pdf_1 = "graph_1.pdf" @@ -432,7 +574,8 @@ if __name__ == "__main__": # write logic to generate pdf here # wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb # sudo apt install ./wkhtmltox_0.12.6-1.focal_amd64.deb - options = {"enable-local-file-access": None} # prevent eerror Blocked access to file + # prevent eerror Blocked access to file + options = {"enable-local-file-access": None} pdfkit.from_file(output_html_1, output_pdf_1, options=options) # test build_bar_graph setting values @@ -465,5 +608,11 @@ if __name__ == "__main__": # write logic to generate pdf here # wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb # sudo apt install ./wkhtmltox_0.12.6-1.focal_amd64.deb - options = {"enable-local-file-access": None} # prevent eerror Blocked access to file + # prevent eerror Blocked access to file + options = {"enable-local-file-access": None} pdfkit.from_file(output_html_2, output_pdf_2, options=options) + + +# Unit Test +if __name__ == "__main__": + main() diff --git a/py-scripts/lf_help_check.bash b/py-scripts/lf_help_check.bash new file mode 100755 index 00000000..8a3f3d1e --- /dev/null +++ b/py-scripts/lf_help_check.bash @@ -0,0 +1,8 @@ +#!/bin/bash + +FILES=`ls *.py` +for FILE in $FILES +do + echo $FILE + (timeout 10 python3 ./${FILE} --help > /dev/null && echo PASSED) || echo "FAILED ${FILE}" +done diff --git a/py-scripts/lf_kpi_csv.py b/py-scripts/lf_kpi_csv.py new file mode 100644 index 00000000..60eacbb4 --- /dev/null +++ b/py-scripts/lf_kpi_csv.py @@ -0,0 +1,239 @@ +#!/usr/bin/env python3 +""" +NAME: lf_kpi_csv.py + +PURPOSE: +Common Library for generating kpi csv for LANforge output +KPI - Key Performance Indicators + +SETUP: +None + +EXAMPLE: + + +COPYWRITE + Copyright 2021 Candela Technologies Inc + License: Free to distribute and modify. LANforge systems must be licensed. + +INCLUDE_IN_README +""" +# may need pandas if a data frame is passed in +# import pandas as pd +import csv +import time +import argparse + +''' +Note teh delimiter for the kpi.csv is a tab + +kpi.csv : specific file that is used for the database, dashboard and blog post +A blank entry is a valid entry in some cases. + + Date: date of run + test-rig : testbed that the tests are run on for example ct_us_001 + test-tag : test specific information to differenciate the test, LANforge radios used, security modes (wpa2 , open) + dut-hw-version : hardware version of the device under test + dut-sw-version : software version of the device under test + dut-model-num : model number / name of the device under test + dut-serial-num : serial number / serial number of the device under test + test-priority : test-priority is arbitrary number, choosing under 95 means it goes down at bottom of blog report, and higher priority goes at top. + test-id : script or test name , AP Auto, wifi capacity, data plane, dfs + short-description : short description of the test + pass/fail : set blank for performance tests + numeric-score : this is the value for the y-axis (x-axis is a timestamp), numeric value of what was measured + test-details : what was measured in the numeric-score, e.g. bits per second, bytes per second, upload speed, minimum cx time (ms) + Units : units used for the numeric-scort + Graph-Group - Items graphed together used by dashboard, For the lf_qa.py dashboard + +''' + + +class lf_kpi_csv: + def __init__(self, + _kpi_headers=None, + _kpi_filename='kpi.csv', # Currently this is the only file name accepted + _kpi_path="", + _kpi_test_rig="TEST_RIG", + _kpi_test_tag="TEST_TAG", + _kpi_dut_hw_version="HW_VERSION", + _kpi_dut_sw_version="SW_VERSION", + _kpi_dut_model_num="MODEL_NUM", + _kpi_dut_serial_num="SERIAL_NUM", + _kpi_test_id="TEST_ID" + ): + if _kpi_headers is None: + _kpi_headers = ['Date', 'test-rig', 'test-tag', 'dut-hw-version', 'dut-sw-version', 'dut-model-num', + 'dut-serial-num', + 'test-priority', 'test-id', 'short-description', 'pass/fail', 'numeric-score', + 'test details', 'Units', 'Graph-Group', 'Subtest-Pass', 'Subtest-Fail'] + self.kpi_headers = _kpi_headers + self.kpi_filename = _kpi_filename + self.kpi_full_path = '' + self.kpi_file = "" + self.kpi_path = _kpi_path + self.kpi_test_rig = _kpi_test_rig + self.kpi_test_tag = _kpi_test_tag + self.kpi_dut_hw_version = _kpi_dut_hw_version + self.kpi_dut_sw_version = _kpi_dut_sw_version + self.kpi_dut_model_num = _kpi_dut_model_num + self.kpi_dut_serial_num = _kpi_dut_serial_num + self.kpi_test_id = _kpi_test_id + self.kpi_rows = "" + try: + print("self.kpi_path {kpi_path}".format(kpi_path=self.kpi_path)) + print("self.kpi_filename {kpi_filename}".format(kpi_filename=self.kpi_filename)) + if self.kpi_path == "": + kpifile = self.kpi_filename + else: + kpifile = self.kpi_path + '/' + self.kpi_filename + print("kpifile {kpifile}".format(kpifile=kpifile)) + self.kpi_file = open(kpifile, 'w') + self.kpi_writer = csv.DictWriter(self.kpi_file, delimiter="\t", fieldnames=self.kpi_headers) + self.kpi_writer.writeheader() + except: + print("lf_kpi_csv.py: {} WARNING unable to open".format(self.kpi_file)) + + self.kpi_dict = dict() + self.kpi_dict['Date'] = '{date}'.format(date=int(time.time())) + self.kpi_dict['test-rig'] = '{test_rig}'.format(test_rig=self.kpi_test_rig) + self.kpi_dict['test-tag'] = '{test_tag}'.format(test_tag=self.kpi_test_tag) + self.kpi_dict['dut-hw-version'] = '{dut_hw_version}'.format(dut_hw_version=self.kpi_dut_hw_version) + self.kpi_dict['dut-sw-version'] = '{dut_sw_version}'.format(dut_sw_version=self.kpi_dut_sw_version) + self.kpi_dict['dut-model-num'] = '{dut_model_num}'.format(dut_model_num=self.kpi_dut_model_num) + self.kpi_dict['dut-serial-num'] = '{dut_serial_num}'.format(dut_serial_num=self.kpi_dut_serial_num) + self.kpi_dict['test-priority'] = '' + self.kpi_dict['test-id'] = '{test_id}'.format(test_id=self.kpi_test_id) + self.kpi_dict['short-description'] = '' + self.kpi_dict['pass/fail'] = '' + self.kpi_dict['numeric-score'] = '' + self.kpi_dict['test details'] = '' + self.kpi_dict['Units'] = '' + self.kpi_dict['Graph-Group'] = '' + self.kpi_dict['Subtest-Pass'] = '' + self.kpi_dict['Subtest-Fail'] = '' + + def kpi_csv_get_dict_update_time(self): + self.kpi_dict['Date'] = '{date}'.format(date=round(time.time() * 1000)) + return self.kpi_dict + + def kpi_csv_write_dict(self, kpi_dict): + self.kpi_writer.writerow(kpi_dict) + self.kpi_file.flush() + + +def main(): + # arguments + parser = argparse.ArgumentParser( + prog='lf_kpi_csv.py', + formatter_class=argparse.RawTextHelpFormatter, + epilog='''\ + lf_kpi_csv.py : unit test in lf_kpi_csv.py for exersiging lf_kpi_csv.py library + ''', + description='''\ +lf_kpi_csv.py +----------- + +Summary : +--------- +lf_kpi_csv.py library : + + Date: date of run + test-rig : testbed that the tests are run on for example ct_us_001 + test-tag : test specific information to differenciate the test, LANforge radios used, security modes (wpa2 , open) + dut-hw-version : hardware version of the device under test + dut-sw-version : software version of the device under test + dut-model-num : model number / name of the device under test + dut-serial-num : serial number / serial number of the device under test + test-priority : test-priority is arbitrary number, choosing under 95 means it goes down at bottom of blog report, and higher priority goes at top. + test-id : script or test name , AP Auto, wifi capacity, data plane, dfs + short-description : short description of the test + pass/fail : set blank for performance tests + numeric-score : this is the value for the y-axis (x-axis is a timestamp), numeric value of what was measured + test-details : what was measured in the numeric-score, e.g. bits per second, bytes per second, upload speed, minimum cx time (ms) + Units : units used for the numeric-scort + Graph-Group - Items graphed together used by dashboard, For the lf_qa.py dashboard + +Example : + + This module is included to assist in filling out the kpi.csv correctly + The Unit test is used for helping to become familiar with the library + +--------- + ''') + + parser.add_argument( + '--local_lf_report_dir', + help='--local_lf_report_dir override the report path, primary use when running test in test suite', + default="") + parser.add_argument("--test_rig", default="lanforge", + help="test rig for kpi.csv, testbed that the tests are run on") + parser.add_argument("--test_tag", default="kpi_generation", + help="test tag for kpi.csv, test specific information to differenciate the test") + parser.add_argument("--dut_hw_version", default="hw_01", + help="dut hw version for kpi.csv, hardware version of the device under test") + parser.add_argument("--dut_sw_version", default="sw_01", + help="dut sw version for kpi.csv, software version of the device under test") + parser.add_argument("--dut_model_num", default="can_ap", + help="dut model for kpi.csv, model number / name of the device under test") + parser.add_argument("--test_priority", default="95", + help="dut model for kpi.csv, test-priority is arbitrary number") + parser.add_argument("--test_id", default="kpi_unit_test", help="test-id for kpi.csv, script or test name") + ''' + Other values that are included in the kpi.csv row. + short-description : short description of the test + pass/fail : set blank for performance tests + numeric-score : this is the value for the y-axis (x-axis is a timestamp), numeric value of what was measured + test details : what was measured in the numeric-score, e.g. bits per second, bytes per second, upload speed, minimum cx time (ms) + Units : units used for the numeric-scort + Graph-Group - For the lf_qa.py dashboard + ''' + + args = parser.parse_args() + + # Get the report path to create the kpi.csv path + # kpi_path = report.get_report_path() in normal use case would get from lf_report.py library + kpi_csv = lf_kpi_csv( + _kpi_path=args.local_lf_report_dir, + _kpi_test_rig=args.test_rig, + _kpi_test_tag=args.test_tag, + _kpi_dut_hw_version=args.dut_hw_version, + _kpi_dut_sw_version=args.dut_sw_version, + _kpi_dut_model_num=args.dut_model_num, + _kpi_test_id=args.test_id) + + results_dict = kpi_csv.kpi_dict + + results_dict['Graph-Group'] = "graph_group" + results_dict['short-description'] = "short_description" + results_dict['numeric-score'] = "100" + results_dict['Units'] = "Mbps" + + print("results_dict {results_dict}".format(results_dict=results_dict)) + print("date {date}".format(date=results_dict['Date'])) + + kpi_csv.kpi_csv_write_dict(results_dict) + + # reuse the dictionary + results_dict['Graph-Group'] = "graph_group_1_5" + results_dict['short-description'] = "short_description_1_5" + results_dict['numeric-score'] = "99" + results_dict['Units'] = "Mbps" + + kpi_csv.kpi_csv_write_dict(results_dict) + + # append to a row to the existing dictionary + results_dict_2 = kpi_csv.kpi_dict + # modify an entry + results_dict_2['test-tag'] = 'kpi_generation_2' + results_dict_2['Graph-Group'] = "graph_group" + results_dict_2['short-description'] = "short_description" + results_dict_2['numeric-score'] = "100" + results_dict_2['Units'] = "Mbps" + print("results_dict_2 {results_dict_2}".format(results_dict_2=results_dict_2)) + print("date 2 {date}".format(date=results_dict_2['Date'])) + kpi_csv.kpi_csv_write_dict(results_dict_2) + + +if __name__ == "__main__": + main() diff --git a/py-scripts/lf_mesh_test.py b/py-scripts/lf_mesh_test.py index 68924e85..c325b0e7 100755 --- a/py-scripts/lf_mesh_test.py +++ b/py-scripts/lf_mesh_test.py @@ -146,14 +146,22 @@ class MeshTest(cvtest): upload_speed="56Kbps", download_speed="85%", duration="60s", - enables=[], - disables=[], - raw_lines=[], + enables=None, + disables=None, + raw_lines=None, raw_lines_file="", - sets=[], + sets=None, ): super().__init__(lfclient_host=lf_host, lfclient_port=lf_port) + if enables is None: + enables = [] + if disables is None: + disables = [] + if raw_lines is None: + raw_lines = [] + if sets is None: + sets = [] self.lf_host = lf_host self.lf_port = lf_port self.lf_user = lf_user @@ -225,14 +233,14 @@ def main(): Open this file in an editor and read the top notes for more details. Example: - ./lf_mesh_test.py --mgr localhost --port 8080 --lf_user lanforge --lf_password lanforge \ - --instance_name mesh-instance --config_name test_con --upstream 1.1.eth1 \ - --raw_line 'selected_dut2: RootAP wactest 08:36:c9:19:47:40 (1)' \ - --raw_line 'selected_dut5: RootAP wactest 08:36:c9:19:47:50 (2)' \ - --duration 15s \ - --download_speed 85% --upload_speed 56Kbps \ - --raw_line 'velocity: 100' \ - --raw_lines_file example-configs/mesh-ferndale-cfg.txt \ + ./lf_mesh_test.py --mgr localhost --port 8080 --lf_user lanforge --lf_password lanforge \\ + --instance_name mesh-instance --config_name test_con --upstream 1.1.eth1 \\ + --raw_line 'selected_dut2: RootAP wactest 08:36:c9:19:47:40 (1)' \\ + --raw_line 'selected_dut5: RootAP wactest 08:36:c9:19:47:50 (2)' \\ + --duration 15s \\ + --download_speed 85% --upload_speed 56Kbps \\ + --raw_line 'velocity: 100' \\ + --raw_lines_file example-configs/mesh-ferndale-cfg.txt \\ --test_rig Ferndale-Mesh-01 --pull_report NOTE: There is quite a lot of config needed, see example-configs/mesh-ferndale-cfg.txt @@ -246,9 +254,9 @@ def main(): parser.add_argument("-u", "--upstream", type=str, default="", help="Upstream port for wifi capacity test ex. 1.1.eth2") - + # argparse uses the % formatting so use %% parser.add_argument("--download_speed", default="", - help="Specify requested download speed. Percentage of theoretical is also supported. Default: 85%") + help="Specify requested download speed. Percentage of theoretical is also supported. Default: 85%%") parser.add_argument("--upload_speed", default="", help="Specify requested upload speed. Percentage of theoretical is also supported. Default: 0") parser.add_argument("--duration", default="", diff --git a/py-scripts/lf_multipsk.py b/py-scripts/lf_multipsk.py index 298247e8..f650fe3c 100755 --- a/py-scripts/lf_multipsk.py +++ b/py-scripts/lf_multipsk.py @@ -45,7 +45,7 @@ Realm = realm.Realm class MultiPsk(Realm): def __init__(self, host=None, - port=None, + port=8080, ssid=None, input=None, security=None, @@ -57,8 +57,10 @@ class MultiPsk(Realm): sta_prefix="sta", debug_=False, ): - self.host = host - self.port = port + super().__init__(lfclient_host=host, + lfclient_port=port), + self.lfclient_host = host + self.lfclient_port = port self.ssid = ssid self.input = input self.security = security @@ -69,8 +71,7 @@ class MultiPsk(Realm): self.resource = resource self.sta_prefix = sta_prefix self.debug = debug_ - self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port) - self.station_profile = self.local_realm.new_station_profile() + self.station_profile = self.new_station_profile() def build(self): station_list = [] @@ -84,30 +85,30 @@ class MultiPsk(Realm): else: station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=self.start_id, end_id_=input['num_station'] - 1, padding_number_=100, - radio=input['radio']) + radio=self.radio) # implementation for non vlan pending **** print("creating stations") - self.station_profile.use_security(self.security, self.ssid, str(input['password'])) + self.station_profile.use_security(self.security, self.ssid, self.passwd) self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) self.station_profile.set_command_param("set_port", "report_timer", 1500) self.station_profile.set_command_flag("set_port", "rpt_timer", 1) - self.station_profile.create(radio=input['radio'], sta_names_=station_list, debug=self.local_realm.debug) - self.local_realm.wait_until_ports_appear(sta_list=station_list) + self.station_profile.create(radio=self.radio, sta_names_=station_list, debug=self.debug) + self.wait_until_ports_appear(sta_list=station_list) self.station_profile.admin_up() - if self.local_realm.wait_for_ip(station_list, timeout_sec=120): + if self.wait_for_ip(station_list, timeout_sec=120): print("All stations got IPs") else: print("Stations failed to get IPs") print("create udp endp") - self.cx_profile_udp = self.local_realm.new_l3_cx_profile() + self.cx_profile_udp = self.new_l3_cx_profile() self.cx_profile_udp.side_a_min_bps = 128000 self.cx_profile_udp.side_b_min_bps = 128000 self.cx_profile_udp.side_a_min_pdu = 1200 self.cx_profile_udp.side_b_min_pdu = 1500 self.cx_profile_udp.report_timer = 1000 self.cx_profile_udp.name_prefix = "udp" - port_list = list(self.local_realm.find_ports_like("%s+" % self.sta_prefix)) + port_list = list(self.find_ports_like("%s+" % self.sta_prefix)) # print("port list", port_list) if (port_list is None) or (len(port_list) < 1): raise ValueError("Unable to find ports named '%s'+" % self.sta_prefix) @@ -118,13 +119,13 @@ class MultiPsk(Realm): # Create TCP endpoints print("create tcp endp") - self.l3_tcp_profile = self.local_realm.new_l3_cx_profile() + self.l3_tcp_profile = self.new_l3_cx_profile() self.l3_tcp_profile.side_a_min_bps = 128000 self.l3_tcp_profile.side_b_min_bps = 56000 self.l3_tcp_profile.name_prefix = "tcp" self.l3_tcp_profile.report_timer = 1000 self.l3_tcp_profile.create(endp_type="lf_tcp", - side_a=list(self.local_realm.find_ports_like("%s+" % self.sta_prefix)), + side_a=list(self.find_ports_like("%s+" % self.sta_prefix)), side_b="%d.%s" % (self.resource, input['upstream']), suppress_related_commands=True) @@ -140,7 +141,7 @@ class MultiPsk(Realm): if "." in i['upstream']: # print(str(i['upstream']) + " is a vlan upstream port") print("checking its ip ..") - data = self.local_realm.json_get("ports/list?fields=IP") + data = self.json_get("ports/list?fields=IP") for val in data["interfaces"]: for j in val: if "1." + str(self.resource) + "." + str(i['upstream']) == j: @@ -157,7 +158,7 @@ class MultiPsk(Realm): if "." not in i['upstream']: # print(str(i['upstream']) + " is not an vlan upstream port") print("checking its ip ..") - data = self.local_realm.json_get("ports/list?fields=IP") + data = self.json_get("ports/list?fields=IP") for val in data["interfaces"]: for j in val: if "1." + str(self.resource) + "." + str(i['upstream']) == j: @@ -168,11 +169,8 @@ class MultiPsk(Realm): return non_vlan_ips def get_sta_ip(self): - # this function gives station ip dict eg{'eth2.100': '172.17.0.100'} - # self.input = [{'password': 'lanforge1', 'upstream': 'eth2.100', 'mac': '', 'num_station': 1, 'radio': 'wiphy4'}, {'password': 'lanforge2', 'upstream': 'eth2.200', 'mac': '', 'num_station': 1, 'radio': 'wiphy4'}, {'password': 'lanforge3', 'upstream': 'eth2', 'mac': '', 'num_station': 1, 'radio': 'wiphy0'}] - # port_list = ['1.1.sta200', '1.1.sta00', '1.1.sta100'] station_ip = {} - port_list = list(self.local_realm.find_ports_like("%s+" % self.sta_prefix)) + port_list = list(self.find_ports_like("%s+" % self.sta_prefix)) # print("port list", port_list) # port list ['1.1.sta200', '1.1.sta00', '1.1.sta100'] for name, id in zip(port_list, self.input): @@ -182,7 +180,7 @@ class MultiPsk(Realm): # print(x) if name == "1." + str(self.resource) + ".sta" + str(x): - data = self.local_realm.json_get("ports/list?fields=IP") + data = self.json_get("ports/list?fields=IP") for i in data["interfaces"]: # print(i) for j in i: @@ -227,7 +225,7 @@ class MultiPsk(Realm): # print(x) if name == "1." + str(self.resource) + ".sta" + str(x): - data = self.local_realm.json_get("ports/list?fields=IP") + data = self.json_get("ports/list?fields=IP") for i in data["interfaces"]: # print(i) for j in i: @@ -241,7 +239,7 @@ class MultiPsk(Realm): def get_non_vlan_sta_ip(self): station_nonvlan_ip = {} x = "" - port_list = list(self.local_realm.find_ports_like("%s+" % self.sta_prefix)) + port_list = list(self.find_ports_like("%s+" % self.sta_prefix)) # print("port list", port_list) for id in self.input: if "." not in id['upstream']: @@ -249,7 +247,7 @@ class MultiPsk(Realm): # print(x) for name in port_list: if name == "1.1.sta00": - data = self.local_realm.json_get("ports/list?fields=IP") + data = self.json_get("ports/list?fields=IP") for i in data["interfaces"]: # print(i) for j in i: @@ -270,11 +268,10 @@ class MultiPsk(Realm): y = station_ip[j].split('.') if x[0] == y[0] and x[1] == y[1]: print("station got ip from vlan") - x = "Pass" + return "Pass" else: print("station did not got ip from vlan") - x = "Fail" - return x + return "Fail" def compare_nonvlan_ip_nat(self): non_vlan_sta_ip = self.get_non_vlan_sta_ip() @@ -312,27 +309,22 @@ class MultiPsk(Realm): self.cx_profile_udp.cleanup() self.l3_tcp_profile.cleanup() self.station_profile.cleanup() - LFUtils.wait_until_ports_disappear(base_url=self.local_realm.lfclient_url, port_list=self.station_profile.station_names, + LFUtils.wait_until_ports_disappear(base_url=self.lfclient_host, port_list=self.station_profile.station_names, debug=self.debug) print("Test Completed") def main(): - parser = argparse.ArgumentParser( + parser = Realm.create_basic_argparse( prog="lf_multipsk.py", formatter_class=argparse.RawTextHelpFormatter, description="lanforge webpage download Test Script") - parser.add_argument('--mgr', help='hostname for where LANforge GUI is running', default='localhost') - parser.add_argument('--mgr_port', help='port LANforge GUI HTTP service is running on', default=8080) - parser.add_argument('--ssid', help='WiFi SSID for client to associate to') - parser.add_argument('--security', help='WiFi Security protocol: {open|wep|wpa2|wpa3', default="wpa2") - parser.add_argument('--mode', help="specify mode of ap eg BRIDGE or NAT", default="BRIDGE") parser.add_argument('--n_vlan', help="type number of vlan using in test eg 1 or 2", default=1) - # parser.add_argument('--input', nargs="+", help="specify list of parameters like passwords,upstream,mac address, number of clients and radio as input, eg password@123,eth2.100,"",1,wiphy0 lanforge@123,eth2.100,"",1,wiphy1") + parser.add_argument('--mode', help="Mode for lf_multipsk", default=None) args = parser.parse_args() input_data = [{ - "password": "lanforge1", + "password": args.passwd, "upstream": "eth2.100", "mac": "", "num_station": 1, @@ -364,8 +356,11 @@ def main(): multi_obj = MultiPsk(host=args.mgr, port=args.mgr_port, ssid=args.ssid, + passwd=args.passwd, input=input_data, - security=args.security) + security=args.security, + debug_=args.debug, + radio=args.radio) multi_obj.build() multi_obj.start() diff --git a/py-scripts/lf_port_probe.py b/py-scripts/lf_port_probe.py new file mode 100755 index 00000000..32c0c050 --- /dev/null +++ b/py-scripts/lf_port_probe.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +import json +import os +import pprint +import sys + +if sys.version_info[0] != 3: + print("This script requires Python 3") + exit(1) + +if 'py-json' not in sys.path: + sys.path.append(os.path.join(os.path.abspath('..'), 'py-json')) + +from time import sleep +from LANforge.lfcli_base import LFCliBase + + +# see https://stackoverflow.com/questions/9295439/python-json-loads-fails-with-valueerror-invalid-control-character-at-line-1-c/16544933#16544933 +# re-load and reexport JSON with strict=False? + +class ProbePort2(LFCliBase): + def __init__(self, + lfhost=None, + lfport=None, + debug=False, + eid_str=None): + super().__init__(_lfjson_host=lfhost, + _lfjson_port=lfport, + _debug=debug) + hunks = eid_str.split(".") + self.probepath = "/probe/1/%s/%s" % (hunks[-2], hunks[-1]) + # self.decoder = json.JSONDecoder() + + def run(self): + self.json_post(self.probepath, {}) + sleep(0.2) + response = self.json_get(self.probepath) + if not response: + print("problem probing port %s" % self.probepath) + exit(1) + # pprint.pprint(response) + if "probe-results" not in response: + print("problem probing port %s" % self.probepath) + exit(1) + + probe_res = response["probe-results"][0] + #pprint.pprint(probe_res) + for (key, value) in probe_res.items(): + # probe_results = [key] + print("port "+key) + # pprint.pprint(value['probe results']) + xlated_results = str(value['probe results']).replace("\\n", "\n").replace("\\r", "\r").replace("\\t", "\t") + print(xlated_results) + + +def main(): + parser = LFCliBase.create_bare_argparse( + prog=__name__, + description='''\ + Example: + ./port_probe.py --port 1.1.eth0 + ''') + + parser.add_argument('--mode', help='Used to force mode of stations') + parser.add_argument('--port_eid', help='EID of station to be used', default="1.1.eth0") + + args = parser.parse_args() + probe = ProbePort2(lfhost=args.mgr, + lfport=args.mgr_port, + debug=args.debug, + eid_str=args.port_eid) + probe.run() + + +if __name__ == "__main__": + main() diff --git a/py-scripts/lf_report.py b/py-scripts/lf_report.py index 96ceadd3..12d98e40 100755 --- a/py-scripts/lf_report.py +++ b/py-scripts/lf_report.py @@ -1,20 +1,20 @@ #!/usr/bin/env python3 -''' +""" NAME: lf_report.py -PURPOSE: +PURPOSE: This program is a helper class for reporting results for a lanforge python script. -The class will generate an output directory based on date and time in the /home/lanforge/html-reports/ . +The class will generate an output directory based on date and time in the /home/lanforge/html-reports/ . If the reports-data is not present then the date and time directory will be created in the current directory. -The banner and Candela Technology logo will be copied in the results directory. -The results directory may be over written and many of the other paramaters during construction. +The banner and Candela Technology logo will be copied in the results directory. +The results directory may be over written and many of the other paramaters during construction. Creating the date time directory on construction was a design choice. -EXAMPLE: +EXAMPLE: -This is a helper class, a unit test is included at the bottom of the file. +This is a helper class, a unit test is included at the bottom of the file. To test lf_report.py and lf_graph.py together use the lf_report_test.py file LICENSE: @@ -23,7 +23,7 @@ LICENSE: INCLUDE_IN_README -''' +""" # CAUTION: adding imports to this file which are not in update_dependencies.py is not advised import os import shutil @@ -31,25 +31,27 @@ import datetime import pandas as pd import pdfkit +import argparse # internal candela references included during intial phases, to be deleted at future date # https://candelatech.atlassian.net/wiki/spaces/LANFORGE/pages/372703360/Scripting+Data+Collection+March+2021 # base report class -class lf_report(): + +class lf_report: def __init__(self, # _path the report directory under which the report directories will be created. _path="/home/lanforge/html-reports", _alt_path="", _date="", - _title="LANForge Test Run Heading", + _title="LANForge Unit Test Run Heading", _table_title="LANForge Table Heading", _graph_title="LANForge Graph Title", _obj="", _obj_title="", _output_html="outfile.html", _output_pdf="outfile.pdf", - _results_dir_name="LANforge_Test_Results", + _results_dir_name="LANforge_Test_Results_Unit_Test", _output_format='html', # pass in on the write functionality, current not used _dataframe="", _path_date_time="", @@ -76,6 +78,7 @@ class lf_report(): self.output_html = _output_html self.path_date_time = _path_date_time self.write_output_html = "" + self.write_output_index_html = "" self.output_pdf = _output_pdf self.write_output_pdf = "" self.banner_html = "" @@ -271,6 +274,17 @@ class lf_report(): print("write_html failed") return self.write_output_html + def write_index_html(self): + self.write_output_index_html = str(self.path_date_time) + '/' + str("index.html") + print("write_output_index_html: {}".format(self.write_output_index_html)) + try: + test_file = open(self.write_output_index_html, "w") + test_file.write(self.html) + test_file.close() + except: + print("write_index_html failed") + return self.write_output_index_html + def write_html_with_timestamp(self): self.write_output_html = "{}/{}-{}".format(self.path_date_time, self.date, self.output_html) print("write_output_html: {}".format(self.write_output_html)) @@ -456,7 +470,7 @@ class lf_report(): setup_information = """ - + - - - ") + echo "$testcommand" + start=$(date +%s) + # this command saves stdout and stderr to the stdout file, and has a special file for stderr text. + # Modified from https://unix.stackexchange.com/a/364176/327076 + FILENAME="${TEST_DIR}/${NAME}" + { eval "$testcommand" 2>&1 >&3 3>&- | tee "${FILENAME}_stderr.txt" 3>&-; } > "${FILENAME}.txt" 3>&1 + chmod 664 "${FILENAME}.txt" + FILESIZE=$(stat -c%s "${FILENAME}_stderr.txt") || 0 + # Check to see if the error is due to LANforge + ERROR_DATA=$(cat "${FILENAME}_stderr.txt") + if [[ $ERROR_DATA =~ "LANforge Error Messages" ]] + then + LANforgeError="Lanforge Error" + echo "LANforge Error" else - results+=(" - - - ") + LANforgeError="" fi + end=$(date +%s) + execution="$((end-start))" + TEXT=$(cat "${FILENAME}".txt) + STDERR="" + if [[ $TEXT =~ "tests failed" ]] + then + TEXTCLASS="partial_failure" + TDTEXT="Partial Failure" + else + TEXTCLASS="success" + TDTEXT="Success" + fi + + if (( FILESIZE > 0)) + then + echo "Errors detected" + TEXTCLASS="failure" + TDTEXT="Failure" + STDERR="STDERR" + else + echo "No errors detected" + fi + results+=(" + + + + + + + ") } -function run_test() { +function start_tests() { if [[ ${#A} -gt 0 ]]; then - for i in "${testCommands[@]}"; do + for testcommand in "${testCommands[@]}"; do NAME=$(cat < /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) - CURR_TEST_NAME=${i%%.py*} + CURR_TEST_NAME=${testcommand%%.py*} CURR_TEST_NAME=${CURR_TEST_NAME#./*} #CURR_TEST_NUM="${name_to_num[$CURR_TEST_NAME]}" if [[ $A == "$CURR_TEST_NAME" ]]; then @@ -487,9 +590,9 @@ function run_test() { fi done else - for i in "${testCommands[@]}"; do + for testcommand in "${testCommands[@]}"; do NAME=$(cat < /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) - CURR_TEST_NAME=${i%%.py*} + CURR_TEST_NAME=${testcommand%%.py*} CURR_TEST_NAME=${CURR_TEST_NAME#./*} #CURR_TEST_NUM="${name_to_num[$CURR_TEST_NAME]}" test @@ -498,61 +601,109 @@ function run_test() { } function html_generator() { - LAST_COMMIT=$(git log --pretty=oneline | tail -n 1) - header=" - - Regression Test Results $NOW - - - - -

Regression Results

-

$NOW

-

$LAST_COMMIT

-
""" + str(value) + """ @@ -496,7 +510,7 @@ class lf_report(): function fallbackCopyTextToClipboard(text) { var textArea = document.createElement("textarea"); textArea.value = text; - + // Avoid scrolling to bottom textArea.style.top = "0"; textArea.style.left = "0"; @@ -561,6 +575,16 @@ function copyTextToClipboard(ele) { # Unit Test if __name__ == "__main__": + parser = argparse.ArgumentParser( + prog="lf_report.py", + formatter_class=argparse.RawTextHelpFormatter, + description="Reporting library Unit Test") + parser.add_argument('--lfmgr', help='sample argument: where LANforge GUI is running', default='localhost') + # the args parser is not really used , this is so the report is not generated when testing + # the imports with --help + args = parser.parse_args() + print("LANforge manager {lfmgr}".format(lfmgr=args.lfmgr)) + # Testing: generate data frame dataframe = pd.DataFrame({ 'product': ['CT521a-264-1ac-1n', 'CT521a-1ac-1ax', 'CT522-264-1ac2-1n', 'CT523c-2ac2-db-10g-cu', @@ -573,7 +597,7 @@ if __name__ == "__main__": print(dataframe) - # Testing: generate data frame + # Testing: generate data frame dataframe2 = pd.DataFrame({ 'station': [1, 2, 3, 4, 5, 6, 7], 'time_seconds': [23, 78, 22, 19, 45, 22, 25] @@ -605,4 +629,3 @@ if __name__ == "__main__": report.write_pdf() print("report path {}".format(report.get_path())) - diff --git a/py-scripts/lf_report_test.py b/py-scripts/lf_report_test.py index 0923f1e9..114af078 100755 --- a/py-scripts/lf_report_test.py +++ b/py-scripts/lf_report_test.py @@ -2,13 +2,13 @@ ''' NAME: lf_report_test.py -PURPOSE: +PURPOSE: Common file for testing lf_report and lf_graph Library generates html and pdf output -SETUP: +SETUP: /lanforge/html-reports directory needs to be present or output generated in local file -EXAMPLE: +EXAMPLE: ./lf_report_test.py : currently script does not accept input COPYWRITE @@ -26,8 +26,9 @@ import numpy as np import pandas as pd import pdfkit import random +import argparse + - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lf_report = importlib.import_module("py-scripts.lf_report") @@ -38,10 +39,45 @@ lf_scatter_graph = lf_graph.lf_scatter_graph lf_stacked_graph = lf_graph.lf_stacked_graph lf_horizontal_stacked_graph = lf_graph.lf_horizontal_stacked_graph - # Unit Test -if __name__ == "__main__": + + +def main(): # Testing: generate data frame + parser = argparse.ArgumentParser( + prog="lf_report_test.py", + formatter_class=argparse.RawTextHelpFormatter, + description='''\ +----------------- +NAME: lf_report_test.py + +PURPOSE: +Common file for testing lf_report and lf_graph Library generates html and pdf output + +SETUP: +/lanforge/html-reports directory needs to be present or output generated in local file + +EXAMPLE: +./lf_report_test.py : currently script does not accept input + +COPYWRITE + Copyright 2021 Candela Technologies Inc + License: Free to distribute and modify. LANforge systems must be licensed. + +INCLUDE_IN_README +''') + + parser.add_argument( + '--mgr', + '--lfmgr', + dest='lfmgr', + help='sample argument: where LANforge GUI is running', + default='localhost') + # the args parser is not really used , this is so the report is not generated when testing + # the imports with --help + args = parser.parse_args() + print("LANforge manager {lfmgr}".format(lfmgr=args.lfmgr)) + dataframe = pd.DataFrame({ 'product': ['CT521a-264-1ac-1n', 'CT521a-1ac-1ax', 'CT522-264-1ac2-1n', 'CT523c-2ac2-db-10g-cu', 'CT523c-3ac2-db-10g-cu', 'CT523c-8ax-ac10g-cu', 'CT523c-192-2ac2-1ac-10g'], @@ -53,7 +89,7 @@ if __name__ == "__main__": print(dataframe) - # Testing: generate data frame + # Testing: generate data frame dataframe2 = pd.DataFrame({ 'station': [1, 2, 3, 4, 5, 6, 7], 'time_seconds': [23, 78, 22, 19, 45, 22, 25] @@ -108,7 +144,7 @@ if __name__ == "__main__": _xaxis_categories=x_axis_values, _graph_image_name="Bi-single_radio_2.4GHz", _label=["bi-downlink", "bi-uplink", 'uplink'], - _color=['darkorange', 'forestgreen','blueviolet'], + _color=['darkorange', 'forestgreen', 'blueviolet'], _color_edge='red', _grp_title="Throughput for each clients", _xaxis_step=5, @@ -117,7 +153,7 @@ if __name__ == "__main__": _text_rotation=45, _xticks_font=7, _legend_loc="best", - _legend_box=(1,1), + _legend_box=(1, 1), _legend_ncol=1, _legend_fontsize=None, _enable_csv=True) @@ -127,7 +163,7 @@ if __name__ == "__main__": print("graph name {}".format(graph_png)) report.set_graph_image(graph_png) - # need to move the graph image to the results + # need to move the graph image to the results report.move_graph_image() if graph.enable_csv: report.set_csv_filename(graph_png) @@ -140,7 +176,7 @@ if __name__ == "__main__": _graph_image_name="image_name1", _color=None, _label=["s1", "s2", "s3"], - _enable_csv = False) + _enable_csv=False) graph_png = graph2.build_scatter_graph() print("graph name {}".format(graph_png)) @@ -149,14 +185,15 @@ if __name__ == "__main__": report.move_graph_image() report.build_graph() - # this will generate graph which is independent,we can customize the value with different colors + # this will generate graph which is independent,we can customize the value + # with different colors graph2 = lf_scatter_graph(_x_data_set=set1, _y_data_set=[45, 67, 45, 34], _values=[0, 0, 0, 1], _xaxis_name="x-axis", _yaxis_name="y-axis", _graph_image_name="image_name_map", _color=None, _label=["s1", "s2"], - _enable_csv = False) + _enable_csv=False) graph_png = graph2.build_scatter_graph() print("graph name {}".format(graph_png)) @@ -165,14 +202,15 @@ if __name__ == "__main__": report.move_graph_image() report.build_graph() - dataset = [["1", "2", "3", "4"], [12, 45, 67, 34], [23, 67, 23, 12], [25, 45, 34, 23]] + dataset = [["1", "2", "3", "4"], [12, 45, 67, 34], + [23, 67, 23, 12], [25, 45, 34, 23]] graph = lf_stacked_graph(_data_set=dataset, _xaxis_name="Stations", _yaxis_name="Login PASS/FAIL", _label=['Success', 'Fail', 'both'], _graph_image_name="login_pass_fail1", _color=None, - _enable_csv = False) + _enable_csv=False) graph_png = graph.build_stacked_graph() @@ -192,7 +230,7 @@ if __name__ == "__main__": _graph_image_name="image_name_pass_fail", _color=["r", "g"], _figsize=(9, 4), - _enable_csv = False) + _enable_csv=False) graph_png = graph.build_horizontal_stacked_graph() @@ -215,3 +253,5 @@ if __name__ == "__main__": # report.write_pdf(_page_size = 'Legal', _orientation='Portrait') # report.generate_report() +if __name__ == "__main__": + main() diff --git a/py-scripts/lf_rvr_test.py b/py-scripts/lf_rvr_test.py index 628f7720..1f14225c 100755 --- a/py-scripts/lf_rvr_test.py +++ b/py-scripts/lf_rvr_test.py @@ -124,7 +124,7 @@ class RvrTest(cvtest): lf_host="localhost", lf_port=8080, ssh_port=22, - local_path="", + local_lf_report_dir="", graph_groups=None, lf_user="lanforge", lf_password="lanforge", @@ -167,8 +167,8 @@ class RvrTest(cvtest): self.raw_lines_file = raw_lines_file self.sets = sets self.ssh_port = ssh_port - self.local_path = local_path self.graph_groups = graph_groups + self.local_lf_report_dir = local_lf_report_dir def setup(self): # Nothing to do at this time. @@ -212,7 +212,7 @@ class RvrTest(cvtest): self.create_and_run_test(self.load_old_cfg, self.test_name, self.instance_name, self.config_name, self.sets, self.pull_report, self.lf_host, self.lf_user, self.lf_password, - cv_cmds, ssh_port=self.ssh_port, local_lf_report_dir=self.local_path, + cv_cmds, ssh_port=self.ssh_port, local_lf_report_dir=self.local_lf_report_dir, graph_groups_file=self.graph_groups) self.rm_text_blob(self.config_name, blob_test) # To delete old config with same name @@ -226,6 +226,39 @@ def main(): Example: + ./lf_rvr_test.py --mgr localhost --port 8080 --lf_user lanforge --lf_password lanforge \\ + --instance_name rvr-instance --config_name test_con --upstream 1.1.eth1 \\ + --dut RootAP --duration 15s --station 1.1.wlan0 \\ + --download_speed 85% --upload_speed 56Kbps \\ + --raw_line 'pkts: MTU' \\ + --raw_line 'directions: DUT Transmit' \\ + --raw_line 'traffic_types: TCP' \\ + --test_rig Ferndale-Mesh-01 --pull_report \\ + --raw_line 'attenuator: 1.1.1040' \\ + --raw_line 'attenuations: 0..+50..950' \\ + --raw_line 'attenuator_mod: 3' \\ + --influx_host c7-graphana --influx_port 8086 --influx_org Candela \\ + --influx_token=-u_Wd-L8o992701QF0c5UmqEp7w7Z7YOMaWLxOMgmHfATJGnQbbmYyNxHBR9PgD6taM_tcxqJl6U8DjU1xINFQ== \\ + --influx_bucket ben \\ + --influx_tag testbed Ferndale-Mesh + + ./lf_rvr_test.py --mgr localhost --port 8080 --lf_user lanforge --lf_password lanforge \\ + --instance_name rvr-instance --config_name test_con --upstream 1.1.eth1 \\ + --dut RootAP --duration 15s --station 1.1.wlan0 \\ + --download_speed 85% --upload_speed 56Kbps \\ + --raw_line 'pkts: MTU' \\ + --raw_line 'directions: DUT Transmit' \\ + --raw_line 'traffic_types: TCP' \\ + --test_rig Ferndale-Mesh-01 --pull_report \\ + --raw_line 'attenuator: 1.1.1040' \\ + --raw_line 'attenuations: 0..+50..950' \\ + --raw_line 'attenuator_mod: 3' \\ + --pull_report \\ + --local_lf_report_dir /tmp/rvr-report \\ + --raw_line 'notes0: my rvr notes' \\ + --raw_line 'notes1: are here.' \\ + --raw_line 'rvr_bringup_wait: 30000' \\ + --raw_line 'first_byte_wait: 30000' """ ) @@ -240,13 +273,14 @@ def main(): parser.add_argument("--dut", default="", help="Specify DUT used by this test, example: linksys-8450") parser.add_argument("--download_speed", default="", - help="Specify requested download speed. Percentage of theoretical is also supported. Default: 85%") + help="Specify requested download speed. Percentage of theoretical is also supported. Default: 85") parser.add_argument("--upload_speed", default="", help="Specify requested upload speed. Percentage of theoretical is also supported. Default: 0") parser.add_argument("--duration", default="", help="Specify duration of each traffic run") parser.add_argument("--graph_groups", help="File to save graph_groups to", default=None) parser.add_argument("--report_dir", default="") + parser.add_argument("--local_lf_report_dir", help="--local_lf_report_dir default '' put where dataplane script run from",default="") args = parser.parse_args() @@ -260,6 +294,7 @@ def main(): config_name=args.config_name, upstream=args.upstream, pull_report=args.pull_report, + local_lf_report_dir = args.local_lf_report_dir, load_old_cfg=args.load_old_cfg, download_speed=args.download_speed, upload_speed=args.upload_speed, diff --git a/py-scripts/lf_rx_sensitivity_test.py b/py-scripts/lf_rx_sensitivity_test.py old mode 100644 new mode 100755 diff --git a/py-scripts/lf_snp_test.py b/py-scripts/lf_snp_test.py index d5a54f8f..05c183c1 100755 --- a/py-scripts/lf_snp_test.py +++ b/py-scripts/lf_snp_test.py @@ -1,41 +1,41 @@ #!/usr/bin/env python3 -''' +""" NAME: lf_snp_test.py snp == Scaling and Performance -PURPOSE: +PURPOSE: -This program is to test an AP connected to a controller. +This program is to test an AP connected to a controller. The AP name is configurable. - The controler - with with a specific ap mode, wifi mode (2.4 Ghz or 5 Ghz), Bandwidth (20,40,80,160) and TX power. -The controller will configure the AP. -The Lanforge radios are configured for a specific client dencity, Packet type (TCP, UDP), Direction (download, upload) and Packet-size. + The controler + with with a specific ap mode, wifi mode (2.4 Ghz or 5 Ghz), Bandwidth (20,40,80,160) and TX power. +The controller will configure the AP. +The Lanforge radios are configured for a specific client dencity, Packet type (TCP, UDP), Direction (download, upload) and Packet-size. The transmission rate will be recorded and compared against the expected rate to determine pass or fail. The results will be recorded in CSV file with the following data AP, Band, wifi_mode, Bandwidth, encryption, ap mode, number of clients, packet type, direction, packet size, measured rx bytes, upload bits per second, -download bits per second. +download bits per second. unique test id, pass / fail, epoch time, and time. TECHNICAL UNDERSTANDING: LANForge Monitored Values Per Polling Interval 'rx bytes' - bytes transmitted - 'rx rate' - bits per second + 'rx rate' - bits per second - in DL direction: -B tx -> -A rx, (side_b_tx_min_bps) LANforge Eth endpoint transmits bytes (AP/DUT), + in DL direction: -B tx -> -A rx, (side_b_tx_min_bps) LANforge Eth endpoint transmits bytes (AP/DUT), station endpoint (Wifi) LANForge receives them. station-end-rx-bps (bits per second) is download rx-bps (bits per second) - in UL direction: -A tx -> -B rx, (side_a_tx_min_bps) LANforge Eth endpoint receives bytes (AP/DUT), + in UL direction: -A tx -> -B rx, (side_a_tx_min_bps) LANforge Eth endpoint receives bytes (AP/DUT), station endpoint (Wifi) LANForge transmits them. ethernet-end-rx-bps (bits per second) is upload load rx-bps (bits per second) configured bps (side_a_tx_min_bps and side_b_tx_min_bps) if lists not same lenght shorter list padded out with 256000 if upload and download selected. NOTES: 1. The controller_client_densities are indpendent of the number of stations on a radio - 2. The --side_a_tx_min_bps (download) and --side_b_tx_min_bps (upload) is used to set the rate - a. default 256000 + 2. The --side_a_tx_min_bps (download) and --side_b_tx_min_bps (upload) is used to set the rate + a. default 256000 The script is devided into parts: -1. Controller Class : CreateCtlr controller interface. +1. Controller Class : CreateCtlr controller interface. Configurable by script: a. Band : a (5ghz) b (2.4ghz) b. wifi_mode : supported modes based on radio @@ -47,13 +47,13 @@ The script is devided into parts: g. packet_type: lf_udp lf_tcp h. traffic direction: upload / download i. pdu: --side_a_min_pdu, --side_b_min_pdu Note: LANforge configuration - + 2. Traffic Generation Class : L3VariableTime a. Creates and brings up stations/clients on radios b. Measures connections c. reports results -3. Scaling And Performance Main +3. Scaling And Performance Main a. Command parcing b. Fixed Configuration Coded Into The Script c. Script Controller Configurations @@ -66,51 +66,51 @@ OUTPUT: html results , default .html pdf results , default .pdf csv results_snp_.csv , results reflected in html and pdf files - csv details_snp_.csv raw data + csv details_snp_.csv raw data * radios and con -EXAMPLE: +EXAMPLE: Use --print_test_config at end of command to see test configuration Test configurations take presidence to command line parameters Using Coded Test Configuration --controller_test_1 - ./lf_snp_test.py --controller_ip 10.195.197.234 --controller_user admin --controller_passwd Milpitas@123 + ./lf_snp_test.py --controller_ip 10.195.197.234 --controller_user admin --controller_passwd Milpitas@123 --controller_aps 'Vanc-e' --controller_series "9800" --endp_types 'lf_udp' --upstream_port eth2 --controller_prompt "Can-SnP-9120" --controller_test_1 --print_test_config Using Coded Test Configuration --controller_test_1 - ./lf_snp_test.py --controller_ip 10.195.197.234 --controller_user admin --controller_passwd Milpitas@123 + ./lf_snp_test.py --controller_ip 10.195.197.234 --controller_user admin --controller_passwd Milpitas@123 --controller_aps 'Vanc-e' --controller_series "9800" --endp_types 'lf_udp' --upstream_port eth2 --controller_prompt "Can-SnP-9120" --controller_test_1 --print_test_config Using Coded Test Configuration: - ./lf_snp_test.py -cc 192.168.100.112 -cu admin -cpw Cisco123 -cca APA453.0E7B.CF9C -cs "3504" --endp_types 'lf_udp' --upstream_port eth2 --controller_test_3 - --controller_prompt "(Cisco Controller)" + ./lf_snp_test.py -cc 192.168.100.112 -cu admin -cpw Cisco123 -cca APA453.0E7B.CF9C -cs "3504" --endp_types 'lf_udp' --upstream_port eth2 --controller_test_3 + --controller_prompt "(Cisco Controller)" --print_test_config Using Commandline with defaults: - ./lf_snp_test.py --controller_ip 192.168.100.112 --controller_user admin --controller_passwd Cisco123 --controller_aps APA453.0E7B.CF9C --controller_series "3504" - --controller_prompt "(Cisco Controller)" --radio "radio==1.wiphy0 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto" + ./lf_snp_test.py --controller_ip 192.168.100.112 --controller_user admin --controller_passwd Cisco123 --controller_aps APA453.0E7B.CF9C --controller_series "3504" + --controller_prompt "(Cisco Controller)" --radio "radio==1.wiphy0 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto" --print_test_config Using Commandline: - ./lf_snp_test.py --controller_ip 192.168.100.112 --controller_user admin --controller_passwd Cisco123 --controller_aps APA453.0E7B.CF9C - --controller_series "3504" --upstream_port eth2 --controller_prompt "(Cisco Controller)" --controller_wifimode "a" --controller_chan_5ghz "36" - --radio "radio==1.wiphy0 stations==10 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==ac" --controller_client_densities "10" + ./lf_snp_test.py --controller_ip 192.168.100.112 --controller_user admin --controller_passwd Cisco123 --controller_aps APA453.0E7B.CF9C + --controller_series "3504" --upstream_port eth2 --controller_prompt "(Cisco Controller)" --controller_wifimode "a" --controller_chan_5ghz "36" + --radio "radio==1.wiphy0 stations==10 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==ac" --controller_client_densities "10" --print_test_config Using Commandline: Setting --test_duration "20s" --polling_interval to 5s -ccd "2" (--controller_client_densities) - ./lf_snp_test.py --controller_ip 192.168.100.112 --controller_user admin --controller_passwd Cisco123 --controller_aps APA453.0E7B.CF9C - --controller_series "3504" --upstream_port eth2 --controller_prompt "(Cisco Controller)" --controller_wifimode "auto" --controller_chan_5ghz "36" - --radio "radio==1.wiphy0 stations==2 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==an" --controller_client_densities "2" + ./lf_snp_test.py --controller_ip 192.168.100.112 --controller_user admin --controller_passwd Cisco123 --controller_aps APA453.0E7B.CF9C + --controller_series "3504" --upstream_port eth2 --controller_prompt "(Cisco Controller)" --controller_wifimode "auto" --controller_chan_5ghz "36" + --radio "radio==1.wiphy0 stations==2 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==an" --controller_client_densities "2" --print_test_config SAMPLE TEST CONFIG: --controller_test_1 output from --print_test_config option 2021-04-21 05:43:25,040 __main__ INFO: USING: controller_test_1 -2021-04-21 05:43:25,040 __main__ INFO: TEST CONFIG: +2021-04-21 05:43:25,040 __main__ INFO: TEST CONFIG: 2021-04-21 05:43:25,040 __main__ INFO: controller_aps ('-cca' ,'--controller_aps'): ['vanc-e'] 2021-04-21 05:43:25,040 __main__ INFO: controller_bands ('-ccf' ,'--controller_bands'): ['a', 'b'] 2021-04-21 05:43:25,040 __main__ INFO: controller_wifimodes ('-cwm' ,'--controller_wifimodes'): ['an', 'anAX', 'anAC', 'abgn', 'bg'] @@ -136,7 +136,7 @@ COPYWRITE Copyright 2021 Candela Technologies Inc License: Free to distribute and modify. LANforge systems must be licensed. -''' +""" import sys import os import importlib @@ -154,57 +154,62 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - +from lf_report import lf_report + sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) LFUtils = importlib.import_module("py-json.LANforge.LFUtils") realm = importlib.import_module("py-json.realm") Realm = realm.Realm -lf_report = importlib.import_module("py-scripts.lf_report") # lf_graph = importlib.import_module("py-scripts.lf_graph") # lf_bar_graph = lf_graph.lf_bar_graph FORMAT = '%(asctime)s %(name)s %(levelname)s: %(message)s' + + # see https://stackoverflow.com/a/13306095/11014343 class FileAdapter(object): def __init__(self, logger): self.logger = logger + def write(self, data): # NOTE: data can be a partial line, multiple lines - data = data.strip() # ignore leading/trailing whitespace - if data: # non-blank - self.logger.info(data) + data = data.strip() # ignore leading/trailing whitespace + if data: # non-blank + self.logger.info(data) + def flush(self): pass # leave it to logging to flush properly + ################################################################################ # # Controller Class : CrateCtlr controller interface # ################################################################################ -class CreateCtlr(): +class CreateCtlr: def __init__(self, - _scheme, - _port, - _series, - _ctlr, - _prompt, - _user, - _passwd, - _ap, - _band, - _chan_5ghz, - _chan_24ghz, - _chan_width, - _ap_mode, - _tx_power, - _wlan, - _cap_ctl_out): + _scheme, + _port, + _series, + _ctlr, + _prompt, + _user, + _passwd, + _ap, + _band, + _chan_5ghz, + _chan_24ghz, + _chan_width, + _ap_mode, + _tx_power, + _wlan, + _cap_ctl_out): self.scheme = _scheme - self.port = _port + self.port = _port self.series = _series self.ctlr = _ctlr self.prompt = _prompt @@ -221,8 +226,8 @@ class CreateCtlr(): self.cap_ctl_out = _cap_ctl_out self.client_density = 0 - #show summary (to get AP) (3400/9800) - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 --action summary --series 9800 --log stdout + # show summary (to get AP) (3400/9800) + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 --action summary --series 9800 --log stdout def controller_show_summary(self): pss = "" try: @@ -237,553 +242,670 @@ class CreateCtlr(): series: {} \ band: {} \ action: {}".format( - self.scheme, - self.ctlr, - self.port, - self.prompt, - self.user, - self.passwd, - self.ap, - self.series, - self.band, - "summary")) + self.scheme, + self.ctlr, + self.port, + self.prompt, + self.user, + self.passwd, + self.ap, + self.series, + self.band, + "summary")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", - "--scheme", self.scheme, - "--prompt", self.prompt, - "--port", self.port, - "-d", self.ctlr, - "-u", self.user, - "-p", self.passwd, - "-a", self.ap, - "--series", self.series, - "--band", self.band, - "--action", "summary"], - capture_output=self.cap_ctl_out, + ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", + "--scheme", self.scheme, + "--prompt", self.prompt, + "--port", self.port, + "-d", self.ctlr, + "-u", self.user, + "-p", self.passwd, + "-a", self.ap, + "--series", self.series, + "--band", self.band, + "--action", "summary"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}" - .format(process_error.returncode, process_error.output)) - time.sleep(1) - exit(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) + exit(1) return pss - #show ap dot11 5ghz summary (band defaults to 5ghz) --band a - #show ap dot11 24ghz summary use --band b for 2.4 ghz - #action advanced (3400/9800) - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 --action advanced --series 9800 --log stdout + # show ap dot11 5ghz summary (band defaults to 5ghz) --band a + # show ap dot11 24ghz summary use --band b for 2.4 ghz + # action advanced (3400/9800) + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 --action advanced --series 9800 --log stdout def controller_show_ap_summary(self): pss = "" try: logg.info("\ - scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,"advanced")) + scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, "advanced")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "advanced"], - capture_output=True, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "advanced"], + capture_output=True, check=True) pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) return pss - #show wlan summary + # show wlan summary def controller_show_wlan_summary(self): try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,"show wlan summary")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, "show wlan summary")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "show_wlan_summary"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "show_wlan_summary"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - #disable AP - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action disable --series 9800 + # disable AP + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action disable --series 9800 def controller_disable_ap(self): try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,"disable")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, "disable")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", - self.ctlr, "-u",self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "disable"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", + self.ctlr, "-u", self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "disable"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - #disable wlan - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action disable_wlan --series 9800 + # disable wlan + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action disable_wlan --series 9800 def controller_disable_wlan(self): try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} wlan: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,self.wlan,"disable_wlan")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} wlan: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, self.wlan, "disable_wlan")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band,"--wlan", self.wlan, "--action", "disable_wlan"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--wlan", self.wlan, "--action", + "disable_wlan"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - #disable network 5ghz - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action disable_network_5ghz --series 9800 + # disable network 5ghz + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action disable_network_5ghz --series 9800 def controller_disable_network_5ghz(self): if self.series == "9800": try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,"disable_network_5ghz")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, "disable_network_5ghz")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "disable_network_5ghz"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "disable_network_5ghz"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) else: try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"cmd","config 802.11a disable network")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "cmd", "config 802.11a disable network")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "cmd", "--value", "config 802.11a disable network"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "cmd", "--value", + "config 802.11a disable network"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - #disable network 24ghz - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action disable_network_24ghz --series 9800 + # disable network 24ghz + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action disable_network_24ghz --series 9800 def controller_disable_network_24ghz(self): if self.series == "9800": try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,"disable_network_24ghz")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, "disable_network_24ghz")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "disable_network_24ghz"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "disable_network_24ghz"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) else: try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"cmd","config 802.11b disable network")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "cmd", "config 802.11b disable network")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "cmd", "--value", "config 802.11b disable network"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "cmd", "--value", + "config 802.11b disable network"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - #set manual mode - Series 9800 must be set to manual mode - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action manual --series 9800 + # set manual mode - Series 9800 must be set to manual mode + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action manual --series 9800 # ap name dot11 5ghz radio role manual client-serving def controller_role_manual(self): if self.series == "9800": try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,"manual")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, "manual")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "manual"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "manual"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) else: - logg.info("Check the controller scheme used attemping 9800 series on 3504 controller: {}".format(self.scheme)) + logg.info( + "Check the controller scheme used attemping 9800 series on 3504 controller: {}".format(self.scheme)) - #set manual mode - Series 9800 must be set to auto mode - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action auto --series 9800 + # set manual mode - Series 9800 must be set to auto mode + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action auto --series 9800 # ap name dot11 5ghz radio role manual client-serving def controller_role_auto(self): if self.series == "9800": try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user, - self.passwd,self.ap,self.series,self.band,"auto")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, + self.passwd, self.ap, self.series, self.band, "auto")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "auto"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "auto"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) else: - logg.info("Check the controller scheme used attemping 9800 series on 3504 controller: {}".format(self.scheme)) + logg.info( + "Check the controller scheme used attemping 9800 series on 3504 controller: {}".format(self.scheme)) - #test parameters summary (txPower 1-8) - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action txPower --value 5 --series 9800 + # test parameters summary (txPower 1-8) + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action txPower --value 5 --series 9800 def controller_set_tx_power(self): try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"txPower", self.tx_power )) # TODO fix txPower to tx_power in wifi_ctl_9800_3504.py - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, - "--action", "txPower","--value", self.tx_power], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "txPower", self.tx_power)) # TODO fix txPower to tx_power in wifi_ctl_9800_3504.py + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, + "--action", "txPower", "--value", self.tx_power], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - #set channel [36, 64, 100] - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action channel --value 36 --series 9800 + # set channel [36, 64, 100] + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action channel --value 36 --series 9800 # 9800 : ap name dot11 [5ghz | 24ghz] channel # 3504 : (controller Controller) >config 802.11a channel ap APA453.0E7B.CF9C 52 def controller_set_channel(self): try: - if (self.band == "a"): + if self.band == "a": controller_channel = self.chan_5ghz else: controller_channel = self.chan_24ghz - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"channel", controller_channel )) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, - "--action", "channel","--value", controller_channel], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "channel", controller_channel)) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, + "--action", "channel", "--value", controller_channel], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - #set bandwidth [20 40 80 160] - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action bandwidth --value 40 --series 9800 + # set bandwidth [20 40 80 160] + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action bandwidth --value 40 --series 9800 def controller_set_bandwidth(self): try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"channel", self.chan_width )) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, - "--action", "channel","--value", self.chan_width], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "channel", self.chan_width)) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, + "--action", "channel", "--value", self.chan_width], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) - + except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - #create wlan - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action create_wlan --wlan "open-wlan" --wlanID 1 --series 9800 + # create wlan + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action create_wlan --wlan "open-wlan" --wlanID 1 --series 9800 def controller_create_wlan(self): if self.series == "9800": try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} wlan {} wlanID {} wlanSSID {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"create_wlan", self.wlan, self.wlanID, self.wlanSSID )) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, - "--action", "create_wlan","--wlan", self.wlan, "--wlanID", self.wlanID, "--wlanSSID", self.wlanSSID], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} wlan {} wlanID {} wlanSSID {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "create_wlan", self.wlan, self.wlanID, self.wlanSSID)) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, + "--action", "create_wlan", "--wlan", self.wlan, "--wlanID", self.wlanID, "--wlanSSID", + self.wlanSSID], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) - + except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) else: - logg.info("Check the controller_scheme used attemping 9800 series on 3504 controller: {}".format(self.scheme)) + logg.info( + "Check the controller_scheme used attemping 9800 series on 3504 controller: {}".format(self.scheme)) - #create wireless tag policy --9800 series needs to have wireless tag policy set - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action wireless_tag_policy --series 9800 + # create wireless tag policy --9800 series needs to have wireless tag policy set + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action wireless_tag_policy --series 9800 def controller_set_wireless_tag_policy(self): if self.series == "9800": try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"wireless_tag_policy" )) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, - "--action", "wireless_tag_policy"], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "wireless_tag_policy")) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, + "--action", "wireless_tag_policy"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) else: - logg.info("Check the controller_scheme used attemping 9800 series on 3504 controller: {}".format(self.scheme)) + logg.info( + "Check the controller_scheme used attemping 9800 series on 3504 controller: {}".format(self.scheme)) - #enable wlan - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action enable_wlan --series 9800 + # enable wlan + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action enable_wlan --series 9800 def controller_enable_wlan(self): try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} wlan: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band, self.wlan,"enable_wlan")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--wlan", self.wlan, - "--action", "enable_wlan"], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} wlan: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, self.wlan, "enable_wlan")) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--wlan", self.wlan, + "--action", "enable_wlan"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) - + except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - #enable 5ghz - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action enable_network_5ghz --series 9800 + # enable 5ghz + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action enable_network_5ghz --series 9800 def controller_enable_network_5ghz(self): if self.series == "9800": try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"enable_network_5ghz")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, - "--action", "enable_network_5ghz"], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "enable_network_5ghz")) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, + "--action", "enable_network_5ghz"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) - + except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) else: try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"cmd","config 802.11a enable network")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "cmd", "config 802.11a enable network")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "cmd", "--value", "config 802.11a enable network"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "cmd", "--value", + "config 802.11a enable network"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - #enable 24ghz - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action enable_network_24ghz --series 9800 + # enable 24ghz + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action enable_network_24ghz --series 9800 def controller_enable_network_24ghz(self): if self.series == "9800": try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"enable_network_24ghz")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, - "--action", "enable_network_24ghz"], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "enable_network_24ghz")) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, + "--action", "enable_network_24ghz"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) else: try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"cmd","config 802.11b enable network")) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {} value: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "cmd", "config 802.11b enable network")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, "--action", "cmd", "--value", "config 802.11b enable network"], - capture_output=self.cap_ctl_out, check=True) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, "--action", "cmd", "--value", + "config 802.11b enable network"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - #enable (band a) - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action enable --series 9800 + # enable (band a) + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action enable --series 9800 def controller_enable_ap(self): try: - logg.info("scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format(self.scheme, - self.ctlr,self.port,self.prompt,self.user,self.passwd, self.ap, self.series, - self.band,"enable")) - ctl_output = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--band", self.band, - "--action", "enable"], - capture_output=self.cap_ctl_out, check=True) + logg.info( + "scheme: {} ctlr: {} port: {} prompt: {} user: {} passwd: {} AP: {} series: {} band: {} action: {}".format( + self.scheme, + self.ctlr, self.port, self.prompt, self.user, self.passwd, self.ap, self.series, + self.band, "enable")) + ctl_output = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, + "-d", self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--band", self.band, + "--action", "enable"], + capture_output=self.cap_ctl_out, check=True) if self.cap_ctl_out: pss = ctl_output.stdout.decode('utf-8', 'ignore') logg.info(pss) except subprocess.CalledProcessError as process_error: - logg.info("Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}". - format(process_error.returncode, process_error.output)) - time.sleep(1) + logg.info( + "Command Error, Controller unable to commicate to AP or unable to communicate to controller error code: {} output {}".format( + process_error.returncode, process_error.output)) + time.sleep(1) exit(1) - #advanced (showes summary) - #./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action advanced --series 9800 + # advanced (showes summary) + # ./wifi_ctl_9800_3504.py --scheme ssh -d 172.19.36.168 -p --port 23 -a "9120-Chamber-1" --band a --action advanced --series 9800 def controller_show_ap_channel(self): - advanced = subprocess.run(["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", self.ctlr, "-u", - self.user, "-p", self.passwd, - "-a", self.ap,"--series", self.series, "--action", "ap_channel"], capture_output=True) + advanced = subprocess.run( + ["../wifi_ctl_9800_3504.py", "--scheme", self.scheme, "--prompt", self.prompt, "--port", self.port, "-d", + self.ctlr, "-u", + self.user, "-p", self.passwd, + "-a", self.ap, "--series", self.series, "--action", "ap_channel"], capture_output=True) pss = advanced.stdout.decode('utf-8', 'ignore') logg.info(pss) if self.series == "9800": - if (self.band == "a"): + if self.band == "a": controller_channel = self.chan_5ghz else: controller_channel = self.chan_24ghz @@ -793,44 +915,55 @@ class CreateCtlr(): logg.info("line {}".format(line)) element_list = line.lstrip().split() logg.info("element_list {}".format(element_list)) - if (line.lstrip().startswith(search_str)): + if line.lstrip().startswith(search_str): logg.info("line {}".format(line)) element_list = line.lstrip().split() logg.info("element_list {}".format(element_list)) # AP Name (0) mac (1) slot (2) Admin State [enable/disable] (3) Oper State [Up/Down] (4) Width (5) Txpwr (6,7) channel (8) mode (9) - logg.info("ap: {} slof {} channel {} chan_width {}".format(element_list[0],element_list[2],element_list[8],element_list[5])) - if (str(controller_channel) in str(element_list[8])) and (str(self.chan_width) in str(element_list[5])): - logg.info("ap {} configuration successful: channel {} in expected {} chan_width {} in expected {}" - .format(element_list[0],controller_channel,element_list[8],self.chan_width,element_list[5])) + logg.info("ap: {} slof {} channel {} chan_width {}".format(element_list[0], element_list[2], + element_list[8], element_list[5])) + if (str(controller_channel) in str(element_list[8])) and ( + str(self.chan_width) in str(element_list[5])): + logg.info( + "ap {} configuration successful: channel {} in expected {} chan_width {} in expected {}".format( + element_list[0], + controller_channel, + element_list[8], + self.chan_width, + element_list[5])) else: logg.info("WARNING ap {} configuration: channel {} in expected {} chan_width {} in expected {}" - .format(element_list[0],controller_channel,element_list[8],self.chan_width,element_list[5])) + .format(element_list[0], controller_channel, element_list[8], self.chan_width, + element_list[5])) break else: logg.info("checking for 802.11{}".format(self.band)) - if (self.band == "a"): + if self.band == "a": controller_channel = self.chan_5ghz else: controller_channel = self.chan_24ghz for line in pss.splitlines(): - #logg.info("line {}".format(line)) + # logg.info("line {}".format(line)) search_str = "802.11{}".format(self.band) - if (line.lstrip().startswith(search_str)): + if line.lstrip().startswith(search_str): logg.info("line {}".format(line)) element_list = line.lstrip().split() logg.info("element_list {}".format(element_list)) - logg.info("ap: {} channel {} chan_width {}".format(self.ap,element_list[4],element_list[5])) - if (str(controller_channel) in str(element_list[4])) and (str(self.chan_width) in str(element_list[5])): + logg.info("ap: {} channel {} chan_width {}".format(self.ap, element_list[4], element_list[5])) + if (str(controller_channel) in str(element_list[4])) and ( + str(self.chan_width) in str(element_list[5])): logg.info("ap configuration successful: channel {} in expected {} chan_width {} in expected {}" - .format(controller_channel,element_list[4],self.chan_width,element_list[5])) + .format(controller_channel, element_list[4], self.chan_width, element_list[5])) else: logg.info("AP WARNING: channel {} expected {} chan_width {} expected {}" - .format(element_list[4],controller_channel,element_list[5],self.chan_width)) + .format(element_list[4], controller_channel, element_list[5], self.chan_width)) break - - logg.info("configure ap {} channel {} chan_width {}".format(self.ap,self.channel,self.chan_width)) + + logg.info("configure ap {} channel {} chan_width {}".format(self.ap, self.channel, self.chan_width)) # Verify channel and channel width. + + ################################################################################ # # End of Controller Class : controller interface @@ -843,65 +976,65 @@ class CreateCtlr(): # ################################################################################ class L3VariableTime(Realm): - def __init__(self, - args, - _scheme, - _port, - _series, - _ctlr, - _prompt, - _user, - _passwd, - _ap, - _ap_slot, - _band, - _chan_5ghz, - _chan_24ghz, - _chan_width, - _ap_mode, - _tx_power, - _client_density, - _cap_ctl_out, - _ap_dict, - endp_type, - tos, - side_b, - radio_name_list, - number_of_stations_per_radio_list, - ssid_list, - ssid_password_list, - ssid_security_list, - wifimode_list, - station_lists, - name_prefix, - debug_on, - outfile, - results, - test_keys, - test_config, - reset_port_enable_list, - reset_port_time_min_list, - reset_port_time_max_list, - csv_started=False, - side_a_tx_min_bps=560000, - side_a_tx_max_bps=0, # setting to 0 will match min - side_a_min_pdu=1518, - side_a_max_pdu=0, - side_b_tx_min_bps=560000, - side_b_tx_max_bps=0, # setting to 0 will match min - side_b_min_pdu=1518, - side_b_max_pdu=0, - number_template="00", - test_duration="256s", - polling_interval="60s", - lfclient_host="localhost", - lfclient_port=8080, - debug=False, - wait_timeout=120, - _exit_on_error=False, - _exit_on_fail=False, - _proxy_str=None, - _capture_signal_list=[]): + def __init__(self, + args, + _scheme, + _port, + _series, + _ctlr, + _prompt, + _user, + _passwd, + _ap, + _ap_slot, + _band, + _chan_5ghz, + _chan_24ghz, + _chan_width, + _ap_mode, + _tx_power, + _client_density, + _cap_ctl_out, + _ap_dict, + endp_type, + tos, + side_b, + radio_name_list, + number_of_stations_per_radio_list, + ssid_list, + ssid_password_list, + ssid_security_list, + wifimode_list, + station_lists, + name_prefix, + debug_on, + outfile, + results, + test_keys, + test_config, + reset_port_enable_list, + reset_port_time_min_list, + reset_port_time_max_list, + csv_started=False, + side_a_tx_min_bps=560000, + side_a_tx_max_bps=0, # setting to 0 will match min + side_a_min_pdu=1518, + side_a_max_pdu=0, + side_b_tx_min_bps=560000, + side_b_tx_max_bps=0, # setting to 0 will match min + side_b_min_pdu=1518, + side_b_max_pdu=0, + number_template="00", + test_duration="256s", + polling_interval="60s", + lfclient_host="localhost", + lfclient_port=8080, + debug=False, + wait_timeout=120, + _exit_on_error=False, + _exit_on_fail=False, + _proxy_str=None, + _capture_signal_list=None): super().__init__(lfclient_host=lfclient_host, lfclient_port=lfclient_port, debug_=debug, @@ -909,17 +1042,19 @@ class L3VariableTime(Realm): _exit_on_fail=_exit_on_fail, _proxy_str=_proxy_str, _capture_signal_list=_capture_signal_list) + if _capture_signal_list is None: + _capture_signal_list = [] self.scheme = _scheme - self.port = _port + self.port = _port self.series = _series - self.ctlr = _ctlr + self.ctlr = _ctlr self.prompt = _prompt - self.user = _user + self.user = _user self.passwd = _passwd - self.ap = _ap + self.ap = _ap self.ap_slot = _ap_slot - self.band = _band - self.chan_5ghz = _chan_5ghz + self.band = _band + self.chan_5ghz = _chan_5ghz self.chan_24ghz = _chan_24ghz self.chan_width = _chan_width self.ap_mode = _ap_mode @@ -932,7 +1067,7 @@ class L3VariableTime(Realm): self.side_b = side_b self.ssid_list = ssid_list self.ssid_password_list = ssid_password_list - self.station_lists = station_lists + self.station_lists = station_lists self.ssid_security_list = ssid_security_list self.wifimode_list = wifimode_list self.reset_port_enable_list = reset_port_enable_list @@ -942,8 +1077,8 @@ class L3VariableTime(Realm): self.name_prefix = name_prefix self.test_duration = test_duration self.radio_name_list = radio_name_list - self.number_of_stations_per_radio_list = number_of_stations_per_radio_list - #self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port, debug_=debug_on) + self.number_of_stations_per_radio_list = number_of_stations_per_radio_list + # self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port, debug_=debug_on) self.polling_interval_seconds = self.duration_time_to_seconds(polling_interval) self.cx_profile = self.new_l3_cx_profile() self.multicast_profile = self.new_multicast_profile() @@ -970,44 +1105,48 @@ class L3VariableTime(Realm): self.test_keys = test_keys self.test_config = test_config - self.test_config_dict = dict(map(lambda x: x.split('=='), str(self.test_config).replace('[','').replace(']','').replace("'","").split())) + self.test_config_dict = dict(map(lambda x: x.split('=='), + str(self.test_config).replace('[', '').replace(']', '').replace("'", + "").split())) # Full spread-sheet data if self.outfile is not None: - self.csv_file_details = open(self.outfile, "a+") + self.csv_file_details = open(self.outfile, "a+") self.csv_writer = csv.writer(self.csv_file_details, delimiter=",") - + if self.results is not None: - self.csv_results = open(self.results, "a+") + self.csv_results = open(self.results, "a+") self.csv_results_writer = csv.writer(self.csv_results, delimiter=",") - for (radio_, ssid_, ssid_password_, ssid_security_, wifimode_,\ - reset_port_enable_, reset_port_time_min_, reset_port_time_max_) \ - in zip(radio_name_list, ssid_list, ssid_password_list, ssid_security_list, wifimode_list,\ - reset_port_enable_list, reset_port_time_min_list, reset_port_time_max_list): + for (radio_, ssid_, ssid_password_, ssid_security_, wifimode_, + reset_port_enable_, reset_port_time_min_, reset_port_time_max_) \ + in zip(radio_name_list, ssid_list, ssid_password_list, ssid_security_list, wifimode_list, + reset_port_enable_list, reset_port_time_min_list, reset_port_time_max_list): self.station_profile = self.new_station_profile() self.station_profile.lfclient_url = self.lfclient_url self.station_profile.ssid = ssid_ self.station_profile.ssid_pass = ssid_password_ self.station_profile.security = ssid_security_ - self.station_profile.mode = wifimode_ + self.station_profile.mode = wifimode_ self.station_profile.number_template = self.number_template - self.station_profile.mode = wifimode_ - self.station_profile.set_reset_extra(reset_port_enable=reset_port_enable_,\ - test_duration=self.duration_time_to_seconds(self.test_duration),\ - reset_port_min_time=self.duration_time_to_seconds(reset_port_time_min_),\ - reset_port_max_time=self.duration_time_to_seconds(reset_port_time_max_)) + self.station_profile.mode = wifimode_ + self.station_profile.set_reset_extra(reset_port_enable=reset_port_enable_, + test_duration=self.duration_time_to_seconds(self.test_duration), + reset_port_min_time=self.duration_time_to_seconds( + reset_port_time_min_), + reset_port_max_time=self.duration_time_to_seconds( + reset_port_time_max_)) self.station_profiles.append(self.station_profile) - + self.multicast_profile.host = self.lfclient_host self.cx_profile.host = self.lfclient_host self.cx_profile.port = self.lfclient_port self.cx_profile.name_prefix = self.name_prefix - self.cx_profile.side_a_min_bps = self.side_a_tx_min_bps # Note: side_a_tx_min_bps is side_a_min_bps in py-json profiles - self.cx_profile.side_a_max_bps = self.side_a_tx_min_bps + self.cx_profile.side_a_min_bps = self.side_a_tx_min_bps # Note: side_a_tx_min_bps is side_a_min_bps in py-json profiles + self.cx_profile.side_a_max_bps = self.side_a_tx_min_bps self.cx_profile.side_a_min_pdu = self.side_a_min_pdu self.cx_profile.side_a_max_pdu = self.side_a_max_pdu - self.cx_profile.side_b_min_bps = self.side_b_tx_min_bps # Note: side_b_tx_min_bps is side_b_min_bps in py-json profiles + self.cx_profile.side_b_min_bps = self.side_b_tx_min_bps # Note: side_b_tx_min_bps is side_b_min_bps in py-json profiles self.cx_profile.side_b_max_bps = self.side_b_tx_min_bps self.cx_profile.side_b_min_pdu = self.side_b_min_pdu self.cx_profile.side_b_max_pdu = self.side_b_max_pdu @@ -1029,26 +1168,26 @@ class L3VariableTime(Realm): our_endps[e] = e for endp_name in endp_list['endpoint']: if endp_name != 'uri' and endp_name != 'handler': - for item, value in endp_name.items(): + for item, endp_value in endp_name.items(): if item in our_endps: - endps.append(value) + endps.append(endp_value) print("endpoint: ", item, " value:\n") - pprint(value) - - for value_name, value in value.items(): + pprint(endp_value) + + for value_name, value in endp_value.items(): if value_name == 'rx bytes': endp_rx_map[item] = value if value_name == 'rx drop %': endp_rx_drop_map[item] = value if value_name == 'rx rate': # This hack breaks for mcast or if someone names endpoints weirdly. - #print("item: ", item, " rx-bps: ", value_rx_bps) + # print("item: ", item, " rx-bps: ", value_rx_bps) if item.endswith("-A"): total_dl += int(value) else: total_ul += int(value) - #print("total-dl: ", total_dl, " total-ul: ", total_ul, "\n") + # print("total-dl: ", total_dl, " total-ul: ", total_ul, "\n") return endp_rx_map, endp_rx_drop_map, endps, total_dl, total_ul def time_stamp(self): @@ -1064,13 +1203,15 @@ class L3VariableTime(Realm): csv_rx_delta_dict = {} test_id = "" - for key in [key for key in old_list if "mtx" in key]: del old_list[key] - for key in [key for key in new_list if "mtx" in key]: del new_list[key] + for key in [key for key in old_list if "mtx" in key]: + del old_list[key] + for key in [key for key in new_list if "mtx" in key]: + del new_list[key] - filtered_values = [v for _, v in new_list.items() if v !=0] + filtered_values = [v for _, v in new_list.items() if v != 0] # Evaluate upload or download new_evaluate_list = new_list.copy() - print("new_evaluate_list before",new_evaluate_list) + print("new_evaluate_list before", new_evaluate_list) # look at ul and dl old_evaluate_list = old_list.copy() @@ -1078,40 +1219,41 @@ class L3VariableTime(Realm): for item, value in old_evaluate_list.items(): # check only upload or download - expected passes corresponds to traffic only in observed direction if "upload" in self.test_config_dict.values() and item.endswith("-B") \ - or "download" in self.test_config_dict.values() and item.endswith("-A"): - expected_passes +=1 + or "download" in self.test_config_dict.values() and item.endswith("-A"): + expected_passes += 1 print("ITEM: {} VALUE: {}".format(item, value)) if new_evaluate_list[item] > old_evaluate_list[item]: passes += 1 - #if self.debug: logg.info(item, new_evaluate_list[item], old_evaluate_list[item], " Difference: ", new_evaluate_list[item] - old_evaluate_list[item]) - print(item, new_evaluate_list[item], old_evaluate_list[item], " Difference: ", new_evaluate_list[item] - old_evaluate_list[item]) + # if self.debug: logg.info(item, new_evaluate_list[item], old_evaluate_list[item], " Difference: ", new_evaluate_list[item] - old_evaluate_list[item]) + print(item, new_evaluate_list[item], old_evaluate_list[item], " Difference: ", + new_evaluate_list[item] - old_evaluate_list[item]) else: if "upload" in self.test_config_dict.values() and item.endswith("-B") \ - or "download" in self.test_config_dict.values() and item.endswith("-A"): + or "download" in self.test_config_dict.values() and item.endswith("-A"): # only a failure if expecting traffic in that direction print("Failed to increase rx bytes: ", item, new_evaluate_list[item], old_evaluate_list[item]) if not self.csv_started: # stations that end in -A are dl (download, download), stations that end in -B are ul (upload, upload) if item.endswith("-A"): - csv_rx_headers.append(item+'-dl-rx-bytes') + csv_rx_headers.append(item + '-dl-rx-bytes') else: - csv_rx_headers.append(item+'-ul-rx-bytes') - csv_rx_delta_dict.update({item:(new_evaluate_list[item] - old_evaluate_list[item])}) - + csv_rx_headers.append(item + '-ul-rx-bytes') + csv_rx_delta_dict.update({item: (new_evaluate_list[item] - old_evaluate_list[item])}) + if not self.csv_started: csv_header = self.csv_generate_column_details_headers() csv_header += csv_rx_headers logg.info(csv_header) self.csv_add_column_headers(csv_header) csv_results = self.csv_generate_column_results_headers() - #csv_results += csv_rx_headers + # csv_results += csv_rx_headers self.csv_add_column_headers_results(csv_results) self.csv_started = True # need to generate list of all the values - filtered_values = [v for _, v in csv_rx_delta_dict.items() if v !=0] + filtered_values = [v for _, v in csv_rx_delta_dict.items() if v != 0] # if need the average use average_rx_delta - #average_rx_delta= sum(filtered_values) / len(filtered_values) if len(filtered_values) != 0 else 0 + # average_rx_delta= sum(filtered_values) / len(filtered_values) if len(filtered_values) != 0 else 0 # write out the configuraiton for the test for key in self.test_keys: @@ -1122,7 +1264,7 @@ class L3VariableTime(Realm): csv_rx_row_data.extend([self.epoch_time, self.time_stamp()]) csv_result_row_data.extend([self.epoch_time, self.time_stamp()]) - #Generate TestID + # Generate TestID for key in self.test_keys: test_id = test_id + "_" + self.test_config_dict[key] @@ -1137,22 +1279,23 @@ class L3VariableTime(Realm): csv_rx_row_data.append(self.side_b_tx_min_bps) # Recorde the Total Transmit rate for all stations - rx_bytes = sum(filtered_values) #total + rx_bytes = sum(filtered_values) # total csv_rx_row_data.append(rx_bytes) # The total_dl_bps and total_up_bps is for the interval csv_rx_row_data.append(total_dl_bps) csv_rx_row_data.append(total_ul_bps) - #csv_result_row_data.append(rx_bytes) + # csv_result_row_data.append(rx_bytes) print("csv_rx_row_data {}".format(csv_rx_row_data)) - #TODO: may want to pass in the information that needs to be in the csv file into the class - + # TODO: may want to pass in the information that needs to be in the csv file into the class + for item, value in old_evaluate_list.items(): - expected_passes +=1 + expected_passes += 1 if new_evaluate_list[item] > old_evaluate_list[item]: passes += 1 - print(item, new_evaluate_list[item], old_evaluate_list[item], " Difference: ", new_evaluate_list[item] - old_evaluate_list[item]) + print(item, new_evaluate_list[item], old_evaluate_list[item], " Difference: ", + new_evaluate_list[item] - old_evaluate_list[item]) else: print("Failed to increase rx data: ", item, new_evaluate_list[item], old_evaluate_list[item]) if not self.csv_started: @@ -1161,36 +1304,46 @@ class L3VariableTime(Realm): csv_rx_row_data.append(new_list[item] - old_list[item]) # data from each station for each iteration - self.csv_add_row(csv_rx_row_data,self.csv_writer,self.csv_file_details) + self.csv_add_row(csv_rx_row_data, self.csv_writer, self.csv_file_details) if passes == expected_passes: return True, rx_bytes, csv_result_row_data else: return False, rx_bytes, csv_result_row_data else: - print("Old-list length: %i new: %i does not match in compare-vals."%(len(old_list), len(new_list))) - print("old-list:",old_list) - print("new-list:",new_list) - return False, None, None + print("Old-list length: %i new: %i does not match in compare-vals." % (len(old_list), len(new_list))) + print("old-list:", old_list) + print("new-list:", new_list) + return False, None, None def reset_port_check(self): for station_profile in self.station_profiles: if station_profile.reset_port_extra_data['reset_port_enable']: - if station_profile.reset_port_extra_data['reset_port_timer_started'] == False: - logg.info("reset_port_time_min: {}".format(station_profile.reset_port_extra_data['reset_port_time_min'])) - logg.info("reset_port_time_max: {}".format(station_profile.reset_port_extra_data['reset_port_time_max'])) + if not station_profile.reset_port_extra_data['reset_port_timer_started']: + logg.info( + "reset_port_time_min: {}".format(station_profile.reset_port_extra_data['reset_port_time_min'])) + logg.info( + "reset_port_time_max: {}".format(station_profile.reset_port_extra_data['reset_port_time_max'])) station_profile.reset_port_extra_data['seconds_till_reset'] = \ - random.randint(station_profile.reset_port_extra_data['reset_port_time_min'],\ - station_profile.reset_port_extra_data['reset_port_time_max']) + random.randint(station_profile.reset_port_extra_data['reset_port_time_min'], + station_profile.reset_port_extra_data['reset_port_time_max']) station_profile.reset_port_extra_data['reset_port_timer_started'] = True - logg.info("on radio {} seconds_till_reset {}".format(station_profile.add_sta_data['radio'],station_profile.reset_port_extra_data['seconds_till_reset'])) + logg.info("on radio {} seconds_till_reset {}".format(station_profile.add_sta_data['radio'], + station_profile.reset_port_extra_data[ + 'seconds_till_reset'])) else: - station_profile.reset_port_extra_data['seconds_till_reset'] = station_profile.reset_port_extra_data['seconds_till_reset'] - 1 - if self.debug: logg.info("radio: {} countdown seconds_till_reset {}".format(station_profile.add_sta_data['radio'] ,station_profile.reset_port_extra_data['seconds_till_reset'])) - if ((station_profile.reset_port_extra_data['seconds_till_reset'] <= 0)): + station_profile.reset_port_extra_data['seconds_till_reset'] = station_profile.reset_port_extra_data[ + 'seconds_till_reset'] - 1 + if self.debug: + logg.info( + "radio: {} countdown seconds_till_reset {}".format(station_profile.add_sta_data['radio'], + station_profile.reset_port_extra_data[ + 'seconds_till_reset'])) + if station_profile.reset_port_extra_data['seconds_till_reset'] <= 0: station_profile.reset_port_extra_data['reset_port_timer_started'] = False - port_to_reset = random.randint(0,len(station_profile.station_names)-1) - logg.info("reset on radio {} station: {}".format(station_profile.add_sta_data['radio'],station_profile.station_names[port_to_reset])) + port_to_reset = random.randint(0, len(station_profile.station_names) - 1) + logg.info("reset on radio {} station: {}".format(station_profile.add_sta_data['radio'], + station_profile.station_names[port_to_reset])) self.reset_port(station_profile.station_names[port_to_reset]) def pre_cleanup(self): @@ -1204,12 +1357,12 @@ class L3VariableTime(Realm): # Verify Stations are Gone count = 0 - while (count < 10): + while count < 10: more = False for station_list in self.station_lists: for sta in station_list: rv = self.rm_port(sta, check_exists=True) - if (rv): + if rv: more = True if not more: break @@ -1223,24 +1376,28 @@ class L3VariableTime(Realm): station_profile.set_number_template(station_profile.number_template) logg.info("Creating stations") - station_profile.create(radio=self.radio_name_list[index], sta_names_=self.station_lists[index], debug=self.debug, sleep_time=0) + station_profile.create(radio=self.radio_name_list[index], sta_names_=self.station_lists[index], + debug=self.debug, sleep_time=0) index += 1 for _tos in self.tos: - logg.info("Creating connections for endpoint type: {} TOS: {} stations_names {}".format(self.endp_type, _tos, station_profile.station_names)) - self.cx_profile.create(endp_type=self.endp_type, side_a=station_profile.station_names, side_b=self.side_b, sleep_time=0, tos=_tos) - self._pass("PASS: Stations build finished") - + logg.info( + "Creating connections for endpoint type: {} TOS: {} stations_names {}".format(self.endp_type, _tos, + station_profile.station_names)) + self.cx_profile.create(endp_type=self.endp_type, side_a=station_profile.station_names, + side_b=self.side_b, sleep_time=0, tos=_tos) + self._pass("PASS: Stations build finished") + def start(self, print_pass=False, print_fail=False): best_rx_bytes = 0 rx_bytes = 0 csv_rx_row_data = " " Result = False logg.info("Bringing up stations") - self.admin_up(self.side_b) + self.admin_up(self.side_b) for station_profile in self.station_profiles: for sta in station_profile.station_names: - logg.info("Bringing up station %s"%(sta)) + logg.info("Bringing up station %s" % sta) self.admin_up(sta) temp_stations_list = [] @@ -1251,7 +1408,7 @@ class L3VariableTime(Realm): logg.info("ip's acquired") else: logg.info("Stations Failed to get IP's , consider increasing -wto','--wait_timeout' from the command line ") - exit(1) # Exit if cannot receive IP's + exit(1) # Exit if cannot receive IP's time.sleep(30) logg.info("Starting layer-3 traffic (if any configured)") self.cx_profile.start_cx() @@ -1264,7 +1421,7 @@ class L3VariableTime(Realm): end_time = self.parse_time(self.test_duration) + cur_time - logg.info("Monitoring throughput for duration: %s"%(self.test_duration)) + logg.info("Monitoring throughput for duration: %s" % self.test_duration) passes = 0 expected_passes = 0 @@ -1276,17 +1433,18 @@ class L3VariableTime(Realm): cur_time = datetime.datetime.now() self.reset_port_check() time.sleep(1) - + self.epoch_time = int(time.time()) # the total_dl_bps and total_up_bps is for all stations - new_rx_values, rx_drop_percent, endps, total_dl_bps, total_ul_bps = self.__get_rx_values() + new_rx_values, rx_drop_percent, endps, total_dl_bps, total_ul_bps = self.__get_rx_values() print("main loop, total-dl: ", total_dl_bps, " total-ul: ", total_ul_bps) expected_passes += 1 # __compare_vals - does the calculations - Result, rx_bytes, csv_rx_row_data = self.__compare_vals(old_rx_values, new_rx_values, total_dl_bps, total_ul_bps) + Result, rx_bytes, csv_rx_row_data = self.__compare_vals(old_rx_values, new_rx_values, total_dl_bps, + total_ul_bps) # save the best rate for the interval if rx_bytes > best_rx_bytes: best_rx_bytes = rx_bytes @@ -1294,7 +1452,8 @@ class L3VariableTime(Realm): if Result: passes += 1 else: - fail_msg = "FAIL: TIME: {} EPOCH: {} Not all stations increased traffic".format(cur_time, self.epoch_time) + fail_msg = "FAIL: TIME: {} EPOCH: {} Not all stations increased traffic".format(cur_time, + self.epoch_time) self._fail(fail_msg, print_fail) old_rx_values = new_rx_values @@ -1306,7 +1465,7 @@ class L3VariableTime(Realm): csv_rx_row_data.append(best_rx_bytes) csv_rx_row_data.append(total_dl_bps) csv_rx_row_data.append(total_ul_bps) - self.csv_add_row(csv_rx_row_data,self.csv_results_writer,self.csv_results) + self.csv_add_row(csv_rx_row_data, self.csv_results_writer, self.csv_results) if passes == expected_passes: self._pass("PASS: All tests passed", print_pass) @@ -1322,52 +1481,59 @@ class L3VariableTime(Realm): self.multicast_profile.cleanup() for station_profile in self.station_profiles: station_profile.cleanup() - + # for details csv file def csv_generate_column_details_headers(self): # test_keys used to generate the test_id - csv_rx_headers = self.test_keys.copy() - csv_rx_headers.extend + csv_rx_headers = self.test_keys.copy() # test_keys are the controller configuration - csv_rx_headers.extend(['epoch_time','time','test_id','test_duration','intv_sec','A_to_B_tx_bps_ul','B_to_A_tx_bps_dl','rx_bytes_intv_best','all_sta_dl_bps','all_sta_ul_bps']) + csv_rx_headers.extend( + ['epoch_time', 'time', 'test_id', 'test_duration', 'intv_sec', 'A_to_B_tx_bps_ul', 'B_to_A_tx_bps_dl', + 'rx_bytes_intv_best', 'all_sta_dl_bps', 'all_sta_ul_bps']) return csv_rx_headers def csv_generate_column_results_headers(self): # test_keys used to generate test_id - csv_rx_headers = self.test_keys.copy() - csv_rx_headers.extend - #test_keys are the controller configuration - csv_rx_headers.extend(['epoch_time','time','test_id','test_duration','intv_sec','A_to_B_tx_bps_ul','B_to_A_tx_bps_dl','rx_bytes_intv_best','all_sta_dl_bps','all_sta_ul_bps']) + csv_rx_headers = self.test_keys.copy() + # test_keys are the controller configuration + csv_rx_headers.extend( + ['epoch_time', 'time', 'test_id', 'test_duration', 'intv_sec', 'A_to_B_tx_bps_ul', 'B_to_A_tx_bps_dl', + 'rx_bytes_intv_best', 'all_sta_dl_bps', 'all_sta_ul_bps']) return csv_rx_headers - def csv_add_column_headers(self,headers): + def csv_add_column_headers(self, headers): if self.csv_file_details is not None: self.csv_writer.writerow(headers) self.csv_file_details.flush() - def csv_add_column_headers_results(self,headers): + def csv_add_column_headers_results(self, headers): if self.csv_results is not None: self.csv_results_writer.writerow(headers) - self.csv_results.flush() + self.csv_results.flush() - def csv_validate_list(self, csv_list, length): + @staticmethod + def csv_validate_list(csv_list, length): if len(csv_list) < length: - csv_list = csv_list + [('no data','no data')] * (length - len(csv_list)) + csv_list = csv_list + [('no data', 'no data')] * (length - len(csv_list)) return csv_list - def csv_add_row(self,row,writer,csv_file_details): # can make two calls eventually + @staticmethod + def csv_add_row(row, writer, csv_file_details): # can make two calls eventually if csv_file_details is not None: writer.writerow(row) csv_file_details.flush() + def valid_endp_types(_endp_type): etypes = _endp_type.split() for endp_type in etypes: - valid_endp_type=['lf_udp','lf_udp6','lf_tcp','lf_tcp6','mc_udp','mc_udp6'] + valid_endp_type = ['lf_udp', 'lf_udp6', 'lf_tcp', 'lf_tcp6', 'mc_udp', 'mc_udp6'] if not (str(endp_type) in valid_endp_type): print('invalid endp_type: %s. Valid types lf_udp, lf_udp6, lf_tcp, lf_tcp6, mc_udp, mc_udp6' % endp_type) exit(1) return _endp_type + + ################################################################################ # # End of Traffic Generation Class @@ -1381,18 +1547,17 @@ def valid_endp_types(_endp_type): ############################################################ def main(): global logg - lfjson_host = "localhost" lfjson_port = 8080 debug_on = False parser = argparse.ArgumentParser( prog='lf_controller_snp.py', - #formatter_class=argparse.RawDescriptionHelpFormatter, + # formatter_class=argparse.RawDescriptionHelpFormatter, formatter_class=argparse.RawTextHelpFormatter, epilog='''\ Scaling and Performance ''', - + description='''\ lf_controller_snp.py: -------------------- @@ -1622,76 +1787,118 @@ LANforge GUI what is displayed in the Column and how to access the value with cl ############################################# # Fixed Configurations Coded Into Script ############################################# - parser.add_argument('-ct1' ,'--controller_test_1', help='--controller_test_1 LANforge static radio configuration',action="store_true") - parser.add_argument('-ct2' ,'--controller_test_2', help='--controller_test_2 LANforge static radio configuration',action="store_true") - parser.add_argument('-ct3' ,'--controller_test_3', help='--controller_test_3 LANforge static radio configuration',action="store_true") + parser.add_argument('-ct1', '--controller_test_1', help='--controller_test_1 LANforge static radio configuration', + action="store_true") + parser.add_argument('-ct2', '--controller_test_2', help='--controller_test_2 LANforge static radio configuration', + action="store_true") + parser.add_argument('-ct3', '--controller_test_3', help='--controller_test_3 LANforge static radio configuration', + action="store_true") ############################################# # Script Controller Configurations ############################################# - parser.add_argument('-cca' ,'--controller_aps', help='--controller_aps List of APs to test default: APA453.0E7B.CF9C',default="APA453.0E7B.CF9C") - parser.add_argument('-ccf' ,'--controller_bands', help='--controller_bands default: a',default="a") - parser.add_argument('-cwm' ,'--controller_wifimodes', help='List of of wifi mode to test default: auto',default="auto") + parser.add_argument('-cca', '--controller_aps', + help='--controller_aps List of APs to test default: APA453.0E7B.CF9C', + default="APA453.0E7B.CF9C") + parser.add_argument('-ccf', '--controller_bands', help='--controller_bands default: a', default="a") + parser.add_argument('-cwm', '--controller_wifimodes', help='List of of wifi mode to test default: auto', + default="auto") - parser.add_argument('-cc5','--controller_chan_5ghzs', help='--controller_chan_5ghzs <36 40 ...> default 36',default="36") - parser.add_argument('-cc2','--controller_chan_24ghzs', help='--controller_chan_24ghzs <1 2 ...> default 1',default="1") - parser.add_argument('-ccw','--controller_chan_widths', help='--controller_chan_widths <20 40 80 160> default: \"20\"',default="20") - parser.add_argument('-cam','--controller_ap_modes', help='--controller_ap_modes default local',default="local") - parser.add_argument('-pdu','--controller_pdus', help='--controller_pdus List of packet sizes \"88 512 1370 1518\" default 1580',default="1518" ) - - parser.add_argument('-cde','--controller_data_encryptions', help='--controller_data_encryptions \"enable disable\"',default="disable" ) - parser.add_argument('-cs' ,'--controller_series', help='--controller_series <9800 | 3504>',default="9800",choices=["9800","3504"]) - parser.add_argument('-ccp','--controller_prompt', type=str,help="controller prompt default WLC",default="WLC") - parser.add_argument('-cas','--controller_ap_slot', type=str,help="AP slot, default 1",default="1") - parser.add_argument('-cwl','--controller_wlan', type=str,help="--controller_wlan , default wlan",default="wlan") + parser.add_argument('-cc5', '--controller_chan_5ghzs', help='--controller_chan_5ghzs <36 40 ...> default 36', + default="36") + parser.add_argument('-cc2', '--controller_chan_24ghzs', help='--controller_chan_24ghzs <1 2 ...> default 1', + default="1") + parser.add_argument('-ccw', '--controller_chan_widths', + help='--controller_chan_widths <20 40 80 160> default: \"20\"', default="20") + parser.add_argument('-cam', '--controller_ap_modes', help='--controller_ap_modes default local', + default="local") + parser.add_argument('-pdu', '--controller_pdus', + help='--controller_pdus List of packet sizes \"88 512 1370 1518\" default 1580', default="1518") - parser.add_argument('-cc' ,'--controller_ip', help='--controller_ip default 192.168.100.178',default="192.168.100.178") - parser.add_argument('-cp' ,'--controller_port', help='--controller_port ssh default 22',default="22") - parser.add_argument('-cu' ,'--controller_user', help='--controller_user ',default="admin") - parser.add_argument('-cpw','--controller_passwd', help='--controller_passwd ',default="controller123") - parser.add_argument('-ccs','--controller_scheme', help='--controller_scheme (serial|telnet|ssh): connect via serial, ssh or telnet',default="ssh",choices=["serial","telnet","ssh"]) - parser.add_argument('-ccd','--controller_client_densities', help='--controller_client_densities List of client densities defaults 1', default="1" ) + parser.add_argument('-cde', '--controller_data_encryptions', + help='--controller_data_encryptions \"enable disable\"', default="disable") + parser.add_argument('-cs', '--controller_series', help='--controller_series <9800 | 3504>', default="9800", + choices=["9800", "3504"]) + parser.add_argument('-ccp', '--controller_prompt', type=str, help="controller prompt default WLC", default="WLC") + parser.add_argument('-cas', '--controller_ap_slot', type=str, help="AP slot, default 1", default="1") + parser.add_argument('-cwl', '--controller_wlan', type=str, help="--controller_wlan , default wlan", + default="wlan") - parser.add_argument('-ctp','--controller_tx_powers', help='--controller_tx_powers <1 | 2 | 3 | 4 | 5 | 6 | 7 | 8> 1 is highest power default 3',default="3" - ,choices=["1","2","3","4","5","6","7","8"]) - parser.add_argument('-cco','--cap_ctl_out', help='--cap_ctl_out , switch the controller controller output will be captured', action='store_true') + parser.add_argument('-cc', '--controller_ip', + help='--controller_ip default 192.168.100.178', + default="192.168.100.178") + parser.add_argument('-cp', '--controller_port', + help='--controller_port ssh default 22', default="22") + parser.add_argument('-cu', '--controller_user', help='--controller_user ', + default="admin") + parser.add_argument('-cpw', '--controller_passwd', help='--controller_passwd ', + default="controller123") + parser.add_argument('-ccs', '--controller_scheme', + help='--controller_scheme (serial|telnet|ssh): connect via serial, ssh or telnet', + default="ssh", choices=["serial", "telnet", "ssh"]) + parser.add_argument('-ccd', '--controller_client_densities', + help='--controller_client_densities List of client densities defaults 1', default="1") + + parser.add_argument('-ctp', '--controller_tx_powers', + help='--controller_tx_powers <1 | 2 | 3 | 4 | 5 | 6 | 7 | 8> 1 is highest power default 3', + default="3", choices=["1", "2", "3", "4", "5", "6", "7", "8"]) + parser.add_argument('-cco', '--cap_ctl_out', + help='--cap_ctl_out , switch the controller controller output will be captured', + action='store_true') ################################################################# # Script AP parameters for reading AP, - not used in this script ################################################################# - parser.add_argument('-api','--ap_info', action='append', nargs=1, type=str, \ - help='(enter 0 if does not apply) --ap_info \"ap_scheme== ap_prompt== ap_ip== ap_port== ap_user== ap_pw== ap_tty==\" ') - #--ap_info "ap_scheme==serial ap_prompt==APA53.0E7B.CF9C ap_ip==0 ap_port==0 ap_user==admin ap_pw==Admin123 ap_tty==/dev/ttyUSB2" + parser.add_argument('-api', '--ap_info', action='append', nargs=1, type=str, + help='(enter 0 if does not apply) --ap_info \"ap_scheme== ap_prompt== ap_ip== ap_port== ap_user== ap_pw== ap_tty==\" ') + # --ap_info "ap_scheme==serial ap_prompt==APA53.0E7B.CF9C ap_ip==0 ap_port==0 ap_user==admin ap_pw==Admin123 ap_tty==/dev/ttyUSB2" ############################################# # Script LANforge Configurations ############################################# - parser.add_argument('-lm','--mgr', help='--mgr ',default='localhost') - parser.add_argument('-d','--test_duration', help='--test_duration example --time 5d (5 days) default: 2m options: number followed by d, h, m or s',default='20s') - parser.add_argument('-pi','--polling_interval', help="--polling_interval ", default='5s') - parser.add_argument('--tos', help='--tos: Support different ToS settings: BK | BE | VI | VO | numeric',default="BE") - parser.add_argument('-db','--debug', help='--debug: Enable debugging',action='store_true') - parser.add_argument('-t', '--endp_types', help='--endp_types example --endp_types \"lf_udp lf_tcp\" Default: lf_udp lf_tcp, options: lf_udp, lf_udp6, lf_tcp, lf_tcp6, mc_udp, mc_udp6', + parser.add_argument('-lm', '--mgr', help='--mgr ', default='localhost') + parser.add_argument('-d', '--test_duration', + help='--test_duration example --time 5d (5 days) default: 2m options: number followed by d, h, m or s', + default='20s') + parser.add_argument('-pi', '--polling_interval', help="--polling_interval ", default='5s') + parser.add_argument('--tos', help='--tos: Support different ToS settings: BK | BE | VI | VO | numeric', + default="BE") + parser.add_argument('-db', '--debug', help='--debug: Enable debugging', action='store_true') + parser.add_argument('-t', '--endp_types', + help='--endp_types example --endp_types \"lf_udp lf_tcp\" Default: lf_udp lf_tcp, options: lf_udp, lf_udp6, lf_tcp, lf_tcp6, mc_udp, mc_udp6', default='lf_udp lf_tcp', type=valid_endp_types) - parser.add_argument('-cd', '--controller_directions', help='--controller_directions example --controller_directions \"upload download\" Default: upload download', default='upload download') - parser.add_argument('-u', '--upstream_port', help='--upstream_port example: --upstream_port eth1',default='eth1') - parser.add_argument('-o','--csv_outfile', help="--csv_outfile ", default='snp') - parser.add_argument("-l", "--log", action='store_true', help="create logfile for messages, default stdout") - parser.add_argument('-c','--csv_output', help="Generate csv output", default=True) + parser.add_argument('-cd', '--controller_directions', + help='--controller_directions example --controller_directions \"upload download\" Default: upload download', + default='upload download') + parser.add_argument('-u', '--upstream_port', + help='--upstream_port example: --upstream_port eth1', + default='eth1') + parser.add_argument('-o', '--csv_outfile', help="--csv_outfile ", default='snp') + parser.add_argument("-l", "--log", action='store_true', help="create logfile for messages, default stdout") + parser.add_argument('-c', '--csv_output', help="Generate csv output", default=True) - parser.add_argument('-r','--radio', action='append', nargs=1, help='--radio \ - \"radio== ssid== ssid_pw== security== wifimode==\" '\ - , required=False) - parser.add_argument('-ul_bps','--side_a_tx_min_bps', help='--side_a_tx_min_bps , upload (A side tx) min tx rate bps default 256000 500000000', default="256000 1000000000") - parser.add_argument('-dl_bps','--side_b_tx_min_bps', help='--side_b_tx_min_bps , download(B side tx) min tx rate bps default 1000000000', default="1000000000") + parser.add_argument('-r', '--radio', action='append', nargs=1, help='--radio \ + \"radio== ssid== ssid_pw== security== wifimode==\" ', + required=False) + parser.add_argument('-ul_bps', '--side_a_tx_min_bps', + help='--side_a_tx_min_bps , upload (A side tx) min tx rate bps default 256000 500000000', + default="256000 1000000000") + parser.add_argument('-dl_bps', '--side_b_tx_min_bps', + help='--side_b_tx_min_bps , download(B side tx) min tx rate bps default 1000000000', + default="1000000000") ############################################## # Parameters Used For Testing ############################################## - parser.add_argument('-noc','--no_controller', help='-noc / --no_controller no configuration of the controller', action='store_true') - parser.add_argument('-nos','--no_stations', help='-nos / --no_stations , no stations', action='store_true') - parser.add_argument('-wto','--wait_timeout', help='-wto / --wait_timeout , time to wait for stations to get IP ', default="360") - parser.add_argument('-ptc','--print_test_config', help='-ptc / --print_test_config , print out the test configuration and exit', action='store_true') + parser.add_argument('-noc', '--no_controller', help='-noc / --no_controller no configuration of the controller', + action='store_true') + parser.add_argument('-nos', '--no_stations', help='-nos / --no_stations , no stations', action='store_true') + parser.add_argument('-wto', '--wait_timeout', type=int, + help='-wto / --wait_timeout , time to wait for stations to get IP ', + default="360") + parser.add_argument('-ptc', '--print_test_config', + help='-ptc / --print_test_config , print out the test configuration and exit', + action='store_true') ############################################################## # @@ -1700,29 +1907,12 @@ LANforge GUI what is displayed in the Column and how to access the value with cl ############################################################## args = parser.parse_args() controller_args = args # use args. - #logg.info("args: {}".format(args)) + # logg.info("args: {}".format(args)) debug_on = args.debug ############################################################### # Gather Test Data ############################################################### - if args.test_duration: - test_duration = args.test_duration - - if args.polling_interval: - polling_interval = args.polling_interval - - if args.mgr: - lfjson_host = args.mgr - - if args.upstream_port: - side_b = args.upstream_port - - if args.radio: - radios = args.radio - - if args.wait_timeout: - wait_timeout = int(args.wait_timeout) if args.controller_scheme: __scheme = args.controller_scheme @@ -1737,7 +1927,7 @@ LANforge GUI what is displayed in the Column and how to access the value with cl __prompt = args.controller_prompt if args.controller_series: - __series = args.controller_series + __series = args.controller_series if args.controller_user: __user = args.controller_user @@ -1749,7 +1939,7 @@ LANforge GUI what is displayed in the Column and how to access the value with cl __cap_ctl_out = args.cap_ctl_out else: __cap_ctl_out = False - + if args.controller_ap_slot: __ap_slot = args.controller_ap_slot @@ -1761,11 +1951,12 @@ LANforge GUI what is displayed in the Column and how to access the value with cl ap_info = args.ap_info for _ap_info in ap_info: print("ap_info {}".format(_ap_info)) - ap_keys = ['ap_scheme','ap_prompt','ap_ip','ap_port','ap_user','ap_pw', 'ap_tty', 'ap_baud'] - ap_dict = dict(map(lambda x: x.split('=='), str(_ap_info).replace('[','').replace(']','').replace("'","").split())) + ap_keys = ['ap_scheme', 'ap_prompt', 'ap_ip', 'ap_port', 'ap_user', 'ap_pw', 'ap_tty', 'ap_baud'] + ap_dict = dict( + map(lambda x: x.split('=='), str(_ap_info).replace('[', '').replace(']', '').replace("'", "").split())) for key in ap_keys: if key not in ap_dict: - print("missing ap config, for the {}, all these need to be set {} ".format(key,ap_keys)) + print("missing ap config, for the {}, all these need to be set {} ".format(key, ap_keys)) exit(1) print("ap_dict: {}".format(ap_dict)) @@ -1774,39 +1965,39 @@ LANforge GUI what is displayed in the Column and how to access the value with cl # Create a report instanciate a reporting class # ############################################### - report = lf_report(_results_dir_name = "Scaling_and_Performance",_output_html="snp.html",_output_pdf="snp.pdf") + report = lf_report(_results_dir_name="Scaling_and_Performance", _output_html="snp.html", _output_pdf="snp.pdf") - if args.csv_outfile != None: + if args.csv_outfile: current_time = time.strftime("%m_%d_%Y_%H_%M_%S", time.localtime()) - csv_outfile = "details_{}_{}.csv".format(args.csv_outfile,current_time) + csv_outfile = "details_{}_{}.csv".format(args.csv_outfile, current_time) csv_outfile = report.file_add_path(csv_outfile) - csv_results = "results_{}_{}.csv".format(args.csv_outfile,current_time) + csv_results = "results_{}_{}.csv".format(args.csv_outfile, current_time) csv_results = report.file_add_path(csv_results) print("csv output file : {}".format(csv_outfile)) print("csv results file : {}".format(csv_results)) - + if args.log: - outfile_log = "{}_{}_output_log.log".format(args.outfile,current_time) + outfile_log = "{}_{}_output_log.log".format(args.outfile, current_time) outfile_log = report.file_add_path(outfile_log) print("output file log: {}".format(outfile_log)) else: outfile_log = "stdout" - print("output file log: {}".format(outfile_log)) + print("output file log: {}".format(outfile_log)) - # Set up the log file + # Set up the log file console_handler = logging.StreamHandler() formatter = logging.Formatter(FORMAT) logg = logging.getLogger(__name__) logg.setLevel(logging.DEBUG) file_handler = None - if (args.log): + if args.log: file_handler = logging.FileHandler(outfile_log, "w") file_handler.setLevel(logging.DEBUG) file_handler.setFormatter(formatter) logg.addHandler(file_handler) - logg.addHandler(logging.StreamHandler(sys.stdout)) # allows to logging to file and stderr + logg.addHandler(logging.StreamHandler(sys.stdout)) # allows to logging to file and stderr # if loggin.basicConfig is called this will result in duplicating log entries # logging.basicConfig(format=FORMAT, handlers=[file_handler]) else: @@ -1819,31 +2010,38 @@ LANforge GUI what is displayed in the Column and how to access the value with cl # Configuration used by command switch --controller_test_1 # ############################################################# - radio_AX200_abgn_ax_list_001_one = [['radio==1.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] + radio_AX200_abgn_ax_list_001_one = [ + ['radio==1.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] - radio_AX200_abgn_ax_list_008_one = [['radio==1.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy2 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy3 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy4 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy5 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy6 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy7 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] + radio_AX200_abgn_ax_list_008_one = [ + ['radio==1.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy2 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy3 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy4 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy5 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy6 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy7 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] - radio_AX200_abgn_ax_dict_one = {'1' : radio_AX200_abgn_ax_list_001_one, - '8' : radio_AX200_abgn_ax_list_008_one} + radio_AX200_abgn_ax_dict_one = {'1': radio_AX200_abgn_ax_list_001_one, + '8': radio_AX200_abgn_ax_list_008_one} - radio_ath10K_9984_an_AC_list_001_one = [['radio==1.wiphy8 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath10K_9984_an_AC_list_010_one = [['radio==1.wiphy8 stations==10 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath10K_9984_an_AC_list_020_one = [['radio==1.wiphy8 stations==20 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath10K_9984_an_AC_list_050_one = [['radio==1.wiphy8 stations==50 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath10K_9984_an_AC_list_050_one = [['radio==1.wiphy8 stations==64 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath10K_9984_an_AC_list_001_one = [ + ['radio==1.wiphy8 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath10K_9984_an_AC_list_010_one = [ + ['radio==1.wiphy8 stations==10 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath10K_9984_an_AC_list_020_one = [ + ['radio==1.wiphy8 stations==20 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath10K_9984_an_AC_list_050_one = [ + ['radio==1.wiphy8 stations==50 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath10K_9984_an_AC_list_050_one = [ + ['radio==1.wiphy8 stations==64 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath10K_9984_an_AC_dict_one = {'1' : radio_ath10K_9984_an_AC_list_001_one, - '10' : radio_ath10K_9984_an_AC_list_010_one, - '20' : radio_ath10K_9984_an_AC_list_020_one, - '50' : radio_ath10K_9984_an_AC_list_020_one, - '65' : radio_ath10K_9984_an_AC_list_020_one} + radio_ath10K_9984_an_AC_dict_one = {'1': radio_ath10K_9984_an_AC_list_001_one, + '10': radio_ath10K_9984_an_AC_list_010_one, + '20': radio_ath10K_9984_an_AC_list_020_one, + '50': radio_ath10K_9984_an_AC_list_020_one, + '65': radio_ath10K_9984_an_AC_list_020_one} #################################################################### # @@ -1857,85 +2055,94 @@ LANforge GUI what is displayed in the Column and how to access the value with cl # Configuration used by command switch --controller_test_2 # ############################################################ - radio_AX200_abgn_ax_list_001 = [['radio==1.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] + radio_AX200_abgn_ax_list_001 = [ + ['radio==1.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] - radio_AX200_abgn_ax_list_010 = [['radio==1.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy2 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy3 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy4 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy5 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy6 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy7 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==2.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==2.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] + radio_AX200_abgn_ax_list_010 = [ + ['radio==1.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy2 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy3 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy4 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy5 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy6 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy7 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==2.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==2.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] + radio_AX200_abgn_ax_list_020 = [ + ['radio==1.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy2 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy3 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy4 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy5 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy6 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy7 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==2.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==2.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==3.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==3.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==4.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==4.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==5.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==5.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==6.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==6.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==6.wiphy2 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==6.wiphy3 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ] - radio_AX200_abgn_ax_list_020 = [['radio==1.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy2 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy3 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy4 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy5 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy6 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy7 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==2.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==2.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==3.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==3.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==4.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==4.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==5.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==5.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==6.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==6.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==6.wiphy2 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==6.wiphy3 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ] + radio_AX200_abgn_ax_list_024 = [ + ['radio==1.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy2 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy3 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy4 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy5 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy6 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy7 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==2.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==2.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==3.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==3.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==4.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==4.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==5.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==5.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==6.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==6.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==6.wiphy2 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==6.wiphy3 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==6.wiphy4 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==6.wiphy5 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==6.wiphy6 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==6.wiphy7 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ] - radio_AX200_abgn_ax_list_024 = [['radio==1.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy2 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy3 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy4 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy5 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy6 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy7 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==2.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==2.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==3.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==3.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==4.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==4.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==5.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==5.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==6.wiphy0 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==6.wiphy1 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==6.wiphy2 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==6.wiphy3 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==6.wiphy4 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==6.wiphy5 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==6.wiphy6 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==6.wiphy7 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ] + radio_AX200_abgn_ax_dict = {'1': radio_AX200_abgn_ax_list_001, + '10': radio_AX200_abgn_ax_list_010, + '24': radio_AX200_abgn_ax_list_024} - radio_AX200_abgn_ax_dict = {'1' : radio_AX200_abgn_ax_list_001, - '10' : radio_AX200_abgn_ax_list_010, - '24' : radio_AX200_abgn_ax_list_024} + radio_ath10K_9984_an_AC_list_001 = [ + ['radio==1.wiphy8 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath10K_9984_an_AC_list_010 = [ + ['radio==1.wiphy8 stations==10 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath10K_9984_an_AC_list_020 = [ + ['radio==1.wiphy8 stations==20 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath10K_9984_an_AC_list_050 = [ + ['radio==1.wiphy8 stations==50 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath10K_9984_an_AC_list_100 = [ + ['radio==1.wiphy8 stations==50 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy9 stations==50 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath10K_9984_an_AC_list_200 = [ + ['radio==1.wiphy8 stations==50 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy9 stations==50 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==6.wiphy8 stations==50 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==6.wiphy9 stations==50 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath10K_9984_an_AC_list_001 = [['radio==1.wiphy8 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath10K_9984_an_AC_list_010 = [['radio==1.wiphy8 stations==10 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath10K_9984_an_AC_list_020 = [['radio==1.wiphy8 stations==20 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath10K_9984_an_AC_list_050 = [['radio==1.wiphy8 stations==50 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath10K_9984_an_AC_list_100 = [['radio==1.wiphy8 stations==50 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy9 stations==50 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath10K_9984_an_AC_list_200 = [['radio==1.wiphy8 stations==50 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy9 stations==50 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==6.wiphy8 stations==50 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==6.wiphy9 stations==50 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']] - - radio_ath10K_9984_an_AC_dict = {'1' : radio_ath10K_9984_an_AC_list_001, - '50' : radio_ath10K_9984_an_AC_list_050, + radio_ath10K_9984_an_AC_dict = {'1': radio_ath10K_9984_an_AC_list_001, + '50': radio_ath10K_9984_an_AC_list_050, '200': radio_ath10K_9984_an_AC_list_200} #################################################################### @@ -1951,50 +2158,64 @@ LANforge GUI what is displayed in the Column and how to access the value with cl # Configuration used by command switch --controller_test_3 # ############################################################# - #iwlwifi(AX200) 521 - radio_AX200_abgn_ax_list_001_wiphy2 = [['radio==1.wiphy2 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] + # iwlwifi(AX200) 521 + radio_AX200_abgn_ax_list_001_wiphy2 = [ + ['radio==1.wiphy2 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] - radio_AX200_abgn_ax_list_001 = [['radio==1.wiphy2 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] - radio_AX200_abgn_ax_list_004 = [['radio==1.wiphy2 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy3 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy4 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto'], - ['radio==1.wiphy5 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] + radio_AX200_abgn_ax_list_001 = [ + ['radio==1.wiphy2 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] + radio_AX200_abgn_ax_list_004 = [ + ['radio==1.wiphy2 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy3 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy4 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto'], + ['radio==1.wiphy5 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] - radio_AX200_abgn_ax_dict_test = {'1' : radio_AX200_abgn_ax_list_001, - '4': radio_AX200_abgn_ax_list_004} + radio_AX200_abgn_ax_dict_test = {'1': radio_AX200_abgn_ax_list_001, + '4': radio_AX200_abgn_ax_list_004} - radio_AX200_abgn_ax_dict_test_wiphy2 = {'1' : radio_AX200_abgn_ax_list_001_wiphy2} + radio_AX200_abgn_ax_dict_test_wiphy2 = {'1': radio_AX200_abgn_ax_list_001_wiphy2} - radio_ath10K_9984_an_AC_list_001 = [['radio==1.wiphy0 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath10K_9984_an_AC_list_010 = [['radio==1.wiphy0 stations==10 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath10K_9984_an_AC_list_020 = [['radio==1.wiphy0 stations==20 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath10K_9984_an_AC_list_050 = [['radio==1.wiphy0 stations==50 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath10K_9984_an_AC_list_001 = [ + ['radio==1.wiphy0 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath10K_9984_an_AC_list_010 = [ + ['radio==1.wiphy0 stations==10 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath10K_9984_an_AC_list_020 = [ + ['radio==1.wiphy0 stations==20 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath10K_9984_an_AC_list_050 = [ + ['radio==1.wiphy0 stations==50 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath10K_9984_an_AC_list_001_wiphy0 = [['radio==1.wiphy0 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath10K_9984_an_AC_list_010_wiphy0 = [['radio==1.wiphy0 stations==10 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath10K_9984_an_AC_list_001_wiphy0 = [ + ['radio==1.wiphy0 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath10K_9984_an_AC_list_010_wiphy0 = [ + ['radio==1.wiphy0 stations==10 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath10K_9984_an_AC_dict_test_wiphy0 = {'1' : radio_ath10K_9984_an_AC_list_001_wiphy0, - '10' : radio_ath10K_9984_an_AC_list_010_wiphy0} + radio_ath10K_9984_an_AC_dict_test_wiphy0 = {'1': radio_ath10K_9984_an_AC_list_001_wiphy0, + '10': radio_ath10K_9984_an_AC_list_010_wiphy0} + + radio_ath10K_9984_an_AC_dict_test = {'1': radio_ath10K_9984_an_AC_list_001, + '10': radio_ath10K_9984_an_AC_list_010, + '50': radio_ath10K_9984_an_AC_list_050} - radio_ath10K_9984_an_AC_dict_test = {'1' : radio_ath10K_9984_an_AC_list_001, - '10' : radio_ath10K_9984_an_AC_list_010, - '50' : radio_ath10K_9984_an_AC_list_050} - #################################################################### # Test to use ath9K #################################################################### - radio_ath9K_9984_abgn_list_001 = [['radio==1.wiphy1 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath9K_9984_abgn_list_010 = [['radio==1.wiphy1 stations==10 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath9K_9984_abgn_list_020 = [['radio==1.wiphy1 stations==20 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath9K_9984_abgn_list_050 = [['radio==1.wiphy1 stations==50 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath9K_9984_abgn_list_200 = [['radio==1.wiphy1 stations==200 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath9K_9984_abgn_list_001 = [ + ['radio==1.wiphy1 stations==1 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath9K_9984_abgn_list_010 = [ + ['radio==1.wiphy1 stations==10 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath9K_9984_abgn_list_020 = [ + ['radio==1.wiphy1 stations==20 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath9K_9984_abgn_list_050 = [ + ['radio==1.wiphy1 stations==50 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] + radio_ath9K_9984_abgn_list_200 = [ + ['radio==1.wiphy1 stations==200 ssid==test_candela ssid_pw==[BLANK] security==open wifimode==auto']] - radio_ath9K_9984_abgn_dict_test = {'1' : radio_ath9K_9984_abgn_list_001, - '10' : radio_ath9K_9984_abgn_list_010, - '20' : radio_ath9K_9984_abgn_list_020, - '50' : radio_ath9K_9984_abgn_list_050, - '200': radio_ath9K_9984_abgn_list_200 } + radio_ath9K_9984_abgn_dict_test = {'1': radio_ath9K_9984_abgn_list_001, + '10': radio_ath9K_9984_abgn_list_010, + '20': radio_ath9K_9984_abgn_list_020, + '50': radio_ath9K_9984_abgn_list_050, + '200': radio_ath9K_9984_abgn_list_200} #################################################################### # Test to only use teh ath9K #################################################################### @@ -2003,7 +2224,7 @@ LANforge GUI what is displayed in the Column and how to access the value with cl # #################################################################### MAX_NUMBER_OF_STATIONS = 200 - + radio_name_list = [] number_of_stations_per_radio_list = [] ssid_list = [] @@ -2011,150 +2232,152 @@ LANforge GUI what is displayed in the Column and how to access the value with cl ssid_security_list = [] wifimode_list = [] - #optional radio configuration + # optional radio configuration reset_port_enable_list = [] reset_port_time_min_list = [] reset_port_time_max_list = [] wifi_mode_dict = { - "auto" : "0", - "a" : "1", - "b" : "2", - "g" : "3", - "abg" : "4", - "abgn" : "5", - "bgn" : "6", - "bg" : "7", - "abgnAC" : "8", - "anAC" : "9", - "an" : "10", - "bgnAC" : "11", - "abgnAX" : "12", - "bgnAX" : "13", - "anAX" : "14" - } + "auto": "0", + "a": "1", + "b": "2", + "g": "3", + "abg": "4", + "abgn": "5", + "bgn": "6", + "bg": "7", + "abgnAC": "8", + "anAC": "9", + "an": "10", + "bgnAC": "11", + "abgnAX": "12", + "bgnAX": "13", + "anAX": "14" + } -########################################################################################### -# Test Configurations: Take presidence over command line arguments -# GOAL: help with command line configurations -########################################################################################### + ########################################################################################### + # Test Configurations: Take presidence over command line arguments + # GOAL: help with command line configurations + ########################################################################################### -########################################################################################### -# -# controller_test_1 -# -########################################################################################### + ########################################################################################### + # + # controller_test_1 + # + ########################################################################################### # Test configuration that may be read in , in conjunction with command line arguments if args.controller_test_1: logg.info("USING: controller_test_1") - controller_aps = "vanc-e".split() - controller_bands = "a b".split() - controller_wifimodes = "an anAX anAC abgn bg".split() - controller_tx_powers = "3".split() - controller_chan_5ghzs = "36".split() - controller_chan_24ghzs = "1".split() - controller_chan_widths = "20 40 80".split() - controller_ap_modes = "local".split() + controller_aps = "vanc-e".split() + controller_bands = "a b".split() + controller_wifimodes = "an anAX anAC abgn bg".split() + controller_tx_powers = "3".split() + controller_chan_5ghzs = "36".split() + controller_chan_24ghzs = "1".split() + controller_chan_widths = "20 40 80".split() + controller_ap_modes = "local".split() controller_data_encryptions = "disable".split() - controller_packet_types = "lf_udp lf_tcp".split() - controller_directions = "upload download".split() - controller_pdus = "88 512 1370 1518".split() + controller_packet_types = "lf_udp lf_tcp".split() + controller_directions = "upload download".split() + controller_pdus = "88 512 1370 1518".split() controller_client_densities = "1 10 50 200".split() - controller_side_a_tx_min_bps = "256000".split() - controller_side_b_tx_min_bps = "256000".split() - radio_AX200_abgn_ax_dict = radio_AX200_abgn_ax_dict_one + controller_side_a_tx_min_bps = "256000".split() + controller_side_b_tx_min_bps = "256000".split() + radio_AX200_abgn_ax_dict = radio_AX200_abgn_ax_dict_one radio_ath10K_9984_an_AC_dict = radio_ath10K_9984_an_AC_dict_one -########################################################################################### -# -# controller_test_2 -# -########################################################################################### + ########################################################################################### + # + # controller_test_2 + # + ########################################################################################### elif args.controller_test_2: logg.info("USING: controller_test_2") # Note the local system only supports 802.11-abgn , 802.11a - controller_aps = "APA453.0E7B.CF9C".split() - controller_bands = "a".split() - #controller_wifimodes = "an anAX anAC abgn bg".split() - controller_wifimodes = "an".split() - controller_tx_powers = "3".split() - controller_chan_5ghzs = "36".split() - controller_chan_24ghzs = "1".split() - controller_chan_widths = "20".split() - controller_ap_modes = "local".split() + controller_aps = "APA453.0E7B.CF9C".split() + controller_bands = "a".split() + # controller_wifimodes = "an anAX anAC abgn bg".split() + controller_wifimodes = "an".split() + controller_tx_powers = "3".split() + controller_chan_5ghzs = "36".split() + controller_chan_24ghzs = "1".split() + controller_chan_widths = "20".split() + controller_ap_modes = "local".split() controller_data_encryptions = "disable".split() - #controller_packet_types = "lf_udp lf_tcp".split() - controller_packet_types = "lf_udp".split() - #controller_directions = "upload download".split() - controller_directions = "upload download".split() - #controller_pdus = "88 512 1370 1518".split() - controller_pdus = "1518".split() + # controller_packet_types = "lf_udp lf_tcp".split() + controller_packet_types = "lf_udp".split() + # controller_directions = "upload download".split() + controller_directions = "upload download".split() + # controller_pdus = "88 512 1370 1518".split() + controller_pdus = "1518".split() controller_client_densities = "10".split() controller_data_encryptions = "disable".split() - controller_side_a_tx_min_bps = "256000".split() - controller_side_b_tx_min_bps = "256000".split() - radio_AX200_abgn_ax_dict = radio_AX200_abgn_ax_dict_test + controller_side_a_tx_min_bps = "256000".split() + controller_side_b_tx_min_bps = "256000".split() + radio_AX200_abgn_ax_dict = radio_AX200_abgn_ax_dict_test radio_ath10K_9984_an_AC_dict = radio_ath10K_9984_an_AC_dict_test -########################################################################################### -# -# controller_test_3 -# -########################################################################################### - elif args.controller_test_3: #CMR_test_3 + ########################################################################################### + # + # controller_test_3 + # + ########################################################################################### + elif args.controller_test_3: # CMR_test_3 logg.info("USING: controller_test_3") # Note the local system only supports 802.11-abgn , 802.11a - controller_aps = "APA453.0E7B.CF9C".split() - controller_bands = "a".split() - #controller_wifimodes = "an anAX anAC abgn bg".split() - controller_wifimodes = "an".split() - controller_tx_powers = "3".split() - controller_chan_5ghzs = "36".split() - controller_chan_24ghzs = "1".split() - controller_chan_widths = "20".split() - controller_ap_modes = "local".split() + controller_aps = "APA453.0E7B.CF9C".split() + controller_bands = "a".split() + # controller_wifimodes = "an anAX anAC abgn bg".split() + controller_wifimodes = "an".split() + controller_tx_powers = "3".split() + controller_chan_5ghzs = "36".split() + controller_chan_24ghzs = "1".split() + controller_chan_widths = "20".split() + controller_ap_modes = "local".split() controller_data_encryptions = "disable".split() - #controller_packet_types = "lf_udp lf_tcp".split() - controller_packet_types = "lf_udp".split() - #controller_directions = "upload download".split() - controller_directions = "upload download".split() - #controller_pdus = "88 512 1370 1518".split() - controller_pdus = "1518".split() + # controller_packet_types = "lf_udp lf_tcp".split() + controller_packet_types = "lf_udp".split() + # controller_directions = "upload download".split() + controller_directions = "upload download".split() + # controller_pdus = "88 512 1370 1518".split() + controller_pdus = "1518".split() controller_client_densities = "1".split() controller_data_encryptions = "disable".split() - controller_side_a_tx_min_bps = "256000".split() - controller_side_b_tx_min_bps = "256000".split() - radio_AX200_abgn_ax_dict = radio_AX200_abgn_ax_dict_test_wiphy2 + controller_side_a_tx_min_bps = "256000".split() + controller_side_b_tx_min_bps = "256000".split() + radio_AX200_abgn_ax_dict = radio_AX200_abgn_ax_dict_test_wiphy2 radio_ath10K_9984_an_AC_dict = radio_ath10K_9984_an_AC_dict_test - #radio_ath10K_9984_an_AC_dict = radio_ath9K_9984_abgn_dict_test + # radio_ath10K_9984_an_AC_dict = radio_ath9K_9984_abgn_dict_test ########################################################################################### # Use Command line arguments ########################################################################################### - else: + else: - controller_aps = args.controller_aps.split() - controller_bands = args.controller_bands.split() - controller_wifimodes = args.controller_wifimodes.split() + controller_aps = args.controller_aps.split() + controller_bands = args.controller_bands.split() + controller_wifimodes = args.controller_wifimodes.split() for mode in controller_wifimodes: if mode in wifi_mode_dict.keys(): pass else: - logg.info("wifimode [{}] not recognised. Please use: auto, a, b, g, abg, abgn, bgn, bg, abgnAC, anAC, an, bgnAC, abgnAX, bgnAX, anAX".format(mode)) + logg.info( + "wifimode [{}] not recognised. Please use: auto, a, b, g, abg, abgn, bgn, bg, abgnAC, anAC, an, bgnAC, abgnAX, bgnAX, anAX".format( + mode)) exit(1) - controller_tx_powers = args.controller_tx_powers.split() - controller_chan_5ghzs = args.controller_chan_5ghzs.split() - controller_chan_24ghzs = args.controller_chan_24ghzs.split() - controller_chan_widths = args.controller_chan_widths.split() - controller_ap_modes = args.controller_ap_modes.split() - controller_client_densities = args.controller_client_densities.split() - controller_packet_types = args.endp_types.split() - controller_pdus = args.controller_pdus.split() - controller_directions = args.controller_directions.split() - controller_data_encryptions = args.controller_data_encryptions.split() + controller_tx_powers = args.controller_tx_powers.split() + controller_chan_5ghzs = args.controller_chan_5ghzs.split() + controller_chan_24ghzs = args.controller_chan_24ghzs.split() + controller_chan_widths = args.controller_chan_widths.split() + controller_ap_modes = args.controller_ap_modes.split() + controller_client_densities = args.controller_client_densities.split() + controller_packet_types = args.endp_types.split() + controller_pdus = args.controller_pdus.split() + controller_directions = args.controller_directions.split() + controller_data_encryptions = args.controller_data_encryptions.split() - controller_side_a_tx_min_bps = args.side_a_tx_min_bps.split() - controller_side_b_tx_min_bps = args.side_b_tx_min_bps.split() + controller_side_a_tx_min_bps = args.side_a_tx_min_bps.split() + controller_side_b_tx_min_bps = args.side_b_tx_min_bps.split() logg.info("TEST CONFIG: ") logg.info("controller_aps ('-cca' ,'--controller_aps'): {}".format(controller_aps)) logg.info("controller_bands ('-ccf' ,'--controller_bands'): {}".format(controller_bands)) @@ -2164,15 +2387,17 @@ LANforge GUI what is displayed in the Column and how to access the value with cl logg.info("controller_chan_widths ('-ccw','--controller_chan_widths'): {}".format(controller_chan_widths)) logg.info("controller_tx_powers ('-ctp','--controller_tx_powers'): {}".format(controller_tx_powers)) logg.info("controller_ap_modes ('-cam','--controller_ap_modes'): {}".format(controller_ap_modes)) - logg.info("controller_client_densities ('-ccd','--controller_client_densities'): {}".format(controller_client_densities)) + logg.info( + "controller_client_densities ('-ccd','--controller_client_densities'): {}".format(controller_client_densities)) logg.info("controller_packet_types ('-t', '--endp_types'): {}".format(controller_packet_types)) logg.info("controller_pdus ('-cps','--controller_pdus'): {}".format(controller_pdus)) logg.info("controller_directions ('-cd', '--controller_directions'): {}".format(controller_directions)) - logg.info("controller_data_encryptions ('-cde','--controller_data_encryptions') {}".format(controller_data_encryptions)) + logg.info( + "controller_data_encryptions ('-cde','--controller_data_encryptions') {}".format(controller_data_encryptions)) logg.info("controller_side_a_tx_min_bps ('-amr','--side_a_tx_min_bps'): {}".format(controller_side_a_tx_min_bps)) logg.info("controller_side_b_tx_min_bps ('-bmr','--side_b_tx_min_bps'): {}".format(controller_side_b_tx_min_bps)) - logg.info("test duration ('-d','--test_duration'): {}".format(test_duration)) - logg.info("polling_interval ('-pi','--polling_interval'): {}".format(polling_interval)) + logg.info("test duration ('-d','--test_duration'): {}".format(args.test_duration)) + logg.info("polling_interval ('-pi','--polling_interval'): {}".format(args.polling_interval)) if args.radio: logg.info("radios from command line used") @@ -2184,7 +2409,8 @@ LANforge GUI what is displayed in the Column and how to access the value with cl logg.info('##### ATH10K_9984 RADIOS ####') logg.info(radio_ath10K_9984_an_AC_dict) else: - logg.info("No radios endered EXITING, use --radio or --controller_test_1, --controller_test_2 or --controller_test_3") + logg.info( + "No radios endered EXITING, use --radio or --controller_test_1, --controller_test_2 or --controller_test_3") exit(1) if args.print_test_config: @@ -2196,30 +2422,32 @@ LANforge GUI what is displayed in the Column and how to access the value with cl logg.info("Reports Directory Created") exit(1) - __ap_set = None - __band_set = None - __chan_width_set = None - __ap_mode_set = None - __tx_power_set = None - __chan_5ghz_set = None - __chan_24ghz_set = None - __csv_started = False + __ap_set = None + __band_set = None + __chan_width_set = None + __ap_mode_set = None + __tx_power_set = None + __chan_5ghz_set = None + __chan_24ghz_set = None + __csv_started = False for controller_ap in controller_aps: for controller_band in controller_bands: # frequency for controller_wifimode in controller_wifimodes: # check for valid frequency and wifi_mode combination put here to simplify logic since all radios do not support all modes # "an anAX anAC abgn bg" - if((controller_band == "a" and controller_wifimode == "bg") or (controller_band == "b" and controller_wifimode == "anAC")): + if ((controller_band == "a" and controller_wifimode == "bg") or ( + controller_band == "b" and controller_wifimode == "anAC")): logg.info("#######################################################################") - logg.info("# Skipping combination controller_band {} controller_wifimode {}".format(controller_band,controller_wifimode)) + logg.info("# Skipping combination controller_band {} controller_wifimode {}".format(controller_band, + controller_wifimode)) logg.info("#######################################################################") - pass # invalid combination continue + pass # invalid combination continue else: for controller_tx_power in controller_tx_powers: for controller_chan_5ghz in controller_chan_5ghzs: for controller_chan_24ghz in controller_chan_24ghzs: - for controller_chan_width in controller_chan_widths: #bandwidth + for controller_chan_width in controller_chan_widths: # bandwidth for controller_data_encryption in controller_data_encryptions: for controller_ap_mode in controller_ap_modes: for controller_client_density in controller_client_densities: @@ -2234,144 +2462,189 @@ LANforge GUI what is displayed in the Column and how to access the value with cl ############################################### if args.radio: radios = args.radio - logg.info("########################################################") + logg.info( + "########################################################") logg.info("# radios configured from command line {}".format(radios)) logg.info("# controller_band: {}".format(controller_band)) logg.info("# controller_wifimode: {}".format(controller_wifimode)) - logg.info("########################################################") - + logg.info( + "########################################################") + ################################################################# # USE radio dictionaies in this file to configure LANforge radios ################################################################# elif controller_band == "a": if controller_wifimode == "anAX" or controller_wifimode == "abgn": - #AX200 dual band + # AX200 dual band try: radios = radio_AX200_abgn_ax_dict[controller_client_density] - logg.info("controller_client_density:{} radios: {}".format(controller_client_density,radios)) + logg.info("controller_client_density:{} radios: {}".format( + controller_client_density, radios)) except: - logg.info("CONTROLLER DENSITY INVALID FOR RADIO DICTIONARY: controller_client_density: {} not supported for configuration".format(controller_client_density)) - logg.info("CONTROLLER DENSITY INVALID FOR RADIO DICTIONARY: current dictionary radio_AX200_abgn_ax_dict {}".format(radio_AX200_abgn_ax_dict)) - logg.info("CONTROLLER DENSITY INVALID FOR RADIO DICTIONARY: MOVE TO NEXT DENSITY CONTINUING TESTING") + logg.info( + "CONTROLLER DENSITY INVALID FOR RADIO DICTIONARY: controller_client_density: {} not supported for configuration".format( + controller_client_density)) + logg.info( + "CONTROLLER DENSITY INVALID FOR RADIO DICTIONARY: current dictionary radio_AX200_abgn_ax_dict {}".format( + radio_AX200_abgn_ax_dict)) + logg.info( + "CONTROLLER DENSITY INVALID FOR RADIO DICTIONARY: MOVE TO NEXT DENSITY CONTINUING TESTING") continue - elif controller_wifimode == "an" or controller_wifimode == "anAC" or controller_wifimode =="auto": - #ath10K only supports 5Ghz + elif controller_wifimode == "an" or controller_wifimode == "anAC" or controller_wifimode == "auto": + # ath10K only supports 5Ghz try: - radios = radio_ath10K_9984_an_AC_dict[controller_client_density] + radios = radio_ath10K_9984_an_AC_dict[ + controller_client_density] logg.info("radios: {}".format(radios)) except: - logg.info("CONTROLLER DENSITY INVALID FOR RADIO DICTIONARY: controller_client_density: {} not supported for configuration".format(controller_client_density)) - logg.info("CONTROLLER DENSITY INVALID FOR RADIO DICTIONARY: current dictionary radio_AX200_abgn_ax_dict {}".format(radio_ath10K_9984_an_AC_dict)) - logg.info("CONTROLLER DENSITY INVALID FOR RADIO DICTIONARY: MOVE TO NEXT DENSITY CONTINUING TESTING") + logg.info( + "CONTROLLER DENSITY INVALID FOR RADIO DICTIONARY: controller_client_density: {} not supported for configuration".format( + controller_client_density)) + logg.info( + "CONTROLLER DENSITY INVALID FOR RADIO DICTIONARY: current dictionary radio_AX200_abgn_ax_dict {}".format( + radio_ath10K_9984_an_AC_dict)) + logg.info( + "CONTROLLER DENSITY INVALID FOR RADIO DICTIONARY: MOVE TO NEXT DENSITY CONTINUING TESTING") continue else: logg.info("##################################") logg.info("# INVALID COMBINATION 5ghz") - #logg.info("# controller run settings: {}".format(test_config)) + # logg.info("# controller run settings: {}".format(test_config)) logg.info("##################################") exit(1) - else: # controller_band == "b" - if controller_wifimode == "an" or controller_wifimode == "anAX" or controller_wifimode == "abgn" or controller_wifimode == "bg" or controller_wifimode == "auto": - #AX200 dual band + else: # controller_band == "b" + if controller_wifimode == "an" or controller_wifimode == "anAX" or controller_wifimode == "abgn" or controller_wifimode == "bg" or controller_wifimode == "auto": + # AX200 dual band try: radios = radio_AX200_abgn_ax_dict[controller_client_density] logg.info("radios: {}".format(radios)) except: - logg.info("CONTROLLER DENSITY INVALID FOR RADIO DICTIONARY: controller_client_density: {} not supported for configuration".format(controller_client_density)) - logg.info("CONTROLLER DENSITY INVALID FOR RADIO DICTIONARY: current dictionary radio_AX200_abgn_ax_dict {}".format(radio_AX200_abgn_ax_dict)) - logg.info("CONTROLLER DENSITY INVALID FOR RADIO DICTIONARY: MOVE TO NEXT DENSITY CONTINUING TESTING") + logg.info( + "CONTROLLER DENSITY INVALID FOR RADIO DICTIONARY: controller_client_density: {} not supported for configuration".format( + controller_client_density)) + logg.info( + "CONTROLLER DENSITY INVALID FOR RADIO DICTIONARY: current dictionary radio_AX200_abgn_ax_dict {}".format( + radio_AX200_abgn_ax_dict)) + logg.info( + "CONTROLLER DENSITY INVALID FOR RADIO DICTIONARY: MOVE TO NEXT DENSITY CONTINUING TESTING") continue else: logg.info("##################################") logg.info("# INVALID COMBINATION 24 ghz") - #logg.info("# controller run settings: {}".format(test_config)) + # logg.info("# controller run settings: {}".format(test_config)) logg.info("##################################") exit(1) for controller_packet_type in controller_packet_types: for controller_direction in controller_directions: # looping though both A and B together, upload direction will select A, download direction will select B - for side_a_tx_min_bps_ul, side_b_tx_min_bps_dl in itertools.zip_longest(controller_side_a_tx_min_bps, controller_side_b_tx_min_bps, fillvalue = 256000): + for side_a_tx_min_bps_ul, side_b_tx_min_bps_dl in itertools.zip_longest( + controller_side_a_tx_min_bps, + controller_side_b_tx_min_bps, fillvalue=256000): for controller_pdu in controller_pdus: - logg.info("###################################################################") - logg.info("# TEST RUNNING direction:{} ul: {} , TEST RUNNING dl: {}" - .format(controller_direction, side_a_tx_min_bps_ul, side_b_tx_min_bps_dl)) - logg.info("####################################################################") + logg.info( + "###################################################################") + logg.info( + "# TEST RUNNING direction:{} ul: {} , TEST RUNNING dl: {}".format( + controller_direction, + side_a_tx_min_bps_ul, + side_b_tx_min_bps_dl)) + logg.info( + "####################################################################") test_config = "AP=={} Band=={} chan_5ghz=={} chan_24ghz=={} wifi_mode=={} BW=={} encryption=={} ap_mode=={} clients=={} packet_type=={} direction=={} pdu=={}".format( - controller_ap,controller_band,controller_chan_5ghz,controller_chan_24ghz,controller_wifimode,controller_chan_width,controller_data_encryption,controller_ap_mode,controller_client_density, - controller_packet_type,controller_direction,controller_pdu) - test_keys = ['AP','Band','wifi_mode','chan_5ghz','chan_24ghz','BW','encryption','ap_mode','clients','packet_type','direction','pdu'] - logg.info("# controller run settings: {}".format(test_config)) - if(args.no_controller): - logg.info("################################################") - logg.info("# TEST MODE : NO CONTROLLER SET : TEST MODE") - logg.info("################################################") - if( controller_ap != __ap_set or - controller_band != __band_set or - controller_chan_width != __chan_width_set or - controller_ap_mode != __ap_mode_set or - controller_tx_power != __tx_power_set or - controller_chan_5ghz != __chan_5ghz_set or - controller_chan_24ghz != __chan_24ghz_set - ): - logg.info("###############################################") - logg.info("# TEST MODE : NEW CONTROLLER CONFIG : TEST MODE") - logg.info("###############################################") - __ap_set = controller_ap - __band_set = controller_band - __chan_width_set = controller_chan_width - __ap_mode_set = controller_ap_mode - __tx_power_set = controller_tx_power - __chan_5ghz_set = controller_chan_5ghz - __chan_24ghz_set = controller_chan_24ghz - __client_density = controller_client_density + controller_ap, controller_band, + controller_chan_5ghz, controller_chan_24ghz, + controller_wifimode, controller_chan_width, + controller_data_encryption, controller_ap_mode, + controller_client_density, + controller_packet_type, controller_direction, + controller_pdu) + test_keys = ['AP', 'Band', 'wifi_mode', 'chan_5ghz', + 'chan_24ghz', 'BW', 'encryption', + 'ap_mode', 'clients', 'packet_type', + 'direction', 'pdu'] + logg.info( + "# controller run settings: {}".format(test_config)) + if args.no_controller: + logg.info( + "################################################") + logg.info( + "# TEST MODE : NO CONTROLLER SET : TEST MODE") + logg.info( + "################################################") + if (controller_ap != __ap_set or + controller_band != __band_set or + controller_chan_width != __chan_width_set or + controller_ap_mode != __ap_mode_set or + controller_tx_power != __tx_power_set or + controller_chan_5ghz != __chan_5ghz_set or + controller_chan_24ghz != __chan_24ghz_set): + logg.info( + "###############################################") + logg.info( + "# TEST MODE : NEW CONTROLLER CONFIG : TEST MODE") + logg.info( + "###############################################") + __ap_set = controller_ap + __band_set = controller_band + __chan_width_set = controller_chan_width + __ap_mode_set = controller_ap_mode + __tx_power_set = controller_tx_power + __chan_5ghz_set = controller_chan_5ghz + __chan_24ghz_set = controller_chan_24ghz + __client_density = controller_client_density else: - logg.info("################################################") - logg.info("# SETUP MODE : SETUP CONTROLLER : SETUP MODE") - logg.info("################################################") - - if( controller_ap != __ap_set or - controller_band != __band_set or - controller_chan_width != __chan_width_set or - controller_ap_mode != __ap_mode_set or - controller_tx_power != __tx_power_set or - controller_chan_5ghz != __chan_5ghz_set or - controller_chan_24ghz != __chan_24ghz_set - ): - logg.info("###############################################") - logg.info("# SETUP MODE : NEW CONTROLLER CONFIG") - logg.info("###############################################") - __ap_set = controller_ap - __band_set = controller_band - __chan_width_set = controller_chan_width - __ap_mode_set = controller_ap_mode - __tx_power_set = controller_tx_power - __chan_5ghz_set = controller_chan_5ghz - __chan_24ghz_set = controller_chan_24ghz - __client_density = controller_client_density + logg.info( + "################################################") + logg.info( + "# SETUP MODE : SETUP CONTROLLER : SETUP MODE") + logg.info( + "################################################") + + if (controller_ap != __ap_set or + controller_band != __band_set or + controller_chan_width != __chan_width_set or + controller_ap_mode != __ap_mode_set or + controller_tx_power != __tx_power_set or + controller_chan_5ghz != __chan_5ghz_set or + controller_chan_24ghz != __chan_24ghz_set): + logg.info( + "###############################################") + logg.info( + "# SETUP MODE : NEW CONTROLLER CONFIG") + logg.info( + "###############################################") + __ap_set = controller_ap + __band_set = controller_band + __chan_width_set = controller_chan_width + __ap_mode_set = controller_ap_mode + __tx_power_set = controller_tx_power + __chan_5ghz_set = controller_chan_5ghz + __chan_24ghz_set = controller_chan_24ghz + __client_density = controller_client_density controller = CreateCtlr( - _scheme=__scheme, - _port=__port, - _series=__series, - _ctlr=__ctlr, - _prompt=__prompt, - _user=__user, - _passwd=__passwd, - _ap=__ap_set, - _band=__band_set, - _chan_5ghz=__chan_5ghz_set, - _chan_24ghz=__chan_24ghz_set, - _chan_width=__chan_width_set, - _ap_mode=__ap_mode_set, - _tx_power=__tx_power_set, - _wlan = __wlan, - _cap_ctl_out=__cap_ctl_out - ) - #Disable AP + _scheme=__scheme, + _port=__port, + _series=__series, + _ctlr=__ctlr, + _prompt=__prompt, + _user=__user, + _passwd=__passwd, + _ap=__ap_set, + _band=__band_set, + _chan_5ghz=__chan_5ghz_set, + _chan_24ghz=__chan_24ghz_set, + _chan_width=__chan_width_set, + _ap_mode=__ap_mode_set, + _tx_power=__tx_power_set, + _wlan=__wlan, + _cap_ctl_out=__cap_ctl_out + ) + # Disable AP # # Controller Configuration # - #if controller_args.controller_series == "9800": + # if controller_args.controller_series == "9800": # controller_controller_no_loggin_console() pss = controller.controller_show_ap_summary() logg.info("pss {}".format(pss)) @@ -2387,13 +2660,13 @@ LANforge GUI what is displayed in the Column and how to access the value with cl controller.controller_set_tx_power() controller.controller_set_channel() controller.controller_set_bandwidth() - #if controller_args.controller_series == "9800": - # CANDELA TODO, not needed controller.controller_create_wlan() - # CANDELA TODO set the policy tag, controller.controller_set_wireless_tag_policy() - # CANDELA controller.controller_enable_wlan() - if controller_band == "a": + # if controller_args.controller_series == "9800": + # CANDELA TODO, not needed controller.controller_create_wlan() + # CANDELA TODO set the policy tag, controller.controller_set_wireless_tag_policy() + # CANDELA controller.controller_enable_wlan() + if controller_band == "a": controller.controller_enable_network_5ghz() - else: + else: controller.controller_enable_network_24ghz() controller.controller_enable_ap() # need to actually check the CAC timer @@ -2402,140 +2675,184 @@ LANforge GUI what is displayed in the Column and how to access the value with cl # end of controller controller code #################################### else: - logg.info("###############################################") - logg.info("# SETUP MODE : NO CHANGE TO CONTROLLER CONFIG") - logg.info("###############################################") - logg.info("controller_ap: {} controller_band: {} controller_chan_width: {} controller_ap_mode: {} controller_tx_power: {} controller_chan_5ghz: {} controller_chan_24ghz: {}" - .format(controller_ap,controller_band, controller_chan_width, controller_ap_mode, controller_tx_power, controller_chan_5ghz, controller_chan_24ghz)) - logg.info("__ap_set: {} __band_set: {} __chan_width_set: {} __ap_mode_set: {} __tx_power_set: {} __chan_5ghz_set: {} __chan_24ghz_set: {}" - .format(__ap_set,__band_set, __chan_width_set, __ap_mode_set, __tx_power_set, __chan_5ghz_set, __chan_24ghz_set)) - logg.info("controller_wifi_mode {}".format(controller_wifimode)) + logg.info( + "###############################################") + logg.info( + "# SETUP MODE : NO CHANGE TO CONTROLLER CONFIG") + logg.info( + "###############################################") + logg.info( + "controller_ap: {} controller_band: {} controller_chan_width: {} controller_ap_mode: {} controller_tx_power: {} controller_chan_5ghz: {} controller_chan_24ghz: {}".format( + controller_ap, controller_band, + controller_chan_width, + controller_ap_mode, + controller_tx_power, + controller_chan_5ghz, + controller_chan_24ghz)) + logg.info( + "__ap_set: {} __band_set: {} __chan_width_set: {} __ap_mode_set: {} __tx_power_set: {} __chan_5ghz_set: {} __chan_24ghz_set: {}".format( + __ap_set, __band_set, + __chan_width_set, __ap_mode_set, + __tx_power_set, __chan_5ghz_set, + __chan_24ghz_set)) + logg.info("controller_wifi_mode {}".format( + controller_wifimode)) logg.info("radios {}".format(radios)) for radio_ in radios: - radio_keys = ['radio','stations','ssid','ssid_pw','security','wifimode'] - radio_info_dict = dict(map(lambda x: x.split('=='), str(radio_).replace('[','').replace(']','').replace("'","").split())) - logg.info("radio_dict {}".format(radio_info_dict)) + radio_keys = ['radio', 'stations', 'ssid', + 'ssid_pw', 'security', 'wifimode'] + radio_info_dict = dict( + map(lambda x: x.split('=='), + str(radio_).replace('[', '').replace( + ']', '').replace("'", "").split())) + logg.info( + "radio_dict {}".format(radio_info_dict)) for key in radio_keys: if key not in radio_info_dict: - logg.info("missing config, for the {}, all of the following need to be present {} ".format(key,radio_keys)) + logg.info( + "missing config, for the {}, all of the following need to be present {} ".format( + key, radio_keys)) exit(1) radio_name_list.append(radio_info_dict['radio']) ssid_list.append(radio_info_dict['ssid']) - ssid_password_list.append(radio_info_dict['ssid_pw']) - ssid_security_list.append(radio_info_dict['security']) + ssid_password_list.append( + radio_info_dict['ssid_pw']) + ssid_security_list.append( + radio_info_dict['security']) if args.radio: - number_of_stations_per_radio_list.append(radio_info_dict['stations']) - wifimode_list.append(int(wifi_mode_dict[radio_info_dict['wifimode']])) - else: - number_of_stations_per_radio_list.append(radio_info_dict['stations']) - wifimode_list.append(int(wifi_mode_dict[radio_info_dict['wifimode']])) - optional_radio_reset_keys = ['reset_port_enable'] + number_of_stations_per_radio_list.append( + radio_info_dict['stations']) + wifimode_list.append(int(wifi_mode_dict[ + radio_info_dict[ + 'wifimode']])) + else: + number_of_stations_per_radio_list.append( + radio_info_dict['stations']) + wifimode_list.append(int(wifi_mode_dict[ + radio_info_dict[ + 'wifimode']])) + optional_radio_reset_keys = [ + 'reset_port_enable'] radio_reset_found = True for key in optional_radio_reset_keys: if key not in radio_info_dict: - #logg.info("port reset test not enabled") + # logg.info("port reset test not enabled") radio_reset_found = False break - + if radio_reset_found: reset_port_enable_list.append(True) - reset_port_time_min_list.append(radio_info_dict['reset_port_time_min']) - reset_port_time_max_list.append(radio_info_dict['reset_port_time_max']) + reset_port_time_min_list.append( + radio_info_dict['reset_port_time_min']) + reset_port_time_max_list.append( + radio_info_dict['reset_port_time_max']) else: reset_port_enable_list.append(False) reset_port_time_min_list.append('0s') reset_port_time_max_list.append('0s') # no stations for testing reconfiguration of the controller - - if(args.no_stations): - logg.info("#################################################") + if args.no_stations: + logg.info( + "#################################################") logg.info("# TEST MODE : NO STATIONS TEST MODE") - logg.info("##################################################") + logg.info( + "##################################################") else: - logg.info("#################################################") - logg.info("# SETUP MODE : CREATING STATIONS SETUP MODE") - logg.info("##################################################") + logg.info( + "#################################################") + logg.info( + "# SETUP MODE : CREATING STATIONS SETUP MODE") + logg.info( + "##################################################") index = 0 station_lists = [] - for (radio_name_, number_of_stations_per_radio_) in zip(radio_name_list,number_of_stations_per_radio_list): - number_of_stations = int(number_of_stations_per_radio_) + for ( + radio_name_, + number_of_stations_per_radio_) in zip(radio_name_list, number_of_stations_per_radio_list): + number_of_stations = int( + number_of_stations_per_radio_) if number_of_stations > MAX_NUMBER_OF_STATIONS: - logg.info("number of stations per radio exceeded max of : {}".format(MAX_NUMBER_OF_STATIONS)) + logg.info( + "number of stations per radio exceeded max of : {}".format( + MAX_NUMBER_OF_STATIONS)) quit(1) - station_list = LFUtils.portNameSeries(prefix_="sta", start_id_= 1 + index*1000, end_id_= number_of_stations + index*1000, - padding_number_=10000, radio=radio_name_) + station_list = LFUtils.portNameSeries( + prefix_="sta", start_id_=1 + index * 1000, + end_id_=number_of_stations + index * 1000, + padding_number_=10000, radio=radio_name_) station_lists.append(station_list) index += 1 # Run Traffic upload (STA to AP) - if(controller_direction == "upload"): - side_a_tx_min_bps = side_a_tx_min_bps_ul - side_b_tx_min_bps = 0 - # Run Traffic download (AP to STA) + if controller_direction == "upload": + side_a_tx_min_bps = side_a_tx_min_bps_ul + side_b_tx_min_bps = 0 + # Run Traffic download (AP to STA) else: - side_a_tx_min_bps = 0 - side_b_tx_min_bps = side_b_tx_min_bps_dl - # current default is to have a values + side_a_tx_min_bps = 0 + side_b_tx_min_bps = side_b_tx_min_bps_dl + # current default is to have a values ip_var_test = L3VariableTime( - args=args, - _scheme=__scheme, - _port=__port, - _series=__series, - _ctlr=__ctlr, - _prompt=__prompt, - _user=__user, - _passwd=__passwd, - _ap=__ap_set, - _ap_slot=__ap_slot, - _band=__band_set, - _chan_5ghz=__chan_5ghz_set, - _chan_24ghz=__chan_24ghz_set, - _chan_width=__chan_width_set, - _ap_mode=__ap_mode_set, - _tx_power=__tx_power_set, - _client_density=__client_density, - _cap_ctl_out=__cap_ctl_out, - _ap_dict = ap_dict, - endp_type=controller_packet_type, - tos=args.tos, - side_b=side_b, - radio_name_list=radio_name_list, - number_of_stations_per_radio_list=number_of_stations_per_radio_list, - ssid_list=ssid_list, - ssid_password_list=ssid_password_list, - ssid_security_list=ssid_security_list, - wifimode_list=wifimode_list, - station_lists= station_lists, - name_prefix="LT-", - debug_on=debug_on, - wait_timeout=wait_timeout, - outfile=csv_outfile, - results=csv_results, - test_keys=test_keys, - test_config=test_config, - reset_port_enable_list=reset_port_enable_list, - reset_port_time_min_list=reset_port_time_min_list, - reset_port_time_max_list=reset_port_time_max_list, - csv_started=__csv_started, - side_a_tx_min_bps = side_a_tx_min_bps, - side_a_tx_max_bps =0, - side_a_min_pdu =controller_pdu, - side_a_max_pdu =0, - side_b_tx_min_bps =side_b_tx_min_bps, - side_b_tx_max_bps =0, - side_b_min_pdu =controller_pdu, - side_b_max_pdu = 0, - number_template="00", - test_duration=test_duration, - polling_interval= polling_interval, - lfclient_host=lfjson_host, - lfclient_port=lfjson_port) + args=args, + _scheme=__scheme, + _port=__port, + _series=__series, + _ctlr=__ctlr, + _prompt=__prompt, + _user=__user, + _passwd=__passwd, + _ap=__ap_set, + _ap_slot=__ap_slot, + _band=__band_set, + _chan_5ghz=__chan_5ghz_set, + _chan_24ghz=__chan_24ghz_set, + _chan_width=__chan_width_set, + _ap_mode=__ap_mode_set, + _tx_power=__tx_power_set, + _client_density=__client_density, + _cap_ctl_out=__cap_ctl_out, + _ap_dict=ap_dict, + endp_type=controller_packet_type, + tos=args.tos, + side_b=args.upstream_port, + radio_name_list=radio_name_list, + number_of_stations_per_radio_list=number_of_stations_per_radio_list, + ssid_list=ssid_list, + ssid_password_list=ssid_password_list, + ssid_security_list=ssid_security_list, + wifimode_list=wifimode_list, + station_lists=station_lists, + name_prefix="LT-", + debug_on=debug_on, + wait_timeout=args.wait_timeout, + outfile=csv_outfile, + results=csv_results, + test_keys=test_keys, + test_config=test_config, + reset_port_enable_list=reset_port_enable_list, + reset_port_time_min_list=reset_port_time_min_list, + reset_port_time_max_list=reset_port_time_max_list, + csv_started=__csv_started, + side_a_tx_min_bps=side_a_tx_min_bps, + side_a_tx_max_bps=0, + side_a_min_pdu=controller_pdu, + side_a_max_pdu=0, + side_b_tx_min_bps=side_b_tx_min_bps, + side_b_tx_max_bps=0, + side_b_min_pdu=controller_pdu, + side_b_max_pdu=0, + number_template="00", + test_duration=args.test_duration, + polling_interval=args.polling_interval, + lfclient_host=args.mgr, + lfclient_port=lfjson_port) __csv_started = True ip_var_test.pre_cleanup() ip_var_test.build() if not ip_var_test.passes(): logg.info("build step failed.") logg.info(ip_var_test.get_fail_message()) - exit(1) + exit(1) ip_var_test.start(False, False) ip_var_test.stop() if not ip_var_test.passes(): @@ -2549,17 +2866,18 @@ LANforge GUI what is displayed in the Column and how to access the value with cl ssid_security_list = [] wifimode_list = [] ip_var_test.cleanup() - if ( args.no_stations): + if args.no_stations: pass else: ip_var_test.passes() - logg.info("Full test passed, all connections increased rx rate") + logg.info( + "Full test passed, all connections increased rx rate") ########################################## # # Build Results # ########################################## - if args.csv_outfile != None: + if args.csv_outfile: logg.info("Report CSV Details: {}".format(csv_outfile)) logg.info("Report CSV Results: {}".format(csv_results)) report.set_title("Scaling And Performance") @@ -2569,10 +2887,11 @@ LANforge GUI what is displayed in the Column and how to access the value with cl report.set_table_dataframe_from_csv(csv_results) report.build_table() report.write_html() - report.write_pdf(_page_size = 'A3', _orientation='Landscape') + report.write_pdf(_page_size='A3', _orientation='Landscape') if args.log: logg.info("output_log: {}".format(outfile_log)) + if __name__ == "__main__": main() diff --git a/py-scripts/lf_tr398v2_test.py b/py-scripts/lf_tr398v2_test.py index 3be1b939..04896fe0 100755 --- a/py-scripts/lf_tr398v2_test.py +++ b/py-scripts/lf_tr398v2_test.py @@ -266,7 +266,6 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) cv_test_manager = importlib.import_module("py-json.cv_test_manager") @@ -291,17 +290,25 @@ class TR398v2Test(cvtest): raw_lines_file="", dut5="", dut2="", - enables=[], - disables=[], - raw_lines=[], - sets=[], + enables=None, + disables=None, + raw_lines=None, + sets=None, ): super().__init__(lfclient_host=lf_host, lfclient_port=lf_port) + if enables is None: + enables = [] + if disables is None: + disables = [] + if raw_lines is None: + raw_lines = [] + if sets is None: + sets = [] self.lf_host = lf_host self.lf_port = lf_port self.lf_user = lf_user - self.lf_password =lf_password + self.lf_password = lf_password self.instance_name = instance_name self.config_name = config_name self.dut5 = dut5 @@ -322,13 +329,12 @@ class TR398v2Test(cvtest): # Nothing to do at this time. return - def run(self): self.sync_cv() time.sleep(2) self.sync_cv() - blob_test = "TR398v2-"; + blob_test = "TR398v2-" self.rm_text_blob(self.config_name, blob_test) # To delete old config with same name self.show_text_blob(None, None, False) @@ -362,7 +368,6 @@ class TR398v2Test(cvtest): def main(): - parser = argparse.ArgumentParser(""" Open this file in an editor and read the top notes for more details. @@ -419,25 +424,25 @@ def main(): cv_base_adjust_parser(args) - CV_Test = TR398v2Test(lf_host = args.mgr, - lf_port = args.port, - lf_user = args.lf_user, - lf_password = args.lf_password, - instance_name = args.instance_name, - config_name = args.config_name, - upstream = args.upstream, - pull_report = args.pull_report, - local_lf_report_dir = args.local_lf_report_dir, - load_old_cfg = args.load_old_cfg, - dut2 = args.dut2, - dut5 = args.dut5, - raw_lines_file = args.raw_lines_file, - enables = args.enable, - disables = args.disable, - raw_lines = args.raw_line, - sets = args.set, + CV_Test = TR398v2Test(lf_host=args.mgr, + lf_port=args.port, + lf_user=args.lf_user, + lf_password=args.lf_password, + instance_name=args.instance_name, + config_name=args.config_name, + upstream=args.upstream, + pull_report=args.pull_report, + local_lf_report_dir=args.local_lf_report_dir, + load_old_cfg=args.load_old_cfg, + dut2=args.dut2, + dut5=args.dut5, + raw_lines_file=args.raw_lines_file, + enables=args.enable, + disables=args.disable, + raw_lines=args.raw_line, + sets=args.set, test_rig=args.test_rig - ) + ) CV_Test.setup() CV_Test.run() diff --git a/py-scripts/lf_webpage.py b/py-scripts/lf_webpage.py index 79a27a62..32f80daf 100755 --- a/py-scripts/lf_webpage.py +++ b/py-scripts/lf_webpage.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 """ This script will create 40 clients on 5Ghz , 2.4Ghz and Both and generate layer4 traffic on LANforge ,The Webpage Download Test is designed to test the performance of the Access Point.The goal is to check whether the webpage loading time meets the expectation when clients connected on single radio as well as dual radio. @@ -13,8 +14,10 @@ import importlib import time import argparse import paramiko +from datetime import datetime +import pandas as pd + - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) LFUtils = importlib.import_module("py-json.LANforge.LFUtils") @@ -23,6 +26,7 @@ Realm = realm.Realm PortUtils = realm.PortUtils lf_report = importlib.import_module("py-scripts.lf_report") lf_graph = importlib.import_module("py-scripts.lf_graph") +lf_kpi_csv = importlib.import_module("py-scripts.lf_kpi_csv") class HttpDownload(Realm): @@ -62,7 +66,7 @@ class HttpDownload(Realm): self.radio = [self.twog_radio] elif self.bands == "Both": self.radio = [self.fiveg_radio, self.twog_radio] - print( self.radio) + print(self.radio) self.num_sta = self.num_sta // 2 def precleanup(self): @@ -116,7 +120,7 @@ class HttpDownload(Realm): self.station_profile.create(radio=rad, sta_names_=self.station_list, debug=self.local_realm.debug) self.local_realm.wait_until_ports_appear(sta_list=self.station_list) self.station_profile.admin_up() - if self.local_realm.wait_for_ip(self.station_list,timeout_sec=60): + if self.local_realm.wait_for_ip(self.station_list, timeout_sec=60): self.local_realm._pass("All stations got IPs") else: self.local_realm._fail("Stations failed to get IPs") @@ -153,44 +157,22 @@ class HttpDownload(Realm): def stop(self): self.http_profile.stop_cx() - def my_monitor(self): + def my_monitor(self, data_mon): # data in json format - data = self.local_realm.json_get("layer4/list?fields=uc-avg") + data = self.local_realm.json_get("layer4/%s/list?fields=%s" % + (','.join(self.http_profile.created_cx.keys()), data_mon.replace(' ', '+'))) + # print(data) data1 = [] - for i in range(len(data['endpoint'])): - data1.append(str(list(data['endpoint'][i]))[2:-2]) - data2 = [] - for i in range(self.num_sta): - data = self.local_realm.json_get("layer4/list?fields=uc-avg") - # print(type(data['endpoint'][i][data1[i]]['uc-avg'])) - data2.append((data['endpoint'][i][data1[i]]['uc-avg'])) - return data2 - - def monitor_bytes(self): - # data in json format - data = self.local_realm.json_get("layer4/list?fields=bytes-rd") - data1 = [] - for i in range(len(data['endpoint'])): - data1.append(str(list(data['endpoint'][i]))[2:-2]) - data2 = [] - for i in range(self.num_sta): - data = self.local_realm.json_get("layer4/list?fields=bytes-rd") - # print(type(data['endpoint'][i][data1[i]]['uc-avg'])) - data2.append((data['endpoint'][i][data1[i]]['bytes-rd'])) - return data2 - - def monitor_rx(self): - # data in json format - data = self.local_realm.json_get("layer4/list?fields=rx rate") - data1 = [] - for i in range(len(data['endpoint'])): - data1.append(str(list(data['endpoint'][i]))[2:-2]) - data2 = [] - for i in range(self.num_sta): - data = self.local_realm.json_get("layer4/list?fields=rx rate") - # print(type(data['endpoint'][i][data1[i]]['uc-avg'])) - data2.append((data['endpoint'][i][data1[i]]['rx rate'])) - return data2 + data = data['endpoint'] + if self.num_sta == 1: + data1.append(data[data_mon]) + else: + for cx in self.http_profile.created_cx.keys(): + for info in data: + if cx in info: + data1.append(info[cx][data_mon]) + # print(data_mon, data1) + return data1 def postcleanup(self): self.http_profile.cleanup() @@ -198,7 +180,7 @@ class HttpDownload(Realm): LFUtils.wait_until_ports_disappear(base_url=self.local_realm.lfclient_url, port_list=self.station_profile.station_names, debug=self.debug) - def file_create(self,ssh_port): + def file_create(self, ssh_port): ip = self.host user = "root" pswd = "lanforge" @@ -228,13 +210,13 @@ class HttpDownload(Realm): time.sleep(1) return output - def download_time_in_sec(self,result_data): + def download_time_in_sec(self, result_data): self.resullt_data = result_data download_time = dict.fromkeys(result_data.keys()) for i in download_time: try: download_time[i] = result_data[i]['dl_time'] - except: + except BaseException: download_time[i] = [] print(download_time) lst = [] @@ -270,13 +252,13 @@ class HttpDownload(Realm): dataset.append(dwnld_time["Both"]) return dataset - def speed_in_Mbps(self,result_data): + def speed_in_Mbps(self, result_data): self.resullt_data = result_data speed = dict.fromkeys(result_data.keys()) for i in speed: try: speed[i] = result_data[i]['speed'] - except: + except BaseException: speed[i] = [] print(speed) lst = [] @@ -358,7 +340,7 @@ class HttpDownload(Realm): pass_fail_list.append("PASS") sumry2.append("PASS") # BOTH - if float(z11[2]) == 0.0 or float(z11[2]) > float(threshold_both) : + if float(z11[2]) == 0.0 or float(z11[2]) > float(threshold_both): var = "FAIL" pass_fail_list.append(var) sumryB.append("FAIL") @@ -462,88 +444,95 @@ class HttpDownload(Realm): pass def generate_graph(self, dataset, lis, bands): - graph = lf_bar_graph(_data_set=dataset, _xaxis_name="Stations", _yaxis_name="Time in Seconds", - _xaxis_categories=lis, _label=bands, _xticks_font=8, - _graph_image_name="webpage download time graph", - _color=['forestgreen', 'darkorange', 'blueviolet'], _color_edge='black', _figsize=(14, 5), - _grp_title="Download time taken by each client", _xaxis_step=1, _show_bar_value=True, - _text_font=6, _text_rotation=60, - _legend_loc="upper right", - _legend_box=(1, 1.15), - _enable_csv=True - ) + graph = lf_graph.lf_bar_graph(_data_set=dataset, _xaxis_name="Stations", _yaxis_name="Time in Seconds", + _xaxis_categories=lis, _label=bands, _xticks_font=8, + _graph_image_name="webpage download time graph", + _color=['forestgreen', 'darkorange', 'blueviolet'], _color_edge='black', _figsize=(14, 5), + _grp_title="Download time taken by each client", _xaxis_step=1, _show_bar_value=True, + _text_font=6, _text_rotation=60, + _legend_loc="upper right", + _legend_box=(1, 1.15), + _enable_csv=True + ) graph_png = graph.build_bar_graph() print("graph name {}".format(graph_png)) return graph_png - def graph_2(self,dataset2, lis, bands): - graph_2 = lf_bar_graph(_data_set=dataset2, _xaxis_name="Stations", _yaxis_name="Download Rate in Mbps", - _xaxis_categories=lis, _label=bands, _xticks_font=8, - _graph_image_name="webpage_speed_graph", - _color=['forestgreen', 'darkorange', 'blueviolet'], _color_edge='black', - _figsize=(14, 5), - _grp_title="Download rate for each client (Mbps)", _xaxis_step=1, _show_bar_value=True, - _text_font=6, _text_rotation=60, - _legend_loc="upper right", - _legend_box=(1, 1.15), - _enable_csv=True - ) + def graph_2(self, dataset2, lis, bands): + graph_2 = lf_graph.lf_bar_graph(_data_set=dataset2, _xaxis_name="Stations", _yaxis_name="Download Rate in Mbps", + _xaxis_categories=lis, _label=bands, _xticks_font=8, + _graph_image_name="webpage_speed_graph", + _color=['forestgreen', 'darkorange', 'blueviolet'], _color_edge='black', + _figsize=(14, 5), + _grp_title="Download rate for each client (Mbps)", _xaxis_step=1, _show_bar_value=True, + _text_font=6, _text_rotation=60, + _legend_loc="upper right", + _legend_box=(1, 1.15), + _enable_csv=True + ) graph_png = graph_2.build_bar_graph() return graph_png - def generate_report(self,date, num_stations,duration, test_setup_info,dataset,lis,bands,threshold_2g,threshold_5g,threshold_both,dataset2,summary_table_value,result_data,test_input_infor): - report = lf_report(_results_dir_name="webpage_test", _output_html="Webpage.html", _output_pdf="Webpage.pdf") - report.set_title("WEBPAGE DOWNLOAD TEST") - report.set_date(date) - report.build_banner() - report.set_table_title("Test Setup Information") - report.build_table_title() + def generate_report(self, date, num_stations, duration, test_setup_info, dataset, lis, bands, threshold_2g, + threshold_5g, threshold_both, dataset2, summary_table_value, result_data, test_rig, + test_tag, dut_hw_version, dut_sw_version, dut_model_num, dut_serial_num, test_id, + test_input_infor, csv_outfile): + report = lf_report.lf_report(_results_dir_name="webpage_test", _output_html="Webpage.html", _output_pdf="Webpage.pdf") - report.test_setup_table(value="Device under test", test_setup_data=test_setup_info) - - report.set_obj_html("Objective", - "The Webpage Download Test is designed to test the performance of the Access Point.The goal is to check whether the webpage loading time of all the " + str( - num_stations) + " clients which are downloading at the same time meets the expectation when clients connected on single radio as well as dual radio") - report.build_objective() - report.set_obj_html("Download Time Graph", - "The below graph provides information about the download time taken by each client to download webpage for test duration of " + str( - duration) + " min") - report.build_objective() - graph = self.generate_graph(dataset=dataset, lis=lis, bands=bands) - report.set_graph_image(graph) - report.set_csv_filename(graph) - report.move_csv_file() - report.move_graph_image() - report.build_graph() - report.set_obj_html("Download Rate Graph", - "The below graph provides information about the download rate in Mbps of each client to download the webpage for test duration of " + str( - duration) + " min") - report.build_objective() - graph2 = self.graph_2(dataset2, lis=lis, bands=bands) - print("graph name {}".format(graph2)) - report.set_graph_image(graph2) - report.set_csv_filename(graph2) - report.move_csv_file() - report.move_graph_image() - report.build_graph() - report.set_obj_html("Summary Table Description", - "This Table shows you the summary result of Webpage Download Test as PASS or FAIL criteria. If the average time taken by " + str( - num_stations) + " clients to access the webpage is less than " + str( - threshold_2g) + "s it's a PASS criteria for 2.4 ghz clients, If the average time taken by " + "" + str( - num_stations) + " clients to access the webpage is less than " + str( - threshold_5g) + "s it's a PASS criteria for 5 ghz clients and If the average time taken by " + str( - num_stations) + " clients to access the webpage is less than " + str( - threshold_both) + "s it's a PASS criteria for 2.4 ghz and 5ghz clients") - - report.build_objective() - test_setup1 = pd.DataFrame(summary_table_value) - report.set_table_dataframe(test_setup1) - report.build_table() - - report.set_obj_html("Download Time Table Description", - "This Table will provide you information of the minimum, maximum and the average time taken by clients to download a webpage in seconds") - - report.build_objective() + # Section commented because graphing breaks two band report generation + # TODO: Fix graphing bug with multiple bands being recorded + # + # report.set_title("WEBPAGE DOWNLOAD TEST") + # report.set_date(date) + # report.build_banner() + # report.set_table_title("Test Setup Information") + # report.build_table_title() + # + # report.test_setup_table(value="Device under test", test_setup_data=test_setup_info) + # + # report.set_obj_html("Objective", + # "The Webpage Download Test is designed to test the performance of the Access Point.The goal is to check whether the webpage loading time of all the " + str( + # num_stations) + " clients which are downloading at the same time meets the expectation when clients connected on single radio as well as dual radio") + # report.build_objective() + # report.set_obj_html("Download Time Graph", + # "The below graph provides information about the download time taken by each client to download webpage for test duration of " + str( + # duration) + " min") + # report.build_objective() + # graph = self.generate_graph(dataset=dataset, lis=lis, bands=bands) + # report.set_graph_image(graph) + # report.set_csv_filename(graph) + # report.move_csv_file() + # report.move_graph_image() + # report.build_graph() + # report.set_obj_html("Download Rate Graph", + # "The below graph provides information about the download rate in Mbps of each client to download the webpage for test duration of " + str( + # duration) + " min") + # report.build_objective() + # graph2 = self.graph_2(dataset2, lis=lis, bands=bands) + # print("graph name {}".format(graph2)) + # report.set_graph_image(graph2) + # report.set_csv_filename(graph2) + # report.move_csv_file() + # report.move_graph_image() + # report.build_graph() + # report.set_obj_html("Summary Table Description", + # "This Table shows you the summary result of Webpage Download Test as PASS or FAIL criteria. If the average time taken by " + str( + # num_stations) + " clients to access the webpage is less than " + str( + # threshold_2g) + "s it's a PASS criteria for 2.4 ghz clients, If the average time taken by " + "" + str( + # num_stations) + " clients to access the webpage is less than " + str( + # threshold_5g) + "s it's a PASS criteria for 5 ghz clients and If the average time taken by " + str( + # num_stations) + " clients to access the webpage is less than " + str( + # threshold_both) + "s it's a PASS criteria for 2.4 ghz and 5ghz clients") + # + # report.build_objective() + # test_setup1 = pd.DataFrame(summary_table_value) + # report.set_table_dataframe(test_setup1) + # report.build_table() + # + # report.set_obj_html("Download Time Table Description", + # "This Table will provide you information of the minimum, maximum and the average time taken by clients to download a webpage in seconds") + # + # report.build_objective() x = [] for fcc in list(result_data.keys()): fcc_type = result_data[fcc]["min"] @@ -595,12 +584,52 @@ class HttpDownload(Realm): z2.append(i) download_table_value = { - "": bands, + "Band": bands, "Minimum": z, "Maximum": z1, "Average": z2 - } + + # Get the report path to create the kpi.csv path + kpi_path = report.get_report_path() + print("kpi_path :{kpi_path}".format(kpi_path=kpi_path)) + + kpi_csv = lf_kpi_csv.lf_kpi_csv( + _kpi_path=kpi_path, + _kpi_test_rig=test_rig, + _kpi_test_tag=test_tag, + _kpi_dut_hw_version=dut_hw_version, + _kpi_dut_sw_version=dut_sw_version, + _kpi_dut_model_num=dut_model_num, + _kpi_dut_serial_num=dut_serial_num, + _kpi_test_id=test_id) + kpi_csv.kpi_dict['Units'] = "Mbps" + for band in range(len(download_table_value["Band"])): + kpi_csv.kpi_csv_get_dict_update_time() + kpi_csv.kpi_dict['Graph-Group'] = "Webpage Download {band}".format( + band=download_table_value['Band'][band]) + kpi_csv.kpi_dict['short-description'] = "Webpage download {band} Minimum".format( + band=download_table_value['Band'][band]) + kpi_csv.kpi_dict['numeric-score'] = "{min}".format(min=download_table_value['Minimum'][band]) + kpi_csv.kpi_csv_write_dict(kpi_csv.kpi_dict) + kpi_csv.kpi_dict['short-description'] = "Webpage download {band} Maximum".format( + band=download_table_value['Band'][band]) + kpi_csv.kpi_dict['numeric-score'] = "{max}".format(max=download_table_value['Maximum'][band]) + kpi_csv.kpi_csv_write_dict(kpi_csv.kpi_dict) + kpi_csv.kpi_dict['short-description'] = "Webpage download {band} Average".format( + band=download_table_value['Band'][band]) + kpi_csv.kpi_dict['numeric-score'] = "{avg}".format(avg=download_table_value['Average'][band]) + kpi_csv.kpi_csv_write_dict(kpi_csv.kpi_dict) + + if csv_outfile is not None: + current_time = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + csv_outfile = "{}_{}-test_l3_longevity.csv".format( + csv_outfile, current_time) + csv_outfile = report.file_add_path(csv_outfile) + print("csv output file : {}".format(csv_outfile)) + + exit() + test_setup = pd.DataFrame(download_table_value) report.set_table_dataframe(test_setup) report.build_table() @@ -611,7 +640,8 @@ class HttpDownload(Realm): html_file = report.write_html() print("returned file {}".format(html_file)) print(html_file) - report.write_pdf() + report.write_pdf_with_timestamp(_page_size='A4', _orientation='Landscape') + def main(): parser = argparse.ArgumentParser( @@ -629,16 +659,32 @@ def main(): parser.add_argument('--passwd', help='WiFi passphrase/password/key') parser.add_argument('--target_per_ten', help='number of request per 10 minutes', default=100) parser.add_argument('--file_size', type=str, help='specify the size of file you want to download', default='5MB') - parser.add_argument('--bands', nargs="+", help='specify which band testing you want to run eg 5G OR 2.4G OR 5G 2.4G', default=["5G", "2.4G", "Both"]) + parser.add_argument('--bands', nargs="+", help='specify which band testing you want to run eg 5G OR 2.4G OR Both', + default=["5G", "2.4G", "Both"]) parser.add_argument('--duration', type=int, help='time to run traffic') - parser.add_argument('--threshold_5g',help="Enter the threshold value for 5G Pass/Fail criteria", default="60") - parser.add_argument('--threshold_2g',help="Enter the threshold value for 2.4G Pass/Fail criteria",default="90") - parser.add_argument('--threshold_both',help="Enter the threshold value for Both Pass/Fail criteria" , default="50") + parser.add_argument('--threshold_5g', help="Enter the threshold value for 5G Pass/Fail criteria", default="60") + parser.add_argument('--threshold_2g', help="Enter the threshold value for 2.4G Pass/Fail criteria", default="90") + parser.add_argument('--threshold_both', help="Enter the threshold value for Both Pass/Fail criteria", default="50") parser.add_argument('--ap_name', help="specify the ap model ", default="TestAP") - parser.add_argument('--ssh_port', type=int, help="specify the shh port eg 22",default=22) + parser.add_argument('--ssh_port', type=int, help="specify the ssh port eg 22", default=22) + parser.add_argument("--test_rig", default="", help="test rig for kpi.csv, testbed that the tests are run on") + parser.add_argument("--test_tag", default="", + help="test tag for kpi.csv, test specific information to differentiate the test") + parser.add_argument("--dut_hw_version", default="", + help="dut hw version for kpi.csv, hardware version of the device under test") + parser.add_argument("--dut_sw_version", default="", + help="dut sw version for kpi.csv, software version of the device under test") + parser.add_argument("--dut_model_num", default="", + help="dut model for kpi.csv, model number / name of the device under test") + parser.add_argument("--dut_serial_num", default="", + help="dut serial for kpi.csv, serial number / serial number of the device under test") + parser.add_argument("--test_priority", default="", help="dut model for kpi.csv, test-priority is arbitrary number") + parser.add_argument("--test_id", default="lf_webpage", help="test-id for kpi.csv, script or test name") + parser.add_argument('--csv_outfile', help="--csv_outfile ", default="") + args = parser.parse_args() - test_time = datetime.datetime.now() + test_time = datetime.now() test_time = test_time.strftime("%b %d %H:%M:%S") print("Test started at ", test_time) list5G = [] @@ -648,14 +694,14 @@ def main(): list2G_bytes = [] list2G_speed = [] Both = [] - Both_bytes =[] - Both_speed =[] + Both_bytes = [] + Both_speed = [] dict_keys = [] dict_keys.extend(args.bands) # print(dict_keys) final_dict = dict.fromkeys(dict_keys) # print(final_dict) - dict1_keys = ['dl_time', 'min', 'max', 'avg','bytes_rd', 'speed'] + dict1_keys = ['dl_time', 'min', 'max', 'avg', 'bytes_rd', 'speed'] for i in final_dict: final_dict[i] = dict.fromkeys(dict1_keys) print(final_dict) @@ -689,21 +735,20 @@ def main(): print("time in seconds ", duration) time.sleep(duration) http.stop() - value = http.my_monitor() - value2 = http.monitor_bytes() - value3 = http.monitor_rx() + uc_avg_val = http.my_monitor('uc-avg') + rx_bytes_val = http.my_monitor('bytes-rd') + rx_rate_val = http.my_monitor('rx rate') http.postcleanup() if bands == "5G": print("yes") - list5G.extend(value) - list5G_bytes.extend(value2) - list5G_speed.extend(value3) + list5G.extend(uc_avg_val) + list5G_bytes.extend(rx_bytes_val) + list5G_speed.extend(rx_rate_val) print(list5G) print(list5G_bytes) print(list5G_speed) final_dict['5G']['dl_time'] = list5G - min5.append(min(list5G)) final_dict['5G']['min'] = min5 max5.append(max(list5G)) @@ -714,9 +759,9 @@ def main(): final_dict['5G']['speed'] = list5G_speed elif bands == "2.4G": print("no") - list2G.extend(value) - list2G_bytes.extend(value2) - list2G_speed.extend(value3) + list2G.extend(uc_avg_val) + list2G_bytes.extend(rx_bytes_val) + list2G_speed.extend(rx_rate_val) print(list2G) print(list2G_bytes) print(list2G_speed) @@ -730,15 +775,15 @@ def main(): final_dict['2.4G']['bytes_rd'] = list2G_bytes final_dict['2.4G']['speed'] = list2G_speed elif bands == "Both": - Both.extend(value) - Both_bytes.extend(value2) - Both_speed.extend(value3) + Both.extend(uc_avg_val) + Both_bytes.extend(rx_bytes_val) + Both_speed.extend(rx_rate_val) final_dict['Both']['dl_time'] = Both min_both.append(min(Both)) final_dict['Both']['min'] = min_both max_both.append(max(Both)) final_dict['Both']['max'] = max_both - avg_both.append((sum(Both) /args.num_stations)) + avg_both.append((sum(Both) / args.num_stations)) final_dict['Both']['avg'] = avg_both final_dict['Both']['bytes_rd'] = Both_bytes final_dict['Both']['speed'] = Both_speed @@ -746,47 +791,52 @@ def main(): result_data = final_dict print("result", result_data) print("Test Finished") - test_end = datetime.datetime.now() + test_end = datetime.now() test_end = test_end.strftime("%b %d %H:%M:%S") print("Test ended at ", test_end) s1 = test_time s2 = test_end # for example FMT = '%b %d %H:%M:%S' - test_duration = datetime.datetime.strptime(s2, FMT) - datetime.datetime.strptime(s1, FMT) + test_duration = datetime.strptime(s2, FMT) - datetime.strptime(s1, FMT) print("total test duration ", test_duration) - date = str(datetime.datetime.now()).split(",")[0].replace(" ", "-").split(".")[0] + date = str(datetime.now()).split(",")[0].replace(" ", "-").split(".")[0] test_setup_info = { - "DUT Name": args.ap_name, - "SSID": args.ssid, - "Test Duration": test_duration, + "DUT Name": args.ap_name, + "SSID": args.ssid, + "Test Duration": test_duration, } - test_input_infor={ - "LANforge ip":args.mgr, - "File Size" : args.file_size, - "Bands" : args.bands, + test_input_infor = { + "LANforge ip": args.mgr, + "File Size": args.file_size, + "Bands": args.bands, "Upstream": args.upstream_port, "Stations": args.num_stations, - "SSID" :args.ssid, + "SSID": args.ssid, "Security": args.security, - "Duration" : args.duration, + "Duration": args.duration, "Contact": "support@candelatech.com" } http1 = HttpDownload(lfclient_host=args.mgr, lfclient_port=args.mgr_port, - upstream=args.upstream_port, num_sta=args.num_stations, - security=args.security, - ssid=args.ssid, password=args.passwd, - target_per_ten=args.target_per_ten, - file_size=args.file_size, bands=args.bands, - twog_radio=args.twog_radio, - fiveg_radio=args.fiveg_radio) + upstream=args.upstream_port, num_sta=args.num_stations, + security=args.security, + ssid=args.ssid, password=args.passwd, + target_per_ten=args.target_per_ten, + file_size=args.file_size, bands=args.bands, + twog_radio=args.twog_radio, + fiveg_radio=args.fiveg_radio) dataset = http1.download_time_in_sec(result_data=result_data) lis = [] for i in range(1, args.num_stations + 1): lis.append(i) - dataset2= http1.speed_in_Mbps(result_data=result_data) - data = http1.summary_calculation(result_data=result_data, bands=args.bands, threshold_5g=args.threshold_5g , threshold_2g= args.threshold_2g, threshold_both=args.threshold_both) + dataset2 = http1.speed_in_Mbps(result_data=result_data) + data = http1.summary_calculation( + result_data=result_data, + bands=args.bands, + threshold_5g=args.threshold_5g, + threshold_2g=args.threshold_2g, + threshold_both=args.threshold_both) summary_table_value = { "": args.bands, @@ -796,7 +846,13 @@ def main(): duration=args.duration, test_setup_info=test_setup_info, dataset=dataset, lis=lis, bands=args.bands, threshold_2g=args.threshold_2g, threshold_5g=args.threshold_5g, threshold_both=args.threshold_both, dataset2=dataset2, - summary_table_value=summary_table_value, result_data=result_data, test_input_infor=test_input_infor) + summary_table_value=summary_table_value, result_data=result_data, + test_rig=args.test_rig, test_tag=args.test_tag, dut_hw_version=args.dut_hw_version, + dut_sw_version=args.dut_sw_version, dut_model_num=args.dut_model_num, + dut_serial_num=args.dut_serial_num, test_id=args.test_id, + test_input_infor=test_input_infor, csv_outfile=args.csv_outfile) + + if __name__ == '__main__': main() diff --git a/py-scripts/lf_wifi_capacity_test.py b/py-scripts/lf_wifi_capacity_test.py index b457e4a8..bc469e9c 100755 --- a/py-scripts/lf_wifi_capacity_test.py +++ b/py-scripts/lf_wifi_capacity_test.py @@ -347,11 +347,11 @@ class WiFiCapacityTest(cv_test): security="open", paswd="[BLANK]", ssid="", - enables=[], - disables=[], - raw_lines=[], + enables=None, + disables=None, + raw_lines=None, raw_lines_file="", - sets=[], + sets=None, influx_host="localhost", influx_port=8086, report_dir="", @@ -362,6 +362,14 @@ class WiFiCapacityTest(cv_test): ): super().__init__(lfclient_host=lfclient_host, lfclient_port=lf_port) + if enables is None: + enables = [] + if disables is None: + disables = [] + if raw_lines is None: + raw_lines = [] + if sets is None: + sets = [] self.lfclient_host = lfclient_host self.lf_port = lf_port self.lf_user = lf_user @@ -534,7 +542,7 @@ def main(): parser.add_argument("--report_dir", default="") parser.add_argument("--scenario", default="") parser.add_argument("--graph_groups", help="File to save graph groups to", default=None) - parser.add_argument("--local_lf_report_dir", help="--local_lf_report_dir default '' put where dataplane script run from",default="") + parser.add_argument("--local_lf_report_dir", help="--local_lf_report_dir default '' put where dataplane script run from", default="") args = parser.parse_args() diff --git a/py-scripts/measure_station_time_up.py b/py-scripts/measure_station_time_up.py index 7a9f0d9f..b4b8086c 100755 --- a/py-scripts/measure_station_time_up.py +++ b/py-scripts/measure_station_time_up.py @@ -15,7 +15,6 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") @@ -34,7 +33,7 @@ class MeasureTimeUp(Realm): _port=None, _num_sta=None, _number_template="00000", - _radio=["wiphy0", "wiphy1"], + _radio=None, _proxy_str=None, _debug_on=False, _up=True, @@ -49,6 +48,8 @@ class MeasureTimeUp(Realm): _clean_dut="no"): super().__init__(_host, _port) + if _radio is None: + _radio = ["wiphy0", "wiphy1"] self.host = _host self.port = _port self.ssid = _ssid @@ -103,7 +104,7 @@ class MeasureTimeUp(Realm): self._pass("PASS: Station build finished") def scenario(self): - if self.load is not None: + if self.load: data = { "name": self.load, "action": self.action, @@ -117,13 +118,13 @@ class MeasureTimeUp(Realm): print("Loading database %s" % self.load) self.json_post("/cli-json/load", data) - elif self.start is not None: + elif self.start: print("Starting test group %s..." % self.start) self.json_post("/cli-json/start_group", {"name": self.start}) - elif self.stop is not None: + elif self.stop: print("Stopping test group %s..." % self.stop) self.json_post("/cli-json/stop_group", {"name": self.stop}) - elif self.quiesce is not None: + elif self.quiesce: print("Quiescing test group %s..." % self.quiesce) self.json_post("/cli-json/quiesce_group", {"name": self.quiesce}) @@ -151,35 +152,37 @@ Command example: ''') required = parser.add_argument_group('required arguments') required.add_argument('--report_file', help='where you want to store results', required=True) + parser.add_argument('--database', help='Which database to load', default='FACTORY_DFLT') + parser.add_argument('--radio2', help='second radio to create stations on', default='wiphy7') args = parser.parse_args() + if args.report_file.split('.')[-1] not in ['pkl', 'csv', 'xlsx']: + raise NameError('Please make sure your file name ends with either pkl, csv, or xlsx') + dictionary = dict() - for num_sta in list(filter(lambda x: (x % 2 == 0), [*range(0, 200)])): + for num_sta in list(filter(lambda x: (x % 2 == 0), [*range(0, args.num_stations)])): print(num_sta) - try: - create_station = MeasureTimeUp(_host=args.mgr, - _port=args.mgr_port, - _ssid=args.ssid, - _password=args.passwd, - _security=args.security, - _num_sta=num_sta, - _radio=["wiphy0", "wiphy1"], - _proxy_str=args.proxy, - _debug_on=args.debug, - _load='FACTORY_DFLT') - create_station.scenario() - time.sleep(5.0 + num_sta / 10) - start = datetime.datetime.now() - create_station.build() - built = datetime.datetime.now() - create_station.station_up() - stationsup = datetime.datetime.now() - dictionary[num_sta] = [start, built, stationsup] - create_station.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=station_list) - time.sleep(5.0 + num_sta / 20) - except: - pass + create_station = MeasureTimeUp(_host=args.mgr, + _port=args.mgr_port, + _ssid=args.ssid, + _password=args.passwd, + _security=args.security, + _num_sta=num_sta, + _radio=[args.radio, args.radio2], + _proxy_str=args.proxy, + _debug_on=args.debug, + _load=args.database) + create_station.scenario() + time.sleep(5.0 + num_sta / 10) + start = datetime.datetime.now() + create_station.build() + built = datetime.datetime.now() + create_station.station_up() + stationsup = datetime.datetime.now() + dictionary[num_sta] = [start, built, stationsup] + create_station.wait_until_ports_disappear() + time.sleep(5.0 + num_sta / 20) df = pd.DataFrame.from_dict(dictionary).transpose() df.columns = ['Start', 'Built', 'Stations Up'] df['built duration'] = df['Built'] - df['Start'] @@ -187,7 +190,12 @@ Command example: df['duration'] = df['Stations Up'] - df['Start'] for variable in ['built duration', 'duration']: df[variable] = [x.total_seconds() for x in df[variable]] - df.to_pickle(args.report_file) + if 'pkl' in args.report_file: + df.to_pickle(args.report_file) + if 'csv' in args.report_file: + df.to_csv(args.report_file) + if 'xlsx' in args.report_file: + df.to_excel(args.report_file) if __name__ == "__main__": diff --git a/py-scripts/port_probe.py b/py-scripts/port_probe.py deleted file mode 100755 index 64e9ca3f..00000000 --- a/py-scripts/port_probe.py +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/env python3 - -""" -NAME: port_probe.py - -PURPOSE: -Probes a port for information. If a station is used, an ssid, radio, and security type must be specified - -Use './port_probe.py --help' to see command line usage and options -Copyright 2021 Candela Technologies Inc -License: Free to distribute and modify. LANforge systems must be licensed. -""" - -import sys -import os - -if sys.version_info[0] != 3: - print("This script requires Python 3") - exit(1) - -if 'py-json' not in sys.path: - sys.path.append(os.path.join(os.path.abspath('..'), 'py-json')) - -if 'py-dashboard' not in sys.path: - sys.path.append(os.path.join(os.path.abspath('..'), 'py-dashboard')) - -import argparse -from LANforge import LFUtils -from realm import Realm -import datetime -import time -import pprint - - -class PortProbe(Realm): - def __init__(self, - ssid=None, - security=None, - password=None, - port_name=None, - upstream=None, - radio=None, - host="localhost", - port=8080, - mode=0, - number_template="00000", - use_ht160=False, - _debug_on=False, - _exit_on_error=False, - _exit_on_fail=False): - super().__init__(lfclient_host=host, - lfclient_port=port), - self.upstream = upstream - self.host = host - self.port = port - self.ssid = ssid - self.port_name = port_name - self.security = security - self.password = password - self.radio = radio - self.mode = mode - self.debug = _debug_on - if 'sta' in self.port_name: - self.number_template = number_template - self.station_profile = self.new_station_profile() - self.station_profile.lfclient_url = self.lfclient_url - self.station_profile.ssid = self.ssid - self.station_profile.ssid_pass = self.password - self.station_profile.security = self.security - self.station_profile.number_template_ = self.number_template - self.station_profile.debug = self.debug - - self.station_profile.use_ht160 = use_ht160 - if self.station_profile.use_ht160: - self.station_profile.mode = 9 - self.station_profile.mode = mode - - def start(self): - if 'sta' in self.port_name: - self.station_profile.admin_up() - print("Probing %s" % self.port_name) - port_info = self.name_to_eid(self.port_name) - data = { - "shelf": 1, - "resource": 1, - "port": self.port_name, - "key": "probe_port.quiet.%d.%d.%s" % (port_info[0], port_info[1], port_info[2]) - } - self.json_post("/cli-json/probe_port", data) - time.sleep(10) - probe_results = self.json_get("probe/1/1/%s" % self.port_name) - - print(probe_results) - - def cleanup(self): - if 'sta' in self.port_name: - self.station_profile.cleanup() - LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=self.station_profile.station_names, - debug=self.debug) - - def build(self): - if 'sta' in self.port_name: - self.station_profile.use_security(self.security, self.ssid, self.password) - self.station_profile.set_number_template(self.number_template) - print("Creating stations") - self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) - self.station_profile.set_command_param("set_port", "report_timer", 1500) - self.station_profile.set_command_flag("set_port", "rpt_timer", 1) - self.station_profile.create(radio=self.radio, sta_names_=[self.port_name], num_stations=1, debug=self.debug) - LFUtils.wait_until_ports_appear(self.port_name) - self._pass("PASS: Station build finished") - - -def main(): - parser = Realm.create_basic_argparse( - prog='port_probe_test.py', - formatter_class=argparse.RawTextHelpFormatter, - epilog='''\ - Used to probe ports for information - ''', - description='''\ - Probes a port for information. If a station is used, an ssid, radio, and security type must be specified - - Example: - ./port_probe.py --ssid test_name --security open --radio wiphy0 - ''') - - parser.add_argument('--mode', help='Used to force mode of stations') - parser.add_argument('--port_name', help='Name of station to be used', default="sta0000") - - args = parser.parse_args() - - port_probe = PortProbe(host=args.mgr, - port=args.mgr_port, - number_template="0000", - port_name=args.port_name, - upstream=args.upstream_port, - ssid=args.ssid, - password=args.passwd, - radio=args.radio, - security=args.security, - use_ht160=False, - mode=args.mode, - _debug_on=args.debug) - - port_probe.build() - # exit() - if not port_probe.passes(): - print(port_probe.get_fail_message()) - port_probe.exit_fail() - - port_probe.start() - port_probe.cleanup() - - -if __name__ == "__main__": - main() diff --git a/py-scripts/recordinflux.py b/py-scripts/recordinflux.py index 7493e111..5f0ec878 100755 --- a/py-scripts/recordinflux.py +++ b/py-scripts/recordinflux.py @@ -72,7 +72,7 @@ def main(): tags=tags) else: - from influx import RecordInflux + from influx_utils import RecordInflux grapher = RecordInflux(_influx_host=args.mgr, _influx_port=args.mgr_port, _influx_db=args.influx_db, diff --git a/py-scripts/regression_test.sh b/py-scripts/regression_test.sh index 6e25430c..212041c2 100755 --- a/py-scripts/regression_test.sh +++ b/py-scripts/regression_test.sh @@ -4,7 +4,7 @@ ########################## Help() { - echo "This bash script aims to automate the test process of all Candela Technologies's test_* scripts in the lanforge-scripts directory. The script can be run 2 ways and may include (via user input) the \"start_num\" and \"stop_num\" variables to select which tests should be run." + echo "This bash script aims to automate the test process of all Candela Technologies test_* scripts in the lanforge-scripts directory to detect software regressions. The script can be run 2 ways and may include (via user input) the \"start_num\" and \"stop_num\" variables to select which tests should be run." echo "OPTION ONE: ./regression_test.sh : this command runs all the scripts in the array \"testCommands\"" echo "OPTION TWO: ./regression_test.sh 4 5 : this command runs py-script commands (in testCommands array) that include the py-script options beginning with 4 and 5 (inclusive) in case function ret_case_num." echo "Optional Variables:" @@ -14,10 +14,14 @@ Help() echo "MGR is the IP address of the device which has LANforge installed, if different from the system you are using." echo "A is used to call to test a specific command based on" echo "F is used to pass in an RC file which can store the credentials for running regression multiple times on your system" + echo "H is used to test the help feature of each script, to make sure it renders properly." + echo "L is used to give the IP address of the LANforge device which is under test" echo "Example command: ./regression_test.sh -s SSID -p PASSWD -w SECURITY -m MGR" + echo "If using the help flag, put the H flag at the end of the command after other flags." } -while getopts ":h:s:p:w:m:A:r:F:B:U:" option; do + +while getopts ":h:s:S:p:w:m:A:r:F:B:U:D:H:M:C:" option; do case "${option}" in h) # display Help Help @@ -26,6 +30,9 @@ while getopts ":h:s:p:w:m:A:r:F:B:U:" option; do s) SSID_USED=${OPTARG} ;; + S) + SHORT="yes" + ;; p) PASSWD_USED=${OPTARG} ;; @@ -48,7 +55,20 @@ while getopts ":h:s:p:w:m:A:r:F:B:U:" option; do BSSID=${OPTARG} ;; U) - UPSTREAM=$OPTARG + UPSTREAM=${OPTARG} + ;; + D) + DUT5=${OPTARG} + DUT2=${OPTARG} + ;; + H) + ./lf_help_check.bash + ;; + M) + RADIO2=${OPTARG} + ;; + C) + RESOURCE=${OPTARG} ;; *) @@ -56,6 +76,36 @@ while getopts ":h:s:p:w:m:A:r:F:B:U:" option; do esac done +if [[ ${#MGR} -eq 0 ]]; then # Allow the user to change the radio they test against + MGR="localhost" +fi + +PYTHON_VERSION=$(python3 -c 'import sys; print(sys.version)') + +BuildVersion=$(wget $MGR:8080 -q -O - | jq '.VersionInfo.BuildVersion') +BuildDate=$(wget $MGR:8080 -q -O - | jq '.VersionInfo.BuildDate') +OS_Version=$(cat /etc/os-release | grep 'VERSION=') +HOSTNAME=$(cat /etc/hostname) +IP_ADDRESS=$(ip a sho eth0 | grep 'inet ' | cut -d "/" -f1 | cut -d "t" -f2) +PYTHON_ENVIRONMENT=$(which python3) + +#SCENARIO_CHECK="$(python3 -c "import requests; print(requests.get('http://${MGR}:8080/events/').status_code)")" +#if [[ ${SCENARIO_CHECK} -eq 200 ]]; then +# : +#else +# echo "${SCENARIO_CHECK}" +# echo "Your LANforge Manager is out of date. Regression test requires LANforge version 5.4.4 or higher in order to run" +# echo "Please upgrade your LANforge using instructions found at https://www.candelatech.com/downloads.php#releases" +# exit 1 +#fi + +if [ -d "/home/lanforge/lanforge_env" ] +then + pip3 install --upgrade lanforge-scripts +else + pip3 install --user -r ../requirements.txt --upgrade +fi + if [[ ${#SSID_USED} -eq 0 ]]; then #Network credentials SSID_USED="jedway-wpa2-x2048-5-3" PASSWD_USED="jedway-wpa2-x2048-5-3" @@ -63,17 +113,24 @@ if [[ ${#SSID_USED} -eq 0 ]]; then #Network credentials fi if [[ ${#RADIO_USED} -eq 0 ]]; then # Allow the user to change the radio they test against - RADIO_USED="wiphy1" + RADIO_USED="1.1.wiphy1" fi +if [[ ${#RADIO2} -eq 0 ]]; then # Allow the user to change the radio they test against + RADIO2="1.1.wiphy0" +fi if [[ ${#UPSTREAM} -eq 0 ]]; then - UPSTREAM="eth1" + UPSTREAM="1.1.eth1" fi if [[ ${#BSSID} -eq 0 ]]; then BSSID="04:f0:21:2c:41:84" fi +if [[ $RESOURCE -eq 0 ]]; then + RESOURCE="1.1" +fi + FILE="/tmp/gui-update.lock" if test -f "$FILE"; then echo "Finish updating your GUI" @@ -98,6 +155,10 @@ TEST_HTTP_IP=${TEST_HTTP_IP:-10.40.0.1} MGRLEN=${#MGR} COL_NAMES="name,tx_bytes,rx_bytes,dropped" +if [[ ${#DUT2} -eq 0 ]]; then + DUT5="linksys-8450 j-wpa2-153 c4:41:1e:f5:3f:25 (1)" + DUT2="linksys-8450 j-wpa2-153 c4:41:1e:f5:3f:25 (1)" +fi #CURR_TEST_NUM=0 CURR_TEST_NAME="BLANK" @@ -114,7 +175,7 @@ fi TEST_DIR="${REPORT_DATA}/${NOW}" function run_l3_longevity() { - ./test_l3_longevity.py --test_duration 15s --upstream_port eth1 --radio "radio==wiphy0 stations==4 ssid==$SSID_USED ssid_pw==$PASSWD_USED security==$SECURITY" --radio "radio==wiphy1 stations==4 ssid==$SSID_USED ssid_pw==$PASSWD_USED security==$SECURITY" --mgr "$MGR" + ./test_l3_longevity.py --test_duration 15s --upstream_port $UPSTREAM --radio "radio==wiphy0 stations==4 ssid==$SSID_USED ssid_pw==$PASSWD_USED security==$SECURITY" --radio "radio==wiphy1 stations==4 ssid==$SSID_USED ssid_pw==$PASSWD_USED security==$SECURITY" --lfmgr "$MGR" } function testgroup_list_groups() { ./scenario.py --load test_l3_scenario_throughput @@ -129,202 +190,213 @@ function testgroup_delete_group() { ./testgroup.py --group_name group1 --add_group --add_cx cx0000,cx0001,cx0002 --remove_cx cx0003 ./testgroup.py --group_name group1--del_group --debug --mgr "$MGR" } -if [[ $MGRLEN -gt 0 ]]; then +function create_bridge_and_station() { + ./create_station.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug --mgr $MGR + ./create_bridge.py --radio $RADIO_USED --upstream_port $UPSTREAM --target_device $RESOURCE.sta0000 --debug --mgr $MGR +} +function create_station_and_dataplane() { + ./create_station.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug --mgr $MGR + ./lf_dataplane_test.py --mgr $MGR --lf_user lanforge --lf_password lanforge \ + --instance_name dataplane-instance --config_name test_con --upstream $UPSTREAM \ + --dut linksys-8450 --duration 15s --station $RESOURCE.sta0001 \ + --download_speed 85% --upload_speed 0 \ + --test_rig Testbed-01 --pull_report \ + #--influx_host 192.168.100.153 --influx_port 8086 --influx_org Candela \ + #--influx_token=-u_Wd-L8o992701QF0c5UmqEp7w7Z7YOMaWLxOMgmHfATJGnQbbmYyNxHBR9PgD6taM_tcxqJl6U8DjU1xINFQ== \ + #--influx_bucket ben \ + #--influx_tag testbed Ferndale-01 +} +function create_dut_and_chamberview() { + ./create_chamberview.py -m $MGR -cs 'regression_test' --delete_scenario \ + --line "Resource=$RESOURCE Profile=STA-AC Amount=1 Uses-1=$RADIO_USED Freq=-1 DUT=regression_dut DUT_RADIO=$RADIO_USED Traffic=http" \ + --line "Resource=$RESOURCE Profile=upstream Amount=1 Uses-1=$UPSTREAM Uses-2=AUTO Freq=-1 DUT=regression_dut DUT_RADIO=$RADIO_USED Traffic=http" + ./create_chamberview_dut.py --lfmgr $MGR --dut_name regression_dut \ + --ssid "ssid_idx=0 ssid='$SSID_USED' security='$SECURITY' password='$PASSWD_USED' bssid=04:f0:21:2c:41:84" + } + +function create_station_and_sensitivity { + ./create_station.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug --mgr $MGR + ./lf_rx_sensitivity_test.py --mgr $MGR --port 8080 --lf_user lanforge --lf_password lanforge \ + --instance_name rx-sensitivity-instance --config_name test_con --upstream $UPSTREAM \ + --dut linksys-8450 --duration 15s --station $RESOURCE.sta0001 \ + --download_speed 85% --upload_speed 0 \ + --raw_line 'txo_preamble\: VHT' \ + --raw_line 'txo_mcs\: 4 OFDM, HT, VHT;5 OFDM, HT, VHT;6 OFDM, HT, VHT;7 OFDM, HT, VHT' \ + --raw_line 'spatial_streams\: 3' \ + --raw_line 'bandw_options\: 80' \ + --raw_line 'txo_sgi\: ON' \ + --raw_line 'txo_retries\: No Retry' \ + --raw_line 'txo_txpower\: 17' \ + --test_rig Testbed-01 --pull_report \ + #--influx_host 192.168.100.153 --influx_port 8086 --influx_org Candela \ + #--influx_token=-u_Wd-L8o992701QF0c5UmqEp7w7Z7YOMaWLxOMgmHfATJGnQbbmYyNxHBR9PgD6taM_tcxqJl6U8DjU1xINFQ== \ + #--influx_bucket ben \ + #--influx_tag testbed Ferndale-01 +} +if [[ ${#SHORT} -gt 0 ]]; then testCommands=( - #"./create_bond.py --network_dev_list eth0,eth1 --debug --mgr $MGR" - #"./create_bridge.py --radio $RADIO_USED --upstream_port eth1 --target_device sta0000 --debug --mgr $MGR" - "./create_chamberview.py -m $MGR -cs \"regression_test\" --line \"Resource=1.1 Profile=STA-AC Amount=1 Uses-1 $RADIO_USED Freq=-1 DUT=TEST DUT_RADIO=$RADIO_USED Traffic=http\" --line \"Resource=1.1 Profile=upstream Amount=1 Uses-1=eth1 Uses-2=AUTO Freq=-1 DUT=Test DUT_RADIO=$RADIO_USED Traffic=http\"" - "./create_chamberview_dut.py --lfmgr $MGR --dut_name regression_dut --ssid \"ssid_idx=0 ssid=$SSID_USED security=$SECURITY password=$PASSWD_USED bssid=04:f0:21:2c:41:84\"" - #"./create_l3.py --radio $RADIO_USED --ssid $SSID_USED --password $PASSWD_USED --security $SECURITY --debug --mgr $MGR" - #"./create_l4.py --radio $RADIO_USED --ssid $SSID_USED --password $PASSWD_USED --security $SECURITY --debug --mgr $MGR" - #"./create_macvlan.py --radio 1.$RADIO_USED --macvlan_parent eth1 --debug --mgr $MGR" - #"./create_qvlan.py --first_qvlan_ip 192.168.1.50 --mgr $MGR" - #"./create_station.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug --mgr $MGR" + "./lf_ap_auto_test.py \ + --mgr $MGR --port 8080 --lf_user lanforge --lf_password lanforge \ + --instance_name ap-auto-instance --config_name test_con --upstream $UPSTREAM \ + --dut5_0 '$DUT5' \ + --dut2_0 '$DUT2' \ + --radio2 $RADIO_USED \ + --radio2 $RADIO2 \ + --radio2 $RADIO2 \ + --set 'Basic Client Connectivity' 1 \ + --set 'Multi Band Performance' 1 \ + --set 'Skip 2.4Ghz Tests' 1 \ + --set 'Skip 5Ghz Tests' 1 \ + --set 'Throughput vs Pkt Size' 0 \ + --set 'Capacity' 0 \ + --set 'Stability' 0 \ + --set 'Band-Steering' 0 \ + --set 'Multi-Station Throughput vs Pkt Size' 0 \ + --set 'Long-Term' 0 \ + --pull_report \ + --local_lf_report_dir /home/matthew/html-reports/" + + + ) +else + testCommands=( + "./create_bond.py --network_dev_list $RESOURCE.eth0,$UPSTREAM --debug --mgr $MGR" + create_bridge_and_station + create_dut_and_chamberview + "./create_l3.py --radio $RADIO_USED --ssid $SSID_USED --password $PASSWD_USED --security $SECURITY --debug --mgr $MGR --endp_a wiphy0 --endp_b wiphy1" + "./create_l3_stations.py --mgr $MGR --radio $RADIO_USED --ssid $SSID_USED --password $PASSWD_USED --security $SECURITY --debug" + "./create_l4.py --radio $RADIO_USED --ssid $SSID_USED --password $PASSWD_USED --security $SECURITY --debug --mgr $MGR" + "./create_macvlan.py --radio 1.$RADIO_USED --macvlan_parent $UPSTREAM --debug --mgr $MGR" + "./create_qvlan.py --first_qvlan_ip 192.168.1.50 --mgr $MGR --qvlan_parent $UPSTREAM" + "./create_station.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug --mgr $MGR" "./create_vap.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug --mgr $MGR" - "./create_vr.py --vr_name 2.vr0 --ports 2.br0,2.vap2 --services 1.br0=dhcp,nat --services 1.vr0=radvd" - #./create_wanlink + #"./create_vr.py --mgr $MGR --vr_name 2.vr0 --ports 2.br0,2.vap2 --services 1.br0=dhcp,nat --services 1.vr0=radvd --debug" #./csv_convert #./csv_processor #./csv_to_grafana #./csv_to_influx - "./cv_manager.py --mgr $MGR --scenario FACTORY_DFLT" + #"./cv_manager.py --mgr $MGR --scenario FACTORY_DFLT" #"./cv_to_grafana --mgr $MGR " #"./docstrings.py --mgr $MGR" - #"./event_breaker --mgr $MGR" - #"./event_flood --mgr $MGR" - "./example_security_connection.py --num_stations $NUM_STA --ssid $SSID_USED --passwd $PASSWD_USED --radio $RADIO_USED --security wpa2 --debug --mgr $MGR" + #"./scripts_deprecated/event_break_flood.py --mgr $MGR" + "./example_security_connection.py --num_stations $NUM_STA --ssid $SSID_USED \ + --passwd $PASSWD_USED --radio $RADIO_USED --security wpa2 --debug --mgr $MGR" #./ftp_html.py - #./ghost_profile #./grafana_profile - #./html_template - #./influx - #./layer3_test.py --mgr $MGR --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY - #./layer4_test --mgr $MGR --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY - "./lf_ap_auto_test.py --mgr $MGR --port 8080 --lf_user lanforge --lf_password lanforge \ - --instance_name ap-auto-instance --config_name test_con --upstream 1.1.eth2 \ - --dut5_0 \"linksys-8450 Default-SSID-5gl c4:41:1e:f5:3f:25 (2)\" \ - --dut2_0 \"linksys-8450 Default-SSID-2g c4:41:1e:f5:3f:24 (1)\" \ - --max_stations_2 100 --max_stations_5 100 --max_stations_dual 200 \ - --radio2 1.1.wiphy0 --radio2 1.1.wiphy1 \ - --set \"Basic Client Connectivity\" 1 --set \"Multi Band Performance\" 1 \ - --set \"Skip 2.4Ghz Tests\" 1 --set \"Skip 5Ghz Tests\" 1 \ - --set \"Throughput vs Pkt Size\" 0 --set 'Capacity' 0 --set 'Stability' 0 --set 'Band-Steering' 0 \ - --set \"Multi-Station Throughput vs Pkt Size\" 0 --set \"Long-Term\" 0 \ - --pull_report \ - --influx_host c7-graphana --influx_port 8086 --influx_org Candela \ - --influx_token=-u_Wd-L8o992701QF0c5UmqEp7w7Z7YOMaWLxOMgmHfATJGnQbbmYyNxHBR9PgD6taM_tcxqJl6U8DjU1xINFQ== \ - --influx_bucket ben \ - --influx_tag testbed Ferndale-01" - #./lf_atten_mod_test + "./lf_ap_auto_test.py \ + --mgr $MGR --port 8080 --lf_user lanforge --lf_password lanforge \ + --instance_name ap-auto-instance --config_name test_con --upstream $UPSTREAM \ + --dut5_0 '$DUT5' \ + --dut2_0 '$DUT2' \ + --max_stations_2 64 \ + --max_stations_5 64 \ + --max_stations_dual 64 \ + --radio2 $RADIO_USED \ + --radio2 $RADIO2 \ + --set 'Basic Client Connectivity' 1 \ + --set 'Multi Band Performance' 1 \ + --set 'Skip 2.4Ghz Tests' 1 \ + --set 'Skip 5Ghz Tests' 1 \ + --set 'Throughput vs Pkt Size' 0 \ + --set 'Capacity' 0 \ + --set 'Stability' 0 \ + --set 'Band-Steering' 0 \ + --set 'Multi-Station Throughput vs Pkt Size' 0 \ + --set 'Long-Term' 0 \ + --pull_report" + #"./lf_atten_mod_test.py --host $MGR --debug" #./lf_csv #./lf_dataplane_config - "./lf_dataplane_test.py --mgr $MGR --lf_user lanforge --lf_password lanforge \ - --instance_name dataplane-instance --config_name test_con --upstream 1.1.$UPSTREAM \ - --dut linksys-8450 --duration 15s --station 1.1.sta01500 \ - --download_speed 85% --upload_speed 0 \ - --raw_line \"pkts: Custom;60;142;256;512;1024;MTU\" \ - --raw_line \"cust_pkt_sz: 88 1200\" \ - --raw_line \"directions: DUT Transmit;DUT Receive\" \ - --raw_line \"traffic_types: UDP;TCP\" \ - --test_rig Testbed-01 --pull_report \ - --influx_host c7-graphana --influx_port 8086 --influx_org Candela \ - --influx_token=-u_Wd-L8o992701QF0c5UmqEp7w7Z7YOMaWLxOMgmHfATJGnQbbmYyNxHBR9PgD6taM_tcxqJl6U8DjU1xINFQ== \ - --influx_bucket ben \ - --influx_tag testbed Ferndale-01" - #./lf_dfs_test - #./lf_dut_sta_vap_test - #"./lf_ftp.py --mgr $MGR --mgr_port 8080 --upstream_port $UPSTREAM --ssid $SSID --security $SECURITY --passwd $PASSWD_USED \ - # --ap_name WAC505 --ap_ip 192.168.213.90 --bands Both --directions Download --twog_radio wiphy1 --fiveg_radio wiphy0 --file_size 2MB --num_stations 40 --Both_duration 1 --traffic_duration 2 --ssh_port 22_" - "./lf_ftp_test.py --mgr $MGR --ssid $SSID --passwd $PASSWD_USED --security $SECURITY --bands 5G --direction Download \ - --file_size 2MB --num_stations 2" + create_station_and_dataplane + #"./lf_dut_sta_vap_test.py --manager $MGR --radio $RADIO_USED \ + # --num_sta 1 --sta_id 1 --ssid $SSID_USED --security $SECURITY --upstream $UPSTREAM \ + # --protocol lf_udp --min_mbps 1000 --max_mbps 10000 --duration 1" "./lf_graph.py --mgr $MGR" - #"./lf_mesh_test.py --mgr $MGR --upstream $UPSTREAM --raw_line 'selected_dut2 RootAP wactest $BSSID'" - #./lf_multipsk - #./lf_report - #./lf_report_test - #./lf_rvr_test - #./lf_rx_sensitivity_test.py - #./lf_sniff_radio - #./lf_snp_test - "./lf_tr398_test.py --mgr $MGR" + "./lf_mesh_test.py --mgr $MGR --upstream $UPSTREAM --raw_line 'selected_dut2 RootAP wactest $BSSID'" + "./lf_multipsk.py --mgr $MGR --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --radio $RADIO_USED --debug" + "./lf_report.py" + "./lf_report_test.py" + # "./lf_rvr_test.py" + create_station_and_sensitivity + "./lf_sniff_radio.py \ + --mgr $MGR \ + --mgr_port 8080 \ + --outfile /home/lanforge/test_sniff.pcap \ + --duration 20 \ + --channel 52 \ + --radio_mode AUTO" + "./lf_snp_test.py --help" + "./lf_tr398_test.py --mgr $MGR --upstream $UPSTREAM" #./lf_webpage "./lf_wifi_capacity_test.py --mgr $MGR --port 8080 --lf_user lanforge --lf_password lanforge \ - --instance_name this_inst --config_name test_con --upstream 1.1.eth2 --batch_size 1,5,25,50,100 --loop_iter 1 \ - --protocol UDP-IPv4 --duration 6000 --pull_report \ - --test_rig Testbed-01" - #--influx_host c7-graphana --influx_port 8086 --influx_org Candela \ - #--influx_token=-u_Wd-L8o992701QF0c5UmqEp7w7Z7YOMaWLxOMgmHfATJGnQbbmYyNxHBR9PgD6taM_tcxqJl6U8DjU1xINFQ== \ - #--influx_bucket ben \ - #measure_station_time_up.py - #modify_station.py - #modify_vap.py + --instance_name this_inst --config_name test_con --upstream $UPSTREAM --batch_size 1,5,25,50,100 --loop_iter 1 \ + --protocol UDP-IPv4 --duration 6000 --pull_report --ssid $SSID_USED --paswd $PASSWD_USED --security $SECURITY\ + --test_rig Testbed-01 --create_stations --stations $RESOURCE.sta0000,$RESOURCE.sta0001" + "./measure_station_time_up.py --radio $RADIO_USED --num_stations 3 --security $SECURITY --ssid $SSID_USED --passwd $PASSWD_USED \ + --debug --report_file measure_station_time_up.pkl --radio2 wiphy1" + "./create_station.py --mgr $MGR --radio $RADIO_USED --security $SECURITY --ssid $SSID_USED --passwd $PASSWD_USED && ./modify_station.py \ + --mgr $MGR \ + --radio $RADIO_USED \ + --station $RESOURCE.sta0000 \ + --security $SECURITY \ + --ssid $SSID_USED \ + --passwd $PASSWD_USED \ + --enable_flag osen_enable \ + --disable_flag ht160_enable \ + --debug" #recordinflux.py - #run_cv_scenario.py - #rvr_scenario.py + "./rvr_scenario.py --lfmgr $MGR --lanforge_db 'handsets' --cv_test Dataplane --test_profile http --cv_scenario ct-us-001" #scenario.py - #sta_connect2.py - #sta_connect_bssid_mac.py - #sta_connect_example.py - #sta_connect_multi_example.py - #sta_connect.py - #sta_scan_test.py + #./sta_connect_bssid_mac.py + "./sta_connect_example.py --mgr $MGR --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --radio $RADIO_USED --upstream_port $UPSTREAM --test_duration 15s" + "./sta_connect.py --mgr $MGR --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --radio $RADIO_USED --upstream_port $UPSTREAM --test_duration 15s" + "./sta_scan_test.py --ssid $SSID_USED --security $SECURITY --passwd $PASSWD_USED --radio $RADIO_USED" #station_layer3.py #stations_connected.py - #test_1k_clients_jedtest.py + #"./test_1k_clients_jedtest.py + # --mgr $MGR + # --mgr_port 8080 + # --sta_per_radio 300 + # --test_duration 3m + # --a_min 1000 + # --b_min 1000 + # --a_max 0 + # --b_max 0 + # --debug" #test_client_admission.py - "./test_fileio.py --macvlan_parent eth2 --num_ports 3 --use_macvlans --first_mvlan_ip 192.168.92.13 --netmask 255.255.255.0 --gateway 192.168.92.1 --test_duration 30s --mgr $MGR" # Better tested on Kelly, where VRF is turned off + "./test_fileio.py --macvlan_parent $UPSTREAM --num_ports 3 --use_macvlans --first_mvlan_ip 192.168.92.13 --netmask 255.255.255.0 --gateway 192.168.92.1 --test_duration 30s --mgr $MGR" # Better tested on Kelly, where VRF is turned off "./test_generic.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --num_stations $NUM_STA --type lfping --dest $TEST_HTTP_IP --debug --mgr $MGR" "./test_generic.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --num_stations $NUM_STA --type speedtest --speedtest_min_up 20 --speedtest_min_dl 20 --speedtest_max_ping 150 --security $SECURITY --debug --mgr $MGR" "./test_generic.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --num_stations $NUM_STA --type iperf3 --debug --mgr $MGR" "./test_generic.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --num_stations $NUM_STA --type lfcurl --dest $TEST_HTTP_IP --file_output ${HOMEPATH}/Documents/lfcurl_output.txt --debug --mgr $MGR" "./testgroup.py --group_name group1 --add_group --list_groups --debug --mgr $MGR" - #testgroup_list_groups - #testgroup_list_connections - #testgroup_delete_group - #"./testgroup2.py --num_stations 4 --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --radio $RADIO_USED --group_name group0 --add_group --mgr $MGR" + "./testgroup2.py --num_stations 4 --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --radio $RADIO_USED --group_name group0 --add_group --mgr $MGR" "./test_ip_connection.py --radio $RADIO_USED --num_stations $NUM_STA --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug --mgr $MGR" - #"./test_ip_variable_time.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --test_duration 15s --output_format excel --layer3_cols $COL_NAMES --debug --mgr $MGR --traffic_type lf_udp" - #"./test_ip_variable_time.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --test_duration 15s --output_format csv --layer3_cols $COL_NAMES --debug --mgr $MGR --traffic_type lf_udp" + "./test_ip_variable_time.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --test_duration 15s --output_format excel --layer3_cols $COL_NAMES --debug --mgr $MGR --traffic_type lf_udp" + "./test_ip_variable_time.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --test_duration 15s --output_format csv --layer3_cols $COL_NAMES --debug --mgr $MGR --traffic_type lf_udp" "./test_ip_connection.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug --mgr $MGR --ipv6" - #"./test_ip_variable_time.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --test_duration 15s --debug --mgr $MGR --ipv6 --traffic_type lf_udp" - #./test_ipv4_ps - #./test_ipv4_ttls - "./test_l3_longevity.py --mgr $MGR --endp_type 'lf_udp lf_tcp' --upstream_port 1.1.$UPSTREAM \ - --radio \"radio==1.1.wiphy0 stations==10 ssid==ASUS_70 ssid_pw==[BLANK] security==open\" \ - --radio \"radio==1.1.wiphy1 stations==1 ssid==ASUS_70 ssid_pw==[BLANK] security==open\" \ - --test_duration 5s --influx_host c7-graphana --influx_port 8086 --influx_org Candela \ - --influx_token=-u_Wd-L8o992701QF0c5UmqEp7w7Z7YOMaWLxOMgmHfATJGnQbbmYyNxHBR9PgD6taM_tcxqJl6U8DjU1xINFQ== \ - --influx_bucket ben --rates_are_totals --side_a_min_bps=20000 --side_b_min_bps=300000000 \ - --influx_tag testbed regression_test --influx_tag DUT ROG -o longevity.csv" + "./test_ip_variable_time.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --test_duration 15s --debug --mgr $MGR --ipv6 --traffic_type lf_udp" + "./test_ipv4_ps.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug --mgr $MGR --radio2 $RADIO2" + "./test_ipv4_ttls.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug --mgr $MGR" + "./test_l3_longevity.py --mgr $MGR --endp_type 'lf_tcp' --upstream_port $UPSTREAM --radio \ + 'radio==$RADIO_USED stations==10 ssid==$SSID_USED ssid_pw==$PASSWD_USED security==$SECURITY' --radio \ + 'radio==$RADIO2 stations==1 ssid==$SSID_USED ssid_pw==$PASSWD_USED security==$SECURITY' --test_duration 5s --rates_are_totals --side_a_min_bps=20000 --side_b_min_bps=300000000 -o longevity.csv" "./test_l3_powersave_traffic.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug --mgr $MGR" - "./test_l3_scenario_throughput.py -t 15s -sc test_l3_scenario_throughput -m $MGR" + #"./test_l3_scenario_throughput.py -t 15s -sc test_l3_scenario_throughput -m $MGR" #./test_l3_unicast_traffic_gen #./test_l3_unicast_traffic_gen #./test_l3_WAN_LAN - #./test_l4 + "./test_l4.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug --mgr $MGR --test_duration 15s" "./test_status_msg.py --debug --mgr $MGR" #this is all which is needed to run #"./test_wanlink.py --name my_wanlink4 --latency_A 20 --latency_B 69 --rate 1000 --jitter_A 53 --jitter_B 73 --jitter_freq 6 --drop_A 12 --drop_B 11 --debug --mgr $MGR" #./test_wpa_passphrases #./tip_station_powersave - #./vap_stations_example #./video_rates - "./wlan_capacity_calculator.py -sta 11abg -t Voice -p 48 -m 106 -e WEP -q Yes -b 1 2 5.5 11 -pre Long -s N/A -co G.711 -r Yes -c Yes -m $MGR" - "./wlan_capacity_calculator.py -sta 11n -t Voice -d 17 -ch 40 -gu 800 -high 9 -e WEP -q Yes -ip 5 -mc 42 -b 6 9 12 24 -m 1538 -co G.729 -pl Greenfield -cw 15 -r Yes -c Yes -m $MGR" - "./wlan_capacity_calculator.py -sta 11ac -t Voice -d 9 -spa 3 -ch 20 -gu 800 -high 1 -e TKIP -q Yes -ip 3 -mc 0 -b 6 12 24 54 -m 1518 -co Greenfield -cw 15 -rc Yes -m $MGR" - #"./ws_generic_monitor_test.py --mgr $MGR" - ) -elif [[ $MGR == "short" ]]; then - testCommands=( - run_l3_longevity - "./test_ipv4_variable_time.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --test_duration 15s --output_format excel --layer3_cols $COL_NAMES --debug --mgr $MGR" - ) -else - testCommands=( - #"../cpu_stats.py --duration 15" - "./example_security_connection.py --num_stations $NUM_STA --ssid jedway-wpa-1 --passwd jedway-wpa-1 --radio $RADIO_USED --security wpa --debug" - "./example_security_connection.py --num_stations $NUM_STA --ssid $SSID_USED --passwd $PASSWD_USED --radio $RADIO_USED --security wpa2 --debug" - "./example_security_connection.py --num_stations $NUM_STA --ssid jedway-wep-48 --passwd 0123456789 --radio $RADIO_USED --security wep --debug" - "./example_security_connection.py --num_stations $NUM_STA --ssid jedway-wpa3-1 --passwd jedway-wpa3-1 --radio $RADIO_USED --security wpa3 --debug" - "./sta_connect2.py --dut_ssid $SSID_USED --dut_passwd $PASSWD_USED --dut_security $SECURITY" - "./sta_connect_example.py" - # want if [[ $DO_FILEIO = 1 ]] - "./test_fileio.py --macvlan_parent eth2 --num_ports 3 --use_macvlans --first_mvlan_ip 192.168.92.13 --netmask 255.255.255.0 --test_duration 30s --gateway 192.168.92.1" # Better tested on Kelly, where VRF is turned off - "./test_generic.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --num_stations $NUM_STA --type lfping --dest $TEST_HTTP_IP --debug" - "./test_generic.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --num_stations $NUM_STA --type speedtest --speedtest_min_up 20 --speedtest_min_dl 20 --speedtest_max_ping 150 --security $SECURITY --debug" - "./test_generic.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --num_stations $NUM_STA --type iperf3 --debug" - "./test_generic.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --num_stations $NUM_STA --type lfcurl --dest $TEST_HTTP_IP --file_output ${HOMEPATH}/Documents/lfcurl_output.txt --debug" - "./testgroup.py --group_name group1 --add_group --list_groups --debug" - testgroup_list_groups - testgroup_list_connections - testgroup_delete_group - "./testgroup2.py --num_stations 4 --ssid lanforge --passwd password --security wpa2 --radio wiphy0 --group_name group0 --add_group" - "./test_ipv4_connection.py --radio $RADIO_USED --num_stations $NUM_STA --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug" - "./test_ipv4_l4_urls_per_ten.py --radio $RADIO_USED --num_stations $NUM_STA --security $SECURITY --ssid $SSID_USED --passwd $PASSWD_USED --num_tests 1 --requests_per_ten 600 --target_per_ten 600 --debug" - "./test_ipv4_l4_wifi.py --radio $RADIO_USED --num_stations $NUM_STA --security $SECURITY --ssid $SSID_USED --passwd $PASSWD_USED --test_duration 15s --debug" - "./test_ipv4_l4.py --radio $RADIO_USED --num_stations 4 --security $SECURITY --ssid $SSID_USED --passwd $PASSWD_USED --test_duration 15s --debug" - "./test_ipv4_variable_time.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --test_duration 15s --output_format excel --layer3_cols $COL_NAMES --traffic_type lf_udp --debug" - "./test_ipv4_variable_time.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --test_duration 15s --output_format csv --layer3_cols $COL_NAMES --traffic_type lf_udp --debug" - "./test_ipv4_l4_ftp_upload.py --upstream_port eth1 --radio $RADIO_USED --num_stations $NUM_STA --security $SECURITY --ssid $SSID_USED --passwd $PASSWD_USED --test_duration 15s --debug" - "./test_ipv6_connection.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug" - "./test_ipv6_variable_time.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --test_duration 15s --cx_type tcp6 --debug" - run_l3_longevity - "./test_l3_powersave_traffic.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug" - #"./test_l3_scenario_throughput.py -t 15s -sc test_l3_scenario_throughput" #always hangs the regression - "./test_status_msg.py --action run_test " #this is all which is needed to run - "./test_wanlink.py --debug" - #"./ws_generic_monitor_test.py" - #"../py-json/ws-sta-monitor.py --debug" - "./create_bridge.py --radio $RADIO_USED --upstream_port eth1 --target_device sta0000 --debug" - "./create_l3.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug" - "./create_l4.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug" - "./create_macvlan.py --radio $RADIO_USED --macvlan_parent eth1 --debug" - "./create_station.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug" - "./create_vap.py --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug" - "./create_vr.py --vr_name 2.vr0 --ports 2.br0,2.vap2 --services" - "./create_qvlan.py --radio $RADIO_USED --qvlan_parent eth1" "./wlan_capacity_calculator.py -sta 11abg -t Voice -p 48 -m 106 -e WEP -q Yes -b 1 2 5.5 11 -pre Long -s N/A -co G.711 -r Yes -c Yes" "./wlan_capacity_calculator.py -sta 11n -t Voice -d 17 -ch 40 -gu 800 -high 9 -e WEP -q Yes -ip 5 -mc 42 -b 6 9 12 24 -m 1538 -co G.729 -pl Greenfield -cw 15 -r Yes -c Yes" "./wlan_capacity_calculator.py -sta 11ac -t Voice -d 9 -spa 3 -ch 20 -gu 800 -high 1 -e TKIP -q Yes -ip 3 -mc 0 -b 6 12 24 54 -m 1518 -co Greenfield -cw 15 -rc Yes" + #"./ws_generic_monitor_test.py --mgr $MGR" + "python3 -c 'import lanforge_scripts'" ) fi #declare -A name_to_num @@ -362,7 +434,6 @@ name_to_num=( ["lf_csv"]=30 ["lf_dataplane_config"]=31 ["lf_dataplane_test"]=32 - ["lf_dfs_test"]=33 ["lf_dut_sta_vap_test"]=34 ["lf_ft"]=35 ["lf_ftp_test"]=36 @@ -449,37 +520,69 @@ function echo_print() { function test() { if [[ $MGRLEN -gt 0 ]]; then - ./scenario.py --load FACTORY_DFLT --mgr "${MGR}" + ./scenario.py --load BLANK --mgr "${MGR}" else - ./scenario.py --load FACTORY_DFLT + ./scenario.py --load BLANK fi echo "" echo "Test $CURR_TEST_NAME" echo_print - echo "$i" - $i > "${TEST_DIR}/${NAME}.txt" 2> "${TEST_DIR}/${NAME}_stderr.txt" - chmod 664 "${TEST_DIR}/${NAME}.txt" - FILESIZE=$(stat -c%s "${TEST_DIR}/${NAME}_stderr.txt") || 0 - if (( FILESIZE > 0)); then - results+=("
${CURR_TEST_NAME}${i}FailureSTDOUTSTDERR
${CURR_TEST_NAME}${i}SuccessSTDOUT
${CURR_TEST_NAME}${testcommand}$TDTEXT${execution}STDOUT${STDERR}${LANforgeError}
- - - - - - - " - tail=" - " + LAST_COMMIT=$(git log --pretty=oneline | head -n 1) + header=" + + +${HOSTNAME} Regression Test Results $NOW + + + + + +

Regression Results

+

$NOW

+

$LAST_COMMIT

+

Test results

+
Command NameCommandStatusSTDOUTSTDERR
+ + + + + + + + + + + + " + tail="" fname="${HOMEPATH}/html-reports/regression_file-${NOW}.html" echo "$header" >> "$fname" echo "${results[@]}" >> "$fname" - echo "
Command NameCommandStatusExecution timeSTDOUTSTDERRLANforge Error
" >> "$fname" + echo " + +
+

System information

+ + + + + + + + + + + + + + + + + + + + + + + +
Python versionLANforge versionLANforge build dateOS VersionHostnameIP AddressPython Environment
${PYTHON_VERSION}${BuildVersion}${BuildDate}${OS_Version}${HOSTNAME}${IP_ADDRESS}${PYTHON_ENVIRONMENT}
" >> "$fname" echo "$tail" >> "$fname" if [ -f "${HOMEPATH}/html-reports/latest.html" ]; then rm -f "${HOMEPATH}/html-reports/latest.html" fi ln -s "${fname}" "${HOMEPATH}/html-reports/latest.html" - HOSTNAME=$(ip -4 addr show enp3s0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}') - content="View the latest regression report at ${HOSTNAME}/html-reports/latest.html" - echo "${content}" + echo "Saving HTML file to disk" + #HOSTNAME=$(ip -4 addr show enp3s0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}') + #content="View the latest regression report at /html-reports/latest.html" + #echo "${content}" #mail -s "Regression Results" scripters@candelatech.com <<<$content } @@ -560,9 +711,9 @@ results=() NOW=$(date +"%Y-%m-%d-%H-%M") NOW="${NOW/:/-}" TEST_DIR="${REPORT_DATA}/${NOW}" -URL2="${HOMEPATH}/report-data/${NOW}" +URL2="/report-data/${NOW}" mkdir "${TEST_DIR}" echo "Recording data to $TEST_DIR" -run_test +start_tests html_generator diff --git a/py-scripts/run_cv_scenario.py b/py-scripts/run_cv_scenario.py index 5e931b6a..51d3ffbc 100755 --- a/py-scripts/run_cv_scenario.py +++ b/py-scripts/run_cv_scenario.py @@ -1,18 +1,18 @@ #!/usr/bin/env python3 # This script will set the LANforge to a BLANK database then it will load the specified database # and start a graphical report -import sys -import os -import importlib import argparse -from time import sleep +import importlib +import os import pprint +import sys +import time +from time import sleep if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) LFUtils = importlib.import_module("py-json.LANforge.LFUtils") @@ -29,15 +29,19 @@ Realm = realm.Realm cvScenario.test_scenario = args.test_scenario """ + class RunCvScenario(LFCliBase): - def __init__(self, lfhost="localhost", lfport=8080, debug_=False, lanforge_db_=None, cv_scenario_=None, cv_test_=None, test_scenario_=None): - super().__init__( _lfjson_host=lfhost, _lfjson_port=lfport, _debug=debug_, _exit_on_error=True, _exit_on_fail=True) + def __init__(self, lfhost="localhost", lfport=8080, debug_=False, lanforge_db_=None, cv_scenario_=None, + cv_test_=None, test_scenario_=None): + super().__init__(_lfjson_host=lfhost, _lfjson_port=lfport, _debug=debug_, _exit_on_error=True, + _exit_on_fail=True) self.lanforge_db = lanforge_db_ self.cv_scenario = cv_scenario_ self.cv_test = cv_test_ self.test_profile = test_scenario_ self.localrealm = Realm(lfclient_host=lfhost, lfclient_port=lfport, debug_=debug_) self.report_name = None + self.load_timeout_sec = 2 * 60 def get_report_file_name(self): return self.report_name @@ -45,14 +49,16 @@ class RunCvScenario(LFCliBase): def build(self): data = { "name": "BLANK", - "action":"overwrite", - "clean_dut":"yes", + "action": "overwrite", + "clean_dut": "yes", "clean_chambers": "yes" } self.json_post("/cli-json/load", data) - sleep(1) - port_counter = 0; + self.wait_for_db_load_and_sync() + + port_counter = 0 attempts = 6 + alias_map = None while (attempts > 0) and (port_counter > 0): sleep(1) attempts -= 1 @@ -69,47 +75,131 @@ class RunCvScenario(LFCliBase): if (port_counter != 0) and (attempts == 0): print("There appears to be a vAP in this database, quitting.") - pprint(alias_map); + pprint.pprint(alias_map) exit(1) data = { "name": self.lanforge_db, - "action":"overwrite", - "clean_dut":"yes", + "action": "overwrite", + "clean_dut": "yes", "clean_chambers": "yes" } self.json_post("/cli-json/load", data) - sleep(1) + self.wait_for_db_load_and_sync() self._pass("Loaded scenario %s" % self.lanforge_db, True) return True + def wait_for_db_load_and_sync(self): + events_response = self.json_get("/events/last") + if "event" not in events_response: + raise ValueError("Unable to find last event") + if "id" not in events_response["event"]: + pprint.pprint(events_response["event"]) + raise ValueError("bad event format") + previous_event_id = events_response["event"]["id"] + + # check for scenario (db) load message + begin_time: int = round(time.time() * 1000) + load_completed = False + while not load_completed: + if time.time() > (begin_time + self.load_timeout_sec): + print("Unable to load database within %d sec" % self.load_timeout_sec) + exit(1) + events_response = self.json_get("/events/since/%s" % previous_event_id) + pronoun = None + if "events" in events_response: + pronoun = "events" + elif "event" in events_response: + pronoun = "event" + if not pronoun: + pprint.pprint(("events response", events_response)) + raise ValueError("incorrect events response") + for event_o in events_response[pronoun]: + if load_completed: + break + for (key, record) in event_o.items(): + if "event description" not in record: + continue + if not record["event description"]: + continue + if record["event description"].startswith("LOAD COMPLETED at "): + print("load completed: %s " % record["event description"]) + load_completed = True + break + if not load_completed: + sleep(1) + + blobs_last_updated = begin_time + status_response = self.json_get("/") + if "text_records_last_updated_ms" in status_response: + blobs_last_updated = int(status_response["text_records_last_updated_ms"]) + # print("*** blobs updated at %d" % blobs_last_updated) + else: + begin_time = round(time.time() * 1000) + print("no text_records_last_updated_ms, using %d " % begin_time) + # next we will want to sync our text blobs up + self.json_post("/cli-json/show_text_blob", { + "type": "ALL", + "name": "ALL" + }) + + load_completed = False + while not load_completed: + sleep(1) + if time.time() > (begin_time + (6 * 1000)): + print("waited %d sec for text blobs to update" % self.load_timeout_sec) + break + status_response = self.json_get("/") + if "text_records_last_updated_ms" in status_response: + updated = int(status_response["text_records_last_updated_ms"]) + print(", , , , , , , , , updated at %d" % updated) + if updated > blobs_last_updated: + break + else: + pprint.pprint(status_response) + self.json_post("/cli-json/show_text_blob", { + "type": "ALL", + "name": "ALL" + }) + delta: float = (time.time() * 1000) - begin_time + print("blobs loaded in %d ms" % delta) + + # next show duts + self.json_post("/cli-json/show_dut", {"name": "ALL"}) + self.json_post("/cli-json/show_profile", {"name": "ALL"}) + self.json_post("/cli-json/show_traffic_profile", {"name": "ALL"}) + sleep(5) + def start(self, debug_=False): # /gui_cli takes commands keyed on 'cmd', so we create an array of commands commands = [ + "cv sync", + "sleep 4", "cv apply '%s'" % self.cv_scenario, + "sleep 4", "cv build", "sleep 4", "cv is_built", "cv sync", - "sleep 2", + "sleep 4", + "cv list_instances", "cv create '%s' 'test_ref' 'true'" % self.cv_test, - "sleep 2", - "cv load test_ref '%s'" % self.test_profile, - "sleep 1", - "cv click test_ref 'Auto Save Report'", "sleep 5", + "cv load test_ref '%s'" % self.test_profile, + "sleep 5", + "cv click test_ref 'Auto Save Report'", + "sleep 1", "cv click test_ref Start", "sleep 60", "cv get test_ref 'Report Location:'", "sleep 5", - #"cv click test_ref 'Save HTML'", + # "cv click test_ref 'Save HTML'", "cv click test_ref 'Close'", "sleep 1", "cv click test_ref Cancel", "sleep 1", "exit" ] - response_json = [] for command in commands: data = { "cmd": command @@ -117,7 +207,7 @@ class RunCvScenario(LFCliBase): try: debug_par = "" if debug_: - debug_par="?_debug=1" + debug_par = "?_debug=1" if command.endswith("is_built"): print("Waiting for scenario to build...", end='') self.localrealm.wait_while_building(debug_=False) @@ -127,21 +217,28 @@ class RunCvScenario(LFCliBase): print("sleeping %d..." % nap) sleep(nap) print("...proceeding") + elif command == "cv list_instances": + response_json = [] + print("running %s..." % command, end='') + response = self.json_post("/gui-json/cmd%s" % debug_par, + data, + debug_=debug_, + response_json_list_=response_json) + if debug_: + LFUtils.debug_printer.pprint(response) else: response_json = [] print("running %s..." % command, end='') - response = self.json_post("/gui-json/cmd%s" % debug_par, data, debug_=False, response_json_list_=response_json) + self.json_post("/gui-json/cmd%s" % debug_par, data, debug_=False, + response_json_list_=response_json) if debug_: LFUtils.debug_printer.pprint(response_json) print("...proceeding") - - except Exception as x: print(x) self._pass("report finished", print_=True) - def stop(self): pass @@ -156,13 +253,14 @@ def main(): prog="run_cv_scenario.py", formatter_class=argparse.RawTextHelpFormatter, description="""LANforge Reporting Script: Load a scenario and run a RvR report - Example: - ./load_ap_scenario.py --lfmgr 127.0.0.1 --scenario_db 'handsets' --cv_test --test_scenario 'test-20' - """) +Example: +./load_ap_scenario.py --lfmgr 127.0.0.1 --lanforge_db 'handsets' --cv_test 'WiFi Capacity' --test_profile 'test-20' +""") parser.add_argument("-m", "--lfmgr", type=str, help="address of the LANforge GUI machine (localhost is default)") parser.add_argument("-o", "--port", type=int, help="IP Port the LANforge GUI is listening on (8080 is default)") parser.add_argument("-d", "--lanforge_db", type=str, help="Name of test scenario database (see Status Tab)") - parser.add_argument("-c", "--cv_scenario", type=str, help="Name of Chamber View test scenario (see CV Manage Scenarios)") + parser.add_argument("-c", "--cv_scenario", type=str, + help="Name of Chamber View test scenario (see CV Manage Scenarios)") parser.add_argument("-n", "--cv_test", type=str, help="Chamber View test") parser.add_argument("-s", "--test_profile", type=str, help="Name of the saved CV test profile") parser.add_argument("--debug", help='Enable debugging', default=False, action="store_true") @@ -210,7 +308,9 @@ def main(): exit(1) report_file = run_cv_scenario.get_report_file_name() - print("Report file saved to "+report_file) + print("Report file saved to " + report_file) + + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/py-scripts/rvr_scenario.py b/py-scripts/rvr_scenario.py index 45d09daa..1c1e7951 100755 --- a/py-scripts/rvr_scenario.py +++ b/py-scripts/rvr_scenario.py @@ -12,7 +12,6 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) LFUtils = importlib.import_module("py-json.LANforge.LFUtils") @@ -29,9 +28,12 @@ Realm = realm.Realm cvScenario.test_scenario = args.test_scenario """ + class RunCvScenario(LFCliBase): - def __init__(self, lfhost="localhost", lfport=8080, debug_=False, lanforge_db_=None, cv_scenario_=None, cv_test_=None, test_scenario_=None): - super().__init__( _lfjson_host=lfhost, _lfjson_port=lfport, _debug=debug_, _exit_on_error=True, _exit_on_fail=True) + def __init__(self, lfhost="localhost", lfport=8080, debug_=False, lanforge_db_=None, cv_scenario_=None, + cv_test_=None, test_scenario_=None): + super().__init__(_lfjson_host=lfhost, _lfjson_port=lfport, _debug=debug_, _exit_on_error=True, + _exit_on_fail=True) self.lanforge_db = lanforge_db_ self.cv_scenario = cv_scenario_ self.cv_test = cv_test_ @@ -45,13 +47,13 @@ class RunCvScenario(LFCliBase): def build(self): data = { "name": "BLANK", - "action":"overwrite", - "clean_dut":"yes", + "action": "overwrite", + "clean_dut": "yes", "clean_chambers": "yes" } self.json_post("/cli-json/load", data) sleep(1) - port_counter = 0; + port_counter = 0 attempts = 6 while (attempts > 0) and (port_counter > 0): sleep(1) @@ -74,8 +76,8 @@ class RunCvScenario(LFCliBase): data = { "name": self.lanforge_db, - "action":"overwrite", - "clean_dut":"yes", + "action": "overwrite", + "clean_dut": "yes", "clean_chambers": "yes" } self.json_post("/cli-json/load", data) @@ -86,7 +88,7 @@ class RunCvScenario(LFCliBase): def start(self, debug_=False): # /gui_cli takes commands keyed on 'cmd', so we create an array of commands commands = [ - #"cv apply '%s'" % self.cv_scenario, + # "cv apply '%s'" % self.cv_scenario, "sleep 5", "cv build", "sleep 5", @@ -103,9 +105,10 @@ class RunCvScenario(LFCliBase): "cv click test_ref Start", "sleep 2", "cv click test_ref 'Another Iteration'", - "sleep 240", #sleep for (test duration for 1 time test takes x num iterations requested) - this example is 2 iterations - "cv click test_ref 'Another Iteration'", #unselect Another Iteration before test ends - "sleep 50" #finish test + "sleep 240", + # sleep for (test duration for 1 time test takes x num iterations requested) - this example is 2 iterations + "cv click test_ref 'Another Iteration'", # unselect Another Iteration before test ends + "sleep 50" # finish test "cv get test_ref 'Report Location:'", "sleep 5", "cv click test_ref 'Save HTML'", @@ -115,7 +118,6 @@ class RunCvScenario(LFCliBase): "sleep 1", "exit" ] - response_json = [] for command in commands: data = { "cmd": command @@ -123,7 +125,7 @@ class RunCvScenario(LFCliBase): try: debug_par = "" if debug_: - debug_par="?_debug=1" + debug_par = "?_debug=1" if command.endswith("is_built"): print("Waiting for scenario to build...", end='') self.localrealm.wait_while_building(debug_=False) @@ -136,18 +138,16 @@ class RunCvScenario(LFCliBase): else: response_json = [] print("running %s..." % command, end='') - response = self.json_post("/gui-json/cmd%s" % debug_par, data, debug_=False, response_json_list_=response_json) + self.json_post("/gui-json/cmd%s" % debug_par, data, debug_=False, response_json_list_=response_json) if debug_: LFUtils.debug_printer.pprint(response_json) print("...proceeding") - except Exception as x: print(x) self._pass("report finished", print_=True) - def stop(self): pass @@ -163,17 +163,17 @@ def main(): formatter_class=argparse.RawTextHelpFormatter, description="""LANforge Reporting Script: Load a scenario and run a RvR report Example: -./load_ap_scenario.py --lfmgr 127.0.0.1 --lanforge_db 'handsets' --cv_test --test_scenario 'test-20' +./rvr_scenario.py --lfmgr 127.0.0.1 --lanforge_db 'handsets' --cv_test --test_scenario 'test-20' """) - parser.add_argument("-m", "--lfmgr", type=str, + parser.add_argument("-m", "--lfmgr", type=str, help="address of the LANforge GUI machine (localhost is default)") - parser.add_argument("-o", "--port", type=int, + parser.add_argument("-o", "--port", type=int, help="IP Port the LANforge GUI is listening on (8080 is default)") parser.add_argument("--lanforge_db", "--db", "--lanforge_scenario", type=str, help="Name of test scenario database (see Status Tab)") - parser.add_argument("-c", "--cv_scenario", type=str, required=True, + parser.add_argument("-c", "--cv_scenario", type=str, required=True, help="Name of Chamber View test scenario (see CV Manage Scenarios)") - parser.add_argument("-n", "--cv_test", type=str, required = True, + parser.add_argument("-n", "--cv_test", type=str, required=True, help="Chamber View test") parser.add_argument("-s", "--test_profile", "--test_settings", type=str, required=True, help="Name of the saved CV test settings") @@ -220,7 +220,9 @@ Example: exit(1) report_file = run_cv_scenario.get_report_file_name() - print("Report file saved to "+report_file) + print("Report file saved to " + report_file) + + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/py-scripts/sandbox/attenuator_mon.py b/py-scripts/sandbox/attenuator_mon.py new file mode 100755 index 00000000..de34207c --- /dev/null +++ b/py-scripts/sandbox/attenuator_mon.py @@ -0,0 +1,198 @@ +#!/usr/bin/env python3 +""" +NAME: attenuator_mon.py + +PURPOSE: example of a monitoring loop that notices when attenator values change + +EXAMPLE: + +NOTES: + + +""" +import sys + +if sys.version_info[0] != 3: + print("This script requires Python3") + exit() + +sys.path.insert(1, "../../py-json") +import argparse +import importlib +import os +from os.path import exists +import pprint +from time import sleep + + +sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../../"))) +lfcli_base = importlib.import_module('py-json.LANforge.lfcli_base') +LFCliBase = lfcli_base.LFCliBase +LFUtils = importlib.import_module('py-json.LANforge.LFUtils') +realm = importlib.import_module('py-json.realm') +Realm = realm.Realm + +lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") +LFCliBase = lfcli_base.LFCliBase + + +class AttenuatorMonitor(Realm): + def __init__(self, + host=None, + port=None, + action=None, + action_every_channel=False, + attenuator=None, + interval_sec: float = 1.0, + stop_file=None, + _deep_clean=False, + _debug_on=False, + _exit_on_error=False, + _exit_on_fail=False): + super().__init__(host, + port, + debug_=_debug_on, + _exit_on_fail=_exit_on_fail) + self.action = action + self.action_every_channel = action_every_channel + self.attenuator = attenuator + self.interval_sec = interval_sec + self.stop_file = stop_file + + self.prev_values = { + "module 1": 0.0, + "module 2": 0.0, + "module 3": 0.0, + "module 4": 0.0, + "module 5": 0.0, + "module 6": 0.0, + "module 7": 0.0, + "module 8": 0.0, + } + # check for attenuator + + response = self.json_get("/atten/list") + if "attenuator" not in response: + if "attenuators" not in response: + print("Unable to retrieve list of attenuators. Is a LANforge GUI at %s:%s ?" + % (host, port)) + exit(1) + + found = False + if "attenuator" in response: + if response["attenuator"]["entity id"] != self.attenuator: + print("Unable to find attenuator %s" % self.attenuator) + pprint.pprint(("reponse", response)) + exit(1) + else: + found = True + elif "attenuators" in response: + atten_list = response["attenuators"] + for atten_o in atten_list: + for key_1 in atten_o.keys(): + if atten_o[key_1]["entity id"] == self.attenuator: + found = True + else: + print("No attenators on system.") + exit(1) + if not found: + print("No matching attenuators found.") + exit(1) + + self.attenuator_url = "/atten/" + self.attenuator + + def run(self): + if self.stop_file is not None: + if exists(self.stop_file): + print("Stop File [%s] already exists. Remove file before starting script." % self.stop_file) + exit(0) + else: + print("No stop file provided. Stop this script with ctrl-c or kill") + + counter = 0; + while(True): + sleep(self.interval_sec) + if exists(self.stop_file): + return + num_changes = 0 + changes = {} + attenuator_values = self.json_get(self.attenuator_url) + z_old: float + z_new: float + + for key in self.prev_values.keys(): + + if key not in attenuator_values["attenuator"]: + pprint.pprint(attenuator_values["attenuator"]) + raise ValueError("Unexpected lack of keys for attenuator record:") + if self.debug: + print("I see: %s -> %s" % (self.prev_values[key], attenuator_values["attenuator"][key])) + + if "" == attenuator_values["attenuator"][key]: + continue + + z_old = float(self.prev_values[key]) + z_new = float(attenuator_values["attenuator"][key]) + + changes[key] = 0 + if z_old != z_new: + if (counter > 0) and self.action_every_channel: + self.do_cmd(channel=key, value=z_new) + else: + changes[key] = str(z_new) + num_changes += 1 + self.prev_values[key] = z_new + + if (counter > 0) and (num_changes > 0) and (not self.action_every_channel): + self.do_cmd(channel="all", + value=",".join(changes.values())) + if exists(self.stop_file): + return + counter += 1 + + def do_cmd(self, + channel=None, + value=None): + if not channel: + raise ValueError("do_cmd not given channel") + if not value: + raise ValueError("do_cmd not given value") + if not self.action: + raise ValueError("do_cmd lost self.action") + + pprint.pprint([("channel", channel), + ("values", value)]) + os.system(self.action) + +def main(): + parser = LFCliBase.create_bare_argparse( + prog=__file__, + formatter_class=argparse.RawTextHelpFormatter, + description=""" +""") + parser.add_argument('--action', help="command to execute when attenuator changes levels") + parser.add_argument('--action_every_channel', help="When True, do an action for every channel that changes") + parser.add_argument('--attenuator', help="attenuator entity id to watch; E.G.: 1.1.323") + parser.add_argument('--interval_sec', type=float, help="wait between checking") + parser.add_argument('--stop_file', help="when this file appears, exit; E.G.: /tmp/stop-monitoring") + + args = parser.parse_args() + + if (not args.action) or ("" == args.action): + print("--action is required; how about 'echo hi' ?") + exit(1) + attenuator_mon = AttenuatorMonitor(args.mgr, + args.mgr_port, + attenuator=args.attenuator, + action=args.action, + action_every_channel=args.action_every_channel, + interval_sec=args.interval_sec, + stop_file=args.stop_file, + _debug_on=False, + _exit_on_error=False, + _exit_on_fail=False) + attenuator_mon.run() + + +if __name__ == "__main__": + main() diff --git a/py-scripts/connection_test.py b/py-scripts/sandbox/connection_test.py similarity index 100% rename from py-scripts/connection_test.py rename to py-scripts/sandbox/connection_test.py diff --git a/py-scripts/download_test.py b/py-scripts/sandbox/download_test.py similarity index 100% rename from py-scripts/download_test.py rename to py-scripts/sandbox/download_test.py diff --git a/py-scripts/sandbox/example-connection-removal.py b/py-scripts/sandbox/example-connection-removal.py new file mode 100755 index 00000000..1eaf7740 --- /dev/null +++ b/py-scripts/sandbox/example-connection-removal.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 + +import sys +import os +import importlib +from pprint import pprint #, pformat + + +path_hunks = os.path.abspath(__file__).split('/') +while( path_hunks[-1] != 'lanforge-scripts'): + path_hunks.pop() +sys.path.append(os.path.join("/".join(path_hunks))) +realm = importlib.import_module("py-json.realm") +Realm = realm.Realm + +class eggsample(Realm): + def __init__(self): + super().__init__("ct521a-lion", 8080); + + def run(self): + layer3_result = self.cx_list() # this is realm::cx_list() + pprint(("layer3 result records:", layer3_result)) + layer3_names = [ item["name"] for item in layer3_result.values() if "_links" in item] + pprint(("layer3 names:", layer3_names)) + #LFUtils.remove_cx(self.url, layer3_names) + + +def main(): + egg = eggsample() + egg.run() + + +if __name__ == "__main__": + main() +# + diff --git a/py-scripts/ftp_html.py b/py-scripts/sandbox/ftp_html.py similarity index 100% rename from py-scripts/ftp_html.py rename to py-scripts/sandbox/ftp_html.py diff --git a/py-scripts/html_template.py b/py-scripts/sandbox/html_template.py similarity index 100% rename from py-scripts/html_template.py rename to py-scripts/sandbox/html_template.py diff --git a/py-scripts/sandbox/jbr_create_wanlink.py b/py-scripts/sandbox/jbr_create_wanlink.py new file mode 100755 index 00000000..0cea923d --- /dev/null +++ b/py-scripts/sandbox/jbr_create_wanlink.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 +""" +NAME: jbr_create_wanlink.py + +PURPOSE: create a wanlink + +EXAMPLE: +$ ./jbr_create_wanlink.py --host ct521a-jana --wl_name snail + +To enable using lf_json_autogen in other parts of the codebase, set LF_USE_AUTOGEN=1: +$ LF_USE_AUTOGEN=1 ./jbr_jag_test.py --test set_port --host ct521a-lion + +NOTES: + + +TO DO NOTES: + +""" +import sys + +if sys.version_info[0] != 3: + print("This script requires Python3") + exit() + +import importlib +import argparse +import pprint +sys.path.insert(1, "../../") +lanforge_api = importlib.import_module("lanforge_client.lanforge_api") +from lanforge_client.lanforge_api import LFSession +from lanforge_client.lanforge_api import LFJsonCommand +from lanforge_client.lanforge_api import LFJsonQuery + + +# import LANforge.lfcli_base +# from LANforge.lfcli_base import LFCliBase + +# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- # + +# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- # +def main(): + parser = argparse.ArgumentParser( + prog=__file__, + formatter_class=argparse.RawTextHelpFormatter, + description='tests creating wanlink') + parser.add_argument("--host", "--mgr", help='specify the GUI to connect to, assumes port 8080') + parser.add_argument("--wl_name", help='name of the wanlink to create') + parser.add_argument("--resource", help='LANforge resource') + parser.add_argument("--debug", help='turn on debugging', action="store_true") + + args = parser.parse_args() + if not args.wl_name: + print("No wanlink name provided") + exit(1) + + session = LFSession(lfclient_url="http://%s:8080" % args.host, + debug=args.debug, + connection_timeout_sec=2.0, + stream_errors=True, + stream_warnings=True, + require_session=True, + exit_on_error=True) + command: LFJsonCommand + command = session.get_command() + query: LFJsonQuery + query = session.get_query() + + command.post_add_rdd(resource=args.resource, + port="rd0a", + peer_ifname="rd0b", + report_timer=1000, + shelf=1, + debug=args.debug) + + command.post_add_rdd(resource=args.resource, + port="rd1a", + peer_ifname="rd1b", + report_timer=1000, + shelf=1, + debug=args.debug) + + endp_a = args.wl_name + "-A" + endp_b = args.wl_name + "-B" + # Comment out some parameters like 'max_jitter', 'drop_freq' and 'wanlink' + # in order to view the X-Errors headers + command.post_add_wl_endp(alias=endp_a, + shelf=1, + resource=args.resource, + wanlink=args.wl_name, + speed=56000, + port="rd0a", + drop_freq="0", + max_jitter="10", + latency="10ms", + min_reorder_amt="1", + max_reorder_amt="10", + min_drop_amt="1", + debug=args.debug) + command.post_add_wl_endp(alias=endp_b, + shelf=1, + resource=args.resource, + port="rd1a", + wanlink=args.wl_name, + speed=56000, + drop_freq="0", + max_jitter="10", + latency="10ms", + min_reorder_amt="1", + max_reorder_amt="10", + min_drop_amt="1", + debug=args.debug) + command.post_add_cx(alias=args.wl_name, + rx_endp=endp_a, + tx_endp=endp_b, + test_mgr="default_tm", + debug=args.debug) + ewarn_list = [] + result = query.get_wl(eid_list=[args.wl_name], + wait_sec=0.2, + timeout_sec=2.0, + errors_warnings=ewarn_list, + debug=args.debug) + pprint.pprint(result) + result = query.get_wl_endp(eid_list=[args.wl_name+"-A", args.wl_name+"-B"], + wait_sec=0.2, + timeout_sec=15.0, + debug=args.debug) + pprint.pprint(result) + + +if __name__ == "__main__": + main() +# diff --git a/py-scripts/sandbox/jbr_monitor_bssids.py b/py-scripts/sandbox/jbr_monitor_bssids.py new file mode 100755 index 00000000..e0e20e70 --- /dev/null +++ b/py-scripts/sandbox/jbr_monitor_bssids.py @@ -0,0 +1,353 @@ +#!/usr/bin/env python3 +""" +NAME: jbr_monitor_bssids.py + +PURPOSE: Creates a series of stations and L3 connections +Uses lanforge_api. + +EXAMPLE: +$ ./jbr_monitor_bssids.py --host ct521a-manx \ + --radio 1.1.wiphy0 \ + --traffic_dur_sec 60 \ + --test_duration_min 120 \ + --security wpa2 \ + --ssid cyrus \ + --passwd HelloRudy \ + --bssid cc:32:e5:4b:ef:b3 \ + --bssid cc:32:e5:4b:ef:b4 \ + --bssid 70:4f:57:1e:15:af \ + --bssid 70:4f:57:1e:15:ae \ + --bssid d8:0d:17:be:ab:36 \ + --bssid d8:0d:17:be:ab:37 \ + --bssid 54:83:3a:9c:38:7f \ + +Notes: + # cyrus1 161- 3x3 MCS 0-9 AC WPA2 cc:32:e5:4b:ef:b3 -31.0 5805 100 5.76 m + cyrus1 11 3x3 MIMO WPA2 cc:32:e5:4b:ef:b4 -32.0 2462 100 5.76 m + cyrus 1 3x3 MIMO WPA2 70:4f:57:1e:15:af -48.0 2412 100 5.76 m + cyrus 149+ 4x4 MCS 0-9 AC WPA2 70:4f:57:1e:15:ae -53.0 5745 100 5.76 m + cyrus 157+ 3x3 MCS 0-9 AC WPA2 d8:0d:17:be:ab:36 -64.0 5785 100 5.76 m + cyrus 11 3x3 MIMO WPA2 d8:0d:17:be:ab:37 -65.0 2462 100 5.76 m + cyrus 11 3x3 MIMO WPA WPA2 54:83:3a:9c:38:7f -72.0 2462 100 5.76 m + + + +TO DO NOTES: + +""" +import logging +import sys + +if sys.version_info[0] != 3: + print("This script requires Python3") + exit() + +import os +import importlib +import argparse +import time +from http.client import HTTPResponse +from typing import Optional +from pprint import pprint + +path_hunks = os.path.abspath(__file__).split('/') +while (path_hunks[-1] != 'lanforge-scripts'): + path_hunks.pop() +sys.path.append(os.path.join("/".join(path_hunks))) +realm = importlib.import_module("py-json.realm") +Realm = realm.Realm +lanforge_api = importlib.import_module("lanforge_client.lanforge_api") +Logg = lanforge_api.Logg +LFSession = lanforge_api.LFSession +LFJsonCommand = lanforge_api.LFJsonCommand +LFJsonQuery = lanforge_api.LFJsonQuery + + +# from scenario import LoadScenario + + +# print(pprint.pformat(("ospath", sys.path))) + +class BssidMonitor(Realm): + def __init__(self, + host: str = "localhost", + port: int = 8080, + debug: bool = False, + args: argparse = None, + radio: str = None, + ssid: str = None, + security: str = None, + password: str = None, + upstream: str = None, + mode: int = 0, + side_a_min_rate: int = 256000, + side_b_min_rate: int = 256000, + test_duration_min: str = "5m", + report_file: str = None, + output_format: str = None, + layer3_cols: list = None, # p3.9 list[str] + port_mgr_cols=None, + monitor_interval_sec: int = 10, + bssid_list: list = None): # p3.9 list[str] + """ + lfclient_host="localhost", + lfclient_port=8080, + debug_=False, + _exit_on_error=False, + _exit_on_fail=False, + _proxy_str=None, + _capture_signal_list=[] + :param host: + :param port: + :param radio: + :param ssid: + :param security: + :param password: + :param upstream: + :param mode: + :param side_a_min_rate: + :param side_b_min_rate: + :param test_duration_min: + :param report_file: + :param output_format: + :param layer3_cols: + :param port_mgr_cols: + :param monitor_interval_sec: + :param bssid_list: + """ + super().__init__(lfclient_host=host, + lfclient_port=port, + debug_=debug, + _exit_on_error=True, + _exit_on_fail=False) + self.radio: str = radio + self.ssid: str = ssid + self.security: str = security + self.password: str = password + self.upstream: str = upstream + self.mode: int = mode + self.side_a_min_rate: int = side_a_min_rate + self.side_b_min_rate: int = side_b_min_rate + self.test_duration = test_duration_min + self.report_file: str = report_file + self.output_format: str = output_format + self.port_mgr_cols: list = port_mgr_cols # p3.9 list[str] + self.layer3_cols = layer3_cols # py 3.9.x tuple[Optional[list[str]]] + # self.layer3_cols: tuple = layer3_cols # py 3.7.7 + self.monitor_interval_sec: int = monitor_interval_sec + + if not bssid_list: + raise ValueError("bssid list necessary to continue") + self.bssid_list: list = bssid_list # p 3.9: list[str] + self.bssid_sta_profiles: dict = {} #p3.9: dict[str,str] + + ''' + session = LFSession(lfclient_url="http://localhost:8080", + connect_timeout_sec=20, + proxy_map={ + 'http':'http://192.168.1.250:3128' + }, + debug=True, + die_on_error=False);''' + + self.lf_session: LFSession = \ + lanforge_api.LFSession(lfclient_url="http://{host}:{port}/".format(host=host, port=port), + debug=debug, + connection_timeout_sec=2, + stream_errors=True, + stream_warnings=True, + require_session=True, + exit_on_error=True) + if args and args.debugging: + pprint(args.debugging) + # we could have a nested list here? + for item in args.debugging: + if (type(item) is list): + item = item[0] + if item.startswith("tag:"): + Logg.register_tag(item[item.rindex(":"):]) + if item.startswith("method:"): + Logg.register_method_name(item[item.rindex(":"):]) + + self.lf_command: LFJsonCommand = self.lf_session.get_command() + self.lf_query: LFJsonQuery = self.lf_session.get_query() + + def build(self): + # get last event id + last_event_id = self.before_load_action() + + # load a database + response: HTTPResponse = self.lf_command.post_load(name="BLANK", + action="overwrite", + clean_dut="NA", + clean_chambers="NA", + debug=self.debug) + + if not self.wait_for_load_to_finish(since_id=last_event_id): + exit(1) + + if not response: + raise ConnectionError("lf_command::post_load returned no response") + + # create a series of stations + for bssid in self.bssid_list: + print("build: bssid: %s" % bssid) + + def before_load_action(self): + """ + Use this + :return: last event ID in event list + """ + err_warn_list = [] + self.lf_command.post_show_events(p_type='all', + shelf=1, + card='all', + port='all', + endp='all') + time.sleep(0.2) + + event_response = self.lf_query.events_last_events(event_count=1, + debug=self.debug, + wait_sec=1, + max_timeout_sec=120, + errors_warnings=err_warn_list) + if not event_response: + Logg.logg(level=logging.ERROR, msg="No event_response, we should have retried that") + return + # pprint(("event_response:", event_response)) + if "id" not in event_response: + pprint(("event_response:", event_response)) + return + return event_response["id"] + + def wait_for_load_to_finish(self, since_id: int = None): + """ + TODO: make this a standard method outside this module + :param since_id: + :return: + """ + completed = False + timer = 0 + timeout = 60 + while not completed: + new_events = self.lf_query.events_since(event_id=since_id) + if new_events: + for event_tup in new_events: + for event_id in event_tup.keys(): + event_record = event_tup[event_id] + if self.debug: + pprint("\n wait_for_load_to_finish: {since} -> {id}: {descr}\n".format( + since=since_id, + id=event_id, + descr=event_record['event description'] + )) + if event_record['event description'].startswith('LOAD COMPLETED'): + completed = True + self.lf_query.logger.warning('Scenario loaded after %s seconds' % timer) + break + if completed: + break + else: + if (timer % 5) == 0: + self.lf_command.post_show_events(p_type='all', + shelf=1, + card='all', + port='all', + endp='all') + timer += 1 + time.sleep(1) + if timer > timeout: + completed = True + print('Scenario failed to load after %s seconds' % timeout) + break + else: + print('Waiting %s out of %s seconds to load scenario' % (timer, timeout)) + return completed + + def start(self): + pass + + def stop(self): + pass + + def cleanup(self): + pass + + +def main(): + parser = Realm.create_basic_argparse( + formatter_class=argparse.RawTextHelpFormatter, + prog=__file__, + epilog="", + description="Monitor traffic to different APs and report connection stability") + + parser.add_argument('--mode', help='Used to force mode of stations') + parser.add_argument('--bssid', + action='append', # action='extend' appears in py 3.9 + type=str, + nargs="+", + help='Add an AP to the list of APs to test connections to') + #parser.add_argument('--debugging', + # action='extend', + # type=str, + # nargs="+", + # help='Debugging for specific areas: "tag:keyword" or "method:methodname" ') + parser.add_argument('--output_format', + type=str, + help='choose either csv or xlsx') + parser.add_argument('--report_file', + default=None, + type=str, + help='where you want to store results') + parser.add_argument('--a_min', + default=256000, + type=int, + help='bps rate minimum for side_a') + parser.add_argument('--b_min', + default=256000, + type=int, + help='bps rate minimum for side_b') + parser.add_argument('--test_duration_min', + default="2", + type=int, + help='duration of the test in minutes') + parser.add_argument('--layer3_cols', + type=list, # py3.9 list[str] + help='titles of columns to report') + parser.add_argument('--port_mgr_cols', + type=list, # py3.9 list[str] + help='titles of columns to report') + + args = parser.parse_args() + + # pprint.pprint(("args.members:", dir(args))) + + bssid_monitor = BssidMonitor(host=args.mgr, + port=args.mgr_port, + debug=args.debug, + args=args, + radio=args.radio, + ssid=args.ssid, + security=args.security, + password=args.passwd, + upstream=args.upstream_port, + mode=args.mode, + side_a_min_rate=args.a_min, + side_b_min_rate=args.b_min, + test_duration_min=args.test_duration_min, + report_file=args.report_file, + output_format=args.output_format, + layer3_cols=args.layer3_cols, + port_mgr_cols=args.port_mgr_cols, + monitor_interval_sec=10, + bssid_list=args.bssid) + + bssid_monitor.build() + bssid_monitor.start() + bssid_monitor.stop() + bssid_monitor.cleanup() + + +if __name__ == "__main__": + main() +# diff --git a/py-scripts/layer3_test.py b/py-scripts/sandbox/layer3_test.py similarity index 73% rename from py-scripts/layer3_test.py rename to py-scripts/sandbox/layer3_test.py index 6199babf..d870da80 100755 --- a/py-scripts/layer3_test.py +++ b/py-scripts/sandbox/layer3_test.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 + +# script moved to sandbox 11/11/2021 - needs updates + import sys import os import importlib @@ -14,18 +17,20 @@ if sys.version_info[0] != 3: sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) LFUtils = importlib.import_module("py-json.LANforge.LFUtils") -lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") -LFCliBase = lfcli_base.LFCliBase realm = importlib.import_module("py-json.realm") Realm = realm.Realm -class Layer3Test(LFCliBase): +class Layer3Test(Realm): def __init__(self, lfclient_host="localhost", lfclient_port=8080, radio="wiphy1", sta_prefix="sta", start_id=0, num_sta=2, - dut_ssid="lexusdut", dut_security="open", dut_passwd="[BLANK]", upstream="eth1", name_prefix="L3Test", - traffic_type="lf_udp",side_a_speed="0M", side_b_speed="10M", session_id="Layer3Test", duration="1m",_debug_on=False, _exit_on_error=False, _exit_on_fail=False): - super().__init__(lfclient_host, lfclient_port, _debug=_debug_on, _exit_on_fail=_exit_on_fail) + dut_ssid="lexusdut", dut_security="open", dut_passwd="[BLANK]", upstream="1.1.eth1", name_prefix="L3Test", + traffic_type="lf_udp", + side_a_min_rate=256000, side_a_max_rate=0, + side_b_min_rate=256000, side_b_max_rate=0, + session_id="Layer3Test", duration="1m", + _debug_on=False, _exit_on_error=False, _exit_on_fail=False): + super().__init__(lfclient_host=lfclient_host, lfclient_port=lfclient_port, debug_=_debug_on, _exit_on_fail=_exit_on_fail) print("Test is about to start") self.host = lfclient_host self.port = lfclient_port @@ -42,29 +47,27 @@ class Layer3Test(LFCliBase): self.password = dut_passwd self.session_id = session_id self.traffic_type = traffic_type - self.side_a_speed = side_a_speed - self.side_b_speed = side_b_speed - self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port) - self.station_profile = self.local_realm.new_station_profile() - self.cx_profile = self.local_realm.new_l3_cx_profile() + self.station_profile = self.new_station_profile() + self.cx_profile = self.new_l3_cx_profile() self.cx_profile.host = self.host self.cx_profile.port = self.port self.cx_profile.name_prefix = self.name_prefix - self.cx_profile.side_a_min_bps = self.local_realm.parse_speed(self.side_a_speed) - self.cx_profile.side_a_max_bps = self.local_realm.parse_speed(self.side_a_speed) - self.cx_profile.side_b_min_bps = self.local_realm.parse_speed(self.side_b_speed) - self.cx_profile.side_b_max_bps = self.local_realm.parse_speed(self.side_b_speed) + self.cx_profile.side_a_min_bps = side_a_min_rate + self.cx_profile.side_a_max_bps = side_a_max_rate + self.cx_profile.side_b_min_bps = side_b_min_rate + self.cx_profile.side_b_max_bps = side_b_max_rate print("Test is Initialized") def precleanup(self): print("precleanup started") - self.station_list = LFUtils.portNameSeries(prefix_=self.sta_prefix, start_id_=self.sta_start_id, end_id_=self.num_sta - 1, padding_number_=10000, radio=self.radio) + self.station_list = LFUtils.portNameSeries(prefix_=self.sta_prefix, start_id_=self.sta_start_id, + end_id_=self.num_sta - 1, padding_number_=10000, radio=self.radio) self.cx_profile.cleanup_prefix() for sta in self.station_list: - self.local_realm.rm_port(sta, check_exists=True) + self.rm_port(sta, check_exists=True) time.sleep(1) self.cx_profile.cleanup() @@ -81,8 +84,9 @@ class Layer3Test(LFCliBase): self.station_profile.set_command_param("set_port", "report_timer", 1500) self.station_profile.set_command_flag("set_port", "rpt_timer", 1) self.station_profile.create(radio=self.radio, sta_names_=self.station_list, debug=self.debug) - self.local_realm.wait_until_ports_appear(sta_list=self.station_list) - self.cx_profile.create(endp_type=self.traffic_type, side_a=self.station_profile.station_names, side_b=self.upstream, sleep_time=0) + self.wait_until_ports_appear(sta_list=self.station_list) + self.cx_profile.create(endp_type=self.traffic_type, side_a=self.station_profile.station_names, + side_b=self.upstream, sleep_time=0) print("Test Build done") pass @@ -92,7 +96,7 @@ class Layer3Test(LFCliBase): self.station_profile.admin_up() temp_stas = self.station_profile.station_names.copy() temp_stas.append(self.upstream) - if (self.local_realm.wait_for_ip(temp_stas)): + if self.wait_for_ip(temp_stas): self._pass("All stations got IPs", print_pass) else: self._fail("Stations failed to get IPs", print_fail) @@ -101,13 +105,13 @@ class Layer3Test(LFCliBase): try: for i in self.cx_profile.get_cx_names(): self.cx_names.append(i) - while self.local_realm.json_get("/cx/" + i).get(i).get('state') != 'Run': + while self.json_get("/cx/" + i).get(i).get('state') != 'Run': continue except Exception as e: pass print("Test Started") self.cur_time = datetime.datetime.now() - self.end_time = self.local_realm.parse_time(self.test_duration) + self.cur_time + self.end_time = self.parse_time(self.test_duration) + self.cur_time print(self.end_time-self.cur_time) self.start_monitor() pass @@ -136,8 +140,12 @@ class Layer3Test(LFCliBase): pass def main(): - # This has --mgr, --mgr_port and --debug - parser = LFCliBase.create_basic_argparse( + # Realm.create_basic_argparse defined in + # /py-json/LANforge/lfcli_base.py + # args --mgr --mgr_port --upstream_port --num_stations --test_id + # --debug --proxy --debugging --debug_log + # --radio --security --ssid --passwd + parser = Realm.create_basic_argparse( prog="layer3_test.py", formatter_class=argparse.RawTextHelpFormatter, epilog="About This Script") @@ -156,7 +164,9 @@ def main(): obj = Layer3Test(lfclient_host=args.mgr, lfclient_port=args.mgr_port, duration=args.test_duration, session_id=args.session_id, traffic_type=args.traffic_type, - dut_ssid=args.ssid, dut_passwd=args.passwd, dut_security=args.security, num_sta=args.num_client, side_a_speed=args.side_a_min_speed, side_b_speed=args.side_b_min_speed, radio=args.radio) + upstream=args.upstream_port, + dut_ssid=args.ssid, dut_passwd=args.passwd, dut_security=args.security, num_sta=args.num_client, + side_a_min_rate=args.side_a_min_speed, side_b_min_rate=args.side_b_min_speed, radio=args.radio,_debug_on=args.debug) obj.precleanup() obj.build() obj.start() diff --git a/py-scripts/layer4_test.py b/py-scripts/sandbox/layer4_test.py similarity index 99% rename from py-scripts/layer4_test.py rename to py-scripts/sandbox/layer4_test.py index 6507ef2a..a35593e3 100755 --- a/py-scripts/layer4_test.py +++ b/py-scripts/sandbox/layer4_test.py @@ -5,7 +5,11 @@ Candela Technologies Inc. Info : Standard Script for Layer 4 Testing Date : Author : Shivam Thakur + + """ + +# script moved to sandbox 11/11/2021 needs work import sys import os import importlib diff --git a/py-scripts/lf_ftp_test.py b/py-scripts/sandbox/lf_ftp_test.py similarity index 100% rename from py-scripts/lf_ftp_test.py rename to py-scripts/sandbox/lf_ftp_test.py diff --git a/py-scripts/sandbox/lf_qa_dash.py b/py-scripts/sandbox/lf_qa_dash.py new file mode 100755 index 00000000..fa0464bb --- /dev/null +++ b/py-scripts/sandbox/lf_qa_dash.py @@ -0,0 +1,607 @@ +#!/usr/bin/env python3 +''' +File: read kpi.csv place in sql database, create png of historical kpi and present graph on dashboard +Usage: kpi_csv_sq.py --store --png --show --path --database +Example: kpi_csv_sq.py --show (show dashboard generated from database) +Example: kpi_csv_sq.py --store --png --show --path (read kpi.csv store to database, write png, show dashboard ) +''' +# visit http://127.0.0.1:8050/ in your web browser. +import sys +import os +import importlib +import dash +import dash_core_components as dcc +import dash_html_components as html +import plotly.express as px +import pandas as pd +import sqlite3 +import argparse +from pathlib import Path +import time + +sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../../"))) + +lf_report = importlib.import_module("py-scripts.lf_report") +lf_report = lf_report.lf_report + +# Any style components can be used +external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] +class csv_sqlite_dash(): + def __init__(self, + _path = '.', + _file = 'kpi.csv', + _database = 'qa_db', + _table = 'qa_table', + _server = 'http://192.168.95.6/', + _cut = '/home/lanforge/', + _png = False): + self.path = _path + self.file = _file + self.database = _database + self.table = _table + self.server = _server + self.cut = _cut + self.png = _png + self.png_generated = False + self.kpi_list = [] + self.html_list = [] + self.conn = None + self.df = pd.DataFrame() + self.plot_figure = [] + self.children_div = [] + self.html_results ="" + self.test_rig_list = [] + self.server_html_reports = self.server + 'html-reports/' #TODO : hard coded - is this needed? have server + self.server_started = False + self.dut_model_num_list = "NA" + self.dut_model_num = "NA" + self.dut_sw_version_list = "NA" + self.dut_sw_version = "NA" + self.dut_hw_version_list = "NA" + self.dut_hw_version = "NA" + self.dut_serial_num_list = "NA" + self.dut_serial_num = "NA" + + self.app = dash.Dash(__name__, external_stylesheets=external_stylesheets) + # https://community.plotly.com/t/putting-a-dash-instance-inside-a-class/6097/3 + #https://dash.plotly.com/dash-html-components/button + #self.app.callback(dash.dependencies.Output('container-button-basic', 'children'), + # [dash.dependencies.Input(component_id ='submit-val', component_property ='n_clicks')])(self.show) + + # Helper methods + def get_test_rig_list(self): + return self.test_rig_list + + def get_html_results(self): + return self.html_results + + def get_dut_info(self): + #try: + print("get_dut_info DUT: {DUT} SW:{SW} HW:{HW} SN:{SN}" + .format(DUT=self.dut_model_num,SW=self.dut_sw_version,HW=self.dut_hw_version,SN=self.dut_serial_num)) + + dut_dict = { + 'DUT':[self.dut_model_num], + 'SW version': [self.dut_sw_version], + 'HW version':[self.dut_hw_version], + 'SN':[self.dut_serial_num] + } + print('DUT dict: {dict}'.format(dict=dut_dict)) + dut_info_df = pd.DataFrame(dut_dict) + print("DUT df from dict: {df}".format(df=dut_info_df)) + + return dut_info_df + + def get_parent_path(self,_path): + parent_path = os.path.dirname(_path) + return parent_path + + def get_test_id_test_tag(self,_kpi_path): + test_id = "NA" + test_tag = "NA" + use_meta_test_tag = False + try: + kpi_df = pd.read_csv(_kpi_path, sep='\t') + test_id_list = list(kpi_df['test-id']) + test_id = list(set(test_id_list)) + test_id = test_id[-1] # done to get element of list + except: + print("exception reading test_id in csv _kpi_path {kpi_path}".format(kpi_path=_kpi_path)) + try: + test_tag_list = list(kpi_df['test-tag']) + test_tag = list(set(test_tag_list)) + test_tag = test_tag[-1] # done to get element of list + except: + print("exception reading test-tag in csv _kpi_path {kpi_path}, try meta.txt".format(kpi_path=_kpi_path)) + + #if test_tag still NA then try meta file + try: + if test_tag == "NA": + _kpi_path = _kpi_path.replace('kpi.csv','') + use_meta_test_tag, test_tag = self.get_test_tag_from_meta(_kpi_path) + except: + print("exception reading meta.txt _kpi_path: {kpi_path}".format(kpi_path=_kpi_path)) + if use_meta_test_tag: + print("test_tag from meta.txt _kpi_path: {kpi_path}".format(kpi_path=_kpi_path)) + return test_id , test_tag + + # could enter on the command line, except there may be other exceptions + # may need an exception file + def get_test_tag_from_meta(self,_kpi_path): + test_tag = "NA" + use_meta_test_tag = False + gui_version_5_4_3 = False + print("read meta path {_kpi_path}".format(_kpi_path=_kpi_path)) + try: + meta_data_path = _kpi_path + '/' + '/meta.txt' + meta_data_fd = open(meta_data_path, 'r') + for line in meta_data_fd: + if "gui_version:" in line: + gui_version = line.replace("gui_version:","") + gui_version = gui_version.strip() + if gui_version =='5.4.3': + gui_version_5_4_3 = True + use_meta_test_tag = True + print("meta_data_path: {meta_data_path} gui_version: {gui_version} 5.4.3: {gui_version_5_4_3}".format( + meta_data_path=meta_data_path,gui_version=gui_version,gui_version_5_4_3=gui_version_5_4_3)) + meta_data_fd.close() + if gui_version_5_4_3: + meta_data_fd = open(meta_data_path, 'r') + test_tag = 'NA' + for line in meta_data_fd: + if "test_tag" in line: + test_tag = line.replace("test_tag","") + test_tag = test_tag.strip() + print("meta_data_path {meta_data_path} test_tag {test_tag}".format(meta_data_path=meta_data_path,test_tag=test_tag)) + meta_data_fd.close() + except: + print("exception reading test_tag from {_kpi_path}".format(_kpi_path=_kpi_path)) + + return use_meta_test_tag, test_tag + + #TODO pass in list to lf_report + # + def get_suite_html(self): + suite_html_results = """ +
+ + + + + + + + + """ + + path = Path(self.path) + pdf_info_list= list(path.glob('**/*.pdf')) # Hard code for now + print("pdf_info_list {}".format(pdf_info_list)) + for pdf_info in pdf_info_list: + if "lf_qa" in str(pdf_info): + pass + else: + pdf_base_name = os.path.basename(pdf_info) + if "check" in str(pdf_base_name): + pass + else: + parent_path = os.path.dirname(pdf_info) + pdf_path = os.path.join(parent_path,pdf_base_name) + pdf_path = self.server + pdf_path.replace(self.cut,'') + html_path = os.path.join(parent_path,"index.html") + html_path = self.server + html_path.replace(self.cut,'') + kpi_path = os.path.join(parent_path,"kpi.csv") + test_id, test_tag = self.get_test_id_test_tag(kpi_path) + suite_html_results += """ + + + """.format(test_id=test_id,test_tag=test_tag,html_path=html_path,pdf_path=pdf_path) + suite_html_results += """ + +
TestTest_TagLinks
{test_id}{test_tag}html / pdf
+
+ """ + + return suite_html_results + + def get_kpi_chart_html(self): + kpi_chart_html = """ + + + """ + path = Path(self.path) + kpi_chart_list= list(path.glob('**/kpi-chart*.png')) # Hard code for now + table_index = 0 + for kpi_chart in kpi_chart_list: + parent_path = os.path.dirname(kpi_chart) + kpi_path = os.path.join(parent_path,"kpi.csv") + test_tag , test_id = self.get_test_id_test_tag(kpi_path) + kpi_chart = os.path.abspath(kpi_chart) # Path returns a list of objects + kpi_chart = self.server + kpi_chart.replace(self.cut,'') + if "print" in kpi_chart: + pass + else: + if (table_index %2) == 0: + kpi_chart_html += """""" + kpi_chart_html += """ + + + """.format(test_tag=test_tag,test_id=test_id,kpi_chart_0=kpi_chart,kpi_chart_1=kpi_chart,kpi_chart_2=kpi_chart) + table_index += 1 + if (table_index %2) == 0: + kpi_chart_html += """""" + if (table_index %2) != 0: + kpi_chart_html += """""" + kpi_chart_html += """
+ {test_tag} {test_id} + + + + +
""" + return kpi_chart_html + + # information on sqlite database + # https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_sql.html + def store(self): + print("reading kpi and storing in db {}".format(self.database)) + path = Path(self.path) + self.kpi_list = list(path.glob('**/kpi.csv')) # Hard code for now + + if not self.kpi_list: + print("WARNING: used --store , no new kpi.csv found, check input path or remove --store from command line") + + for kpi in self.kpi_list: #TODO note empty kpi.csv failed test + df_kpi_tmp = pd.read_csv(kpi, sep='\t') + _kpi_path = str(kpi).replace('kpi.csv','') # only store the path to the kpi.csv file + df_kpi_tmp['kpi_path'] = _kpi_path + use_meta_test_tag, test_tag = self.get_test_tag_from_meta(_kpi_path) + if use_meta_test_tag: + df_kpi_tmp['test-tag'] = test_tag + df_kpi_tmp = df_kpi_tmp.append(df_kpi_tmp, ignore_index=True) + self.df = self.df.append(df_kpi_tmp, ignore_index=True) + + self.conn = sqlite3.connect(self.database) + try: + self.df.to_sql(self.table,self.conn,if_exists='append') + except: + print("attempt to append to database with different column layout, caused an exception, input new name --database ") + print("Error attempt to append to database with different column layout, caused an exception, input new name --database ", file=sys.stderr) + exit(1) + self.conn.close() + + def generate_graph_png(self): + print("generate png and html to display, generate time: {}".format(time.time())) + + #https://datacarpentry.org/python-ecology-lesson/09-working-with-sql/index.html- + self.conn = sqlite3.connect(self.database) + df3 = pd.read_sql_query("SELECT * from {}".format(self.table) ,self.conn) #current connection is sqlite3 /TODO move to SQLAlchemy + # sort by date from oldest to newest. + try: + df3 = df3.sort_values(by='Date') + except: + print("Database empty: KeyError(key) when sorting by Date, check Database name, path to kpi, typo in path, exiting") + exit(1) + self.conn.close() + + # graph group and test-tag are used for detemining the graphs, can use any columns + # the following list manipulation removes the duplicates + graph_group_list = list(df3['Graph-Group']) + graph_group_list = list(set(graph_group_list)) + print("graph_group_list: {}".format(graph_group_list)) + + # prior to 5.4.3 there was not test-tag + #try: + print("dataframe df3 {df3}".format(df3=df3)) + test_tag_list = list(df3['test-tag']) + test_tag_list = list(set(test_tag_list)) + print("test_tag_list: {}".format(test_tag_list) ) + #except: + #test_tag_list = ['NO_TAG_PRE_5.4.4'] + #print("exception when creating test_tag_list: {}".format(test_tag_list) ) + #print("Check database, exception when creating test_tag_list: {}".format(test_tag_list) ) + + + + test_rig_list = list(df3['test-rig']) + test_rig_list = list(set(test_rig_list)) + self.test_rig_list = test_rig_list + print("test_rig_list: {}".format(test_rig_list) ) + + self.children_div.append(html.A('html_reports', href=self.server_html_reports, target='_blank')) + for test_rig in test_rig_list: + for test_tag in test_tag_list: + for group in graph_group_list: + df_tmp = df3.loc[(df3['test-rig'] == test_rig) & (df3['Graph-Group'] == str(group)) & (df3['test-tag'] == str(test_tag))] + if df_tmp.empty == False: + + df_tmp = df_tmp.sort_values(by='Date') + test_id_list = list(df_tmp['test-id']) + kpi_path_list = list(df_tmp['kpi_path']) + # get Device Under Test Information , + # the set reduces the redundency , list puts it back into a list + self.dut_model_num_list = list(set(list(df_tmp['dut-model-num']))) + print("in png self.dut_model_num_list {dut_model_num_list}".format(dut_model_num_list=self.dut_model_num_list)) + if self.dut_model_num_list[0] != None: + self.dut_model_num = self.dut_model_num_list[0] + self.dut_sw_version_list = list(set(list(df_tmp['dut-sw-version']))) + if self.dut_sw_version_list[0] != None: + self.dut_sw_version = self.dut_sw_version_list[0] + self.dut_hw_version_list = list(set(list(df_tmp['dut-hw-version']))) + if self.dut_hw_version_list[0] != None: + self.dut_hw_version = self.dut_hw_version_list[0] + self.dut_serial_num_list = list(set(list(df_tmp['dut-serial-num']))) + if self.dut_serial_num_list[0] != None: + self.dut_serial_num_ = self.dut_serial_num_list[0] + + print("In png DUT: {DUT} SW:{SW} HW:{HW} SN:{SN}" + .format(DUT=self.dut_model_num_list,SW=self.dut_sw_version_list,HW=self.dut_hw_version_list,SN=self.dut_serial_num_list)) + + units_list = list(df_tmp['Units']) + print("GRAPHING::: test-rig {} test-tag {} Graph-Group {}".format(test_rig,test_tag,group)) + kpi_fig = (px.scatter(df_tmp, x="Date", y="numeric-score", + color="short-description", hover_name="short-description", + size_max=60)).update_traces(mode='lines+markers') + + kpi_fig.update_layout( + title="{} : {} : {} : {}".format(test_id_list[-1], group, test_tag, test_rig), + xaxis_title="Time", + yaxis_title="{}".format(units_list[-1]), + xaxis = {'type' : 'date'} + ) + # save the figure - figures will be over written png + # for testing + png_server_img = '' + #TODO work out when to generate the png files + if self.png: + if self.png_generated: + pass + else: + print("generate png and kpi images from kpi kpi_path:{}".format(df_tmp['kpi_path'])) + # generate png img path + png_path = os.path.join(kpi_path_list[-1],"{}_{}_{}_kpi.png".format( group, test_tag, test_rig)) + png_path = png_path.replace(' ','') + # generate html graphics path + html_path = os.path.join(kpi_path_list[-1],"{}_{}_{}_kpi.html".format( group, test_tag, test_rig)) + html_path = html_path.replace(' ','') + # NOTE: html links to png do not like spaces + png_server_img = self.server + png_path.replace(self.cut,'') + # generate png image + try: + kpi_fig.write_image(png_path,scale=1,width=1200,height=350) + except: + print("ERROR: {database} Was correct database passed in, moved or duplicates of same name?".format(database=self.database)) + #https://plotly.com/python/interactive-html-export/ + # generate html image (interactive) + kpi_fig.write_html(html_path) + # generate link for dashboard + self.children_div.append(html.Img(src=png_server_img)) + #HERE add clickable link + img_kpi_html_path = self.server + html_path + img_kpi_html_path = img_kpi_html_path.replace(self.cut,'') + + self.html_results += """ + + + + """.format(img_kpi_html_path=img_kpi_html_path,png_server_img=png_server_img) + + # WARNING: DO NOT USE os.path.join will use the path for where the script is RUN which can be container. + # Constructed path to server manually. + # link to interactive results + kpi_html_path = self.server + html_path + kpi_html_path = kpi_html_path.replace(self.cut,'') + self.children_div.append(html.Br()) + #self.html_results +="""
""" + self.children_div.append(html.A('{test_id}_{group}_{test_tag}_{test_rig}_kpi.html' + .format(test_id=test_id_list[-1], group=group, test_tag=test_tag, test_rig=test_rig), + href=kpi_html_path, target='_blank')) + + # link to full test results + report_index_html_path = self.server + kpi_path_list[-1] + "index.html" + report_index_html_path = report_index_html_path.replace(self.cut,'') + self.children_div.append(html.Br()) + #self.html_results +="""
""" + self.children_div.append(html.A('{test_id}_{group}_{test_tag}_{test_rig}_report.html' + .format(test_id=test_id_list[-1], group=group, test_tag=test_tag, test_rig=test_rig), + href=report_index_html_path, target='_blank')) + self.html_results +="""{test_id}_{group}_{test_tag}_{test_rig}_Report + """.format(report_index_html_path=report_index_html_path,test_id=test_id_list[-1], group=group, test_tag=test_tag, test_rig=test_rig) + self.children_div.append(html.Br()) + self.children_div.append(html.Br()) + self.children_div.append(html.Br()) + self.html_results +="""
""" + self.html_results +="""
""" + self.html_results +="""
""" + self.html_results +="""
""" + self.html_results +="""
""" + + # TODO see if this stops the regenration of the graphs each time + self.png_generated = True + + + # access from server + # https://stackoverflow.com/questions/61678129/how-to-access-a-plotly-dash-app-server-via-lan + #def show(self,n_clicks): + def show(self): + # gererate dash display + #print("refreshes: {}".format(n_clicks)) + self.generate_graph_png() + if not self.children_div: + print("NOTE: test-tag may not be present in the kpi thus no results generated") + print("show: {}".format(time.time())) + self.app.layout = html.Div([ + html.Div(id='my-output'), + html.H1(children= "LANforge Testing",className="lanforge", + style={'color':'green','text-align':'center'}), + #For dash refresh # html.Button('Submit Recalculate',id='submit-val', n_clicks=0), + #For dash refresh # html.Div(id='container-button-basic', children='to recalculate hit submit'), + html.H2(children= "Results",className="ts1", + style={'color':'#00361c','text-align':'left'}), + # images_div is already a list, children = a list of html components + # remove scrolling : html.Div(children= self.children_div, style={"maxHeight": "600px", "overflow": "scroll"} ), + html.Div(children= self.children_div ), + html.A('www.candelatech.com',href='http://www.candelatech.com', target='_blank', + style={'color':'#00361c','text-align':'left'}), + ]) + + # save as standalone files + #https://plotly.com/python/static-image-export/ + + if self.server_started: + print("refresh complete") + pass + else: + self.server_started = True + print("self.server_started {}".format(self.server_started)) + #NOTE: the server_started flag needs to be set prior to run_server (or you get to debug an infinite loop) + #NOTE: debug=False will prevent init going though twice, also stops auto reload when editing code + self.app.run_server(host= '0.0.0.0', debug=True) + # host = '0.0.0.0' allows for remote access, local debug host = '127.0.0.1' + # app.run_server(host= '0.0.0.0', debug=True) + +# Feature, Sum up the subtests passed/failed from the kpi files for each run, poke those into the database, and generate a kpi graph for them. +def main(): + + parser = argparse.ArgumentParser( + prog='lf_qa.py', + formatter_class=argparse.RawTextHelpFormatter, + epilog='''\ + read kpi.csv into sqlite database , save png of history and preset on dashboard + + ''', + description='''\ +File: read kpi.csv place in sql database, create png of historical kpi and present graph on dashboard +Usage: kpi_csv_sq.py --store --png --show --path --database +Example: kpi_csv_sq.py --show (show dashboard generated from database) +Example: kpi_csv_sq.py --store --png --show --path (read kpi.csv store to database, write png, show dashboard ) + + ''') + parser.add_argument('--path', help='--path top directory path to kpi if regererating database or png files',default='') + parser.add_argument('--file', help='--file kpi.csv default: kpi.csv',default='kpi.csv') #TODO is this needed + parser.add_argument('--database', help='--database qa_test_db default: qa_test_db',default='qa_test_db') + parser.add_argument('--table', help='--table qa_table default: qa_table',default='qa_table') + parser.add_argument('--server', help='--server http:/// default: http://192.168.95.6/',default='http://192.168.95.6/') + parser.add_argument('--cut', help='--cut /home/lanforge/ used to adjust server path default: /home/lanforge/',default='/home/lanforge/') + parser.add_argument('--store', help='--store , store kpi to db, action store_true',action='store_true') + parser.add_argument('--png', help='--png, generate png for kpi in path, generate display, action store_true',action='store_true') + parser.add_argument('--show', help='--show generate display and show dashboard, action store_true',action='store_true') + parser.add_argument('--dir', help="--dir default lf_qa", default="lf_qa") + + args = parser.parse_args() + + __path = args.path + __file = args.file + __database = args.database + __table = args.table + __server = args.server + __png = args.png + __dir = args.dir + __cut = args.cut + + # needed for refresh button + # n_clicks = 0 + + print("config: path:{} file:{} database:{} table:{} server:{} store:{} png:{} show:{} " + .format(__path,__file,__database,__table,__server,args.store, args.png,args.show)) + + if(__path == '' and args.store == True): + print("--path must be entered if --store , exiting") + exit(1) + + if(args.png == True and args.store == False): + print("if --png set to create png files then --store must also be set, exiting") + exit(1) + + if(args.png == True and args.show == True): + print("generating png files will effect initial display performance") + + if args.store == False and args.png == False and args.show == False: + print("Need to enter an action of --store --png --show ") + + # create report class for reporting + report = lf_report(_path = __path, + _results_dir_name =__dir, + _output_html="lf_qa.html", + _output_pdf="lf_qa.pdf" ) + + csv_dash = csv_sqlite_dash( + _path = __path, + _file = __file, + _database = __database, + _table = __table, + _server = __server, + _cut = __cut, + _png = __png) + if args.store: + csv_dash.store() + if args.png: + csv_dash.generate_graph_png() + + # generate output reports + report.set_title("LF QA: Verification Test Run") + report.build_banner_left() + report.start_content_div2() + report.set_obj_html("Objective", "QA Verification") + report.build_objective() + report.set_table_title("Device Under Test") + report.build_table_title() + dut_info_df = csv_dash.get_dut_info() + print("DUT Results: {}".format(dut_info_df)) + report.set_table_dataframe(dut_info_df) + report.build_table() + + test_rig_list = csv_dash.get_test_rig_list() + report.set_table_title("Test Rig: {} Links".format(test_rig_list[-1])) # keep the list, currently one test bed results + report.build_table_title() + + pdf_link_path = report.get_pdf_path() + pdf_link_path = __server + pdf_link_path.replace(__cut,'') + report.build_pdf_link("PDF_Report",pdf_link_path) + + report_path = report.get_path() + report_path = __server + report_path.replace(__cut,'') + report.build_link("Current Test Suite Results Directory",report_path) + + report_parent_path = report.get_parent_path() + report_parent_path = __server + report_parent_path.replace(__cut,'') + report.build_link("All Test-Rig Test Suites Results Directory",report_parent_path) + + # links table for tests TODO : can this be a table + report.set_table_title("Test Suite") + report.build_table_title() + suite_html = csv_dash.get_suite_html() + print("suite_html {}".format(suite_html)) + report.set_custom_html(suite_html) + report.build_custom() + + # png summary of test + report.set_table_title("Suite Summary") + report.build_table_title() + kpi_chart_html = csv_dash.get_kpi_chart_html() + report.set_custom_html(kpi_chart_html) + report.build_custom() + + + report.set_table_title("QA Test Results") + report.build_table_title() + # report.set_text("lanforge-scripts git sha: {}".format(git_sha)) + # report.build_text() + html_results = csv_dash.get_html_results() + report.set_custom_html(html_results) + report.build_custom() + report.build_footer() + html_report = report.write_html_with_timestamp() + print("html report: {}".format(html_report)) + try: + report.write_pdf_with_timestamp() + except: + print("exception write_pdf_with_timestamp()") + + if args.show: + #csv_dash.show(n_clicks) + csv_dash.show() + +if __name__ == '__main__': + main() + diff --git a/py-scripts/sandbox/logger_example.py b/py-scripts/sandbox/logger_example.py new file mode 100755 index 00000000..75079561 --- /dev/null +++ b/py-scripts/sandbox/logger_example.py @@ -0,0 +1,51 @@ +#!/usr/bin/python3 + +import logging +from random import choice +logging.basicConfig() + + +class ContextFilter(logging.Filter): + """ + This is a filter which injects contextual information into the log. + + Rather than use actual contextual information, we just use random + data in this demo. + """ + + USERS = ['jim', 'fred', 'sheila'] + IPS = ['123.231.231.123', '127.0.0.1', '192.168.0.1'] + + def filter(self, record): + + record.ip = choice(ContextFilter.IPS) + record.user = choice(ContextFilter.USERS) + return True + + +def main(): + levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL) + logging.basicConfig(level=logging.DEBUG, + format='%(asctime)-15s %(name)-5s %(levelname)-8s IP: %(ip)-15s User: %(user)-8s %(message)s') + a1 = logging.getLogger('a.b.c') + a2 = logging.getLogger('d.e.f') + + logging.basicConfig(filename='example.log', level=logging.DEBUG) + logging.warning('this is a tutorial') + logging.info('It includes the basic logging functions') + + logging.info("Don't include certain strings") + logging.info('define a filter') + f = ContextFilter() + a1.addFilter(f) + a2.addFilter(f) + a1.debug('A debug message') + a1.info('An info message with %s', 'some parameters') + for x in range(10): + lvl = choice(levels) + lvlname = logging.getLevelName(lvl) + a2.log(lvl, 'A message at %s level with %d %s', lvlname, 2, 'parameters') + + +if __name__ == '__main__': + main() diff --git a/py-scripts/sandbox/logger_example_1.py b/py-scripts/sandbox/logger_example_1.py new file mode 100755 index 00000000..318d1c5c --- /dev/null +++ b/py-scripts/sandbox/logger_example_1.py @@ -0,0 +1,26 @@ +#!/usr/bin/python3 + +import logging +import argparse + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--debug', + type=int, + default=2, + help="Set logging level, range 0 through 4. 0 is DEBUG, 4 is CRITICAL") + + args = parser.parse_args() + levels = [logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL] + logging.basicConfig(level=levels[args.debug]) + + logging.debug('This is debug output, level 0') + logging.info('This is info output, level 1') + logging.warning('This is warning output, level 2') + logging.error('This is error output, level 3') + logging.critical('This is error output, level 4') + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/py-scripts/sandbox/monitor_rvr.py b/py-scripts/sandbox/monitor_rvr.py new file mode 100755 index 00000000..aa96c88d --- /dev/null +++ b/py-scripts/sandbox/monitor_rvr.py @@ -0,0 +1,244 @@ +#!/usr/bin/env python3 +# This script will set the LANforge to a BLANK database then it will load the specified database +# and start a graphical report +import sys +import os +import importlib +import argparse +from time import sleep +import pprint + +if sys.version_info[0] != 3: + print("This script requires Python 3") + exit(1) + + +sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../../"))) + +LFUtils = importlib.import_module("py-json.LANforge.LFUtils") +lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base") +LFCliBase = lfcli_base.LFCliBase +realm = importlib.import_module("py-json.realm") +Realm = realm.Realm + +""" + cvScenario.scenario_db = args.scenario_db + if args.cv_test is not None: + cvScenario.cv_test = args.cv_test + if args.test_scenario is not None: + cvScenario.test_scenario = args.test_scenario +""" + +class RunCvScenario(LFCliBase): + def __init__(self, lfhost="localhost", lfport=8080, debug_=False, lanforge_db_=None, cv_scenario_=None, cv_test_=None, test_scenario_=None): + super().__init__( _lfjson_host=lfhost, _lfjson_port=lfport, _debug=debug_, _exit_on_error=True, _exit_on_fail=True) + self.lanforge_db = lanforge_db_ + self.cv_scenario = cv_scenario_ + self.cv_test = cv_test_ + self.test_profile = test_scenario_ + self.localrealm = Realm(lfclient_host=lfhost, lfclient_port=lfport, debug_=debug_) + self.report_name = None + + def get_report_file_name(self): + return self.report_name + + def build(self): + data = { + "name": "BLANK", + "action":"overwrite", + "clean_dut":"yes", + "clean_chambers": "yes" + } + self.json_post("/cli-json/load", data) + sleep(1) + port_counter = 0 + attempts = 6 + while (attempts > 0) and (port_counter > 0): + sleep(1) + attempts -= 1 + print("looking for ports like vap+") + port_list = self.localrealm.find_ports_like("vap+") + alias_map = LFUtils.portListToAliasMap(port_list) + port_counter = len(alias_map) + + port_list = self.localrealm.find_ports_like("sta+") + alias_map = LFUtils.portListToAliasMap(port_list) + port_counter += len(alias_map) + if port_counter == 0: + break + + if (port_counter != 0) and (attempts == 0): + print("There appears to be a vAP in this database, quitting.") + pprint(alias_map) + exit(1) + + data = { + "name": self.lanforge_db, + "action":"overwrite", + "clean_dut":"yes", + "clean_chambers": "yes" + } + self.json_post("/cli-json/load", data) + sleep(1) + self._pass("Loaded scenario %s" % self.lanforge_db, True) + return True + + def start(self, debug_=False): + # /gui_cli takes commands keyed on 'cmd', so we create an array of commands + commands = [ + "sleep 4", + "cv sync", + "sleep 4", + "cv apply '%s'" % self.cv_scenario, + "sleep 4", + "cv build", + "sleep 10", + "cv is_built", + "sleep 1", + "cv sync", + "sleep 5", + "cv create '%s' 'test_ref' 'true'" % self.cv_test, + "sleep 5", + "cv load test_ref '%s'" % self.test_profile, + "sleep 5", + "cv click test_ref 'Auto Save Report'", + "sleep 1", + "cv click test_ref Start", + "sleep 2", + "cv get test_ref progress_area", + "sleep 2", + "cv get test_ref progress_area", + "sleep 2", + "cv get test_ref progress_area", + "sleep 2", + "cv get test_ref progress_area", + "sleep 2", + "cv get test_ref progress_area", + "sleep 2", + "cv get test_ref progress_area", + "sleep 2", + "cv get test_ref progress_area", + "sleep 2", + "cv get test_ref progress_area", + "sleep 2", + "cv get test_ref progress_area", + "sleep 2", + "cv get test_ref progress_area", + "sleep 2", + "cv get test_ref progress_area", + "cv get test_ref 'Report Location:'", + "sleep 5", + #"cv click test_ref 'Save HTML'", + "cv click test_ref 'Close'", + "sleep 1", + "cv click test_ref Cancel", + "sleep 1", + "exit" + ] + response_json = [] + for command in commands: + data = { + "cmd": command + } + try: + debug_par = "" + if debug_: + debug_par="?_debug=1" + if command.endswith("is_built"): + print("Waiting for scenario to build...", end='') + self.localrealm.wait_while_building(debug_=False) + print("...proceeding") + elif command.startswith("sleep "): + nap = int(command.split(" ")[1]) + print("sleeping %d..." % nap) + sleep(nap) + print("...proceeding") + else: + response_json = [] + print("running %s..." % command, end='') + response = self.json_post("/gui-json/cmd%s" % debug_par, data, debug_=False, response_json_list_=response_json) + if debug_ or command.startswith("cv get "): + LFUtils.debug_printer.pprint(response_json) + print("...proceeding") + + + except Exception as x: + print(x) + + self._pass("report finished", print_=True) + + + def stop(self): + pass + + def cleanup(self): + pass + + +def main(): + lfjson_host = "localhost" + lfjson_port = 8080 + parser = argparse.ArgumentParser( + prog="run_cv_scenario.py", + formatter_class=argparse.RawTextHelpFormatter, + description="""LANforge Reporting Script: Load a scenario and run a RvR report + Example: + ./load_ap_scenario.py --lfmgr 127.0.0.1 --scenario_db 'handsets' --cv_test --test_scenario 'test-20' + """) + parser.add_argument("-m", "--lfmgr", type=str, help="address of the LANforge GUI machine (localhost is default)") + parser.add_argument("-o", "--port", type=int, help="IP Port the LANforge GUI is listening on (8080 is default)") + parser.add_argument("-d", "--lanforge_db", type=str, help="Name of test scenario database (see Status Tab)") + parser.add_argument("-c", "--cv_scenario", type=str, help="Name of Chamber View test scenario (see CV Manage Scenarios)") + parser.add_argument("-n", "--cv_test", type=str, help="Chamber View test") + parser.add_argument("-s", "--test_profile", type=str, help="Name of the saved CV test profile") + parser.add_argument("--debug", help='Enable debugging', default=False, action="store_true") + + args = parser.parse_args() + if args.lfmgr is not None: + lfjson_host = args.lfmgr + if args.port is not None: + lfjson_port = args.port + debug = False + if args.debug is not None: + debug = args.debug + run_cv_scenario = RunCvScenario(lfjson_host, lfjson_port, debug_=debug) + + if args.lanforge_db is not None: + run_cv_scenario.lanforge_db = args.lanforge_db + if args.cv_scenario is not None: + run_cv_scenario.cv_scenario = args.cv_scenario + if args.cv_test is not None: + run_cv_scenario.cv_test = args.cv_test + if args.test_profile is not None: + run_cv_scenario.test_profile = args.test_profile + + if (run_cv_scenario.lanforge_db is None) or (run_cv_scenario.lanforge_db == ""): + raise ValueError("Please specificy scenario database name with --scenario_db") + + if not (run_cv_scenario.build() and run_cv_scenario.passes()): + print("scenario failed to build.") + print(run_cv_scenario.get_fail_message()) + exit(1) + + if not (run_cv_scenario.start() and run_cv_scenario.passes()): + print("scenario failed to start.") + print(run_cv_scenario.get_fail_message()) + exit(1) + + if not (run_cv_scenario.stop() and run_cv_scenario.passes()): + print("scenario failed to stop:") + print(run_cv_scenario.get_fail_message()) + exit(1) + + if not (run_cv_scenario.cleanup() and run_cv_scenario.passes()): + print("scenario failed to clean up:") + print(run_cv_scenario.get_fail_message()) + exit(1) + + report_file = run_cv_scenario.get_report_file_name() + print("Report file saved to "+report_file) +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +if __name__ == "__main__": + main() diff --git a/py-scripts/sandbox/test_l3_longevity_beta.py b/py-scripts/sandbox/test_l3_longevity_beta.py new file mode 100644 index 00000000..ded14a1f --- /dev/null +++ b/py-scripts/sandbox/test_l3_longevity_beta.py @@ -0,0 +1,1899 @@ +#!/usr/bin/env python3 +''' +NAME: test_l3_longevity.py + +PURPOSE: + + Supports creating user-specified amount stations on multiple radios + Supports configuring upload and download requested rates and PDU sizes. + Supports generating KPI data for storing in influxdb (used by Graphana) + Supports generating connections with different ToS values. + Supports generating tcp and/or UDP traffic types. + Supports iterating over different PDU sizes + Supports iterating over different requested tx rates (configurable as total or per-connection value) + Supports iterating over attenuation values. + Supports testing connection between two ethernet connection - L3 dataplane + +EXAMPLE: + + 10 stations on wiphy0, 1 station on wiphy2. open-auth to ASUS_70 SSID + Configured to submit KPI info to influxdb-version2. +./test_l3_longevity.py --mgr localhost --endp_type 'lf_udp lf_tcp' --upstream_port 1.1.eth1 \ + --radio "radio==1.1.wiphy0 stations==10 ssid==ASUS_70 ssid_pw==[BLANK] security==open" \ + --radio "radio==1.1.wiphy2 stations==1 ssid==ASUS_70 ssid_pw==[BLANK] security==open" \ + --test_duration 5s --influx_host c7-graphana --influx_port 8086 --influx_org Candela \ + --influx_token=-u_Wd-L8o992701QF0c5UmqEp7w7Z7YOMaWLxOMgmHfATJGnQbbmYyNxHBR9PgD6taM_tcxqJl6U8DjU1xINFQ== \ + --influx_bucket ben --rates_are_totals --side_a_min_bps=20000 --side_b_min_bps=300000000 \ + --influx_tag testbed ath11k --influx_tag DUT ROG -o longevity.csv + +Example command using attenuator +./test_l3_longevity.py --test_duration 5m --polling_interval 1s --upstream_port eth2 \ + --radio 'radio==wiphy1,stations==1,ssid==TCH-XB7,ssid_pw==comcast123,security==wpa2' \ + --radio 'radio==wiphy2,stations==1,ssid==TCH-XB7,ssid_pw==comcast123,security==wpa2' \ + --radio 'radio==wiphy3,stations==1,ssid==TCH-XB7,ssid_pw==comcast123,security==wpa2' \ + --radio 'radio==wiphy4,stations==1,ssid==TCH-XB7,ssid_pw==comcast123,security==wpa2' \ + --endp_type lf_udp --ap_read --ap_scheduler_stats --ap_ofdma_stats --side_a_min_bps=20000 --side_b_min_bps=400000000 \ + --attenuators 1.1..1 \ + --atten_vals 20,21,40,41 + +Example using upsteam eth1 downstream eth2 + ./test_l3_longevity.py --test_duration 20s --polling_interval 1s --upstream_port eth1 --downstream_port eth2 + --endp_type lf --rates_are_totals --side_a_min_bps=10000000,0 --side_a_min_pdu=1000 --side_b_min_bps=0,300000000 --side_b_min_pdu=1000 + +COPYRIGHT: +Copyright 2021 Candela Technologies Inc + +INCLUDE_IN_README +''' +import sys +import os +import importlib +from pprint import pprint +import serial +import pexpect +from pexpect_serial import SerialSpawn +import argparse +import time +import datetime +import csv +import random + +if sys.version_info[0] != 3: + print("This script requires Python 3") + exit(1) + + +sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) + +lf_report = importlib.import_module("py-scripts.lf_report") +LFUtils = importlib.import_module("py-json.LANforge.LFUtils") +realm = importlib.import_module("py-json.realm") +Realm = realm.Realm +csv_to_influx = importlib.import_module("py-scripts.csv_to_influx") +InfluxRequest = importlib.import_module("py-dashboard.InfluxRequest") +influx_add_parser_args = InfluxRequest.influx_add_parser_args + + +# This class handles running the test and generating reports. +class L3VariableTime(Realm): + def __init__(self, + endp_types, + args, + tos, + side_b, + side_a, + radio_name_list, + number_of_stations_per_radio_list, + ssid_list, + ssid_password_list, + ssid_security_list, + station_lists, + name_prefix, + outfile, + reset_port_enable_list, + reset_port_time_min_list, + reset_port_time_max_list, + side_a_min_rate=[56000], + side_a_max_rate=[0], + side_b_min_rate=[56000], + side_b_max_rate=[0], + side_a_min_pdu=["MTU"], + side_a_max_pdu=[0], + side_b_min_pdu=["MTU"], + side_b_max_pdu=[0], + user_tags=[], + rates_are_totals=False, + mconn=1, + attenuators=[], + atten_vals=[], + number_template="00", + test_duration="256s", + polling_interval="60s", + lfclient_host="localhost", + lfclient_port=8080, + debug=False, + influxdb=None, + ap_scheduler_stats=False, + ap_ofdma_stats=False, + ap_read=False, + ap_port='/dev/ttyUSB0', + ap_baud='115200', + ap_cmd_6g='wl -i wl2 bs_data', + ap_cmd_5g='wl -i wl1 bs_data', + ap_cmd_2g='wl -i wl0 bs_data', + ap_chanim_cmd_6g='wl -i wl2 chanim_stats', + ap_chanim_cmd_5g='wl -i wl1 chanim_stats', + ap_chanim_cmd_2g='wl -i wl0 chanim_stats', + ap_test_mode=False, + _exit_on_error=False, + _exit_on_fail=False, + _proxy_str=None, + _capture_signal_list=[]): + super().__init__(lfclient_host=lfclient_host, + lfclient_port=lfclient_port, + debug_=debug, + _exit_on_error=_exit_on_error, + _exit_on_fail=_exit_on_fail, + _proxy_str=_proxy_str, + _capture_signal_list=_capture_signal_list) + self.influxdb = influxdb + self.tos = tos.split(",") + self.endp_types = endp_types.split(",") + self.side_b = side_b + self.side_a = side_a + # if it is a dataplane test the side_a is not none and an ethernet port + if self.side_a is not None: + self.dataplane = True + else: + self.dataplane = False + self.ssid_list = ssid_list + self.ssid_password_list = ssid_password_list + self.station_lists = station_lists + self.ssid_security_list = ssid_security_list + self.reset_port_enable_list = reset_port_enable_list + self.reset_port_time_min_list = reset_port_time_min_list + self.reset_port_time_max_list = reset_port_time_max_list + self.number_template = number_template + self.name_prefix = name_prefix + self.test_duration = test_duration + self.radio_name_list = radio_name_list + self.number_of_stations_per_radio_list = number_of_stations_per_radio_list + #self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port, debug_=debug_on) + self.polling_interval_seconds = self.duration_time_to_seconds(polling_interval) + self.cx_profile = self.new_l3_cx_profile() + self.multicast_profile = self.new_multicast_profile() + self.multicast_profile.name_prefix = "MLT-" + self.station_profiles = [] + self.args = args + self.outfile = outfile + self.csv_started = False + self.epoch_time = int(time.time()) + self.debug = debug + self.mconn = mconn + self.user_tags = user_tags + + self.side_a_min_rate = side_a_min_rate + self.side_a_max_rate = side_a_max_rate + self.side_b_min_rate = side_b_min_rate + self.side_b_max_rate = side_b_max_rate + + self.side_a_min_pdu = side_a_min_pdu + self.side_a_max_pdu = side_a_max_pdu + self.side_b_min_pdu = side_b_min_pdu + self.side_b_max_pdu = side_b_max_pdu + + self.rates_are_totals = rates_are_totals + self.cx_count = 0 + self.station_count = 0 + + self.attenuators = attenuators + self.atten_vals = atten_vals + if ((len(self.atten_vals) > 0) and (self.atten_vals[0] != -1) and (len(self.attenuators) == 0)): + print("ERROR: Attenuation values configured, but no Attenuator EIDs specified.\n") + exit(1) + + self.cx_profile.mconn = mconn + self.cx_profile.side_a_min_bps = side_a_min_rate[0] + self.cx_profile.side_a_max_bps = side_a_max_rate[0] + self.cx_profile.side_b_min_bps = side_b_min_rate[0] + self.cx_profile.side_b_max_bps = side_b_max_rate[0] + + self.ap_scheduler_stats = ap_scheduler_stats + self.ap_ofdma_stats = ap_ofdma_stats + self.ap_read = ap_read + self.ap_port = ap_port + self.ap_baud = ap_baud + self.ap_cmd_6g = ap_cmd_6g + self.ap_cmd_5g = ap_cmd_5g + self.ap_cmd_2g = ap_cmd_2g + self.ap_chanim_cmd_6g = ap_chanim_cmd_6g + self.ap_chanim_cmd_5g = ap_chanim_cmd_5g + self.ap_chanim_cmd_2g = ap_chanim_cmd_2g + self.ap_test_mode = ap_test_mode + self.ap_6g_umsched = "" + self.ap_6g_msched = "" + self.ap_5g_umsched = "" + self.ap_5g_msched = "" + self.ap_24g_umsched = "" + self.ap_24g_msched = "" + self.ap_ofdma_6g = "" + self.ap_ofdma_5g = "" + self.ap_ofdma_24g = "" + + # Lookup key is port-eid name + self.port_csv_files = {} + self.port_csv_writers = {} + + # TODO: cmd-line arg to enable/disable these stats. + self.ap_stats_col_titles = ["Station Address", "PHY Mbps", "Data Mbps", "Air Use", "Data Use", + "Retries", "bw", "mcs", "Nss", "ofdma", "mu-mimo", "channel utilization"] + + dur = self.duration_time_to_seconds(self.test_duration) + + if (self.polling_interval_seconds > dur + 1): + self.polling_interval_seconds = dur - 1 + + # Full spread-sheet data + if self.outfile is not None: + kpi = self.outfile[:-4] + kpi = kpi + "-kpi.csv" + self.csv_kpi_file = open(kpi, "w") + self.csv_kpi_writer = csv.writer(self.csv_kpi_file, delimiter=",") + + # if it is a dataplane test the side_a is not None and an ethernet port + # if side_a is None then side_a is radios + if self.dataplane == False: + for (radio_, ssid_, ssid_password_, ssid_security_, + reset_port_enable_, reset_port_time_min_, reset_port_time_max_) \ + in zip(radio_name_list, ssid_list, ssid_password_list, ssid_security_list, + reset_port_enable_list, reset_port_time_min_list, reset_port_time_max_list): + self.station_profile = self.new_station_profile() + self.station_profile.lfclient_url = self.lfclient_url + self.station_profile.ssid = ssid_ + self.station_profile.ssid_pass = ssid_password_ + self.station_profile.security = ssid_security_ + self.station_profile.number_template = self.number_template + self.station_profile.mode = 0 + self.station_profile.set_reset_extra(reset_port_enable=reset_port_enable_, + test_duration=self.duration_time_to_seconds(self.test_duration), + reset_port_min_time=self.duration_time_to_seconds(reset_port_time_min_), + reset_port_max_time=self.duration_time_to_seconds(reset_port_time_max_)) + self.station_profiles.append(self.station_profile) + else: + pass + + self.multicast_profile.host = self.lfclient_host + self.cx_profile.host = self.lfclient_host + self.cx_profile.port = self.lfclient_port + self.cx_profile.name_prefix = self.name_prefix + + def get_ap_6g_umsched(self): + return self.ap_6g_umsched + + def get_ap_6g_msched(self): + return self.ap_6g_msched + + def get_ap_5g_umsched(self): + return self.ap_5g_umsched + + def get_ap_5g_msched(self): + return self.ap_5g_msched + + def get_ap_24g_umsched(self): + return self.ap_5g_umsched + + def get_ap_24g_msched(self): + return self.ap_5g_msched + + def get_ap_ofdma_6g(self): + return self.ap_ofdma_6g + + def get_ap_ofdma_5g(self): + return self.ap_ofdma_5g + + def get_ap_ofdma_24g(self): + return self.ap_ofdma_24g + + def get_kpi_csv(self): + #print("self.csv_kpi_file {}".format(self.csv_kpi_file.name)) + return self.csv_kpi_file.name + + # Find avg latency, jitter for connections using specified port. + def get_endp_stats_for_port(self, eid_name, endps): + lat = 0 + jit = 0 + total_dl_rate = 0 + total_dl_rate_ll = 0 + total_dl_pkts_ll = 0 + total_ul_rate = 0 + total_ul_rate_ll = 0 + total_ul_pkts_ll = 0 + count = 0 + sta_name = 'no_station' + + #print("endp-stats-for-port, port-eid: {}".format(eid_name)) + eid = self.name_to_eid(eid_name) + print("eid_name: {eid_name} eid: {eid}".format(eid_name=eid_name, eid=eid)) + + # Convert all eid elements to strings + eid[0] = str(eid[0]) + eid[1] = str(eid[1]) + eid[2] = str(eid[2]) + + for endp in endps: + pprint(endp) + eid_endp = endp["eid"].split(".") + print("Comparing eid:{eid} to endp-id {eid_endp}".format(eid=eid, eid_endp=eid_endp)) + # Look through all the endpoints (endps), to find the port the eid_name is using. + # The eid_name that has the same Shelf, Resource, and Port as the eid_endp (looking at all the endps) + # Then read the eid_endp to get the delay, jitter and rx rate + # Note: the endp eid is shelf.resource.port.endp-id, the eid can be treated somewhat as + # child class of port-eid , and look up the port the eid is using. + if eid[0] == eid_endp[0] and eid[1] == eid_endp[1] and eid[2] == eid_endp[2]: + lat += int(endp["delay"]) + jit += int(endp["jitter"]) + name = endp["name"] + print("endp name {name}".format(name=name)) + sta_name = name.replace('-A', '') + # only the -A endpoint will be found so need to look + + count += 1 + print("Matched: name: {name} eid:{eid} to endp-id {eid_endp}".format(name=name, eid=eid, eid_endp=eid_endp)) + else: + name = endp["name"] + print("No Match: name: {name} eid:{eid} to endp-id {eid_endp}".format(name=name, eid=eid, eid_endp=eid_endp)) + + if count > 1: + lat = int(lat / count) + jit = int(jit / count) + + # need to loop though again to find the upload and download per station if the name matched + for endp in endps: + if sta_name in endp["name"]: + name = endp["name"] + if name.endswith("-A"): + print("name has -A") + total_dl_rate += int(endp["rx rate"]) + total_dl_rate_ll += int(endp["rx rate ll"]) + total_dl_pkts_ll += int(endp["rx pkts ll"]) + # -B upload side + else: + total_ul_rate += int(endp["rx rate"]) + total_ul_rate_ll += int(endp["rx rate ll"]) + total_ul_pkts_ll += int(endp["rx pkts ll"]) + + return lat, jit, total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll + + # Query all endpoints to generate rx and other stats, returned + # as an array of objects. + def __get_rx_values(self): + endp_list = self.json_get("endp?fields=name,eid,delay,jitter,rx+rate,rx+rate+ll,rx+bytes,rx+drop+%25,rx+pkts+ll", debug_=False) + endp_rx_drop_map = {} + endp_rx_map = {} + our_endps = {} + endps = [] + + total_ul = 0 + total_ul_ll = 0 + total_dl = 0 + total_dl_ll = 0 + + for e in self.multicast_profile.get_mc_names(): + our_endps[e] = e + for e in self.cx_profile.created_endp.keys(): + our_endps[e] = e + for endp_name in endp_list['endpoint']: + if endp_name != 'uri' and endp_name != 'handler': + for item, value in endp_name.items(): + if item in our_endps: + endps.append(value) + print("endpoint: ", item, " value:\n") + pprint(value) + + for value_name, value in value.items(): + if value_name == 'rx bytes': + endp_rx_map[item] = value + if value_name == 'rx rate': + endp_rx_map[item] = value + if value_name == 'rx rate ll': + endp_rx_map[item] = value + if value_name == 'rx pkts ll': + endp_rx_map[item] = value + if value_name == 'rx drop %': + endp_rx_drop_map[item] = value + if value_name == 'rx rate': + # This hack breaks for mcast or if someone names endpoints weirdly. + #print("item: ", item, " rx-bps: ", value_rx_bps) + if item.endswith("-A"): + total_dl += int(value) + else: + total_ul += int(value) + if value_name == 'rx rate ll': + # This hack breaks for mcast or if someone names endpoints weirdly. + if item.endswith("-A"): + total_dl_ll += int(value) + else: + total_ul_ll += int(value) + + #print("total-dl: ", total_dl, " total-ul: ", total_ul, "\n") + return endp_rx_map, endp_rx_drop_map, endps, total_dl, total_ul, total_dl_ll, total_ul_ll + # This script supports resetting ports, allowing one to test AP/controller under data load + # while bouncing wifi stations. Check here to see if we should reset ports. + + def reset_port_check(self): + for station_profile in self.station_profiles: + if station_profile.reset_port_extra_data['reset_port_enable']: + if not station_profile.reset_port_extra_data['reset_port_timer_started']: + print("reset_port_timer_started {}".format(station_profile.reset_port_extra_data['reset_port_timer_started'])) + print("reset_port_time_min: {}".format(station_profile.reset_port_extra_data['reset_port_time_min'])) + print("reset_port_time_max: {}".format(station_profile.reset_port_extra_data['reset_port_time_max'])) + station_profile.reset_port_extra_data['seconds_till_reset'] = \ + random.randint(station_profile.reset_port_extra_data['reset_port_time_min'], + station_profile.reset_port_extra_data['reset_port_time_max']) + station_profile.reset_port_extra_data['reset_port_timer_started'] = True + print( + "on radio {} seconds_till_reset {}".format( + station_profile.add_sta_data['radio'], + station_profile.reset_port_extra_data['seconds_till_reset'])) + else: + station_profile.reset_port_extra_data['seconds_till_reset'] = station_profile.reset_port_extra_data['seconds_till_reset'] - 1 + print( + "radio: {} countdown seconds_till_reset {}".format( + station_profile.add_sta_data['radio'], + station_profile.reset_port_extra_data['seconds_till_reset'])) + if ((station_profile.reset_port_extra_data['seconds_till_reset'] <= 0)): + station_profile.reset_port_extra_data['reset_port_timer_started'] = False + port_to_reset = random.randint(0, len(station_profile.station_names) - 1) + print( + "reset on radio {} station: {}".format( + station_profile.add_sta_data['radio'], + station_profile.station_names[port_to_reset])) + self.reset_port(station_profile.station_names[port_to_reset]) + + # Common code to generate timestamp for CSV files. + def time_stamp(self): + return time.strftime('%m_%d_%Y_%H_%M_%S', time.localtime(self.epoch_time)) + + # Cleanup any older config that a previous run of this test may have created. + def pre_cleanup(self): + self.cx_profile.cleanup_prefix() + self.multicast_profile.cleanup_prefix() + self.total_stas = 0 + for station_list in self.station_lists: + for sta in station_list: + self.rm_port(sta, check_exists=True) + self.total_stas += 1 + + # Make sure they are gone + count = 0 + while (count < 10): + more = False + for station_list in self.station_lists: + for sta in station_list: + rv = self.rm_port(sta, check_exists=True) + if (rv): + more = True + if not more: + break + count += 1 + time.sleep(5) + + def gather_port_eids(self): + rv = [self.side_b] + + for station_profile in self.station_profiles: + rv = rv + station_profile.station_names + + return rv + + # Create stations and connections/endpoints. If rebuild is true, then + # only update connections/endpoints. + def build(self, rebuild=False): + index = 0 + self.station_count = 0 + self.udp_endps = [] + self.tcp_endps = [] + self.eth_endps = [] + + if rebuild: + # if we are just re-applying new cx values, then no need to rebuild + # stations, so allow skipping it. + # Do clean cx lists so that when we re-apply them we get same endp name + # as we had previously + #print("rebuild: Clearing cx profile lists.\n") + self.cx_profile.clean_cx_lists() + self.multicast_profile.clean_mc_lists() + + if self.dataplane: + for etype in self.endp_types: + for _tos in self.tos: + print("Creating connections for endpoint type: %s TOS: %s cx-count: %s" % (etype, _tos, self.cx_profile.get_cx_count())) + # use brackes on [self.side_a] to make it a list + these_cx, these_endp = self.cx_profile.create(endp_type=etype, side_a=[self.side_a], + side_b=self.side_b, sleep_time=0, tos=_tos) + if (etype == "lf_udp" or etype == "lf_udp6"): + self.udp_endps = self.udp_endps + these_endp + elif(etype == "lf"): + self.lf_endps = self.eth_endps + these_endp + else: + self.tcp_endps = self.tcp_endps + these_endp + + else: + for station_profile in self.station_profiles: + if not rebuild: + station_profile.use_security(station_profile.security, station_profile.ssid, station_profile.ssid_pass) + station_profile.set_number_template(station_profile.number_template) + print("Creating stations on radio %s" % (self.radio_name_list[index])) + + station_profile.create(radio=self.radio_name_list[index], sta_names_=self.station_lists[index], debug=self.debug, sleep_time=0) + index += 1 + + self.station_count += len(station_profile.station_names) + + # Build/update connection types + for etype in self.endp_types: + if etype == "mc_udp" or etype == "mc_udp6": + print("Creating Multicast connections for endpoint type: %s" % (etype)) + self.multicast_profile.create_mc_tx(etype, self.side_b, etype) + self.multicast_profile.create_mc_rx(etype, side_rx=station_profile.station_names) + else: + for _tos in self.tos: + print("Creating connections for endpoint type: %s TOS: %s cx-count: %s" % (etype, _tos, self.cx_profile.get_cx_count())) + these_cx, these_endp = self.cx_profile.create(endp_type=etype, side_a=station_profile.station_names, + side_b=self.side_b, sleep_time=0, tos=_tos) + if (etype == "lf_udp" or etype == "lf_udp6"): + self.udp_endps = self.udp_endps + these_endp + else: + self.tcp_endps = self.tcp_endps + these_endp + + self.cx_count = self.cx_profile.get_cx_count() + + if self.dataplane == True: + self._pass("PASS: CX build finished: created/updated: %s connections." % (self.cx_count)) + else: + self._pass("PASS: Stations & CX build finished: created/updated: %s stations and %s connections." % (self.station_count, self.cx_count)) + + def ap_custom_cmd(self, ap_custom_cmd): + ap_results = "" + try: + # configure the serial interface + ser = serial.Serial(self.ap_port, int(self.ap_baud), timeout=5) + ss = SerialSpawn(ser) + ss.sendline(str(ap_custom_cmd)) + ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output + ap_results = ss.before.decode('utf-8', 'ignore') + print("ap_custom_cmd: {} ap_results {}".format(ap_custom_cmd, ap_results)) + except BaseException: + print("ap_custom_cmd: {} WARNING unable to read AP ".format(ap_custom_cmd)) + + return ap_results + + def read_ap_stats_6g(self): + # 6ghz: wl -i wl2 bs_data + ap_stats_6g = "" + try: + # configure the serial interface + ser = serial.Serial(self.ap_port, int(self.ap_baud), timeout=5) + ss = SerialSpawn(ser) + ss.sendline(str(self.ap_cmd_6g)) + ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output + ap_stats_6g = ss.before.decode('utf-8', 'ignore') + print("ap_stats_6g from AP: {}".format(ap_stats_6g)) + + except BaseException: + print("WARNING: ap_stats_6g unable to read AP") + + return ap_stats_6g + + def read_ap_stats_5g(self): + # 5ghz: wl -i wl1 bs_data + ap_stats_5g = "" + try: + # configure the serial interface + ser = serial.Serial(self.ap_port, int(self.ap_baud), timeout=5) + ss = SerialSpawn(ser) + ss.sendline(str(self.ap_cmd_5g)) + ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output + ap_stats_5g = ss.before.decode('utf-8', 'ignore') + print("ap_stats_5g from AP: {}".format(ap_stats_5g)) + + except BaseException: + print("WARNING: ap_stats_5g unable to read AP") + + return ap_stats_5g + + def read_ap_stats_2g(self): + # 2.4ghz# wl -i wl0 bs_data + ap_stats_2g = "" + try: + # configure the serial interface + ser = serial.Serial(self.ap_port, int(self.ap_baud), timeout=5) + ss = SerialSpawn(ser) + ss.sendline(str(self.ap_cmd_2g)) + ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output + ap_stats_2g = ss.before.decode('utf-8', 'ignore') + print("ap_stats_2g from AP: {}".format(ap_stats_2g)) + + except BaseException: + print("WARNING: ap_stats_2g unable to read AP") + + return ap_stats_2g + + def read_ap_chanim_stats_6g(self): + # 5ghz: wl -i wl1 chanim_stats + ap_chanim_stats_6g = "" + try: + # configure the serial interface + ser = serial.Serial(self.ap_port, int(self.ap_baud), timeout=5) + ss = SerialSpawn(ser) + ss.sendline(str(self.ap_chanim_cmd_6g)) + ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output + ap_chanim_stats_6g = ss.before.decode('utf-8', 'ignore') + print("read_ap_chanim_stats_6g {}".format(ap_chanim_stats_6g)) + + except BaseException: + print("WARNING: read_ap_chanim_stats_6g unable to read AP") + + return ap_chanim_stats_6g + + def read_ap_chanim_stats_5g(self): + # 5ghz: wl -i wl1 chanim_stats + ap_chanim_stats_5g = "" + try: + # configure the serial interface + ser = serial.Serial(self.ap_port, int(self.ap_baud), timeout=5) + ss = SerialSpawn(ser) + ss.sendline(str(self.ap_chanim_cmd_5g)) + ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output + ap_chanim_stats_5g = ss.before.decode('utf-8', 'ignore') + print("read_ap_chanim_stats_5g {}".format(ap_chanim_stats_5g)) + + except BaseException: + print("WARNING: read_ap_chanim_stats_5g unable to read AP") + + return ap_chanim_stats_5g + + def read_ap_chanim_stats_2g(self): + # 2.4ghz# wl -i wl0 chanim_stats + ap_chanim_stats_2g = "" + try: + # configure the serial interface + ser = serial.Serial(self.ap_port, int(self.ap_baud), timeout=5) + ss = SerialSpawn(ser) + ss.sendline(str(self.ap_chanim_cmd_2g)) + ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output + ap_chanim_stats_2g = ss.before.decode('utf-8', 'ignore') + print("read_ap_chanim_stats_2g {}".format(ap_chanim_stats_2g)) + + except BaseException: + print("WARNING: read_ap_chanim_stats_2g unable to read AP") + + return ap_chanim_stats_2g + + # Run the main body of the test logic. + def start(self, print_pass=False, print_fail=False): + print("Bringing up stations") + self.admin_up(self.side_b) + for station_profile in self.station_profiles: + for sta in station_profile.station_names: + print("Bringing up station %s" % (sta)) + self.admin_up(sta) + + temp_stations_list = [] + temp_stations_list.append(self.side_b) + for station_profile in self.station_profiles: + temp_stations_list.extend(station_profile.station_names.copy()) + + if self.wait_for_ip(temp_stations_list, timeout_sec=120): + print("ip's acquired") + else: + # TODO: Allow fail and abort at this point. + print("print failed to get IP's") + + csv_header = self.csv_generate_column_headers() + # print(csv_header) + self.csv_add_column_headers(csv_header) + port_eids = self.gather_port_eids() + for eid_name in port_eids: + self.csv_add_port_column_headers(eid_name, self.csv_generate_port_column_headers()) + + # For each rate + rate_idx = 0 + for ul in self.side_a_min_rate: + dl = self.side_b_min_rate[rate_idx] + rate_idx += 1 + + # For each pdu size + pdu_idx = 0 + for ul_pdu in self.side_a_min_pdu: + dl_pdu = self.side_b_min_pdu[pdu_idx] + pdu_idx += 1 + + # Adjust rate to take into account the number of connections we have. + if self.cx_count > 1 and self.rates_are_totals: + # Convert from string to int to do math, then back to string + # as that is what the cx_profile wants. + ul = str(int(int(ul) / self.cx_count)) + dl = str(int(int(dl) / self.cx_count)) + + dl_pdu_str = dl_pdu + ul_pdu_str = ul_pdu + + if (ul_pdu == "AUTO" or ul_pdu == "MTU"): + ul_pdu = "-1" + + if (dl_pdu == "AUTO" or dl_pdu == "MTU"): + dl_pdu = "-1" + + print("ul: %s dl: %s cx-count: %s rates-are-totals: %s\n" % (ul, dl, self.cx_count, self.rates_are_totals)) + + # Set rate and pdu size config + self.cx_profile.side_a_min_bps = ul + self.cx_profile.side_a_max_bps = ul + self.cx_profile.side_b_min_bps = dl + self.cx_profile.side_b_max_bps = dl + + self.cx_profile.side_a_min_pdu = ul_pdu + self.cx_profile.side_a_max_pdu = ul_pdu + self.cx_profile.side_b_min_pdu = dl_pdu + self.cx_profile.side_b_max_pdu = dl_pdu + + # Update connections with the new rate and pdu size config. + self.build(rebuild=True) + + if self.ap_scheduler_stats or self.ap_ofdma_stats: + self.ap_custom_cmd('wl -i wl2 dump_clear') + self.ap_custom_cmd('wl -i wl1 dump_clear') + self.ap_custom_cmd('wl -i wl0 dump_clear') + + for atten_val in self.atten_vals: + if atten_val != -1: + for atten_idx in self.attenuators: + self.set_atten(atten_idx, atten_val) + + print("Starting multicast traffic (if any configured)") + self.multicast_profile.start_mc(debug_=self.debug) + self.multicast_profile.refresh_mc(debug_=self.debug) + print("Starting layer-3 traffic (if any configured)") + self.cx_profile.start_cx() + self.cx_profile.refresh_cx() + + cur_time = datetime.datetime.now() + print("Getting initial values.") + old_rx_values, rx_drop_percent, endps, total_dl_bps, total_ul_bps, total_dl_ll_bps, total_ul_ll_bps = self.__get_rx_values() + + end_time = self.parse_time(self.test_duration) + cur_time + + print("Monitoring throughput for duration: %s" % (self.test_duration)) + + # Monitor test for the interval duration. + passes = 0 + expected_passes = 0 + total_dl_bps = 0 + total_ul_bps = 0 + total_dl_ll_bps = 0 + total_ul_ll_bps = 0 + endps = [] + ap_row = [] + ap_stats_col_titles = [] + mac_found_5g = False + mac_found_2g = False + reset_timer = 0 + + while cur_time < end_time: + #interval_time = cur_time + datetime.timedelta(seconds=5) + interval_time = cur_time + datetime.timedelta(seconds=self.polling_interval_seconds) + #print("polling_interval_seconds {}".format(self.polling_interval_seconds)) + + while cur_time < interval_time: + cur_time = datetime.datetime.now() + time.sleep(.2) + reset_timer += 1 + if reset_timer % 5 is 0: + self.reset_port_check() + + self.epoch_time = int(time.time()) + new_rx_values, rx_drop_percent, endps, total_dl_bps, total_ul_bps, total_dl_ll_bps, total_ul_ll_bps = self.__get_rx_values() + + print( + "main loop, total-dl: ", + total_dl_bps, + " total-ul: ", + total_ul_bps, + " total-dl-ll: ", + total_dl_ll_bps, + " total-ul-ll: ", + total_ul_ll_bps) + + # AP OUTPUT + if self.ap_read: + # 6G test mode + if self.ap_test_mode: + # Create the test data as a continuous string + ap_stats_6g = "{}{}{}{}{}{}".format("root@Docsis-Gateway:~# wl -i wl2 bs_data\n", + "Station Address PHY Mbps Data Mbps Air Use Data Use Retries bw mcs Nss ofdma mu-mimo\n", + "04:f0:21:82:2f:d6 1016.6 48.9 6.5% 24.4% 16.6% 80 9.7 2 0.0% 0.0%\n", + "50:E0:85:84:7A:E7 880.9 52.2 7.7% 26.1% 20.0% 80 8.5 2 0.0% 0.0%\n", + "50:E0:85:89:5D:00 840.0 47.6 6.4% 23.8% 2.3% 80 8.0 2 0.0% 0.0%\n", + "50:E0:85:87:5B:F4 960.7 51.5 5.9% 25.7% 0.0% 80 9 2 0.0% 0.0%\n") + #Keep commented for testing "- note the MAC will match ap_stats.append((overall) - 200.2 26.5% - - \n") + print("ap_stats 6g{}".format(ap_stats_6g)) + + # Create the test data as a continuous string + ap_chanim_stats_6g = "{}{}{}{}".format("root@Docsis-Gateway:~# wl -i wl2 chanim_stats\n", + "version: 3\n", + "chanspec tx inbss obss nocat nopkt doze txop goodtx badtx glitch badplcp knoise idle timestamp\n", + # `"0xe06a 61 15 0 17 0 0 6 53 2 0 0 -91 65 343370578\n") + '0xe06a\t41.82\t20.22\t0.00\t13.56\t0.02\t0.00\t17.58\t29.54\t1.94\t3\t0\t-90\t58\t146903490\n') + # "0xe06a 1.67 15.00 0.00 17.00 0.00 0.00 97.33 53.00 2.00 0 0 -91 65 343370578\n") + + else: + # read from the AP 6g + ap_stats_6g = self.read_ap_stats_6g() + ap_chanim_stats_6g = self.read_ap_chanim_stats_6g() + + ap_stats_6g_rows = ap_stats_6g.splitlines() + print("From AP stats: ap_stats_6g_rows {}".format(ap_stats_6g_rows)) + + ap_chanim_stats_rows_6g = ap_chanim_stats_6g.splitlines() + print("From AP chanim: ap_chanim_stats_rows_6g {}".format(ap_chanim_stats_rows_6g)) + channel_utilization = 0 + + # Query all of our ports + # Note: the endp eid is the shelf.resource.port.endp-id + port_eids = self.gather_port_eids() + for eid_name in port_eids: + eid = self.name_to_eid(eid_name) + url = "/port/%s/%s/%s" % (eid[0], eid[1], eid[2]) + # read LANforge to get the mac + response = self.json_get(url) + if (response is None) or ("interface" not in response): + print("6g query-port: %s: incomplete response:" % (url)) + pprint(response) + else: + # print("response".format(response)) + pprint(response) + p = response['interface'] + print("#### 6g From LANforge: p, response['insterface']:{}".format(p)) + mac = p['mac'] + # print("#### From LANforge: p['mac']: {mac}".format(mac=mac)) + + # Parse the ap stats to find the matching mac then use that row for reporting + for row in ap_stats_6g_rows: + split_row = row.split() + #print("split_row {}".format(split_row)) + #print("split_row[0] {} mac {}".format(split_row[0].lower(),mac.lower())) + if self.ap_test_mode: + if split_row[0].lower() != mac.lower(): + ap_row = split_row + mac_found_6g = True + else: + try: + # split_row[0].lower() , mac from AP + # mac.lower() , mac from LANforge + if split_row[0].lower() == mac.lower(): + ap_row = split_row + mac_found_6g = True + except BaseException: + print("6g 'No stations are currently associated.'? from AP") + print(" since possibly no stations: excption on compare split_row[0].lower() ") + if mac_found_6g == True: + mac_found_6g = False + print("6g selected ap_row (from split_row): {}".format(ap_row)) + + # Find latency, jitter for connections using this port. + latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll = self.get_endp_stats_for_port( + p["port"], endps) + + # now report the ap_chanim_stats along side of the ap_stats_6g + xtop_reported = False + for row in ap_chanim_stats_rows_6g: + split_row = row.split() + if xtop_reported: + print("6g xtop_reported row: {row}".format(row=row)) + print("6g xtop_reported split_row: {split_row}".format(split_row=split_row)) + try: + xtop = split_row[7] + print("6g xtop {xtop}".format(xtop=xtop)) + except BaseException: + print("6g detected chanspec with reading chanim_stats, exception reading xtop") + + try: + channel_utilization = float(100) - float(xtop) + print("6g channel_utilization {utilization}".format(utilization=channel_utilization)) + except BaseException: + print("6g detected chanspec with reading chanim_stats, failed calcluating channel_utilization from xtop") + # should be only one channel utilization + break + else: + try: + if split_row[0].lower() == 'chanspec': + print("6g chanspec found xtop_reported = True") + xtop_reported = True + except BaseException: + print("6g Error reading xtop") + # ap information is passed with ap_row so all information needs to be contained in ap_row + ap_row.append(str(channel_utilization)) + print("6g channel_utilization {channel_utilization}".format(channel_utilization=channel_utilization)) + print("6g ap_row {ap_row}".format(ap_row=ap_row)) + + ap_stats_6g_col_titles = ['Station Address', 'PHY Mbps', 'Data Mbps', 'Air Use', + 'Data Use', 'Retries', 'bw', 'mcs', 'Nss', 'ofdma', 'mu-mimo', 'channel_utilization'] + + self.write_port_csv(len(temp_stations_list), ul, dl, ul_pdu_str, dl_pdu_str, atten_val, eid_name, p, + latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, + total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll, ap_row, ap_stats_6g_col_titles) # ap_stats_5g_col_titles used as a length + # 5G test mode + if self.ap_test_mode: + # Create the test data as a continuous string + ap_stats_5g = "{}{}{}{}{}{}".format("root@Docsis-Gateway:~# wl -i wl1 bs_data\n", + "Station Address PHY Mbps Data Mbps Air Use Data Use Retries bw mcs Nss ofdma mu-mimo\n", + "04:f0:21:82:2f:d6 1016.6 48.9 6.5% 24.4% 16.6% 80 9.7 2 0.0% 0.0%\n", + "50:E0:85:84:7A:E7 880.9 52.2 7.7% 26.1% 20.0% 80 8.5 2 0.0% 0.0%\n", + "50:E0:85:89:5D:00 840.0 47.6 6.4% 23.8% 2.3% 80 8.0 2 0.0% 0.0%\n", + "50:E0:85:87:5B:F4 960.7 51.5 5.9% 25.7% 0.0% 80 9 2 0.0% 0.0%\n") + #Keep Commented for Testing "- note the MAC will match ap_stats.append((overall) - 200.2 26.5% - - \n") + print("ap_stats 5g {}".format(ap_stats_5g)) + + # Create the test data as a continuous string + ap_chanim_stats_5g = "{}{}{}{}".format("root@Docsis-Gateway:~# wl -i wl1 chanim_stats\n", + "version: 3\n", + "chanspec tx inbss obss nocat nopkt doze txop goodtx badtx glitch badplcp knoise idle timestamp\n", + # `"0xe06a 61 15 0 17 0 0 6 53 2 0 0 -91 65 343370578\n") + '0xe06a\t41.82\t20.22\t0.00\t13.56\t0.02\t0.00\t17.58\t29.54\t1.94\t3\t0\t-90\t58\t146903490\n') + # "0xe06a 1.67 15.00 0.00 17.00 0.00 0.00 97.33 53.00 2.00 0 0 -91 65 343370578\n") + + else: + # read from the AP + ap_stats_5g = self.read_ap_stats_5g() + ap_chanim_stats_5g = self.read_ap_chanim_stats_5g() + + ap_stats_5g_rows = ap_stats_5g.splitlines() + print("From AP stats: ap_stats_5g_rows {}".format(ap_stats_5g_rows)) + + ap_chanim_stats_rows_5g = ap_chanim_stats_5g.splitlines() + print("From AP chanim: ap_chanim_stats_rows_5g {}".format(ap_chanim_stats_rows_5g)) + channel_utilization = 0 + + # Query all of our ports + # Note: the endp eid is the shelf.resource.port.endp-id + port_eids = self.gather_port_eids() + for eid_name in port_eids: + eid = self.name_to_eid(eid_name) + url = "/port/%s/%s/%s" % (eid[0], eid[1], eid[2]) + # read LANforge to get the mac + response = self.json_get(url) + if (response is None) or ("interface" not in response): + print("query-port 5g: %s: incomplete response:" % (url)) + pprint(response) + else: + # print("response".format(response)) + pprint(response) + p = response['interface'] + print("#### From LANforge: p, response['insterface']:{}".format(p)) + mac = p['mac'] + # print("#### From LANforge: p['mac']: {mac}".format(mac=mac)) + + # Parse the ap stats to find the matching mac then use that row for reporting + for row in ap_stats_5g_rows: + split_row = row.split() + #print("split_row {}".format(split_row)) + #print("split_row[0] {} mac {}".format(split_row[0].lower(),mac.lower())) + if self.ap_test_mode: + if split_row[0].lower() != mac.lower(): + ap_row = split_row + mac_found_5g = True + else: + try: + # split_row[0].lower() , mac from AP + # mac.lower() , mac from LANforge + if split_row[0].lower() == mac.lower(): + ap_row = split_row + mac_found_5g = True + except BaseException: + print("5g 'No stations are currently associated.'? from AP") + print("5g since possibly no stations: excption on compare split_row[0].lower() ") + if mac_found_5g == True: + mac_found_5g = False + print("5g selected ap_row (from split_row): {}".format(ap_row)) + + # Find latency, jitter for connections using this port. + latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll = self.get_endp_stats_for_port( + p["port"], endps) + + # now report the ap_chanim_stats along side of the ap_stats_5g + xtop_reported = False + for row in ap_chanim_stats_rows_5g: + split_row = row.split() + if xtop_reported: + print("xtop_reported 5g row: {row}".format(row=row)) + print("xtop_reported 5g split_row: {split_row}".format(split_row=split_row)) + try: + xtop = split_row[7] + print("5g xtop {xtop}".format(xtop=xtop)) + except BaseException: + print("5g detected chanspec with reading chanim_stats, exception reading xtop") + + try: + channel_utilization = float(100) - float(xtop) + print("5g channel_utilization {utilization}".format(utilization=channel_utilization)) + except BaseException: + print("5g detected chanspec with reading chanim_stats, failed calcluating channel_utilization from xtop") + # should be only one channel utilization + break + else: + try: + if split_row[0].lower() == 'chanspec': + print("5g chanspec found xtop_reported = True") + xtop_reported = True + except BaseException: + print("5g Error reading xtop") + # ap information is passed with ap_row so all information needs to be contained in ap_row + ap_row.append(str(channel_utilization)) + print("5g channel_utilization {channel_utilization}".format(channel_utilization=channel_utilization)) + print("5g ap_row {ap_row}".format(ap_row=ap_row)) + + ap_stats_5g_col_titles = ['Station Address', 'PHY Mbps', 'Data Mbps', 'Air Use', + 'Data Use', 'Retries', 'bw', 'mcs', 'Nss', 'ofdma', 'mu-mimo', 'channel_utilization'] + + self.write_port_csv(len(temp_stations_list), ul, dl, ul_pdu_str, dl_pdu_str, atten_val, eid_name, p, + latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, + total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll, ap_row, ap_stats_5g_col_titles) # ap_stats_5g_col_titles used as a length + # 2g test mode + if self.ap_test_mode: + # Create the test data as a continuous string + ap_stats_2g = "{}{}{}{}{}{}{}".format("root@Docsis-Gateway:~# wl -i wl0 bs_data\n", + "Station Address PHY Mbps Data Mbps Air Use Data Use Retries bw mcs Nss ofdma mu-mimo\n", + "04:f0:21:82:2f:d6 1016.6 48.9 6.5% 24.4% 16.6% 80 9.7 2 0.0% 0.0%\n", + "50:E0:85:84:7A:E7 880.9 52.2 7.7% 26.1% 20.0% 80 8.5 2 0.0% 0.0%\n", + "50:E0:85:89:5D:00 840.0 47.6 6.4% 23.8% 2.3% 80 8.0 2 0.0% 0.0%\n", + "50:E0:85:87:5B:F4 960.7 51.5 5.9% 25.7% 0.0% 80 9 2 0.0% 0.0%\n", + "- note the MAC will match ap_stats_2g.append((overall) - 200.2 26.5% - - \n") + print("ap_stats_2g {}".format(ap_stats_2g)) + + # Create the test data as a continuous string + ap_chanim_stats_2g = "{}{}{}{}".format("root@Docsis-Gateway:~# wl -i wl1 chanim_stats\n", + "version: 3\n", + "chanspec tx inbss obss nocat nopkt doze txop goodtx badtx glitch badplcp knoise idle timestamp\n", + # "0xe06a 62 15 0 17 0 0 6 53 2 0 0 -91 65 343370578\n") + '0xe06a\t41.82\t20.22\t0.00\t13.56\t0.02\t0.00\t17.58\t29.54\t1.94\t3\t0\t-90\t58\t146903490\n') + # "0xe06a 1.67 15.00 0.00 17.00 0.00 0.00 97.33 53.00 2.00 0 0 -91 65 343370578\n") + else: + # read from the AP + ap_stats_2g = self.read_ap_stats_2g() + ap_chanim_stats_2g = self.read_ap_chanim_stats_2g() + + ap_stats_2g_rows = ap_stats_2g.splitlines() + print("From AP stats: ap_stats_2g_rows {}".format(ap_stats_2g_rows)) + + ap_chanim_stats_rows_2g = ap_chanim_stats_2g.splitlines() + print("From AP chanim: ap_chanim_stats_rows_2g {}".format(ap_chanim_stats_rows_2g)) + channel_utilization = 0 + + # Query all of our ports + # Note: the endp eid is the shelf.resource.port.endp-id + port_eids = self.gather_port_eids() + for eid_name in port_eids: + eid = self.name_to_eid(eid_name) + url = "/port/%s/%s/%s" % (eid[0], eid[1], eid[2]) + # read LANforge to get the mac + response = self.json_get(url) + if (response is None) or ("interface" not in response): + print("2g query-port: %s: incomplete response:" % (url)) + pprint(response) + else: + # print("response".format(response)) + pprint(response) + p = response['interface'] + # print("#### From LANforge: p, response['insterface']:{}".format(p)) + mac = p['mac'] + # print("#### From LANforge: p['mac']: {mac}".format(mac=mac)) + + # Parse the ap stats to find the matching mac then use that row for reporting + for row in ap_stats_2g_rows: + split_row = row.split() + #print("split_row {}".format(split_row)) + #print("split_row[0] {} mac {}".format(split_row[0].lower(),mac.lower())) + if self.ap_test_mode: + if split_row[0].lower() != mac.lower(): + ap_row = split_row + mac_found_2g = True + else: + try: + # split_row[0].lower() , mac from AP + # mac.lower() , mac from LANforge + if split_row[0].lower() == mac.lower(): + ap_row = split_row + mac_found_2g = True + except BaseException: + print("2g 'No stations are currently associated.'? from AP") + print("2g since possibly no stations: excption on compare split_row[0].lower() ") + if mac_found_2g == True: + mac_found_2g = False + print("2g selected ap_row (from split_row): {}".format(ap_row)) + + # Find latency, jitter for connections using this port. + latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll = self.get_endp_stats_for_port( + p["port"], endps) + + # now report the ap_chanim_stats along side of the ap_stats_2g + xtop_reported = False + for row in ap_chanim_stats_rows_2g: + split_row = row.split() + if xtop_reported: + print("2g xtop_reported row: {row}".format(row=row)) + print("2g xtop_reported split_row: {split_row}".format(split_row=split_row)) + try: + xtop = split_row[7] + print("2g xtop {xtop}".format(xtop=xtop)) + except BaseException: + print("2g detected chanspec with reading chanim_stats, exception reading xtop") + + try: + channel_utilization = float(100) - float(xtop) + print("2g channel_utilization {utilization}".format(utilization=channel_utilization)) + except BaseException: + print("2g detected chanspec with reading chanim_stats, failed calcluating channel_utilization from xtop") + # should be only one channel utilization + break + else: + try: + if split_row[0].lower() == 'chanspec': + print("2g chanspec found xtop_reported = True") + xtop_reported = True + except BaseException: + print("2g Error reading xtop") + # ap information is passed with ap_row so all information needs to be contained in ap_row + ap_row.append(str(channel_utilization)) + print("2g channel_utilization {channel_utilization}".format(channel_utilization=channel_utilization)) + print("2g ap_row {ap_row}".format(ap_row=ap_row)) + + ap_stats_2g_col_titles = ['Station Address', 'PHY Mbps', 'Data Mbps', 'Air Use', + 'Data Use', 'Retries', 'bw', 'mcs', 'Nss', 'ofdma', 'mu-mimo', 'channel_utilization'] + + self.write_port_csv(len(temp_stations_list), ul, dl, ul_pdu_str, dl_pdu_str, atten_val, eid_name, p, + latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, + total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll, ap_row, ap_stats_2g_col_titles) # ap_stats_2g_col_titles used as a length + + else: + + # Query all of our ports + # Note: the endp eid is the shelf.resource.port.endp-id + port_eids = self.gather_port_eids() + for eid_name in port_eids: + eid = self.name_to_eid(eid_name) + url = "/port/%s/%s/%s" % (eid[0], eid[1], eid[2]) + response = self.json_get(url) + if (response is None) or ("interface" not in response): + print("query-port: %s: incomplete response:" % (url)) + pprint(response) + else: + p = response['interface'] + latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll = self.get_endp_stats_for_port( + p["port"], endps) + + self.write_port_csv(len(temp_stations_list), ul, dl, ul_pdu_str, dl_pdu_str, atten_val, eid_name, p, + latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, + total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll, ap_row, ap_stats_col_titles) # ap_stats_col_titles used as a length + + # At end of test step, record KPI information. This is different the kpi.csv + self.record_kpi( + len(temp_stations_list), + ul, + dl, + ul_pdu_str, + dl_pdu_str, + atten_val, + total_dl_bps, + total_ul_bps, + total_dl_ll_bps, + total_ul_ll_bps) + + # At end of test if requested store upload and download stats + if self.ap_scheduler_stats: + # get the (UL) Upload 6g scheduler statistics + self.ap_6g_umsched += self.ap_custom_cmd('wl -i wl2 dump umsched') + # get the (DL) Download 6g schduler staticstics + self.ap_6g_msched += self.ap_custom_cmd('wl -i wl2 dump msched') + + # get the (UL) Upload 5g scheduler statistics + self.ap_5g_umsched += self.ap_custom_cmd('wl -i wl1 dump umsched') + # get the (DL) Download 5g schduler staticstics + self.ap_5g_msched += self.ap_custom_cmd('wl -i wl1 dump msched') + + # get the (UL) Upload 24g scheduler statistics + self.ap_24g_umsched += self.ap_custom_cmd('wl -i wl0 dump umsched') + # get the (DL) Download 24g schduler staticstics + self.ap_24g_msched += self.ap_custom_cmd('wl -i wl0 dump msched') + + if self.ap_ofdma_stats: + # provide OFDMA stats 6GHz + self.ap_ofdma_6g += self.ap_custom_cmd('wl -i wl2 muinfo -v') + + # provide OFDMA stats 5GHz + self.ap_ofdma_5g += self.ap_custom_cmd('wl -i wl1 muinfo -v') + + # provide OFDMA stats 2.4GHz + self.ap_ofdma_24g += self.ap_custom_cmd('wl -i wl0 muinfo -v') + + # Stop connections. + self.cx_profile.stop_cx() + self.multicast_profile.stop_mc() + + cur_time = datetime.datetime.now() + + if passes == expected_passes: + self._pass("PASS: Requested-Rate: %s <-> %s PDU: %s <-> %s All tests passed" % (ul, dl, ul_pdu, dl_pdu), print_pass) + + def write_port_csv(self, sta_count, ul, dl, ul_pdu, dl_pdu, atten, eid_name, port_data, latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, + total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll, ap_row, ap_stats_col_titles): + row = [self.epoch_time, self.time_stamp(), sta_count, + ul, ul, dl, dl, dl_pdu, dl_pdu, ul_pdu, ul_pdu, + atten, eid_name + ] + + row = row + [port_data['bps rx'], port_data['bps tx'], port_data['rx-rate'], port_data['tx-rate'], + port_data['signal'], port_data['ap'], port_data['mode'], latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll] + + # Add in info queried from AP. NOTE: do not need to pass in the ap_stats_col_titles + #print("ap_row length {} col_titles length {}".format(len(ap_row),len(self.ap_stats_col_titles))) + #print("self.ap_stats_col_titles {} ap_stats_col_titles {}".format(self.ap_stats_col_titles,ap_stats_col_titles)) + if len(ap_row) == len(self.ap_stats_col_titles): + #print("ap_row {}".format(ap_row)) + for col in ap_row: + #print("col {}".format(col)) + row.append(col) + + writer = self.port_csv_writers[eid_name] + writer.writerow(row) + self.port_csv_files[eid_name].flush() + + # Submit data to the influx db if configured to do so. + + def record_kpi(self, sta_count, ul, dl, ul_pdu, dl_pdu, atten, total_dl_bps, total_ul_bps, total_dl_ll_bps, total_ul_ll_bps): + + tags = dict() + tags['requested-ul-bps'] = ul + tags['requested-dl-bps'] = dl + tags['ul-pdu-size'] = ul_pdu + tags['dl-pdu-size'] = dl_pdu + tags['station-count'] = sta_count + tags['attenuation'] = atten + tags["script"] = 'test_l3_longevity' + + # Add user specified tags + for k in self.user_tags: + tags[k[0]] = k[1] + + now = str(datetime.datetime.utcnow().isoformat()) + + print("NOTE: Adding kpi to influx, total-download-bps: %s upload: %s bi-directional: %s\n" % + (total_dl_bps, total_ul_bps, (total_ul_bps + total_dl_bps))) + + if self.influxdb is not None: + self.influxdb.post_to_influx("total-download-bps", total_dl_bps, tags, now) + self.influxdb.post_to_influx("total-upload-bps", total_ul_bps, tags, now) + self.influxdb.post_to_influx("total-bi-directional-bps", total_ul_bps + total_dl_bps, tags, now) + + if self.csv_kpi_file: + row = [self.epoch_time, self.time_stamp(), sta_count, + ul, ul, dl, dl, dl_pdu, dl_pdu, ul_pdu, ul_pdu, + atten, + total_dl_bps, total_ul_bps, (total_ul_bps + total_dl_bps), + total_dl_ll_bps, total_ul_ll_bps, (total_ul_ll_bps + total_dl_ll_bps) + ] + # Add values for any user specified tags + for k in self.user_tags: + row.append(k[1]) + + self.csv_kpi_writer.writerow(row) + self.csv_kpi_file.flush() + + # Stop traffic and admin down stations. + def stop(self): + self.cx_profile.stop_cx() + self.multicast_profile.stop_mc() + for station_list in self.station_lists: + for station_name in station_list: + self.admin_down(station_name) + + # Remove traffic connections and stations. + def cleanup(self): + self.cx_profile.cleanup() + self.multicast_profile.cleanup() + for station_profile in self.station_profiles: + station_profile.cleanup() + + def csv_generate_column_headers(self): + csv_rx_headers = ['Time epoch', 'Time', 'Monitor', + 'UL-Min-Requested', 'UL-Max-Requested', 'DL-Min-Requested', 'DL-Max-Requested', + 'UL-Min-PDU', 'UL-Max-PDU', 'DL-Min-PDU', 'DL-Max-PDU', + ] + csv_rx_headers.append("average_rx_data_bytes") + return csv_rx_headers + + def csv_generate_port_column_headers(self): + csv_rx_headers = ['Time epoch', 'Time', 'Station-Count', + 'UL-Min-Requested', 'UL-Max-Requested', 'DL-Min-Requested', 'DL-Max-Requested', + 'UL-Min-PDU', 'UL-Max-PDU', 'DL-Min-PDU', 'DL-Max-PDU', 'Attenuation', + 'Name', 'Rx-Bps', 'Tx-Bps', 'Rx-Link-Rate', 'Tx-Link-Rate', 'RSSI', 'AP', 'Mode', + 'Rx-Latency', 'Rx-Jitter', 'Ul-Rx-Goodput-bps', 'Ul-Rx-Rate-ll', 'Ul-Rx-Pkts-ll', 'Dl-Rx-Goodput-bps', 'Dl-Rx-Rate-ll', 'Dl-Rx-Pkts-ll' + ] + # Add in columns we are going to query from the AP + for col in self.ap_stats_col_titles: + csv_rx_headers.append(col) + + return csv_rx_headers + + def csv_generate_kpi_column_headers(self): + csv_rx_headers = ['Time epoch', 'Time', 'Station-Count', + 'UL-Min-Requested', 'UL-Max-Requested', 'DL-Min-Requested', 'DL-Max-Requested', + 'UL-Min-PDU', 'UL-Max-PDU', 'DL-Min-PDU', 'DL-Max-PDU', 'Attenuation', + 'Total-Download-Bps', 'Total-Upload-Bps', 'Total-UL/DL-Bps', + 'Total-Download-LL-Bps', 'Total-Upload-LL-Bps', 'Total-UL/DL-LL-Bps' + ] + for k in self.user_tags: + csv_rx_headers.append(k[0]) + + return csv_rx_headers + + # Write initial headers to csv file. + def csv_add_column_headers(self, headers): + if self.csv_kpi_file is not None: + self.csv_kpi_writer.writerow(self.csv_generate_kpi_column_headers()) + self.csv_kpi_file.flush() + + # Write initial headers to port csv file. + def csv_add_port_column_headers(self, eid_name, headers): + # if self.csv_file is not None: + fname = self.outfile[:-4] # Strip '.csv' from file name + fname = fname + "-" + eid_name + ".csv" + pfile = open(fname, "w") + port_csv_writer = csv.writer(pfile, delimiter=",") + self.port_csv_files[eid_name] = pfile + self.port_csv_writers[eid_name] = port_csv_writer + + port_csv_writer.writerow(headers) + pfile.flush() + + def csv_validate_list(self, csv_list, length): + if len(csv_list) < length: + csv_list = csv_list + [('no data', 'no data')] * (length - len(csv_list)) + return csv_list + + def csv_add_row(self, row, writer, csv_file): + if csv_file is not None: + writer.writerow(row) + csv_file.flush() + + # End of the main class. + +# Check some input values. + + +def valid_endp_types(_endp_type): + etypes = _endp_type.split(',') + for endp_type in etypes: + valid_endp_type = ['lf', 'lf_udp', 'lf_udp6', 'lf_tcp', 'lf_tcp6', 'mc_udp', 'mc_udp6'] + if not (str(endp_type) in valid_endp_type): + print('invalid endp_type: %s. Valid types lf, lf_udp, lf_udp6, lf_tcp, lf_tcp6, mc_udp, mc_udp6' % endp_type) + exit(1) + return _endp_type + + +# Starting point for running this from cmd line. +def main(): + lfjson_host = "localhost" + lfjson_port = 8080 + endp_types = "lf_udp" + debug = False + + parser = argparse.ArgumentParser( + prog='test_l3_longevity.py', + # formatter_class=argparse.RawDescriptionHelpFormatter, + formatter_class=argparse.RawTextHelpFormatter, + epilog='''\ + Useful Information: + 1. Polling interval for checking traffic is fixed at 1 minute + 2. The test will generate csv file + 3. The tx/rx rates are fixed at 256000 bits per second + 4. Maximum stations per radio based on radio + ''', + + description='''\ +test_l3_longevity.py: +-------------------- + +Summary : +---------- +create stations, create traffic between upstream port and stations, run traffic. +The traffic on the stations will be checked once per minute to verify that traffic is transmitted +and received. + +Generic command layout: +----------------------- +python .\\test_l3_longevity.py --test_duration --endp_type --upstream_port + --radio "radio== stations== ssid== ssid_pw== + security==" --debug +Multiple radios may be entered with individual --radio switches + +# UDP bi-directional test, no use of controller. +/test_l3_longevity.py --mgr localhost --endp_type 'lf_udp lf_tcp' --upstream_port 1.1.eth1 \ + --radio "radio==1.1.wiphy0 stations==10 ssid==ASUS_70 ssid_pw==[BLANK] security==open" \ + --radio "radio==1.1.wiphy2 stations==1 ssid==ASUS_70 ssid_pw==[BLANK] security==open" \ + --test_duration 30s + +# Port resets, chooses random value between min and max +test_l3_longevity.py --lfmgr LF_MGR_IP --test_duration 90s --polling_interval 10s --upstream_port eth2 \ + --radio 'radio==wiphy1,stations==4,ssid==SSID_USED,ssid_pw==SSID_PW_USED,security==SECURITY_USED, \ + reset_port_enable==TRUE,reset_port_time_min==10s,reset_port_time_max==20s' + --endp_type lf_udp --rates_are_totals --side_a_min_bps=20000 --side_b_min_bps=300000000" + + +: number followed by one of the following +d - days +h - hours +m - minutes +s - seconds + +: +lf_udp : IPv4 UDP traffic +lf_tcp : IPv4 TCP traffic +lf_udp6 : IPv6 UDP traffic +lf_tcp6 : IPv6 TCP traffic +mc_udp : IPv4 multi cast UDP traffic +mc_udp6 : IPv6 multi cast UDP traffic + +: +BK, BE, VI, VO: Optional wifi related Tos Settings. Or, use your preferred numeric values. + +################################# +#Command switches +################################# + +--mgr ',default='localhost' +-d / --test_duration example --time 5d (5 days) default: 3m options: number followed by d, h, m or s',default='3m' +--tos: Support different ToS settings: BK | BE | VI | VO | numeric',default="BE" +--debug: Enable debugging',default=False +-t / --endp_type example --endp_type \"lf_udp lf_tcp mc_udp\" Default: lf_udp , options: lf_udp, lf_udp6, lf_tcp, lf_tcp6, mc_udp, mc_udp6', + default='lf_udp', type=valid_endp_types +-u / --upstream_port example: --upstream_port eth1',default='eth1') +-o / --outfile ", default='longevity_results' + +######################################### +# Examples +# ####################################### +Example #1 running traffic with two radios +1. Test duration 4 minutes +2. Traffic IPv4 TCP +3. Upstream-port eth1 +4. Radio #0 wiphy0 has 32 stations, ssid = candelaTech-wpa2-x2048-4-1, ssid password = candelaTech-wpa2-x2048-4-1 +5. Radio #1 wiphy1 has 64 stations, ssid = candelaTech-wpa2-x2048-5-3, ssid password = candelaTech-wpa2-x2048-5-3 +6. Create connections with TOS of BK and VI + +Command: (remove carriage returns) +python3 .\\test_l3_longevity.py --test_duration 4m --endp_type \"lf_tcp lf_udp mc_udp\" --tos \"BK VI\" --upstream_port eth1 +--radio "radio==wiphy0 stations==32 ssid==candelaTech-wpa2-x2048-4-1 ssid_pw==candelaTech-wpa2-x2048-4-1 security==wpa2" +--radio "radio==wiphy1 stations==64 ssid==candelaTech-wpa2-x2048-5-3 ssid_pw==candelaTech-wpa2-x2048-5-3 security==wpa2" + + + ''') + + parser.add_argument( + '--local_lf_report_dir', + help='--local_lf_report_dir override the report path, primary use when running test in test suite', + default="") + parser.add_argument('-o', '--csv_outfile', help="--csv_outfile ", default="") + + parser.add_argument('--tty', help='--tty \"/dev/ttyUSB2\" the serial interface to the AP', default="") + parser.add_argument('--baud', help='--baud \"9600\" AP baud rate for the serial interface', default="9600") + parser.add_argument('--lfmgr', help='--lfmgr ', default='localhost') + parser.add_argument( + '--test_duration', + help='--test_duration example --time 5d (5 days) default: 3m options: number followed by d, h, m or s', + default='3m') + parser.add_argument('--tos', help='--tos: Support different ToS settings: BK | BE | VI | VO | numeric', default="BE") + parser.add_argument('--debug', help='--debug flag present debug on enable debugging', action='store_true') + parser.add_argument('-t', '--endp_type', help='--endp_type example --endp_type \"lf_udp lf_tcp mc_udp\" Default: lf_udp , options: lf_udp, lf_udp6, lf_tcp, lf_tcp6, mc_udp, mc_udp6', + default='lf_udp', type=valid_endp_types) + parser.add_argument('-u', '--upstream_port', help='--upstream_port example: --upstream_port eth1', default='eth1') + parser.add_argument('--downstream_port', help='--downstream_port example: --downstream_port eth2') + parser.add_argument('--polling_interval', help="--polling_interval ", default='60s') + + parser.add_argument('-r', '--radio', action='append', nargs=1, help='--radio\ + "radio== ssid== ssid_pw== security==\ + reset_port_enable==TRUE,reset_port_time_min==s,reset_port_time_max==s" ') + + parser.add_argument('--ap_read', help='--ap_read flag present enable reading ap', action='store_true') + parser.add_argument('--ap_port', help='--ap_port \'/dev/ttyUSB0\'', default='/dev/ttyUSB0') + parser.add_argument('--ap_baud', help='--ap_baud \'115200\'', default='115200') + # note wl2 is the 6G interface , check the MAC ifconfig -a of the interface to the AP BSSID connection (default may be eth8) + parser.add_argument('--ap_cmd_6g', help='ap_cmd_5g \'wl -i wl2 bs_data\'', default="wl -i wl2 bs_data") + # note wl1 is the 5G interface , check the MAC ifconfig -a of the interface to the AP BSSID connection (default may be eth7) + parser.add_argument('--ap_cmd_5g', help='ap_cmd_5g \'wl -i wl1 bs_data\'', default="wl -i wl1 bs_data") + # note wl1 is the 2.4G interface , check the MAC ifconfig -a of the interface to the AP BSSID connection (default may be eth6) + parser.add_argument('--ap_cmd_2g', help='ap_cmd_2g \'wl -i wl0 bs_data\'', default="wl -i wl0 bs_data") + parser.add_argument('--ap_chanim_cmd_6g', help='ap_chanim_cmd_6g \'wl -i wl2 chanim_stats\'', default="wl -i wl2 chanim_stats") + parser.add_argument('--ap_chanim_cmd_5g', help='ap_chanim_cmd_5g \'wl -i wl1 chanim_stats\'', default="wl -i wl1 chanim_stats") + parser.add_argument('--ap_chanim_cmd_2g', help='ap_chanim_cmd_2g \'w1 -i wl0 chanim_stats\'', default="wl -i wl0 chanim_stats") + parser.add_argument( + '--ap_scheduler_stats', + help='--ap_scheduler_stats flag to clear stats run test then dump ul and dl stats to file', + action='store_true') + parser.add_argument( + '--ap_ofdma_stats', + help='--ap_ofdma_stats flag to clear stats run test then dumps wl -i wl1 muinfo -v and wl 0i wl0 muinof -v to file', + action='store_true') + + parser.add_argument('--ap_test_mode', help='ap_test_mode flag present use ap canned data', action='store_true') + + parser.add_argument('-amr', '--side_a_min_bps', + help='--side_a_min_bps, requested downstream min tx rate, comma separated list for multiple iterations. Default 256k', default="256000") + parser.add_argument('-amp', '--side_a_min_pdu', + help='--side_a_min_pdu, downstream pdu size, comma separated list for multiple iterations. Default MTU', default="MTU") + parser.add_argument('-bmr', '--side_b_min_bps', + help='--side_b_min_bps, requested upstream min tx rate, comma separated list for multiple iterations. Default 256000', default="256000") + parser.add_argument('-bmp', '--side_b_min_pdu', + help='--side_b_min_pdu, upstream pdu size, comma separated list for multiple iterations. Default MTU', default="MTU") + parser.add_argument("--rates_are_totals", default=False, + help="Treat configured rates as totals instead of using the un-modified rate for every connection.", action='store_true') + parser.add_argument("--multiconn", default=1, + help="Configure multi-conn setting for endpoints. Default is 1 (auto-helper is enabled by default as well).") + + parser.add_argument( + '--attenuators', + help='--attenuators, comma separated list of attenuator module eids: shelf.resource.atten-serno.atten-idx', + default="") + parser.add_argument('--atten_vals', help='--atten_vals, comma separated list of attenuator settings in ddb units (1/10 of db)', default="") + + influx_add_parser_args(parser) + + parser.add_argument("--cap_ctl_out", help="--cap_ctl_out, switch the controller output will be captured", action='store_true') + parser.add_argument("--wait", help="--wait