diff --git a/pscheduler-test-latency/latency/cli-to-spec b/pscheduler-test-latency/latency/cli-to-spec index c4bf945c7..19ba94691 100755 --- a/pscheduler-test-latency/latency/cli-to-spec +++ b/pscheduler-test-latency/latency/cli-to-spec @@ -68,6 +68,11 @@ opt_parser.add_option("--dest-node", action="store", type="string", dest="dest_node") +opt_parser.add_option("--protocol", + help="The protocol to use in making the measurement", + action="store", type="str", + dest="protocol") + opt_parser.add_option("-c", "--packet-count", help="The number of packets to send", action="store", type="int", @@ -111,7 +116,7 @@ opt_parser.add_option("-b", "--bucket-width", help="The bin size to use for histogram calculations. This value is divided into the result as reported in seconds and truncated to the nearest 2 decimal places.", action="store", type="float", dest="bucket_width") - + opt_parser.add_option("-f", "--flip", help="In multi-participant mode, have the dest start the client and request a reverse test. Useful in some firewall and NAT environments.", action="store_true", dest="flip", default=False) @@ -127,7 +132,7 @@ opt_parser.add_option("--traverse-nat", opt_parser.add_option("-R", "--output-raw", help="Output individual packet statistics. This will substantially increase the size of a successful result.", action="store_true", dest="output_raw", default=False) - + (options, remaining_args) = opt_parser.parse_args(args) if len(remaining_args) != 0: @@ -143,7 +148,7 @@ if options.source is not None: if options.source_node is not None: result['source-node'] = options.source_node - + if options.dest is not None: result['dest'] = options.dest @@ -153,9 +158,13 @@ if options.dest_node is not None: if options.packet_count is not None: result['packet-count'] = options.packet_count +if options.protocol is not None: + result['protocol'] = options.protocol + spec_schema.set(4) + if options.packet_interval is not None: result['packet-interval'] = options.packet_interval - + if options.packet_timeout is not None: result['packet-timeout'] = options.packet_timeout diff --git a/pscheduler-test-latency/latency/spec-format b/pscheduler-test-latency/latency/spec-format index 405d1b47d..0d7540b9d 100755 --- a/pscheduler-test-latency/latency/spec-format +++ b/pscheduler-test-latency/latency/spec-format @@ -16,6 +16,9 @@ Source ............... {{ unspec(source) }} Source Node .......... {{ unspec(sourcenode) }} Destination .......... {{ unspec(dest) }} Destination Node ..... {{ unspec(destnode) }} +{% if schema >= 4 -%} +Protocol ............. {{ unspec(protocol) }} +{%- endif %} Packet Count ......... {{ unspec(packetcount) }} Packet Interval ...... {{ unspec(packetinterval) }} Packet Timeout ....... {{ unspec(packettimeout) }} diff --git a/pscheduler-test-latency/latency/validate.py b/pscheduler-test-latency/latency/validate.py index 813d08cdc..3ec0d9c91 100644 --- a/pscheduler-test-latency/latency/validate.py +++ b/pscheduler-test-latency/latency/validate.py @@ -10,7 +10,7 @@ from pscheduler import json_validate -MAX_SCHEMA = 3 +MAX_SCHEMA = 4 SPEC_SCHEMA = { @@ -60,7 +60,7 @@ "packet-interval": { "description": "The number of seconds to delay between sending packets", "$ref": "#/local/packet-interval" - + }, "packet-timeout": { "description": "The number of seconds to wait before declaring a packet lost", @@ -83,12 +83,12 @@ "$ref": "#/pScheduler/IPTOS" }, "ip-version": { - "description": "Force a specific IP address type used performing the test. Useful when specifying hostnames as source or dest that may map to both IPv4 and IPv6 addresses.", - "$ref": "#/pScheduler/ip-version" + "description": "Force a specific IP address type used performing the test. Useful when specifying hostnames as source or dest that may map to both IPv4 and IPv6 addresses.", + "$ref": "#/pScheduler/ip-version" }, "bucket-width": { "description": "The bin size to use for histogram calculations. This value is divided into the result as reported in seconds and truncated to the nearest 2 decimal places.", - "$ref": "#/local/bucket-width" + "$ref": "#/local/bucket-width" }, "output-raw": { "description": "Output individual packet statistics. This will substantially increase the size of a successful result.", @@ -135,7 +135,7 @@ "packet-interval": { "description": "The number of seconds to delay between sending packets", "$ref": "#/local/packet-interval" - + }, "packet-timeout": { "description": "The number of seconds to wait before declaring a packet lost", @@ -158,12 +158,12 @@ "$ref": "#/pScheduler/IPTOS" }, "ip-version": { - "description": "Force a specific IP address type used performing the test. Useful when specifying hostnames as source or dest that may map to both IPv4 and IPv6 addresses.", - "$ref": "#/pScheduler/ip-version" + "description": "Force a specific IP address type used performing the test. Useful when specifying hostnames as source or dest that may map to both IPv4 and IPv6 addresses.", + "$ref": "#/pScheduler/ip-version" }, "bucket-width": { "description": "The bin size to use for histogram calculations. This value is divided into the result as reported in seconds and truncated to the nearest 2 decimal places.", - "$ref": "#/local/bucket-width" + "$ref": "#/local/bucket-width" }, "output-raw": { "description": "Output individual packet statistics. This will substantially increase the size of a successful result.", @@ -214,7 +214,93 @@ "packet-interval": { "description": "The number of seconds to delay between sending packets", "$ref": "#/local/packet-interval" - + + }, + "packet-timeout": { + "description": "The number of seconds to wait before declaring a packet lost", + "$ref": "#/pScheduler/CardinalZero" + }, + "packet-padding": { + "description": "The size of padding to add to the packet in bytes", + "$ref": "#/pScheduler/CardinalZero" + }, + "ctrl-port": { + "description": "The control plane port to use for the entity acting as the server (the dest if flip is not set, the source otherwise)", + "$ref": "#/pScheduler/IPPort" + }, + "data-ports": { + "description": "The port range to use on the side of the test running the client. At least two ports required.", + "$ref": "#/pScheduler/IPPortRange" + }, + "ip-tos": { + "description": "DSCP value for TOS byte in the IP header as an integer", + "$ref": "#/pScheduler/IPTOS" + }, + "ip-version": { + "description": "Force a specific IP address type used performing the test. Useful when specifying hostnames as source or dest that may map to both IPv4 and IPv6 addresses.", + "$ref": "#/pScheduler/ip-version" + }, + "bucket-width": { + "description": "The bin size to use for histogram calculations. This value is divided into the result as reported in seconds and truncated to the nearest 2 decimal places.", + "$ref": "#/local/bucket-width" + }, + "output-raw": { + "description": "Output individual packet statistics. This will substantially increase the size of a successful result.", + "$ref": "#/pScheduler/Boolean" + }, + "flip": { + "description": "In multi-participant mode, have the dest start the client and request a reverse test. Useful in some firewall and NAT environments.", + "$ref": "#/pScheduler/Boolean" + }, + "reverse": { + "description": "Report results in the reverse direction (destination to source) if possible.", + "$ref": "#/pScheduler/Boolean" + }, + "traverse-nat": { + "description": "Make an effort to traverse outbound NAT,", + "$ref": "#/pScheduler/Boolean" + }, + }, + "required": ["schema", "dest"], + "additionalProperties": False + }, + + "v4": { + "type": "object", + "properties": { + "schema": { + "description": "The version of the schema", + "type": "integer", + "enum": [ 4 ] + }, + "source": { + "description": "The address of the entity sending packets in this test", + "$ref": "#/pScheduler/Host" + }, + "source-node": { + "description": "The address of the source pScheduler node, if different", + "$ref": "#/pScheduler/URLHostPort" + }, + "dest": { + "description": "The address of the entity receiving packets in this test", + "$ref": "#/pScheduler/Host" + }, + "dest-node": { + "description": "The address of the destination pScheduler node, if different", + "$ref": "#/pScheduler/URLHostPort" + }, + "protocol": { + "description": "The protocol to use in making the measurement", + "$ref": "#/pScheduler/String" + }, + "packet-count": { + "description": "The number of packets to send", + "$ref": "#/pScheduler/Cardinal" + }, + "packet-interval": { + "description": "The number of seconds to delay between sending packets", + "$ref": "#/local/packet-interval" + }, "packet-timeout": { "description": "The number of seconds to wait before declaring a packet lost", @@ -237,12 +323,12 @@ "$ref": "#/pScheduler/IPTOS" }, "ip-version": { - "description": "Force a specific IP address type used performing the test. Useful when specifying hostnames as source or dest that may map to both IPv4 and IPv6 addresses.", - "$ref": "#/pScheduler/ip-version" + "description": "Force a specific IP address type used performing the test. Useful when specifying hostnames as source or dest that may map to both IPv4 and IPv6 addresses.", + "$ref": "#/pScheduler/ip-version" }, "bucket-width": { "description": "The bin size to use for histogram calculations. This value is divided into the result as reported in seconds and truncated to the nearest 2 decimal places.", - "$ref": "#/local/bucket-width" + "$ref": "#/local/bucket-width" }, "output-raw": { "description": "Output individual packet statistics. This will substantially increase the size of a successful result.", @@ -292,7 +378,7 @@ }, "ip-ttl": { "type": "integer", - "minimum": 0, + "minimum": 0, "maximum": 255 } }, @@ -407,5 +493,5 @@ def spec_is_valid(json): return json_validate(json, temp_schema, max_schema=MAX_SCHEMA) -def result_is_valid(json): +def result_is_valid(json): return json_validate(json, RESPONSE_SCHEMA) diff --git a/pscheduler-test-latencybg/latencybg/cli-to-spec b/pscheduler-test-latencybg/latencybg/cli-to-spec index 973434e6c..bd7f55b3a 100755 --- a/pscheduler-test-latencybg/latencybg/cli-to-spec +++ b/pscheduler-test-latencybg/latencybg/cli-to-spec @@ -69,6 +69,11 @@ opt_parser.add_option("--dest-node", action="store", type="string", dest="dest_node") +opt_parser.add_option("--protocol", + help="The protocol to use in making the measurement", + action="store", type="str", + dest="protocol") + opt_parser.add_option("-c", "--packet-count", help="The number of packets to send", action="store", type="int", @@ -132,7 +137,8 @@ if len(remaining_args) != 0: pscheduler.fail("Unusable arguments: %s" % " ".join(remaining_args)) -result = { 'schema': 1 } +result = { } +schema = pscheduler.HighInteger(1) if options.source is not None: result['source'] = options.source @@ -159,6 +165,10 @@ if options.duration is not None: if options.packet_count is not None: result['packet-count'] = options.packet_count +if options.protocol is not None: + result['protocol'] = options.protocol + schema.set(2) + if options.packet_interval is not None: result['packet-interval'] = options.packet_interval @@ -199,5 +209,6 @@ if options.flip: if options.output_raw: result['output-raw'] = options.output_raw +result['schema'] = schema.value() pscheduler.succeed_json(result) diff --git a/pscheduler-test-latencybg/latencybg/result-format b/pscheduler-test-latencybg/latencybg/result-format index 8bcc7b0ab..b67de1013 100755 --- a/pscheduler-test-latencybg/latencybg/result-format +++ b/pscheduler-test-latencybg/latencybg/result-format @@ -6,6 +6,7 @@ import pscheduler import sys import math +from validate import result_max_schema from validate import result_is_valid ''' @@ -147,7 +148,7 @@ if format != 'text/plain': pscheduler.fail("Unsupported format '%s'" % format) #parse JSON input -input = pscheduler.json_load(exit_on_error=True, max_schema=1) +input = pscheduler.json_load(exit_on_error=True, max_schema=result_max_schema()) #validate against JSON schema file if "result" not in input: diff --git a/pscheduler-test-latencybg/latencybg/spec-format b/pscheduler-test-latencybg/latencybg/spec-format index 6fc795bdd..2eee94490 100755 --- a/pscheduler-test-latencybg/latencybg/spec-format +++ b/pscheduler-test-latencybg/latencybg/spec-format @@ -5,8 +5,8 @@ import pscheduler +from validate import spec_max_schema from validate import spec_is_valid -from validate import MAX_SCHEMA TEMPLATE=''' {% if _mime_type == 'text/plain' %} @@ -16,6 +16,9 @@ Source Node .......... {{ unspec(sourcenode) }} Destination .......... {{ unspec(dest) }} Destination Node ..... {{ unspec(destnode) }} Duration ............. {{ unspec(duration) }} +{% if schema >= 2 -%} +Protocol ............. {{ unspec(protocol) }} +{%- endif %} Packet Count ......... {{ unspec(packetcount) }} Packet Interval ...... {{ unspec(packetinterval) }} Packet Timeout ....... {{ unspec(packettimeout) }} @@ -64,4 +67,4 @@ Flip Mode ............ {{ unspec(flip) }} {% endif %} ''' -pscheduler.spec_format_method(TEMPLATE, max_schema=MAX_SCHEMA, validator=spec_is_valid) +pscheduler.spec_format_method(TEMPLATE, max_schema=spec_max_schema(), validator=spec_is_valid) diff --git a/pscheduler-test-latencybg/latencybg/spec-is-valid b/pscheduler-test-latencybg/latencybg/spec-is-valid index 443ab1e54..f7bb83404 100755 --- a/pscheduler-test-latencybg/latencybg/spec-is-valid +++ b/pscheduler-test-latencybg/latencybg/spec-is-valid @@ -6,10 +6,11 @@ import pscheduler from validate import spec_is_valid +from validate import spec_max_schema try: - json = pscheduler.json_load(max_schema=1) + json = pscheduler.json_load(max_schema=spec_max_schema()) except ValueError as ex: pscheduler.succeed_json({ "valid": False, diff --git a/pscheduler-test-latencybg/latencybg/spec-to-cli b/pscheduler-test-latencybg/latencybg/spec-to-cli index 33ddb5ab3..4a521af14 100755 --- a/pscheduler-test-latencybg/latencybg/spec-to-cli +++ b/pscheduler-test-latencybg/latencybg/spec-to-cli @@ -3,11 +3,13 @@ # Convert a test specification to command-line options import pscheduler -import jsonschema -from validate import spec_is_valid, REQUEST_SCHEMA + +from validate import spec_is_valid +from validate import spec_max_schema +from validate import SPEC_SCHEMA #load spec JSON -spec = pscheduler.json_load(exit_on_error=True, max_schema=1) +spec = pscheduler.json_load(exit_on_error=True, max_schema=spec_max_schema()) if not isinstance(spec, dict): pscheduler.fail("Invalid JSON for this operation") @@ -17,8 +19,12 @@ if not valid: pscheduler.fail(message) #get properties from schema -schema_props = REQUEST_SCHEMA.get('properties', {}) -if not schema_props: +spec_version = spec.get('schema', 1) +try: + # It's safe to assume that the schema version is valid because it + # passed validation above. + schema_props = SPEC_SCHEMA['versions'][str(spec_version)]['properties'] +except KeyError: pscheduler.fail("Error retrieving schema properties") #build command-line from schema diff --git a/pscheduler-test-latencybg/latencybg/validate.py b/pscheduler-test-latencybg/latencybg/validate.py index bff1aafe9..02c2589bd 100644 --- a/pscheduler-test-latencybg/latencybg/validate.py +++ b/pscheduler-test-latencybg/latencybg/validate.py @@ -2,232 +2,335 @@ # Validator for "latency" Test # +# IMPORTANT: # -# Development Order #3: +# When making changes to the JSON schemas in this file, corresponding +# changes MUST be made in 'spec-format' and 'result-format' to make +# them capable of formatting the new specifications and results. + +from pscheduler import json_validate +from pscheduler import json_validate_from_standard_template +from pscheduler import json_standard_template_max_schema + + + # -# This file determines the required and optional data types which are -# allowed to be in the test spec and result. This is used -# for validation of these structures. +# Specification # -# Several existing datatypes are available for use at: -# pscheduler/python-pscheduler/pscheduler/pscheduler/jsonval.py -# -from pscheduler import json_validate +SPEC_SCHEMA = { -MAX_SCHEMA = 1 + "local": { + "packet-interval": { + "type": "number", + "exclusiveMinimum": 0.0 + }, + "bucket-width": { + "type": "number", + "exclusiveMinimum": 0.0, + "exclusiveMaximum": 1.0, + "default": ".001" + } + }, + + "versions": { + "1": { + "type": "object", + "properties": { + "schema": { + "description": "The version of the schema", + "$ref": "#/pScheduler/Cardinal" + }, + "source": { + "description": "The address of the entity sending packets in this test", + "$ref": "#/pScheduler/Host" + }, + "source-node": { + "description": "The address of the source pScheduler node, if different", + "$ref": "#/pScheduler/URLHostPort" + }, + "dest": { + "description": "The address of the entity receiving packets in this test", + "$ref": "#/pScheduler/Host" + }, + "dest-node": { + "description": "The address of the destination pScheduler node, if different", + "$ref": "#/pScheduler/URLHostPort" + }, + "duration": { + "description": "The length of time to run the test", + "$ref": "#/pScheduler/Duration" + }, + "packet-count": { + "description": "The number of packets to send before reporting a result", + "$ref": "#/pScheduler/Cardinal" + }, + "packet-interval": { + "description": "The number of seconds to delay between sending packets", + "$ref": "#/local/packet-interval" + }, + "packet-timeout": { + "description": "The number of seconds to wait before declaring a packet lost", + "$ref": "#/pScheduler/CardinalZero" + }, + "packet-padding": { + "description": "The size of padding to add to the packet in bytes", + "$ref": "#/pScheduler/CardinalZero" + }, + "ctrl-port": { + "description": "The control plane port to use for the entity acting as the server (the dest if flip is not set, the source otherwise)", + "$ref": "#/pScheduler/IPPort" + }, + "data-ports": { + "description": "The port range to use on the side of the test running the client. At least two ports required.", + "$ref": "#/pScheduler/IPPortRange" + }, + "ip-tos": { + "description": "DSCP value for TOS byte in the IP header as an integer", + "$ref": "#/pScheduler/IPTOS" + }, + "ip-version": { + "description": "Force a specific IP address type used performing the test. Useful when specifying hostnames as source or dest that may map to both IPv4 and IPv6 addresses.", + "$ref": "#/pScheduler/ip-version" + }, + "bucket-width": { + "description": "The bin size to use for histogram calculations. This value is divided into the result as reported in seconds and truncated to the nearest 2 decimal places.", + "$ref": "#/local/bucket-width" + }, + "output-raw": { + "description": "Output individual packet statistics. This will substantially increase the size of a successful result.", + "$ref": "#/pScheduler/Boolean" + }, + "flip": { + "description": "In multi-participant mode, have the dest start the client and request a reverse test. Useful in some firewall and NAT environments.", + "$ref": "#/pScheduler/Boolean" + } -REQUEST_SCHEMA = { - "title": "pScheduler One-way Latency Background Request Schema", - "type": "object", - "local": { - "packet-interval": { - "type": "number", - "exclusiveMinimum": 0.0 - }, - "bucket-width": { - "type": "number", - "exclusiveMinimum": 0.0, - "exclusiveMaximum": 1.0, - "default": ".001" }, + "required": ["dest"] }, - "properties": { - "schema": { - "description": "The version of the schema", - "$ref": "#/pScheduler/Cardinal" - }, - "source": { - "description": "The address of the entity sending packets in this test", - "$ref": "#/pScheduler/Host" - }, - "source-node": { - "description": "The address of the source pScheduler node, if different", - "$ref": "#/pScheduler/URLHostPort" - }, - "dest": { - "description": "The address of the entity receiving packets in this test", - "$ref": "#/pScheduler/Host" - }, - "dest-node": { - "description": "The address of the destination pScheduler node, if different", - "$ref": "#/pScheduler/URLHostPort" - }, - "duration": { - "description": "The length of time to run the test", - "$ref": "#/pScheduler/Duration" - }, - "packet-count": { - "description": "The number of packets to send before reporting a result", - "$ref": "#/pScheduler/Cardinal" - }, - "packet-interval": { - "description": "The number of seconds to delay between sending packets", - "$ref": "#/local/packet-interval" - - }, - "packet-timeout": { - "description": "The number of seconds to wait before declaring a packet lost", - "$ref": "#/pScheduler/CardinalZero" - }, - "packet-padding": { - "description": "The size of padding to add to the packet in bytes", - "$ref": "#/pScheduler/CardinalZero" - }, - "ctrl-port": { - "description": "The control plane port to use for the entity acting as the server (the dest if flip is not set, the source otherwise)", - "$ref": "#/pScheduler/IPPort" - }, - "data-ports": { - "description": "The port range to use on the side of the test running the client. At least two ports required.", - "$ref": "#/pScheduler/IPPortRange" - }, - "ip-tos": { - "description": "DSCP value for TOS byte in the IP header as an integer", - "$ref": "#/pScheduler/IPTOS" - }, - "ip-version": { - "description": "Force a specific IP address type used performing the test. Useful when specifying hostnames as source or dest that may map to both IPv4 and IPv6 addresses.", - "$ref": "#/pScheduler/ip-version" + "2": { + "type": "object", + "properties": { + "schema": { + "description": "The version of the schema", + "$ref": "#/pScheduler/Cardinal" + }, + "source": { + "description": "The address of the entity sending packets in this test", + "$ref": "#/pScheduler/Host" + }, + "source-node": { + "description": "The address of the source pScheduler node, if different", + "$ref": "#/pScheduler/URLHostPort" + }, + "dest": { + "description": "The address of the entity receiving packets in this test", + "$ref": "#/pScheduler/Host" + }, + "dest-node": { + "description": "The address of the destination pScheduler node, if different", + "$ref": "#/pScheduler/URLHostPort" + }, + "protocol": { + "description": "The protocol to use in making the measurement", + "$ref": "#/pScheduler/String" + }, + "duration": { + "description": "The length of time to run the test", + "$ref": "#/pScheduler/Duration" + }, + "packet-count": { + "description": "The number of packets to send before reporting a result", + "$ref": "#/pScheduler/Cardinal" + }, + "packet-interval": { + "description": "The number of seconds to delay between sending packets", + "$ref": "#/local/packet-interval" + }, + "packet-timeout": { + "description": "The number of seconds to wait before declaring a packet lost", + "$ref": "#/pScheduler/CardinalZero" + }, + "packet-padding": { + "description": "The size of padding to add to the packet in bytes", + "$ref": "#/pScheduler/CardinalZero" + }, + "ctrl-port": { + "description": "The control plane port to use for the entity acting as the server (the dest if flip is not set, the source otherwise)", + "$ref": "#/pScheduler/IPPort" + }, + "data-ports": { + "description": "The port range to use on the side of the test running the client. At least two ports required.", + "$ref": "#/pScheduler/IPPortRange" + }, + "ip-tos": { + "description": "DSCP value for TOS byte in the IP header as an integer", + "$ref": "#/pScheduler/IPTOS" + }, + "ip-version": { + "description": "Force a specific IP address type used performing the test. Useful when specifying hostnames as source or dest that may map to both IPv4 and IPv6 addresses.", + "$ref": "#/pScheduler/ip-version" + }, + "bucket-width": { + "description": "The bin size to use for histogram calculations. This value is divided into the result as reported in seconds and truncated to the nearest 2 decimal places.", + "$ref": "#/local/bucket-width" + }, + "output-raw": { + "description": "Output individual packet statistics. This will substantially increase the size of a successful result.", + "$ref": "#/pScheduler/Boolean" + }, + "flip": { + "description": "In multi-participant mode, have the dest start the client and request a reverse test. Useful in some firewall and NAT environments.", + "$ref": "#/pScheduler/Boolean" + } + }, - "bucket-width": { - "description": "The bin size to use for histogram calculations. This value is divided into the result as reported in seconds and truncated to the nearest 2 decimal places.", - "$ref": "#/local/bucket-width" + "required": ["dest"] + } + + } +} + + +def spec_max_schema(): + return json_standard_template_max_schema(SPEC_SCHEMA) + +def spec_is_valid(json): + return json_validate_from_standard_template(json, SPEC_SCHEMA) + + +# +# Result +# + +RESULT_SCHEMA = { + + "local": { + "histogram-number-integer": { + "type": "object", + "patternProperties": { + "^[-+]?([0-9]+(\\.[0-9]+)?|\\.[0-9]+)$": { "type": "integer" } }, - "output-raw": { - "description": "Output individual packet statistics. This will substantially increase the size of a successful result.", - "$ref": "#/pScheduler/Boolean" + "additionalProperties": False + }, + "histogram-integer-integer": { + "type": "object", + "patternProperties": { + "^\\d+$": { "type": "integer" } }, - "flip": { - "description": "In multi-participant mode, have the dest start the client and request a reverse test. Useful in some firewall and NAT environments.", - "$ref": "#/pScheduler/Boolean" - } - + "additionalProperties": False }, - "required": ["dest"] -} + "ip-ttl": { + "type": "integer", + "minimum": 0, + "maximum": 255 + } + }, -RESPONSE_SCHEMA = { - "title": "pScheduler One-way Latency Background Response Schema", - "type": "object", - "local": { - "histogram-number-integer": { - "type": "object", - "patternProperties": { - "^[-+]?([0-9]+(\\.[0-9]+)?|\\.[0-9]+)$": { "type": "integer" } + "versions": { + "1": { + "type": "object", + "properties": { + "schema": { + "description": "The version of the schema", + "$ref": "#/pScheduler/Cardinal" }, - "additionalProperties": False - }, - "histogram-integer-integer": { - "type": "object", - "patternProperties": { - "^\\d+$": { "type": "integer" } + "succeeded": { + "description": "Indicates if the test ran successfully", + "$ref": "#/pScheduler/Boolean" }, - "additionalProperties": False - }, - "ip-ttl": { - "type": "integer", - "minimum": 0, - "maximum": 255 - } - }, - "properties": { - "schema": { - "description": "The version of the schema", - "$ref": "#/pScheduler/Cardinal" - }, - "succeeded": { - "description": "Indicates if the test ran successfully", - "$ref": "#/pScheduler/Boolean" - }, - "error": { - "description": "Errors that occurred", - "$ref": "#/pScheduler/String" - }, - "diags": { - "description": "Diagnostic information", - "$ref": "#/pScheduler/String" - }, - "packets-sent": { - "description": "The number of packets sent by the sender", - "$ref": "#/pScheduler/CardinalZero" - }, - "packets-received": { - "description": "The number of packets received by the receiver", - "$ref": "#/pScheduler/CardinalZero" - }, - "packets-lost": { - "description": "The difference between the number of packets sent and received", - "$ref": "#/pScheduler/CardinalZero" - }, - "packets-duplicated": { - "description": "The number of duplicate packets seen by the receiver", - "$ref": "#/pScheduler/CardinalZero" - }, - "packets-reordered": { - "description": "The number of packets received out of order seen by the receiver", - "$ref": "#/pScheduler/CardinalZero" - }, - "max-clock-error": { - "description": "As the maximum estimate of difference between sender and receiver clocks in milliseconds", - "$ref": "#/pScheduler/Number" - }, - "histogram-latency": { - "description": "A histogram where the key is observed one-way latency values divided by bucket-width rounded to the nearest two decimal places, and the value is the number of packets that observed that value.", - "$ref": "#/local/histogram-number-integer" - }, - "histogram-ttl": { - "description": "A histogram where the key is the IP time-to-live of the packet when it reached the receiver and the value is the number of packets that observed that value", - "$ref": "#/local/histogram-integer-integer" - }, - "raw-packets": { - "description": "List of individual packet measurements collected during test", - "type": "array", - "items": { - "type": "object", - "properties": { - "seq-num": { - "description": "A monotonically increasing number starting a 0 indicating when the packet was sent in relation to otehr packets ", - "$ref": "#/pScheduler/CardinalZero" - }, - "src-ts": { - "description": "The timestamp when the packet was sent. Note this is a RFC1305 64-bit timestamp", - "$ref": "#/pScheduler/CardinalZero" - }, - "src-clock-sync": { - "description": "Indicates if the clock on the sender is synced with NTP", - "$ref": "#/pScheduler/Boolean" - }, - "src-clock-err": { - "description": "The estimates NTP error of the sender's clock", - "$ref": "#/pScheduler/Number" - }, - "dst-ts": { - "description": "The timestamp when the packet was received. Note this is a RFC1305 64-bit timestamp", - "$ref": "#/pScheduler/CardinalZero" - }, - "dst-clock-sync": { - "description": "Indicates if the clock on the receiver is synced with NTP", - "$ref": "#/pScheduler/Boolean" - }, - "dst-clock-err": { - "description": "The estimates NTP error of the receiver's clock", - "$ref": "#/pScheduler/Number" + "error": { + "description": "Errors that occurred", + "$ref": "#/pScheduler/String" + }, + "diags": { + "description": "Diagnostic information", + "$ref": "#/pScheduler/String" + }, + "packets-sent": { + "description": "The number of packets sent by the sender", + "$ref": "#/pScheduler/CardinalZero" + }, + "packets-received": { + "description": "The number of packets received by the receiver", + "$ref": "#/pScheduler/CardinalZero" + }, + "packets-lost": { + "description": "The difference between the number of packets sent and received", + "$ref": "#/pScheduler/CardinalZero" + }, + "packets-duplicated": { + "description": "The number of duplicate packets seen by the receiver", + "$ref": "#/pScheduler/CardinalZero" + }, + "packets-reordered": { + "description": "The number of packets received out of order seen by the receiver", + "$ref": "#/pScheduler/CardinalZero" + }, + "max-clock-error": { + "description": "As the maximum estimate of difference between sender and receiver clocks in milliseconds", + "$ref": "#/pScheduler/Number" + }, + "histogram-latency": { + "description": "A histogram where the key is observed one-way latency values divided by bucket-width rounded to the nearest two decimal places, and the value is the number of packets that observed that value.", + "$ref": "#/local/histogram-number-integer" + }, + "histogram-ttl": { + "description": "A histogram where the key is the IP time-to-live of the packet when it reached the receiver and the value is the number of packets that observed that value", + "$ref": "#/local/histogram-integer-integer" + }, + "raw-packets": { + "description": "List of individual packet measurements collected during test", + "type": "array", + "items": { + "type": "object", + "properties": { + "seq-num": { + "description": "A monotonically increasing number starting a 0 indicating when the packet was sent in relation to otehr packets ", + "$ref": "#/pScheduler/CardinalZero" + }, + "src-ts": { + "description": "The timestamp when the packet was sent. Note this is a RFC1305 64-bit timestamp", + "$ref": "#/pScheduler/CardinalZero" + }, + "src-clock-sync": { + "description": "Indicates if the clock on the sender is synced with NTP", + "$ref": "#/pScheduler/Boolean" + }, + "src-clock-err": { + "description": "The estimates NTP error of the sender's clock", + "$ref": "#/pScheduler/Number" + }, + "dst-ts": { + "description": "The timestamp when the packet was received. Note this is a RFC1305 64-bit timestamp", + "$ref": "#/pScheduler/CardinalZero" + }, + "dst-clock-sync": { + "description": "Indicates if the clock on the receiver is synced with NTP", + "$ref": "#/pScheduler/Boolean" + }, + "dst-clock-err": { + "description": "The estimates NTP error of the receiver's clock", + "$ref": "#/pScheduler/Number" + }, + "ip-ttl": { + "description": "The time-to-live value in teh IP header when the packet reached the receiver", + "$ref": "#/local/ip-ttl" + } }, - "ip-ttl": { - "description": "The time-to-live value in teh IP header when the packet reached the receiver", - "$ref": "#/local/ip-ttl" - } - }, - "required": ["seq-num", "src-ts", "src-clock-sync", "dst-ts", "dst-clock-sync", "ip-ttl"] + "required": ["seq-num", "src-ts", "src-clock-sync", "dst-ts", "dst-clock-sync", "ip-ttl"] + } } - } - }, - "required": [ "succeeded"] + }, + "required": [ "succeeded" ] + } } +} -def spec_is_valid(json): - return json_validate(json, REQUEST_SCHEMA, max_schema=MAX_SCHEMA) + +def result_max_schema(): + return json_standard_template_max_schema(RESULT_SCHEMA) def result_is_valid(json): - return json_validate(json, RESPONSE_SCHEMA) + return json_validate_from_standard_template(json, RESPONSE_SCHEMA) diff --git a/pscheduler-test-rtt/rtt/cli-to-spec b/pscheduler-test-rtt/rtt/cli-to-spec index 3a4703000..c6f38d1ea 100755 --- a/pscheduler-test-rtt/rtt/cli-to-spec +++ b/pscheduler-test-rtt/rtt/cli-to-spec @@ -156,7 +156,6 @@ if len(remaining_args) != 0: result = { } schema = pscheduler.HighInteger(1) - if options.count is not None: result['count'] = options.count diff --git a/pscheduler-tool-halfping/halfping/can-run b/pscheduler-tool-halfping/halfping/can-run index 31ed0830f..f380830ae 100755 --- a/pscheduler-tool-halfping/halfping/can-run +++ b/pscheduler-tool-halfping/halfping/can-run @@ -30,17 +30,25 @@ except KeyError: spec = json['spec'] SUPPORTED_OPTIONS = ["schema", "source", "source-node", "dest", "dest-node", - "packet-count", "packet-interval", + "protocol", "packet-count", "packet-interval", "packet-timeout", "packet-padding", "ip-tos", "ip-version", "bucket-width" ] errors = [] + for option in spec: if option not in SUPPORTED_OPTIONS: errors.append(f"halfping does not support {option}") +try: + protocol = spec['protocol'] + if protocol != 'icmp': + errors.append(f'Protocol "{protocol}" is not supported.') +except KeyError: + pass + result = {"can-run": len(errors) == 0} if len(errors) > 0: result["reasons"] = errors diff --git a/pscheduler-tool-owping/owping/can-run b/pscheduler-tool-owping/owping/can-run index 1fcf35dc2..2aa699ab3 100755 --- a/pscheduler-tool-owping/owping/can-run +++ b/pscheduler-tool-owping/owping/can-run @@ -24,7 +24,7 @@ except KeyError: try: spec = json["spec"] - pscheduler.json_check_schema(spec, 1) + pscheduler.json_check_schema(spec, 4) except KeyError: pscheduler.succeed_json({ "can-run": False, @@ -38,4 +38,17 @@ except ValueError as ex: -pscheduler.succeed_json({ "can-run": True }) +errors = [] + +try: + protocol = spec['protocol'] + if protocol != 'owamp': + errors.append(f'Protocol "{protocol}" is not supported.') +except KeyError: + pass + +result = {"can-run": len(errors) == 0} +if len(errors) > 0: + result["reasons"] = errors + +pscheduler.succeed_json(result) diff --git a/pscheduler-tool-powstream/powstream/can-run b/pscheduler-tool-powstream/powstream/can-run index 242f9f0c3..fd0789826 100755 --- a/pscheduler-tool-powstream/powstream/can-run +++ b/pscheduler-tool-powstream/powstream/can-run @@ -21,7 +21,7 @@ except KeyError: try: spec = json["spec"] - pscheduler.json_check_schema(spec, 1) + pscheduler.json_check_schema(spec, 2) except KeyError: pscheduler.succeed_json({ "can-run": False, @@ -41,4 +41,11 @@ if "ip-tos" in spec: }) +protocol = spec.get('protocol', 'owamp') +if protocol != 'owamp': + pscheduler.succeed_json({ + "can-run": False, + "reasons": [ f'Protocol {protocol} is not supported' ] + }) + pscheduler.succeed_json({ "can-run": True }) diff --git a/pscheduler-tool-twping/twping/can-run b/pscheduler-tool-twping/twping/can-run index f5aa35a33..e1abd9361 100755 --- a/pscheduler-tool-twping/twping/can-run +++ b/pscheduler-tool-twping/twping/can-run @@ -38,15 +38,21 @@ except ValueError as ex: errors = [] -if json['type'] == 'rtt' and ('protocol' not in spec or spec['protocol'] != 'twamp'): - errors.append("Only twamp protocol is supported") - -if json['type'] == 'rtt' and ('fragment' in spec): - errors.append("Fragmentation control is not supported.") +test_type = json['type'] if 'port' in spec: errors.append("Ports are not supported") +try: + if spec['protocol'] != 'twamp': + errors.append("Only twamp protocol is supported") +except KeyError: + pass + +if test_type == 'rtt': + if spec.get('fragment', False): + errors.append("Fragmentation control is not supported.") + result = { "can-run": len(errors) == 0